Remove old code and revamp path checker to fix download bugs
This commit is contained in:
parent
ee372660e4
commit
348ed49b81
@ -87,31 +87,26 @@ std::string Utils::HexString(BYTE* data, int len)
|
|||||||
return ss.str();
|
return ss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
static const std::string illegalChars = "\\/:?\"<>|";
|
bool IsEqualIgnoreCase(const std::string& stringOne, const std::string& stringTwo)
|
||||||
void Utils::RemoveForbiddenChar(std::string* str)
|
|
||||||
{
|
{
|
||||||
std::string::iterator it;
|
return std::equal(stringOne.begin(), stringOne.end(), stringTwo.begin(), [](char a, char b)
|
||||||
|
|
||||||
for (it = str->begin(); it < str->end(); ++it)
|
|
||||||
{
|
{
|
||||||
bool found = illegalChars.find(*it) != std::string::npos;
|
return tolower(a) == tolower(b);
|
||||||
|
});
|
||||||
if (found)
|
|
||||||
*it = '_';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Utils::RemoveForbiddenCharW(std::wstring* str)
|
std::wstring Utils::FixPathStr(std::wstring str)
|
||||||
{
|
{
|
||||||
std::wstring::iterator it;
|
// No forbidden characters
|
||||||
|
std::wstring badCharsRegex = std::wstring(L"[<>:\"/\\|?*\x00-\x1F]", 14); // Use this constructor for \x00
|
||||||
|
str = std::regex_replace(str, std::wregex(badCharsRegex), L"_");
|
||||||
|
|
||||||
for (it = str->begin(); it < str->end(); ++it)
|
// No forbidden words or ending periods or spaces
|
||||||
{
|
if (std::regex_match(str, std::wregex(L"^(CON|PRN|AUX|NUL|COM[0-9]|LPT[0-9])$| +$|\\.+$",
|
||||||
bool found = illegalChars.find(*it) != std::string::npos;
|
std::regex_constants::ECMAScript | std::regex_constants::icase)))
|
||||||
|
str.append(L"_");
|
||||||
|
|
||||||
if (found)
|
return str;
|
||||||
*it = '_';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::wstring Utils::Utf8ToUtf16(const std::string& str)
|
std::wstring Utils::Utf8ToUtf16(const std::string& str)
|
||||||
@ -146,16 +141,11 @@ void Utils::DownloadSong(std::string fileId, std::string trackUri, std::string k
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*std::cout << "fileId = " << fileId << std::endl;
|
|
||||||
std::cout << "trackUri = " << trackUri << std::endl;
|
|
||||||
std::cout << "key = " << key << std::endl;
|
|
||||||
std::cout << "authToken = " << authToken << std::endl;*/
|
|
||||||
|
|
||||||
// Get storage resolve from Spotify
|
// Get storage resolve from Spotify
|
||||||
std::string srStr = DownloadSpotifyUrl("spclient.wg.spotify.com",
|
std::string srStr = DownloadSpotifyUrl("spclient.wg.spotify.com",
|
||||||
"/storage-resolve/files/audio/interactive_prefetch/" + fileId + "?product=0", authToken);
|
"/storage-resolve/files/audio/interactive_prefetch/" + fileId + "?product=0", authToken);
|
||||||
|
|
||||||
if (srStr.substr(0, 5).compare("Error") == 0)
|
if (srStr.length() > 5 && srStr.substr(0, 5).compare("Error") == 0)
|
||||||
{
|
{
|
||||||
std::cout << srStr << std::endl;
|
std::cout << srStr << std::endl;
|
||||||
return;
|
return;
|
||||||
@ -164,20 +154,19 @@ void Utils::DownloadSong(std::string fileId, std::string trackUri, std::string k
|
|||||||
// Parse storage resolve response to get the encrypted song data's URL
|
// Parse storage resolve response to get the encrypted song data's URL
|
||||||
std::string songHost = (srStr.substr(srStr.find("https://") + 8))
|
std::string songHost = (srStr.substr(srStr.find("https://") + 8))
|
||||||
.erase(srStr.substr(srStr.find("https://") + 8).find("/audio/"));
|
.erase(srStr.substr(srStr.find("https://") + 8).find("/audio/"));
|
||||||
std::string songPath = srStr.substr(srStr.find("/audio/")).erase(srStr.substr(srStr.find("/audio/")).find("=") + 85);
|
std::string songPath = srStr.substr(srStr.find("/audio/")).erase(srStr.substr(srStr.find("/audio/")).find("=")
|
||||||
|
+ 85);
|
||||||
|
|
||||||
// Download encrypted song data from Spotify
|
// Download encrypted song data from Spotify
|
||||||
std::string songStr = DownloadSpotifyUrl(songHost, songPath, "");
|
std::string songStr = DownloadSpotifyUrl(songHost, songPath, "");
|
||||||
|
|
||||||
//std::cout << "URL: " << songHost + songPath << std::endl;
|
|
||||||
|
|
||||||
if (songStr.substr(0, 6).compare("<HTML>") == 0)
|
if (songStr.substr(0, 6).compare("<HTML>") == 0)
|
||||||
{
|
{
|
||||||
std::cout << "Error: " + songStr << std::endl;
|
std::cout << "Error: " + songStr << std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decrypt encrypted song data
|
// Decrypt encrypted song data with Tiny AES in C
|
||||||
struct AES_ctx ctx;
|
struct AES_ctx ctx;
|
||||||
AES_init_ctx_iv(&ctx, reinterpret_cast<const uint8_t*>(&key[0]), IV);
|
AES_init_ctx_iv(&ctx, reinterpret_cast<const uint8_t*>(&key[0]), IV);
|
||||||
AES_CTR_xcrypt_buffer(&ctx, reinterpret_cast<uint8_t*>(&songStr[0]), songStr.size());
|
AES_CTR_xcrypt_buffer(&ctx, reinterpret_cast<uint8_t*>(&songStr[0]), songStr.size());
|
||||||
@ -195,18 +184,7 @@ void Utils::DownloadSong(std::string fileId, std::string trackUri, std::string k
|
|||||||
songInfo.album = strtok((char*)(metadata.substr(metadata.find(albumSearchPattern) + 404)).c_str(), "\"");
|
songInfo.album = strtok((char*)(metadata.substr(metadata.find(albumSearchPattern) + 404)).c_str(), "\"");
|
||||||
songInfo.cover = strtok((char*)(metadata.substr(metadata.find("height") + 30)).c_str(), "\"");
|
songInfo.cover = strtok((char*)(metadata.substr(metadata.find("height") + 30)).c_str(), "\"");
|
||||||
|
|
||||||
/*std::cout << "<> <> <> <> <> <> <> <> <> <> <> <> <> <>" << std::endl;
|
std::wstring tempDirArtist = FixPathStr(Utf8ToUtf16(songInfo.artist));
|
||||||
std::cout << metadata << std::endl;
|
|
||||||
std::cout << "<> <> <> <> <> <> <> <> <> <> <> <> <> <>" << std::endl;
|
|
||||||
std::cout << "=========================================" << std::endl;
|
|
||||||
std::cout << "title: " << songInfo.title << std::endl;
|
|
||||||
std::cout << "artist: " << songInfo.artist << std::endl;
|
|
||||||
std::cout << "album: " << songInfo.album << std::endl;
|
|
||||||
std::cout << "title: " << songInfo.cover << std::endl;
|
|
||||||
std::cout << "=========================================" << std::endl;*/
|
|
||||||
|
|
||||||
std::wstring tempDirArtist = Utf8ToUtf16(songInfo.artist);
|
|
||||||
RemoveForbiddenCharW(&tempDirArtist);
|
|
||||||
|
|
||||||
songDir = songDirRoot;
|
songDir = songDirRoot;
|
||||||
if (!CreateDirectoryW(songDir.c_str(), NULL) && ERROR_ALREADY_EXISTS != GetLastError())
|
if (!CreateDirectoryW(songDir.c_str(), NULL) && ERROR_ALREADY_EXISTS != GetLastError())
|
||||||
@ -215,16 +193,14 @@ void Utils::DownloadSong(std::string fileId, std::string trackUri, std::string k
|
|||||||
if (CreateDirectoryW(std::wstring(songDir + L"\\" + tempDirArtist).c_str(), NULL)
|
if (CreateDirectoryW(std::wstring(songDir + L"\\" + tempDirArtist).c_str(), NULL)
|
||||||
|| ERROR_ALREADY_EXISTS == GetLastError())
|
|| ERROR_ALREADY_EXISTS == GetLastError())
|
||||||
{
|
{
|
||||||
std::wstring tempDirAlbum = Utf8ToUtf16(songInfo.album);
|
std::wstring tempDirAlbum = FixPathStr(Utf8ToUtf16(songInfo.album));
|
||||||
RemoveForbiddenCharW(&tempDirAlbum);
|
|
||||||
|
|
||||||
if (CreateDirectoryW(std::wstring(songDir + L"\\" + tempDirArtist + std::wstring(L"\\")
|
if (CreateDirectoryW(std::wstring(songDir + L"\\" + tempDirArtist + std::wstring(L"\\")
|
||||||
+ tempDirAlbum).c_str(), NULL) || ERROR_ALREADY_EXISTS == GetLastError())
|
+ tempDirAlbum).c_str(), NULL) || ERROR_ALREADY_EXISTS == GetLastError())
|
||||||
{
|
{
|
||||||
songDir += L"\\" + tempDirArtist + std::wstring(L"\\") + tempDirAlbum;
|
songDir += L"\\" + tempDirArtist + std::wstring(L"\\") + tempDirAlbum;
|
||||||
|
|
||||||
std::wstring tempDirSong = Utf8ToUtf16(songInfo.title);
|
std::wstring tempDirSong = FixPathStr(Utf8ToUtf16(songInfo.title));
|
||||||
RemoveForbiddenCharW(&tempDirSong);
|
|
||||||
|
|
||||||
std::ofstream songFileOut(songDir + L".\\" + tempDirArtist + L" - " + tempDirSong + L".ogg",
|
std::ofstream songFileOut(songDir + L".\\" + tempDirArtist + L" - " + tempDirSong + L".ogg",
|
||||||
std::ios_base::binary);
|
std::ios_base::binary);
|
||||||
@ -311,53 +287,6 @@ std::string Utils::DownloadSpotifyUrl(std::string host, std::string path, std::s
|
|||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Utils::DownloadUrlOld(std::string host, std::string path, std::string authToken)
|
|
||||||
{
|
|
||||||
std::string authHeader;
|
|
||||||
std::string userAgent = "Spotify/11" + std::to_string(spotifyVer) + std::string("00")
|
|
||||||
+ std::to_string(spotifyVerEnd) + std::string(" Win32/Windows 10 (10.0.19042; x64)");
|
|
||||||
HINTERNET hInternet = InternetOpenA(userAgent.c_str(), INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
|
|
||||||
HINTERNET hConnect;
|
|
||||||
HINTERNET hRequest;
|
|
||||||
BOOL bRequestSent;
|
|
||||||
|
|
||||||
authHeader = "Authorization: Bearer " + authToken;
|
|
||||||
|
|
||||||
if (hInternet == NULL)
|
|
||||||
return "Error: Could not initialize request!";
|
|
||||||
|
|
||||||
hConnect = InternetConnectA(hInternet, host.c_str(), 80, NULL, NULL, INTERNET_SERVICE_HTTP, 0, NULL);
|
|
||||||
|
|
||||||
if (hConnect == NULL)
|
|
||||||
return "Error: Could not create connect!";
|
|
||||||
|
|
||||||
hRequest = HttpOpenRequestA(hConnect, "GET", path.c_str(), NULL, NULL, NULL, INTERNET_FLAG_NO_AUTH, 0);
|
|
||||||
|
|
||||||
if (hRequest == NULL)
|
|
||||||
return "Error: Could not create open request!";
|
|
||||||
|
|
||||||
HttpAddRequestHeadersA(hRequest, authHeader.c_str(), -1, HTTP_ADDREQ_FLAG_ADD | HTTP_ADDREQ_FLAG_REPLACE);
|
|
||||||
bRequestSent = HttpSendRequestA(hRequest, NULL, 0, NULL, 0);
|
|
||||||
|
|
||||||
if (!bRequestSent)
|
|
||||||
return "Error: Could not send request!";
|
|
||||||
|
|
||||||
std::string response;
|
|
||||||
const int bufferSize = 1024;
|
|
||||||
char tmpBuffer[bufferSize];
|
|
||||||
|
|
||||||
BOOL canRead = true;
|
|
||||||
DWORD bytesRead = -1;
|
|
||||||
|
|
||||||
while (canRead && bytesRead != 0)
|
|
||||||
{
|
|
||||||
canRead = InternetReadFile(hRequest, tmpBuffer, bufferSize, &bytesRead);
|
|
||||||
response.append(tmpBuffer, bytesRead);
|
|
||||||
}
|
|
||||||
|
|
||||||
return response;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Utils::BadPtr(void* ptr)
|
bool Utils::BadPtr(void* ptr)
|
||||||
{
|
{
|
||||||
MEMORY_BASIC_INFORMATION mbi = { 0 };
|
MEMORY_BASIC_INFORMATION mbi = { 0 };
|
||||||
|
@ -7,12 +7,10 @@ public:
|
|||||||
static char* TrampHook32(char* src, char* dst, const intptr_t len);
|
static char* TrampHook32(char* src, char* dst, const intptr_t len);
|
||||||
static int GetSpotifyVersion();
|
static int GetSpotifyVersion();
|
||||||
static std::string HexString(BYTE* data, int len);
|
static std::string HexString(BYTE* data, int len);
|
||||||
static void RemoveForbiddenChar(std::string* str);
|
static std::wstring FixPathStr(std::wstring str);
|
||||||
static void RemoveForbiddenCharW(std::wstring* str);
|
|
||||||
static std::wstring Utf8ToUtf16(const std::string& str);
|
static std::wstring Utf8ToUtf16(const std::string& str);
|
||||||
static void DownloadSong(std::string fileId, std::string fileUri, std::string key, std::string authToken);
|
static void DownloadSong(std::string fileId, std::string fileUri, std::string key, std::string authToken);
|
||||||
static std::string DownloadSpotifyUrl(std::string host, std::string path, std::string authToken);
|
static std::string DownloadSpotifyUrl(std::string host, std::string path, std::string authToken);
|
||||||
static std::string DownloadUrlOld(std::string host, std::string path, std::string authToken);
|
|
||||||
static bool BadPtr(void* ptr);
|
static bool BadPtr(void* ptr);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <regex>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <tchar.h>
|
#include <tchar.h>
|
||||||
|
Loading…
Reference in New Issue
Block a user