aboutsummaryrefslogtreecommitdiff
path: root/launcher/minecraft/auth
diff options
context:
space:
mode:
Diffstat (limited to 'launcher/minecraft/auth')
-rw-r--r--launcher/minecraft/auth/AccountData.cpp207
-rw-r--r--launcher/minecraft/auth/AccountData.h23
-rw-r--r--launcher/minecraft/auth/AccountList.cpp428
-rw-r--r--launcher/minecraft/auth/AccountList.h54
-rw-r--r--launcher/minecraft/auth/AccountTask.cpp52
-rw-r--r--launcher/minecraft/auth/AccountTask.h43
-rw-r--r--launcher/minecraft/auth/AuthRequest.cpp53
-rw-r--r--launcher/minecraft/auth/AuthRequest.h39
-rw-r--r--launcher/minecraft/auth/AuthSession.cpp9
-rw-r--r--launcher/minecraft/auth/AuthSession.h10
-rw-r--r--launcher/minecraft/auth/AuthStep.cpp4
-rw-r--r--launcher/minecraft/auth/AuthStep.h20
-rw-r--r--launcher/minecraft/auth/MinecraftAccount.cpp144
-rw-r--r--launcher/minecraft/auth/MinecraftAccount.h118
-rw-r--r--launcher/minecraft/auth/Parsers.cpp192
-rw-r--r--launcher/minecraft/auth/Parsers.h27
-rw-r--r--launcher/minecraft/auth/Yggdrasil.cpp162
-rw-r--r--launcher/minecraft/auth/Yggdrasil.h38
-rw-r--r--launcher/minecraft/auth/flows/AuthFlow.cpp44
-rw-r--r--launcher/minecraft/auth/flows/AuthFlow.h29
-rw-r--r--launcher/minecraft/auth/flows/MSA.cpp19
-rw-r--r--launcher/minecraft/auth/flows/MSA.h20
-rw-r--r--launcher/minecraft/auth/flows/Mojang.cpp19
-rw-r--r--launcher/minecraft/auth/flows/Mojang.h23
-rw-r--r--launcher/minecraft/auth/flows/Offline.cpp12
-rw-r--r--launcher/minecraft/auth/flows/Offline.h20
-rw-r--r--launcher/minecraft/auth/steps/EntitlementsStep.cpp21
-rw-r--r--launcher/minecraft/auth/steps/EntitlementsStep.h9
-rw-r--r--launcher/minecraft/auth/steps/GetSkinStep.cpp24
-rw-r--r--launcher/minecraft/auth/steps/GetSkinStep.h7
-rw-r--r--launcher/minecraft/auth/steps/LauncherLoginStep.cpp44
-rw-r--r--launcher/minecraft/auth/steps/LauncherLoginStep.h7
-rw-r--r--launcher/minecraft/auth/steps/MSAStep.cpp25
-rw-r--r--launcher/minecraft/auth/steps/MSAStep.h18
-rw-r--r--launcher/minecraft/auth/steps/MigrationEligibilityStep.cpp26
-rw-r--r--launcher/minecraft/auth/steps/MigrationEligibilityStep.h7
-rw-r--r--launcher/minecraft/auth/steps/MinecraftProfileStep.cpp61
-rw-r--r--launcher/minecraft/auth/steps/MinecraftProfileStep.h7
-rw-r--r--launcher/minecraft/auth/steps/MinecraftProfileStepMojang.cpp63
-rw-r--r--launcher/minecraft/auth/steps/MinecraftProfileStepMojang.h7
-rw-r--r--launcher/minecraft/auth/steps/OfflineStep.cpp9
-rw-r--r--launcher/minecraft/auth/steps/OfflineStep.h4
-rw-r--r--launcher/minecraft/auth/steps/XboxAuthorizationStep.cpp132
-rw-r--r--launcher/minecraft/auth/steps/XboxAuthorizationStep.h19
-rw-r--r--launcher/minecraft/auth/steps/XboxProfileStep.cpp54
-rw-r--r--launcher/minecraft/auth/steps/XboxProfileStep.h7
-rw-r--r--launcher/minecraft/auth/steps/XboxUserStep.cpp41
-rw-r--r--launcher/minecraft/auth/steps/XboxUserStep.h7
-rw-r--r--launcher/minecraft/auth/steps/YggdrasilStep.cpp25
-rw-r--r--launcher/minecraft/auth/steps/YggdrasilStep.h10
50 files changed, 1096 insertions, 1347 deletions
diff --git a/launcher/minecraft/auth/AccountData.cpp b/launcher/minecraft/auth/AccountData.cpp
index 0b78cb0c..b621a68c 100644
--- a/launcher/minecraft/auth/AccountData.cpp
+++ b/launcher/minecraft/auth/AccountData.cpp
@@ -34,87 +34,90 @@
*/
#include "AccountData.h"
+#include <QDebug>
+#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
-#include <QJsonArray>
-#include <QDebug>
-#include <QUuid>
#include <QRegularExpression>
+#include <QUuid>
namespace {
-void tokenToJSONV3(QJsonObject &parent, Katabasis::Token t, const char * tokenName) {
- if(!t.persistent) {
+void tokenToJSONV3(QJsonObject& parent, Katabasis::Token t, const char* tokenName)
+{
+ if (!t.persistent) {
return;
}
QJsonObject out;
- if(t.issueInstant.isValid()) {
+ if (t.issueInstant.isValid()) {
out["iat"] = QJsonValue(t.issueInstant.toMSecsSinceEpoch() / 1000);
}
- if(t.notAfter.isValid()) {
+ if (t.notAfter.isValid()) {
out["exp"] = QJsonValue(t.notAfter.toMSecsSinceEpoch() / 1000);
}
bool save = false;
- if(!t.token.isEmpty()) {
+ if (!t.token.isEmpty()) {
out["token"] = QJsonValue(t.token);
save = true;
}
- if(!t.refresh_token.isEmpty()) {
+ if (!t.refresh_token.isEmpty()) {
out["refresh_token"] = QJsonValue(t.refresh_token);
save = true;
}
- if(t.extra.size()) {
+ if (t.extra.size()) {
out["extra"] = QJsonObject::fromVariantMap(t.extra);
save = true;
}
- if(save) {
+ if (save) {
parent[tokenName] = out;
}
}
-Katabasis::Token tokenFromJSONV3(const QJsonObject &parent, const char * tokenName) {
+Katabasis::Token tokenFromJSONV3(const QJsonObject& parent, const char* tokenName)
+{
Katabasis::Token out;
auto tokenObject = parent.value(tokenName).toObject();
- if(tokenObject.isEmpty()) {
+ if (tokenObject.isEmpty()) {
return out;
}
auto issueInstant = tokenObject.value("iat");
- if(issueInstant.isDouble()) {
- out.issueInstant = QDateTime::fromMSecsSinceEpoch(((int64_t) issueInstant.toDouble()) * 1000);
+ if (issueInstant.isDouble()) {
+ out.issueInstant = QDateTime::fromMSecsSinceEpoch(((int64_t)issueInstant.toDouble()) * 1000);
}
auto notAfter = tokenObject.value("exp");
- if(notAfter.isDouble()) {
- out.notAfter = QDateTime::fromMSecsSinceEpoch(((int64_t) notAfter.toDouble()) * 1000);
+ if (notAfter.isDouble()) {
+ out.notAfter = QDateTime::fromMSecsSinceEpoch(((int64_t)notAfter.toDouble()) * 1000);
}
auto token = tokenObject.value("token");
- if(token.isString()) {
+ if (token.isString()) {
out.token = token.toString();
out.validity = Katabasis::Validity::Assumed;
}
auto refresh_token = tokenObject.value("refresh_token");
- if(refresh_token.isString()) {
+ if (refresh_token.isString()) {
out.refresh_token = refresh_token.toString();
}
auto extra = tokenObject.value("extra");
- if(extra.isObject()) {
+ if (extra.isObject()) {
out.extra = extra.toObject().toVariantMap();
}
return out;
}
-void profileToJSONV3(QJsonObject &parent, MinecraftProfile p, const char * tokenName) {
- if(p.id.isEmpty()) {
+void profileToJSONV3(QJsonObject& parent, MinecraftProfile p, const char* tokenName)
+{
+ if (p.id.isEmpty()) {
return;
}
QJsonObject out;
out["id"] = QJsonValue(p.id);
out["name"] = QJsonValue(p.name);
- if(!p.currentCape.isEmpty()) {
+ if (!p.currentCape.isEmpty()) {
out["cape"] = p.currentCape;
}
@@ -123,19 +126,19 @@ void profileToJSONV3(QJsonObject &parent, MinecraftProfile p, const char * token
skinObj["id"] = p.skin.id;
skinObj["url"] = p.skin.url;
skinObj["variant"] = p.skin.variant;
- if(p.skin.data.size()) {
+ if (p.skin.data.size()) {
skinObj["data"] = QString::fromLatin1(p.skin.data.toBase64());
}
out["skin"] = skinObj;
}
QJsonArray capesArray;
- for(auto & cape: p.capes) {
+ for (auto& cape : p.capes) {
QJsonObject capeObj;
capeObj["id"] = cape.id;
capeObj["url"] = cape.url;
capeObj["alias"] = cape.alias;
- if(cape.data.size()) {
+ if (cape.data.size()) {
capeObj["data"] = QString::fromLatin1(cape.data.toBase64());
}
capesArray.push_back(capeObj);
@@ -144,16 +147,17 @@ void profileToJSONV3(QJsonObject &parent, MinecraftProfile p, const char * token
parent[tokenName] = out;
}
-MinecraftProfile profileFromJSONV3(const QJsonObject &parent, const char * tokenName) {
+MinecraftProfile profileFromJSONV3(const QJsonObject& parent, const char* tokenName)
+{
MinecraftProfile out;
auto tokenObject = parent.value(tokenName).toObject();
- if(tokenObject.isEmpty()) {
+ if (tokenObject.isEmpty()) {
return out;
}
{
auto idV = tokenObject.value("id");
auto nameV = tokenObject.value("name");
- if(!idV.isString() || !nameV.isString()) {
+ if (!idV.isString() || !nameV.isString()) {
qWarning() << "mandatory profile attributes are missing or of unexpected type";
return MinecraftProfile();
}
@@ -163,7 +167,7 @@ MinecraftProfile profileFromJSONV3(const QJsonObject &parent, const char * token
{
auto skinV = tokenObject.value("skin");
- if(!skinV.isObject()) {
+ if (!skinV.isObject()) {
qWarning() << "skin is missing";
return MinecraftProfile();
}
@@ -171,7 +175,7 @@ MinecraftProfile profileFromJSONV3(const QJsonObject &parent, const char * token
auto idV = skinObj.value("id");
auto urlV = skinObj.value("url");
auto variantV = skinObj.value("variant");
- if(!idV.isString() || !urlV.isString() || !variantV.isString()) {
+ if (!idV.isString() || !urlV.isString() || !variantV.isString()) {
qWarning() << "mandatory skin attributes are missing or of unexpected type";
return MinecraftProfile();
}
@@ -181,11 +185,10 @@ MinecraftProfile profileFromJSONV3(const QJsonObject &parent, const char * token
// data for skin is optional
auto dataV = skinObj.value("data");
- if(dataV.isString()) {
+ if (dataV.isString()) {
// TODO: validate base64
out.skin.data = QByteArray::fromBase64(dataV.toString().toLatin1());
- }
- else if (!dataV.isUndefined()) {
+ } else if (!dataV.isUndefined()) {
qWarning() << "skin data is something unexpected";
return MinecraftProfile();
}
@@ -193,13 +196,13 @@ MinecraftProfile profileFromJSONV3(const QJsonObject &parent, const char * token
{
auto capesV = tokenObject.value("capes");
- if(!capesV.isArray()) {
+ if (!capesV.isArray()) {
qWarning() << "capes is not an array!";
return MinecraftProfile();
}
auto capesArray = capesV.toArray();
- for(auto capeV: capesArray) {
- if(!capeV.isObject()) {
+ for (auto capeV : capesArray) {
+ if (!capeV.isObject()) {
qWarning() << "cape is not an object!";
return MinecraftProfile();
}
@@ -207,7 +210,7 @@ MinecraftProfile profileFromJSONV3(const QJsonObject &parent, const char * token
auto idV = capeObj.value("id");
auto urlV = capeObj.value("url");
auto aliasV = capeObj.value("alias");
- if(!idV.isString() || !urlV.isString() || !aliasV.isString()) {
+ if (!idV.isString() || !urlV.isString() || !aliasV.isString()) {
qWarning() << "mandatory skin attributes are missing or of unexpected type";
return MinecraftProfile();
}
@@ -218,11 +221,10 @@ MinecraftProfile profileFromJSONV3(const QJsonObject &parent, const char * token
// data for cape is optional.
auto dataV = capeObj.value("data");
- if(dataV.isString()) {
+ if (dataV.isString()) {
// TODO: validate base64
cape.data = QByteArray::fromBase64(dataV.toString().toLatin1());
- }
- else if (!dataV.isUndefined()) {
+ } else if (!dataV.isUndefined()) {
qWarning() << "cape data is something unexpected";
return MinecraftProfile();
}
@@ -232,9 +234,9 @@ MinecraftProfile profileFromJSONV3(const QJsonObject &parent, const char * token
// current cape
{
auto capeV = tokenObject.value("cape");
- if(capeV.isString()) {
+ if (capeV.isString()) {
auto currentCape = capeV.toString();
- if(out.capes.contains(currentCape)) {
+ if (out.capes.contains(currentCape)) {
out.currentCape = currentCape;
}
}
@@ -243,8 +245,9 @@ MinecraftProfile profileFromJSONV3(const QJsonObject &parent, const char * token
return out;
}
-void entitlementToJSONV3(QJsonObject &parent, MinecraftEntitlement p) {
- if(p.validity == Katabasis::Validity::None) {
+void entitlementToJSONV3(QJsonObject& parent, MinecraftEntitlement p)
+{
+ if (p.validity == Katabasis::Validity::None) {
return;
}
QJsonObject out;
@@ -253,15 +256,16 @@ void entitlementToJSONV3(QJsonObject &parent, MinecraftEntitlement p) {
parent["entitlement"] = out;
}
-bool entitlementFromJSONV3(const QJsonObject &parent, MinecraftEntitlement & out) {
+bool entitlementFromJSONV3(const QJsonObject& parent, MinecraftEntitlement& out)
+{
auto entitlementObject = parent.value("entitlement").toObject();
- if(entitlementObject.isEmpty()) {
+ if (entitlementObject.isEmpty()) {
return false;
}
{
auto ownsMinecraftV = entitlementObject.value("ownsMinecraft");
auto canPlayMinecraftV = entitlementObject.value("canPlayMinecraft");
- if(!ownsMinecraftV.isBool() || !canPlayMinecraftV.isBool()) {
+ if (!ownsMinecraftV.isBool() || !canPlayMinecraftV.isBool()) {
qWarning() << "mandatory attributes are missing or of unexpected type";
return false;
}
@@ -272,12 +276,12 @@ bool entitlementFromJSONV3(const QJsonObject &parent, MinecraftEntitlement & out
return true;
}
-}
+} // namespace
-bool AccountData::resumeStateFromV2(QJsonObject data) {
+bool AccountData::resumeStateFromV2(QJsonObject data)
+{
// The JSON object must at least have a username for it to be valid.
- if (!data.value("username").isString())
- {
+ if (!data.value("username").isString()) {
qCritical() << "Can't load Mojang account info from JSON object. Username field is missing or of the wrong type.";
return false;
}
@@ -287,14 +291,12 @@ bool AccountData::resumeStateFromV2(QJsonObject data) {
QString accessToken = data.value("accessToken").toString("");
QJsonArray profileArray = data.value("profiles").toArray();
- if (profileArray.size() < 1)
- {
+ if (profileArray.size() < 1) {
qCritical() << "Can't load Mojang account with username \"" << userName << "\". No profiles found.";
return false;
}
- struct AccountProfile
- {
+ struct AccountProfile {
QString id;
QString name;
bool legacy;
@@ -304,24 +306,22 @@ bool AccountData::resumeStateFromV2(QJsonObject data) {
int currentProfileIndex = 0;
int index = -1;
QString currentProfile = data.value("activeProfile").toString("");
- for (QJsonValue profileVal : profileArray)
- {
+ for (QJsonValue profileVal : profileArray) {
index++;
QJsonObject profileObject = profileVal.toObject();
QString id = profileObject.value("id").toString("");
QString name = profileObject.value("name").toString("");
bool legacy = profileObject.value("legacy").toBool(false);
- if (id.isEmpty() || name.isEmpty())
- {
+ if (id.isEmpty() || name.isEmpty()) {
qWarning() << "Unable to load a profile" << name << "because it was missing an ID or a name.";
continue;
}
- if(id == currentProfile) {
+ if (id == currentProfile) {
currentProfileIndex = index;
}
- profiles.append({id, name, legacy});
+ profiles.append({ id, name, legacy });
}
- auto & profile = profiles[currentProfileIndex];
+ auto& profile = profiles[currentProfileIndex];
type = AccountType::Mojang;
legacy = profile.legacy;
@@ -339,14 +339,15 @@ bool AccountData::resumeStateFromV2(QJsonObject data) {
return true;
}
-bool AccountData::resumeStateFromV3(QJsonObject data) {
+bool AccountData::resumeStateFromV3(QJsonObject data)
+{
auto typeV = data.value("type");
- if(!typeV.isString()) {
+ if (!typeV.isString()) {
qWarning() << "Failed to parse account data: type is missing.";
return false;
}
auto typeS = typeV.toString();
- if(typeS == "MSA") {
+ if (typeS == "MSA") {
type = AccountType::MSA;
} else if (typeS == "Mojang") {
type = AccountType::Mojang;
@@ -357,16 +358,16 @@ bool AccountData::resumeStateFromV3(QJsonObject data) {
return false;
}
- if(type == AccountType::Mojang) {
+ if (type == AccountType::Mojang) {
legacy = data.value("legacy").toBool(false);
canMigrateToMSA = data.value("canMigrateToMSA").toBool(false);
}
- if(type == AccountType::MSA) {
+ if (type == AccountType::MSA) {
auto clientIDV = data.value("msa-client-id");
if (clientIDV.isString()) {
msaClientID = clientIDV.toString();
- } // leave msaClientID empty if it doesn't exist or isn't a string
+ } // leave msaClientID empty if it doesn't exist or isn't a string
msaToken = tokenFromJSONV3(data, "msa");
userToken = tokenFromJSONV3(data, "utoken");
xboxApiToken = tokenFromJSONV3(data, "xrp-main");
@@ -379,8 +380,8 @@ bool AccountData::resumeStateFromV3(QJsonObject data) {
yggdrasilToken.token = "0";
minecraftProfile = profileFromJSONV3(data, "profile");
- if(!entitlementFromJSONV3(data, minecraftEntitlement)) {
- if(minecraftProfile.validity != Katabasis::Validity::None) {
+ if (!entitlementFromJSONV3(data, minecraftEntitlement)) {
+ if (minecraftProfile.validity != Katabasis::Validity::None) {
minecraftEntitlement.canPlayMinecraft = true;
minecraftEntitlement.ownsMinecraft = true;
minecraftEntitlement.validity = Katabasis::Validity::Assumed;
@@ -391,26 +392,25 @@ bool AccountData::resumeStateFromV3(QJsonObject data) {
return true;
}
-QJsonObject AccountData::saveState() const {
+QJsonObject AccountData::saveState() const
+{
QJsonObject output;
- if(type == AccountType::Mojang) {
+ if (type == AccountType::Mojang) {
output["type"] = "Mojang";
- if(legacy) {
+ if (legacy) {
output["legacy"] = true;
}
- if(canMigrateToMSA) {
+ if (canMigrateToMSA) {
output["canMigrateToMSA"] = true;
}
- }
- else if (type == AccountType::MSA) {
+ } else if (type == AccountType::MSA) {
output["type"] = "MSA";
output["msa-client-id"] = msaClientID;
tokenToJSONV3(output, msaToken, "msa");
tokenToJSONV3(output, userToken, "utoken");
tokenToJSONV3(output, xboxApiToken, "xrp-main");
tokenToJSONV3(output, mojangservicesToken, "xrp-mc");
- }
- else if (type == AccountType::Offline) {
+ } else if (type == AccountType::Offline) {
output["type"] = "Offline";
}
@@ -420,60 +420,68 @@ QJsonObject AccountData::saveState() const {
return output;
}
-QString AccountData::userName() const {
- if(type == AccountType::MSA) {
+QString AccountData::userName() const
+{
+ if (type == AccountType::MSA) {
return QString();
}
return yggdrasilToken.extra["userName"].toString();
}
-QString AccountData::accessToken() const {
+QString AccountData::accessToken() const
+{
return yggdrasilToken.token;
}
-QString AccountData::clientToken() const {
- if(type != AccountType::Mojang) {
+QString AccountData::clientToken() const
+{
+ if (type != AccountType::Mojang) {
return QString();
}
return yggdrasilToken.extra["clientToken"].toString();
}
-void AccountData::setClientToken(QString clientToken) {
- if(type != AccountType::Mojang) {
+void AccountData::setClientToken(QString clientToken)
+{
+ if (type != AccountType::Mojang) {
return;
}
yggdrasilToken.extra["clientToken"] = clientToken;
}
-void AccountData::generateClientTokenIfMissing() {
- if(yggdrasilToken.extra.contains("clientToken")) {
+void AccountData::generateClientTokenIfMissing()
+{
+ if (yggdrasilToken.extra.contains("clientToken")) {
return;
}
invalidateClientToken();
}
-void AccountData::invalidateClientToken() {
- if(type != AccountType::Mojang) {
+void AccountData::invalidateClientToken()
+{
+ if (type != AccountType::Mojang) {
return;
}
yggdrasilToken.extra["clientToken"] = QUuid::createUuid().toString().remove(QRegularExpression("[{-}]"));
}
-QString AccountData::profileId() const {
+QString AccountData::profileId() const
+{
return minecraftProfile.id;
}
-QString AccountData::profileName() const {
- if(minecraftProfile.name.size() == 0) {
+QString AccountData::profileName() const
+{
+ if (minecraftProfile.name.size() == 0) {
return QObject::tr("No profile (%1)").arg(accountDisplayString());
- }
- else {
+ } else {
return minecraftProfile.name;
}
}
-QString AccountData::accountDisplayString() const {
- switch(type) {
+QString AccountData::accountDisplayString() const
+{
+ switch (type) {
case AccountType::Mojang: {
return userName();
}
@@ -481,7 +489,7 @@ QString AccountData::accountDisplayString() const {
return QObject::tr("<Offline>");
}
case AccountType::MSA: {
- if(xboxApiToken.extra.contains("gtg")) {
+ if (xboxApiToken.extra.contains("gtg")) {
return xboxApiToken.extra["gtg"].toString();
}
return "Xbox profile missing";
@@ -492,6 +500,7 @@ QString AccountData::accountDisplayString() const {
}
}
-QString AccountData::lastError() const {
+QString AccountData::lastError() const
+{
return errorString;
}
diff --git a/launcher/minecraft/auth/AccountData.h b/launcher/minecraft/auth/AccountData.h
index 092e1691..38e3c3c9 100644
--- a/launcher/minecraft/auth/AccountData.h
+++ b/launcher/minecraft/auth/AccountData.h
@@ -34,11 +34,11 @@
*/
#pragma once
-#include <QString>
-#include <QByteArray>
-#include <QVector>
#include <katabasis/Bits.h>
+#include <QByteArray>
#include <QJsonObject>
+#include <QString>
+#include <QVector>
struct Skin {
QString id;
@@ -71,22 +71,9 @@ struct MinecraftProfile {
Katabasis::Validity validity = Katabasis::Validity::None;
};
-enum class AccountType {
- MSA,
- Mojang,
- Offline
-};
+enum class AccountType { MSA, Mojang, Offline };
-enum class AccountState {
- Unchecked,
- Offline,
- Working,
- Online,
- Disabled,
- Errored,
- Expired,
- Gone
-};
+enum class AccountState { Unchecked, Offline, Working, Online, Disabled, Errored, Expired, Gone };
struct AccountData {
QJsonObject saveState() const;
diff --git a/launcher/minecraft/auth/AccountList.cpp b/launcher/minecraft/auth/AccountList.cpp
index d6f42b75..609eaa55 100644
--- a/launcher/minecraft/auth/AccountList.cpp
+++ b/launcher/minecraft/auth/AccountList.cpp
@@ -37,14 +37,14 @@
#include "AccountData.h"
#include "AccountTask.h"
-#include <QIODevice>
+#include <QDir>
#include <QFile>
-#include <QTextStream>
-#include <QJsonDocument>
+#include <QIODevice>
#include <QJsonArray>
+#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonParseError>
-#include <QDir>
+#include <QTextStream>
#include <QTimer>
#include <QDebug>
@@ -54,12 +54,10 @@
#include <chrono>
-enum AccountListVersion {
- MojangOnly = 2,
- MojangMSA = 3
-};
+enum AccountListVersion { MojangOnly = 2, MojangMSA = 3 };
-AccountList::AccountList(QObject *parent) : QAbstractListModel(parent) {
+AccountList::AccountList(QObject* parent) : QAbstractListModel(parent)
+{
m_refreshTimer = new QTimer(this);
m_refreshTimer->setSingleShot(true);
connect(m_refreshTimer, &QTimer::timeout, this, &AccountList::fillQueue);
@@ -70,7 +68,8 @@ AccountList::AccountList(QObject *parent) : QAbstractListModel(parent) {
AccountList::~AccountList() noexcept {}
-int AccountList::findAccountByProfileId(const QString& profileId) const {
+int AccountList::findAccountByProfileId(const QString& profileId) const
+{
for (int i = 0; i < count(); i++) {
MinecraftAccountPtr account = at(i);
if (account->profileId() == profileId) {
@@ -80,7 +79,8 @@ int AccountList::findAccountByProfileId(const QString& profileId) const {
return -1;
}
-MinecraftAccountPtr AccountList::getAccountByProfileName(const QString& profileName) const {
+MinecraftAccountPtr AccountList::getAccountByProfileName(const QString& profileName) const
+{
for (int i = 0; i < count(); i++) {
MinecraftAccountPtr account = at(i);
if (account->profileName() == profileName) {
@@ -95,11 +95,12 @@ const MinecraftAccountPtr AccountList::at(int i) const
return MinecraftAccountPtr(m_accounts.at(i));
}
-QStringList AccountList::profileNames() const {
+QStringList AccountList::profileNames() const
+{
QStringList out;
- for(auto & account: m_accounts) {
- auto profileName = account->profileName();
- if(profileName.isEmpty()) {
+ for (auto& account : m_accounts) {
+ auto profileName = account->profileName();
+ if (profileName.isEmpty()) {
continue;
}
out.append(profileName);
@@ -122,14 +123,14 @@ void AccountList::addAccount(const MinecraftAccountPtr account)
// override/replace existing account with the same profileId
auto profileId = account->profileId();
- if(profileId.size()) {
+ if (profileId.size()) {
auto existingAccount = findAccountByProfileId(profileId);
- if(existingAccount != -1) {
+ if (existingAccount != -1) {
qDebug() << "Replacing old account with a new one with the same profile ID!";
MinecraftAccountPtr existingAccountPtr = m_accounts[existingAccount];
m_accounts[existingAccount] = account;
- if(m_defaultAccount == existingAccountPtr) {
+ if (m_defaultAccount == existingAccountPtr) {
m_defaultAccount = account;
}
// disconnect notifications for changes in the account being replaced
@@ -154,11 +155,9 @@ void AccountList::addAccount(const MinecraftAccountPtr account)
void AccountList::removeAccount(QModelIndex index)
{
int row = index.row();
- if(index.isValid() && row >= 0 && row < m_accounts.size())
- {
- auto & account = m_accounts[row];
- if(account == m_defaultAccount)
- {
+ if (index.isValid() && row >= 0 && row < m_accounts.size()) {
+ auto& account = m_accounts[row];
+ if (account == m_defaultAccount) {
m_defaultAccount = nullptr;
onDefaultAccountChanged();
}
@@ -178,43 +177,34 @@ MinecraftAccountPtr AccountList::defaultAccount() const
void AccountList::setDefaultAccount(MinecraftAccountPtr newAccount)
{
- if (!newAccount && m_defaultAccount)
- {
+ if (!newAccount && m_defaultAccount) {
int idx = 0;
auto previousDefaultAccount = m_defaultAccount;
m_defaultAccount = nullptr;
- for (MinecraftAccountPtr account : m_accounts)
- {
- if (account == previousDefaultAccount)
- {
+ for (MinecraftAccountPtr account : m_accounts) {
+ if (account == previousDefaultAccount) {
emit dataChanged(index(idx), index(idx, columnCount(QModelIndex()) - 1));
}
- idx ++;
+ idx++;
}
onDefaultAccountChanged();
- }
- else
- {
+ } else {
auto currentDefaultAccount = m_defaultAccount;
int currentDefaultAccountIdx = -1;
auto newDefaultAccount = m_defaultAccount;
int newDefaultAccountIdx = -1;
int idx = 0;
- for (MinecraftAccountPtr account : m_accounts)
- {
- if (account == newAccount)
- {
+ for (MinecraftAccountPtr account : m_accounts) {
+ if (account == newAccount) {
newDefaultAccount = account;
newDefaultAccountIdx = idx;
}
- if(currentDefaultAccount == account)
- {
+ if (currentDefaultAccount == account) {
currentDefaultAccountIdx = idx;
}
idx++;
}
- if(currentDefaultAccount != newDefaultAccount)
- {
+ if (currentDefaultAccount != newDefaultAccount) {
emit dataChanged(index(currentDefaultAccountIdx), index(currentDefaultAccountIdx, columnCount(QModelIndex()) - 1));
emit dataChanged(index(newDefaultAccountIdx), index(newDefaultAccountIdx, columnCount(QModelIndex()) - 1));
m_defaultAccount = newDefaultAccount;
@@ -231,27 +221,25 @@ void AccountList::accountChanged()
void AccountList::accountActivityChanged(bool active)
{
- MinecraftAccount *account = qobject_cast<MinecraftAccount *>(sender());
+ MinecraftAccount* account = qobject_cast<MinecraftAccount*>(sender());
bool found = false;
for (int i = 0; i < count(); i++) {
if (at(i).get() == account) {
- emit dataChanged(index(i), index(i, columnCount(QModelIndex()) - 1));
+ emit dataChanged(index(i), index(i, columnCount(QModelIndex()) - 1));
found = true;
break;
}
}
- if(found) {
+ if (found) {
emit listActivityChanged();
- if(active) {
+ if (active) {
beginActivity();
- }
- else {
+ } else {
endActivity();
}
}
}
-
void AccountList::onListChanged()
{
if (m_autosave)
@@ -274,7 +262,7 @@ int AccountList::count() const
return m_accounts.count();
}
-QVariant AccountList::data(const QModelIndex &index, int role) const
+QVariant AccountList::data(const QModelIndex& index, int role) const
{
if (!index.isValid())
return QVariant();
@@ -284,70 +272,67 @@ QVariant AccountList::data(const QModelIndex &index, int role) const
MinecraftAccountPtr account = at(index.row());
- switch (role)
- {
+ switch (role) {
case Qt::DisplayRole:
- switch (index.column())
- {
- case ProfileNameColumn: {
- return account->profileName();
- }
+ switch (index.column()) {
+ case ProfileNameColumn: {
+ return account->profileName();
+ }
- case NameColumn:
- return account->accountDisplayString();
+ case NameColumn:
+ return account->accountDisplayString();
- case TypeColumn: {
- auto typeStr = account->typeString();
- typeStr[0] = typeStr[0].toUpper();
- return typeStr;
- }
+ case TypeColumn: {
+ auto typeStr = account->typeString();
+ typeStr[0] = typeStr[0].toUpper();
+ return typeStr;
+ }
- case StatusColumn: {
- switch(account->accountState()) {
- case AccountState::Unchecked: {
- return tr("Unchecked", "Account status");
- }
- case AccountState::Offline: {
- return tr("Offline", "Account status");
- }
- case AccountState::Online: {
- return tr("Ready", "Account status");
- }
- case AccountState::Working: {
- return tr("Working", "Account status");
- }
- case AccountState::Errored: {
- return tr("Errored", "Account status");
- }
- case AccountState::Expired: {
- return tr("Expired", "Account status");
- }
- case AccountState::Disabled: {
- return tr("Disabled", "Account status");
- }
- case AccountState::Gone: {
- return tr("Gone", "Account status");
- }
- default: {
- return tr("Unknown", "Account status");
+ case StatusColumn: {
+ switch (account->accountState()) {
+ case AccountState::Unchecked: {
+ return tr("Unchecked", "Account status");
+ }
+ case AccountState::Offline: {
+ return tr("Offline", "Account status");
+ }
+ case AccountState::Online: {
+ return tr("Ready", "Account status");
+ }
+ case AccountState::Working: {
+ return tr("Working", "Account status");
+ }
+ case AccountState::Errored: {
+ return tr("Errored", "Account status");
+ }
+ case AccountState::Expired: {
+ return tr("Expired", "Account status");
+ }
+ case AccountState::Disabled: {
+ return tr("Disabled", "Account status");
+ }
+ case AccountState::Gone: {
+ return tr("Gone", "Account status");
+ }
+ default: {
+ return tr("Unknown", "Account status");
+ }
}
}
- }
- case MigrationColumn: {
- if(account->isMSA() || account->isOffline()) {
- return tr("N/A", "Can Migrate");
- }
- if (account->canMigrate()) {
- return tr("Yes", "Can Migrate");
- }
- else {
- return tr("No", "Can Migrate");
+ case MigrationColumn: {
+ if (account->isMSA() || account->isOffline()) {
+ return tr("N/A", "Can Migrate");
+ }
+ if (account->canMigrate()) {
+ return tr("Yes", "Can Migrate");
+ } else {
+ return tr("No", "Can Migrate");
+ }
}
- }
- default:
- return QVariant();
+ default:
+ return QVariant();
}
case Qt::ToolTipRole:
@@ -362,7 +347,6 @@ QVariant AccountList::data(const QModelIndex &index, int role) const
} else {
return QVariant();
}
-
default:
return QVariant();
@@ -371,79 +355,72 @@ QVariant AccountList::data(const QModelIndex &index, int role) const
QVariant AccountList::headerData(int section, Qt::Orientation orientation, int role) const
{
- switch (role)
- {
- case Qt::DisplayRole:
- switch (section)
- {
- case ProfileNameColumn:
- return tr("Username");
- case NameColumn:
- return tr("Account");
- case TypeColumn:
- return tr("Type");
- case StatusColumn:
- return tr("Status");
- case MigrationColumn:
- return tr("Can Migrate?");
- default:
- return QVariant();
- }
+ switch (role) {
+ case Qt::DisplayRole:
+ switch (section) {
+ case ProfileNameColumn:
+ return tr("Username");
+ case NameColumn:
+ return tr("Account");
+ case TypeColumn:
+ return tr("Type");
+ case StatusColumn:
+ return tr("Status");
+ case MigrationColumn:
+ return tr("Can Migrate?");
+ default:
+ return QVariant();
+ }
+
+ case Qt::ToolTipRole:
+ switch (section) {
+ case ProfileNameColumn:
+ return tr("Minecraft username associated with the account.");
+ case NameColumn:
+ return tr("User name of the account.");
+ case TypeColumn:
+ return tr("Type of the account - Mojang or MSA.");
+ case StatusColumn:
+ return tr("Current status of the account.");
+ case MigrationColumn:
+ return tr("Can this account migrate to a Microsoft account?");
+ default:
+ return QVariant();
+ }
- case Qt::ToolTipRole:
- switch (section)
- {
- case ProfileNameColumn:
- return tr("Minecraft username associated with the account.");
- case NameColumn:
- return tr("User name of the account.");
- case TypeColumn:
- return tr("Type of the account - Mojang or MSA.");
- case StatusColumn:
- return tr("Current status of the account.");
- case MigrationColumn:
- return tr("Can this account migrate to a Microsoft account?");
default:
return QVariant();
- }
-
- default:
- return QVariant();
}
}
-int AccountList::rowCount(const QModelIndex &parent) const
+int AccountList::rowCount(const QModelIndex& parent) const
{
// Return count
return parent.isValid() ? 0 : count();
}
-int AccountList::columnCount(const QModelIndex &parent) const
+int AccountList::columnCount(const QModelIndex& parent) const
{
return parent.isValid() ? 0 : NUM_COLUMNS;
}
-Qt::ItemFlags AccountList::flags(const QModelIndex &index) const
+Qt::ItemFlags AccountList::flags(const QModelIndex& index) const
{
- if (index.row() < 0 || index.row() >= rowCount(index.parent()) || !index.isValid())
- {
+ if (index.row() < 0 || index.row() >= rowCount(index.parent()) || !index.isValid()) {
return Qt::NoItemFlags;
}
return Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable;
}
-bool AccountList::setData(const QModelIndex &idx, const QVariant &value, int role)
+bool AccountList::setData(const QModelIndex& idx, const QVariant& value, int role)
{
- if (idx.row() < 0 || idx.row() >= rowCount(idx) || !idx.isValid())
- {
+ if (idx.row() < 0 || idx.row() >= rowCount(idx) || !idx.isValid()) {
return false;
}
- if(role == Qt::CheckStateRole)
- {
- if(value == Qt::Checked)
- {
+ if (role == Qt::CheckStateRole) {
+ if (value == Qt::Checked) {
MinecraftAccountPtr account = at(idx.row());
setDefaultAccount(account);
}
@@ -455,8 +432,7 @@ bool AccountList::setData(const QModelIndex &idx, const QVariant &value, int rol
bool AccountList::loadList()
{
- if (m_listFilePath.isEmpty())
- {
+ if (m_listFilePath.isEmpty()) {
qCritical() << "Can't load Mojang account list. No file path given and no default set.";
return false;
}
@@ -465,8 +441,7 @@ bool AccountList::loadList()
// Try to open the file and fail if we can't.
// TODO: We should probably report this error to the user.
- if (!file.open(QIODevice::ReadOnly))
- {
+ if (!file.open(QIODevice::ReadOnly)) {
qCritical() << QString("Failed to read the account list file (%1).").arg(m_listFilePath).toUtf8();
return false;
}
@@ -479,17 +454,15 @@ bool AccountList::loadList()
QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonData, &parseError);
// Fail if the JSON is invalid.
- if (parseError.error != QJsonParseError::NoError)
- {
+ if (parseError.error != QJsonParseError::NoError) {
qCritical() << QString("Failed to parse account list file: %1 at offset %2")
- .arg(parseError.errorString(), QString::number(parseError.offset))
- .toUtf8();
+ .arg(parseError.errorString(), QString::number(parseError.offset))
+ .toUtf8();
return false;
}
// Make sure the root is an object.
- if (!jsonDoc.isObject())
- {
+ if (!jsonDoc.isObject()) {
qCritical() << "Invalid account list JSON: Root should be an array.";
return false;
}
@@ -498,15 +471,13 @@ bool AccountList::loadList()
// Make sure the format version matches.
auto listVersion = root.value("formatVersion").toVariant().toInt();
- switch(listVersion) {
+ switch (listVersion) {
case AccountListVersion::MojangOnly: {
return loadV2(root);
- }
- break;
+ } break;
case AccountListVersion::MojangMSA: {
return loadV3(root);
- }
- break;
+ } break;
default: {
QString newName = "accounts-old.json";
qWarning() << "Unknown format version when loading account list. Existing one will be renamed to" << newName;
@@ -517,21 +488,20 @@ bool AccountList::loadList()
}
}
-bool AccountList::loadV2(QJsonObject& root) {
+bool AccountList::loadV2(QJsonObject& root)
+{
beginResetModel();
auto defaultUserName = root.value("activeAccount").toString("");
QJsonArray accounts = root.value("accounts").toArray();
- for (QJsonValue accountVal : accounts)
- {
+ for (QJsonValue accountVal : accounts) {
QJsonObject accountObj = accountVal.toObject();
MinecraftAccountPtr account = MinecraftAccount::loadFromJsonV2(accountObj);
- if (account.get() != nullptr)
- {
+ if (account.get() != nullptr) {
auto profileId = account->profileId();
- if(!profileId.size()) {
+ if (!profileId.size()) {
continue;
}
- if(findAccountByProfileId(profileId) != -1) {
+ if (findAccountByProfileId(profileId) != -1) {
continue;
}
connect(account.get(), &MinecraftAccount::changed, this, &AccountList::accountChanged);
@@ -540,9 +510,7 @@ bool AccountList::loadV2(QJsonObject& root) {
if (defaultUserName.size() && account->mojangUserName() == defaultUserName) {
m_defaultAccount = account;
}
- }
- else
- {
+ } else {
qWarning() << "Failed to load an account.";
}
}
@@ -550,30 +518,27 @@ bool AccountList::loadV2(QJsonObject& root) {
return true;
}
-bool AccountList::loadV3(QJsonObject& root) {
+bool AccountList::loadV3(QJsonObject& root)
+{
beginResetModel();
QJsonArray accounts = root.value("accounts").toArray();
- for (QJsonValue accountVal : accounts)
- {
+ for (QJsonValue accountVal : accounts) {
QJsonObject accountObj = accountVal.toObject();
MinecraftAccountPtr account = MinecraftAccount::loadFromJsonV3(accountObj);
- if (account.get() != nullptr)
- {
+ if (account.get() != nullptr) {
auto profileId = account->profileId();
- if(profileId.size()) {
- if(findAccountByProfileId(profileId) != -1) {
+ if (profileId.size()) {
+ if (findAccountByProfileId(profileId) != -1) {
continue;
}
}
connect(account.get(), &MinecraftAccount::changed, this, &AccountList::accountChanged);
connect(account.get(), &MinecraftAccount::activityChanged, this, &AccountList::accountActivityChanged);
m_accounts.append(account);
- if(accountObj.value("active").toBool(false)) {
+ if (accountObj.value("active").toBool(false)) {
m_defaultAccount = account;
}
- }
- else
- {
+ } else {
qWarning() << "Failed to load an account.";
}
}
@@ -581,23 +546,20 @@ bool AccountList::loadV3(QJsonObject& root) {
return true;
}
-
bool AccountList::saveList()
{
- if (m_listFilePath.isEmpty())
- {
+ if (m_listFilePath.isEmpty()) {
qCritical() << "Can't save Mojang account list. No file path given and no default set.";
return false;
}
// make sure the parent folder exists
- if(!FS::ensureFilePathExists(m_listFilePath))
+ if (!FS::ensureFilePathExists(m_listFilePath))
return false;
// make sure the file wasn't overwritten with a folder before (fixes a bug)
QFileInfo finfo(m_listFilePath);
- if(finfo.isDir())
- {
+ if (finfo.isDir()) {
QDir badDir(m_listFilePath);
badDir.removeRecursively();
}
@@ -613,10 +575,9 @@ bool AccountList::saveList()
// Build a list of accounts.
qDebug() << "Building account array.";
QJsonArray accounts;
- for (MinecraftAccountPtr account : m_accounts)
- {
+ for (MinecraftAccountPtr account : m_accounts) {
QJsonObject accountObj = account->saveToJson();
- if(m_defaultAccount == account) {
+ if (m_defaultAccount == account) {
accountObj["active"] = true;
}
accounts.append(accountObj);
@@ -634,20 +595,18 @@ bool AccountList::saveList()
// Try to open the file and fail if we can't.
// TODO: We should probably report this error to the user.
- if (!file.open(QIODevice::WriteOnly))
- {
+ if (!file.open(QIODevice::WriteOnly)) {
qCritical() << QString("Failed to read the account list file (%1).").arg(m_listFilePath).toUtf8();
return false;
}
// Write the JSON to the file.
file.write(doc.toJson());
- file.setPermissions(QFile::ReadOwner|QFile::WriteOwner|QFile::ReadUser|QFile::WriteUser);
- if(file.commit()) {
+ file.setPermissions(QFile::ReadOwner | QFile::WriteOwner | QFile::ReadUser | QFile::WriteUser);
+ if (file.commit()) {
qDebug() << "Saved account list to" << m_listFilePath;
return true;
- }
- else {
+ } else {
qDebug() << "Failed to save accounts to" << m_listFilePath;
return false;
}
@@ -661,30 +620,29 @@ void AccountList::setListFilePath(QString path, bool autosave)
bool AccountList::anyAccountIsValid()
{
- for(auto account: m_accounts)
- {
- if(account->ownsMinecraft()) {
+ for (auto account : m_accounts) {
+ if (account->ownsMinecraft()) {
return true;
}
}
return false;
}
-void AccountList::fillQueue() {
-
- if(m_defaultAccount && m_defaultAccount->shouldRefresh()) {
+void AccountList::fillQueue()
+{
+ if (m_defaultAccount && m_defaultAccount->shouldRefresh()) {
auto idToRefresh = m_defaultAccount->internalId();
m_refreshQueue.push_back(idToRefresh);
qDebug() << "AccountList: Queued default account with internal ID " << idToRefresh << " to refresh first";
}
- for(int i = 0; i < count(); i++) {
+ for (int i = 0; i < count(); i++) {
auto account = at(i);
- if(account == m_defaultAccount) {
+ if (account == m_defaultAccount) {
continue;
}
- if(account->shouldRefresh()) {
+ if (account->shouldRefresh()) {
auto idToRefresh = account->internalId();
queueRefresh(idToRefresh);
}
@@ -692,40 +650,43 @@ void AccountList::fillQueue() {
tryNext();
}
-void AccountList::requestRefresh(QString accountId) {
+void AccountList::requestRefresh(QString accountId)
+{
auto index = m_refreshQueue.indexOf(accountId);
- if(index != -1) {
+ if (index != -1) {
m_refreshQueue.removeAt(index);
}
m_refreshQueue.push_front(accountId);
qDebug() << "AccountList: Pushed account with internal ID " << accountId << " to the front of the queue";
- if(!isActive()) {
+ if (!isActive()) {
tryNext();
}
}
-void AccountList::queueRefresh(QString accountId) {
- if(m_refreshQueue.indexOf(accountId) != -1) {
+void AccountList::queueRefresh(QString accountId)
+{
+ if (m_refreshQueue.indexOf(accountId) != -1) {
return;
}
m_refreshQueue.push_back(accountId);
qDebug() << "AccountList: Queued account with internal ID " << accountId << " to refresh";
}
-
-void AccountList::tryNext() {
+void AccountList::tryNext()
+{
while (m_refreshQueue.length()) {
auto accountId = m_refreshQueue.front();
m_refreshQueue.pop_front();
- for(int i = 0; i < count(); i++) {
+ for (int i = 0; i < count(); i++) {
auto account = at(i);
- if(account->internalId() == accountId) {
+ if (account->internalId() == accountId) {
m_currentTask = account->refresh();
- if(m_currentTask) {
+ if (m_currentTask) {
connect(m_currentTask.get(), &AccountTask::succeeded, this, &AccountList::authSucceeded);
connect(m_currentTask.get(), &AccountTask::failed, this, &AccountList::authFailed);
m_currentTask->start();
- qDebug() << "RefreshSchedule: Processing account " << account->accountDisplayString() << " with internal ID " << accountId;
+ qDebug() << "RefreshSchedule: Processing account " << account->accountDisplayString() << " with internal ID "
+ << accountId;
return;
}
}
@@ -736,38 +697,43 @@ void AccountList::tryNext() {
m_refreshTimer->start(1000 * 3600);
}
-void AccountList::authSucceeded() {
+void AccountList::authSucceeded()
+{
qDebug() << "RefreshSchedule: Background account refresh succeeded";
m_currentTask.reset();
m_nextTimer->start(1000 * 20);
}
-void AccountList::authFailed(QString reason) {
+void AccountList::authFailed(QString reason)
+{
qDebug() << "RefreshSchedule: Background account refresh failed: " << reason;
m_currentTask.reset();
m_nextTimer->start(1000 * 20);
}
-bool AccountList::isActive() const {
+bool AccountList::isActive() const
+{
return m_activityCount != 0;
}
-void AccountList::beginActivity() {
+void AccountList::beginActivity()
+{
bool activating = m_activityCount == 0;
m_activityCount++;
- if(activating) {
+ if (activating) {
emit activityChanged(true);
}
}
-void AccountList::endActivity() {
- if(m_activityCount == 0) {
+void AccountList::endActivity()
+{
+ if (m_activityCount == 0) {
qWarning() << m_name << " - Activity count would become below zero";
return;
}
bool deactivating = m_activityCount == 1;
m_activityCount--;
- if(deactivating) {
+ if (deactivating) {
emit activityChanged(false);
}
}
diff --git a/launcher/minecraft/auth/AccountList.h b/launcher/minecraft/auth/AccountList.h
index a8c3529a..30926d13 100644
--- a/launcher/minecraft/auth/AccountList.h
+++ b/launcher/minecraft/auth/AccountList.h
@@ -37,26 +37,21 @@
#include "MinecraftAccount.h"
-#include <QObject>
-#include <QVariant>
#include <QAbstractListModel>
+#include <QObject>
#include <QSharedPointer>
+#include <QVariant>
/*!
* List of available Mojang accounts.
* This should be loaded in the background by Prism Launcher on startup.
*/
-class AccountList : public QAbstractListModel
-{
+class AccountList : public QAbstractListModel {
Q_OBJECT
-public:
- enum ModelRoles
- {
- PointerRole = 0x34B1CB48
- };
+ public:
+ enum ModelRoles { PointerRole = 0x34B1CB48 };
- enum VListColumns
- {
+ enum VListColumns {
// TODO: Add icon column.
ProfileNameColumn = 0,
NameColumn,
@@ -67,24 +62,24 @@ public:
NUM_COLUMNS
};
- explicit AccountList(QObject *parent = 0);
+ explicit AccountList(QObject* parent = 0);
virtual ~AccountList() noexcept;
const MinecraftAccountPtr at(int i) const;
int count() const;
//////// List Model Functions ////////
- QVariant data(const QModelIndex &index, int role) const override;
+ QVariant data(const QModelIndex& index, int role) const override;
virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
- virtual int rowCount(const QModelIndex &parent) const override;
- virtual int columnCount(const QModelIndex &parent) const override;
- virtual Qt::ItemFlags flags(const QModelIndex &index) const override;
- virtual bool setData(const QModelIndex &index, const QVariant &value, int role) override;
+ virtual int rowCount(const QModelIndex& parent) const override;
+ virtual int columnCount(const QModelIndex& parent) const override;
+ virtual Qt::ItemFlags flags(const QModelIndex& index) const override;
+ virtual bool setData(const QModelIndex& index, const QVariant& value, int role) override;
void addAccount(const MinecraftAccountPtr account);
void removeAccount(QModelIndex index);
- int findAccountByProfileId(const QString &profileId) const;
- MinecraftAccountPtr getAccountByProfileName(const QString &profileName) const;
+ int findAccountByProfileId(const QString& profileId) const;
+ MinecraftAccountPtr getAccountByProfileName(const QString& profileName) const;
QStringList profileNames() const;
// requesting a refresh pushes it to the front of the queue
@@ -102,8 +97,8 @@ public:
void setListFilePath(QString path, bool autosave = false);
bool loadList();
- bool loadV2(QJsonObject &root);
- bool loadV3(QJsonObject &root);
+ bool loadV2(QJsonObject& root);
+ bool loadV3(QJsonObject& root);
bool saveList();
MinecraftAccountPtr defaultAccount() const;
@@ -112,20 +107,20 @@ public:
bool isActive() const;
-protected:
+ protected:
void beginActivity();
void endActivity();
-private:
+ private:
const char* m_name;
uint32_t m_activityCount = 0;
-signals:
+ signals:
void listChanged();
void listActivityChanged();
void defaultAccountChanged();
void activityChanged(bool active);
-public slots:
+ public slots:
/**
* This is called when one of the accounts changes and the list needs to be updated
*/
@@ -141,16 +136,16 @@ public slots:
*/
void fillQueue();
-private slots:
+ private slots:
void tryNext();
void authSucceeded();
void authFailed(QString reason);
-protected:
+ protected:
QList<QString> m_refreshQueue;
- QTimer *m_refreshTimer;
- QTimer *m_nextTimer;
+ QTimer* m_refreshTimer;
+ QTimer* m_nextTimer;
shared_qobject_ptr<AccountTask> m_currentTask;
/*!
@@ -178,4 +173,3 @@ protected:
*/
bool m_autosave = false;
};
-
diff --git a/launcher/minecraft/auth/AccountTask.cpp b/launcher/minecraft/auth/AccountTask.cpp
index 4118c3c5..89660719 100644
--- a/launcher/minecraft/auth/AccountTask.cpp
+++ b/launcher/minecraft/auth/AccountTask.cpp
@@ -36,43 +36,41 @@
#include "AccountTask.h"
#include "MinecraftAccount.h"
-#include <QObject>
-#include <QString>
-#include <QJsonObject>
+#include <QByteArray>
#include <QJsonDocument>
+#include <QJsonObject>
#include <QNetworkReply>
-#include <QByteArray>
+#include <QObject>
+#include <QString>
#include <QDebug>
-AccountTask::AccountTask(AccountData *data, QObject *parent)
- : Task(parent), m_data(data)
+AccountTask::AccountTask(AccountData* data, QObject* parent) : Task(parent), m_data(data)
{
changeState(AccountTaskState::STATE_CREATED);
}
QString AccountTask::getStateMessage() const
{
- switch (m_taskState)
- {
- case AccountTaskState::STATE_CREATED:
- return "Waiting...";
- case AccountTaskState::STATE_WORKING:
- return tr("Sending request to auth servers...");
- case AccountTaskState::STATE_SUCCEEDED:
- return tr("Authentication task succeeded.");
- case AccountTaskState::STATE_OFFLINE:
- return tr("Failed to contact the authentication server.");
- case AccountTaskState::STATE_DISABLED:
- return tr("Client ID has changed. New session needs to be created.");
- case AccountTaskState::STATE_FAILED_SOFT:
- return tr("Encountered an error during authentication.");
- case AccountTaskState::STATE_FAILED_HARD:
- return tr("Failed to authenticate. The session has expired.");
- case AccountTaskState::STATE_FAILED_GONE:
- return tr("Failed to authenticate. The account no longer exists.");
- default:
- return tr("...");
+ switch (m_taskState) {
+ case AccountTaskState::STATE_CREATED:
+ return "Waiting...";
+ case AccountTaskState::STATE_WORKING:
+ return tr("Sending request to auth servers...");
+ case AccountTaskState::STATE_SUCCEEDED:
+ return tr("Authentication task succeeded.");
+ case AccountTaskState::STATE_OFFLINE:
+ return tr("Failed to contact the authentication server.");
+ case AccountTaskState::STATE_DISABLED:
+ return tr("Client ID has changed. New session needs to be created.");
+ case AccountTaskState::STATE_FAILED_SOFT:
+ return tr("Encountered an error during authentication.");
+ case AccountTaskState::STATE_FAILED_HARD:
+ return tr("Failed to authenticate. The session has expired.");
+ case AccountTaskState::STATE_FAILED_GONE:
+ return tr("Failed to authenticate. The account no longer exists.");
+ default:
+ return tr("...");
}
}
@@ -82,7 +80,7 @@ bool AccountTask::changeState(AccountTaskState newState, QString reason)
// FIXME: virtual method invoked in constructor.
// We want that behavior, but maybe make it less weird?
setStatus(getStateMessage());
- switch(newState) {
+ switch (newState) {
case AccountTaskState::STATE_CREATED: {
m_data->errorString.clear();
return true;
diff --git a/launcher/minecraft/auth/AccountTask.h b/launcher/minecraft/auth/AccountTask.h
index 1bd6c59f..68bbfe5f 100644
--- a/launcher/minecraft/auth/AccountTask.h
+++ b/launcher/minecraft/auth/AccountTask.h
@@ -37,10 +37,10 @@
#include <tasks/Task.h>
-#include <QString>
+#include <qsslerror.h>
#include <QJsonObject>
+#include <QString>
#include <QTimer>
-#include <qsslerror.h>
#include "MinecraftAccount.h"
@@ -50,37 +50,32 @@ class QNetworkReply;
* Enum for describing the state of the current task.
* Used by the getStateMessage function to determine what the status message should be.
*/
-enum class AccountTaskState
-{
+enum class AccountTaskState {
STATE_CREATED,
STATE_WORKING,
STATE_SUCCEEDED,
- STATE_DISABLED, //!< MSA Client ID has changed. Tell user to reloginn
- STATE_FAILED_SOFT, //!< soft failure. authentication went through partially
- STATE_FAILED_HARD, //!< hard failure. main tokens are invalid
- STATE_FAILED_GONE, //!< hard failure. main tokens are invalid, and the account no longer exists
- STATE_OFFLINE //!< soft failure. authentication failed in the first step in a 'soft' way
+ STATE_DISABLED, //!< MSA Client ID has changed. Tell user to reloginn
+ STATE_FAILED_SOFT, //!< soft failure. authentication went through partially
+ STATE_FAILED_HARD, //!< hard failure. main tokens are invalid
+ STATE_FAILED_GONE, //!< hard failure. main tokens are invalid, and the account no longer exists
+ STATE_OFFLINE //!< soft failure. authentication failed in the first step in a 'soft' way
};
-class AccountTask : public Task
-{
+class AccountTask : public Task {
Q_OBJECT
-public:
- explicit AccountTask(AccountData * data, QObject *parent = 0);
- virtual ~AccountTask() {};
+ public:
+ explicit AccountTask(AccountData* data, QObject* parent = 0);
+ virtual ~AccountTask(){};
AccountTaskState m_taskState = AccountTaskState::STATE_CREATED;
- AccountTaskState taskState() {
- return m_taskState;
- }
+ AccountTaskState taskState() { return m_taskState; }
-signals:
- void showVerificationUriAndCode(const QUrl &uri, const QString &code, int expiresIn);
+ signals:
+ void showVerificationUriAndCode(const QUrl& uri, const QString& code, int expiresIn);
void hideVerificationUriAndCode();
-protected:
-
+ protected:
/**
* Returns the state message for the given state.
* Used to set the status message for the task.
@@ -88,10 +83,10 @@ protected:
*/
virtual QString getStateMessage() const;
-protected slots:
+ protected slots:
// NOTE: true -> non-terminal state, false -> terminal state
bool changeState(AccountTaskState newState, QString reason = QString());
-protected:
- AccountData *m_data = nullptr;
+ protected:
+ AccountData* m_data = nullptr;
};
diff --git a/launcher/minecraft/auth/AuthRequest.cpp b/launcher/minecraft/auth/AuthRequest.cpp
index a21634b7..bd48a059 100644
--- a/launcher/minecraft/auth/AuthRequest.cpp
+++ b/launcher/minecraft/auth/AuthRequest.cpp
@@ -35,44 +35,44 @@
#include <cassert>
+#include <QBuffer>
#include <QDebug>
#include <QTimer>
-#include <QBuffer>
#include <QUrlQuery>
#include "Application.h"
#include "AuthRequest.h"
#include "katabasis/Globals.h"
-AuthRequest::AuthRequest(QObject *parent): QObject(parent) {
-}
+AuthRequest::AuthRequest(QObject* parent) : QObject(parent) {}
-AuthRequest::~AuthRequest() {
-}
+AuthRequest::~AuthRequest() {}
-void AuthRequest::get(const QNetworkRequest &req, int timeout/* = 60*1000*/) {
+void AuthRequest::get(const QNetworkRequest& req, int timeout /* = 60*1000*/)
+{
setup(req, QNetworkAccessManager::GetOperation);
reply_ = APPLICATION->network()->get(request_);
status_ = Requesting;
timedReplies_.add(new Katabasis::Reply(reply_, timeout));
-#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) // QNetworkReply::errorOccurred added in 5.15
+#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) // QNetworkReply::errorOccurred added in 5.15
connect(reply_, &QNetworkReply::errorOccurred, this, &AuthRequest::onRequestError);
-#else // &QNetworkReply::error SIGNAL depricated
+#else // &QNetworkReply::error SIGNAL depricated
connect(reply_, QOverload<QNetworkReply::NetworkError>::of(&QNetworkReply::error), this, &AuthRequest::onRequestError);
#endif
connect(reply_, &QNetworkReply::finished, this, &AuthRequest::onRequestFinished);
connect(reply_, &QNetworkReply::sslErrors, this, &AuthRequest::onSslErrors);
}
-void AuthRequest::post(const QNetworkRequest &req, const QByteArray &data, int timeout/* = 60*1000*/) {
+void AuthRequest::post(const QNetworkRequest& req, const QByteArray& data, int timeout /* = 60*1000*/)
+{
setup(req, QNetworkAccessManager::PostOperation);
data_ = data;
status_ = Requesting;
reply_ = APPLICATION->network()->post(request_, data_);
timedReplies_.add(new Katabasis::Reply(reply_, timeout));
-#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) // QNetworkReply::errorOccurred added in 5.15
+#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) // QNetworkReply::errorOccurred added in 5.15
connect(reply_, &QNetworkReply::errorOccurred, this, &AuthRequest::onRequestError);
-#else // &QNetworkReply::error SIGNAL depricated
+#else // &QNetworkReply::error SIGNAL depricated
connect(reply_, QOverload<QNetworkReply::NetworkError>::of(&QNetworkReply::error), this, &AuthRequest::onRequestError);
#endif
connect(reply_, &QNetworkReply::finished, this, &AuthRequest::onRequestFinished);
@@ -80,35 +80,39 @@ void AuthRequest::post(const QNetworkRequest &req, const QByteArray &data, int t
connect(reply_, &QNetworkReply::uploadProgress, this, &AuthRequest::onUploadProgress);
}
-void AuthRequest::onRequestFinished() {
+void AuthRequest::onRequestFinished()
+{
if (status_ == Idle) {
return;
}
- if (reply_ != qobject_cast<QNetworkReply *>(sender())) {
+ if (reply_ != qobject_cast<QNetworkReply*>(sender())) {
return;
}
httpStatus_ = reply_->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
finish();
}
-void AuthRequest::onRequestError(QNetworkReply::NetworkError error) {
+void AuthRequest::onRequestError(QNetworkReply::NetworkError error)
+{
qWarning() << "AuthRequest::onRequestError: Error" << (int)error;
if (status_ == Idle) {
return;
}
- if (reply_ != qobject_cast<QNetworkReply *>(sender())) {
+ if (reply_ != qobject_cast<QNetworkReply*>(sender())) {
return;
}
errorString_ = reply_->errorString();
httpStatus_ = reply_->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
error_ = error;
qWarning() << "AuthRequest::onRequestError: Error string: " << errorString_;
- qWarning() << "AuthRequest::onRequestError: HTTP status" << httpStatus_ << reply_->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString();
+ qWarning() << "AuthRequest::onRequestError: HTTP status" << httpStatus_
+ << reply_->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString();
// QTimer::singleShot(10, this, SLOT(finish()));
}
-void AuthRequest::onSslErrors(QList<QSslError> errors) {
+void AuthRequest::onSslErrors(QList<QSslError> errors)
+{
int i = 1;
for (auto error : errors) {
qCritical() << "LOGIN SSL Error #" << i << " : " << error.errorString();
@@ -118,23 +122,25 @@ void AuthRequest::onSslErrors(QList<QSslError> errors) {
}
}
-void AuthRequest::onUploadProgress(qint64 uploaded, qint64 total) {
+void AuthRequest::onUploadProgress(qint64 uploaded, qint64 total)
+{
if (status_ == Idle) {
qWarning() << "AuthRequest::onUploadProgress: No pending request";
return;
}
- if (reply_ != qobject_cast<QNetworkReply *>(sender())) {
+ if (reply_ != qobject_cast<QNetworkReply*>(sender())) {
return;
}
// Restart timeout because request in progress
- Katabasis::Reply *o2Reply = timedReplies_.find(reply_);
- if(o2Reply) {
+ Katabasis::Reply* o2Reply = timedReplies_.find(reply_);
+ if (o2Reply) {
o2Reply->start();
}
emit uploadProgress(uploaded, total);
}
-void AuthRequest::setup(const QNetworkRequest &req, QNetworkAccessManager::Operation operation, const QByteArray &verb) {
+void AuthRequest::setup(const QNetworkRequest& req, QNetworkAccessManager::Operation operation, const QByteArray& verb)
+{
request_ = req;
operation_ = operation;
url_ = req.url();
@@ -152,7 +158,8 @@ void AuthRequest::setup(const QNetworkRequest &req, QNetworkAccessManager::Opera
httpStatus_ = 0;
}
-void AuthRequest::finish() {
+void AuthRequest::finish()
+{
QByteArray data;
if (status_ == Idle) {
qWarning() << "AuthRequest::finish: No pending request";
diff --git a/launcher/minecraft/auth/AuthRequest.h b/launcher/minecraft/auth/AuthRequest.h
index 89f7a123..84d2a7d6 100644
--- a/launcher/minecraft/auth/AuthRequest.h
+++ b/launcher/minecraft/auth/AuthRequest.h
@@ -1,27 +1,26 @@
#pragma once
-#include <QObject>
-#include <QNetworkRequest>
-#include <QNetworkReply>
+#include <QByteArray>
#include <QNetworkAccessManager>
+#include <QNetworkReply>
+#include <QNetworkRequest>
+#include <QObject>
#include <QUrl>
-#include <QByteArray>
#include "katabasis/Reply.h"
/// Makes authentication requests.
-class AuthRequest: public QObject {
+class AuthRequest : public QObject {
Q_OBJECT
-public:
- explicit AuthRequest(QObject *parent = 0);
+ public:
+ explicit AuthRequest(QObject* parent = 0);
~AuthRequest();
-public slots:
- void get(const QNetworkRequest &req, int timeout = 60*1000);
- void post(const QNetworkRequest &req, const QByteArray &data, int timeout = 60*1000);
-
+ public slots:
+ void get(const QNetworkRequest& req, int timeout = 60 * 1000);
+ void post(const QNetworkRequest& req, const QByteArray& data, int timeout = 60 * 1000);
-signals:
+ signals:
/// Emitted when a request has been completed or failed.
void finished(QNetworkReply::NetworkError error, QByteArray data, QList<QNetworkReply::RawHeaderPair> headers);
@@ -29,7 +28,7 @@ signals:
/// Emitted when an upload has progressed.
void uploadProgress(qint64 bytesSent, qint64 bytesTotal);
-protected slots:
+ protected slots:
/// Handle request finished.
void onRequestFinished();
@@ -46,25 +45,23 @@ protected slots:
/// Handle upload progress.
void onUploadProgress(qint64 uploaded, qint64 total);
-public:
+ public:
QNetworkReply::NetworkError error_;
int httpStatus_ = 0;
QString errorString_;
-protected:
- void setup(const QNetworkRequest &request, QNetworkAccessManager::Operation operation, const QByteArray &verb = QByteArray());
+ protected:
+ void setup(const QNetworkRequest& request, QNetworkAccessManager::Operation operation, const QByteArray& verb = QByteArray());
- enum Status {
- Idle, Requesting, ReRequesting
- };
+ enum Status { Idle, Requesting, ReRequesting };
QNetworkRequest request_;
QByteArray data_;
- QNetworkReply *reply_;
+ QNetworkReply* reply_;
Status status_;
QNetworkAccessManager::Operation operation_;
QUrl url_;
Katabasis::ReplyList timedReplies_;
- QTimer *timer_;
+ QTimer* timer_;
};
diff --git a/launcher/minecraft/auth/AuthSession.cpp b/launcher/minecraft/auth/AuthSession.cpp
index 2c06beaa..37534f98 100644
--- a/launcher/minecraft/auth/AuthSession.cpp
+++ b/launcher/minecraft/auth/AuthSession.cpp
@@ -1,7 +1,7 @@
#include "AuthSession.h"
-#include <QJsonObject>
#include <QJsonArray>
#include <QJsonDocument>
+#include <QJsonObject>
#include <QStringList>
QString AuthSession::serializeUserProperties()
@@ -16,13 +16,11 @@ QString AuthSession::serializeUserProperties()
*/
QJsonDocument value(userAttrs);
return value.toJson(QJsonDocument::Compact);
-
}
bool AuthSession::MakeOffline(QString offline_playername)
{
- if (status != PlayableOffline && status != PlayableOnline)
- {
+ if (status != PlayableOffline && status != PlayableOnline) {
return false;
}
session = "-";
@@ -32,7 +30,8 @@ bool AuthSession::MakeOffline(QString offline_playername)
return true;
}
-void AuthSession::MakeDemo() {
+void AuthSession::MakeDemo()
+{
player_name = "Player";
demo = true;
}
diff --git a/launcher/minecraft/auth/AuthSession.h b/launcher/minecraft/auth/AuthSession.h
index a75df506..40519476 100644
--- a/launcher/minecraft/auth/AuthSession.h
+++ b/launcher/minecraft/auth/AuthSession.h
@@ -1,22 +1,20 @@
#pragma once
-#include <QString>
#include <QMultiMap>
+#include <QString>
#include <memory>
#include "QObjectPtr.h"
class MinecraftAccount;
class QNetworkAccessManager;
-struct AuthSession
-{
+struct AuthSession {
bool MakeOffline(QString offline_playername);
void MakeDemo();
QString serializeUserProperties();
- enum Status
- {
+ enum Status {
Undetermined,
RequiresOAuth,
RequiresPassword,
@@ -45,7 +43,7 @@ struct AuthSession
// Did the user request online mode?
bool wants_online = true;
- //Is this a demo session?
+ // Is this a demo session?
bool demo = false;
};
diff --git a/launcher/minecraft/auth/AuthStep.cpp b/launcher/minecraft/auth/AuthStep.cpp
index ffa2581b..6240cc54 100644
--- a/launcher/minecraft/auth/AuthStep.cpp
+++ b/launcher/minecraft/auth/AuthStep.cpp
@@ -1,7 +1,5 @@
#include "AuthStep.h"
-AuthStep::AuthStep(AccountData *data) : QObject(nullptr), m_data(data) {
-}
+AuthStep::AuthStep(AccountData* data) : QObject(nullptr), m_data(data) {}
AuthStep::~AuthStep() noexcept = default;
-
diff --git a/launcher/minecraft/auth/AuthStep.h b/launcher/minecraft/auth/AuthStep.h
index 2a8dc2ca..becd9b0c 100644
--- a/launcher/minecraft/auth/AuthStep.h
+++ b/launcher/minecraft/auth/AuthStep.h
@@ -1,33 +1,33 @@
#pragma once
-#include <QObject>
#include <QList>
#include <QNetworkReply>
+#include <QObject>
+#include "AccountTask.h"
#include "QObjectPtr.h"
#include "minecraft/auth/AccountData.h"
-#include "AccountTask.h"
class AuthStep : public QObject {
Q_OBJECT
-public:
+ public:
using Ptr = shared_qobject_ptr<AuthStep>;
-public:
- explicit AuthStep(AccountData *data);
+ public:
+ explicit AuthStep(AccountData* data);
virtual ~AuthStep() noexcept;
virtual QString describe() = 0;
-public slots:
+ public slots:
virtual void perform() = 0;
virtual void rehydrate() = 0;
-signals:
+ signals:
void finished(AccountTaskState resultingState, QString message);
- void showVerificationUriAndCode(const QUrl &uri, const QString &code, int expiresIn);
+ void showVerificationUriAndCode(const QUrl& uri, const QString& code, int expiresIn);
void hideVerificationUriAndCode();
-protected:
- AccountData *m_data;
+ protected:
+ AccountData* m_data;
};
diff --git a/launcher/minecraft/auth/MinecraftAccount.cpp b/launcher/minecraft/auth/MinecraftAccount.cpp
index 5d279af1..e8422a6f 100644
--- a/launcher/minecraft/auth/MinecraftAccount.cpp
+++ b/launcher/minecraft/auth/MinecraftAccount.cpp
@@ -38,12 +38,12 @@
#include "MinecraftAccount.h"
#include <QCryptographicHash>
-#include <QUuid>
-#include <QJsonObject>
#include <QJsonArray>
+#include <QJsonDocument>
+#include <QJsonObject>
#include <QRegularExpression>
#include <QStringList>
-#include <QJsonDocument>
+#include <QUuid>
#include <QDebug>
@@ -53,28 +53,30 @@
#include "flows/Mojang.h"
#include "flows/Offline.h"
-MinecraftAccount::MinecraftAccount(QObject* parent) : QObject(parent) {
+MinecraftAccount::MinecraftAccount(QObject* parent) : QObject(parent)
+{
data.internalId = QUuid::createUuid().toString().remove(QRegularExpression("[{}-]"));
}
-
-MinecraftAccountPtr MinecraftAccount::loadFromJsonV2(const QJsonObject& json) {
+MinecraftAccountPtr MinecraftAccount::loadFromJsonV2(const QJsonObject& json)
+{
MinecraftAccountPtr account(new MinecraftAccount());
- if(account->data.resumeStateFromV2(json)) {
+ if (account->data.resumeStateFromV2(json)) {
return account;
}
return nullptr;
}
-MinecraftAccountPtr MinecraftAccount::loadFromJsonV3(const QJsonObject& json) {
+MinecraftAccountPtr MinecraftAccount::loadFromJsonV3(const QJsonObject& json)
+{
MinecraftAccountPtr account(new MinecraftAccount());
- if(account->data.resumeStateFromV3(json)) {
+ if (account->data.resumeStateFromV3(json)) {
return account;
}
return nullptr;
}
-MinecraftAccountPtr MinecraftAccount::createFromUsername(const QString &username)
+MinecraftAccountPtr MinecraftAccount::createFromUsername(const QString& username)
{
auto account = makeShared<MinecraftAccount>();
account->data.type = AccountType::Mojang;
@@ -90,7 +92,7 @@ MinecraftAccountPtr MinecraftAccount::createBlankMSA()
return account;
}
-MinecraftAccountPtr MinecraftAccount::createOffline(const QString &username)
+MinecraftAccountPtr MinecraftAccount::createOffline(const QString& username)
{
auto account = makeShared<MinecraftAccount>();
account->data.type = AccountType::Offline;
@@ -107,19 +109,20 @@ MinecraftAccountPtr MinecraftAccount::createOffline(const QString &username)
return account;
}
-
QJsonObject MinecraftAccount::saveToJson() const
{
return data.saveState();
}
-AccountState MinecraftAccount::accountState() const {
+AccountState MinecraftAccount::accountState() const
+{
return data.accountState;
}
-QPixmap MinecraftAccount::getFace() const {
+QPixmap MinecraftAccount::getFace() const
+{
QPixmap skinTexture;
- if(!skinTexture.loadFromData(data.minecraftProfile.skin.data, "PNG")) {
+ if (!skinTexture.loadFromData(data.minecraftProfile.skin.data, "PNG")) {
return QPixmap();
}
QPixmap skin = QPixmap(8, 8);
@@ -129,67 +132,68 @@ QPixmap MinecraftAccount::getFace() const {
return skin.scaled(64, 64, Qt::KeepAspectRatio);
}
-
-shared_qobject_ptr<AccountTask> MinecraftAccount::login(QString password) {
+shared_qobject_ptr<AccountTask> MinecraftAccount::login(QString password)
+{
Q_ASSERT(m_currentTask.get() == nullptr);
m_currentTask.reset(new MojangLogin(&data, password));
connect(m_currentTask.get(), &Task::succeeded, this, &MinecraftAccount::authSucceeded);
connect(m_currentTask.get(), &Task::failed, this, &MinecraftAccount::authFailed);
- connect(m_currentTask.get(), &Task::aborted, this, [this]{ authFailed(tr("Aborted")); });
+ connect(m_currentTask.get(), &Task::aborted, this, [this] { authFailed(tr("Aborted")); });
emit activityChanged(true);
return m_currentTask;
}
-shared_qobject_ptr<AccountTask> MinecraftAccount::loginMSA() {
+shared_qobject_ptr<AccountTask> MinecraftAccount::loginMSA()
+{
Q_ASSERT(m_currentTask.get() == nullptr);
m_currentTask.reset(new MSAInteractive(&data));
connect(m_currentTask.get(), &Task::succeeded, this, &MinecraftAccount::authSucceeded);
connect(m_currentTask.get(), &Task::failed, this, &MinecraftAccount::authFailed);
- connect(m_currentTask.get(), &Task::aborted, this, [this]{ authFailed(tr("Aborted")); });
+ connect(m_currentTask.get(), &Task::aborted, this, [this] { authFailed(tr("Aborted")); });
emit activityChanged(true);
return m_currentTask;
}
-shared_qobject_ptr<AccountTask> MinecraftAccount::loginOffline() {
+shared_qobject_ptr<AccountTask> MinecraftAccount::loginOffline()
+{
Q_ASSERT(m_currentTask.get() == nullptr);
m_currentTask.reset(new OfflineLogin(&data));
connect(m_currentTask.get(), &Task::succeeded, this, &MinecraftAccount::authSucceeded);
connect(m_currentTask.get(), &Task::failed, this, &MinecraftAccount::authFailed);
- connect(m_currentTask.get(), &Task::aborted, this, [this]{ authFailed(tr("Aborted")); });
+ connect(m_currentTask.get(), &Task::aborted, this, [this] { authFailed(tr("Aborted")); });
emit activityChanged(true);
return m_currentTask;
}
-shared_qobject_ptr<AccountTask> MinecraftAccount::refresh() {
- if(m_currentTask) {
+shared_qobject_ptr<AccountTask> MinecraftAccount::refresh()
+{
+ if (m_currentTask) {
return m_currentTask;
}
- if(data.type == AccountType::MSA) {
+ if (data.type == AccountType::MSA) {
m_currentTask.reset(new MSASilent(&data));
- }
- else if(data.type == AccountType::Offline) {
+ } else if (data.type == AccountType::Offline) {
m_currentTask.reset(new OfflineRefresh(&data));
- }
- else {
+ } else {
m_currentTask.reset(new MojangRefresh(&data));
}
connect(m_currentTask.get(), &Task::succeeded, this, &MinecraftAccount::authSucceeded);
connect(m_currentTask.get(), &Task::failed, this, &MinecraftAccount::authFailed);
- connect(m_currentTask.get(), &Task::aborted, this, [this]{ authFailed(tr("Aborted")); });
+ connect(m_currentTask.get(), &Task::aborted, this, [this] { authFailed(tr("Aborted")); });
emit activityChanged(true);
return m_currentTask;
}
-shared_qobject_ptr<AccountTask> MinecraftAccount::currentTask() {
+shared_qobject_ptr<AccountTask> MinecraftAccount::currentTask()
+{
return m_currentTask;
}
-
void MinecraftAccount::authSucceeded()
{
m_currentTask.reset();
@@ -206,28 +210,24 @@ void MinecraftAccount::authFailed(QString reason)
}
case AccountTaskState::STATE_FAILED_SOFT: {
// NOTE: this doesn't do much. There was an error of some sort.
- }
- break;
+ } break;
case AccountTaskState::STATE_FAILED_HARD: {
- if(isMSA()) {
+ if (isMSA()) {
data.msaToken.token = QString();
data.msaToken.refresh_token = QString();
data.msaToken.validity = Katabasis::Validity::None;
data.validity_ = Katabasis::Validity::None;
- }
- else {
+ } else {
data.yggdrasilToken.token = QString();
data.yggdrasilToken.validity = Katabasis::Validity::None;
data.validity_ = Katabasis::Validity::None;
}
emit changed();
- }
- break;
+ } break;
case AccountTaskState::STATE_FAILED_GONE: {
data.validity_ = Katabasis::Validity::None;
emit changed();
- }
- break;
+ } break;
case AccountTaskState::STATE_CREATED:
case AccountTaskState::STATE_WORKING:
case AccountTaskState::STATE_SUCCEEDED: {
@@ -238,21 +238,23 @@ void MinecraftAccount::authFailed(QString reason)
emit activityChanged(false);
}
-bool MinecraftAccount::isActive() const {
+bool MinecraftAccount::isActive() const
+{
return !m_currentTask.isNull();
}
-bool MinecraftAccount::shouldRefresh() const {
+bool MinecraftAccount::shouldRefresh() const
+{
/*
* Never refresh accounts that are being used by the game, it breaks the game session.
* Always refresh accounts that have not been refreshed yet during this session.
* Don't refresh broken accounts.
* Refresh accounts that would expire in the next 12 hours (fresh token validity is 24 hours).
*/
- if(isInUse()) {
+ if (isInUse()) {
return false;
}
- switch(data.validity_) {
+ switch (data.validity_) {
case Katabasis::Validity::Certain: {
break;
}
@@ -267,7 +269,7 @@ bool MinecraftAccount::shouldRefresh() const {
auto issuedTimestamp = data.yggdrasilToken.issueInstant;
auto expiresTimestamp = data.yggdrasilToken.notAfter;
- if(!expiresTimestamp.isValid()) {
+ if (!expiresTimestamp.isValid()) {
expiresTimestamp = issuedTimestamp.addSecs(24 * 3600);
}
if (now.secsTo(expiresTimestamp) < (12 * 3600)) {
@@ -278,14 +280,12 @@ bool MinecraftAccount::shouldRefresh() const {
void MinecraftAccount::fillSession(AuthSessionPtr session)
{
- if(ownsMinecraft() && !hasProfile()) {
+ if (ownsMinecraft() && !hasProfile()) {
session->status = AuthSession::RequiresProfileSetup;
- }
- else {
- if(session->wants_online) {
+ } else {
+ if (session->wants_online) {
session->status = AuthSession::PlayableOnline;
- }
- else {
+ } else {
session->status = AuthSession::PlayableOffline;
}
}
@@ -303,12 +303,9 @@ void MinecraftAccount::fillSession(AuthSessionPtr session)
session->uuid = data.profileId();
// 'legacy' or 'mojang', depending on account type
session->user_type = typeString();
- if (!session->access_token.isEmpty())
- {
+ if (!session->access_token.isEmpty()) {
session->session = "token:" + data.accessToken() + ":" + data.profileId();
- }
- else
- {
+ } else {
session->session = "-";
}
}
@@ -316,8 +313,7 @@ void MinecraftAccount::fillSession(AuthSessionPtr session)
void MinecraftAccount::decrementUses()
{
Usable::decrementUses();
- if(!isInUse())
- {
+ if (!isInUse()) {
emit changed();
// FIXME: we now need a better way to identify accounts...
qWarning() << "Profile" << data.profileId() << "is no longer in use.";
@@ -328,39 +324,31 @@ void MinecraftAccount::incrementUses()
{
bool wasInUse = isInUse();
Usable::incrementUses();
- if(!wasInUse)
- {
+ if (!wasInUse) {
emit changed();
// FIXME: we now need a better way to identify accounts...
qWarning() << "Profile" << data.profileId() << "is now in use.";
}
}
-QUuid MinecraftAccount::uuidFromUsername(QString username) {
+QUuid MinecraftAccount::uuidFromUsername(QString username)
+{
auto input = QString("OfflinePlayer:%1").arg(username).toUtf8();
// basically a reimplementation of Java's UUID#nameUUIDFromBytes
QByteArray digest = QCryptographicHash::hash(input, QCryptographicHash::Md5);
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
- auto bOr = [](QByteArray& array, int index, char value) {
- array[index] = array.at(index) | value;
- };
- auto bAnd = [](QByteArray& array, int index, char value) {
- array[index] = array.at(index) & value;
- };
+ auto bOr = [](QByteArray& array, int index, char value) { array[index] = array.at(index) | value; };
+ auto bAnd = [](QByteArray& array, int index, char value) { array[index] = array.at(index) & value; };
#else
- auto bOr = [](QByteArray& array, qsizetype index, char value) {
- array[index] |= value;
- };
- auto bAnd = [](QByteArray& array, qsizetype index, char value) {
- array[index] &= value;
- };
+ auto bOr = [](QByteArray& array, qsizetype index, char value) { array[index] |= value; };
+ auto bAnd = [](QByteArray& array, qsizetype index, char value) { array[index] &= value; };
#endif
- bAnd(digest, 6, (char) 0x0f); // clear version
- bOr(digest, 6, (char) 0x30); // set to version 3
- bAnd(digest, 8, (char) 0x3f); // clear variant
- bOr(digest, 8, (char) 0x80); // set to IETF variant
+ bAnd(digest, 6, (char)0x0f); // clear version
+ bOr(digest, 6, (char)0x30); // set to version 3
+ bAnd(digest, 8, (char)0x3f); // clear variant
+ bOr(digest, 8, (char)0x80); // set to IETF variant
return QUuid::fromRfc4122(digest);
}
diff --git a/launcher/minecraft/auth/MinecraftAccount.h b/launcher/minecraft/auth/MinecraftAccount.h
index 67623a5a..395ca549 100644
--- a/launcher/minecraft/auth/MinecraftAccount.h
+++ b/launcher/minecraft/auth/MinecraftAccount.h
@@ -35,20 +35,20 @@
#pragma once
-#include <QObject>
-#include <QString>
-#include <QList>
#include <QJsonObject>
-#include <QPair>
+#include <QList>
#include <QMap>
+#include <QObject>
+#include <QPair>
#include <QPixmap>
+#include <QString>
#include <memory>
-#include "AuthSession.h"
-#include "Usable.h"
#include "AccountData.h"
+#include "AuthSession.h"
#include "QObjectPtr.h"
+#include "Usable.h"
class Task;
class AccountTask;
@@ -64,8 +64,7 @@ Q_DECLARE_METATYPE(MinecraftAccountPtr)
* but we might as well add some things for it in Prism Launcher right now so
* we don't have to rip the code to pieces to add it later.
*/
-struct AccountProfile
-{
+struct AccountProfile {
QString id;
QString name;
bool legacy;
@@ -77,34 +76,30 @@ struct AccountProfile
* Said information may include things such as that account's username, client token, and access
* token if the user chose to stay logged in.
*/
-class MinecraftAccount :
- public QObject,
- public Usable
-{
+class MinecraftAccount : public QObject, public Usable {
Q_OBJECT
-public: /* construction */
+ public: /* construction */
//! Do not copy accounts. ever.
- explicit MinecraftAccount(const MinecraftAccount &other, QObject *parent) = delete;
+ explicit MinecraftAccount(const MinecraftAccount& other, QObject* parent) = delete;
//! Default constructor
- explicit MinecraftAccount(QObject *parent = 0);
+ explicit MinecraftAccount(QObject* parent = 0);
- static MinecraftAccountPtr createFromUsername(const QString &username);
+ static MinecraftAccountPtr createFromUsername(const QString& username);
static MinecraftAccountPtr createBlankMSA();
- static MinecraftAccountPtr createOffline(const QString &username);
+ static MinecraftAccountPtr createOffline(const QString& username);
- static MinecraftAccountPtr loadFromJsonV2(const QJsonObject &json);
- static MinecraftAccountPtr loadFromJsonV3(const QJsonObject &json);
+ static MinecraftAccountPtr loadFromJsonV2(const QJsonObject& json);
+ static MinecraftAccountPtr loadFromJsonV3(const QJsonObject& json);
static QUuid uuidFromUsername(QString username);
//! Saves a MinecraftAccount to a JSON object and returns it.
QJsonObject saveToJson() const;
-public: /* manipulation */
-
+ 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.
@@ -119,70 +114,46 @@ public: /* manipulation */
shared_qobject_ptr<AccountTask> currentTask();
-public: /* queries */
- QString internalId() const {
- return data.internalId;
- }
+ public: /* queries */
+ QString internalId() const { return data.internalId; }
- QString accountDisplayString() const {
- return data.accountDisplayString();
- }
+ QString accountDisplayString() const { return data.accountDisplayString(); }
- QString mojangUserName() const {
- return data.userName();
- }
+ QString mojangUserName() const { return data.userName(); }
- QString accessToken() const {
- return data.accessToken();
- }
+ QString accessToken() const { return data.accessToken(); }
- QString profileId() const {
- return data.profileId();
- }
+ QString profileId() const { return data.profileId(); }
- QString profileName() const {
- return data.profileName();
- }
+ QString profileName() const { return data.profileName(); }
bool isActive() const;
- bool canMigrate() const {
- return data.canMigrateToMSA;
- }
+ bool canMigrate() const { return data.canMigrateToMSA; }
- bool isMSA() const {
- return data.type == AccountType::MSA;
- }
+ bool isMSA() const { return data.type == AccountType::MSA; }
- bool isOffline() const {
- return data.type == AccountType::Offline;
- }
+ bool isOffline() const { return data.type == AccountType::Offline; }
- bool ownsMinecraft() const {
- return data.minecraftEntitlement.ownsMinecraft;
- }
+ bool ownsMinecraft() const { return data.minecraftEntitlement.ownsMinecraft; }
- bool hasProfile() const {
- return data.profileId().size() != 0;
- }
+ bool hasProfile() const { return data.profileId().size() != 0; }
- QString typeString() const {
- switch(data.type) {
+ QString typeString() const
+ {
+ switch (data.type) {
case AccountType::Mojang: {
- if(data.legacy) {
+ if (data.legacy) {
return "legacy";
}
return "mojang";
- }
- break;
+ } break;
case AccountType::MSA: {
return "msa";
- }
- break;
+ } break;
case AccountType::Offline: {
return "offline";
- }
- break;
+ } break;
default: {
return "unknown";
}
@@ -194,19 +165,15 @@ public: /* queries */
//! Returns the current state of the account
AccountState accountState() const;
- AccountData * accountData() {
- return &data;
- }
+ AccountData* accountData() { return &data; }
bool shouldRefresh() const;
void fillSession(AuthSessionPtr session);
- QString lastError() const {
- return data.lastError();
- }
+ QString lastError() const { return data.lastError(); }
-signals:
+ signals:
/**
* This signal is emitted when the account changes
*/
@@ -216,20 +183,17 @@ signals:
// TODO: better signalling for the various possible state changes - especially errors
-protected: /* variables */
+ protected: /* variables */
AccountData data;
// current task we are executing here
shared_qobject_ptr<AccountTask> m_currentTask;
-protected: /* methods */
-
+ protected: /* methods */
void incrementUses() override;
void decrementUses() override;
-private
-slots:
+ private slots:
void authSucceeded();
void authFailed(QString reason);
};
-
diff --git a/launcher/minecraft/auth/Parsers.cpp b/launcher/minecraft/auth/Parsers.cpp
index f3d9ad56..8dbe446a 100644
--- a/launcher/minecraft/auth/Parsers.cpp
+++ b/launcher/minecraft/auth/Parsers.cpp
@@ -2,46 +2,51 @@
#include "Json.h"
#include "Logging.h"
-#include <QJsonDocument>
-#include <QJsonArray>
#include <QDebug>
+#include <QJsonArray>
+#include <QJsonDocument>
namespace Parsers {
-bool getDateTime(QJsonValue value, QDateTime & out) {
- if(!value.isString()) {
+bool getDateTime(QJsonValue value, QDateTime& out)
+{
+ if (!value.isString()) {
return false;
}
out = QDateTime::fromString(value.toString(), Qt::ISODate);
return out.isValid();
}
-bool getString(QJsonValue value, QString & out) {
- if(!value.isString()) {
+bool getString(QJsonValue value, QString& out)
+{
+ if (!value.isString()) {
return false;
}
out = value.toString();
return true;
}
-bool getNumber(QJsonValue value, double & out) {
- if(!value.isDouble()) {
+bool getNumber(QJsonValue value, double& out)
+{
+ if (!value.isDouble()) {
return false;
}
out = value.toDouble();
return true;
}
-bool getNumber(QJsonValue value, int64_t & out) {
- if(!value.isDouble()) {
+bool getNumber(QJsonValue value, int64_t& out)
+{
+ if (!value.isDouble()) {
return false;
}
- out = (int64_t) value.toDouble();
+ out = (int64_t)value.toDouble();
return true;
}
-bool getBool(QJsonValue value, bool & out) {
- if(!value.isBool()) {
+bool getBool(QJsonValue value, bool& out)
+{
+ if (!value.isBool()) {
return false;
}
out = value.toBool();
@@ -74,49 +79,50 @@ bool getBool(QJsonValue value, bool & out) {
// 2148916238 = child account not linked to a family
*/
-bool parseXTokenResponse(QByteArray & data, Katabasis::Token &output, QString name) {
- qDebug() << "Parsing" << name <<":";
+bool parseXTokenResponse(QByteArray& data, Katabasis::Token& output, QString name)
+{
+ qDebug() << "Parsing" << name << ":";
qCDebug(authCredentials()) << data;
QJsonParseError jsonError;
QJsonDocument doc = QJsonDocument::fromJson(data, &jsonError);
- if(jsonError.error) {
+ if (jsonError.error) {
qWarning() << "Failed to parse response from user.auth.xboxlive.com as JSON: " << jsonError.errorString();
return false;
}
auto obj = doc.object();
- if(!getDateTime(obj.value("IssueInstant"), output.issueInstant)) {
+ if (!getDateTime(obj.value("IssueInstant"), output.issueInstant)) {
qWarning() << "User IssueInstant is not a timestamp";
return false;
}
- if(!getDateTime(obj.value("NotAfter"), output.notAfter)) {
+ if (!getDateTime(obj.value("NotAfter"), output.notAfter)) {
qWarning() << "User NotAfter is not a timestamp";
return false;
}
- if(!getString(obj.value("Token"), output.token)) {
+ if (!getString(obj.value("Token"), output.token)) {
qWarning() << "User Token is not a string";
return false;
}
auto arrayVal = obj.value("DisplayClaims").toObject().value("xui");
- if(!arrayVal.isArray()) {
+ if (!arrayVal.isArray()) {
qWarning() << "Missing xui claims array";
return false;
}
bool foundUHS = false;
- for(auto item: arrayVal.toArray()) {
- if(!item.isObject()) {
+ for (auto item : arrayVal.toArray()) {
+ if (!item.isObject()) {
continue;
}
auto obj = item.toObject();
- if(obj.contains("uhs")) {
+ if (obj.contains("uhs")) {
foundUHS = true;
} else {
continue;
}
// consume all 'display claims' ... whatever that means
- for(auto iter = obj.begin(); iter != obj.end(); iter++) {
+ for (auto iter = obj.begin(); iter != obj.end(); iter++) {
QString claim;
- if(!getString(obj.value(iter.key()), claim)) {
+ if (!getString(obj.value(iter.key()), claim)) {
qWarning() << "display claim " << iter.key() << " is not a string...";
return false;
}
@@ -125,7 +131,7 @@ bool parseXTokenResponse(QByteArray & data, Katabasis::Token &output, QString na
break;
}
- if(!foundUHS) {
+ if (!foundUHS) {
qWarning() << "Missing uhs";
return false;
}
@@ -134,46 +140,47 @@ bool parseXTokenResponse(QByteArray & data, Katabasis::Token &output, QString na
return true;
}
-bool parseMinecraftProfile(QByteArray & data, MinecraftProfile &output) {
+bool parseMinecraftProfile(QByteArray& data, MinecraftProfile& output)
+{
qDebug() << "Parsing Minecraft profile...";
qCDebug(authCredentials()) << data;
QJsonParseError jsonError;
QJsonDocument doc = QJsonDocument::fromJson(data, &jsonError);
- if(jsonError.error) {
+ if (jsonError.error) {
qWarning() << "Failed to parse response from user.auth.xboxlive.com as JSON: " << jsonError.errorString();
return false;
}
auto obj = doc.object();
- if(!getString(obj.value("id"), output.id)) {
+ if (!getString(obj.value("id"), output.id)) {
qWarning() << "Minecraft profile id is not a string";
return false;
}
- if(!getString(obj.value("name"), output.name)) {
+ if (!getString(obj.value("name"), output.name)) {
qWarning() << "Minecraft profile name is not a string";
return false;
}
auto skinsArray = obj.value("skins").toArray();
- for(auto skin: skinsArray) {
+ for (auto skin : skinsArray) {
auto skinObj = skin.toObject();
Skin skinOut;
- if(!getString(skinObj.value("id"), skinOut.id)) {
+ if (!getString(skinObj.value("id"), skinOut.id)) {
continue;
}
QString state;
- if(!getString(skinObj.value("state"), state)) {
+ if (!getString(skinObj.value("state"), state)) {
continue;
}
- if(state != "ACTIVE") {
+ if (state != "ACTIVE") {
continue;
}
- if(!getString(skinObj.value("url"), skinOut.url)) {
+ if (!getString(skinObj.value("url"), skinOut.url)) {
continue;
}
- if(!getString(skinObj.value("variant"), skinOut.variant)) {
+ if (!getString(skinObj.value("variant"), skinOut.variant)) {
continue;
}
// we deal with only the active skin
@@ -183,23 +190,23 @@ bool parseMinecraftProfile(QByteArray & data, MinecraftProfile &output) {
auto capesArray = obj.value("capes").toArray();
QString currentCape;
- for(auto cape: capesArray) {
+ for (auto cape : capesArray) {
auto capeObj = cape.toObject();
Cape capeOut;
- if(!getString(capeObj.value("id"), capeOut.id)) {
+ if (!getString(capeObj.value("id"), capeOut.id)) {
continue;
}
QString state;
- if(!getString(capeObj.value("state"), state)) {
+ if (!getString(capeObj.value("state"), state)) {
continue;
}
- if(state == "ACTIVE") {
+ if (state == "ACTIVE") {
currentCape = capeOut.id;
}
- if(!getString(capeObj.value("url"), capeOut.url)) {
+ if (!getString(capeObj.value("url"), capeOut.url)) {
continue;
}
- if(!getString(capeObj.value("alias"), capeOut.alias)) {
+ if (!getString(capeObj.value("alias"), capeOut.alias)) {
continue;
}
@@ -211,30 +218,33 @@ bool parseMinecraftProfile(QByteArray & data, MinecraftProfile &output) {
}
namespace {
- // these skin URLs are for the MHF_Steve and MHF_Alex accounts (made by a Mojang employee)
- // they are needed because the session server doesn't return skin urls for default skins
- static const QString SKIN_URL_STEVE = "http://textures.minecraft.net/texture/1a4af718455d4aab528e7a61f86fa25e6a369d1768dcb13f7df319a713eb810b";
- static const QString SKIN_URL_ALEX = "http://textures.minecraft.net/texture/83cee5ca6afcdb171285aa00e8049c297b2dbeba0efb8ff970a5677a1b644032";
-
- bool isDefaultModelSteve(QString uuid) {
- // need to calculate *Java* hashCode of UUID
- // if number is even, skin/model is steve, otherwise it is alex
-
- // just in case dashes are in the id
- uuid.remove('-');
+// these skin URLs are for the MHF_Steve and MHF_Alex accounts (made by a Mojang employee)
+// they are needed because the session server doesn't return skin urls for default skins
+static const QString SKIN_URL_STEVE =
+ "http://textures.minecraft.net/texture/1a4af718455d4aab528e7a61f86fa25e6a369d1768dcb13f7df319a713eb810b";
+static const QString SKIN_URL_ALEX =
+ "http://textures.minecraft.net/texture/83cee5ca6afcdb171285aa00e8049c297b2dbeba0efb8ff970a5677a1b644032";
+
+bool isDefaultModelSteve(QString uuid)
+{
+ // need to calculate *Java* hashCode of UUID
+ // if number is even, skin/model is steve, otherwise it is alex
- if (uuid.size() != 32) {
- return true;
- }
+ // just in case dashes are in the id
+ uuid.remove('-');
- // qulonglong is guaranteed to be 64 bits
- // we need to use unsigned numbers to guarantee truncation below
- qulonglong most = uuid.left(16).toULongLong(nullptr, 16);
- qulonglong least = uuid.right(16).toULongLong(nullptr, 16);
- qulonglong xored = most ^ least;
- return ((static_cast<quint32>(xored >> 32)) ^ static_cast<quint32>(xored)) % 2 == 0;
+ if (uuid.size() != 32) {
+ return true;
}
+
+ // qulonglong is guaranteed to be 64 bits
+ // we need to use unsigned numbers to guarantee truncation below
+ qulonglong most = uuid.left(16).toULongLong(nullptr, 16);
+ qulonglong least = uuid.right(16).toULongLong(nullptr, 16);
+ qulonglong xored = most ^ least;
+ return ((static_cast<quint32>(xored >> 32)) ^ static_cast<quint32>(xored)) % 2 == 0;
}
+} // namespace
/**
Uses session server for skin/cape lookup instead of profile,
@@ -270,31 +280,32 @@ decoded base64 "value":
}
*/
-bool parseMinecraftProfileMojang(QByteArray & data, MinecraftProfile &output) {
+bool parseMinecraftProfileMojang(QByteArray& data, MinecraftProfile& output)
+{
qDebug() << "Parsing Minecraft profile...";
qCDebug(authCredentials()) << data;
QJsonParseError jsonError;
QJsonDocument doc = QJsonDocument::fromJson(data, &jsonError);
- if(jsonError.error) {
+ if (jsonError.error) {
qWarning() << "Failed to parse response as JSON: " << jsonError.errorString();
return false;
}
auto obj = Json::requireObject(doc, "mojang minecraft profile");
- if(!getString(obj.value("id"), output.id)) {
+ if (!getString(obj.value("id"), output.id)) {
qWarning() << "Minecraft profile id is not a string";
return false;
}
- if(!getString(obj.value("name"), output.name)) {
+ if (!getString(obj.value("name"), output.name)) {
qWarning() << "Minecraft profile name is not a string";
return false;
}
auto propsArray = obj.value("properties").toArray();
QByteArray texturePayload;
- for( auto p : propsArray) {
+ for (auto p : propsArray) {
auto pObj = p.toObject();
auto name = pObj.value("name");
if (!name.isString() || name.toString() != "textures") {
@@ -321,7 +332,7 @@ bool parseMinecraftProfileMojang(QByteArray & data, MinecraftProfile &output) {
}
doc = QJsonDocument::fromJson(texturePayload, &jsonError);
- if(jsonError.error) {
+ if (jsonError.error) {
qWarning() << "Failed to parse response as JSON: " << jsonError.errorString();
return false;
}
@@ -357,8 +368,7 @@ bool parseMinecraftProfileMojang(QByteArray & data, MinecraftProfile &output) {
// might not be present
getString(meta.value("model"), skinOut.variant);
}
- }
- else if (idx.key() == "CAPE") {
+ } else if (idx.key() == "CAPE") {
auto cape = idx->toObject();
if (!getString(cape.value("url"), capeOut.url)) {
qWarning() << "Cape url is not a string";
@@ -374,7 +384,7 @@ bool parseMinecraftProfileMojang(QByteArray & data, MinecraftProfile &output) {
output.skin = skinOut;
if (capeOut.alias == "cape") {
- output.capes = QMap<QString, Cape>({{capeOut.alias, capeOut}});
+ output.capes = QMap<QString, Cape>({ { capeOut.alias, capeOut } });
output.currentCape = capeOut.alias;
}
@@ -382,13 +392,14 @@ bool parseMinecraftProfileMojang(QByteArray & data, MinecraftProfile &output) {
return true;
}
-bool parseMinecraftEntitlements(QByteArray & data, MinecraftEntitlement &output) {
+bool parseMinecraftEntitlements(QByteArray& data, MinecraftEntitlement& output)
+{
qDebug() << "Parsing Minecraft entitlements...";
qCDebug(authCredentials()) << data;
QJsonParseError jsonError;
QJsonDocument doc = QJsonDocument::fromJson(data, &jsonError);
- if(jsonError.error) {
+ if (jsonError.error) {
qWarning() << "Failed to parse response from user.auth.xboxlive.com as JSON: " << jsonError.errorString();
return false;
}
@@ -398,16 +409,16 @@ bool parseMinecraftEntitlements(QByteArray & data, MinecraftEntitlement &output)
output.ownsMinecraft = false;
auto itemsArray = obj.value("items").toArray();
- for(auto item: itemsArray) {
+ for (auto item : itemsArray) {
auto itemObj = item.toObject();
QString name;
- if(!getString(itemObj.value("name"), name)) {
+ if (!getString(itemObj.value("name"), name)) {
continue;
}
- if(name == "game_minecraft") {
+ if (name == "game_minecraft") {
output.canPlayMinecraft = true;
}
- if(name == "product_minecraft") {
+ if (name == "product_minecraft") {
output.ownsMinecraft = true;
}
}
@@ -415,47 +426,50 @@ bool parseMinecraftEntitlements(QByteArray & data, MinecraftEntitlement &output)
return true;
}
-bool parseRolloutResponse(QByteArray & data, bool& result) {
+bool parseRolloutResponse(QByteArray& data, bool& result)
+{
qDebug() << "Parsing Rollout response...";
qCDebug(authCredentials()) << data;
QJsonParseError jsonError;
QJsonDocument doc = QJsonDocument::fromJson(data, &jsonError);
- if(jsonError.error) {
- qWarning() << "Failed to parse response from https://api.minecraftservices.com/rollout/v1/msamigration as JSON: " << jsonError.errorString();
+ if (jsonError.error) {
+ qWarning() << "Failed to parse response from https://api.minecraftservices.com/rollout/v1/msamigration as JSON: "
+ << jsonError.errorString();
return false;
}
auto obj = doc.object();
QString feature;
- if(!getString(obj.value("feature"), feature)) {
+ if (!getString(obj.value("feature"), feature)) {
qWarning() << "Rollout feature is not a string";
return false;
}
- if(feature != "msamigration") {
+ if (feature != "msamigration") {
qWarning() << "Rollout feature is not what we expected (msamigration), but is instead \"" << feature << "\"";
return false;
}
- if(!getBool(obj.value("rollout"), result)) {
+ if (!getBool(obj.value("rollout"), result)) {
qWarning() << "Rollout feature is not a string";
return false;
}
return true;
}
-bool parseMojangResponse(QByteArray & data, Katabasis::Token &output) {
+bool parseMojangResponse(QByteArray& data, Katabasis::Token& output)
+{
QJsonParseError jsonError;
qDebug() << "Parsing Mojang response...";
qCDebug(authCredentials()) << data;
QJsonDocument doc = QJsonDocument::fromJson(data, &jsonError);
- if(jsonError.error) {
+ if (jsonError.error) {
qWarning() << "Failed to parse response from api.minecraftservices.com/launcher/login as JSON: " << jsonError.errorString();
return false;
}
auto obj = doc.object();
double expires_in = 0;
- if(!getNumber(obj.value("expires_in"), expires_in)) {
+ if (!getNumber(obj.value("expires_in"), expires_in)) {
qWarning() << "expires_in is not a valid number";
return false;
}
@@ -464,13 +478,13 @@ bool parseMojangResponse(QByteArray & data, Katabasis::Token &output) {
output.notAfter = currentTime.addSecs(expires_in);
QString username;
- if(!getString(obj.value("username"), username)) {
+ if (!getString(obj.value("username"), username)) {
qWarning() << "username is not valid";
return false;
}
// TODO: it's a JWT... validate it?
- if(!getString(obj.value("access_token"), output.token)) {
+ if (!getString(obj.value("access_token"), output.token)) {
qWarning() << "access_token is not valid";
return false;
}
@@ -479,4 +493,4 @@ bool parseMojangResponse(QByteArray & data, Katabasis::Token &output) {
return true;
}
-}
+} // namespace Parsers
diff --git a/launcher/minecraft/auth/Parsers.h b/launcher/minecraft/auth/Parsers.h
index 2666d890..d073f999 100644
--- a/launcher/minecraft/auth/Parsers.h
+++ b/launcher/minecraft/auth/Parsers.h
@@ -2,19 +2,18 @@
#include "AccountData.h"
-namespace Parsers
-{
- bool getDateTime(QJsonValue value, QDateTime & out);
- bool getString(QJsonValue value, QString & out);
- bool getNumber(QJsonValue value, double & out);
- bool getNumber(QJsonValue value, int64_t & out);
- bool getBool(QJsonValue value, bool & out);
+namespace Parsers {
+bool getDateTime(QJsonValue value, QDateTime& out);
+bool getString(QJsonValue value, QString& out);
+bool getNumber(QJsonValue value, double& out);
+bool getNumber(QJsonValue value, int64_t& out);
+bool getBool(QJsonValue value, bool& out);
- bool parseXTokenResponse(QByteArray &data, Katabasis::Token &output, QString name);
- bool parseMojangResponse(QByteArray &data, Katabasis::Token &output);
+bool parseXTokenResponse(QByteArray& data, Katabasis::Token& output, QString name);
+bool parseMojangResponse(QByteArray& data, Katabasis::Token& output);
- bool parseMinecraftProfile(QByteArray &data, MinecraftProfile &output);
- bool parseMinecraftProfileMojang(QByteArray &data, MinecraftProfile &output);
- bool parseMinecraftEntitlements(QByteArray &data, MinecraftEntitlement &output);
- bool parseRolloutResponse(QByteArray &data, bool& result);
-}
+bool parseMinecraftProfile(QByteArray& data, MinecraftProfile& output);
+bool parseMinecraftProfileMojang(QByteArray& data, MinecraftProfile& output);
+bool parseMinecraftEntitlements(QByteArray& data, MinecraftEntitlement& output);
+bool parseRolloutResponse(QByteArray& data, bool& result);
+} // namespace Parsers
diff --git a/launcher/minecraft/auth/Yggdrasil.cpp b/launcher/minecraft/auth/Yggdrasil.cpp
index d3e7ccdd..97f2a78d 100644
--- a/launcher/minecraft/auth/Yggdrasil.cpp
+++ b/launcher/minecraft/auth/Yggdrasil.cpp
@@ -16,24 +16,24 @@
#include "Yggdrasil.h"
#include "AccountData.h"
-#include <QObject>
-#include <QString>
-#include <QJsonObject>
+#include <QByteArray>
#include <QJsonDocument>
+#include <QJsonObject>
#include <QNetworkReply>
-#include <QByteArray>
+#include <QObject>
+#include <QString>
#include <QDebug>
#include "Application.h"
-Yggdrasil::Yggdrasil(AccountData *data, QObject *parent)
- : AccountTask(data, parent)
+Yggdrasil::Yggdrasil(AccountData* data, QObject* parent) : AccountTask(data, parent)
{
changeState(AccountTaskState::STATE_CREATED);
}
-void Yggdrasil::sendRequest(QUrl endpoint, QByteArray content) {
+void Yggdrasil::sendRequest(QUrl endpoint, QByteArray content)
+{
changeState(AccountTaskState::STATE_WORKING);
QNetworkRequest netRequest(endpoint);
@@ -52,10 +52,10 @@ void Yggdrasil::sendRequest(QUrl endpoint, QByteArray content) {
connect(&counter, &QTimer::timeout, this, &Yggdrasil::heartbeat);
}
-void Yggdrasil::executeTask() {
-}
+void Yggdrasil::executeTask() {}
-void Yggdrasil::refresh() {
+void Yggdrasil::refresh()
+{
start();
/*
* {
@@ -90,7 +90,8 @@ void Yggdrasil::refresh() {
sendRequest(reqUrl, requestData);
}
-void Yggdrasil::login(QString password) {
+void Yggdrasil::login(QString password)
+{
start();
/*
* {
@@ -136,20 +137,21 @@ void Yggdrasil::login(QString password) {
sendRequest(reqUrl, requestData);
}
-
-
-void Yggdrasil::refreshTimers(qint64, qint64) {
+void Yggdrasil::refreshTimers(qint64, qint64)
+{
timeout_keeper.stop();
timeout_keeper.start(timeout_max);
progress(count = 0, timeout_max);
}
-void Yggdrasil::heartbeat() {
+void Yggdrasil::heartbeat()
+{
count += time_step;
progress(count, timeout_max);
}
-bool Yggdrasil::abort() {
+bool Yggdrasil::abort()
+{
progress(timeout_max, timeout_max);
// TODO: actually use this in a meaningful way
m_aborted = Yggdrasil::BY_USER;
@@ -157,14 +159,16 @@ bool Yggdrasil::abort() {
return true;
}
-void Yggdrasil::abortByTimeout() {
+void Yggdrasil::abortByTimeout()
+{
progress(timeout_max, timeout_max);
// TODO: actually use this in a meaningful way
m_aborted = Yggdrasil::BY_TIMEOUT;
m_netReply->abort();
}
-void Yggdrasil::sslErrors(QList<QSslError> errors) {
+void Yggdrasil::sslErrors(QList<QSslError> errors)
+{
int i = 1;
for (auto error : errors) {
qCritical() << "LOGIN SSL Error #" << i << " : " << error.errorString();
@@ -174,7 +178,8 @@ void Yggdrasil::sslErrors(QList<QSslError> errors) {
}
}
-void Yggdrasil::processResponse(QJsonObject responseData) {
+void Yggdrasil::processResponse(QJsonObject responseData)
+{
// Read the response data. We need to get the client token, access token, and the selected
// profile.
qDebug() << "Processing authentication response.";
@@ -188,11 +193,11 @@ void Yggdrasil::processResponse(QJsonObject responseData) {
changeState(AccountTaskState::STATE_FAILED_HARD, tr("Authentication server didn't send a client token."));
return;
}
- if(m_data->clientToken().isEmpty()) {
+ if (m_data->clientToken().isEmpty()) {
m_data->setClientToken(clientToken);
- }
- else if(clientToken != m_data->clientToken()) {
- changeState(AccountTaskState::STATE_FAILED_HARD, tr("Authentication server attempted to change the client token. This isn't supported."));
+ } else if (clientToken != m_data->clientToken()) {
+ changeState(AccountTaskState::STATE_FAILED_HARD,
+ tr("Authentication server attempted to change the client token. This isn't supported."));
return;
}
@@ -220,8 +225,7 @@ void Yggdrasil::processResponse(QJsonObject responseData) {
for (auto i = profileObj.constBegin(); i != profileObj.constEnd(); ++i) {
if (i.key() == "name" && i.value().isString()) {
m_data->minecraftProfile.name = i->toString();
- }
- else if (i.key() == "id" && i.value().isString()) {
+ } else if (i.key() == "id" && i.value().isString()) {
m_data->minecraftProfile.id = i->toString();
}
}
@@ -237,50 +241,43 @@ void Yggdrasil::processResponse(QJsonObject responseData) {
changeState(AccountTaskState::STATE_SUCCEEDED);
}
-void Yggdrasil::processReply() {
+void Yggdrasil::processReply()
+{
changeState(AccountTaskState::STATE_WORKING);
- switch (m_netReply->error())
- {
- case QNetworkReply::NoError:
- break;
- case QNetworkReply::TimeoutError:
- changeState(AccountTaskState::STATE_FAILED_SOFT, tr("Authentication operation timed out."));
- return;
- case QNetworkReply::OperationCanceledError:
- changeState(AccountTaskState::STATE_FAILED_SOFT, tr("Authentication operation cancelled."));
- return;
- case QNetworkReply::SslHandshakeFailedError:
- changeState(
- AccountTaskState::STATE_FAILED_SOFT,
- tr(
- "<b>SSL Handshake failed.</b><br/>There might be a few causes for it:<br/>"
- "<ul>"
- "<li>You use Windows and need to update your root certificates, please install any outstanding updates.</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 log file for details</li>"
- "</ul>"
- )
- );
- return;
- // used for invalid credentials and similar errors. Fall through.
- case QNetworkReply::ContentAccessDenied:
- case QNetworkReply::ContentOperationNotPermittedError:
- break;
- case QNetworkReply::ContentGoneError: {
- changeState(
- AccountTaskState::STATE_FAILED_GONE,
- tr("The Mojang account no longer exists. It may have been migrated to a Microsoft account.")
- );
- return;
- }
- default:
- changeState(
- AccountTaskState::STATE_FAILED_SOFT,
- tr("Authentication operation failed due to a network error: %1 (%2)").arg(m_netReply->errorString()).arg(m_netReply->error())
- );
- return;
+ switch (m_netReply->error()) {
+ case QNetworkReply::NoError:
+ break;
+ case QNetworkReply::TimeoutError:
+ changeState(AccountTaskState::STATE_FAILED_SOFT, tr("Authentication operation timed out."));
+ return;
+ case QNetworkReply::OperationCanceledError:
+ changeState(AccountTaskState::STATE_FAILED_SOFT, tr("Authentication operation cancelled."));
+ return;
+ case QNetworkReply::SslHandshakeFailedError:
+ changeState(AccountTaskState::STATE_FAILED_SOFT,
+ tr("<b>SSL Handshake failed.</b><br/>There might be a few causes for it:<br/>"
+ "<ul>"
+ "<li>You use Windows and need to update your root certificates, please install any outstanding updates.</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 log file for details</li>"
+ "</ul>"));
+ return;
+ // used for invalid credentials and similar errors. Fall through.
+ case QNetworkReply::ContentAccessDenied:
+ case QNetworkReply::ContentOperationNotPermittedError:
+ break;
+ case QNetworkReply::ContentGoneError: {
+ changeState(AccountTaskState::STATE_FAILED_GONE,
+ tr("The Mojang account no longer exists. It may have been migrated to a Microsoft account."));
+ return;
+ }
+ default:
+ changeState(AccountTaskState::STATE_FAILED_SOFT, tr("Authentication operation failed due to a network error: %1 (%2)")
+ .arg(m_netReply->errorString())
+ .arg(m_netReply->error()));
+ return;
}
// Try to parse the response regardless of the response code.
@@ -299,12 +296,11 @@ void Yggdrasil::processReply() {
if (jsonError.error == QJsonParseError::NoError || replyData.size() == 0) {
processResponse(replyData.size() > 0 ? doc.object() : QJsonObject());
return;
- }
- else {
- changeState(
- AccountTaskState::STATE_FAILED_SOFT,
- tr("Failed to parse authentication server response JSON response: %1 at offset %2.").arg(jsonError.errorString()).arg(jsonError.offset)
- );
+ } else {
+ changeState(AccountTaskState::STATE_FAILED_SOFT,
+ tr("Failed to parse authentication server response JSON response: %1 at offset %2.")
+ .arg(jsonError.errorString())
+ .arg(jsonError.offset));
qCritical() << replyData;
}
return;
@@ -320,34 +316,26 @@ void Yggdrasil::processReply() {
// stuff there.
qDebug() << "The request failed, but the server gave us an error message. Processing error.";
processError(doc.object());
- }
- else {
+ } else {
// The server didn't say anything regarding the error. Give the user an unknown
// error.
qDebug() << "The request failed and the server gave no error message. Unknown error.";
changeState(
AccountTaskState::STATE_FAILED_SOFT,
- tr("An unknown error occurred when trying to communicate with the authentication server: %1").arg(m_netReply->errorString())
- );
+ tr("An unknown error occurred when trying to communicate with the authentication server: %1").arg(m_netReply->errorString()));
}
}
-void Yggdrasil::processError(QJsonObject responseData) {
+void Yggdrasil::processError(QJsonObject responseData)
+{
QJsonValue errorVal = responseData.value("error");
QJsonValue errorMessageValue = responseData.value("errorMessage");
QJsonValue causeVal = responseData.value("cause");
if (errorVal.isString() && errorMessageValue.isString()) {
- m_error = std::shared_ptr<Error>(
- new Error {
- errorVal.toString(""),
- errorMessageValue.toString(""),
- causeVal.toString("")
- }
- );
+ m_error = std::shared_ptr<Error>(new Error{ errorVal.toString(""), errorMessageValue.toString(""), causeVal.toString("") });
changeState(AccountTaskState::STATE_FAILED_HARD, m_error->m_errorMessageVerbose);
- }
- else {
+ } else {
// Error is not in standard format. Don't set m_error and return unknown error.
changeState(AccountTaskState::STATE_FAILED_HARD, tr("An unknown Yggdrasil error occurred."));
}
diff --git a/launcher/minecraft/auth/Yggdrasil.h b/launcher/minecraft/auth/Yggdrasil.h
index 4f52a04c..560d7fb8 100644
--- a/launcher/minecraft/auth/Yggdrasil.h
+++ b/launcher/minecraft/auth/Yggdrasil.h
@@ -17,10 +17,10 @@
#include "AccountTask.h"
-#include <QString>
+#include <qsslerror.h>
#include <QJsonObject>
+#include <QString>
#include <QTimer>
-#include <qsslerror.h>
#include "MinecraftAccount.h"
@@ -30,35 +30,25 @@ class QNetworkReply;
/**
* A Yggdrasil task is a task that performs an operation on a given mojang account.
*/
-class Yggdrasil : public AccountTask
-{
+class Yggdrasil : public AccountTask {
Q_OBJECT
-public:
- explicit Yggdrasil(
- AccountData *data,
- QObject *parent = 0
- );
+ public:
+ explicit Yggdrasil(AccountData* data, QObject* parent = 0);
virtual ~Yggdrasil() = default;
void refresh();
void login(QString password);
- struct Error
- {
+ struct Error {
QString m_errorMessageShort;
QString m_errorMessageVerbose;
QString m_cause;
};
std::shared_ptr<Error> m_error;
- enum AbortedBy
- {
- BY_NOTHING,
- BY_USER,
- BY_TIMEOUT
- } m_aborted = BY_NOTHING;
+ enum AbortedBy { BY_NOTHING, BY_USER, BY_TIMEOUT } m_aborted = BY_NOTHING;
-protected:
+ protected:
void executeTask() override;
/**
@@ -78,24 +68,24 @@ protected:
*/
virtual void processError(QJsonObject responseData);
-protected slots:
+ protected slots:
void processReply();
void refreshTimers(qint64, qint64);
void heartbeat();
void sslErrors(QList<QSslError>);
void abortByTimeout();
-public slots:
+ public slots:
virtual bool abort() override;
-private:
+ private:
void sendRequest(QUrl endpoint, QByteArray content);
-protected:
- QNetworkReply *m_netReply = nullptr;
+ protected:
+ QNetworkReply* m_netReply = nullptr;
QTimer timeout_keeper;
QTimer counter;
- int count = 0; // num msec since time reset
+ int count = 0; // num msec since time reset
const int timeout_max = 30000;
const int time_step = 50;
diff --git a/launcher/minecraft/auth/flows/AuthFlow.cpp b/launcher/minecraft/auth/flows/AuthFlow.cpp
index 4f78e8c3..c51839a8 100644
--- a/launcher/minecraft/auth/flows/AuthFlow.cpp
+++ b/launcher/minecraft/auth/flows/AuthFlow.cpp
@@ -1,36 +1,33 @@
+#include <QDebug>
#include <QNetworkAccessManager>
-#include <QNetworkRequest>
#include <QNetworkReply>
-#include <QDebug>
+#include <QNetworkRequest>
#include "AuthFlow.h"
#include "katabasis/Globals.h"
#include <Application.h>
-AuthFlow::AuthFlow(AccountData * data, QObject *parent) :
- AccountTask(data, parent)
-{
-}
+AuthFlow::AuthFlow(AccountData* data, QObject* parent) : AccountTask(data, parent) {}
-void AuthFlow::succeed() {
+void AuthFlow::succeed()
+{
m_data->validity_ = Katabasis::Validity::Certain;
- changeState(
- AccountTaskState::STATE_SUCCEEDED,
- tr("Finished all authentication steps")
- );
+ changeState(AccountTaskState::STATE_SUCCEEDED, tr("Finished all authentication steps"));
}
-void AuthFlow::executeTask() {
- if(m_currentStep) {
+void AuthFlow::executeTask()
+{
+ if (m_currentStep) {
return;
}
changeState(AccountTaskState::STATE_WORKING, tr("Initializing"));
nextStep();
}
-void AuthFlow::nextStep() {
- if(m_steps.size() == 0) {
+void AuthFlow::nextStep()
+{
+ if (m_steps.size() == 0) {
// we got to the end without an incident... assume this is all.
m_currentStep.reset();
succeed();
@@ -46,15 +43,13 @@ void AuthFlow::nextStep() {
m_currentStep->perform();
}
-
-QString AuthFlow::getStateMessage() const {
- switch (m_taskState)
- {
+QString AuthFlow::getStateMessage() const
+{
+ switch (m_taskState) {
case AccountTaskState::STATE_WORKING: {
- if(m_currentStep) {
+ if (m_currentStep) {
return m_currentStep->describe();
- }
- else {
+ } else {
return tr("Working...");
}
}
@@ -64,8 +59,9 @@ QString AuthFlow::getStateMessage() const {
}
}
-void AuthFlow::stepFinished(AccountTaskState resultingState, QString message) {
- if(changeState(resultingState, message)) {
+void AuthFlow::stepFinished(AccountTaskState resultingState, QString message)
+{
+ if (changeState(resultingState, message)) {
nextStep();
}
}
diff --git a/launcher/minecraft/auth/flows/AuthFlow.h b/launcher/minecraft/auth/flows/AuthFlow.h
index e067cc99..c2c412ab 100644
--- a/launcher/minecraft/auth/flows/AuthFlow.h
+++ b/launcher/minecraft/auth/flows/AuthFlow.h
@@ -1,45 +1,42 @@
#pragma once
-#include <QObject>
+#include <QImage>
#include <QList>
-#include <QVector>
-#include <QSet>
#include <QNetworkReply>
-#include <QImage>
+#include <QObject>
+#include <QSet>
+#include <QVector>
#include <katabasis/DeviceFlow.h>
-#include "minecraft/auth/Yggdrasil.h"
#include "minecraft/auth/AccountData.h"
#include "minecraft/auth/AccountTask.h"
#include "minecraft/auth/AuthStep.h"
+#include "minecraft/auth/Yggdrasil.h"
-class AuthFlow : public AccountTask
-{
+class AuthFlow : public AccountTask {
Q_OBJECT
-public:
- explicit AuthFlow(AccountData * data, QObject *parent = 0);
+ public:
+ explicit AuthFlow(AccountData* data, QObject* parent = 0);
- Katabasis::Validity validity() {
- return m_data->validity_;
- };
+ Katabasis::Validity validity() { return m_data->validity_; };
QString getStateMessage() const override;
void executeTask() override;
-signals:
+ signals:
void activityChanged(Katabasis::Activity activity);
-private slots:
+ private slots:
void stepFinished(AccountTaskState resultingState, QString message);
-protected:
+ protected:
void succeed();
void nextStep();
-protected:
+ protected:
QList<AuthStep::Ptr> m_steps;
AuthStep::Ptr m_currentStep;
};
diff --git a/launcher/minecraft/auth/flows/MSA.cpp b/launcher/minecraft/auth/flows/MSA.cpp
index f1987e0c..f0399342 100644
--- a/launcher/minecraft/auth/flows/MSA.cpp
+++ b/launcher/minecraft/auth/flows/MSA.cpp
@@ -1,15 +1,16 @@
#include "MSA.h"
+#include "minecraft/auth/steps/EntitlementsStep.h"
+#include "minecraft/auth/steps/GetSkinStep.h"
+#include "minecraft/auth/steps/LauncherLoginStep.h"
#include "minecraft/auth/steps/MSAStep.h"
-#include "minecraft/auth/steps/XboxUserStep.h"
+#include "minecraft/auth/steps/MinecraftProfileStep.h"
#include "minecraft/auth/steps/XboxAuthorizationStep.h"
-#include "minecraft/auth/steps/LauncherLoginStep.h"
#include "minecraft/auth/steps/XboxProfileStep.h"
-#include "minecraft/auth/steps/EntitlementsStep.h"
-#include "minecraft/auth/steps/MinecraftProfileStep.h"
-#include "minecraft/auth/steps/GetSkinStep.h"
+#include "minecraft/auth/steps/XboxUserStep.h"
-MSASilent::MSASilent(AccountData* data, QObject* parent) : AuthFlow(data, parent) {
+MSASilent::MSASilent(AccountData* data, QObject* parent) : AuthFlow(data, parent)
+{
m_steps.append(makeShared<MSAStep>(m_data, MSAStep::Action::Refresh));
m_steps.append(makeShared<XboxUserStep>(m_data));
m_steps.append(makeShared<XboxAuthorizationStep>(m_data, &m_data->xboxApiToken, "http://xboxlive.com", "Xbox"));
@@ -21,10 +22,8 @@ MSASilent::MSASilent(AccountData* data, QObject* parent) : AuthFlow(data, parent
m_steps.append(makeShared<GetSkinStep>(m_data));
}
-MSAInteractive::MSAInteractive(
- AccountData* data,
- QObject* parent
-) : AuthFlow(data, parent) {
+MSAInteractive::MSAInteractive(AccountData* data, QObject* parent) : AuthFlow(data, parent)
+{
m_steps.append(makeShared<MSAStep>(m_data, MSAStep::Action::Login));
m_steps.append(makeShared<XboxUserStep>(m_data));
m_steps.append(makeShared<XboxAuthorizationStep>(m_data, &m_data->xboxApiToken, "http://xboxlive.com", "Xbox"));
diff --git a/launcher/minecraft/auth/flows/MSA.h b/launcher/minecraft/auth/flows/MSA.h
index 14a4ff43..e403d530 100644
--- a/launcher/minecraft/auth/flows/MSA.h
+++ b/launcher/minecraft/auth/flows/MSA.h
@@ -1,22 +1,14 @@
#pragma once
#include "AuthFlow.h"
-class MSAInteractive : public AuthFlow
-{
+class MSAInteractive : public AuthFlow {
Q_OBJECT
-public:
- explicit MSAInteractive(
- AccountData *data,
- QObject *parent = 0
- );
+ public:
+ explicit MSAInteractive(AccountData* data, QObject* parent = 0);
};
-class MSASilent : public AuthFlow
-{
+class MSASilent : public AuthFlow {
Q_OBJECT
-public:
- explicit MSASilent(
- AccountData * data,
- QObject *parent = 0
- );
+ public:
+ explicit MSASilent(AccountData* data, QObject* parent = 0);
};
diff --git a/launcher/minecraft/auth/flows/Mojang.cpp b/launcher/minecraft/auth/flows/Mojang.cpp
index 5900ea98..7e2db16f 100644
--- a/launcher/minecraft/auth/flows/Mojang.cpp
+++ b/launcher/minecraft/auth/flows/Mojang.cpp
@@ -1,25 +1,20 @@
#include "Mojang.h"
-#include "minecraft/auth/steps/YggdrasilStep.h"
-#include "minecraft/auth/steps/MinecraftProfileStepMojang.h"
-#include "minecraft/auth/steps/MigrationEligibilityStep.h"
#include "minecraft/auth/steps/GetSkinStep.h"
+#include "minecraft/auth/steps/MigrationEligibilityStep.h"
+#include "minecraft/auth/steps/MinecraftProfileStepMojang.h"
+#include "minecraft/auth/steps/YggdrasilStep.h"
-MojangRefresh::MojangRefresh(
- AccountData *data,
- QObject *parent
-) : AuthFlow(data, parent) {
+MojangRefresh::MojangRefresh(AccountData* data, QObject* parent) : AuthFlow(data, parent)
+{
m_steps.append(makeShared<YggdrasilStep>(m_data, QString()));
m_steps.append(makeShared<MinecraftProfileStepMojang>(m_data));
m_steps.append(makeShared<MigrationEligibilityStep>(m_data));
m_steps.append(makeShared<GetSkinStep>(m_data));
}
-MojangLogin::MojangLogin(
- AccountData *data,
- QString password,
- QObject *parent
-): AuthFlow(data, parent), m_password(password) {
+MojangLogin::MojangLogin(AccountData* data, QString password, QObject* parent) : AuthFlow(data, parent), m_password(password)
+{
m_steps.append(makeShared<YggdrasilStep>(m_data, m_password));
m_steps.append(makeShared<MinecraftProfileStepMojang>(m_data));
m_steps.append(makeShared<MigrationEligibilityStep>(m_data));
diff --git a/launcher/minecraft/auth/flows/Mojang.h b/launcher/minecraft/auth/flows/Mojang.h
index c09c81a8..779ca7e3 100644
--- a/launcher/minecraft/auth/flows/Mojang.h
+++ b/launcher/minecraft/auth/flows/Mojang.h
@@ -1,26 +1,17 @@
#pragma once
#include "AuthFlow.h"
-class MojangRefresh : public AuthFlow
-{
+class MojangRefresh : public AuthFlow {
Q_OBJECT
-public:
- explicit MojangRefresh(
- AccountData *data,
- QObject *parent = 0
- );
+ public:
+ explicit MojangRefresh(AccountData* data, QObject* parent = 0);
};
-class MojangLogin : public AuthFlow
-{
+class MojangLogin : public AuthFlow {
Q_OBJECT
-public:
- explicit MojangLogin(
- AccountData *data,
- QString password,
- QObject *parent = 0
- );
+ public:
+ explicit MojangLogin(AccountData* data, QString password, QObject* parent = 0);
-private:
+ private:
QString m_password;
};
diff --git a/launcher/minecraft/auth/flows/Offline.cpp b/launcher/minecraft/auth/flows/Offline.cpp
index d5c63271..3770b869 100644
--- a/launcher/minecraft/auth/flows/Offline.cpp
+++ b/launcher/minecraft/auth/flows/Offline.cpp
@@ -2,16 +2,12 @@
#include "minecraft/auth/steps/OfflineStep.h"
-OfflineRefresh::OfflineRefresh(
- AccountData *data,
- QObject *parent
-) : AuthFlow(data, parent) {
+OfflineRefresh::OfflineRefresh(AccountData* data, QObject* parent) : AuthFlow(data, parent)
+{
m_steps.append(makeShared<OfflineStep>(m_data));
}
-OfflineLogin::OfflineLogin(
- AccountData *data,
- QObject *parent
-) : AuthFlow(data, parent) {
+OfflineLogin::OfflineLogin(AccountData* data, QObject* parent) : AuthFlow(data, parent)
+{
m_steps.append(makeShared<OfflineStep>(m_data));
}
diff --git a/launcher/minecraft/auth/flows/Offline.h b/launcher/minecraft/auth/flows/Offline.h
index 5d1f83a4..2bc9c761 100644
--- a/launcher/minecraft/auth/flows/Offline.h
+++ b/launcher/minecraft/auth/flows/Offline.h
@@ -1,22 +1,14 @@
#pragma once
#include "AuthFlow.h"
-class OfflineRefresh : public AuthFlow
-{
+class OfflineRefresh : public AuthFlow {
Q_OBJECT
-public:
- explicit OfflineRefresh(
- AccountData *data,
- QObject *parent = 0
- );
+ public:
+ explicit OfflineRefresh(AccountData* data, QObject* parent = 0);
};
-class OfflineLogin : public AuthFlow
-{
+class OfflineLogin : public AuthFlow {
Q_OBJECT
-public:
- explicit OfflineLogin(
- AccountData *data,
- QObject *parent = 0
- );
+ public:
+ explicit OfflineLogin(AccountData* data, QObject* parent = 0);
};
diff --git a/launcher/minecraft/auth/steps/EntitlementsStep.cpp b/launcher/minecraft/auth/steps/EntitlementsStep.cpp
index bd604292..e942db52 100644
--- a/launcher/minecraft/auth/steps/EntitlementsStep.cpp
+++ b/launcher/minecraft/auth/steps/EntitlementsStep.cpp
@@ -11,12 +11,13 @@ EntitlementsStep::EntitlementsStep(AccountData* data) : AuthStep(data) {}
EntitlementsStep::~EntitlementsStep() noexcept = default;
-QString EntitlementsStep::describe() {
+QString EntitlementsStep::describe()
+{
return tr("Determining game ownership.");
}
-
-void EntitlementsStep::perform() {
+void EntitlementsStep::perform()
+{
auto uuid = QUuid::createUuid();
m_entitlementsRequestId = uuid.toString().remove('{').remove('}');
auto url = "https://api.minecraftservices.com/entitlements/license?requestId=" + m_entitlementsRequestId;
@@ -24,22 +25,20 @@ void EntitlementsStep::perform() {
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
request.setRawHeader("Accept", "application/json");
request.setRawHeader("Authorization", QString("Bearer %1").arg(m_data->yggdrasilToken.token).toUtf8());
- AuthRequest *requestor = new AuthRequest(this);
+ AuthRequest* requestor = new AuthRequest(this);
connect(requestor, &AuthRequest::finished, this, &EntitlementsStep::onRequestDone);
requestor->get(request);
qDebug() << "Getting entitlements...";
}
-void EntitlementsStep::rehydrate() {
+void EntitlementsStep::rehydrate()
+{
// NOOP, for now. We only save bools and there's nothing to check.
}
-void EntitlementsStep::onRequestDone(
- QNetworkReply::NetworkError error,
- QByteArray data,
- QList<QNetworkReply::RawHeaderPair> headers
-) {
- auto requestor = qobject_cast<AuthRequest *>(QObject::sender());
+void EntitlementsStep::onRequestDone(QNetworkReply::NetworkError error, QByteArray data, QList<QNetworkReply::RawHeaderPair> headers)
+{
+ auto requestor = qobject_cast<AuthRequest*>(QObject::sender());
requestor->deleteLater();
qCDebug(authCredentials()) << data;
diff --git a/launcher/minecraft/auth/steps/EntitlementsStep.h b/launcher/minecraft/auth/steps/EntitlementsStep.h
index 9412ae79..be16bda1 100644
--- a/launcher/minecraft/auth/steps/EntitlementsStep.h
+++ b/launcher/minecraft/auth/steps/EntitlementsStep.h
@@ -4,12 +4,11 @@
#include "QObjectPtr.h"
#include "minecraft/auth/AuthStep.h"
-
class EntitlementsStep : public AuthStep {
Q_OBJECT
-public:
- explicit EntitlementsStep(AccountData *data);
+ public:
+ explicit EntitlementsStep(AccountData* data);
virtual ~EntitlementsStep() noexcept;
void perform() override;
@@ -17,9 +16,9 @@ public:
QString describe() override;
-private slots:
+ private slots:
void onRequestDone(QNetworkReply::NetworkError, QByteArray, QList<QNetworkReply::RawHeaderPair>);
-private:
+ private:
QString m_entitlementsRequestId;
};
diff --git a/launcher/minecraft/auth/steps/GetSkinStep.cpp b/launcher/minecraft/auth/steps/GetSkinStep.cpp
index 3521f8dc..52087702 100644
--- a/launcher/minecraft/auth/steps/GetSkinStep.cpp
+++ b/launcher/minecraft/auth/steps/GetSkinStep.cpp
@@ -6,34 +6,32 @@
#include "minecraft/auth/AuthRequest.h"
#include "minecraft/auth/Parsers.h"
-GetSkinStep::GetSkinStep(AccountData* data) : AuthStep(data) {
-
-}
+GetSkinStep::GetSkinStep(AccountData* data) : AuthStep(data) {}
GetSkinStep::~GetSkinStep() noexcept = default;
-QString GetSkinStep::describe() {
+QString GetSkinStep::describe()
+{
return tr("Getting skin.");
}
-void GetSkinStep::perform() {
+void GetSkinStep::perform()
+{
auto url = QUrl(m_data->minecraftProfile.skin.url);
QNetworkRequest request = QNetworkRequest(url);
- AuthRequest *requestor = new AuthRequest(this);
+ AuthRequest* requestor = new AuthRequest(this);
connect(requestor, &AuthRequest::finished, this, &GetSkinStep::onRequestDone);
requestor->get(request);
}
-void GetSkinStep::rehydrate() {
+void GetSkinStep::rehydrate()
+{
// NOOP, for now.
}
-void GetSkinStep::onRequestDone(
- QNetworkReply::NetworkError error,
- QByteArray data,
- QList<QNetworkReply::RawHeaderPair> headers
-) {
- auto requestor = qobject_cast<AuthRequest *>(QObject::sender());
+void GetSkinStep::onRequestDone(QNetworkReply::NetworkError error, QByteArray data, QList<QNetworkReply::RawHeaderPair> headers)
+{
+ auto requestor = qobject_cast<AuthRequest*>(QObject::sender());
requestor->deleteLater();
if (error == QNetworkReply::NoError) {
diff --git a/launcher/minecraft/auth/steps/GetSkinStep.h b/launcher/minecraft/auth/steps/GetSkinStep.h
index 6b97371e..105e497d 100644
--- a/launcher/minecraft/auth/steps/GetSkinStep.h
+++ b/launcher/minecraft/auth/steps/GetSkinStep.h
@@ -4,12 +4,11 @@
#include "QObjectPtr.h"
#include "minecraft/auth/AuthStep.h"
-
class GetSkinStep : public AuthStep {
Q_OBJECT
-public:
- explicit GetSkinStep(AccountData *data);
+ public:
+ explicit GetSkinStep(AccountData* data);
virtual ~GetSkinStep() noexcept;
void perform() override;
@@ -17,6 +16,6 @@ public:
QString describe() override;
-private slots:
+ private slots:
void onRequestDone(QNetworkReply::NetworkError, QByteArray, QList<QNetworkReply::RawHeaderPair>);
};
diff --git a/launcher/minecraft/auth/steps/LauncherLoginStep.cpp b/launcher/minecraft/auth/steps/LauncherLoginStep.cpp
index 8a26cbe7..c57f5111 100644
--- a/launcher/minecraft/auth/steps/LauncherLoginStep.cpp
+++ b/launcher/minecraft/auth/steps/LauncherLoginStep.cpp
@@ -8,17 +8,17 @@
#include "minecraft/auth/Parsers.h"
#include "net/NetUtils.h"
-LauncherLoginStep::LauncherLoginStep(AccountData* data) : AuthStep(data) {
-
-}
+LauncherLoginStep::LauncherLoginStep(AccountData* data) : AuthStep(data) {}
LauncherLoginStep::~LauncherLoginStep() noexcept = default;
-QString LauncherLoginStep::describe() {
+QString LauncherLoginStep::describe()
+{
return tr("Accessing Mojang services.");
}
-void LauncherLoginStep::perform() {
+void LauncherLoginStep::perform()
+{
auto requestURL = "https://api.minecraftservices.com/launcher/login";
auto uhs = m_data->mojangservicesToken.extra["uhs"].toString();
auto xToken = m_data->mojangservicesToken.token;
@@ -34,22 +34,20 @@ void LauncherLoginStep::perform() {
QNetworkRequest request = QNetworkRequest(QUrl(requestURL));
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
request.setRawHeader("Accept", "application/json");
- AuthRequest *requestor = new AuthRequest(this);
+ AuthRequest* requestor = new AuthRequest(this);
connect(requestor, &AuthRequest::finished, this, &LauncherLoginStep::onRequestDone);
requestor->post(request, requestBody.toUtf8());
qDebug() << "Getting Minecraft access token...";
}
-void LauncherLoginStep::rehydrate() {
+void LauncherLoginStep::rehydrate()
+{
// TODO: check the token validity
}
-void LauncherLoginStep::onRequestDone(
- QNetworkReply::NetworkError error,
- QByteArray data,
- QList<QNetworkReply::RawHeaderPair> headers
-) {
- auto requestor = qobject_cast<AuthRequest *>(QObject::sender());
+void LauncherLoginStep::onRequestDone(QNetworkReply::NetworkError error, QByteArray data, QList<QNetworkReply::RawHeaderPair> headers)
+{
+ auto requestor = qobject_cast<AuthRequest*>(QObject::sender());
requestor->deleteLater();
qCDebug(authCredentials()) << data;
@@ -57,27 +55,17 @@ void LauncherLoginStep::onRequestDone(
qWarning() << "Reply error:" << error;
qCDebug(authCredentials()) << data;
if (Net::isApplicationError(error)) {
- emit finished(
- AccountTaskState::STATE_FAILED_SOFT,
- tr("Failed to get Minecraft access token: %1").arg(requestor->errorString_)
- );
- }
- else {
- emit finished(
- AccountTaskState::STATE_OFFLINE,
- tr("Failed to get Minecraft access token: %1").arg(requestor->errorString_)
- );
+ emit finished(AccountTaskState::STATE_FAILED_SOFT, tr("Failed to get Minecraft access token: %1").arg(requestor->errorString_));
+ } else {
+ emit finished(AccountTaskState::STATE_OFFLINE, tr("Failed to get Minecraft access token: %1").arg(requestor->errorString_));
}
return;
}
- if(!Parsers::parseMojangResponse(data, m_data->yggdrasilToken)) {
+ if (!Parsers::parseMojangResponse(data, m_data->yggdrasilToken)) {
qWarning() << "Could not parse login_with_xbox response...";
qCDebug(authCredentials()) << data;
- emit finished(
- AccountTaskState::STATE_FAILED_SOFT,
- tr("Failed to parse the Minecraft access token response.")
- );
+ emit finished(AccountTaskState::STATE_FAILED_SOFT, tr("Failed to parse the Minecraft access token response."));
return;
}
emit finished(AccountTaskState::STATE_WORKING, tr(""));
diff --git a/launcher/minecraft/auth/steps/LauncherLoginStep.h b/launcher/minecraft/auth/steps/LauncherLoginStep.h
index e06a306f..30c18e67 100644
--- a/launcher/minecraft/auth/steps/LauncherLoginStep.h
+++ b/launcher/minecraft/auth/steps/LauncherLoginStep.h
@@ -4,12 +4,11 @@
#include "QObjectPtr.h"
#include "minecraft/auth/AuthStep.h"
-
class LauncherLoginStep : public AuthStep {
Q_OBJECT
-public:
- explicit LauncherLoginStep(AccountData *data);
+ public:
+ explicit LauncherLoginStep(AccountData* data);
virtual ~LauncherLoginStep() noexcept;
void perform() override;
@@ -17,6 +16,6 @@ public:
QString describe() override;
-private slots:
+ private slots:
void onRequestDone(QNetworkReply::NetworkError, QByteArray, QList<QNetworkReply::RawHeaderPair>);
};
diff --git a/launcher/minecraft/auth/steps/MSAStep.cpp b/launcher/minecraft/auth/steps/MSAStep.cpp
index 6fc8d468..66a9a0e8 100644
--- a/launcher/minecraft/auth/steps/MSAStep.cpp
+++ b/launcher/minecraft/auth/steps/MSAStep.cpp
@@ -47,7 +47,8 @@
using OAuth2 = Katabasis::DeviceFlow;
using Activity = Katabasis::Activity;
-MSAStep::MSAStep(AccountData* data, Action action) : AuthStep(data), m_action(action) {
+MSAStep::MSAStep(AccountData* data, Action action) : AuthStep(data), m_action(action)
+{
m_clientId = APPLICATION->getMSAClientID();
OAuth2::Options opts;
opts.scope = "XboxLive.signin offline_access";
@@ -64,13 +65,14 @@ MSAStep::MSAStep(AccountData* data, Action action) : AuthStep(data), m_action(ac
MSAStep::~MSAStep() noexcept = default;
-QString MSAStep::describe() {
+QString MSAStep::describe()
+{
return tr("Logging in with Microsoft account.");
}
-
-void MSAStep::rehydrate() {
- switch(m_action) {
+void MSAStep::rehydrate()
+{
+ switch (m_action) {
case Refresh: {
// TODO: check the tokens and see if they are old (older than a day)
return;
@@ -82,12 +84,14 @@ void MSAStep::rehydrate() {
}
}
-void MSAStep::perform() {
- switch(m_action) {
+void MSAStep::perform()
+{
+ switch (m_action) {
case Refresh: {
if (m_data->msaClientID != m_clientId) {
emit hideVerificationUriAndCode();
- emit finished(AccountTaskState::STATE_DISABLED, tr("Microsoft user authentication failed - client identification has changed."));
+ emit finished(AccountTaskState::STATE_DISABLED,
+ tr("Microsoft user authentication failed - client identification has changed."));
}
m_oauth2->refresh();
return;
@@ -105,8 +109,9 @@ void MSAStep::perform() {
}
}
-void MSAStep::onOAuthActivityChanged(Katabasis::Activity activity) {
- switch(activity) {
+void MSAStep::onOAuthActivityChanged(Katabasis::Activity activity)
+{
+ switch (activity) {
case Katabasis::Activity::Idle:
case Katabasis::Activity::LoggingIn:
case Katabasis::Activity::Refreshing:
diff --git a/launcher/minecraft/auth/steps/MSAStep.h b/launcher/minecraft/auth/steps/MSAStep.h
index e9a1524e..fc070ff6 100644
--- a/launcher/minecraft/auth/steps/MSAStep.h
+++ b/launcher/minecraft/auth/steps/MSAStep.h
@@ -43,13 +43,11 @@
class MSAStep : public AuthStep {
Q_OBJECT
-public:
- enum Action {
- Refresh,
- Login
- };
-public:
- explicit MSAStep(AccountData *data, Action action);
+ public:
+ enum Action { Refresh, Login };
+
+ public:
+ explicit MSAStep(AccountData* data, Action action);
virtual ~MSAStep() noexcept;
void perform() override;
@@ -57,11 +55,11 @@ public:
QString describe() override;
-private slots:
+ private slots:
void onOAuthActivityChanged(Katabasis::Activity activity);
-private:
- Katabasis::DeviceFlow *m_oauth2 = nullptr;
+ private:
+ Katabasis::DeviceFlow* m_oauth2 = nullptr;
Action m_action;
QString m_clientId;
};
diff --git a/launcher/minecraft/auth/steps/MigrationEligibilityStep.cpp b/launcher/minecraft/auth/steps/MigrationEligibilityStep.cpp
index f5b5637a..5ce953df 100644
--- a/launcher/minecraft/auth/steps/MigrationEligibilityStep.cpp
+++ b/launcher/minecraft/auth/steps/MigrationEligibilityStep.cpp
@@ -5,37 +5,37 @@
#include "minecraft/auth/AuthRequest.h"
#include "minecraft/auth/Parsers.h"
-MigrationEligibilityStep::MigrationEligibilityStep(AccountData* data) : AuthStep(data) {
-
-}
+MigrationEligibilityStep::MigrationEligibilityStep(AccountData* data) : AuthStep(data) {}
MigrationEligibilityStep::~MigrationEligibilityStep() noexcept = default;
-QString MigrationEligibilityStep::describe() {
+QString MigrationEligibilityStep::describe()
+{
return tr("Checking for migration eligibility.");
}
-void MigrationEligibilityStep::perform() {
+void MigrationEligibilityStep::perform()
+{
auto url = QUrl("https://api.minecraftservices.com/rollout/v1/msamigration");
QNetworkRequest request = QNetworkRequest(url);
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
request.setRawHeader("Authorization", QString("Bearer %1").arg(m_data->yggdrasilToken.token).toUtf8());
- AuthRequest *requestor = new AuthRequest(this);
+ AuthRequest* requestor = new AuthRequest(this);
connect(requestor, &AuthRequest::finished, this, &MigrationEligibilityStep::onRequestDone);
requestor->get(request);
}
-void MigrationEligibilityStep::rehydrate() {
+void MigrationEligibilityStep::rehydrate()
+{
// NOOP, for now. We only save bools and there's nothing to check.
}
-void MigrationEligibilityStep::onRequestDone(
- QNetworkReply::NetworkError error,
- QByteArray data,
- QList<QNetworkReply::RawHeaderPair> headers
-) {
- auto requestor = qobject_cast<AuthRequest *>(QObject::sender());
+void MigrationEligibilityStep::onRequestDone(QNetworkReply::NetworkError error,
+ QByteArray data,
+ QList<QNetworkReply::RawHeaderPair> headers)
+{
+ auto requestor = qobject_cast<AuthRequest*>(QObject::sender());
requestor->deleteLater();
if (error == QNetworkReply::NoError) {
diff --git a/launcher/minecraft/auth/steps/MigrationEligibilityStep.h b/launcher/minecraft/auth/steps/MigrationEligibilityStep.h
index b1bf9cbf..8638975d 100644
--- a/launcher/minecraft/auth/steps/MigrationEligibilityStep.h
+++ b/launcher/minecraft/auth/steps/MigrationEligibilityStep.h
@@ -4,12 +4,11 @@
#include "QObjectPtr.h"
#include "minecraft/auth/AuthStep.h"
-
class MigrationEligibilityStep : public AuthStep {
Q_OBJECT
-public:
- explicit MigrationEligibilityStep(AccountData *data);
+ public:
+ explicit MigrationEligibilityStep(AccountData* data);
virtual ~MigrationEligibilityStep() noexcept;
void perform() override;
@@ -17,6 +16,6 @@ public:
QString describe() override;
-private slots:
+ private slots:
void onRequestDone(QNetworkReply::NetworkError, QByteArray, QList<QNetworkReply::RawHeaderPair>);
};
diff --git a/launcher/minecraft/auth/steps/MinecraftProfileStep.cpp b/launcher/minecraft/auth/steps/MinecraftProfileStep.cpp
index 6cfa7c1c..7cdce23f 100644
--- a/launcher/minecraft/auth/steps/MinecraftProfileStep.cpp
+++ b/launcher/minecraft/auth/steps/MinecraftProfileStep.cpp
@@ -7,52 +7,46 @@
#include "minecraft/auth/Parsers.h"
#include "net/NetUtils.h"
-MinecraftProfileStep::MinecraftProfileStep(AccountData* data) : AuthStep(data) {
-
-}
+MinecraftProfileStep::MinecraftProfileStep(AccountData* data) : AuthStep(data) {}
MinecraftProfileStep::~MinecraftProfileStep() noexcept = default;
-QString MinecraftProfileStep::describe() {
+QString MinecraftProfileStep::describe()
+{
return tr("Fetching the Minecraft profile.");
}
-
-void MinecraftProfileStep::perform() {
+void MinecraftProfileStep::perform()
+{
auto url = QUrl("https://api.minecraftservices.com/minecraft/profile");
QNetworkRequest request = QNetworkRequest(url);
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
request.setRawHeader("Authorization", QString("Bearer %1").arg(m_data->yggdrasilToken.token).toUtf8());
- AuthRequest *requestor = new AuthRequest(this);
+ AuthRequest* requestor = new AuthRequest(this);
connect(requestor, &AuthRequest::finished, this, &MinecraftProfileStep::onRequestDone);
requestor->get(request);
}
-void MinecraftProfileStep::rehydrate() {
+void MinecraftProfileStep::rehydrate()
+{
// NOOP, for now. We only save bools and there's nothing to check.
}
-void MinecraftProfileStep::onRequestDone(
- QNetworkReply::NetworkError error,
- QByteArray data,
- QList<QNetworkReply::RawHeaderPair> headers
-) {
- auto requestor = qobject_cast<AuthRequest *>(QObject::sender());
+void MinecraftProfileStep::onRequestDone(QNetworkReply::NetworkError error, QByteArray data, QList<QNetworkReply::RawHeaderPair> headers)
+{
+ auto requestor = qobject_cast<AuthRequest*>(QObject::sender());
requestor->deleteLater();
qCDebug(authCredentials()) << data;
if (error == QNetworkReply::ContentNotFoundError) {
// NOTE: Succeed even if we do not have a profile. This is a valid account state.
- if(m_data->type == AccountType::Mojang) {
+ if (m_data->type == AccountType::Mojang) {
m_data->minecraftEntitlement.canPlayMinecraft = false;
m_data->minecraftEntitlement.ownsMinecraft = false;
}
m_data->minecraftProfile = MinecraftProfile();
- emit finished(
- AccountTaskState::STATE_SUCCEEDED,
- tr("Account has no Minecraft profile.")
- );
+ emit finished(AccountTaskState::STATE_SUCCEEDED, tr("Account has no Minecraft profile."));
return;
}
if (error != QNetworkReply::NoError) {
@@ -65,35 +59,24 @@ void MinecraftProfileStep::onRequestDone(
qWarning() << QString::fromUtf8(data);
if (Net::isApplicationError(error)) {
- emit finished(
- AccountTaskState::STATE_FAILED_SOFT,
- tr("Minecraft Java profile acquisition failed: %1").arg(requestor->errorString_)
- );
- }
- else {
- emit finished(
- AccountTaskState::STATE_OFFLINE,
- tr("Minecraft Java profile acquisition failed: %1").arg(requestor->errorString_)
- );
+ emit finished(AccountTaskState::STATE_FAILED_SOFT,
+ tr("Minecraft Java profile acquisition failed: %1").arg(requestor->errorString_));
+ } else {
+ emit finished(AccountTaskState::STATE_OFFLINE,
+ tr("Minecraft Java profile acquisition failed: %1").arg(requestor->errorString_));
}
return;
}
- if(!Parsers::parseMinecraftProfile(data, m_data->minecraftProfile)) {
+ if (!Parsers::parseMinecraftProfile(data, m_data->minecraftProfile)) {
m_data->minecraftProfile = MinecraftProfile();
- emit finished(
- AccountTaskState::STATE_FAILED_SOFT,
- tr("Minecraft Java profile response could not be parsed")
- );
+ emit finished(AccountTaskState::STATE_FAILED_SOFT, tr("Minecraft Java profile response could not be parsed"));
return;
}
- if(m_data->type == AccountType::Mojang) {
+ if (m_data->type == AccountType::Mojang) {
auto validProfile = m_data->minecraftProfile.validity == Katabasis::Validity::Certain;
m_data->minecraftEntitlement.canPlayMinecraft = validProfile;
m_data->minecraftEntitlement.ownsMinecraft = validProfile;
}
- emit finished(
- AccountTaskState::STATE_WORKING,
- tr("Minecraft Java profile acquisition succeeded.")
- );
+ emit finished(AccountTaskState::STATE_WORKING, tr("Minecraft Java profile acquisition succeeded."));
}
diff --git a/launcher/minecraft/auth/steps/MinecraftProfileStep.h b/launcher/minecraft/auth/steps/MinecraftProfileStep.h
index 8ef3395c..cb30dab2 100644
--- a/launcher/minecraft/auth/steps/MinecraftProfileStep.h
+++ b/launcher/minecraft/auth/steps/MinecraftProfileStep.h
@@ -4,12 +4,11 @@
#include "QObjectPtr.h"
#include "minecraft/auth/AuthStep.h"
-
class MinecraftProfileStep : public AuthStep {
Q_OBJECT
-public:
- explicit MinecraftProfileStep(AccountData *data);
+ public:
+ explicit MinecraftProfileStep(AccountData* data);
virtual ~MinecraftProfileStep() noexcept;
void perform() override;
@@ -17,6 +16,6 @@ public:
QString describe() override;
-private slots:
+ private slots:
void onRequestDone(QNetworkReply::NetworkError, QByteArray, QList<QNetworkReply::RawHeaderPair>);
};
diff --git a/launcher/minecraft/auth/steps/MinecraftProfileStepMojang.cpp b/launcher/minecraft/auth/steps/MinecraftProfileStepMojang.cpp
index 8c378588..d035e39a 100644
--- a/launcher/minecraft/auth/steps/MinecraftProfileStepMojang.cpp
+++ b/launcher/minecraft/auth/steps/MinecraftProfileStepMojang.cpp
@@ -7,18 +7,17 @@
#include "minecraft/auth/Parsers.h"
#include "net/NetUtils.h"
-MinecraftProfileStepMojang::MinecraftProfileStepMojang(AccountData* data) : AuthStep(data) {
-
-}
+MinecraftProfileStepMojang::MinecraftProfileStepMojang(AccountData* data) : AuthStep(data) {}
MinecraftProfileStepMojang::~MinecraftProfileStepMojang() noexcept = default;
-QString MinecraftProfileStepMojang::describe() {
+QString MinecraftProfileStepMojang::describe()
+{
return tr("Fetching the Minecraft profile.");
}
-
-void MinecraftProfileStepMojang::perform() {
+void MinecraftProfileStepMojang::perform()
+{
if (m_data->minecraftProfile.id.isEmpty()) {
emit finished(AccountTaskState::STATE_FAILED_HARD, tr("A UUID is required to get the profile."));
return;
@@ -27,35 +26,32 @@ void MinecraftProfileStepMojang::perform() {
// use session server instead of profile due to profile endpoint being locked for locked Mojang accounts
QUrl url = QUrl("https://sessionserver.mojang.com/session/minecraft/profile/" + m_data->minecraftProfile.id);
QNetworkRequest req = QNetworkRequest(url);
- AuthRequest *request = new AuthRequest(this);
+ AuthRequest* request = new AuthRequest(this);
connect(request, &AuthRequest::finished, this, &MinecraftProfileStepMojang::onRequestDone);
request->get(req);
}
-void MinecraftProfileStepMojang::rehydrate() {
+void MinecraftProfileStepMojang::rehydrate()
+{
// NOOP, for now. We only save bools and there's nothing to check.
}
-void MinecraftProfileStepMojang::onRequestDone(
- QNetworkReply::NetworkError error,
- QByteArray data,
- QList<QNetworkReply::RawHeaderPair> headers
-) {
- auto requestor = qobject_cast<AuthRequest *>(QObject::sender());
+void MinecraftProfileStepMojang::onRequestDone(QNetworkReply::NetworkError error,
+ QByteArray data,
+ QList<QNetworkReply::RawHeaderPair> headers)
+{
+ auto requestor = qobject_cast<AuthRequest*>(QObject::sender());
requestor->deleteLater();
qCDebug(authCredentials()) << data;
if (error == QNetworkReply::ContentNotFoundError) {
// NOTE: Succeed even if we do not have a profile. This is a valid account state.
- if(m_data->type == AccountType::Mojang) {
+ if (m_data->type == AccountType::Mojang) {
m_data->minecraftEntitlement.canPlayMinecraft = false;
m_data->minecraftEntitlement.ownsMinecraft = false;
}
m_data->minecraftProfile = MinecraftProfile();
- emit finished(
- AccountTaskState::STATE_SUCCEEDED,
- tr("Account has no Minecraft profile.")
- );
+ emit finished(AccountTaskState::STATE_SUCCEEDED, tr("Account has no Minecraft profile."));
return;
}
if (error != QNetworkReply::NoError) {
@@ -68,35 +64,24 @@ void MinecraftProfileStepMojang::onRequestDone(
qWarning() << QString::fromUtf8(data);
if (Net::isApplicationError(error)) {
- emit finished(
- AccountTaskState::STATE_FAILED_SOFT,
- tr("Minecraft Java profile acquisition failed: %1").arg(requestor->errorString_)
- );
- }
- else {
- emit finished(
- AccountTaskState::STATE_OFFLINE,
- tr("Minecraft Java profile acquisition failed: %1").arg(requestor->errorString_)
- );
+ emit finished(AccountTaskState::STATE_FAILED_SOFT,
+ tr("Minecraft Java profile acquisition failed: %1").arg(requestor->errorString_));
+ } else {
+ emit finished(AccountTaskState::STATE_OFFLINE,
+ tr("Minecraft Java profile acquisition failed: %1").arg(requestor->errorString_));
}
return;
}
- if(!Parsers::parseMinecraftProfileMojang(data, m_data->minecraftProfile)) {
+ if (!Parsers::parseMinecraftProfileMojang(data, m_data->minecraftProfile)) {
m_data->minecraftProfile = MinecraftProfile();
- emit finished(
- AccountTaskState::STATE_FAILED_SOFT,
- tr("Minecraft Java profile response could not be parsed")
- );
+ emit finished(AccountTaskState::STATE_FAILED_SOFT, tr("Minecraft Java profile response could not be parsed"));
return;
}
- if(m_data->type == AccountType::Mojang) {
+ if (m_data->type == AccountType::Mojang) {
auto validProfile = m_data->minecraftProfile.validity == Katabasis::Validity::Certain;
m_data->minecraftEntitlement.canPlayMinecraft = validProfile;
m_data->minecraftEntitlement.ownsMinecraft = validProfile;
}
- emit finished(
- AccountTaskState::STATE_WORKING,
- tr("Minecraft Java profile acquisition succeeded.")
- );
+ emit finished(AccountTaskState::STATE_WORKING, tr("Minecraft Java profile acquisition succeeded."));
}
diff --git a/launcher/minecraft/auth/steps/MinecraftProfileStepMojang.h b/launcher/minecraft/auth/steps/MinecraftProfileStepMojang.h
index e06b30ab..730ec3f6 100644
--- a/launcher/minecraft/auth/steps/MinecraftProfileStepMojang.h
+++ b/launcher/minecraft/auth/steps/MinecraftProfileStepMojang.h
@@ -4,12 +4,11 @@
#include "QObjectPtr.h"
#include "minecraft/auth/AuthStep.h"
-
class MinecraftProfileStepMojang : public AuthStep {
Q_OBJECT
-public:
- explicit MinecraftProfileStepMojang(AccountData *data);
+ public:
+ explicit MinecraftProfileStepMojang(AccountData* data);
virtual ~MinecraftProfileStepMojang() noexcept;
void perform() override;
@@ -17,6 +16,6 @@ public:
QString describe() override;
-private slots:
+ private slots:
void onRequestDone(QNetworkReply::NetworkError, QByteArray, QList<QNetworkReply::RawHeaderPair>);
};
diff --git a/launcher/minecraft/auth/steps/OfflineStep.cpp b/launcher/minecraft/auth/steps/OfflineStep.cpp
index dc092bfd..bf111abe 100644
--- a/launcher/minecraft/auth/steps/OfflineStep.cpp
+++ b/launcher/minecraft/auth/steps/OfflineStep.cpp
@@ -5,14 +5,17 @@
OfflineStep::OfflineStep(AccountData* data) : AuthStep(data) {}
OfflineStep::~OfflineStep() noexcept = default;
-QString OfflineStep::describe() {
+QString OfflineStep::describe()
+{
return tr("Creating offline account.");
}
-void OfflineStep::rehydrate() {
+void OfflineStep::rehydrate()
+{
// NOOP
}
-void OfflineStep::perform() {
+void OfflineStep::perform()
+{
emit finished(AccountTaskState::STATE_WORKING, tr("Created offline account."));
}
diff --git a/launcher/minecraft/auth/steps/OfflineStep.h b/launcher/minecraft/auth/steps/OfflineStep.h
index 436597cd..3bf123d6 100644
--- a/launcher/minecraft/auth/steps/OfflineStep.h
+++ b/launcher/minecraft/auth/steps/OfflineStep.h
@@ -8,8 +8,8 @@
class OfflineStep : public AuthStep {
Q_OBJECT
-public:
- explicit OfflineStep(AccountData *data);
+ public:
+ explicit OfflineStep(AccountData* data);
virtual ~OfflineStep() noexcept;
void perform() override;
diff --git a/launcher/minecraft/auth/steps/XboxAuthorizationStep.cpp b/launcher/minecraft/auth/steps/XboxAuthorizationStep.cpp
index b397b734..c33d7e62 100644
--- a/launcher/minecraft/auth/steps/XboxAuthorizationStep.cpp
+++ b/launcher/minecraft/auth/steps/XboxAuthorizationStep.cpp
@@ -1,33 +1,32 @@
#include "XboxAuthorizationStep.h"
-#include <QNetworkRequest>
-#include <QJsonParseError>
#include <QJsonDocument>
+#include <QJsonParseError>
+#include <QNetworkRequest>
#include "Logging.h"
#include "minecraft/auth/AuthRequest.h"
#include "minecraft/auth/Parsers.h"
#include "net/NetUtils.h"
-XboxAuthorizationStep::XboxAuthorizationStep(AccountData* data, Katabasis::Token *token, QString relyingParty, QString authorizationKind):
- AuthStep(data),
- m_token(token),
- m_relyingParty(relyingParty),
- m_authorizationKind(authorizationKind)
-{
-}
+XboxAuthorizationStep::XboxAuthorizationStep(AccountData* data, Katabasis::Token* token, QString relyingParty, QString authorizationKind)
+ : AuthStep(data), m_token(token), m_relyingParty(relyingParty), m_authorizationKind(authorizationKind)
+{}
XboxAuthorizationStep::~XboxAuthorizationStep() noexcept = default;
-QString XboxAuthorizationStep::describe() {
+QString XboxAuthorizationStep::describe()
+{
return tr("Getting authorization to access %1 services.").arg(m_authorizationKind);
}
-void XboxAuthorizationStep::rehydrate() {
+void XboxAuthorizationStep::rehydrate()
+{
// FIXME: check if the tokens are good?
}
-void XboxAuthorizationStep::perform() {
+void XboxAuthorizationStep::perform()
+{
QString xbox_auth_template = R"XXX(
{
"Properties": {
@@ -41,129 +40,98 @@ void XboxAuthorizationStep::perform() {
}
)XXX";
auto xbox_auth_data = xbox_auth_template.arg(m_data->userToken.token, m_relyingParty);
-// http://xboxlive.com
+ // http://xboxlive.com
QNetworkRequest request = QNetworkRequest(QUrl("https://xsts.auth.xboxlive.com/xsts/authorize"));
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
request.setRawHeader("Accept", "application/json");
- AuthRequest *requestor = new AuthRequest(this);
+ AuthRequest* requestor = new AuthRequest(this);
connect(requestor, &AuthRequest::finished, this, &XboxAuthorizationStep::onRequestDone);
requestor->post(request, xbox_auth_data.toUtf8());
qDebug() << "Getting authorization token for " << m_relyingParty;
}
-void XboxAuthorizationStep::onRequestDone(
- QNetworkReply::NetworkError error,
- QByteArray data,
- QList<QNetworkReply::RawHeaderPair> headers
-) {
- auto requestor = qobject_cast<AuthRequest *>(QObject::sender());
+void XboxAuthorizationStep::onRequestDone(QNetworkReply::NetworkError error, QByteArray data, QList<QNetworkReply::RawHeaderPair> headers)
+{
+ auto requestor = qobject_cast<AuthRequest*>(QObject::sender());
requestor->deleteLater();
qCDebug(authCredentials()) << data;
if (error != QNetworkReply::NoError) {
qWarning() << "Reply error:" << error;
if (Net::isApplicationError(error)) {
- if(!processSTSError(error, data, headers)) {
- emit finished(
- AccountTaskState::STATE_FAILED_SOFT,
- tr("Failed to get authorization for %1 services. Error %2.").arg(m_authorizationKind, error)
- );
- }
- else {
- emit finished(
- AccountTaskState::STATE_FAILED_SOFT,
- tr("Unknown STS error for %1 services: %2").arg(m_authorizationKind, requestor->errorString_)
- );
+ if (!processSTSError(error, data, headers)) {
+ emit finished(AccountTaskState::STATE_FAILED_SOFT,
+ tr("Failed to get authorization for %1 services. Error %2.").arg(m_authorizationKind, error));
+ } else {
+ emit finished(AccountTaskState::STATE_FAILED_SOFT,
+ tr("Unknown STS error for %1 services: %2").arg(m_authorizationKind, requestor->errorString_));
}
- }
- else {
- emit finished(
- AccountTaskState::STATE_OFFLINE,
- tr("Failed to get authorization for %1 services: %2").arg(m_authorizationKind, requestor->errorString_)
- );
+ } else {
+ emit finished(AccountTaskState::STATE_OFFLINE,
+ tr("Failed to get authorization for %1 services: %2").arg(m_authorizationKind, requestor->errorString_));
}
return;
}
Katabasis::Token temp;
- if(!Parsers::parseXTokenResponse(data, temp, m_authorizationKind)) {
- emit finished(
- AccountTaskState::STATE_FAILED_SOFT,
- tr("Could not parse authorization response for access to %1 services.").arg(m_authorizationKind)
- );
+ if (!Parsers::parseXTokenResponse(data, temp, m_authorizationKind)) {
+ emit finished(AccountTaskState::STATE_FAILED_SOFT,
+ tr("Could not parse authorization response for access to %1 services.").arg(m_authorizationKind));
return;
}
- if(temp.extra["uhs"] != m_data->userToken.extra["uhs"]) {
- emit finished(
- AccountTaskState::STATE_FAILED_SOFT,
- tr("Server has changed %1 authorization user hash in the reply. Something is wrong.").arg(m_authorizationKind)
- );
+ if (temp.extra["uhs"] != m_data->userToken.extra["uhs"]) {
+ emit finished(AccountTaskState::STATE_FAILED_SOFT,
+ tr("Server has changed %1 authorization user hash in the reply. Something is wrong.").arg(m_authorizationKind));
return;
}
- auto & token = *m_token;
+ auto& token = *m_token;
token = temp;
emit finished(AccountTaskState::STATE_WORKING, tr("Got authorization to access %1").arg(m_relyingParty));
}
-
-bool XboxAuthorizationStep::processSTSError(
- QNetworkReply::NetworkError error,
- QByteArray data,
- QList<QNetworkReply::RawHeaderPair> headers
-) {
- if(error == QNetworkReply::AuthenticationRequiredError) {
+bool XboxAuthorizationStep::processSTSError(QNetworkReply::NetworkError error, QByteArray data, QList<QNetworkReply::RawHeaderPair> headers)
+{
+ if (error == QNetworkReply::AuthenticationRequiredError) {
QJsonParseError jsonError;
QJsonDocument doc = QJsonDocument::fromJson(data, &jsonError);
- if(jsonError.error) {
+ if (jsonError.error) {
qWarning() << "Cannot parse error XSTS response as JSON: " << jsonError.errorString();
- emit finished(
- AccountTaskState::STATE_FAILED_SOFT,
- tr("Cannot parse %1 authorization error response as JSON: %2").arg(m_authorizationKind, jsonError.errorString())
- );
+ emit finished(AccountTaskState::STATE_FAILED_SOFT,
+ tr("Cannot parse %1 authorization error response as JSON: %2").arg(m_authorizationKind, jsonError.errorString()));
return true;
}
int64_t errorCode = -1;
auto obj = doc.object();
- if(!Parsers::getNumber(obj.value("XErr"), errorCode)) {
- emit finished(
- AccountTaskState::STATE_FAILED_SOFT,
- tr("XErr element is missing from %1 authorization error response.").arg(m_authorizationKind)
- );
+ if (!Parsers::getNumber(obj.value("XErr"), errorCode)) {
+ emit finished(AccountTaskState::STATE_FAILED_SOFT,
+ tr("XErr element is missing from %1 authorization error response.").arg(m_authorizationKind));
return true;
}
- switch(errorCode) {
- case 2148916233:{
- emit finished(
- AccountTaskState::STATE_FAILED_SOFT,
- tr("This Microsoft account does not have an XBox Live profile. Buy the game on %1 first.")
- .arg("<a href=\"https://www.minecraft.net/en-us/store/minecraft-java-edition\">minecraft.net</a>")
- );
+ switch (errorCode) {
+ case 2148916233: {
+ emit finished(AccountTaskState::STATE_FAILED_SOFT,
+ tr("This Microsoft account does not have an XBox Live profile. Buy the game on %1 first.")
+ .arg("<a href=\"https://www.minecraft.net/en-us/store/minecraft-java-edition\">minecraft.net</a>"));
return true;
}
case 2148916235: {
// NOTE: this is the Grulovia error
- emit finished(
- AccountTaskState::STATE_FAILED_SOFT,
- tr("XBox Live is not available in your country. You've been blocked.")
- );
+ emit finished(AccountTaskState::STATE_FAILED_SOFT, tr("XBox Live is not available in your country. You've been blocked."));
return true;
}
case 2148916238: {
emit finished(
AccountTaskState::STATE_FAILED_SOFT,
tr("This Microsoft account is underaged and is not linked to a family.\n\nPlease set up your account according to %1.")
- .arg("<a href=\"https://help.minecraft.net/hc/en-us/articles/4403181904525\">help.minecraft.net</a>")
- );
+ .arg("<a href=\"https://help.minecraft.net/hc/en-us/articles/4403181904525\">help.minecraft.net</a>"));
return true;
}
default: {
- emit finished(
- AccountTaskState::STATE_FAILED_SOFT,
- tr("XSTS authentication ended with unrecognized error(s):\n\n%1").arg(errorCode)
- );
+ emit finished(AccountTaskState::STATE_FAILED_SOFT,
+ tr("XSTS authentication ended with unrecognized error(s):\n\n%1").arg(errorCode));
return true;
}
}
diff --git a/launcher/minecraft/auth/steps/XboxAuthorizationStep.h b/launcher/minecraft/auth/steps/XboxAuthorizationStep.h
index 31e43bf0..dee24c95 100644
--- a/launcher/minecraft/auth/steps/XboxAuthorizationStep.h
+++ b/launcher/minecraft/auth/steps/XboxAuthorizationStep.h
@@ -4,12 +4,11 @@
#include "QObjectPtr.h"
#include "minecraft/auth/AuthStep.h"
-
class XboxAuthorizationStep : public AuthStep {
Q_OBJECT
-public:
- explicit XboxAuthorizationStep(AccountData *data, Katabasis::Token *token, QString relyingParty, QString authorizationKind);
+ public:
+ explicit XboxAuthorizationStep(AccountData* data, Katabasis::Token* token, QString relyingParty, QString authorizationKind);
virtual ~XboxAuthorizationStep() noexcept;
void perform() override;
@@ -17,18 +16,14 @@ public:
QString describe() override;
-private:
- bool processSTSError(
- QNetworkReply::NetworkError error,
- QByteArray data,
- QList<QNetworkReply::RawHeaderPair> headers
- );
+ private:
+ bool processSTSError(QNetworkReply::NetworkError error, QByteArray data, QList<QNetworkReply::RawHeaderPair> headers);
-private slots:
+ private slots:
void onRequestDone(QNetworkReply::NetworkError, QByteArray, QList<QNetworkReply::RawHeaderPair>);
-private:
- Katabasis::Token *m_token;
+ private:
+ Katabasis::Token* m_token;
QString m_relyingParty;
QString m_authorizationKind;
};
diff --git a/launcher/minecraft/auth/steps/XboxProfileStep.cpp b/launcher/minecraft/auth/steps/XboxProfileStep.cpp
index 644c419b..fd2b32cc 100644
--- a/launcher/minecraft/auth/steps/XboxProfileStep.cpp
+++ b/launcher/minecraft/auth/steps/XboxProfileStep.cpp
@@ -8,66 +8,56 @@
#include "minecraft/auth/Parsers.h"
#include "net/NetUtils.h"
-XboxProfileStep::XboxProfileStep(AccountData* data) : AuthStep(data) {
-
-}
+XboxProfileStep::XboxProfileStep(AccountData* data) : AuthStep(data) {}
XboxProfileStep::~XboxProfileStep() noexcept = default;
-QString XboxProfileStep::describe() {
+QString XboxProfileStep::describe()
+{
return tr("Fetching Xbox profile.");
}
-void XboxProfileStep::rehydrate() {
+void XboxProfileStep::rehydrate()
+{
// NOOP, for now. We only save bools and there's nothing to check.
}
-void XboxProfileStep::perform() {
+void XboxProfileStep::perform()
+{
auto url = QUrl("https://profile.xboxlive.com/users/me/profile/settings");
QUrlQuery q;
- q.addQueryItem(
- "settings",
- "GameDisplayName,AppDisplayName,AppDisplayPicRaw,GameDisplayPicRaw,"
- "PublicGamerpic,ShowUserAsAvatar,Gamerscore,Gamertag,ModernGamertag,ModernGamertagSuffix,"
- "UniqueModernGamertag,AccountTier,TenureLevel,XboxOneRep,"
- "PreferredColor,Location,Bio,Watermarks,"
- "RealName,RealNameOverride,IsQuarantined"
- );
+ q.addQueryItem("settings",
+ "GameDisplayName,AppDisplayName,AppDisplayPicRaw,GameDisplayPicRaw,"
+ "PublicGamerpic,ShowUserAsAvatar,Gamerscore,Gamertag,ModernGamertag,ModernGamertagSuffix,"
+ "UniqueModernGamertag,AccountTier,TenureLevel,XboxOneRep,"
+ "PreferredColor,Location,Bio,Watermarks,"
+ "RealName,RealNameOverride,IsQuarantined");
url.setQuery(q);
QNetworkRequest request = QNetworkRequest(url);
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
request.setRawHeader("Accept", "application/json");
request.setRawHeader("x-xbl-contract-version", "3");
- request.setRawHeader("Authorization", QString("XBL3.0 x=%1;%2").arg(m_data->userToken.extra["uhs"].toString(), m_data->xboxApiToken.token).toUtf8());
- AuthRequest *requestor = new AuthRequest(this);
+ request.setRawHeader("Authorization",
+ QString("XBL3.0 x=%1;%2").arg(m_data->userToken.extra["uhs"].toString(), m_data->xboxApiToken.token).toUtf8());
+ AuthRequest* requestor = new AuthRequest(this);
connect(requestor, &AuthRequest::finished, this, &XboxProfileStep::onRequestDone);
requestor->get(request);
qDebug() << "Getting Xbox profile...";
}
-void XboxProfileStep::onRequestDone(
- QNetworkReply::NetworkError error,
- QByteArray data,
- QList<QNetworkReply::RawHeaderPair> headers
-) {
- auto requestor = qobject_cast<AuthRequest *>(QObject::sender());
+void XboxProfileStep::onRequestDone(QNetworkReply::NetworkError error, QByteArray data, QList<QNetworkReply::RawHeaderPair> headers)
+{
+ auto requestor = qobject_cast<AuthRequest*>(QObject::sender());
requestor->deleteLater();
if (error != QNetworkReply::NoError) {
qWarning() << "Reply error:" << error;
qCDebug(authCredentials()) << data;
if (Net::isApplicationError(error)) {
- emit finished(
- AccountTaskState::STATE_FAILED_SOFT,
- tr("Failed to retrieve the Xbox profile: %1").arg(requestor->errorString_)
- );
- }
- else {
- emit finished(
- AccountTaskState::STATE_OFFLINE,
- tr("Failed to retrieve the Xbox profile: %1").arg(requestor->errorString_)
- );
+ emit finished(AccountTaskState::STATE_FAILED_SOFT, tr("Failed to retrieve the Xbox profile: %1").arg(requestor->errorString_));
+ } else {
+ emit finished(AccountTaskState::STATE_OFFLINE, tr("Failed to retrieve the Xbox profile: %1").arg(requestor->errorString_));
}
return;
}
diff --git a/launcher/minecraft/auth/steps/XboxProfileStep.h b/launcher/minecraft/auth/steps/XboxProfileStep.h
index 7a0c5873..b8494b6e 100644
--- a/launcher/minecraft/auth/steps/XboxProfileStep.h
+++ b/launcher/minecraft/auth/steps/XboxProfileStep.h
@@ -4,12 +4,11 @@
#include "QObjectPtr.h"
#include "minecraft/auth/AuthStep.h"
-
class XboxProfileStep : public AuthStep {
Q_OBJECT
-public:
- explicit XboxProfileStep(AccountData *data);
+ public:
+ explicit XboxProfileStep(AccountData* data);
virtual ~XboxProfileStep() noexcept;
void perform() override;
@@ -17,6 +16,6 @@ public:
QString describe() override;
-private slots:
+ private slots:
void onRequestDone(QNetworkReply::NetworkError, QByteArray, QList<QNetworkReply::RawHeaderPair>);
};
diff --git a/launcher/minecraft/auth/steps/XboxUserStep.cpp b/launcher/minecraft/auth/steps/XboxUserStep.cpp
index 842eb60f..61c33a18 100644
--- a/launcher/minecraft/auth/steps/XboxUserStep.cpp
+++ b/launcher/minecraft/auth/steps/XboxUserStep.cpp
@@ -6,22 +6,22 @@
#include "minecraft/auth/Parsers.h"
#include "net/NetUtils.h"
-XboxUserStep::XboxUserStep(AccountData* data) : AuthStep(data) {
-
-}
+XboxUserStep::XboxUserStep(AccountData* data) : AuthStep(data) {}
XboxUserStep::~XboxUserStep() noexcept = default;
-QString XboxUserStep::describe() {
+QString XboxUserStep::describe()
+{
return tr("Logging in as an Xbox user.");
}
-
-void XboxUserStep::rehydrate() {
+void XboxUserStep::rehydrate()
+{
// NOOP, for now. We only save bools and there's nothing to check.
}
-void XboxUserStep::perform() {
+void XboxUserStep::perform()
+{
QString xbox_auth_template = R"XXX(
{
"Properties": {
@@ -40,40 +40,31 @@ void XboxUserStep::perform() {
request.setRawHeader("Accept", "application/json");
// set contract-verison header (prevent err 400 bad-request?)
// https://learn.microsoft.com/en-us/gaming/gdk/_content/gc/reference/live/rest/additional/httpstandardheaders
- request.setRawHeader("x-xbl-contract-version", "1");
+ request.setRawHeader("x-xbl-contract-version", "1");
- auto *requestor = new AuthRequest(this);
+ auto* requestor = new AuthRequest(this);
connect(requestor, &AuthRequest::finished, this, &XboxUserStep::onRequestDone);
requestor->post(request, xbox_auth_data.toUtf8());
qDebug() << "First layer of XBox auth ... commencing.";
}
-void XboxUserStep::onRequestDone(
- QNetworkReply::NetworkError error,
- QByteArray data,
- QList<QNetworkReply::RawHeaderPair> headers
-) {
- auto requestor = qobject_cast<AuthRequest *>(QObject::sender());
+void XboxUserStep::onRequestDone(QNetworkReply::NetworkError error, QByteArray data, QList<QNetworkReply::RawHeaderPair> headers)
+{
+ auto requestor = qobject_cast<AuthRequest*>(QObject::sender());
requestor->deleteLater();
if (error != QNetworkReply::NoError) {
qWarning() << "Reply error:" << error;
if (Net::isApplicationError(error)) {
- emit finished(AccountTaskState::STATE_FAILED_SOFT,
- tr("XBox user authentication failed: %1").arg(requestor->errorString_)
- );
- }
- else {
- emit finished(
- AccountTaskState::STATE_OFFLINE,
- tr("XBox user authentication failed: %1").arg(requestor->errorString_)
- );
+ emit finished(AccountTaskState::STATE_FAILED_SOFT, tr("XBox user authentication failed: %1").arg(requestor->errorString_));
+ } else {
+ emit finished(AccountTaskState::STATE_OFFLINE, tr("XBox user authentication failed: %1").arg(requestor->errorString_));
}
return;
}
Katabasis::Token temp;
- if(!Parsers::parseXTokenResponse(data, temp, "UToken")) {
+ if (!Parsers::parseXTokenResponse(data, temp, "UToken")) {
qWarning() << "Could not parse user authentication response...";
emit finished(AccountTaskState::STATE_FAILED_SOFT, tr("XBox user authentication response could not be understood."));
return;
diff --git a/launcher/minecraft/auth/steps/XboxUserStep.h b/launcher/minecraft/auth/steps/XboxUserStep.h
index 83e9405f..e92727a4 100644
--- a/launcher/minecraft/auth/steps/XboxUserStep.h
+++ b/launcher/minecraft/auth/steps/XboxUserStep.h
@@ -4,12 +4,11 @@
#include "QObjectPtr.h"
#include "minecraft/auth/AuthStep.h"
-
class XboxUserStep : public AuthStep {
Q_OBJECT
-public:
- explicit XboxUserStep(AccountData *data);
+ public:
+ explicit XboxUserStep(AccountData* data);
virtual ~XboxUserStep() noexcept;
void perform() override;
@@ -17,6 +16,6 @@ public:
QString describe() override;
-private slots:
+ private slots:
void onRequestDone(QNetworkReply::NetworkError, QByteArray, QList<QNetworkReply::RawHeaderPair>);
};
diff --git a/launcher/minecraft/auth/steps/YggdrasilStep.cpp b/launcher/minecraft/auth/steps/YggdrasilStep.cpp
index e1d33172..fdcaa0d6 100644
--- a/launcher/minecraft/auth/steps/YggdrasilStep.cpp
+++ b/launcher/minecraft/auth/steps/YggdrasilStep.cpp
@@ -4,7 +4,8 @@
#include "minecraft/auth/Parsers.h"
#include "minecraft/auth/Yggdrasil.h"
-YggdrasilStep::YggdrasilStep(AccountData* data, QString password) : AuthStep(data), m_password(password) {
+YggdrasilStep::YggdrasilStep(AccountData* data, QString password) : AuthStep(data), m_password(password)
+{
m_yggdrasil = new Yggdrasil(m_data, this);
connect(m_yggdrasil, &Task::failed, this, &YggdrasilStep::onAuthFailed);
@@ -14,28 +15,32 @@ YggdrasilStep::YggdrasilStep(AccountData* data, QString password) : AuthStep(dat
YggdrasilStep::~YggdrasilStep() noexcept = default;
-QString YggdrasilStep::describe() {
+QString YggdrasilStep::describe()
+{
return tr("Logging in with Mojang account.");
}
-void YggdrasilStep::rehydrate() {
+void YggdrasilStep::rehydrate()
+{
// NOOP, for now.
}
-void YggdrasilStep::perform() {
- if(m_password.size()) {
+void YggdrasilStep::perform()
+{
+ if (m_password.size()) {
m_yggdrasil->login(m_password);
- }
- else {
+ } else {
m_yggdrasil->refresh();
}
}
-void YggdrasilStep::onAuthSucceeded() {
+void YggdrasilStep::onAuthSucceeded()
+{
emit finished(AccountTaskState::STATE_WORKING, tr("Logged in with Mojang"));
}
-void YggdrasilStep::onAuthFailed() {
+void YggdrasilStep::onAuthFailed()
+{
// TODO: hook these in again, expand to MSA
// m_error = m_yggdrasil->m_error;
// m_aborted = m_yggdrasil->m_aborted;
@@ -44,7 +49,7 @@ void YggdrasilStep::onAuthFailed() {
QString errorMessage = tr("Mojang user authentication failed.");
// NOTE: soft error in the first step means 'offline'
- if(state == AccountTaskState::STATE_FAILED_SOFT) {
+ if (state == AccountTaskState::STATE_FAILED_SOFT) {
state = AccountTaskState::STATE_OFFLINE;
errorMessage = tr("Mojang user authentication ended with a network error.");
}
diff --git a/launcher/minecraft/auth/steps/YggdrasilStep.h b/launcher/minecraft/auth/steps/YggdrasilStep.h
index ebafb8e5..ef31f34d 100644
--- a/launcher/minecraft/auth/steps/YggdrasilStep.h
+++ b/launcher/minecraft/auth/steps/YggdrasilStep.h
@@ -9,8 +9,8 @@ class Yggdrasil;
class YggdrasilStep : public AuthStep {
Q_OBJECT
-public:
- explicit YggdrasilStep(AccountData *data, QString password);
+ public:
+ explicit YggdrasilStep(AccountData* data, QString password);
virtual ~YggdrasilStep() noexcept;
void perform() override;
@@ -18,11 +18,11 @@ public:
QString describe() override;
-private slots:
+ private slots:
void onAuthSucceeded();
void onAuthFailed();
-private:
- Yggdrasil *m_yggdrasil = nullptr;
+ private:
+ Yggdrasil* m_yggdrasil = nullptr;
QString m_password;
};