summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrei Karas <akaras@inbox.ru>2014-05-05 17:23:21 +0300
committerAndrei Karas <akaras@inbox.ru>2014-05-06 13:06:50 +0300
commit05cec243c28f50bd5ee7a167067501f7bd8db3ff (patch)
treeb3b4e97b873ebf5e082ee1092a4c33a1ebdd72b8
parent25bed1bb7f7dbfa3caa0f239c63dbabd3b0bd50d (diff)
downloadmv-05cec243c28f50bd5ee7a167067501f7bd8db3ff.tar.gz
mv-05cec243c28f50bd5ee7a167067501f7bd8db3ff.tar.bz2
mv-05cec243c28f50bd5ee7a167067501f7bd8db3ff.tar.xz
mv-05cec243c28f50bd5ee7a167067501f7bd8db3ff.zip
Validate xml downloads, and if failed, use another mirror.
-rw-r--r--src/commands.cpp2
-rw-r--r--src/gui/windows/serverdialog.cpp2
-rw-r--r--src/gui/windows/updaterwindow.cpp20
-rw-r--r--src/gui/windows/updaterwindow.h2
-rw-r--r--src/net/download.cpp21
-rw-r--r--src/net/download.h8
-rw-r--r--src/utils/xml.cpp38
-rw-r--r--src/utils/xml.h6
8 files changed, 87 insertions, 12 deletions
diff --git a/src/commands.cpp b/src/commands.cpp
index aeb1f3f53..508c78e4e 100644
--- a/src/commands.cpp
+++ b/src/commands.cpp
@@ -1338,7 +1338,7 @@ static void uploadFile(const std::string &str,
Net::Download *const upload = new Net::Download(info,
"http://sprunge.us",
&uploadUpdate,
- false, true);
+ false, true, false);
info->upload = upload;
info->text = str;
info->addStr = addStr;
diff --git a/src/gui/windows/serverdialog.cpp b/src/gui/windows/serverdialog.cpp
index 653d62567..015c94f00 100644
--- a/src/gui/windows/serverdialog.cpp
+++ b/src/gui/windows/serverdialog.cpp
@@ -522,7 +522,7 @@ void ServerDialog::downloadServerList()
}
mDownload = new Net::Download(this, listFile,
- &downloadUpdate, false, false);
+ &downloadUpdate, false, false, true);
mDownload->setFile(std::string(mDir).append("/").append(
branding.getStringValue("onlineServerFile")));
mDownload->start();
diff --git a/src/gui/windows/updaterwindow.cpp b/src/gui/windows/updaterwindow.cpp
index 842176793..dab1a6ebc 100644
--- a/src/gui/windows/updaterwindow.cpp
+++ b/src/gui/windows/updaterwindow.cpp
@@ -193,7 +193,8 @@ UpdaterWindow::UpdaterWindow(const std::string &restrict updateHost,
mStoreInMemory(true),
mDownloadComplete(true),
mUserCancel(false),
- mLoadUpdates(applyUpdates)
+ mLoadUpdates(applyUpdates),
+ mValidateXml(false)
{
setWindowName("UpdaterWindow");
setResizable(true);
@@ -532,13 +533,16 @@ void UpdaterWindow::download()
{
mDownload = new Net::Download(this,
"http://manaplus.org/update/" + mCurrentFile,
- &updateProgress, true, false);
+ &updateProgress,
+ true, false, mValidateXml);
mDownload->addMirror("http://www.manaplus.org/update/" + mCurrentFile);
}
else
{
- mDownload = new Net::Download(this, std::string(mUpdateHost).append(
- "/").append(mCurrentFile), &updateProgress, false, false);
+ mDownload = new Net::Download(this,
+ std::string(mUpdateHost).append("/").append(mCurrentFile),
+ &updateProgress,
+ false, false, mValidateXml);
const std::vector<std::string> &mirrors = client->getMirrors();
FOR_EACH (std::vector<std::string>::const_iterator, it, mirrors)
@@ -788,6 +792,7 @@ void UpdaterWindow::logic()
// Parse current memory buffer as news and dispose of the data
loadNews();
+ mValidateXml = true;
mCurrentFile = xmlUpdateFile;
mStoreInMemory = false;
mDownloadStatus = UPDATE_LIST;
@@ -803,6 +808,7 @@ void UpdaterWindow::logic()
mUpdateHost = updateServer2 + mUpdateServerPath;
mUpdatesDir.append("/fix");
mCurrentFile = xmlUpdateFile;
+ mValidateXml = true;
mStoreInMemory = false;
mDownloadStatus = UPDATE_LIST2;
download();
@@ -827,6 +833,7 @@ void UpdaterWindow::logic()
// If the resources.xml file fails,
// fall back onto a older version
mCurrentFile = txtUpdateFile;
+ mValidateXml = false;
mStoreInMemory = false;
mDownloadStatus = UPDATE_LIST;
download();
@@ -835,6 +842,7 @@ void UpdaterWindow::logic()
}
else if (mCurrentFile == txtUpdateFile)
{
+ mValidateXml = true;
mUpdateFiles = loadTxtFile(std::string(mUpdatesDir).append(
"/").append(txtUpdateFile));
}
@@ -863,6 +871,7 @@ void UpdaterWindow::logic()
std::ifstream temp((std::string(mUpdatesDir).append(
"/").append(mCurrentFile)).c_str());
+ mValidateXml = false;
if (!temp.is_open() || !validateFile(std::string(
mUpdatesDir).append("/").append(mCurrentFile),
mCurrentChecksum))
@@ -883,6 +892,7 @@ void UpdaterWindow::logic()
mCurrentFile = "latest.txt";
mStoreInMemory = true;
mDownloadStatus = UPDATE_PATCH;
+ mValidateXml = false;
download(); // download() changes
// mDownloadComplete to false
}
@@ -898,6 +908,7 @@ void UpdaterWindow::logic()
}
mUpdateIndexOffset = mUpdateIndex;
mUpdateIndex = 0;
+ mValidateXml = true;
mStoreInMemory = false;
mDownloadStatus = UPDATE_RESOURCES2;
download();
@@ -906,6 +917,7 @@ void UpdaterWindow::logic()
case UPDATE_RESOURCES2:
if (mDownloadComplete)
{
+ mValidateXml = false;
if (mUpdateIndex < mTempUpdateFiles.size())
{
const UpdateFile thisFile = mTempUpdateFiles[mUpdateIndex];
diff --git a/src/gui/windows/updaterwindow.h b/src/gui/windows/updaterwindow.h
index 4874ba8ba..d73da1e3e 100644
--- a/src/gui/windows/updaterwindow.h
+++ b/src/gui/windows/updaterwindow.h
@@ -268,6 +268,8 @@ private:
/** Tells ~UpdaterWindow() if it should load updates */
bool mLoadUpdates;
+
+ bool mValidateXml;
};
#endif // GUI_WINDOWS_UPDATERWINDOW_H
diff --git a/src/net/download.cpp b/src/net/download.cpp
index 26a3cfe58..e1b5012fd 100644
--- a/src/net/download.cpp
+++ b/src/net/download.cpp
@@ -60,9 +60,12 @@ namespace Net
std::string Download::mUploadResponse = "";
-Download::Download(void *const ptr, const std::string &url,
+Download::Download(void *const ptr,
+ const std::string &url,
const DownloadUpdate updateFunction,
- const bool ignoreError, const bool isUpload) :
+ const bool ignoreError,
+ const bool isUpload,
+ const bool isXml) :
mPtr(ptr),
mUrl(url),
mOptions(),
@@ -77,7 +80,8 @@ Download::Download(void *const ptr, const std::string &url,
mFormPost(nullptr),
mError(static_cast<char*>(calloc(CURL_ERROR_SIZE + 1, 1))),
mIgnoreError(ignoreError),
- mUpload(isUpload)
+ mUpload(isUpload),
+ mIsXml(isXml)
{
if (mError)
mError[0] = 0;
@@ -417,6 +421,7 @@ int Download::downloadThread(void *ptr)
continue; // Bail out here to avoid the renaming
}
}
+
if (file)
{
fclose(file);
@@ -427,6 +432,16 @@ int Download::downloadThread(void *ptr)
// otherwise the rename will fail on Windows.
if (!d->mOptions.cancel)
{
+ if (d->mIsXml)
+ {
+ if (!XML::Document::validateXml(outFilename))
+ {
+ logger->log_r("Xml file validation error");
+ attempts++;
+ continue;
+ }
+ }
+
::remove(d->mFileName.c_str());
Files::renameFile(outFilename, d->mFileName);
diff --git a/src/net/download.h b/src/net/download.h
index 2201aaff2..bc12a8f7c 100644
--- a/src/net/download.h
+++ b/src/net/download.h
@@ -55,9 +55,12 @@ namespace Net
class Download final
{
public:
- Download(void *const ptr, const std::string &url,
+ Download(void *const ptr,
+ const std::string &url,
const DownloadUpdate updateFunction,
- const bool ignoreError, const bool isUpload);
+ const bool ignoreError,
+ const bool isUpload,
+ const bool isXml);
A_DELETE_COPY(Download)
@@ -141,6 +144,7 @@ class Download final
char *mError;
bool mIgnoreError;
bool mUpload;
+ bool mIsXml;
};
} // namespace Net
diff --git a/src/utils/xml.cpp b/src/utils/xml.cpp
index 3d98fda61..eae3567ef 100644
--- a/src/utils/xml.cpp
+++ b/src/utils/xml.cpp
@@ -27,6 +27,7 @@
#include "resources/resourcemanager.h"
#include "utils/fuzzer.h"
+#include "utils/stringutils.h"
#include "utils/translation/podict.h"
@@ -34,6 +35,11 @@
#include "debug.h"
+namespace
+{
+ bool valid = false;
+} // namespace
+
static void xmlErrorLogger(void *ctx A_UNUSED, const char *msg A_UNUSED, ...)
#ifdef __GNUC__
#ifdef __OpenBSD__
@@ -61,12 +67,13 @@ static void xmlErrorLogger(void *ctx A_UNUSED, const char *msg, ...)
va_end(ap);
if (logger)
- logger->log1(buf);
+ logger->log_r("%s", buf);
else
puts(buf);
// Delete temporary buffer
delete [] buf;
+ valid = false;
}
namespace XML
@@ -80,6 +87,7 @@ namespace XML
#endif
int size = 0;
char *data = nullptr;
+ valid = true;
if (useResman)
{
const ResourceManager *const resman
@@ -122,6 +130,7 @@ namespace XML
{
logger->log("Error loading %s", filename.c_str());
}
+ mIsValid = valid;
}
Document::Document(const char *const data, const int size) :
@@ -261,4 +270,31 @@ namespace XML
xmlCleanupParser();
}
+ bool Document::validateXml(const std::string &fileName)
+ {
+ xmlDocPtr doc = xmlReadFile(fileName.c_str(),
+ nullptr, XML_PARSE_PEDANTIC);
+ const bool valid(doc);
+ xmlFreeDoc(doc);
+ if (!valid)
+ return false;
+
+ std::ifstream file;
+ file.open(fileName.c_str(), std::ios::in);
+ if (!file.is_open())
+ {
+ file.close();
+ return false;
+ }
+ char line[101];
+ if (!file.getline(line, 100))
+ return false;
+ file.close();
+
+ const std::string str = line;
+ if (!strStartWith(str, "<?xml "))
+ return false;
+
+ return true;
+ }
} // namespace XML
diff --git a/src/utils/xml.h b/src/utils/xml.h
index d8a281045..9ed433ad5 100644
--- a/src/utils/xml.h
+++ b/src/utils/xml.h
@@ -93,8 +93,14 @@ namespace XML
bool isLoaded() const
{ return mDoc != nullptr; }
+ bool isValid() const
+ { return mIsValid; }
+
+ static bool validateXml(const std::string &fileName);
+
private:
xmlDocPtr mDoc;
+ bool mIsValid;
};
/**