From 114653052972383f9b154d96c581a2b90c483c87 Mon Sep 17 00:00:00 2001 From: Alystrasz Date: Tue, 30 Aug 2022 08:31:34 +0200 Subject: [PATCH 01/21] feat: add verifiedmods.cpp skeleton --- NorthstarDLL/verifiedmods.cpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 NorthstarDLL/verifiedmods.cpp diff --git a/NorthstarDLL/verifiedmods.cpp b/NorthstarDLL/verifiedmods.cpp new file mode 100644 index 000000000..92e094226 --- /dev/null +++ b/NorthstarDLL/verifiedmods.cpp @@ -0,0 +1,17 @@ +#include "pch.h" + +void _FetchVerifiedModsList() { + +} + +char* GetVerifiedModsList() { + // TODO return list if it already has been parsed + // TODO else fetch list and return it +} + +void DownloadMod(char* dependencyString) { + // TODO check if mod is already present + // TODO check if mod is verified (throw if not) + // TODO download zip in temporary folder + // TODO move mod to mods/ folder +} From 36394d9a107f3a1de42ce559cdd96c23ed40a25c Mon Sep 17 00:00:00 2001 From: Alystrasz Date: Tue, 30 Aug 2022 20:00:25 +0200 Subject: [PATCH 02/21] feat: add header file --- NorthstarDLL/verifiedmods.h | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 NorthstarDLL/verifiedmods.h diff --git a/NorthstarDLL/verifiedmods.h b/NorthstarDLL/verifiedmods.h new file mode 100644 index 000000000..0c96b7b1e --- /dev/null +++ b/NorthstarDLL/verifiedmods.h @@ -0,0 +1,6 @@ +#pragma once +#include "memalloc.h" + +void _FetchVerifiedModsList(); +rapidjson_document GetVerifiedModsList(); +void DownloadMod(char* dependencyString); From b52f467f34acbe0633bec0e3e763cf5e06587156 Mon Sep 17 00:00:00 2001 From: Alystrasz Date: Tue, 30 Aug 2022 20:08:42 +0200 Subject: [PATCH 03/21] build: add verifiedmods files to solution --- NorthstarDLL/NorthstarDLL.vcxproj | 1 + NorthstarDLL/NorthstarDLL.vcxproj.filters | 9 ++++++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/NorthstarDLL/NorthstarDLL.vcxproj b/NorthstarDLL/NorthstarDLL.vcxproj index 19444e8de..9b672d275 100644 --- a/NorthstarDLL/NorthstarDLL.vcxproj +++ b/NorthstarDLL/NorthstarDLL.vcxproj @@ -629,6 +629,7 @@ + diff --git a/NorthstarDLL/NorthstarDLL.vcxproj.filters b/NorthstarDLL/NorthstarDLL.vcxproj.filters index d06134086..a0aff336b 100644 --- a/NorthstarDLL/NorthstarDLL.vcxproj.filters +++ b/NorthstarDLL/NorthstarDLL.vcxproj.filters @@ -1538,9 +1538,6 @@ Source Files\Dedicated - - Source Files\Client - Source Files\Shared @@ -1694,6 +1691,12 @@ Source Files\Shared + + Source Files\Dedicated + + + Source Files\Client + From 1ce0eb1a09769b99d25a8f14cd5f23439f834867 Mon Sep 17 00:00:00 2001 From: Alystrasz Date: Tue, 30 Aug 2022 20:21:59 +0200 Subject: [PATCH 04/21] build: add header file to dllmain --- NorthstarDLL/dllmain.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/NorthstarDLL/dllmain.cpp b/NorthstarDLL/dllmain.cpp index 020ab1cdb..ae5953417 100644 --- a/NorthstarDLL/dllmain.cpp +++ b/NorthstarDLL/dllmain.cpp @@ -46,6 +46,7 @@ #include "version.h" #include "pch.h" #include "scriptutility.h" +#include "verifiedmods.h" #include "rapidjson/document.h" #include "rapidjson/stringbuffer.h" From ba6354508509469a684012f6bfb5f87d4c005da3 Mon Sep 17 00:00:00 2001 From: Alystrasz Date: Tue, 30 Aug 2022 21:03:11 +0200 Subject: [PATCH 05/21] feat: add _FetchVerifiedModsList stupid implementation --- NorthstarDLL/verifiedmods.cpp | 47 +++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/NorthstarDLL/verifiedmods.cpp b/NorthstarDLL/verifiedmods.cpp index 92e094226..7b42d21c6 100644 --- a/NorthstarDLL/verifiedmods.cpp +++ b/NorthstarDLL/verifiedmods.cpp @@ -1,7 +1,54 @@ #include "pch.h" +#include "masterserver.cpp" void _FetchVerifiedModsList() { + CURL* curl = curl_easy_init(); + std::string readBuffer; + curl_easy_setopt(curl, CURLOPT_URL, fmt::format("{}/client/verifiedmods", Cvar_ns_masterserver_hostname->GetString()).c_str()); + curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "GET"); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CurlWriteToStringBufferCallback); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer); + + CURLcode result = curl_easy_perform(curl); + + if (result == CURLcode::CURLE_OK) + { + rapidjson_document verifiedModsJson; + verifiedModsJson.Parse(readBuffer.c_str()); + + if (verifiedModsJson.HasParseError()) + { + spdlog::error( + "Failed reading masterserver verified mods response: encountered parse error \"{}\"", + rapidjson::GetParseError_En(verifiedModsJson.GetParseError())); + goto REQUEST_END_CLEANUP; + } + if (!verifiedModsJson.IsObject()) + { + spdlog::error("Failed reading masterserver verified mods response: root object is not an object"); + goto REQUEST_END_CLEANUP; + } + if (verifiedModsJson.HasMember("error")) + { + spdlog::error("Failed reading masterserver response: got fastify error response"); + spdlog::error(readBuffer); + if (verifiedModsJson["error"].HasMember("enum")) + spdlog::error( std::string(verifiedModsJson["error"]["enum"].GetString()) ); + else + spdlog::error(std::string("No error message provided")); + goto REQUEST_END_CLEANUP; + } + } + else + { + spdlog::error("Failed requesting verified mods list: error {}", curl_easy_strerror(result)); + } + + // TODO store mods in a global variable + + REQUEST_END_CLEANUP: + curl_easy_cleanup(curl); } char* GetVerifiedModsList() { From be5b8dcecb82da81878ccb18c18a10ce1dca2f73 Mon Sep 17 00:00:00 2001 From: Alystrasz Date: Wed, 31 Aug 2022 22:00:11 +0200 Subject: [PATCH 06/21] feat: use local variable to store mods list --- NorthstarDLL/verifiedmods.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/NorthstarDLL/verifiedmods.cpp b/NorthstarDLL/verifiedmods.cpp index 7b42d21c6..4cc7d8652 100644 --- a/NorthstarDLL/verifiedmods.cpp +++ b/NorthstarDLL/verifiedmods.cpp @@ -1,6 +1,8 @@ #include "pch.h" #include "masterserver.cpp" +rapidjson_document verifiedModsJson; + void _FetchVerifiedModsList() { CURL* curl = curl_easy_init(); @@ -14,7 +16,6 @@ void _FetchVerifiedModsList() { if (result == CURLcode::CURLE_OK) { - rapidjson_document verifiedModsJson; verifiedModsJson.Parse(readBuffer.c_str()); if (verifiedModsJson.HasParseError()) @@ -45,8 +46,6 @@ void _FetchVerifiedModsList() { spdlog::error("Failed requesting verified mods list: error {}", curl_easy_strerror(result)); } - // TODO store mods in a global variable - REQUEST_END_CLEANUP: curl_easy_cleanup(curl); } From 09cb3342f83a87088342e231845241ce0b3a8fa2 Mon Sep 17 00:00:00 2001 From: Alystrasz Date: Wed, 31 Aug 2022 22:19:06 +0200 Subject: [PATCH 07/21] feat: add GetVerifiedModsList stupid implementation --- NorthstarDLL/verifiedmods.cpp | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/NorthstarDLL/verifiedmods.cpp b/NorthstarDLL/verifiedmods.cpp index 4cc7d8652..2bf69f51e 100644 --- a/NorthstarDLL/verifiedmods.cpp +++ b/NorthstarDLL/verifiedmods.cpp @@ -1,7 +1,12 @@ #include "pch.h" #include "masterserver.cpp" +#include "rapidjson/document.h" +#include "rapidjson/writer.h" +#include "rapidjson/stringbuffer.h" -rapidjson_document verifiedModsJson; +using namespace rapidjson; + +Document verifiedModsJson; void _FetchVerifiedModsList() { CURL* curl = curl_easy_init(); @@ -50,9 +55,15 @@ void _FetchVerifiedModsList() { curl_easy_cleanup(curl); } -char* GetVerifiedModsList() { - // TODO return list if it already has been parsed - // TODO else fetch list and return it +std::string GetVerifiedModsList() { + if (verifiedModsJson.IsNull()) + { + _FetchVerifiedModsList(); + } + StringBuffer buffer; + Writer writer(buffer); + verifiedModsJson.Accept(writer); + return buffer.GetString(); } void DownloadMod(char* dependencyString) { From 124890676a63950d1ad82bb9a6d3f983cc112df4 Mon Sep 17 00:00:00 2001 From: Alystrasz Date: Wed, 31 Aug 2022 22:39:15 +0200 Subject: [PATCH 08/21] feat: add wrapper method for GetVerifiedModsList method --- NorthstarDLL/verifiedmods.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/NorthstarDLL/verifiedmods.cpp b/NorthstarDLL/verifiedmods.cpp index 2bf69f51e..9e73397c0 100644 --- a/NorthstarDLL/verifiedmods.cpp +++ b/NorthstarDLL/verifiedmods.cpp @@ -3,6 +3,7 @@ #include "rapidjson/document.h" #include "rapidjson/writer.h" #include "rapidjson/stringbuffer.h" +#include "squirrel.h" using namespace rapidjson; @@ -72,3 +73,20 @@ void DownloadMod(char* dependencyString) { // TODO download zip in temporary folder // TODO move mod to mods/ folder } + + +/** + * Squirrel-exposed wrapper methods + **/ + +SQRESULT SQ_GetVerifiedModsList(void* sqvm) +{ + std::string mods = GetVerifiedModsList(); + const SQChar* buffer = mods.c_str(); + ClientSq_pushstring(sqvm, buffer, -1); + return SQRESULT_NOTNULL; +} + +void InitialiseVerifiedModsScripts(HMODULE baseAddress) { + g_UISquirrelManager->AddFuncRegistration("string", "GetVerifiedModsList", "", "", SQ_GetVerifiedModsList); +} From 5317e3ece86e73718a8c5399fdd7afcb2c272f61 Mon Sep 17 00:00:00 2001 From: Alystrasz Date: Wed, 31 Aug 2022 22:42:20 +0200 Subject: [PATCH 09/21] build: add DLL load callback --- NorthstarDLL/dllmain.cpp | 1 + NorthstarDLL/verifiedmods.h | 1 + 2 files changed, 2 insertions(+) diff --git a/NorthstarDLL/dllmain.cpp b/NorthstarDLL/dllmain.cpp index ae5953417..f5a7e5af2 100644 --- a/NorthstarDLL/dllmain.cpp +++ b/NorthstarDLL/dllmain.cpp @@ -291,6 +291,7 @@ bool InitialiseNorthstar() // mod manager after everything else AddDllLoadCallback("engine.dll", InitialiseModManager); + AddDllLoadCallback("engine.dll", InitialiseVerifiedModsScripts); { // activate multi-module exploitfixes callbacks diff --git a/NorthstarDLL/verifiedmods.h b/NorthstarDLL/verifiedmods.h index 0c96b7b1e..5fdcb3a0a 100644 --- a/NorthstarDLL/verifiedmods.h +++ b/NorthstarDLL/verifiedmods.h @@ -4,3 +4,4 @@ void _FetchVerifiedModsList(); rapidjson_document GetVerifiedModsList(); void DownloadMod(char* dependencyString); +void InitialiseVerifiedModsScripts(HMODULE baseAddress); From 2da03e4a812b8cbf069d16616b0f5a3ff269dc07 Mon Sep 17 00:00:00 2001 From: Alystrasz Date: Tue, 6 Sep 2022 15:14:10 +0200 Subject: [PATCH 10/21] fix: add masterserver header instead of source code file --- NorthstarDLL/verifiedmods.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/NorthstarDLL/verifiedmods.cpp b/NorthstarDLL/verifiedmods.cpp index 9e73397c0..3ad15c0f9 100644 --- a/NorthstarDLL/verifiedmods.cpp +++ b/NorthstarDLL/verifiedmods.cpp @@ -1,5 +1,5 @@ #include "pch.h" -#include "masterserver.cpp" +#include "masterserver.h" #include "rapidjson/document.h" #include "rapidjson/writer.h" #include "rapidjson/stringbuffer.h" @@ -15,7 +15,6 @@ void _FetchVerifiedModsList() { std::string readBuffer; curl_easy_setopt(curl, CURLOPT_URL, fmt::format("{}/client/verifiedmods", Cvar_ns_masterserver_hostname->GetString()).c_str()); curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "GET"); - curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CurlWriteToStringBufferCallback); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer); CURLcode result = curl_easy_perform(curl); @@ -26,9 +25,7 @@ void _FetchVerifiedModsList() { if (verifiedModsJson.HasParseError()) { - spdlog::error( - "Failed reading masterserver verified mods response: encountered parse error \"{}\"", - rapidjson::GetParseError_En(verifiedModsJson.GetParseError())); + spdlog::error( "Failed reading masterserver verified mods response: encountered parse error." ); goto REQUEST_END_CLEANUP; } if (!verifiedModsJson.IsObject()) From 7f7574532dee46faeafa73f796242eed911091f1 Mon Sep 17 00:00:00 2001 From: BobTheBob <32057864+BobTheBob9@users.noreply.github.com> Date: Sat, 3 Sep 2022 01:44:06 +0100 Subject: [PATCH 11/21] Check LSX for Origin launch (#263) --- NorthstarLauncher/main.cpp | 51 +++++++++++++++++++++++++++++++++++--- 1 file changed, 48 insertions(+), 3 deletions(-) diff --git a/NorthstarLauncher/main.cpp b/NorthstarLauncher/main.cpp index b097b2f85..078cbc4a4 100644 --- a/NorthstarLauncher/main.cpp +++ b/NorthstarLauncher/main.cpp @@ -7,6 +7,11 @@ #include #include +#pragma comment(lib, "Ws2_32.lib") + +#include +#include + namespace fs = std::filesystem; extern "C" @@ -125,6 +130,41 @@ void LibraryLoadError(DWORD dwMessageId, const wchar_t* libName, const wchar_t* MessageBoxA(GetForegroundWindow(), text, "Northstar Launcher Error", 0); } +void AwaitOriginStartup() +{ + WSADATA wsaData; + WSAStartup(MAKEWORD(2, 2), &wsaData); + SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + + if (sock != INVALID_SOCKET) + { + const int LSX_PORT = 3216; + + sockaddr_in lsxAddr; + lsxAddr.sin_family = AF_INET; + inet_pton(AF_INET, "127.0.0.1", &(lsxAddr.sin_addr)); + lsxAddr.sin_port = htons(LSX_PORT); + + std::cout << "LSX: connect()" << std::endl; + connect(sock, (struct sockaddr*)&lsxAddr, sizeof(lsxAddr)); + + char buf[4096]; + memset(buf, 0, sizeof(buf)); + + do + { + recv(sock, buf, 4096, 0); + std::cout << buf << std::endl; + + // honestly really shit, this isn't needed for origin due to being able to check OriginClientService + // but for ea desktop we don't have anything like this, so atm we just have to wait to ensure that we start after logging in + Sleep(8000); + } while (!strstr(buf, "")); // ensure we're actually getting data from lsx + } + + WSACleanup(); // cleanup sockets and such so game can contact lsx itself +} + void EnsureOriginStarted() { if (GetProcessByName(L"Origin.exe") || GetProcessByName(L"EADesktop.exe")) @@ -170,9 +210,14 @@ void EnsureOriginStarted() std::cout << "[*] Waiting for Origin..." << std::endl; - // wait for origin to be ready, this process is created when origin is ready enough to launch game without any errors - while (!GetProcessByName(L"OriginClientService.exe") && !GetProcessByName(L"EADesktop.exe")) - Sleep(200); + // wait for origin process to boot + do + { + Sleep(500); + } while (!GetProcessByName(L"OriginClientService.exe") && !GetProcessByName(L"EADesktop.exe")); + + // wait for origin to be ready to start + AwaitOriginStartup(); CloseHandle(pi.hProcess); CloseHandle(pi.hThread); From 4fc2083a5f1664c6bbb2163b18c4371013ef1625 Mon Sep 17 00:00:00 2001 From: Alystrasz Date: Tue, 6 Sep 2022 18:29:19 +0200 Subject: [PATCH 12/21] build: include verifiedmods header in build --- NorthstarDLL/NorthstarDLL.vcxproj | 1 + NorthstarDLL/NorthstarDLL.vcxproj.filters | 3 +++ 2 files changed, 4 insertions(+) diff --git a/NorthstarDLL/NorthstarDLL.vcxproj b/NorthstarDLL/NorthstarDLL.vcxproj index 9b672d275..45ba14df8 100644 --- a/NorthstarDLL/NorthstarDLL.vcxproj +++ b/NorthstarDLL/NorthstarDLL.vcxproj @@ -567,6 +567,7 @@ + diff --git a/NorthstarDLL/NorthstarDLL.vcxproj.filters b/NorthstarDLL/NorthstarDLL.vcxproj.filters index a0aff336b..adc85ed84 100644 --- a/NorthstarDLL/NorthstarDLL.vcxproj.filters +++ b/NorthstarDLL/NorthstarDLL.vcxproj.filters @@ -1521,6 +1521,9 @@ Header Files\Shared + + Header Files\Client + From 2fd87c012224acf0a1f4592aa921aa6175010c72 Mon Sep 17 00:00:00 2001 From: Alystrasz Date: Tue, 6 Sep 2022 18:31:08 +0200 Subject: [PATCH 13/21] fix: load library after client.dll load --- NorthstarDLL/dllmain.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NorthstarDLL/dllmain.cpp b/NorthstarDLL/dllmain.cpp index f5a7e5af2..74c9264a0 100644 --- a/NorthstarDLL/dllmain.cpp +++ b/NorthstarDLL/dllmain.cpp @@ -244,6 +244,7 @@ bool InitialiseNorthstar() AddDllLoadCallbackForClient("engine.dll", InitialiseChatCommands); AddDllLoadCallbackForClient("client.dll", InitialiseScriptModMenu); AddDllLoadCallbackForClient("client.dll", InitialiseScriptServerBrowser); + AddDllLoadCallbackForClient("client.dll", InitialiseVerifiedModsScripts); AddDllLoadCallbackForClient("localize.dll", InitialiseModLocalisation); AddDllLoadCallbackForClient("engine.dll", InitialiseClientAuthHooks); AddDllLoadCallbackForClient("client.dll", InitialiseLatencyFleX); @@ -291,7 +292,6 @@ bool InitialiseNorthstar() // mod manager after everything else AddDllLoadCallback("engine.dll", InitialiseModManager); - AddDllLoadCallback("engine.dll", InitialiseVerifiedModsScripts); { // activate multi-module exploitfixes callbacks From 588b564bc6eab5cb4185dfc3c80c46cc8027dc1a Mon Sep 17 00:00:00 2001 From: Alystrasz Date: Tue, 6 Sep 2022 18:32:04 +0200 Subject: [PATCH 14/21] fix: include header in source module --- NorthstarDLL/verifiedmods.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/NorthstarDLL/verifiedmods.cpp b/NorthstarDLL/verifiedmods.cpp index 3ad15c0f9..ed60cb610 100644 --- a/NorthstarDLL/verifiedmods.cpp +++ b/NorthstarDLL/verifiedmods.cpp @@ -4,6 +4,7 @@ #include "rapidjson/writer.h" #include "rapidjson/stringbuffer.h" #include "squirrel.h" +#include "verifiedmods.h" using namespace rapidjson; From ee0715d8bf928b3e7905f8b07587ea615b2953c7 Mon Sep 17 00:00:00 2001 From: Alystrasz Date: Tue, 6 Sep 2022 18:32:52 +0200 Subject: [PATCH 15/21] refactor: remove unused prototypes from module header --- NorthstarDLL/verifiedmods.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/NorthstarDLL/verifiedmods.h b/NorthstarDLL/verifiedmods.h index 5fdcb3a0a..30957f1e9 100644 --- a/NorthstarDLL/verifiedmods.h +++ b/NorthstarDLL/verifiedmods.h @@ -1,7 +1,4 @@ #pragma once #include "memalloc.h" -void _FetchVerifiedModsList(); -rapidjson_document GetVerifiedModsList(); -void DownloadMod(char* dependencyString); void InitialiseVerifiedModsScripts(HMODULE baseAddress); From e9b57ad3495d1bb95b954fe667328e34506d50ed Mon Sep 17 00:00:00 2001 From: Remy Raes Date: Sat, 17 Sep 2022 15:38:09 +0200 Subject: [PATCH 16/21] docs: add TODO notes --- NorthstarDLL/verifiedmods.cpp | 86 ++++++++++++++++++++++------------- 1 file changed, 54 insertions(+), 32 deletions(-) diff --git a/NorthstarDLL/verifiedmods.cpp b/NorthstarDLL/verifiedmods.cpp index ed60cb610..57ddb3a06 100644 --- a/NorthstarDLL/verifiedmods.cpp +++ b/NorthstarDLL/verifiedmods.cpp @@ -11,54 +11,76 @@ using namespace rapidjson; Document verifiedModsJson; void _FetchVerifiedModsList() { - CURL* curl = curl_easy_init(); + spdlog::info("Requesting verified mods list from {}", Cvar_ns_masterserver_hostname->GetString()); - std::string readBuffer; - curl_easy_setopt(curl, CURLOPT_URL, fmt::format("{}/client/verifiedmods", Cvar_ns_masterserver_hostname->GetString()).c_str()); - curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "GET"); - curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer); + std::thread requestThread([]() { + CURL* curl = curl_easy_init(); - CURLcode result = curl_easy_perform(curl); + std::string readBuffer; + curl_easy_setopt(curl, CURLOPT_URL, fmt::format("{}/client/verifiedmods", Cvar_ns_masterserver_hostname->GetString()).c_str()); + curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "GET"); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer); - if (result == CURLcode::CURLE_OK) - { - verifiedModsJson.Parse(readBuffer.c_str()); + verifiedModsJson.Parse("{\"Mod Settings\" : {\"DependencyPrefix\" : \"EladNLG-ModSettings\", \"Versions\" : [ \"1.0.0\", \"1.1.0\" ]}, \"Moblin.Archon\" : {\"DependencyPrefix\" : \"GalacticMoblin-MoblinArchon\", \"Versions\" : [ \"1.3.0\", \"1.3.1\" ]}}"); + return; - if (verifiedModsJson.HasParseError()) - { - spdlog::error( "Failed reading masterserver verified mods response: encountered parse error." ); - goto REQUEST_END_CLEANUP; - } - if (!verifiedModsJson.IsObject()) + // TODO fetch list from masterserver + + CURLcode result = curl_easy_perform(curl); + spdlog::info(result); + + if (result == CURLcode::CURLE_OK) { - spdlog::error("Failed reading masterserver verified mods response: root object is not an object"); - goto REQUEST_END_CLEANUP; + spdlog::info("curl succeeded"); + + verifiedModsJson.Parse(readBuffer.c_str()); + + if (verifiedModsJson.HasParseError()) + { + spdlog::error("Failed reading masterserver verified mods response: encountered parse error."); + goto REQUEST_END_CLEANUP; + } + if (!verifiedModsJson.IsObject()) + { + spdlog::error("Failed reading masterserver verified mods response: root object is not an object"); + goto REQUEST_END_CLEANUP; + } + if (verifiedModsJson.HasMember("error")) + { + spdlog::error("Failed reading masterserver response: got fastify error response"); + spdlog::error(readBuffer); + if (verifiedModsJson["error"].HasMember("enum")) + spdlog::error(std::string(verifiedModsJson["error"]["enum"].GetString())); + else + spdlog::error(std::string("No error message provided")); + goto REQUEST_END_CLEANUP; + } } - if (verifiedModsJson.HasMember("error")) + else { - spdlog::error("Failed reading masterserver response: got fastify error response"); - spdlog::error(readBuffer); - if (verifiedModsJson["error"].HasMember("enum")) - spdlog::error( std::string(verifiedModsJson["error"]["enum"].GetString()) ); - else - spdlog::error(std::string("No error message provided")); - goto REQUEST_END_CLEANUP; + spdlog::error("Failed requesting verified mods list: error {}", curl_easy_strerror(result)); } - } - else - { - spdlog::error("Failed requesting verified mods list: error {}", curl_easy_strerror(result)); - } - REQUEST_END_CLEANUP: - curl_easy_cleanup(curl); + REQUEST_END_CLEANUP: + curl_easy_cleanup(curl); + }); + requestThread.detach(); } std::string GetVerifiedModsList() { if (verifiedModsJson.IsNull()) { _FetchVerifiedModsList(); + + while (verifiedModsJson.IsNull()) + { + spdlog::info("Wait for verified mods list to arrive..."); + Sleep(2000); // TODO do this asynchronously to avoid blocking the thread + } + + spdlog::info("Verified mods list arrived."); } + StringBuffer buffer; Writer writer(buffer); verifiedModsJson.Accept(writer); From 8de669857e38e16f1cef5d49b0f71dfed2b2bb2e Mon Sep 17 00:00:00 2001 From: Remy Raes Date: Sun, 18 Sep 2022 00:01:05 +0200 Subject: [PATCH 17/21] feat: add IsModVerified method --- NorthstarDLL/verifiedmods.cpp | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/NorthstarDLL/verifiedmods.cpp b/NorthstarDLL/verifiedmods.cpp index 57ddb3a06..4bbb79d15 100644 --- a/NorthstarDLL/verifiedmods.cpp +++ b/NorthstarDLL/verifiedmods.cpp @@ -87,7 +87,19 @@ std::string GetVerifiedModsList() { return buffer.GetString(); } -void DownloadMod(char* dependencyString) { +bool IsModVerified(char* modName, char* modVersion) +{ + // TODO log warning if not supported + // TODO log if name is supported, but not version + + spdlog::info("Mod {} (version {}) is not verified, and thus couldn't be downloaded.", modName, modVersion); + return false; +} + +void DownloadMod(char* modName, char* modVersion) { + if (!IsModVerified(modName, modVersion)) + return; + // TODO check if mod is already present // TODO check if mod is verified (throw if not) // TODO download zip in temporary folder @@ -95,6 +107,7 @@ void DownloadMod(char* dependencyString) { } + /** * Squirrel-exposed wrapper methods **/ @@ -107,6 +120,18 @@ SQRESULT SQ_GetVerifiedModsList(void* sqvm) return SQRESULT_NOTNULL; } +SQRESULT SQ_IsModVerified(void* sqvm) +{ + const SQChar* modName = ClientSq_getstring(sqvm, 1); + const SQChar* modVersion = ClientSq_getstring(sqvm, 2); + + bool result = IsModVerified((char*)modName, (char*)modVersion); + + ClientSq_pushbool(sqvm, result); + return SQRESULT_NOTNULL; +} + void InitialiseVerifiedModsScripts(HMODULE baseAddress) { g_UISquirrelManager->AddFuncRegistration("string", "GetVerifiedModsList", "", "", SQ_GetVerifiedModsList); + g_UISquirrelManager->AddFuncRegistration("bool", "IsModVerified", "string modName, string modVersion", "", SQ_IsModVerified); } From 08929eac97b8674f6558bfa93856497e8c41155b Mon Sep 17 00:00:00 2001 From: Remy Raes Date: Sun, 18 Sep 2022 00:54:45 +0200 Subject: [PATCH 18/21] feat: add IsModVerified complete implementation --- NorthstarDLL/verifiedmods.cpp | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/NorthstarDLL/verifiedmods.cpp b/NorthstarDLL/verifiedmods.cpp index 4bbb79d15..eb1d3cefc 100644 --- a/NorthstarDLL/verifiedmods.cpp +++ b/NorthstarDLL/verifiedmods.cpp @@ -21,7 +21,7 @@ void _FetchVerifiedModsList() { curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "GET"); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer); - verifiedModsJson.Parse("{\"Mod Settings\" : {\"DependencyPrefix\" : \"EladNLG-ModSettings\", \"Versions\" : [ \"1.0.0\", \"1.1.0\" ]}, \"Moblin.Archon\" : {\"DependencyPrefix\" : \"GalacticMoblin-MoblinArchon\", \"Versions\" : [ \"1.3.0\", \"1.3.1\" ]}}"); + verifiedModsJson.Parse("{\"Dinorush's LTS Rebalance\" : {\"DependencyPrefix\" : \"Dinorush-LTSRebalance\", \"Versions\" : []}, \"Mod Settings\" : {\"DependencyPrefix\" : \"EladNLG-ModSettings\", \"Versions\" : [ \"1.0.0\", \"1.1.0\" ]}, \"Moblin.Archon\" : {\"DependencyPrefix\" : \"GalacticMoblin-MoblinArchon\", \"Versions\" : [ \"1.3.0\", \"1.3.1\" ]}}"); return; // TODO fetch list from masterserver @@ -87,12 +87,34 @@ std::string GetVerifiedModsList() { return buffer.GetString(); } +/** +* Checks if a mod is verified by controlling if its name matches a key in the verified mods JSON +* document, and if its version is included in the JSON versions list. +*/ bool IsModVerified(char* modName, char* modVersion) { - // TODO log warning if not supported - // TODO log if name is supported, but not version + // 1. Mod is not verified if its name isn't a `verifiedModsJson` key. + if (!verifiedModsJson.HasMember(modName)) + { + spdlog::info("Mod \"{}\" is not verified, and thus couldn't be downloaded.", modName); + return false; + } + + // 2. Check if mod version has been validated. + const Value& entry = verifiedModsJson[modName]; + GenericArray versions = entry["Versions"].GetArray(); + + // Check versions in reverse order, since clients are more likely to ask for latest version. + for (rapidjson::Value::ConstValueIterator iterator = versions.End(); iterator != versions.Begin(); iterator--) + { + const rapidjson::Value& version = *iterator; + if (version.GetString() == modVersion) + { + return true; + } + } - spdlog::info("Mod {} (version {}) is not verified, and thus couldn't be downloaded.", modName, modVersion); + spdlog::info("Required version {} for mod \"{}\" is not verified, and thus couldn't be downloaded.", modVersion, modName); return false; } From fb59e76033aa4279f78d4219f77a084018475de1 Mon Sep 17 00:00:00 2001 From: Remy Raes Date: Sun, 18 Sep 2022 11:47:21 +0200 Subject: [PATCH 19/21] refactor: export mods test list outside fetching method --- NorthstarDLL/verifiedmods.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/NorthstarDLL/verifiedmods.cpp b/NorthstarDLL/verifiedmods.cpp index eb1d3cefc..7b9efa1b8 100644 --- a/NorthstarDLL/verifiedmods.cpp +++ b/NorthstarDLL/verifiedmods.cpp @@ -10,6 +10,14 @@ using namespace rapidjson; Document verifiedModsJson; +// Test string used to test branch without masterserver +const char* modsTestString = + "{" + "\"Dinorush's LTS Rebalance\" : {\"DependencyPrefix\" : \"Dinorush-LTSRebalance\", \"Versions\" : []}, " + "\"Mod Settings\" : {\"DependencyPrefix\" : \"EladNLG-ModSettings\", \"Versions\" : [ \"1.0.0\", \"1.1.0\" ]}, " + "\"Moblin.Archon\" : {\"DependencyPrefix\" : \"GalacticMoblin-MoblinArchon\", \"Versions\" : [ \"1.3.0\", \"1.3.1\" ]}" + "}"; + void _FetchVerifiedModsList() { spdlog::info("Requesting verified mods list from {}", Cvar_ns_masterserver_hostname->GetString()); @@ -21,10 +29,9 @@ void _FetchVerifiedModsList() { curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "GET"); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer); - verifiedModsJson.Parse("{\"Dinorush's LTS Rebalance\" : {\"DependencyPrefix\" : \"Dinorush-LTSRebalance\", \"Versions\" : []}, \"Mod Settings\" : {\"DependencyPrefix\" : \"EladNLG-ModSettings\", \"Versions\" : [ \"1.0.0\", \"1.1.0\" ]}, \"Moblin.Archon\" : {\"DependencyPrefix\" : \"GalacticMoblin-MoblinArchon\", \"Versions\" : [ \"1.3.0\", \"1.3.1\" ]}}"); - return; - // TODO fetch list from masterserver + verifiedModsJson.Parse( modsTestString ); + return; CURLcode result = curl_easy_perform(curl); spdlog::info(result); From e7a473fd3542c0747b57211890144e81c1d98bf9 Mon Sep 17 00:00:00 2001 From: Remy Raes Date: Sun, 18 Sep 2022 12:45:15 +0200 Subject: [PATCH 20/21] fix: IsModVerified correctly compares mod versions --- NorthstarDLL/verifiedmods.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/NorthstarDLL/verifiedmods.cpp b/NorthstarDLL/verifiedmods.cpp index 7b9efa1b8..c405b955a 100644 --- a/NorthstarDLL/verifiedmods.cpp +++ b/NorthstarDLL/verifiedmods.cpp @@ -14,6 +14,7 @@ Document verifiedModsJson; const char* modsTestString = "{" "\"Dinorush's LTS Rebalance\" : {\"DependencyPrefix\" : \"Dinorush-LTSRebalance\", \"Versions\" : []}, " + "\"Dinorush.Brute4\" : {\"DependencyPrefix\" : \"Dinorush-Brute4\", \"Versions\" : [ \"1.5\", \"1.6\" ]}, " "\"Mod Settings\" : {\"DependencyPrefix\" : \"EladNLG-ModSettings\", \"Versions\" : [ \"1.0.0\", \"1.1.0\" ]}, " "\"Moblin.Archon\" : {\"DependencyPrefix\" : \"GalacticMoblin-MoblinArchon\", \"Versions\" : [ \"1.3.0\", \"1.3.1\" ]}" "}"; @@ -111,11 +112,10 @@ bool IsModVerified(char* modName, char* modVersion) const Value& entry = verifiedModsJson[modName]; GenericArray versions = entry["Versions"].GetArray(); - // Check versions in reverse order, since clients are more likely to ask for latest version. - for (rapidjson::Value::ConstValueIterator iterator = versions.End(); iterator != versions.Begin(); iterator--) + for (rapidjson::Value::ConstValueIterator iterator = versions.Begin(); iterator != versions.End(); iterator++) { const rapidjson::Value& version = *iterator; - if (version.GetString() == modVersion) + if (strcmp(version.GetString(), modVersion)) { return true; } From 91dec31422ceea19fa1e25b66e7d9c9a03a7eb3a Mon Sep 17 00:00:00 2001 From: Remy Raes Date: Sun, 18 Sep 2022 16:42:33 +0200 Subject: [PATCH 21/21] fix: strcmp returns 0 on valid comparison --- NorthstarDLL/verifiedmods.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/NorthstarDLL/verifiedmods.cpp b/NorthstarDLL/verifiedmods.cpp index c405b955a..524cce146 100644 --- a/NorthstarDLL/verifiedmods.cpp +++ b/NorthstarDLL/verifiedmods.cpp @@ -112,11 +112,14 @@ bool IsModVerified(char* modName, char* modVersion) const Value& entry = verifiedModsJson[modName]; GenericArray versions = entry["Versions"].GetArray(); + spdlog::info("There's an entry for mod \"{}\", now checking version...", modName); + for (rapidjson::Value::ConstValueIterator iterator = versions.Begin(); iterator != versions.End(); iterator++) { const rapidjson::Value& version = *iterator; - if (strcmp(version.GetString(), modVersion)) + if (strcmp(version.GetString(), modVersion) == 0) { + spdlog::info("Mod \"{}\" (version {}) is verified.", modName, modVersion); return true; } }