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: [PATCH] Lock down the version cache. Just enough to make it annoying to corrupt the files. --- gui/dialogs/InstanceEditDialog.cpp | 55 ++++++++++++++++++------ gui/dialogs/InstanceEditDialog.h | 1 + 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 + 8 files changed, 99 insertions(+), 46 deletions(-) diff --git a/gui/dialogs/InstanceEditDialog.cpp b/gui/dialogs/InstanceEditDialog.cpp index 5bd923e3a..48657c71f 100644 --- a/gui/dialogs/InstanceEditDialog.cpp +++ b/gui/dialogs/InstanceEditDialog.cpp @@ -50,6 +50,7 @@ #include "CustomMessageBox.h" #include #include +#include #include #include @@ -171,6 +172,26 @@ void InstanceEditDialog::on_removeLibraryBtn_clicked() } } +void InstanceEditDialog::on_jarmodBtn_clicked() +{ + QFileDialog w; + w.setFileMode(QFileDialog::AnyFile); + // w.setOption(QFileDialog::DontUseNativeDialog, true); + QListView *l = w.findChild("listView"); + if (l) + { + l->setSelectionMode(QAbstractItemView::ExtendedSelection); + } + QTreeView *t = w.findChild(); + if (t) + { + t->setSelectionMode(QAbstractItemView::ExtendedSelection); + } + int result = w.exec(); + auto list = w.selectedFiles(); + QLOG_INFO() << list.join(" "); +} + void InstanceEditDialog::on_resetLibraryOrderBtn_clicked() { try @@ -192,8 +213,10 @@ void InstanceEditDialog::on_moveLibraryUpBtn_clicked() try { const int row = ui->libraryTreeView->selectionModel()->selectedRows().first().row(); - const int newRow = 0;m_version->move(row, VersionFinal::MoveUp); - //ui->libraryTreeView->selectionModel()->setCurrentIndex(m_version->index(newRow), QItemSelectionModel::ClearAndSelect); + const int newRow = 0; + m_version->move(row, VersionFinal::MoveUp); + // ui->libraryTreeView->selectionModel()->setCurrentIndex(m_version->index(newRow), + // QItemSelectionModel::ClearAndSelect); } catch (MMCError &e) { @@ -210,8 +233,10 @@ void InstanceEditDialog::on_moveLibraryDownBtn_clicked() try { const int row = ui->libraryTreeView->selectionModel()->selectedRows().first().row(); - const int newRow = 0;m_version->move(row, VersionFinal::MoveDown); - //ui->libraryTreeView->selectionModel()->setCurrentIndex(m_version->index(newRow), QItemSelectionModel::ClearAndSelect); + const int newRow = 0; + m_version->move(row, VersionFinal::MoveDown); + // ui->libraryTreeView->selectionModel()->setCurrentIndex(m_version->index(newRow), + // QItemSelectionModel::ClearAndSelect); } catch (MMCError &e) { @@ -221,7 +246,8 @@ void InstanceEditDialog::on_moveLibraryDownBtn_clicked() void InstanceEditDialog::on_changeMCVersionBtn_clicked() { - VersionSelectDialog vselect(m_inst->versionList().get(), tr("Change Minecraft version"), this); + VersionSelectDialog vselect(m_inst->versionList().get(), tr("Change Minecraft version"), + this); if (!vselect.exec() || !vselect.selectedVersion()) return; @@ -266,8 +292,9 @@ void InstanceEditDialog::on_forgeBtn_clicked() // FIXME: use actual model, not reloading. Move logic to model. if (m_version->hasFtbPack()) { - if (QMessageBox::question(this, tr("Revert?"), - tr("This action will remove the FTB pack version patch. Continue?")) != + if (QMessageBox::question( + this, tr("Revert?"), + tr("This action will remove the FTB pack version patch. Continue?")) != QMessageBox::Yes) { return; @@ -293,7 +320,8 @@ void InstanceEditDialog::on_forgeBtn_clicked() if (vselect.exec() && vselect.selectedVersion()) { ProgressDialog dialog(this); - dialog.exec(ForgeInstaller().createInstallTask(m_inst, vselect.selectedVersion(), this)); + dialog.exec( + ForgeInstaller().createInstallTask(m_inst, vselect.selectedVersion(), this)); } } @@ -301,8 +329,9 @@ void InstanceEditDialog::on_liteloaderBtn_clicked() { if (m_version->hasFtbPack()) { - if (QMessageBox::question(this, tr("Revert?"), - tr("This action will remove the FTB pack version patch. Continue?")) != + if (QMessageBox::question( + this, tr("Revert?"), + tr("This action will remove the FTB pack version patch. Continue?")) != QMessageBox::Yes) { return; @@ -329,7 +358,8 @@ void InstanceEditDialog::on_liteloaderBtn_clicked() if (vselect.exec() && vselect.selectedVersion()) { ProgressDialog dialog(this); - dialog.exec(LiteLoaderInstaller().createInstallTask(m_inst, vselect.selectedVersion(), this)); + dialog.exec( + LiteLoaderInstaller().createInstallTask(m_inst, vselect.selectedVersion(), this)); } } @@ -497,8 +527,7 @@ void InstanceEditDialog::loaderCurrent(QModelIndex current, QModelIndex previous ui->frame->updateWithMod(m); } -void InstanceEditDialog::versionCurrent(const QModelIndex ¤t, - const QModelIndex &previous) +void InstanceEditDialog::versionCurrent(const QModelIndex ¤t, const QModelIndex &previous) { if (!current.isValid()) { diff --git a/gui/dialogs/InstanceEditDialog.h b/gui/dialogs/InstanceEditDialog.h index d601074ac..e99899be3 100644 --- a/gui/dialogs/InstanceEditDialog.h +++ b/gui/dialogs/InstanceEditDialog.h @@ -44,6 +44,7 @@ slots: void on_resetLibraryOrderBtn_clicked(); void on_moveLibraryUpBtn_clicked(); void on_moveLibraryDownBtn_clicked(); + void on_jarmodBtn_clicked(); // loader mod tab void on_addModBtn_clicked(); diff --git a/logic/OneSixInstance.cpp b/logic/OneSixInstance.cpp index 574dfc69c..fc53bd390 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 b66b97689..21cdbacc0 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 8c30e38d8..b561606b5 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 bbbd71e11..4753ce059 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 d19c28775..cff708213 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 fc06e6144..6097840b9 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);