diff options
28 files changed, 393 insertions, 128 deletions
diff --git a/depends/pack200/anti200.cpp b/depends/pack200/anti200.cpp index 3dfdb5dc..1e1ec0c8 100644 --- a/depends/pack200/anti200.cpp +++ b/depends/pack200/anti200.cpp @@ -8,21 +8,36 @@ int main(int argc, char **argv) { - if (argc == 3) + if (argc != 3) { - try - { - unpack_200(argv[1], argv[2]); - } - catch (std::runtime_error &e) - { - std::cerr << "Bad things happened: " << e.what() << std::endl; - return EXIT_FAILURE; - } - return EXIT_SUCCESS; - } - else std::cerr << "Simple pack200 unpacker!" << std::endl << "Run like this:" << std::endl << " " << argv[0] << " input.jar.lzma output.jar" << std::endl; - return EXIT_FAILURE; + return EXIT_FAILURE; + } + + FILE *input = fopen(argv[1], "rb"); + FILE *output = fopen(argv[2], "wb"); + if (!input) + { + std::cerr << "Can't open input file"; + return EXIT_FAILURE; + } + if (!output) + { + fclose(output); + std::cerr << "Can't open output file"; + return EXIT_FAILURE; + } + try + { + unpack_200(input, output); + } + catch (std::runtime_error &e) + { + std::cerr << "Bad things happened: " << e.what() << std::endl; + fclose(input); + fclose(output); + return EXIT_FAILURE; + } + return EXIT_SUCCESS; } diff --git a/depends/pack200/include/unpack200.h b/depends/pack200/include/unpack200.h index bcee8009..f9239488 100644 --- a/depends/pack200/include/unpack200.h +++ b/depends/pack200/include/unpack200.h @@ -34,4 +34,4 @@ * @return void * @throw std::runtime_error for any error encountered */ -void unpack_200(std::string input_path, std::string output_path); +void unpack_200(FILE * input, FILE * output); diff --git a/depends/pack200/src/unpack200.cpp b/depends/pack200/src/unpack200.cpp index 0a9d2714..22b7f3b0 100644 --- a/depends/pack200/src/unpack200.cpp +++ b/depends/pack200/src/unpack200.cpp @@ -94,20 +94,9 @@ static int read_magic(unpacker *u, char peek[], int peeklen) return magic; } -void unpack_200(std::string input_path, std::string output_path) +void unpack_200(FILE *input, FILE *output) { unpacker u; - FILE *input = fopen(input_path.c_str(), "rb"); - if (!input) - { - throw std::runtime_error("Can't open input file" + input_path); - } - FILE *output = fopen(output_path.c_str(), "wb"); - if (!output) - { - fclose(output); - throw std::runtime_error("Can't open output file" + output_path); - } u.init(read_input_via_stdio); // initialize jar output diff --git a/gui/MainWindow.cpp b/gui/MainWindow.cpp index a2a2d885..4fb4489f 100644 --- a/gui/MainWindow.cpp +++ b/gui/MainWindow.cpp @@ -462,7 +462,7 @@ void MainWindow::downloadUpdates(QString repo, int versionId, bool installOnExit if (installOnExit) MMC->setUpdateOnExit(updateTask.updateFilesDir()); else - MMC->installUpdates(updateTask.updateFilesDir()); + MMC->installUpdates(updateTask.updateFilesDir(), true); } } @@ -865,6 +865,8 @@ void MainWindow::doLaunch() if (!account.get()) return; + QString failReason = tr("Your account is currently not logged in. Please enter " + "your password to log in again."); // do the login. if the account has an access token, try to refresh it first. if (account->accountStatus() != NotVerified) { @@ -879,13 +881,28 @@ void MainWindow::doLaunch() { updateInstance(m_selectedInstance, account); } - // revert from online to verified. + else + { + if (!task->successful()) + { + failReason = task->failReason(); + } + if (loginWithPassword(account, failReason)) + updateInstance(m_selectedInstance, account); + } + // in any case, revert from online to verified. + account->downgrade(); + } + else + { + if (loginWithPassword(account, failReason)) + { + updateInstance(m_selectedInstance, account); + account->downgrade(); + } + // in any case, revert from online to verified. account->downgrade(); - return; } - if (loginWithPassword(account, tr("Your account is currently not logged in. Please enter " - "your password to log in again."))) - updateInstance(m_selectedInstance, account); } bool MainWindow::loginWithPassword(MojangAccountPtr account, const QString &errorMsg) diff --git a/gui/dialogs/AccountListDialog.cpp b/gui/dialogs/AccountListDialog.cpp index 242590fb..1712e352 100644 --- a/gui/dialogs/AccountListDialog.cpp +++ b/gui/dialogs/AccountListDialog.cpp @@ -26,7 +26,9 @@ #include <gui/dialogs/EditAccountDialog.h> #include <gui/dialogs/ProgressDialog.h> #include <gui/dialogs/AccountSelectDialog.h> +#include "CustomMessageBox.h" #include <logic/tasks/Task.h> +#include <logic/auth/YggdrasilTask.h> #include <MultiMC.h> @@ -147,5 +149,12 @@ void AccountListDialog::addAccount(const QString& errMsg) job->start(); } + else + { + auto reason = task->failReason(); + auto dlg = CustomMessageBox::selectable(this, tr("Login error."), reason, QMessageBox::Critical); + dlg->exec(); + delete dlg; + } } } diff --git a/gui/dialogs/EditAccountDialog.cpp b/gui/dialogs/EditAccountDialog.cpp index dd3f0523..a1bd5591 100644 --- a/gui/dialogs/EditAccountDialog.cpp +++ b/gui/dialogs/EditAccountDialog.cpp @@ -15,6 +15,8 @@ #include "EditAccountDialog.h" #include "ui_EditAccountDialog.h" +#include <QDesktopServices> +#include <QUrl> EditAccountDialog::EditAccountDialog(const QString &text, QWidget *parent, int flags) : QDialog(parent), ui(new Ui::EditAccountDialog) @@ -33,6 +35,11 @@ EditAccountDialog::~EditAccountDialog() delete ui; } +void EditAccountDialog::on_label_linkActivated(const QString &link) +{ + QDesktopServices::openUrl(QUrl(link)); +} + QString EditAccountDialog::username() const { return ui->userTextBox->text(); diff --git a/gui/dialogs/EditAccountDialog.h b/gui/dialogs/EditAccountDialog.h index be3a88d8..83f25124 100644 --- a/gui/dialogs/EditAccountDialog.h +++ b/gui/dialogs/EditAccountDialog.h @@ -52,6 +52,9 @@ public: PasswordField, }; +private slots: + void on_label_linkActivated(const QString &link); + private: Ui::EditAccountDialog *ui; }; diff --git a/gui/dialogs/EditAccountDialog.ui b/gui/dialogs/EditAccountDialog.ui index 1a8f9dba..5f727bd4 100644 --- a/gui/dialogs/EditAccountDialog.ui +++ b/gui/dialogs/EditAccountDialog.ui @@ -19,6 +19,12 @@ <property name="text"> <string>Message label placeholder.</string> </property> + <property name="textFormat"> + <enum>Qt::RichText</enum> + </property> + <property name="textInteractionFlags"> + <set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set> + </property> </widget> </item> <item> diff --git a/logic/JavaChecker.cpp b/logic/JavaChecker.cpp index 2b94fbb6..113974ff 100644 --- a/logic/JavaChecker.cpp +++ b/logic/JavaChecker.cpp @@ -99,6 +99,7 @@ void JavaChecker::error(QProcess::ProcessError err) if(err == QProcess::FailedToStart) { killTimer.stop(); + checkerJar.remove(); JavaCheckResult result; { @@ -116,6 +117,5 @@ void JavaChecker::timeout() if(process) { process->kill(); - process.reset(); } } diff --git a/logic/LegacyUpdate.cpp b/logic/LegacyUpdate.cpp index e71b270e..fb9dcf2b 100644 --- a/logic/LegacyUpdate.cpp +++ b/logic/LegacyUpdate.cpp @@ -76,7 +76,7 @@ void LegacyUpdate::lwjglStart() return; } - setStatus("Downloading new LWJGL."); + setStatus(tr("Downloading new LWJGL...")); auto version = list->getVersion(lwjglVersion); if (!version) { @@ -144,7 +144,7 @@ void LegacyUpdate::lwjglFinished(QNetworkReply *reply) saveMe.open(QIODevice::WriteOnly); saveMe.write(m_reply->readAll()); saveMe.close(); - setStatus("Installing new LWJGL..."); + setStatus(tr("Installing new LWJGL...")); extractLwjgl(); jarStart(); } @@ -220,7 +220,7 @@ void LegacyUpdate::extractLwjgl() // Now if destFileName is still empty, go to the next file. if (!destFileName.isEmpty()) { - setStatus("Installing new LWJGL - Extracting " + name); + setStatus(tr("Installing new LWJGL - extracting ") + name + "..."); QFile output(destFileName); output.open(QIODevice::WriteOnly); output.write(file.readAll()); // FIXME: wste of memory!? @@ -250,7 +250,7 @@ void LegacyUpdate::jarStart() return; } - setStatus("Checking for jar updates..."); + setStatus(tr("Checking for jar updates...")); // Make directories QDir binDir(inst->binDir()); if (!binDir.exists() && !binDir.mkpath(".")) @@ -260,7 +260,7 @@ void LegacyUpdate::jarStart() } // Build a list of URLs that will need to be downloaded. - setStatus("Downloading new minecraft.jar"); + setStatus(tr("Downloading new minecraft.jar ...")); QString version_id = inst->intendedVersionId(); QString localPath = version_id + "/" + version_id + ".jar"; @@ -294,7 +294,7 @@ void LegacyUpdate::jarFailed() bool LegacyUpdate::MergeZipFiles(QuaZip *into, QFileInfo from, QSet<QString> &contained, MetainfAction metainf) { - setStatus("Installing mods - Adding " + from.fileName()); + setStatus(tr("Installing mods: Adding ") + from.fileName() + " ..."); QuaZip modZip(from.filePath()); modZip.open(QuaZip::mdUnzip); @@ -380,7 +380,7 @@ void LegacyUpdate::ModTheJar() return; } - setStatus("Installing mods - backing up minecraft.jar..."); + setStatus(tr("Installing mods: Backing up minecraft.jar ...")); if (!baseJar.exists() && !QFile::copy(runnableJar.filePath(), baseJar.filePath())) { emitFailed("It seems both the active and base jar are gone. A fresh base jar will " @@ -405,7 +405,7 @@ void LegacyUpdate::ModTheJar() } // TaskStep(); // STEP 1 - setStatus("Installing mods - Opening minecraft.jar"); + setStatus(tr("Installing mods: Opening minecraft.jar ...")); QuaZip zipOut(runnableJar.filePath()); if (!zipOut.open(QuaZip::mdCreate)) @@ -419,7 +419,7 @@ void LegacyUpdate::ModTheJar() QSet<QString> addedFiles; // Modify the jar - setStatus("Installing mods - Adding mod files..."); + setStatus(tr("Installing mods: Adding mod files...")); for (int i = modList->size() - 1; i >= 0; i--) { auto &mod = modList->operator[](i); diff --git a/logic/OneSixUpdate.cpp b/logic/OneSixUpdate.cpp index 696eeff0..4d93477a 100644 --- a/logic/OneSixUpdate.cpp +++ b/logic/OneSixUpdate.cpp @@ -57,7 +57,7 @@ void OneSixUpdate::executeTask() /* * FIXME: in offline mode, do not proceed! */ - setStatus("Testing the Java installation."); + setStatus(tr("Testing the Java installation...")); QString java_path = m_inst->settings().get("JavaPath").toString(); checker.reset(new JavaChecker()); @@ -89,7 +89,7 @@ void OneSixUpdate::executeTask() void OneSixUpdate::checkJavaOnline() { - setStatus("Testing the Java installation."); + setStatus(tr("Testing the Java installation...")); QString java_path = m_inst->settings().get("JavaPath").toString(); checker.reset(new JavaChecker()); @@ -128,7 +128,7 @@ void OneSixUpdate::checkFinishedOffline(JavaCheckResult result) void OneSixUpdate::versionFileStart() { QLOG_INFO() << m_inst->name() << ": getting version file."; - setStatus("Getting the version files from Mojang."); + setStatus(tr("Getting the version files from Mojang...")); QString urlstr = "http://" + URLConstants::AWS_DOWNLOAD_VERSIONS + targetVersion->descriptor() + "/" + targetVersion->descriptor() + ".json"; auto job = new NetJob("Version index"); @@ -196,7 +196,7 @@ void OneSixUpdate::versionFileFailed() void OneSixUpdate::assetIndexStart() { - setStatus("Updating asset index."); + setStatus(tr("Updating assets index...")); OneSixInstance *inst = (OneSixInstance *)m_inst; std::shared_ptr<OneSixVersion> version = inst->getFullVersion(); QString assetName = version->assets; @@ -247,7 +247,7 @@ void OneSixUpdate::assetIndexFinished() } if(dls.size()) { - setStatus("Getting the assets files from Mojang..."); + setStatus(tr("Getting the assets files from Mojang...")); auto job = new NetJob("Assets for " + inst->name()); for(auto dl: dls) job->addNetAction(dl); @@ -281,7 +281,7 @@ void OneSixUpdate::assetsFailed() void OneSixUpdate::jarlibStart() { - setStatus("Getting the library files from Mojang."); + setStatus(tr("Getting the library files from Mojang...")); QLOG_INFO() << m_inst->name() << ": downloading libraries"; OneSixInstance *inst = (OneSixInstance *)m_inst; bool successful = inst->reloadFullVersion(); @@ -369,7 +369,7 @@ void OneSixUpdate::jarlibFailed() void OneSixUpdate::prepareForLaunch() { - setStatus("Preparing for launch."); + setStatus(tr("Preparing for launch...")); QLOG_INFO() << m_inst->name() << ": preparing for launch"; auto onesix_inst = (OneSixInstance *)m_inst; diff --git a/logic/auth/MojangAccount.cpp b/logic/auth/MojangAccount.cpp index bc6af98f..a462eda5 100644 --- a/logic/auth/MojangAccount.cpp +++ b/logic/auth/MojangAccount.cpp @@ -32,7 +32,8 @@ MojangAccountPtr MojangAccount::loadFromJson(const QJsonObject &object) // The JSON object must at least have a username for it to be valid. if (!object.value("username").isString()) { - QLOG_ERROR() << "Can't load Mojang account info from JSON object. Username field is missing or of the wrong type."; + QLOG_ERROR() << "Can't load Mojang account info from JSON object. Username field is " + "missing or of the wrong type."; return nullptr; } @@ -43,7 +44,8 @@ MojangAccountPtr MojangAccount::loadFromJson(const QJsonObject &object) QJsonArray profileArray = object.value("profiles").toArray(); if (profileArray.size() < 1) { - QLOG_ERROR() << "Can't load Mojang account with username \"" << username << "\". No profiles found."; + QLOG_ERROR() << "Can't load Mojang account with username \"" << username + << "\". No profiles found."; return nullptr; } @@ -63,7 +65,7 @@ MojangAccountPtr MojangAccount::loadFromJson(const QJsonObject &object) } MojangAccountPtr account(new MojangAccount()); - if(object.value("user").isObject()) + if (object.value("user").isObject()) { User u; QJsonObject userStructure = object.value("user").toObject(); @@ -92,7 +94,7 @@ MojangAccountPtr MojangAccount::loadFromJson(const QJsonObject &object) return account; } -MojangAccountPtr MojangAccount::createFromUsername(const QString& username) +MojangAccountPtr MojangAccount::createFromUsername(const QString &username) { MojangAccountPtr account(new MojangAccount()); account->m_clientToken = QUuid::createUuid().toString().remove(QRegExp("[{}-]")); @@ -152,27 +154,27 @@ bool MojangAccount::setCurrentProfile(const QString &profileId) return false; } -const AccountProfile* MojangAccount::currentProfile() const +const AccountProfile *MojangAccount::currentProfile() const { - if(m_currentProfile == -1) + if (m_currentProfile == -1) return nullptr; return &m_profiles[m_currentProfile]; } AccountStatus MojangAccount::accountStatus() const { - if(m_accessToken.isEmpty()) + if (m_accessToken.isEmpty()) return NotVerified; - if(!m_online) + if (!m_online) return Verified; return Online; } -std::shared_ptr<Task> MojangAccount::login(QString password) +std::shared_ptr<YggdrasilTask> MojangAccount::login(QString password) { - if(m_currentTask) + if (m_currentTask) return m_currentTask; - if(password.isEmpty()) + if (password.isEmpty()) { m_currentTask.reset(new RefreshTask(this)); } @@ -196,7 +198,7 @@ void MojangAccount::authFailed(QString reason) { // This is emitted when the yggdrasil tasks time out or are cancelled. // -> we treat the error as no-op - if(reason != "Yggdrasil task cancelled.") + if (reason != "Yggdrasil task cancelled.") { m_online = false; m_accessToken = QString(); diff --git a/logic/auth/MojangAccount.h b/logic/auth/MojangAccount.h index 325aa826..dd5d54ae 100644 --- a/logic/auth/MojangAccount.h +++ b/logic/auth/MojangAccount.h @@ -95,7 +95,7 @@ public: /* manipulation */ * Attempt to login. Empty password means we use the token. * If the attempt fails because we already are performing some task, it returns false. */ - std::shared_ptr<Task> login(QString password = QString()); + std::shared_ptr<YggdrasilTask> login(QString password = QString()); void downgrade() { diff --git a/logic/auth/YggdrasilTask.cpp b/logic/auth/YggdrasilTask.cpp index 088e1fc0..3ba53bd7 100644 --- a/logic/auth/YggdrasilTask.cpp +++ b/logic/auth/YggdrasilTask.cpp @@ -48,6 +48,7 @@ void YggdrasilTask::executeTask() connect(m_netReply, &QNetworkReply::finished, this, &YggdrasilTask::processReply); connect(m_netReply, &QNetworkReply::uploadProgress, this, &YggdrasilTask::refreshTimers); connect(m_netReply, &QNetworkReply::downloadProgress, this, &YggdrasilTask::refreshTimers); + connect(m_netReply, &QNetworkReply::sslErrors, this, &YggdrasilTask::sslErrors); timeout_keeper.setSingleShot(true); timeout_keeper.start(timeout_max); counter.setSingleShot(false); @@ -75,10 +76,33 @@ void YggdrasilTask::abort() m_netReply->abort(); } +void YggdrasilTask::sslErrors(QList<QSslError> errors) +{ + int i = 1; + for(auto error: errors) + { + QLOG_ERROR() << "LOGIN SSL Error #" << i << " : " << error.errorString(); + auto cert = error.certificate(); + QLOG_ERROR() << "Certificate in question:\n" << cert.toText(); + i++; + } +} + void YggdrasilTask::processReply() { setStatus(getStateMessage(STATE_PROCESSING_RESPONSE)); + if (m_netReply->error() == QNetworkReply::SslHandshakeFailedError) + { + emitFailed(tr("<b>SSL Handshake failed.</b><br/>There might be a few causes for it:<br/>" + "<ul>" + "<li>You use Windows XP and need to <a href=\"http://www.microsoft.com/en-us/download/details.aspx?id=38918\">update your root certificates</a></li>" + "<li>Some device on your network is interfering with SSL traffic. In that case, you have bigger worries than Minecraft not starting.</li>" + "<li>Possibly something else. Check the MultiMC log file for details</li>" + "</ul>")); + return; + } + // any network errors lead to offline mode right now if (m_netReply->error() >= QNetworkReply::ConnectionRefusedError && m_netReply->error() <= QNetworkReply::UnknownNetworkError) @@ -172,10 +196,10 @@ QString YggdrasilTask::getStateMessage(const YggdrasilTask::State state) const switch (state) { case STATE_SENDING_REQUEST: - return tr("Sending request to auth servers."); + return tr("Sending request to auth servers..."); case STATE_PROCESSING_RESPONSE: - return tr("Processing response from servers."); + return tr("Processing response from servers..."); default: - return tr("Processing. Please wait."); + return tr("Processing. Please wait..."); } } diff --git a/logic/auth/YggdrasilTask.h b/logic/auth/YggdrasilTask.h index 1f81a2d0..85f5a1e1 100644 --- a/logic/auth/YggdrasilTask.h +++ b/logic/auth/YggdrasilTask.h @@ -20,6 +20,7 @@ #include <QString> #include <QJsonObject> #include <QTimer> +#include <qsslerror.h> #include "logic/auth/MojangAccount.h" @@ -99,6 +100,7 @@ slots: void processReply(); void refreshTimers(qint64, qint64); void heartbeat(); + void sslErrors(QList<QSslError>); public slots: diff --git a/logic/auth/flows/AuthenticateTask.cpp b/logic/auth/flows/AuthenticateTask.cpp index f60be35d..6548c4e9 100644 --- a/logic/auth/flows/AuthenticateTask.cpp +++ b/logic/auth/flows/AuthenticateTask.cpp @@ -194,9 +194,9 @@ QString AuthenticateTask::getStateMessage(const YggdrasilTask::State state) cons switch (state) { case STATE_SENDING_REQUEST: - return tr("Authenticating: Sending request."); + return tr("Authenticating: Sending request..."); case STATE_PROCESSING_RESPONSE: - return tr("Authenticating: Processing response."); + return tr("Authenticating: Processing response..."); default: return YggdrasilTask::getStateMessage(state); } diff --git a/logic/auth/flows/RefreshTask.cpp b/logic/auth/flows/RefreshTask.cpp index 5f68ccc7..f63c736e 100644 --- a/logic/auth/flows/RefreshTask.cpp +++ b/logic/auth/flows/RefreshTask.cpp @@ -145,9 +145,9 @@ QString RefreshTask::getStateMessage(const YggdrasilTask::State state) const switch (state) { case STATE_SENDING_REQUEST: - return tr("Refreshing login token."); + return tr("Refreshing login token..."); case STATE_PROCESSING_RESPONSE: - return tr("Refreshing login token: Processing response."); + return tr("Refreshing login token: Processing response..."); default: return YggdrasilTask::getStateMessage(state); } diff --git a/logic/auth/flows/ValidateTask.cpp b/logic/auth/flows/ValidateTask.cpp index 84d5e703..4f7323fd 100644 --- a/logic/auth/flows/ValidateTask.cpp +++ b/logic/auth/flows/ValidateTask.cpp @@ -55,9 +55,9 @@ QString ValidateTask::getStateMessage(const YggdrasilTask::State state) const switch (state) { case STATE_SENDING_REQUEST: - return tr("Validating Access Token: Sending request."); + return tr("Validating access token: Sending request..."); case STATE_PROCESSING_RESPONSE: - return tr("Validating Access Token: Processing response."); + return tr("Validating access token: Processing response..."); default: return YggdrasilTask::getStateMessage(state); } diff --git a/logic/lists/ForgeVersionList.cpp b/logic/lists/ForgeVersionList.cpp index d6d353da..56eca744 100644 --- a/logic/lists/ForgeVersionList.cpp +++ b/logic/lists/ForgeVersionList.cpp @@ -15,6 +15,7 @@ #include "ForgeVersionList.h" #include <logic/net/NetJob.h> +#include <logic/net/URLConstants.h> #include "MultiMC.h" #include <QtNetwork> @@ -23,8 +24,6 @@ #include "logger/QsLog.h" -#define JSON_URL "http://files.minecraftforge.net/minecraftforge/json" - ForgeVersionList::ForgeVersionList(QObject *parent) : BaseVersionList(parent) { } @@ -159,45 +158,43 @@ ForgeListLoadTask::ForgeListLoadTask(ForgeVersionList *vlist) : Task() void ForgeListLoadTask::executeTask() { - setStatus(tr("Fetching Forge version list")); + setStatus(tr("Fetching Forge version lists...")); auto job = new NetJob("Version index"); // we do not care if the version is stale or not. auto forgeListEntry = MMC->metacache()->resolveEntry("minecraftforge", "list.json"); + auto gradleForgeListEntry = MMC->metacache()->resolveEntry("minecraftforge", "json"); // verify by poking the server. forgeListEntry->stale = true; + gradleForgeListEntry->stale = true; + + job->addNetAction(listDownload = CacheDownload::make(QUrl(URLConstants::FORGE_LEGACY_URL), + forgeListEntry)); + job->addNetAction(gradleListDownload = CacheDownload::make( + QUrl(URLConstants::FORGE_GRADLE_URL), gradleForgeListEntry)); + + connect(listDownload.get(), SIGNAL(failed(int)), SLOT(listFailed())); + connect(gradleListDownload.get(), SIGNAL(failed(int)), SLOT(gradleListFailed())); - job->addNetAction(CacheDownload::make(QUrl(JSON_URL), forgeListEntry)); listJob.reset(job); - connect(listJob.get(), SIGNAL(succeeded()), SLOT(list_downloaded())); - connect(listJob.get(), SIGNAL(failed()), SLOT(list_failed())); + connect(listJob.get(), SIGNAL(succeeded()), SLOT(listDownloaded())); connect(listJob.get(), SIGNAL(progress(qint64, qint64)), SIGNAL(progress(qint64, qint64))); listJob->start(); } -void ForgeListLoadTask::list_failed() -{ - auto DlJob = listJob->first(); - auto reply = DlJob->m_reply; - if (reply) - { - QLOG_ERROR() << "Getting forge version list failed: " << reply->errorString(); - } - else - QLOG_ERROR() << "Getting forge version list failed for reasons unknown."; -} - -void ForgeListLoadTask::list_downloaded() +bool ForgeListLoadTask::parseForgeList(QList<BaseVersionPtr> &out) { QByteArray data; { - auto DlJob = listJob->first(); - auto filename = std::dynamic_pointer_cast<CacheDownload>(DlJob)->m_target_path; + auto dlJob = listDownload; + auto filename = std::dynamic_pointer_cast<CacheDownload>(dlJob)->m_target_path; QFile listFile(filename); if (!listFile.open(QIODevice::ReadOnly)) - return; + { + return false; + } data = listFile.readAll(); - DlJob.reset(); + dlJob.reset(); } QJsonParseError jsonError; @@ -206,13 +203,13 @@ void ForgeListLoadTask::list_downloaded() if (jsonError.error != QJsonParseError::NoError) { emitFailed("Error parsing version list JSON:" + jsonError.errorString()); - return; + return false; } if (!jsonDoc.isObject()) { - emitFailed("Error parsing version list JSON: jsonDoc is not an object"); - return; + emitFailed("Error parsing version list JSON: JSON root is not an object"); + return false; } QJsonObject root = jsonDoc.object(); @@ -222,11 +219,10 @@ void ForgeListLoadTask::list_downloaded() { emitFailed( "Error parsing version list JSON: version list object is missing 'builds' array"); - return; + return false; } QJsonArray builds = root.value("builds").toArray(); - QList<BaseVersionPtr> tempList; for (int i = 0; i < builds.count(); i++) { // Load the version info. @@ -247,7 +243,9 @@ void ForgeListLoadTask::list_downloaded() for (int j = 0; j < files.count(); j++) { if (!files[j].isObject()) + { continue; + } QJsonObject file = files[j].toObject(); buildtype = file.value("buildtype").toString(); if ((buildtype == "client" || buildtype == "universal") && !valid) @@ -263,7 +261,9 @@ void ForgeListLoadTask::list_downloaded() { QString ext = file.value("ext").toString(); if (ext.isEmpty()) + { continue; + } changelog_url = file.value("url").toString(); } else if (buildtype == "installer") @@ -283,15 +283,161 @@ void ForgeListLoadTask::list_downloaded() fVersion->jobbuildver = jobbuildver; fVersion->mcver = mcver; if (installer_filename.isEmpty()) + { fVersion->filename = filename; + } else + { fVersion->filename = installer_filename; + } fVersion->m_buildnr = build_nr; - tempList.append(fVersion); |
