Remove old code and revamp path checker to fix download bugs

This commit is contained in:
_ 2020-11-27 03:02:27 -07:00
parent ee372660e4
commit 348ed49b81
3 changed files with 23 additions and 95 deletions

View File

@ -87,31 +87,26 @@ std::string Utils::HexString(BYTE* data, int len)
return ss.str();
}
static const std::string illegalChars = "\\/:?\"<>|";
void Utils::RemoveForbiddenChar(std::string* str)
bool IsEqualIgnoreCase(const std::string& stringOne, const std::string& stringTwo)
{
std::string::iterator it;
for (it = str->begin(); it < str->end(); ++it)
{
bool found = illegalChars.find(*it) != std::string::npos;
if (found)
*it = '_';
}
return std::equal(stringOne.begin(), stringOne.end(), stringTwo.begin(), [](char a, char b)
{
return tolower(a) == tolower(b);
});
}
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)
{
bool found = illegalChars.find(*it) != std::string::npos;
// 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])$| +$|\\.+$",
std::regex_constants::ECMAScript | std::regex_constants::icase)))
str.append(L"_");
if (found)
*it = '_';
}
return 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;
}
/*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
std::string srStr = DownloadSpotifyUrl("spclient.wg.spotify.com",
"/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;
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
std::string songHost = (srStr.substr(srStr.find("https://") + 8))
.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
std::string songStr = DownloadSpotifyUrl(songHost, songPath, "");
//std::cout << "URL: " << songHost + songPath << std::endl;
if (songStr.substr(0, 6).compare("<HTML>") == 0)
{
std::cout << "Error: " + songStr << std::endl;
return;
}
// Decrypt encrypted song data
// Decrypt encrypted song data with Tiny AES in C
struct AES_ctx ctx;
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());
@ -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.cover = strtok((char*)(metadata.substr(metadata.find("height") + 30)).c_str(), "\"");
/*std::cout << "<> <> <> <> <> <> <> <> <> <> <> <> <> <>" << std::endl;
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);
std::wstring tempDirArtist = FixPathStr(Utf8ToUtf16(songInfo.artist));
songDir = songDirRoot;
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)
|| ERROR_ALREADY_EXISTS == GetLastError())
{
std::wstring tempDirAlbum = Utf8ToUtf16(songInfo.album);
RemoveForbiddenCharW(&tempDirAlbum);
std::wstring tempDirAlbum = FixPathStr(Utf8ToUtf16(songInfo.album));
if (CreateDirectoryW(std::wstring(songDir + L"\\" + tempDirArtist + std::wstring(L"\\")
+ tempDirAlbum).c_str(), NULL) || ERROR_ALREADY_EXISTS == GetLastError())
{
songDir += L"\\" + tempDirArtist + std::wstring(L"\\") + tempDirAlbum;
std::wstring tempDirSong = Utf8ToUtf16(songInfo.title);
RemoveForbiddenCharW(&tempDirSong);
std::wstring tempDirSong = FixPathStr(Utf8ToUtf16(songInfo.title));
std::ofstream songFileOut(songDir + L".\\" + tempDirArtist + L" - " + tempDirSong + L".ogg",
std::ios_base::binary);
@ -311,53 +287,6 @@ std::string Utils::DownloadSpotifyUrl(std::string host, std::string path, std::s
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)
{
MEMORY_BASIC_INFORMATION mbi = { 0 };

View File

@ -7,12 +7,10 @@ public:
static char* TrampHook32(char* src, char* dst, const intptr_t len);
static int GetSpotifyVersion();
static std::string HexString(BYTE* data, int len);
static void RemoveForbiddenChar(std::string* str);
static void RemoveForbiddenCharW(std::wstring* str);
static std::wstring FixPathStr(std::wstring 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 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);
};

View File

@ -16,6 +16,7 @@
#include <fstream>
#include <iomanip>
#include <iostream>
#include <regex>
#include <sstream>
#include <stdint.h>
#include <tchar.h>