diff options
author | Thorbjørn Lindeijer <bjorn@lindeijer.nl> | 2024-02-29 17:25:29 +0100 |
---|---|---|
committer | Thorbjørn Lindeijer <bjorn@lindeijer.nl> | 2024-02-29 17:25:29 +0100 |
commit | 2e60491ceb0548b0bea93207c13b974d6a6cf5cc (patch) | |
tree | 43ea8aefa4aa1646df82a5163b9cdae0a39df48e | |
parent | dd1db3753ecf8a4d782aee1f518759763d8caf87 (diff) | |
download | mana-2e60491ceb0548b0bea93207c13b974d6a6cf5cc.tar.gz mana-2e60491ceb0548b0bea93207c13b974d6a6cf5cc.tar.bz2 mana-2e60491ceb0548b0bea93207c13b974d6a6cf5cc.tar.xz mana-2e60491ceb0548b0bea93207c13b974d6a6cf5cc.zip |
Re-download updates when their checksum no longer matches
The Mana World currently likes to just update its "TMW.zip" file,
whereas updates were always given unique names in the past. With this
change, the client checks the Adler32 checksum to know when it should
re-download an update file.
This matches the behavior of ManaPlus commit
96150f1aeacf55d311c41ffe12d9e754b1cda001.
-rw-r--r-- | src/gui/updaterwindow.cpp | 34 | ||||
-rw-r--r-- | src/net/download.cpp | 45 | ||||
-rw-r--r-- | src/net/download.h | 11 | ||||
-rw-r--r-- | src/utils/xml.cpp | 2 |
4 files changed, 43 insertions, 49 deletions
diff --git a/src/gui/updaterwindow.cpp b/src/gui/updaterwindow.cpp index 2861f973..54ce8aeb 100644 --- a/src/gui/updaterwindow.cpp +++ b/src/gui/updaterwindow.cpp @@ -70,10 +70,10 @@ std::vector<UpdateFile> loadXMLFile(const std::string &fileName) continue; UpdateFile file; - file.name = XML::getProperty(fileNode, "file", ""); - file.hash = XML::getProperty(fileNode, "hash", ""); + file.name = XML::getProperty(fileNode, "file", std::string()); + file.hash = XML::getProperty(fileNode, "hash", std::string()); file.type = XML::getProperty(fileNode, "type", "data"); - file.desc = XML::getProperty(fileNode, "description", ""); + file.desc = XML::getProperty(fileNode, "description", std::string()); file.required = XML::getProperty(fileNode, "required", "yes") == "yes"; files.push_back(file); @@ -86,13 +86,14 @@ std::vector<UpdateFile> loadTxtFile(const std::string &fileName) { std::vector<UpdateFile> files; std::ifstream fileHandler; - fileHandler.open(fileName.c_str(), std::ios::in); + fileHandler.open(fileName, std::ios::in); if (fileHandler.is_open()) { while (fileHandler.good()) { - char name[256], hash[50]; + char name[256]; + char hash[50]; fileHandler.getline(name, 256, ' '); fileHandler.getline(hash, 50); @@ -101,7 +102,6 @@ std::vector<UpdateFile> loadTxtFile(const std::string &fileName) thisFile.hash = hash; thisFile.type = "data"; thisFile.required = true; - thisFile.desc.clear(); if (!thisFile.name.empty()) files.push_back(thisFile); @@ -459,35 +459,31 @@ void UpdaterWindow::logic() { if (mUpdateIndex < mUpdateFiles.size()) { - UpdateFile thisFile = mUpdateFiles[mUpdateIndex]; + const UpdateFile &thisFile = mUpdateFiles[mUpdateIndex]; if (!thisFile.required) { - // This statement checks to see if the file type is music, and if download-music is true - // If it fails, this statement returns true, and results in not downloading the file - // Else it will ignore the break, and download the file. - if ( !(thisFile.type == "music" && config.getBoolValue("download-music")) ) + if (!(thisFile.type == "music" && config.getBoolValue("download-music"))) { mUpdateIndex++; break; } } mCurrentFile = thisFile.name; - std::string checksum; - checksum = thisFile.hash; - std::stringstream ss(checksum); + std::stringstream ss(thisFile.hash); ss >> std::hex >> mCurrentChecksum; - std::ifstream temp( - (mUpdatesDir + "/" + mCurrentFile).c_str()); + std::string filename = mUpdatesDir + "/" + mCurrentFile; + FILE *file = fopen(filename.c_str(), "r+b"); - if (!temp.is_open()) + if (!file || Net::Download::fadler32(file) != mCurrentChecksum) { - temp.close(); + if (file) + fclose(file); download(); } else { - temp.close(); + fclose(file); logger->log("%s already here", mCurrentFile.c_str()); } mUpdateIndex++; diff --git a/src/net/download.cpp b/src/net/download.cpp index dc928d56..8a41ebfa 100644 --- a/src/net/download.cpp +++ b/src/net/download.cpp @@ -33,32 +33,33 @@ const char *DOWNLOAD_ERROR_MESSAGE_THREAD = "Could not create download thread!"; +namespace Net { + /** * Calculates the Alder-32 checksum for the given file. */ -static unsigned long fadler32(FILE *file) +unsigned long Download::fadler32(FILE *file) { - // Obtain file size - fseek(file, 0, SEEK_END); - long fileSize = ftell(file); + if (!file || fseek(file, 0, SEEK_END) != 0) + return 0; + + const long fileSize = ftell(file); + if (fileSize < 0) + return 0; + rewind(file); // Calculate Adler-32 checksum - char *buffer = (char*) malloc(fileSize); + void *buffer = malloc(fileSize); const size_t read = fread(buffer, 1, fileSize, file); - unsigned long adler = adler32(0L, Z_NULL, 0); - adler = adler32(adler, (Bytef*) buffer, read); + unsigned long adler = adler32_z(0L, Z_NULL, 0); + adler = adler32_z(adler, (Bytef*) buffer, read); free(buffer); return adler; } -enum { - OPTIONS_NONE = 0, - OPTIONS_MEMORY = 1 -}; -namespace Net{ Download::Download(void *ptr, const std::string &url, DownloadUpdate updateFunction): mPtr(ptr), @@ -92,18 +93,12 @@ void Download::noCache() addHeader("Cache-Control: no-cache"); } -void Download::setFile(const std::string &filename, int64_t adler32) +void Download::setFile(const std::string &filename, + std::optional<unsigned long> adler32) { mOptions.memoryWrite = false; mFileName = filename; - - if (adler32 > -1) - { - mAdler = (unsigned long) adler32; - mOptions.checkAdler = true; - } - else - mOptions.checkAdler = false; + mAdler = adler32; } void Download::setWriteFunction(WriteFunction write) @@ -142,7 +137,7 @@ void Download::cancel() } } -char *Download::getError() +const char *Download::getError() const { return mError; } @@ -223,7 +218,7 @@ int Download::downloadThread(void *ptr) curl_easy_setopt(d->mCurl, CURLOPT_URL, d->mUrl.c_str()); curl_easy_setopt(d->mCurl, CURLOPT_NOPROGRESS, 0); curl_easy_setopt(d->mCurl, CURLOPT_XFERINFOFUNCTION, downloadProgress); - curl_easy_setopt(d->mCurl, CURLOPT_PROGRESSDATA, ptr); + curl_easy_setopt(d->mCurl, CURLOPT_XFERINFODATA, ptr); curl_easy_setopt(d->mCurl, CURLOPT_NOSIGNAL, 1); curl_easy_setopt(d->mCurl, CURLOPT_CONNECTTIMEOUT, 15); @@ -262,7 +257,7 @@ int Download::downloadThread(void *ptr) if (!d->mOptions.memoryWrite) { // Don't check resources.xml checksum - if (d->mOptions.checkAdler) + if (d->mAdler) { unsigned long adler = fadler32(file); @@ -274,7 +269,7 @@ int Download::downloadThread(void *ptr) ::remove(d->mFileName.c_str()); logger->log("Checksum for file %s failed: (%lx/%lx)", d->mFileName.c_str(), - adler, d->mAdler); + adler, *d->mAdler); attempts++; continue; // Bail out here to avoid the renaming } diff --git a/src/net/download.h b/src/net/download.h index 500de0b6..0ce8cc8a 100644 --- a/src/net/download.h +++ b/src/net/download.h @@ -21,6 +21,7 @@ #include <cstdlib> // pulls in int64_t #include <cstdio> #include <string> +#include <optional> #include <curl/curl.h> @@ -61,7 +62,8 @@ class Download */ void noCache(); - void setFile(const std::string &filename, int64_t adler32 = -1); + void setFile(const std::string &filename, + std::optional<unsigned long> adler32 = {}); void setWriteFunction(WriteFunction write); @@ -79,7 +81,9 @@ class Download */ void cancel(); - char *getError(); + const char *getError() const; + + static unsigned long fadler32(FILE *file); private: static int downloadThread(void *ptr); @@ -91,11 +95,10 @@ class Download struct { unsigned cancel : 1; unsigned memoryWrite: 1; - unsigned checkAdler: 1; } mOptions; std::string mFileName; WriteFunction mWriteFunction = nullptr; - unsigned long mAdler; + std::optional<unsigned long> mAdler; DownloadUpdate mUpdateFunction; SDL_Thread *mThread = nullptr; CURL *mCurl = nullptr; diff --git a/src/utils/xml.cpp b/src/utils/xml.cpp index 2fb9d66b..fea5589f 100644 --- a/src/utils/xml.cpp +++ b/src/utils/xml.cpp @@ -58,7 +58,7 @@ namespace XML if (useResman) { ResourceManager *resman = ResourceManager::getInstance(); - data = (char*) resman->loadFile(filename.c_str(), size); + data = (char*) resman->loadFile(filename, size); } else { |