From 06c741edc57936ff3d6955006f739116d744d8c8 Mon Sep 17 00:00:00 2001 From: Tixx <83774803+WiserTixx@users.noreply.github.com> Date: Sun, 26 Jan 2025 23:08:31 +0100 Subject: [PATCH] Fix wstring for windows and add crossplatform code for fs strings --- include/Http.h | 4 +- include/Security/Init.h | 8 ++-- include/Startup.h | 8 ++-- include/Utils.h | 79 +++++++++------------------------------ src/GameStart.cpp | 2 +- src/Logger.cpp | 10 +++-- src/Network/Http.cpp | 4 +- src/Network/Resources.cpp | 34 ++++++++--------- src/Security/BeamNG.cpp | 14 +++---- src/Startup.cpp | 44 ++++++++++------------ 10 files changed, 81 insertions(+), 126 deletions(-) diff --git a/include/Http.h b/include/Http.h index cd9bd83..f491dc4 100644 --- a/include/Http.h +++ b/include/Http.h @@ -6,10 +6,12 @@ #pragma once #include "Logger.h" +#include "Utils.h" + #include class HTTP { public: - static bool Download(const std::string& IP, const std::wstring& Path); + static bool Download(const std::string& IP, const beammp_fs_string& Path); static std::string Post(const std::string& IP, const std::string& Fields); static std::string Get(const std::string& IP); static bool ProgressBar(size_t c, size_t t); diff --git a/include/Security/Init.h b/include/Security/Init.h index 4667bad..242c929 100644 --- a/include/Security/Init.h +++ b/include/Security/Init.h @@ -6,9 +6,9 @@ #pragma once #include -void PreGame(const std::wstring& GamePath); -std::string CheckVer(const std::wstring& path); -void InitGame(const std::wstring& Dir); -std::wstring GetGameDir(); +void PreGame(const beammp_fs_string& GamePath); +std::string CheckVer(const beammp_fs_string& path); +void InitGame(const beammp_fs_string& Dir); +beammp_fs_string GetGameDir(); void LegitimacyCheck(); void CheckLocalKey(); \ No newline at end of file diff --git a/include/Startup.h b/include/Startup.h index daebb13..65084d0 100644 --- a/include/Startup.h +++ b/include/Startup.h @@ -5,14 +5,16 @@ */ #pragma once +#include "Utils.h" + #include #include #include void InitLauncher(); -std::wstring GetEP(const wchar_t* P = nullptr); -std::wstring GetGamePath(); +beammp_fs_string GetEP(const beammp_fs_char* P = nullptr); +beammp_fs_string GetGamePath(); std::string GetVer(); std::string GetPatch(); -std::wstring GetEN(); +beammp_fs_string GetEN(); void ConfigInit(); diff --git a/include/Utils.h b/include/Utils.h index c4ff384..28c601b 100644 --- a/include/Utils.h +++ b/include/Utils.h @@ -15,6 +15,16 @@ #include #include +#ifdef _WIN32 +#define beammp_fs_string std::wstring +#define beammp_fs_char wchar_t +#define beammp_wide(str) L##str +#else +#define beammp_fs_string std::string +#define beammp_fs_char char +#define beammp_wide(str) str +#endif + namespace Utils { inline std::vector Split(const std::string& String, const std::string& delimiter) { @@ -120,71 +130,16 @@ namespace Utils { inline std::string ToString(const std::wstring& w) { return std::wstring_convert>().to_bytes(w); } +#ifdef _WIN32 inline std::wstring ToWString(const std::string& s) { return std::wstring_convert>().from_bytes(s); } - inline std::string GetSha256HashReallyFast(const std::string& filename) { - try { - EVP_MD_CTX* mdctx; - const EVP_MD* md; - uint8_t sha256_value[EVP_MAX_MD_SIZE]; - md = EVP_sha256(); - if (md == nullptr) { - throw std::runtime_error("EVP_sha256() failed"); - } - - mdctx = EVP_MD_CTX_new(); - if (mdctx == nullptr) { - throw std::runtime_error("EVP_MD_CTX_new() failed"); - } - if (!EVP_DigestInit_ex2(mdctx, md, NULL)) { - EVP_MD_CTX_free(mdctx); - throw std::runtime_error("EVP_DigestInit_ex2() failed"); - } - - std::ifstream stream(filename, std::ios::binary); - - const size_t FileSize = std::filesystem::file_size(filename); - size_t Read = 0; - std::vector Data; - while (Read < FileSize) { - Data.resize(size_t(std::min(FileSize - Read, 4096))); - size_t RealDataSize = Data.size(); - stream.read(Data.data(), std::streamsize(Data.size())); - if (stream.eof() || stream.fail()) { - RealDataSize = size_t(stream.gcount()); - } - Data.resize(RealDataSize); - if (RealDataSize == 0) { - break; - } - if (RealDataSize > 0 && !EVP_DigestUpdate(mdctx, Data.data(), Data.size())) { - EVP_MD_CTX_free(mdctx); - throw std::runtime_error("EVP_DigestUpdate() failed"); - } - Read += RealDataSize; - } - unsigned int sha256_len = 0; - if (!EVP_DigestFinal_ex(mdctx, sha256_value, &sha256_len)) { - EVP_MD_CTX_free(mdctx); - throw std::runtime_error("EVP_DigestFinal_ex() failed"); - } - EVP_MD_CTX_free(mdctx); - - std::string result; - for (size_t i = 0; i < sha256_len; i++) { - char buf[3]; - sprintf(buf, "%02x", sha256_value[i]); - buf[2] = 0; - result += buf; - } - return result; - } catch (const std::exception& e) { - error("Sha256 hashing of '" + filename + "' failed: " + e.what()); - return ""; - } +#else + inline std::string ToWString(const std::string& s) { + return s; } - inline std::string GetSha256HashReallyFast(const std::wstring& filename) { +#endif + inline std::string GetSha256HashReallyFast(const beammp_fs_string& filename) { try { EVP_MD_CTX* mdctx; const EVP_MD* md; @@ -241,7 +196,7 @@ namespace Utils { } return result; } catch (const std::exception& e) { - error(L"Sha256 hashing of '" + filename + L"' failed: " + ToWString(e.what())); + error(beammp_wide("Sha256 hashing of '") + filename + beammp_wide("' failed: ") + ToWString(e.what())); return ""; } } diff --git a/src/GameStart.cpp b/src/GameStart.cpp index d75fac0..70ed9a2 100644 --- a/src/GameStart.cpp +++ b/src/GameStart.cpp @@ -187,7 +187,7 @@ void StartGame(std::string Dir) { } #endif -void InitGame(const std::wstring& Dir) { +void InitGame(const beammp_fs_string& Dir) { if (!options.no_launch) { std::thread Game(StartGame, Dir); Game.detach(); diff --git a/src/Logger.cpp b/src/Logger.cpp index f13056e..33215fb 100644 --- a/src/Logger.cpp +++ b/src/Logger.cpp @@ -37,7 +37,7 @@ std::string getDate() { } void InitLog() { std::ofstream LFS; - LFS.open(GetEP() + L"Launcher.log"); + LFS.open(GetEP() + beammp_wide("Launcher.log")); if (!LFS.is_open()) { error("logger file init failed!"); } else @@ -45,13 +45,13 @@ void InitLog() { } void addToLog(const std::string& Line) { std::ofstream LFS; - LFS.open(GetEP() + L"Launcher.log", std::ios_base::app); + LFS.open(GetEP() + beammp_wide("Launcher.log"), std::ios_base::app); LFS << Line.c_str(); LFS.close(); } void addToLog(const std::wstring& Line) { std::wofstream LFS; - LFS.open(GetEP() + L"Launcher.log", std::ios_base::app); + LFS.open(GetEP() + beammp_wide("Launcher.log"), std::ios_base::app); LFS << Line.c_str(); LFS.close(); } @@ -91,6 +91,7 @@ void except(const std::string& toPrint) { } +#ifdef _WIN32 void info(const std::wstring& toPrint) { std::wstring Print = Utils::ToWString(getDate()) + L"[INFO] " + toPrint + L"\n"; std::wcout << Print; @@ -124,4 +125,5 @@ void except(const std::wstring& toPrint) { std::wstring Print = Utils::ToWString(getDate()) + L"[EXCEP] " + toPrint + L"\n"; std::wcout << Print; addToLog(Print); -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/src/Network/Http.cpp b/src/Network/Http.cpp index 649c6a9..92d8500 100644 --- a/src/Network/Http.cpp +++ b/src/Network/Http.cpp @@ -127,7 +127,7 @@ std::string HTTP::Post(const std::string& IP, const std::string& Fields) { return Ret; } -bool HTTP::Download(const std::string& IP, const std::wstring& Path) { +bool HTTP::Download(const std::string& IP, const beammp_fs_string& Path) { static std::mutex Lock; std::scoped_lock Guard(Lock); @@ -145,7 +145,7 @@ bool HTTP::Download(const std::string& IP, const std::wstring& Path) { File.close(); info("Download Complete!"); } else { - error(L"Failed to open file directory: " + Path); + error(beammp_wide("Failed to open file directory: ") + Path); return false; } diff --git a/src/Network/Resources.cpp b/src/Network/Resources.cpp index 22da317..68e917d 100644 --- a/src/Network/Resources.cpp +++ b/src/Network/Resources.cpp @@ -444,14 +444,14 @@ void NewSyncResources(SOCKET Sock, const std::string& Mods, const std::vectorFileName).stem().string() + "-" + ModInfoIter->Hash.substr(0, 8) + std::filesystem::path(ModInfoIter->FileName).extension().string(); - auto PathToSaveTo = (fs::path(CachingDirectory) / FileName).string(); + auto PathToSaveTo = (fs::path(CachingDirectory) / FileName); if (fs::exists(PathToSaveTo) && Utils::GetSha256HashReallyFast(PathToSaveTo) == ModInfoIter->Hash) { debug("Mod '" + FileName + "' found in cache"); UpdateUl(false, std::to_string(ModNo) + "/" + std::to_string(TotalMods) + ": " + ModInfoIter->FileName); std::this_thread::sleep_for(std::chrono::milliseconds(50)); try { - if (!fs::exists(GetGamePath() + L"mods/multiplayer")) { - fs::create_directories(GetGamePath() + L"mods/multiplayer"); + if (!fs::exists(GetGamePath() + beammp_wide("mods/multiplayer"))) { + fs::create_directories(GetGamePath() + beammp_wide("mods/multiplayer")); } auto modname = ModInfoIter->FileName; #if defined(__linux__) @@ -476,15 +476,15 @@ void NewSyncResources(SOCKET Sock, const std::string& Mods, const std::vectorFileName).filename(); - fs::exists(OldCachedPath) && GetSha256HashReallyFast(OldCachedPath.string()) == ModInfoIter->Hash) { + fs::exists(OldCachedPath) && Utils::GetSha256HashReallyFast(OldCachedPath) == ModInfoIter->Hash) { debug("Mod '" + FileName + "' found in old cache, copying it to the new cache"); UpdateUl(false, std::to_string(ModNo) + "/" + std::to_string(TotalMods) + ": " + ModInfoIter->FileName); std::this_thread::sleep_for(std::chrono::milliseconds(50)); try { fs::copy_file(OldCachedPath, PathToSaveTo, fs::copy_options::overwrite_existing); - if (!fs::exists(GetGamePath() + "mods/multiplayer")) { - fs::create_directories(GetGamePath() + "mods/multiplayer"); + if (!fs::exists(GetGamePath() + beammp_wide("mods/multiplayer"))) { + fs::create_directories(GetGamePath() + beammp_wide("mods/multiplayer")); } auto modname = ModInfoIter->FileName; @@ -525,7 +525,7 @@ void NewSyncResources(SOCKET Sock, const std::string& Mods, const std::vectorFileName; do { - debug("Loading file '" + FName + "' to '" + PathToSaveTo + "'"); + debug("Loading file '" + FName + "' to '" + PathToSaveTo.string() + "'"); TCPSend("f" + ModInfoIter->FileName, Sock); std::string Data = TCPRcv(Sock); @@ -558,7 +558,7 @@ void NewSyncResources(SOCKET Sock, const std::string& Mods, const std::vectorFileSize && !Terminate); if (!Terminate) { - if (!fs::exists(GetGamePath() + L"mods/multiplayer")) { - fs::create_directories(GetGamePath() + L"mods/multiplayer"); + if (!fs::exists(GetGamePath() + beammp_wide("mods/multiplayer"))) { + fs::create_directories(GetGamePath() + beammp_wide("mods/multiplayer")); } // Linux version of the game doesnt support uppercase letters in mod names @@ -667,8 +667,8 @@ void SyncResources(SOCKET Sock) { UpdateUl(false, std::to_string(Pos) + "/" + std::to_string(Amount) + ": " + PathToSaveTo.substr(PathToSaveTo.find_last_of('/'))); std::this_thread::sleep_for(std::chrono::milliseconds(50)); try { - if (!fs::exists(GetGamePath() + L"mods/multiplayer")) { - fs::create_directories(GetGamePath() + L"mods/multiplayer"); + if (!fs::exists(GetGamePath() + beammp_wide("mods/multiplayer"))) { + fs::create_directories(GetGamePath() + beammp_wide("mods/multiplayer")); } auto modname = PathToSaveTo.substr(PathToSaveTo.find_last_of('/')); #if defined(__linux__) @@ -677,8 +677,8 @@ void SyncResources(SOCKET Sock) { c = ::tolower(c); } #endif - auto name = GetGamePath() + L"mods/multiplayer" + Utils::ToWString(modname); - auto tmp_name = name + L".tmp"; + auto name = GetGamePath() + beammp_wide("mods/multiplayer") + Utils::ToWString(modname); + auto tmp_name = name + beammp_wide(".tmp"); fs::copy_file(PathToSaveTo, tmp_name, fs::copy_options::overwrite_existing); fs::rename(tmp_name, name); UpdateModUsage(modname); @@ -725,8 +725,8 @@ void SyncResources(SOCKET Sock) { } } while (fs::file_size(PathToSaveTo) != std::stoull(*FS) && !Terminate); if (!Terminate) { - if (!fs::exists(GetGamePath() + L"mods/multiplayer")) { - fs::create_directories(GetGamePath() + L"mods/multiplayer"); + if (!fs::exists(GetGamePath() + beammp_wide("mods/multiplayer"))) { + fs::create_directories(GetGamePath() + beammp_wide("mods/multiplayer")); } // Linux version of the game doesnt support uppercase letters in mod names @@ -736,7 +736,7 @@ void SyncResources(SOCKET Sock) { } #endif - fs::copy_file(PathToSaveTo, GetGamePath() + L"mods/multiplayer" + Utils::ToWString(FName), fs::copy_options::overwrite_existing); + fs::copy_file(PathToSaveTo, GetGamePath() + beammp_wide("mods/multiplayer") + Utils::ToWString(FName), fs::copy_options::overwrite_existing); UpdateModUsage(FN->substr(pos)); } WaitForConfirm(); diff --git a/src/Security/BeamNG.cpp b/src/Security/BeamNG.cpp index 2704d56..36ff5d6 100644 --- a/src/Security/BeamNG.cpp +++ b/src/Security/BeamNG.cpp @@ -15,6 +15,8 @@ #include #endif #include "Logger.h" +#include "Utils.h" + #include #include #include @@ -23,7 +25,7 @@ #define MAX_VALUE_NAME 16383 int TraceBack = 0; -std::wstring GameDir; +beammp_fs_string GameDir; void lowExit(int code) { TraceBack = 0; @@ -33,7 +35,7 @@ void lowExit(int code) { exit(2); } -std::wstring GetGameDir() { +beammp_fs_string GetGameDir() { #if defined(_WIN32) return GameDir.substr(0, GameDir.find_last_of('\\')); #elif defined(__linux__) @@ -231,13 +233,9 @@ void LegitimacyCheck() { } #endif } -std::string CheckVer(const std::wstring& dir) { +std::string CheckVer(const beammp_fs_string& dir) { std::string temp; -#if defined(_WIN32) - std::wstring Path = dir + L"\\integrity.json"; -#elif defined(__linux__) - std::wstring Path = dir + L"/integrity.json"; -#endif + beammp_fs_string Path = dir + beammp_wide("\\integrity.json"); std::ifstream f(Path.c_str(), std::ios::binary); int Size = int(std::filesystem::file_size(Path)); std::string vec(Size, 0); diff --git a/src/Startup.cpp b/src/Startup.cpp index 7ed8377..cd87590 100644 --- a/src/Startup.cpp +++ b/src/Startup.cpp @@ -73,12 +73,8 @@ Version::Version(const std::array& v) : Version(v[0], v[1], v[2]) { } -std::wstring GetEN() { -#if defined(_WIN32) - return L"BeamMP-Launcher.exe"; -#elif defined(__linux__) - return L"BeamMP-Launcher"; -#endif +beammp_fs_string GetEN() { + return beammp_wide("BeamMP-Launcher.exe"); } std::string GetVer() { @@ -88,10 +84,10 @@ std::string GetPatch() { return ".1"; } -std::wstring GetEP(const wchar_t* P) { - static std::wstring Ret = [&]() { - std::wstring path(P); - return path.substr(0, path.find_last_of(L"\\/") + 1); +beammp_fs_string GetEP(const beammp_fs_char* P) { + static beammp_fs_string Ret = [&]() { + beammp_fs_string path(P); + return path.substr(0, path.find_last_of(beammp_wide("\\/")) + 1); }(); return Ret; } @@ -152,14 +148,14 @@ void CheckName() { #if defined(_WIN32) std::wstring DN = GetEN(), CDir = Utils::ToWString(options.executable_name), FN = CDir.substr(CDir.find_last_of('\\') + 1); #elif defined(__linux__) - std::wstring DN = GetEN(), CDir = Utils::ToWString(options.executable_name), FN = CDir.substr(CDir.find_last_of('/') + 1); + std::string DN = GetEN(), CDir = options.executable_name, FN = CDir.substr(CDir.find_last_of('/') + 1); #endif if (FN != DN) { if (fs::exists(DN)) - _wremove(DN.c_str()); + fs::remove(DN.c_str()); if (fs::exists(DN)) ReLaunch(); - _wrename(FN.c_str(), DN.c_str()); + fs::rename(FN.c_str(), DN.c_str()); URelaunch(); } } @@ -170,7 +166,7 @@ void CheckForUpdates(const std::string& CV) { "https://backend.beammp.com/version/launcher?branch=" + Branch + "&pk=" + PublicKey); transform(LatestHash.begin(), LatestHash.end(), LatestHash.begin(), ::tolower); - std::wstring EP(GetEP() + GetEN()), Back(GetEP() + L"BeamMP-Launcher.back"); + beammp_fs_string EP(GetEP() + GetEN()), Back(GetEP() + beammp_wide("BeamMP-Launcher.back")); std::string FileHash = Utils::GetSha256HashReallyFast(EP); @@ -252,7 +248,7 @@ size_t DirCount(const std::filesystem::path& path) { return (size_t)std::distance(std::filesystem::directory_iterator { path }, std::filesystem::directory_iterator {}); } -void CheckMP(const std::wstring& Path) { +void CheckMP(const beammp_fs_string& Path) { if (!fs::exists(Path)) return; size_t c = DirCount(fs::path(Path)); @@ -272,7 +268,7 @@ void CheckMP(const std::wstring& Path) { } void EnableMP() { - std::wstring File(GetGamePath() + L"mods/db.json"); + beammp_fs_string File(GetGamePath() + beammp_wide("mods/db.json")); if (!fs::exists(File)) return; auto Size = fs::file_size(File); @@ -295,18 +291,18 @@ void EnableMP() { ofs << d.dump(); ofs.close(); } else { - error(L"Failed to write " + File); + error(beammp_wide("Failed to write ") + File); } } } } -void PreGame(const std::wstring& GamePath) { +void PreGame(const beammp_fs_string& GamePath) { std::string GameVer = CheckVer(GamePath); info("Game Version : " + GameVer); - CheckMP(GetGamePath() + L"mods/multiplayer"); - info(L"Game user path: " + GetGamePath()); + CheckMP(GetGamePath() + beammp_wide("mods/multiplayer")); + info(beammp_wide("Game user path: ") + GetGamePath()); if (!options.no_download) { std::string LatestHash = HTTP::Get("https://backend.beammp.com/sha/mod?branch=" + Branch + "&pk=" + PublicKey); @@ -316,8 +312,8 @@ void PreGame(const std::wstring& GamePath) { LatestHash.end()); try { - if (!fs::exists(GetGamePath() + L"mods/multiplayer")) { - fs::create_directories(GetGamePath() + L"mods/multiplayer"); + if (!fs::exists(GetGamePath() + beammp_wide("mods/multiplayer"))) { + fs::create_directories(GetGamePath() + beammp_wide("mods/multiplayer")); } EnableMP(); } catch (std::exception& e) { @@ -327,7 +323,7 @@ void PreGame(const std::wstring& GamePath) { std::wstring ZipPath(GetGamePath() + LR"(mods\multiplayer\BeamMP.zip)"); #elif defined(__linux__) // Linux version of the game cant handle mods with uppercase names - std::wstring ZipPath(GetGamePath() + LR"(mods/multiplayer/beammp.zip)"); + std::string ZipPath(GetGamePath() + R"(mods/multiplayer/beammp.zip)"); #endif std::string FileHash = Utils::GetSha256HashReallyFast(ZipPath); @@ -340,7 +336,7 @@ void PreGame(const std::wstring& GamePath) { ZipPath); } - std::wstring Target(GetGamePath() + L"mods/unpacked/beammp"); + beammp_fs_string Target(GetGamePath() + beammp_wide("mods/unpacked/beammp")); if (fs::is_directory(Target) && !fs::is_directory(Target + "/.git")) { fs::remove_all(Target);