From 55a0d110b654a93ef1bb9ee50a6f02ecaec7f88d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Tue, 13 May 2014 23:57:34 +0200 Subject: Lock down the version cache. Just enough to make it annoying to corrupt the files. --- logic/OneSixInstance.cpp | 21 +++++++--------- logic/minecraft/MinecraftVersion.cpp | 4 +-- logic/minecraft/MinecraftVersionList.cpp | 42 ++++++++++++++++++-------------- logic/minecraft/MinecraftVersionList.h | 2 +- logic/minecraft/VersionBuilder.cpp | 19 +++++++++++++++ logic/minecraft/VersionBuilder.h | 1 + 6 files changed, 56 insertions(+), 33 deletions(-) (limited to 'logic') diff --git a/logic/OneSixInstance.cpp b/logic/OneSixInstance.cpp index 574dfc69..fc53bd39 100644 --- a/logic/OneSixInstance.cpp +++ b/logic/OneSixInstance.cpp @@ -24,6 +24,7 @@ #include "logic/OneSixInstance_p.h" #include "logic/OneSixUpdate.h" #include "logic/minecraft/VersionFinal.h" +#include "minecraft/VersionBuildError.h" #include "logic/assets/AssetsUtils.h" #include "icons/IconList.h" @@ -42,21 +43,13 @@ OneSixInstance::OneSixInstance(const QString &rootDir, SettingsObject *settings, void OneSixInstance::init() { - // FIXME: why is this decided here? what does this even mean? - if (QDir(instanceRoot()).exists("version.json")) + try { - try - { - reloadVersion(); - } - catch (MMCError &e) - { - // QLOG_ERROR() << "Caught exception on instance init: " << e.cause(); - } + reloadVersion(); } - else + catch (MMCError &e) { - clearVersion(); + QLOG_ERROR() << "Caught exception on instance init: " << e.cause(); } } @@ -388,6 +381,10 @@ void OneSixInstance::reloadVersion() d->version->reload(externalPatches()); d->m_flags.remove(VersionBrokenFlag); emit versionReloaded(); + } + catch (VersionIncomplete & error) + { + } catch (MMCError &error) { diff --git a/logic/minecraft/MinecraftVersion.cpp b/logic/minecraft/MinecraftVersion.cpp index b66b9768..21cdbacc 100644 --- a/logic/minecraft/MinecraftVersion.cpp +++ b/logic/minecraft/MinecraftVersion.cpp @@ -56,9 +56,9 @@ bool MinecraftVersion::isMinecraftVersion() // 2. if discrepancies are found, fall out and fail (impossible to apply incomplete version). void MinecraftVersion::applyFileTo(VersionFinal *version) { - QFileInfo versionFile(QString("versions/%1/%1.json").arg(m_descriptor)); + QFileInfo versionFile(QString("versions/%1/%1.dat").arg(m_descriptor)); - auto versionObj = VersionBuilder::parseJsonFile(versionFile, false, false); + auto versionObj = VersionBuilder::parseBinaryJsonFile(versionFile); versionObj->applyTo(version); } diff --git a/logic/minecraft/MinecraftVersionList.cpp b/logic/minecraft/MinecraftVersionList.cpp index 8c30e38d..b561606b 100644 --- a/logic/minecraft/MinecraftVersionList.cpp +++ b/logic/minecraft/MinecraftVersionList.cpp @@ -29,6 +29,8 @@ #include #include +static const char * localVersionCache = "versions/versions.dat"; + class ListLoadError : public MMCError { public: @@ -78,7 +80,7 @@ void MinecraftVersionList::sortInternal() void MinecraftVersionList::loadCachedList() { - QFile localIndex("versions/versions.json"); + QFile localIndex(localVersionCache); if (!localIndex.exists()) { return; @@ -92,13 +94,18 @@ void MinecraftVersionList::loadCachedList() auto data = localIndex.readAll(); try { - loadMojangList(data, Local); + localIndex.close(); + QJsonDocument jsonDoc = QJsonDocument::fromBinaryData(data); + if (jsonDoc.isNull()) + { + throw ListLoadError(tr("Error reading the version list.")); + } + loadMojangList(jsonDoc, Local); } catch (MMCError &e) { // the cache has gone bad for some reason... flush it. QLOG_ERROR() << "The minecraft version cache is corrupted. Flushing cache."; - localIndex.close(); localIndex.remove(); return; } @@ -172,18 +179,10 @@ void MinecraftVersionList::loadBuiltinList() } } -void MinecraftVersionList::loadMojangList(QByteArray data, VersionSource source) +void MinecraftVersionList::loadMojangList(QJsonDocument jsonDoc, VersionSource source) { QLOG_INFO() << "Loading" << ((source == Remote) ? "remote" : "local") << "version list."; - QJsonParseError jsonError; - QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &jsonError); - if (jsonError.error != QJsonParseError::NoError) - { - throw ListLoadError( - tr("Error parsing version list JSON: %1").arg(jsonError.errorString())); - } - if (!jsonDoc.isObject()) { throw ListLoadError(tr("Error parsing version list JSON: jsonDoc is not an object")); @@ -391,7 +390,14 @@ void MCVListLoadTask::list_downloaded() vlistReply->deleteLater(); try { - m_list->loadMojangList(data, Remote); + QJsonParseError jsonError; + QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &jsonError); + if (jsonError.error != QJsonParseError::NoError) + { + throw ListLoadError( + tr("Error parsing version list JSON: %1").arg(jsonError.errorString())); + } + m_list->loadMojangList(jsonDoc, Remote); } catch (MMCError &e) { @@ -474,9 +480,9 @@ void MCVListVersionUpdateTask::json_downloaded() // now dump the file to disk auto doc = file->toJson(false); - auto newdata = doc.toJson(); + auto newdata = doc.toBinaryData(); QLOG_INFO() << newdata; - QString targetPath = "versions/" + versionToUpdate + "/" + versionToUpdate + ".json"; + QString targetPath = "versions/" + versionToUpdate + "/" + versionToUpdate + ".dat"; ensureFilePathExists(targetPath); QSaveFile vfile1(targetPath); if (!vfile1.open(QIODevice::Truncate | QIODevice::WriteOnly)) @@ -511,9 +517,9 @@ std::shared_ptr MinecraftVersionList::createUpdateTask(QString version) void MinecraftVersionList::saveCachedList() { // FIXME: throw. - if (!ensureFilePathExists("versions/versions.json")) + if (!ensureFilePathExists(localVersionCache)) return; - QSaveFile tfile("versions/versions.json"); + QSaveFile tfile(localVersionCache); if (!tfile.open(QIODevice::WriteOnly | QIODevice::Truncate)) return; QJsonObject toplevel; @@ -554,7 +560,7 @@ void MinecraftVersionList::saveCachedList() } QJsonDocument doc(toplevel); - QByteArray jsonData = doc.toJson(); + QByteArray jsonData = doc.toBinaryData(); qint64 result = tfile.write(jsonData); if (result == -1) return; diff --git a/logic/minecraft/MinecraftVersionList.h b/logic/minecraft/MinecraftVersionList.h index bbbd71e1..4753ce05 100644 --- a/logic/minecraft/MinecraftVersionList.h +++ b/logic/minecraft/MinecraftVersionList.h @@ -34,7 +34,7 @@ class MinecraftVersionList : public BaseVersionList private: void sortInternal(); void loadBuiltinList(); - void loadMojangList(QByteArray data, VersionSource source); + void loadMojangList(QJsonDocument jsonDoc, VersionSource source); void loadCachedList(); void saveCachedList(); void finalizeUpdate(QString version); diff --git a/logic/minecraft/VersionBuilder.cpp b/logic/minecraft/VersionBuilder.cpp index d19c2877..cff70821 100644 --- a/logic/minecraft/VersionBuilder.cpp +++ b/logic/minecraft/VersionBuilder.cpp @@ -237,6 +237,25 @@ VersionFilePtr VersionBuilder::parseJsonFile(const QFileInfo &fileInfo, const bo // info.").arg(file.fileName()); } +VersionFilePtr VersionBuilder::parseBinaryJsonFile(const QFileInfo &fileInfo) +{ + QFile file(fileInfo.absoluteFilePath()); + if (!file.open(QFile::ReadOnly)) + { + throw JSONValidationError(QObject::tr("Unable to open the version file %1: %2.") + .arg(fileInfo.fileName(), file.errorString())); + } + QJsonDocument doc = QJsonDocument::fromBinaryData(file.readAll()); + file.close(); + if (doc.isNull()) + { + file.remove(); + throw JSONValidationError( + QObject::tr("Unable to process the version file %1.").arg(fileInfo.fileName())); + } + return VersionFile::fromJson(doc, file.fileName(), false, false); +} + QMap VersionBuilder::readOverrideOrders(OneSixInstance *instance) { QMap out; diff --git a/logic/minecraft/VersionBuilder.h b/logic/minecraft/VersionBuilder.h index fc06e614..6097840b 100644 --- a/logic/minecraft/VersionBuilder.h +++ b/logic/minecraft/VersionBuilder.h @@ -31,6 +31,7 @@ public: static void build(VersionFinal *version, OneSixInstance *instance, const QStringList &external); static void readJsonAndApplyToVersion(VersionFinal *version, const QJsonObject &obj); static VersionFilePtr parseJsonFile(const QFileInfo &fileInfo, const bool requireOrder, bool isFTB = false); + static VersionFilePtr parseBinaryJsonFile(const QFileInfo &fileInfo); static QMap readOverrideOrders(OneSixInstance *instance); static bool writeOverrideOrders(const QMap &order, OneSixInstance *instance); -- cgit v1.2.3