diff --git a/src/Components/Modules/News.cpp b/src/Components/Modules/News.cpp index 02b0c73c..51ee2436 100644 --- a/src/Components/Modules/News.cpp +++ b/src/Components/Modules/News.cpp @@ -7,6 +7,8 @@ namespace Components bool News::Terminate; std::thread News::Thread; std::string News::UpdaterArgs; + std::string News::UpdaterHash; + int News::UpdaterRefresh; bool News::unitTest() { @@ -50,6 +52,56 @@ namespace Components TerminateProcess(GetCurrentProcess(), exitCode); } + bool News::GetLatestUpdater() + { + if (Utils::IO::FileExists("updater.exe")) + { + // Generate hash of local updater.exe + std::string localUpdater = Utils::IO::ReadFile("updater.exe"); + localUpdater = Utils::Cryptography::SHA1::Compute(localUpdater, true); + + if (News::UpdaterHash.empty() || (News::UpdaterRefresh - Game::Sys_Milliseconds() > 900000)) // Check for updater Update every 15 mins max + { + News::UpdaterRefresh = Game::Sys_Milliseconds(); + + std::string data = Utils::Cache::GetFile("/json/updater"); // {"updater.exe":{"SHA1":"*HASH*"}} + + std::string error; + json11::Json listData = json11::Json::parse(data, error); + + if (error.empty() || listData.is_object()) + { + News::UpdaterHash = listData["updater.exe"]["SHA1"].string_value(); + } + } + + if (!News::UpdaterHash.empty() && localUpdater != News::UpdaterHash) + { + remove("updater.exe"); + } + } + + if (!Utils::IO::FileExists("updater.exe")) + { + return News::DownloadUpdater(); + } + + return true; + } + + bool News::DownloadUpdater() + { + std::string data = Utils::Cache::GetFile("/iw4/updater.exe"); + + if (!data.empty()) + { + Utils::IO::WriteFile("updater.exe", data); + return true; + } + + return false; + } + const char* News::GetNewsText() { return Localization::Get("MPUI_MOTD_TEXT"); @@ -95,21 +147,18 @@ namespace Components std::thread([]() { - std::string data = Utils::Cache::GetFile("/iw4/updater.exe"); - - if (data.empty()) + if (News::GetLatestUpdater()) + { + Console::SetSkipShutdown(); + Command::Execute("wait 300; quit;", false); + } + else { Localization::ClearTemp(); News::UpdaterArgs.clear(); Command::Execute("closemenu popup_reconnectingtoparty", false); Game::ShowMessageBox("Failed to download the updater!", "Error"); } - else - { - Console::SetSkipShutdown(); - Utils::IO::WriteFile("updater.exe", data); - Command::Execute("wait 300; quit;", false); - } }).detach(); } @@ -121,6 +170,8 @@ namespace Components News::News() { News::UpdaterArgs.clear(); + News::UpdaterHash.clear(); + News::UpdaterRefresh = 0; if (ZoneBuilder::IsEnabled()) return; // Maybe also dedi? Dvar::Register("g_firstLaunch", true, Game::DVAR_FLAG_SAVED, ""); @@ -151,10 +202,7 @@ namespace Components Localization::Set("MPUI_CHANGELOG_TEXT", "Loading..."); Localization::Set("MPUI_MOTD_TEXT", NEWS_MOTD_DEFAULT); - if (Utils::IO::FileExists("updater.exe")) - { - remove("updater.exe"); - } + //News::GetLatestUpdater(); // make newsfeed (ticker) menu items not cut off based on safe area Utils::Hook::Nop(0x63892D, 5); @@ -208,6 +256,7 @@ namespace Components News::~News() { News::UpdaterArgs.clear(); + News::UpdaterHash.clear(); } void News::preDestroy() diff --git a/src/Components/Modules/News.hpp b/src/Components/Modules/News.hpp index e374efaf..36ad52d8 100644 --- a/src/Components/Modules/News.hpp +++ b/src/Components/Modules/News.hpp @@ -20,8 +20,13 @@ namespace Components private: static std::string UpdaterArgs; + static std::string UpdaterHash; + static int UpdaterRefresh; static std::thread Thread; + static bool Terminate; + static bool GetLatestUpdater(); + static bool DownloadUpdater(); static void CheckForUpdate(); static void ExitProcessStub(unsigned int exitCode);