diff --git a/launcher/include/squareboot.h b/launcher/include/squareboot.h index 2d464de..f2dbb26 100644 --- a/launcher/include/squareboot.h +++ b/launcher/include/squareboot.h @@ -3,6 +3,8 @@ #pragma once +#include + #include "patcher.h" class SquareLauncher; @@ -15,9 +17,9 @@ class SquareBoot : public QObject public: SquareBoot(LauncherCore &window, SquareLauncher &launcher, QObject *parent = nullptr); - Q_INVOKABLE void checkGateStatus(LoginInformation *info); + QCoro::Task<> checkGateStatus(LoginInformation *info); - void bootCheck(const LoginInformation &info); + QCoro::Task<> bootCheck(const LoginInformation &info); private: Patcher *patcher = nullptr; diff --git a/launcher/include/squarelauncher.h b/launcher/include/squarelauncher.h index 4dc757b..3981c94 100644 --- a/launcher/include/squarelauncher.h +++ b/launcher/include/squarelauncher.h @@ -3,6 +3,8 @@ #pragma once +#include + #include "launchercore.h" #include "patcher.h" @@ -12,18 +14,19 @@ class SquareLauncher : public QObject public: explicit SquareLauncher(LauncherCore &window, QObject *parent = nullptr); - void getStored(const LoginInformation &info); + using StoredInfo = std::pair; + QCoro::Task> getStored(const LoginInformation &info); - void login(const LoginInformation &info, const QUrl &referer); + QCoro::Task<> login(const LoginInformation &info); - void registerSession(const LoginInformation &info); + QCoro::Task<> registerSession(const LoginInformation &info); private: QString getBootHash(const LoginInformation &info); Patcher *patcher = nullptr; - QString stored, SID, username; + QString SID, username; LoginAuth auth; LauncherCore &window; diff --git a/launcher/src/squareboot.cpp b/launcher/src/squareboot.cpp index b2ea743..9a76963 100644 --- a/launcher/src/squareboot.cpp +++ b/launcher/src/squareboot.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include "account.h" #include "squarelauncher.h" @@ -21,7 +22,7 @@ SquareBoot::SquareBoot(LauncherCore &window, SquareLauncher &launcher, QObject * { } -void SquareBoot::bootCheck(const LoginInformation &info) +QCoro::Task<> SquareBoot::bootCheck(const LoginInformation &info) { Q_EMIT window.stageChanged(i18n("Checking for launcher updates...")); qDebug() << "Performing boot check..."; @@ -30,7 +31,7 @@ void SquareBoot::bootCheck(const LoginInformation &info) connect(patcher, &Patcher::done, [this, &info] { info.profile->readGameVersion(); - launcher.getStored(info); + launcher.login(info); }); QUrlQuery query; @@ -52,14 +53,14 @@ void SquareBoot::bootCheck(const LoginInformation &info) request.setRawHeader("Host", QStringLiteral("patch-bootver.%1").arg(window.squareEnixServer()).toUtf8()); auto reply = window.mgr->get(request); - connect(reply, &QNetworkReply::finished, [this, reply] { - const QString response = reply->readAll(); + co_await reply; - patcher->processPatchList(*window.mgr, response); - }); + const QString response = reply->readAll(); + + patcher->processPatchList(*window.mgr, response); } -void SquareBoot::checkGateStatus(LoginInformation *info) +QCoro::Task<> SquareBoot::checkGateStatus(LoginInformation *info) { Q_EMIT window.stageChanged(i18n("Checking gate...")); qDebug() << "Checking gate..."; @@ -76,15 +77,15 @@ void SquareBoot::checkGateStatus(LoginInformation *info) window.buildRequest(*info->profile, request); auto reply = window.mgr->get(request); - connect(reply, &QNetworkReply::finished, [this, reply, info] { - const QJsonDocument document = QJsonDocument::fromJson(reply->readAll()); + co_await reply; - const bool isGateOpen = !document.isEmpty() && document.object()["status"].toInt() != 0; + const QJsonDocument document = QJsonDocument::fromJson(reply->readAll()); - if (isGateOpen) { - bootCheck(*info); - } else { - Q_EMIT window.loginError(i18n("The login gate is closed, the game may be under maintenance.\n\n%1", reply->errorString())); - } - }); + const bool isGateOpen = !document.isEmpty() && document.object()["status"].toInt() != 0; + + if (isGateOpen) { + bootCheck(*info); + } else { + Q_EMIT window.loginError(i18n("The login gate is closed, the game may be under maintenance.\n\n%1", reply->errorString())); + } } diff --git a/launcher/src/squarelauncher.cpp b/launcher/src/squarelauncher.cpp index 25180c8..404bca1 100644 --- a/launcher/src/squarelauncher.cpp +++ b/launcher/src/squarelauncher.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include "account.h" #include "launchercore.h" @@ -31,7 +32,7 @@ QString getFileHash(const QString &file) return QString("%1/%2").arg(QString::number(f.size()), hash.result().toHex()); } -void SquareLauncher::getStored(const LoginInformation &info) +QCoro::Task> SquareLauncher::getStored(const LoginInformation &info) { Q_EMIT window.stageChanged(i18n("Logging in...")); @@ -62,39 +63,44 @@ void SquareLauncher::getStored(const LoginInformation &info) auto request = QNetworkRequest(url); window.buildRequest(*info.profile, request); - QNetworkReply *reply = window.mgr->get(request); + auto reply = window.mgr->get(request); + co_await reply; - connect(reply, &QNetworkReply::finished, [this, &info, reply, url] { - auto str = QString(reply->readAll()); + const auto str = QString(reply->readAll()); - // fetches Steam username - if (info.profile->account()->license() == Account::GameLicense::WindowsSteam) { - QRegularExpression re(R"lit(.*)""\/>)lit"); - QRegularExpressionMatch match = re.match(str); - - if (match.hasMatch()) { - username = match.captured(1); - } else { - Q_EMIT window.loginError(i18n("Could not get Steam username, have you attached your account?")); - } - } else { - username = info.username; - } - - QRegularExpression re(R"lit(\t<\s*input .* name="_STORED_" value="(?.*)">)lit"); + // fetches Steam username + if (info.profile->account()->license() == Account::GameLicense::WindowsSteam) { + QRegularExpression re(R"lit(.*)""\/>)lit"); QRegularExpressionMatch match = re.match(str); + if (match.hasMatch()) { - stored = match.captured(1); - login(info, url); + username = match.captured(1); } else { - Q_EMIT window.loginError( - i18n("Square Enix servers refused to confirm session information. The game may be under maintenance, try the official launcher.")); + Q_EMIT window.loginError(i18n("Could not get Steam username, have you attached your account?")); } - }); + } else { + username = info.username; + } + + QRegularExpression re(R"lit(\t<\s*input .* name="_STORED_" value="(?.*)">)lit"); + QRegularExpressionMatch match = re.match(str); + if (match.hasMatch()) { + co_return StoredInfo{match.captured(1), url}; + } else { + Q_EMIT window.loginError( + i18n("Square Enix servers refused to confirm session information. The game may be under maintenance, try the official launcher.")); + co_return {}; + } } -void SquareLauncher::login(const LoginInformation &info, const QUrl &referer) +QCoro::Task<> SquareLauncher::login(const LoginInformation &info) { + const auto storedResult = co_await getStored(info); + if (storedResult == std::nullopt) { + co_return; + } + const auto [stored, referer] = *storedResult; + QUrlQuery postData; postData.addQueryItem("_STORED_", stored); postData.addQueryItem("sqexid", info.username); @@ -113,47 +119,47 @@ void SquareLauncher::login(const LoginInformation &info, const QUrl &referer) request.setRawHeader("Cache-Control", "no-cache"); auto reply = window.mgr->post(request, postData.toString(QUrl::FullyEncoded).toUtf8()); - connect(reply, &QNetworkReply::finished, [this, &info, reply] { - auto str = QString(reply->readAll()); + co_await reply; - QRegularExpression re(R"lit(window.external.user\("login=auth,ok,(?.*)\);)lit"); - QRegularExpressionMatch match = re.match(str); - if (match.hasMatch()) { - const auto parts = match.captured(1).split(','); + auto str = QString(reply->readAll()); - const bool terms = parts[3] == "1"; - const bool playable = parts[9] == "1"; + QRegularExpression re(R"lit(window.external.user\("login=auth,ok,(?.*)\);)lit"); + QRegularExpressionMatch match = re.match(str); + if (match.hasMatch()) { + const auto parts = match.captured(1).split(','); - if (!playable) { - Q_EMIT window.loginError(i18n("Your account is unplayable. Check that you have the correct license, and a valid subscription.")); - return; - } + const bool terms = parts[3] == "1"; + const bool playable = parts[9] == "1"; - if (!terms) { - Q_EMIT window.loginError(i18n("Your account is unplayable. You need to accept the terms of service from the official launcher first.")); - return; - } - - SID = parts[1]; - auth.region = parts[5].toInt(); - auth.maxExpansion = parts[13].toInt(); - - registerSession(info); - } else { - QRegularExpression re(R"lit(window.external.user\("login=auth,ng,err,(?.*)\);)lit"); - QRegularExpressionMatch match = re.match(str); - - const auto parts = match.captured(1).split(','); - - // there's a stray quote at the end of the error string, so let's remove that - QString errorStr = match.captured(1).chopped(1); - - Q_EMIT window.loginError(errorStr); + if (!playable) { + Q_EMIT window.loginError(i18n("Your account is unplayable. Check that you have the correct license, and a valid subscription.")); + co_return; } - }); + + if (!terms) { + Q_EMIT window.loginError(i18n("Your account is unplayable. You need to accept the terms of service from the official launcher first.")); + co_return; + } + + SID = parts[1]; + auth.region = parts[5].toInt(); + auth.maxExpansion = parts[13].toInt(); + + registerSession(info); + } else { + QRegularExpression re(R"lit(window.external.user\("login=auth,ng,err,(?.*)\);)lit"); + QRegularExpressionMatch match = re.match(str); + + const auto parts = match.captured(1).split(','); + + // there's a stray quote at the end of the error string, so let's remove that + QString errorStr = match.captured(1).chopped(1); + + Q_EMIT window.loginError(errorStr); + } } -void SquareLauncher::registerSession(const LoginInformation &info) +QCoro::Task<> SquareLauncher::registerSession(const LoginInformation &info) { QUrl url; url.setScheme("https"); @@ -177,35 +183,35 @@ void SquareLauncher::registerSession(const LoginInformation &info) } auto reply = window.mgr->post(request, report.toUtf8()); - connect(reply, &QNetworkReply::finished, [this, &info, reply] { - if (reply->error() == QNetworkReply::NoError) { - if (reply->rawHeaderList().contains("X-Patch-Unique-Id")) { - QString body = reply->readAll(); + co_await reply; - patcher = new Patcher(window, info.profile->gamePath() + "/game", info.profile->gameData, this); - connect(patcher, &Patcher::done, [this, &info, reply] { - info.profile->readGameVersion(); + if (reply->error() == QNetworkReply::NoError) { + if (reply->rawHeaderList().contains("X-Patch-Unique-Id")) { + QString body = reply->readAll(); - auth.SID = reply->rawHeader("X-Patch-Unique-Id"); + patcher = new Patcher(window, info.profile->gamePath() + "/game", info.profile->gameData, this); + connect(patcher, &Patcher::done, [this, &info, reply] { + info.profile->readGameVersion(); - window.launchGame(*info.profile, auth); - }); + auth.SID = reply->rawHeader("X-Patch-Unique-Id"); - patcher->processPatchList(*window.mgr, body); - } else { - Q_EMIT window.loginError(i18n("Fatal error, request was successful but X-Patch-Unique-Id was not recieved.")); - } + window.launchGame(*info.profile, auth); + }); + + patcher->processPatchList(*window.mgr, body); } else { - if (reply->error() == QNetworkReply::SslHandshakeFailedError) { - Q_EMIT window.loginError( - i18n("SSL handshake error detected. If you are using OpenSUSE or Fedora, try running `update-crypto-policies --set LEGACY`.")); - } else if (reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt() == 405) { - Q_EMIT window.loginError(i18n("The game failed the anti-tamper check. Restore the game to the original state and try updating again.")); - } else { - Q_EMIT window.loginError(i18n("Unknown error when registering the session.")); - } + Q_EMIT window.loginError(i18n("Fatal error, request was successful but X-Patch-Unique-Id was not recieved.")); } - }); + } else { + if (reply->error() == QNetworkReply::SslHandshakeFailedError) { + Q_EMIT window.loginError( + i18n("SSL handshake error detected. If you are using OpenSUSE or Fedora, try running `update-crypto-policies --set LEGACY`.")); + } else if (reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt() == 405) { + Q_EMIT window.loginError(i18n("The game failed the anti-tamper check. Restore the game to the original state and try updating again.")); + } else { + Q_EMIT window.loginError(i18n("Unknown error when registering the session.")); + } + } } QString SquareLauncher::getBootHash(const LoginInformation &info)