summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEugenio Favalli <elvenprogrammer@gmail.com>2006-12-12 15:52:42 +0000
committerEugenio Favalli <elvenprogrammer@gmail.com>2006-12-12 15:52:42 +0000
commit16cb089845b3adcdd605d138d903bd7ada0f9e03 (patch)
treed43dea9b474d9cceee0de653e23f9aa2c556009e /src
parent15d969bb200b3e820982ccc8cb157231d7befa7e (diff)
downloadmana-16cb089845b3adcdd605d138d903bd7ada0f9e03.tar.gz
mana-16cb089845b3adcdd605d138d903bd7ada0f9e03.tar.bz2
mana-16cb089845b3adcdd605d138d903bd7ada0f9e03.tar.xz
mana-16cb089845b3adcdd605d138d903bd7ada0f9e03.zip
Added Adler32 checksum for updates
Diffstat (limited to 'src')
-rw-r--r--src/gui/updatewindow.cpp171
-rw-r--r--src/gui/updatewindow.h9
-rw-r--r--src/main.cpp9
3 files changed, 121 insertions, 68 deletions
diff --git a/src/gui/updatewindow.cpp b/src/gui/updatewindow.cpp
index a23438cb..3bdd5526 100644
--- a/src/gui/updatewindow.cpp
+++ b/src/gui/updatewindow.cpp
@@ -26,6 +26,7 @@
#include <iostream>
#include <SDL.h>
#include <SDL_thread.h>
+#include <zlib.h>
#include <curl/curl.h>
@@ -48,9 +49,9 @@ UpdaterWindow::UpdaterWindow():
Window("Updating..."),
mThread(NULL), mMutex(NULL), mDownloadStatus(UPDATE_NEWS),
mUpdateHost(""), mCurrentFile("news.txt"), mBasePath(""),
- mStoreInMemory(true), mDownloadComplete(true), mUserCancel(false),
- mDownloadedBytes(0), mMemoryBuffer(NULL),
- mCurlError(new char[CURL_ERROR_SIZE]), mFileIndex(0)
+ mStoreInMemory(true), mDownloadComplete(true), mUserCancel(false),
+ mDownloadedBytes(0), mMemoryBuffer(NULL),
+ mCurlError(new char[CURL_ERROR_SIZE]), mLineIndex(0)
{
mCurlError[0] = 0;
@@ -233,78 +234,116 @@ size_t UpdaterWindow::memoryWrite(void *ptr,
int UpdaterWindow::downloadThread(void *ptr)
{
+ int attempts = 0;
+ UpdaterWindow *uw = reinterpret_cast<UpdaterWindow *>(ptr);
CURL *curl;
CURLcode res;
- FILE *outfile = NULL;
- UpdaterWindow *uw = reinterpret_cast<UpdaterWindow *>(ptr);
std::string outFilename;
std::string url(uw->mUpdateHost + "/" + uw->mCurrentFile);
- uw->setLabel(uw->mCurrentFile + " (0%)");
- curl = curl_easy_init();
+ while (attempts < 3 && !uw->mDownloadComplete) {
+ FILE *outfile = NULL;
+ uw->setLabel(uw->mCurrentFile + " (0%)");
- if (curl)
- {
- logger->log("Downloading: %s", url.c_str());
+ curl = curl_easy_init();
- if (uw->mStoreInMemory)
+ if (curl)
{
- uw->mDownloadedBytes = 0;
- curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1);
- curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION,
- UpdaterWindow::memoryWrite);
- curl_easy_setopt(curl, CURLOPT_WRITEDATA, ptr);
- }
- else
- {
- // Download in the proper folder : ./updates under win,
- // /home/user/.tmw/updates for unices
- outFilename = uw->mBasePath + "/updates/download.temp";
- outfile = fopen(outFilename.c_str(), "wb");
- curl_easy_setopt(curl, CURLOPT_WRITEDATA, outfile);
- }
+ logger->log("Downloading: %s", url.c_str());
- curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, uw->mCurlError);
- curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
- curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0);
- curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION,
- UpdaterWindow::updateProgress);
- curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, ptr);
- curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
- curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 15);
+ if (uw->mStoreInMemory)
+ {
+ uw->mDownloadedBytes = 0;
+ curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1);
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION,
+ UpdaterWindow::memoryWrite);
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, ptr);
+ }
+ else
+ {
+ // Download in the proper folder : ./updates under win,
+ // /home/user/.tmw/updates for unices
+ outFilename = uw->mBasePath + "/updates/download.temp";
+ outfile = fopen(outFilename.c_str(), "w+b");
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, outfile);
+ }
- if ((res = curl_easy_perform(curl)) != 0)
- {
- uw->mDownloadStatus = UPDATE_ERROR;
- switch (res)
+ curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, uw->mCurlError);
+ curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
+ curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0);
+ curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION,
+ UpdaterWindow::updateProgress);
+ curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, ptr);
+ curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
+ curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 15);
+
+ if ((res = curl_easy_perform(curl)) != 0)
{
- case CURLE_COULDNT_CONNECT: // give more debug info on that error
- std::cerr << "curl error " << res << " : " << uw->mCurlError << " " << url.c_str()
- << std::endl;
- break;
-
- default:
- std::cerr << "curl error " << res << " : " << uw->mCurlError << " host: " << url.c_str()
- << std::endl;
+ uw->mDownloadStatus = UPDATE_ERROR;
+ switch (res)
+ {
+ case CURLE_COULDNT_CONNECT: // give more debug info on that error
+ std::cerr << "curl error " << res << " : " << uw->mCurlError << " " << url.c_str()
+ << std::endl;
+ break;
+
+ default:
+ std::cerr << "curl error " << res << " : " << uw->mCurlError << " host: " << url.c_str()
+ << std::endl;
+ }
}
- }
- curl_easy_cleanup(curl);
- uw->mDownloadComplete = true;
+ curl_easy_cleanup(curl);
- if (!uw->mStoreInMemory)
- {
- fclose(outfile);
+ uw->mDownloadComplete = true;
- // Give the file the proper name
- std::string newName(uw->mBasePath + "/updates/" +
- uw->mCurrentFile.c_str());
+ if (!uw->mStoreInMemory)
+ {
+ long fileSize;
+ char *buffer;
+ // Obtain file size.
+ fseek(outfile, 0, SEEK_END);
+ fileSize = ftell(outfile);
+ rewind(outfile);
+ buffer = (char*)malloc(fileSize);
+ fread(buffer, 1, fileSize, outfile);
+ fclose(outfile);
+
+ // Give the file the proper name
+ std::string newName(uw->mBasePath + "/updates/" +
+ uw->mCurrentFile.c_str());
+
+ // Any existing file with this name is deleted first, otherwise the
+ // rename will fail on Windows.
+ ::remove(newName.c_str());
+ ::rename(outFilename.c_str(), newName.c_str());
+
+ // Don't check resources2.txt checksum
+ if (uw->mDownloadStatus == UPDATE_RESOURCES)
+ {
+ // Calculate Adler-32 checksum
+ unsigned long adler = adler32(0L, Z_NULL, 0);
+ adler = adler32(adler, (Bytef *)buffer, fileSize);
+ free(buffer);
+
+ if (uw->mCurrentChecksum != adler) {
+ uw->mDownloadComplete = false;
+ // Remove the corrupted file
+ ::remove(newName.c_str());
+ logger->log(
+ "Checksum for file %s failed: (%lx/%lx)",
+ uw->mCurrentFile.c_str(),
+ adler, uw->mCurrentChecksum);
+ }
+ }
- // Any existing file with this name is deleted first, otherwise the
- // rename will fail on Windows.
- ::remove(newName.c_str());
- ::rename(outFilename.c_str(), newName.c_str());
+ }
}
+ attempts++;
+ }
+
+ if (!uw->mDownloadComplete) {
+ uw->mDownloadStatus = UPDATE_ERROR;
}
return 0;
@@ -356,7 +395,7 @@ void UpdaterWindow::logic()
// Parse current memory buffer as news and dispose of the data
loadNews();
- mCurrentFile = "resources.txt";
+ mCurrentFile = "resources2.txt";
mStoreInMemory = false;
download();
mDownloadStatus = UPDATE_LIST;
@@ -366,7 +405,7 @@ void UpdaterWindow::logic()
if (mDownloadComplete)
{
ResourceManager *resman = ResourceManager::getInstance();
- mFiles = resman->loadTextFile("updates/resources.txt");
+ mLines = resman->loadTextFile("updates/resources2.txt");
mStoreInMemory = false;
mDownloadStatus = UPDATE_RESOURCES;
}
@@ -380,9 +419,15 @@ void UpdaterWindow::logic()
mThread = NULL;
}
- if (mFileIndex < mFiles.size())
+ if (mLineIndex < mLines.size())
{
- mCurrentFile = mFiles[mFileIndex];
+ std::stringstream line(mLines[mLineIndex]);
+ line >> mCurrentFile;
+ std::string checksum;
+ line >> checksum;
+ std::stringstream ss(checksum);
+ ss >> std::hex >> mCurrentChecksum;
+
std::ifstream temp(
(mBasePath + "/updates/" + mCurrentFile).c_str());
if (!temp.is_open())
@@ -394,7 +439,7 @@ void UpdaterWindow::logic()
{
logger->log("%s already here", mCurrentFile.c_str());
}
- mFileIndex++;
+ mLineIndex++;
}
else
{
diff --git a/src/gui/updatewindow.h b/src/gui/updatewindow.h
index 5016036d..d2d1d68f 100644
--- a/src/gui/updatewindow.h
+++ b/src/gui/updatewindow.h
@@ -146,6 +146,11 @@ class UpdaterWindow : public Window, public gcn::ActionListener
std::string mCurrentFile;
/**
+ * The Adler32 checksum of the file currently downloading.
+ */
+ unsigned long mCurrentChecksum;
+
+ /**
* Absolute path to locally save downloaded files.
*/
std::string mBasePath;
@@ -184,12 +189,12 @@ class UpdaterWindow : public Window, public gcn::ActionListener
/**
* List of files to download
*/
- std::vector<std::string> mFiles;
+ std::vector<std::string> mLines;
/**
* Index of the file to be downloaded
*/
- unsigned int mFileIndex;
+ unsigned int mLineIndex;
gcn::Label *mLabel; /**< Progress bar caption. */
Button *mCancelButton; /**< Button to stop the update process. */
diff --git a/src/main.cpp b/src/main.cpp
index eebb92bb..f54b0792 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -380,19 +380,22 @@ void parseOptions(int argc, char *argv[], Options &options)
}
/**
- * Reads the file "updates/resources.txt" and attempts to load each update
+ * Reads the file "updates/resources2.txt" and attempts to load each update
* mentioned in it.
*/
void loadUpdates()
{
- const std::string updatesFile = "updates/resources.txt";
+ const std::string updatesFile = "updates/resources2.txt";
ResourceManager *resman = ResourceManager::getInstance();
std::vector<std::string> lines = resman->loadTextFile(updatesFile);
std::string homeDir = config.getValue("homeDir", "");
for (unsigned int i = 0; i < lines.size(); ++i)
{
- resman->addToSearchPath(homeDir + "/updates/" + lines[i], false);
+ std::stringstream line(lines[i]);
+ std::string filename;
+ line >> filename;
+ resman->addToSearchPath(homeDir + "/updates/" + filename, false);
}
}