/* Copyright 2013-2021 MultiMC Contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "InjectAuthlib.h" #include #include #include #include #include InjectAuthlib::InjectAuthlib(LaunchTask *parent, AuthlibInjectorPtr* injector, QString url) : LaunchStep(parent) { m_injector = injector; m_url = url; } void InjectAuthlib::executeTask() { if (m_aborted) { emitFailed(tr("Task aborted.")); return; } auto latestVersionInfo = QString("https://authlib-injector.yushi.moe/artifact/latest.json"); auto netJob = makeShared("Injector versions info download", APPLICATION->network()); MetaEntryPtr entry = APPLICATION->metacache()->resolveEntry("injectors", "version.json"); if (!m_offlineMode) { entry->setStale(true); auto task = Net::Download::makeCached(QUrl(latestVersionInfo), entry); netJob->addNetAction(task); jobPtr.reset(netJob); QObject::connect(netJob.get(), &NetJob::succeeded, this, &InjectAuthlib::onVersionDownloadSucceeded); QObject::connect(netJob.get(), &NetJob::failed, this, &InjectAuthlib::onDownloadFailed); jobPtr->start(); } else { onVersionDownloadSucceeded(); } } void InjectAuthlib::onVersionDownloadSucceeded() { QByteArray data; try { data = FS::read(QDir("injectors").absoluteFilePath("version.json")); } catch (const Exception &e) { qCritical() << "Translations Download Failed: index file not readable"; jobPtr.reset(); emitFailed("Error while parsing JSON response from InjectorEndpoint"); return; } QJsonParseError parse_error; QJsonDocument doc = QJsonDocument::fromJson(data, &parse_error); if (parse_error.error != QJsonParseError::NoError) { qCritical() << "Error while parsing JSON response from InjectorEndpoint at " << parse_error.offset << " reason: " << parse_error.errorString(); qCritical() << data; jobPtr.reset(); emitFailed("Error while parsing JSON response from InjectorEndpoint"); return; } if (!doc.isObject()) { qCritical() << "Error while parsing JSON response from InjectorEndpoint root is not object"; qCritical() << data; jobPtr.reset(); emitFailed("Error while parsing JSON response from InjectorEndpoint"); return; } QString downloadUrl; try { downloadUrl = Json::requireString(doc.object(), "download_url"); } catch (const JSONValidationError &e) { qCritical() << "Error while parsing JSON response from InjectorEndpoint download url is not string"; qCritical() << e.cause(); qCritical() << data; jobPtr.reset(); emitFailed("Error while parsing JSON response from InjectorEndpoint"); return; } QFileInfo fi(downloadUrl); m_versionName = fi.fileName(); qDebug() << "Authlib injector version:" << m_versionName; if (!m_offlineMode) { auto netJob = makeShared("Injector download", APPLICATION->network()); MetaEntryPtr entry = APPLICATION->metacache()->resolveEntry("injectors", m_versionName); entry->setStale(true); auto task = Net::Download::makeCached(QUrl(downloadUrl), entry); netJob->addNetAction(task); jobPtr.reset(netJob); QObject::connect(netJob.get(), &NetJob::succeeded, this, &InjectAuthlib::onDownloadSucceeded); QObject::connect(netJob.get(), &NetJob::failed, this, &InjectAuthlib::onDownloadFailed); jobPtr->start(); } else { onDownloadSucceeded(); } } void InjectAuthlib::onDownloadSucceeded() { QString injector = QString("%1=%2").arg(QDir("injectors").absoluteFilePath(m_versionName)).arg(m_url); qDebug() << "Injecting " << injector; auto inj = new AuthlibInjector(injector); m_injector->reset(inj); jobPtr.reset(); emitSucceeded(); } void InjectAuthlib::onDownloadFailed(QString reason) { jobPtr.reset(); emitFailed(reason); } void InjectAuthlib::proceed() { } bool InjectAuthlib::canAbort() const { if (jobPtr) { return jobPtr->canAbort(); } return true; } bool InjectAuthlib::abort() { m_aborted = true; if (jobPtr) { if (jobPtr->canAbort()) { return jobPtr->abort(); } } return true; }