cleanup + stdout/http to file
This commit is contained in:
parent
6465e9e2b5
commit
7b1ba0e8c0
|
|
@ -10,10 +10,7 @@ int placeId;
|
|||
void InitializeDiscord()
|
||||
{
|
||||
// Check if Discord should be enabled by checking if the binary is the client as well as if the binary's containing folder contains a ".nodiscord" file
|
||||
char buffer[MAX_PATH];
|
||||
GetModuleFileNameA(NULL, buffer, MAX_PATH);
|
||||
|
||||
std::string path = std::string(buffer);
|
||||
std::string path = Helpers::getModulePath();
|
||||
|
||||
if (fs::path(path).stem() != "TadahPlayer")
|
||||
{
|
||||
|
|
@ -26,32 +23,14 @@ void InitializeDiscord()
|
|||
}
|
||||
|
||||
// Get the username and placeId
|
||||
CURL* curl = curl_easy_init();
|
||||
CURLcode result;
|
||||
long response = 0;
|
||||
std::string data;
|
||||
|
||||
if (!curl)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_URL, std::string(BASE_URL + std::string("/api/places/information?ticket=") + ticket));
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, Helpers::write);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &data);
|
||||
|
||||
result = curl_easy_perform(curl);
|
||||
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response);
|
||||
|
||||
curl_easy_cleanup(curl);
|
||||
|
||||
if (result != CURLE_OK || response != 200)
|
||||
std::pair<bool, std::string> response = Helpers::httpGet(BASE_URL + std::string("/api/places/information?ticket=") + ticket);
|
||||
if (!response.first)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
rapidjson::Document document;
|
||||
document.Parse(data.c_str());
|
||||
document.Parse(response.second.c_str());
|
||||
|
||||
if (document.HasParseError() || !document.HasMember("username") || !document.HasMember("placeId"))
|
||||
{
|
||||
|
|
@ -79,32 +58,14 @@ void UpdatePresence()
|
|||
int max = 0;
|
||||
|
||||
// Get title, size, and max
|
||||
CURL* curl = curl_easy_init();
|
||||
CURLcode result;
|
||||
long response = 0;
|
||||
std::string data;
|
||||
|
||||
if (!curl)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_URL, std::string(BASE_URL + std::string("/api/places/information?id=") + std::to_string(placeId)));
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, Helpers::write);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &data);
|
||||
|
||||
result = curl_easy_perform(curl);
|
||||
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response);
|
||||
|
||||
curl_easy_cleanup(curl);
|
||||
|
||||
if (result != CURLE_OK || response != 200)
|
||||
std::pair<bool, std::string> response = Helpers::httpGet(BASE_URL + std::string("/api/places/information?id=") + std::to_string(placeId));
|
||||
if (!response.first)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
rapidjson::Document document;
|
||||
document.Parse(data.c_str());
|
||||
document.Parse(response.second.c_str());
|
||||
|
||||
if (document.HasParseError() || !document.HasMember("title") || !document.HasMember("size") || !document.HasMember("max"))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -121,4 +121,91 @@ size_t Helpers::write(char* contents, size_t size, size_t memory, void* pointer)
|
|||
{
|
||||
((std::string*)pointer)->append((char*)contents, size * memory);
|
||||
return size * memory;
|
||||
}
|
||||
}
|
||||
|
||||
std::string Helpers::getModulePath()
|
||||
{
|
||||
char buffer[MAX_PATH];
|
||||
GetModuleFileNameA(NULL, buffer, MAX_PATH);
|
||||
|
||||
return std::string(buffer);
|
||||
}
|
||||
|
||||
std::string Helpers::getISOTimestamp()
|
||||
{
|
||||
time_t now = time(0);
|
||||
struct tm now_gmt {};
|
||||
|
||||
gmtime_s(&now_gmt, &now);
|
||||
|
||||
char buffer[20];
|
||||
strftime(buffer, sizeof(buffer), "%FT%TZ", &now_gmt);
|
||||
|
||||
return std::string(buffer);
|
||||
}
|
||||
|
||||
std::pair<bool, std::map<std::string, std::string>> Helpers::parseURL(std::string url)
|
||||
{
|
||||
CURLU* curl = curl_url();
|
||||
CURLUcode result = curl_url_set(curl, CURLUPART_URL, url.c_str(), 0);
|
||||
|
||||
std::map<std::string, std::string> map;
|
||||
bool success = false;
|
||||
|
||||
if (result == CURLE_OK)
|
||||
{
|
||||
success = true;
|
||||
|
||||
char* path;
|
||||
char* host;
|
||||
char* query;
|
||||
|
||||
curl_url_get(curl, CURLUPART_PATH, &path, 0);
|
||||
curl_url_get(curl, CURLUPART_HOST, &host, 0);
|
||||
curl_url_get(curl, CURLUPART_QUERY, &query, 0);
|
||||
curl_url_cleanup(curl);
|
||||
|
||||
map = {
|
||||
{ "path", std::string(path) },
|
||||
{ "host", std::string(host) },
|
||||
{ "query", std::string(query) }
|
||||
};
|
||||
|
||||
curl_free(path);
|
||||
curl_free(host);
|
||||
curl_free(query);
|
||||
}
|
||||
|
||||
return std::make_pair(success, map);
|
||||
}
|
||||
|
||||
std::pair<bool, std::string> Helpers::httpGet(std::string url)
|
||||
{
|
||||
bool success = false;
|
||||
std::string data;
|
||||
|
||||
CURL* curl = curl_easy_init();
|
||||
CURLcode result;
|
||||
long response = 0;
|
||||
|
||||
if (!curl)
|
||||
{
|
||||
return std::make_pair(false, "");
|
||||
}
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_URL, url);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, Helpers::write);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &data);
|
||||
|
||||
result = curl_easy_perform(curl);
|
||||
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response);
|
||||
|
||||
curl_easy_cleanup(curl);
|
||||
|
||||
if (result != CURLE_OK || response != 200)
|
||||
{
|
||||
return std::make_pair(false, "");
|
||||
}
|
||||
|
||||
return std::make_pair(true, data);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,63 +14,34 @@ Http__trustCheck_t Http__trustCheck = (Http__trustCheck_t)ADDRESS_HTTP__TRUSTCHE
|
|||
|
||||
void __fastcall Http__httpGetPostWinInet_hook(Http* _this, void*, bool isPost, int a3, bool compressData, LPCSTR additionalHeaders, int a6)
|
||||
{
|
||||
CURLU* curl = curl_url();
|
||||
CURLUcode result = curl_url_set(curl, CURLUPART_URL, _this->url.c_str(), 0);
|
||||
|
||||
std::pair<bool, std::map<std::string, std::string>> parsed = Helpers::parseURL(_this->url);
|
||||
Http _changed = *_this;
|
||||
|
||||
if (result == CURLE_OK)
|
||||
if (parsed.first)
|
||||
{
|
||||
char* path;
|
||||
char* host;
|
||||
char* query;
|
||||
std::map<std::string, std::string> url = parsed.second;
|
||||
|
||||
curl_url_get(curl, CURLUPART_PATH, &path, 0);
|
||||
curl_url_get(curl, CURLUPART_HOST, &host, 0);
|
||||
curl_url_get(curl, CURLUPART_QUERY, &query, 0);
|
||||
curl_url_cleanup(curl);
|
||||
|
||||
if (path != NULL && host != NULL && query != NULL)
|
||||
if (!url["path"].empty() && !url["host"].empty() && !url["query"].empty())
|
||||
{
|
||||
std::string _path = Helpers::toLower(std::string(path));
|
||||
std::string _host = std::string(host);
|
||||
std::string _query = std::string(query);
|
||||
url["path"] = Helpers::toLower(url["path"]);
|
||||
|
||||
if (_host == "roblox.com" || _host == "www.roblox.com")
|
||||
if (url["host"] == "roblox.com" || url["host"] == "www.roblox.com")
|
||||
{
|
||||
if (_path == "/asset" || _path == "/asset/" || _path == "/asset/default.ashx")
|
||||
if (url["path"] == "/asset" || url["path"] == "/asset/" || url["path"] == "/asset/default.ashx")
|
||||
{
|
||||
_changed.url = "https://assetdelivery.roblox.com/v1/asset/?" + _query;
|
||||
_changed.url = "https://assetdelivery.roblox.com/v1/asset/?" + url["query"];
|
||||
_this = &_changed;
|
||||
}
|
||||
else if (_path == "/thumbs/asset.ashx" || _path == "/thumbs/avatar.ashx")
|
||||
else if (url["path"] == "/thumbs/asset.ashx" || url["path"] == "/thumbs/avatar.ashx")
|
||||
{
|
||||
/*
|
||||
Both Roblox endpoints require thumbnailFormatId to be set. We will make the default value for it as 0.
|
||||
std::string api = "https://www.roblox.com/" + std::string(url["path"] == "/thumbs/asset.ashx" ? "asset" : "avatar") + "/request-thumbnail-fix";
|
||||
|
||||
Asset.ashx -> requires overrideModeration (default false) -> /asset/request-thumbnail-fix
|
||||
Avatar.ashx -> requires dummy (default false) -> /avatar/request-thumbnail-fix
|
||||
|
||||
1. Parse query
|
||||
2. Construct a brand new blank query with thumbnailFormatId as 0 and dummy/overrideModeration as false (if Avatar.ashx or Asset.ashx)
|
||||
3. Merge the old query with priority over the old query so that if they declared any of the special variables, ours gets overwritten
|
||||
4. Rename id (if found) to assetId or userId (specific to the endpoint)
|
||||
5. Append to the Roblox url (specific to the endpoint)
|
||||
6. Fetch Roblox API
|
||||
7. Parse JSON
|
||||
8. Set the URL as the given url
|
||||
*/
|
||||
|
||||
std::string api = "https://www.roblox.com/" + std::string(_path == "/thumbs/asset.ashx" ? "asset" : "avatar") + "/request-thumbnail-fix";
|
||||
|
||||
std::map<std::string, std::string> source = Helpers::parseQueryString(query);
|
||||
std::map<std::string, std::string> source = Helpers::parseQueryString(url["query"]);
|
||||
std::map<std::string, std::string> fixed = {
|
||||
{ _path == "/thumbs/asset.ashx" ? "overrideModeration" : "dummy", "false" },
|
||||
{ url["path"] == "/thumbs/asset.ashx" ? "overrideModeration" : "dummy", "false" },
|
||||
{ "thumbnailFormatId", "0" }
|
||||
};
|
||||
|
||||
// the modern Roblox API doesn't care about parameter capitalization because of asp.net quirks
|
||||
// thus, we are able to do this :-)
|
||||
|
||||
for (auto& pair : source)
|
||||
{
|
||||
fixed[Helpers::toLower(pair.first)] = pair.second;
|
||||
|
|
@ -79,42 +50,21 @@ void __fastcall Http__httpGetPostWinInet_hook(Http* _this, void*, bool isPost, i
|
|||
if (fixed.find("id") != fixed.end())
|
||||
{
|
||||
auto handler = fixed.extract("id");
|
||||
handler.key() = _path == "/thumbs/asset.ashx" ? "assetId" : "userId";
|
||||
handler.key() = url["path"] == "/thumbs/asset.ashx" ? "assetId" : "userId";
|
||||
|
||||
fixed.insert(std::move(handler));
|
||||
}
|
||||
|
||||
api += Helpers::joinQueryString(fixed);
|
||||
|
||||
// get the api response
|
||||
CURL* curl = curl_easy_init();
|
||||
CURLcode result;
|
||||
long response = 0;
|
||||
std::string data;
|
||||
|
||||
if (!curl)
|
||||
{
|
||||
throw std::runtime_error("Failed to initialize cURL");
|
||||
}
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_URL, api);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, Helpers::write);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &data);
|
||||
|
||||
result = curl_easy_perform(curl);
|
||||
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response);
|
||||
|
||||
curl_easy_cleanup(curl);
|
||||
|
||||
if (result != CURLE_OK)
|
||||
// Get the API response
|
||||
std::pair<bool, std::string> response = Helpers::httpGet(api);
|
||||
if (!response.first)
|
||||
{
|
||||
throw std::runtime_error("Unexpected error occurred when fetching Roblox API: 0x0");
|
||||
}
|
||||
|
||||
if (response != 200)
|
||||
{
|
||||
throw std::runtime_error("Unexpected error occurred when fetching Roblox API: Response code was " + std::to_string(response));
|
||||
}
|
||||
std::string data = response.second;
|
||||
|
||||
rapidjson::Document document;
|
||||
document.Parse(data.c_str());
|
||||
|
|
@ -139,6 +89,12 @@ void __fastcall Http__httpGetPostWinInet_hook(Http* _this, void*, bool isPost, i
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef SERVER
|
||||
httpLog.open(httpLogPath, std::ios::out);
|
||||
httpLog << "[" << Helpers::getISOTimestamp << "] [" << (isPost ? "POST" : "GET") << "] '" << _this->url << "'" << std::endl;
|
||||
httpLog.close();
|
||||
#endif
|
||||
|
||||
Http__httpGetPostWinInet(_this, isPost, a3, compressData, additionalHeaders, a6);
|
||||
}
|
||||
|
||||
|
|
@ -146,19 +102,11 @@ bool __fastcall Http__trustCheck_hook(const char* url)
|
|||
{
|
||||
if (strlen(url) == 7 && !Helpers::isASCII(url))
|
||||
{
|
||||
// so the client does this really fucking stupid thing where if it opens an ie window,
|
||||
// it passes a char**, and not a char*
|
||||
// no idea if thats a detours quirk (i doubt it) or if thats how its just actually handled
|
||||
// practically no url is ever going to be seven characters long so it doesn't really matter
|
||||
|
||||
url = ((char**)url)[0];
|
||||
}
|
||||
|
||||
std::string _url = std::string(url);
|
||||
|
||||
// checking for embedded schemes must come BEFORE checking if it's valid
|
||||
// cURL does not treat embedded resources as URLs
|
||||
|
||||
if (_url == "about:blank")
|
||||
{
|
||||
return true;
|
||||
|
|
@ -172,35 +120,28 @@ bool __fastcall Http__trustCheck_hook(const char* url)
|
|||
}
|
||||
}
|
||||
|
||||
CURLU* curl = curl_url();
|
||||
CURLUcode result = curl_url_set(curl, CURLUPART_URL, url, 0);
|
||||
|
||||
if (result != CURLE_OK)
|
||||
std::pair<bool, std::map<std::string, std::string>> result = Helpers::parseURL(url);
|
||||
if (!result.first)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
char* scheme;
|
||||
char* host;
|
||||
std::map<std::string, std::string> parsed = result.second;
|
||||
|
||||
curl_url_get(curl, CURLUPART_SCHEME, &scheme, 0);
|
||||
curl_url_get(curl, CURLUPART_HOST, &host, 0);
|
||||
curl_url_cleanup(curl);
|
||||
|
||||
if (std::find(Helpers::allowedSchemes.begin(), Helpers::allowedSchemes.end(), std::string(scheme)) != Helpers::allowedSchemes.end())
|
||||
if (!parsed["scheme"].empty() && !parsed["host"].empty())
|
||||
{
|
||||
std::string _host = std::string(host);
|
||||
|
||||
// this is crude and inefficient but I don't care
|
||||
for (std::string wildcard : Helpers::allowedWildcardDomains)
|
||||
if (std::find(Helpers::allowedSchemes.begin(), Helpers::allowedSchemes.end(), std::string(parsed["scheme"])) != Helpers::allowedSchemes.end())
|
||||
{
|
||||
if (_host.size() >= wildcard.size() && 0 == wildcard.compare(_host.size() - wildcard.size(), wildcard.size(), wildcard))
|
||||
for (std::string wildcard : Helpers::allowedWildcardDomains)
|
||||
{
|
||||
return true;
|
||||
if (parsed["host"].size() >= wildcard.size() && 0 == wildcard.compare(parsed["host"].size() - wildcard.size(), wildcard.size(), wildcard))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return std::find(Helpers::allowedDomains.begin(), Helpers::allowedDomains.end(), _host) != Helpers::allowedDomains.end();
|
||||
return std::find(Helpers::allowedDomains.begin(), Helpers::allowedDomains.end(), parsed["host"]) != Helpers::allowedDomains.end();
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -1,10 +1,17 @@
|
|||
#include "pch.h"
|
||||
|
||||
#include "Patches.h"
|
||||
#include "Hooks/StandardOut.h"
|
||||
|
||||
#ifdef SERVER
|
||||
|
||||
HANDLE outputHandle;
|
||||
|
||||
std::string httpLogPath;
|
||||
std::string stdoutLogPath;
|
||||
|
||||
std::ofstream httpLog;
|
||||
std::ofstream stdoutLog;
|
||||
|
||||
void InitializeOutput()
|
||||
{
|
||||
AllocConsole();
|
||||
|
|
@ -16,8 +23,25 @@ void InitializeOutput()
|
|||
|
||||
#ifdef _DEBUG
|
||||
SetConsoleTextAttribute(outputHandle, FOREGROUND_RED | FOREGROUND_GREEN);
|
||||
printf("Compiled as Debug\n\n"); //
|
||||
printf("Compiled as Debug\n\n");
|
||||
#endif
|
||||
|
||||
// Initialize file logging
|
||||
fs::create_directory(fs::path(Helpers::getModulePath()).parent_path() / "logs");
|
||||
|
||||
std::string time = Helpers::getISOTimestamp();
|
||||
|
||||
stdoutLogPath = (fs::path(Helpers::getModulePath()).parent_path() / "logs" / (time + "-StandardOut.log")).string();
|
||||
httpLogPath = (fs::path(Helpers::getModulePath()).parent_path() / "logs" / (time + "-Http.log")).string();
|
||||
|
||||
stdoutLog.open(stdoutLogPath, std::ios::out);
|
||||
httpLog.open(stdoutLogPath, std::ios::out);
|
||||
|
||||
stdoutLog << "Tadah.DLL v1.0.0 - StandardOut" << std::endl << std::endl;
|
||||
httpLog << "Tadah.DLL v1.0.0 - Http" << std::endl << std::endl;
|
||||
|
||||
stdoutLog.close();
|
||||
httpLog.close();
|
||||
}
|
||||
|
||||
StandardOut__print_t StandardOut__print = (StandardOut__print_t)ADDRESS_STANDARDOUT__PRINT;
|
||||
|
|
@ -31,22 +55,35 @@ void __fastcall StandardOut__print_hook(int _this, void*, int type, std::string*
|
|||
message = reinterpret_cast<std::string*>((int)message + 4);
|
||||
#endif
|
||||
|
||||
std::string stringifiedType;
|
||||
std::string time = Helpers::getISOTimestamp();
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case RBX__MESSAGE_OUTPUT:
|
||||
SetConsoleTextAttribute(outputHandle, FOREGROUND_BLUE | FOREGROUND_INTENSITY);
|
||||
stringifiedType = "out";
|
||||
break;
|
||||
case RBX__MESSAGE_INFO:
|
||||
SetConsoleTextAttribute(outputHandle, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
|
||||
stringifiedType = "info";
|
||||
break;
|
||||
case RBX__MESSAGE_WARNING:
|
||||
SetConsoleTextAttribute(outputHandle, FOREGROUND_RED | FOREGROUND_GREEN);
|
||||
stringifiedType = "warn";
|
||||
break;
|
||||
case RBX__MESSAGE_ERROR:
|
||||
stringifiedType = "err";
|
||||
SetConsoleTextAttribute(outputHandle, FOREGROUND_RED | FOREGROUND_INTENSITY);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
printf("%s\n", message->c_str());
|
||||
SetConsoleTextAttribute(outputHandle, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
|
||||
}
|
||||
|
||||
stdoutLog.open(stdoutLogPath, std::ios::out);
|
||||
stdoutLog << "[" << time << "] [" << stringifiedType << "] " << message << std::endl;
|
||||
stdoutLog.close();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -1,5 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <curl/curl.h>
|
||||
|
||||
#include "Configuration.h"
|
||||
|
||||
class Helpers
|
||||
|
|
@ -17,4 +19,8 @@ public:
|
|||
static std::string joinQueryString(std::map<std::string, std::string> query);
|
||||
static std::string ws2s(std::wstring widestring);
|
||||
static size_t write(char* contents, size_t size, size_t memory, void* pointer);
|
||||
static std::string getModulePath();
|
||||
static std::string getISOTimestamp();
|
||||
static std::pair<bool, std::map<std::string, std::string>> parseURL(std::string url);
|
||||
static std::pair<bool, std::string> httpGet(std::string url);
|
||||
};
|
||||
|
|
@ -6,6 +6,10 @@
|
|||
#include "Configuration.h"
|
||||
#include "Helpers.h"
|
||||
|
||||
#ifdef SERVER
|
||||
#include "Hooks/StandardOut.h"
|
||||
#endif
|
||||
|
||||
struct Http
|
||||
{
|
||||
#if PADDING_STRUCT != 0
|
||||
|
|
|
|||
|
|
@ -1,6 +1,10 @@
|
|||
#pragma once
|
||||
|
||||
#include "Configuration.h"
|
||||
#include "Patches.h"
|
||||
#include "Helpers.h"
|
||||
|
||||
#ifdef SERVER
|
||||
|
||||
void InitializeOutput();
|
||||
|
||||
|
|
@ -8,7 +12,15 @@ typedef void(__thiscall* StandardOut__print_t)(int _this, int type, std::string*
|
|||
void __fastcall StandardOut__print_hook(int _this, void*, int type, std::string* message);
|
||||
extern StandardOut__print_t StandardOut__print;
|
||||
|
||||
extern std::string httpLogPath;
|
||||
extern std::string stdoutLogPath;
|
||||
|
||||
extern std::ofstream httpLog;
|
||||
extern std::ofstream stdoutLog;
|
||||
|
||||
#define RBX__MESSAGE_INFO 0
|
||||
#define RBX__MESSAGE_OUTPUT 1
|
||||
#define RBX__MESSAGE_WARNING 2
|
||||
#define RBX__MESSAGE_ERROR 3
|
||||
#define RBX__MESSAGE_ERROR 3
|
||||
|
||||
#endif
|
||||
|
|
@ -12,5 +12,7 @@
|
|||
#include <algorithm>
|
||||
#include <stdexcept>
|
||||
#include <thread>
|
||||
#include <ctime>
|
||||
#include <ios>
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
Loading…
Reference in New Issue