From c8962075a46b7a152defde698da9335e7de73e81 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Mon, 6 Jun 2016 13:00:48 +0200 Subject: [PATCH] Add userraw and redirect http requests to the game's filesystem --- src/Components/Modules/Download.cpp | 52 ++++++++++++++++++++++++--- src/Components/Modules/FileSystem.cpp | 34 ++++++++++++++++++ src/Components/Modules/FileSystem.hpp | 9 +++-- src/Game/Functions.cpp | 12 +++++++ src/Game/Functions.hpp | 5 +++ src/STDInclude.hpp | 2 ++ src/Utils/Utils.cpp | 14 ++++++++ src/Utils/Utils.hpp | 1 + 8 files changed, 123 insertions(+), 6 deletions(-) diff --git a/src/Components/Modules/Download.cpp b/src/Components/Modules/Download.cpp index 7937e97f..072d866a 100644 --- a/src/Components/Modules/Download.cpp +++ b/src/Components/Modules/Download.cpp @@ -230,10 +230,54 @@ namespace Components // } // else { - std::string path = (Dvar::Var("fs_basepath").Get() + "\\" BASEGAME "\\html"); - mg_serve_http_opts opts = { 0 }; - opts.document_root = path.data(); - mg_serve_http(nc, message, opts); + //std::string path = (Dvar::Var("fs_basepath").Get() + "\\" BASEGAME "\\html"); + //mg_serve_http_opts opts = { 0 }; + //opts.document_root = path.data(); + //mg_serve_http(nc, message, opts); + + FileSystem::File file; + std::string url = "html" + std::string(message->uri.p, message->uri.len); + + if (Utils::EndsWith(url, "/")) + { + url.append("index.html"); + file = FileSystem::File(url); + } + else + { + file = FileSystem::File(url); + + if (!file.Exists()) + { + url.append("/index.html"); + file = FileSystem::File(url); + } + } + + std::string mimeType = Utils::GetMimeType(url); + + if (file.Exists()) + { + std::string& buffer = file.GetBuffer(); + + mg_printf(nc, + "HTTP/1.1 200 OK\r\n" + "Content-Type: %s\r\n" + "Content-Length: %d\r\n" + "Connection: close\r\n" + "\r\n", mimeType.data(), buffer.size()); + + mg_send(nc, buffer.data(), static_cast(buffer.size())); + } + else + { + mg_printf(nc, + "HTTP/1.1 404 Not Found\r\n" + "Content-Type: text/html\r\n" + "Connection: close\r\n" + "\r\n" + "404 - Not Found"); + } } nc->flags |= MG_F_SEND_AND_CLOSE; diff --git a/src/Components/Modules/FileSystem.cpp b/src/Components/Modules/FileSystem.cpp index da7d33e9..e8d70b63 100644 --- a/src/Components/Modules/FileSystem.cpp +++ b/src/Components/Modules/FileSystem.cpp @@ -97,6 +97,37 @@ namespace Components Game::FS_Remove(path); } + void FileSystem::RegisterFolder(const char* folder) + { + const char* fs_cdpath = Dvar::Var("fs_cdpath").Get(); + const char* fs_basepath = Dvar::Var("fs_basepath").Get(); + const char* fs_homepath = Dvar::Var("fs_homepath").Get(); + + if (fs_cdpath) Game::FS_AddLocalizedGameDirectory(fs_cdpath, folder); + if (fs_basepath) Game::FS_AddLocalizedGameDirectory(fs_basepath, folder); + if (fs_homepath) Game::FS_AddLocalizedGameDirectory(fs_homepath, folder); + } + + void FileSystem::RegisterFolders() + { + FileSystem::RegisterFolder("userraw"); + } + + void __declspec(naked) FileSystem::StartupStub() + { + __asm + { + push esi + call FileSystem::RegisterFolders + pop esi + + mov edx, ds:63D0CC0h + + mov eax, 48264Dh + jmp eax + } + } + int FileSystem::ExecIsFSStub(const char* execFilename) { return !File(execFilename).Exists(); @@ -107,6 +138,9 @@ namespace Components // Filesystem config checks Utils::Hook(0x6098FD, FileSystem::ExecIsFSStub, HOOK_CALL).Install()->Quick(); + // Register additional folders + Utils::Hook(0x482647, FileSystem::StartupStub, HOOK_JUMP).Install()->Quick(); + // exec whitelist removal (YAYFINITY WARD) Utils::Hook::Nop(0x609685, 5); Utils::Hook::Nop(0x60968C, 2); diff --git a/src/Components/Modules/FileSystem.hpp b/src/Components/Modules/FileSystem.hpp index 2925a05d..3db6f36a 100644 --- a/src/Components/Modules/FileSystem.hpp +++ b/src/Components/Modules/FileSystem.hpp @@ -7,10 +7,10 @@ namespace Components class File { public: - //File() {}; + File() {}; File(std::string file) : FilePath(file) { this->Read(); }; - bool Exists() { return this->Buffer.size() > 0; }; + bool Exists() { return !this->Buffer.empty(); }; std::string GetName() { return this->FilePath; }; std::string& GetBuffer() { return this->Buffer; }; @@ -45,6 +45,11 @@ namespace Components static void DeleteFile(std::string folder, std::string file); private: + + static void RegisterFolder(const char* folder); + + static void RegisterFolders(); + static void StartupStub(); static int ExecIsFSStub(const char* execFilename); }; } diff --git a/src/Game/Functions.cpp b/src/Game/Functions.cpp index f71a2f38..550d4025 100644 --- a/src/Game/Functions.cpp +++ b/src/Game/Functions.cpp @@ -57,6 +57,7 @@ namespace Game FS_FOpenFileAppend_t FS_FOpenFileAppend = (FS_FOpenFileAppend_t)0x410BB0; FS_FOpenFileAppend_t FS_FOpenFileWrite = (FS_FOpenFileAppend_t)0x4BA530; FS_FOpenFileRead_t FS_FOpenFileRead = (FS_FOpenFileRead_t)0x46CBF0; + FS_FOpenFileReadForThread_t FS_FOpenFileReadForThread = (FS_FOpenFileReadForThread_t)0x643270; FS_FCloseFile_t FS_FCloseFile = (FS_FCloseFile_t)0x462000; FS_WriteFile_t FS_WriteFile = (FS_WriteFile_t)0x426450; FS_Write_t FS_Write = (FS_Write_t)0x4C06E0; @@ -329,6 +330,17 @@ namespace Game return false; } + void FS_AddLocalizedGameDirectory(const char *path, const char *dir) + { + __asm + { + mov ebx, path + mov eax, dir + mov ecx, 642EF0h + call ecx + } + } + void MessageBox(std::string message, std::string title) { SetConsole("com_errorMessage", message.data()); diff --git a/src/Game/Functions.hpp b/src/Game/Functions.hpp index 6986b659..2a7ca459 100644 --- a/src/Game/Functions.hpp +++ b/src/Game/Functions.hpp @@ -127,6 +127,9 @@ namespace Game typedef int(__cdecl * FS_FOpenFileRead_t)(const char* file, int* fh, int uniqueFile); extern FS_FOpenFileRead_t FS_FOpenFileRead; + typedef int(__cdecl * FS_FOpenFileReadForThread_t)(const char *filename, int *file, int thread); + extern FS_FOpenFileReadForThread_t FS_FOpenFileReadForThread; + typedef int(__cdecl * FS_FCloseFile_t)(int fh); extern FS_FCloseFile_t FS_FCloseFile; @@ -438,6 +441,8 @@ namespace Game XAssetType DB_GetXAssetNameType(const char* name); bool DB_IsZoneLoaded(const char* zone); + void FS_AddLocalizedGameDirectory(const char *path, const char *dir); + void MessageBox(std::string message, std::string title); unsigned int R_HashString(const char* string); diff --git a/src/STDInclude.hpp b/src/STDInclude.hpp index e75025cb..89d6aff5 100644 --- a/src/STDInclude.hpp +++ b/src/STDInclude.hpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -101,6 +102,7 @@ #pragma comment(lib, "d3d9.lib") #pragma comment(lib, "Wininet.lib") #pragma comment(lib, "shlwapi.lib") +#pragma comment(lib, "Urlmon.lib") // Enable additional literals using namespace std::literals; diff --git a/src/Utils/Utils.cpp b/src/Utils/Utils.cpp index d6afad73..7740fb3e 100644 --- a/src/Utils/Utils.cpp +++ b/src/Utils/Utils.cpp @@ -5,6 +5,20 @@ namespace Utils { + std::string GetMimeType(std::string url) + { + wchar_t* mimeType = nullptr; + FindMimeFromData(NULL, std::wstring(url.begin(), url.end()).data(), NULL, 0, NULL, 0, &mimeType, 0); + + if (mimeType) + { + std::wstring wMimeType(mimeType); + return std::string(wMimeType.begin(), wMimeType.end()); + } + + return "application/octet-stream"; + } + const char *VA(const char *fmt, ...) { static char g_vaBuffer[VA_BUFFER_COUNT][VA_BUFFER_SIZE]; diff --git a/src/Utils/Utils.hpp b/src/Utils/Utils.hpp index 141f4796..fdc58de4 100644 --- a/src/Utils/Utils.hpp +++ b/src/Utils/Utils.hpp @@ -2,6 +2,7 @@ namespace Utils { + std::string GetMimeType(std::string url); const char *VA(const char *fmt, ...); std::string StrToLower(std::string input); bool EndsWith(std::string haystack, std::string needle);