Merge pull request #4993 from bunnei/web-token-b64
citra_qt: configure_web: Use Base64 encoded token
This commit is contained in:
commit
926902cc5e
|
@ -11,6 +11,31 @@
|
||||||
#include "core/telemetry_session.h"
|
#include "core/telemetry_session.h"
|
||||||
#include "ui_configure_web.h"
|
#include "ui_configure_web.h"
|
||||||
|
|
||||||
|
static constexpr char token_delimiter{':'};
|
||||||
|
|
||||||
|
static std::string GenerateDisplayToken(const std::string& username, const std::string& token) {
|
||||||
|
if (username.empty() || token.empty()) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string unencoded_display_token{username + token_delimiter + token};
|
||||||
|
QByteArray b{unencoded_display_token.c_str()};
|
||||||
|
QByteArray b64 = b.toBase64();
|
||||||
|
return b64.toStdString();
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string UsernameFromDisplayToken(const std::string& display_token) {
|
||||||
|
const std::string unencoded_display_token{
|
||||||
|
QByteArray::fromBase64(display_token.c_str()).toStdString()};
|
||||||
|
return unencoded_display_token.substr(0, unencoded_display_token.find(token_delimiter));
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string TokenFromDisplayToken(const std::string& display_token) {
|
||||||
|
const std::string unencoded_display_token{
|
||||||
|
QByteArray::fromBase64(display_token.c_str()).toStdString()};
|
||||||
|
return unencoded_display_token.substr(unencoded_display_token.find(token_delimiter) + 1);
|
||||||
|
}
|
||||||
|
|
||||||
ConfigureWeb::ConfigureWeb(QWidget* parent)
|
ConfigureWeb::ConfigureWeb(QWidget* parent)
|
||||||
: QWidget(parent), ui(std::make_unique<Ui::ConfigureWeb>()) {
|
: QWidget(parent), ui(std::make_unique<Ui::ConfigureWeb>()) {
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
@ -46,11 +71,18 @@ void ConfigureWeb::SetConfiguration() {
|
||||||
"underline; color:#039be5;\">What is my token?</span></a>"));
|
"underline; color:#039be5;\">What is my token?</span></a>"));
|
||||||
|
|
||||||
ui->toggle_telemetry->setChecked(Settings::values.enable_telemetry);
|
ui->toggle_telemetry->setChecked(Settings::values.enable_telemetry);
|
||||||
ui->edit_username->setText(QString::fromStdString(Settings::values.citra_username));
|
|
||||||
ui->edit_token->setText(QString::fromStdString(Settings::values.citra_token));
|
if (Settings::values.citra_username.empty()) {
|
||||||
|
ui->username->setText(tr("Unspecified"));
|
||||||
|
} else {
|
||||||
|
ui->username->setText(QString::fromStdString(Settings::values.citra_username));
|
||||||
|
}
|
||||||
|
|
||||||
|
ui->edit_token->setText(QString::fromStdString(
|
||||||
|
GenerateDisplayToken(Settings::values.citra_username, Settings::values.citra_token)));
|
||||||
|
|
||||||
// Connect after setting the values, to avoid calling OnLoginChanged now
|
// Connect after setting the values, to avoid calling OnLoginChanged now
|
||||||
connect(ui->edit_token, &QLineEdit::textChanged, this, &ConfigureWeb::OnLoginChanged);
|
connect(ui->edit_token, &QLineEdit::textChanged, this, &ConfigureWeb::OnLoginChanged);
|
||||||
connect(ui->edit_username, &QLineEdit::textChanged, this, &ConfigureWeb::OnLoginChanged);
|
|
||||||
ui->label_telemetry_id->setText(
|
ui->label_telemetry_id->setText(
|
||||||
tr("Telemetry ID: 0x%1").arg(QString::number(Core::GetTelemetryId(), 16).toUpper()));
|
tr("Telemetry ID: 0x%1").arg(QString::number(Core::GetTelemetryId(), 16).toUpper()));
|
||||||
user_verified = true;
|
user_verified = true;
|
||||||
|
@ -62,12 +94,13 @@ void ConfigureWeb::ApplyConfiguration() {
|
||||||
Settings::values.enable_telemetry = ui->toggle_telemetry->isChecked();
|
Settings::values.enable_telemetry = ui->toggle_telemetry->isChecked();
|
||||||
UISettings::values.enable_discord_presence = ui->toggle_discordrpc->isChecked();
|
UISettings::values.enable_discord_presence = ui->toggle_discordrpc->isChecked();
|
||||||
if (user_verified) {
|
if (user_verified) {
|
||||||
Settings::values.citra_username = ui->edit_username->text().toStdString();
|
Settings::values.citra_username =
|
||||||
Settings::values.citra_token = ui->edit_token->text().toStdString();
|
UsernameFromDisplayToken(ui->edit_token->text().toStdString());
|
||||||
|
Settings::values.citra_token = TokenFromDisplayToken(ui->edit_token->text().toStdString());
|
||||||
} else {
|
} else {
|
||||||
QMessageBox::warning(this, tr("Username and token not verified"),
|
QMessageBox::warning(
|
||||||
tr("Username and token were not verified. The changes to your "
|
this, tr("Token not verified"),
|
||||||
"username and/or token have not been saved."));
|
tr("Token was not verified. The change to your token has not been saved."));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,17 +111,15 @@ void ConfigureWeb::RefreshTelemetryID() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigureWeb::OnLoginChanged() {
|
void ConfigureWeb::OnLoginChanged() {
|
||||||
if (ui->edit_username->text().isEmpty() && ui->edit_token->text().isEmpty()) {
|
if (ui->edit_token->text().isEmpty()) {
|
||||||
user_verified = true;
|
user_verified = true;
|
||||||
|
|
||||||
const QPixmap pixmap = QIcon::fromTheme(QStringLiteral("checked")).pixmap(16);
|
const QPixmap pixmap = QIcon::fromTheme(QStringLiteral("checked")).pixmap(16);
|
||||||
ui->label_username_verified->setPixmap(pixmap);
|
|
||||||
ui->label_token_verified->setPixmap(pixmap);
|
ui->label_token_verified->setPixmap(pixmap);
|
||||||
} else {
|
} else {
|
||||||
user_verified = false;
|
user_verified = false;
|
||||||
|
|
||||||
const QPixmap pixmap = QIcon::fromTheme(QStringLiteral("failed")).pixmap(16);
|
const QPixmap pixmap = QIcon::fromTheme(QStringLiteral("failed")).pixmap(16);
|
||||||
ui->label_username_verified->setPixmap(pixmap);
|
|
||||||
ui->label_token_verified->setPixmap(pixmap);
|
ui->label_token_verified->setPixmap(pixmap);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -96,10 +127,11 @@ void ConfigureWeb::OnLoginChanged() {
|
||||||
void ConfigureWeb::VerifyLogin() {
|
void ConfigureWeb::VerifyLogin() {
|
||||||
ui->button_verify_login->setDisabled(true);
|
ui->button_verify_login->setDisabled(true);
|
||||||
ui->button_verify_login->setText(tr("Verifying..."));
|
ui->button_verify_login->setText(tr("Verifying..."));
|
||||||
verify_watcher.setFuture(QtConcurrent::run([username = ui->edit_username->text().toStdString(),
|
verify_watcher.setFuture(QtConcurrent::run(
|
||||||
token = ui->edit_token->text().toStdString()] {
|
[username = UsernameFromDisplayToken(ui->edit_token->text().toStdString()),
|
||||||
return Core::VerifyLogin(username, token);
|
token = TokenFromDisplayToken(ui->edit_token->text().toStdString())] {
|
||||||
}));
|
return Core::VerifyLogin(username, token);
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigureWeb::OnLoginVerified() {
|
void ConfigureWeb::OnLoginVerified() {
|
||||||
|
@ -109,16 +141,16 @@ void ConfigureWeb::OnLoginVerified() {
|
||||||
user_verified = true;
|
user_verified = true;
|
||||||
|
|
||||||
const QPixmap pixmap = QIcon::fromTheme(QStringLiteral("checked")).pixmap(16);
|
const QPixmap pixmap = QIcon::fromTheme(QStringLiteral("checked")).pixmap(16);
|
||||||
ui->label_username_verified->setPixmap(pixmap);
|
|
||||||
ui->label_token_verified->setPixmap(pixmap);
|
ui->label_token_verified->setPixmap(pixmap);
|
||||||
|
ui->username->setText(
|
||||||
|
QString::fromStdString(UsernameFromDisplayToken(ui->edit_token->text().toStdString())));
|
||||||
} else {
|
} else {
|
||||||
const QPixmap pixmap = QIcon::fromTheme(QStringLiteral("failed")).pixmap(16);
|
const QPixmap pixmap = QIcon::fromTheme(QStringLiteral("failed")).pixmap(16);
|
||||||
ui->label_username_verified->setPixmap(pixmap);
|
|
||||||
ui->label_token_verified->setPixmap(pixmap);
|
ui->label_token_verified->setPixmap(pixmap);
|
||||||
QMessageBox::critical(
|
ui->username->setText(tr("Unspecified"));
|
||||||
this, tr("Verification failed"),
|
QMessageBox::critical(this, tr("Verification failed"),
|
||||||
tr("Verification failed. Check that you have entered your username and token "
|
tr("Verification failed. Check that you have entered your token "
|
||||||
"correctly, and that your internet connection is working."));
|
"correctly, and that your internet connection is working."));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -55,11 +55,7 @@
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="1" colspan="3">
|
<item row="0" column="1" colspan="3">
|
||||||
<widget class="QLineEdit" name="edit_username">
|
<widget class="QLabel" name="username" />
|
||||||
<property name="maxLength">
|
|
||||||
<number>36</number>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="0">
|
<item row="1" column="0">
|
||||||
<widget class="QLabel" name="label_token">
|
<widget class="QLabel" name="label_token">
|
||||||
|
@ -79,14 +75,10 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="4">
|
|
||||||
<widget class="QLabel" name="label_username_verified">
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="1" colspan="3">
|
<item row="1" column="1" colspan="3">
|
||||||
<widget class="QLineEdit" name="edit_token">
|
<widget class="QLineEdit" name="edit_token">
|
||||||
<property name="maxLength">
|
<property name="maxLength">
|
||||||
<number>36</number>
|
<number>80</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="echoMode">
|
<property name="echoMode">
|
||||||
<enum>QLineEdit::Password</enum>
|
<enum>QLineEdit::Password</enum>
|
||||||
|
|
|
@ -13,7 +13,7 @@ if (ENABLE_WEB_SERVICE)
|
||||||
target_link_libraries(citra-room PRIVATE web_service)
|
target_link_libraries(citra-room PRIVATE web_service)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
target_link_libraries(citra-room PRIVATE glad)
|
target_link_libraries(citra-room PRIVATE cryptopp glad)
|
||||||
if (MSVC)
|
if (MSVC)
|
||||||
target_link_libraries(citra-room PRIVATE getopt)
|
target_link_libraries(citra-room PRIVATE getopt)
|
||||||
endif()
|
endif()
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include <regex>
|
#include <regex>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
#include <cryptopp/base64.h>
|
||||||
#include <glad/glad.h>
|
#include <glad/glad.h>
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
@ -66,6 +67,24 @@ static void PrintVersion() {
|
||||||
/// The magic text at the beginning of a citra-room ban list file.
|
/// The magic text at the beginning of a citra-room ban list file.
|
||||||
static constexpr char BanListMagic[] = "CitraRoom-BanList-1";
|
static constexpr char BanListMagic[] = "CitraRoom-BanList-1";
|
||||||
|
|
||||||
|
static constexpr char token_delimiter{':'};
|
||||||
|
|
||||||
|
static std::string UsernameFromDisplayToken(const std::string& display_token) {
|
||||||
|
std::string unencoded_display_token;
|
||||||
|
CryptoPP::StringSource ss(
|
||||||
|
display_token, true,
|
||||||
|
new CryptoPP::Base64Decoder(new CryptoPP::StringSink(unencoded_display_token)));
|
||||||
|
return unencoded_display_token.substr(0, unencoded_display_token.find(token_delimiter));
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string TokenFromDisplayToken(const std::string& display_token) {
|
||||||
|
std::string unencoded_display_token;
|
||||||
|
CryptoPP::StringSource ss(
|
||||||
|
display_token, true,
|
||||||
|
new CryptoPP::Base64Decoder(new CryptoPP::StringSink(unencoded_display_token)));
|
||||||
|
return unencoded_display_token.substr(unencoded_display_token.find(token_delimiter) + 1);
|
||||||
|
}
|
||||||
|
|
||||||
static Network::Room::BanList LoadBanList(const std::string& path) {
|
static Network::Room::BanList LoadBanList(const std::string& path) {
|
||||||
std::ifstream file;
|
std::ifstream file;
|
||||||
OpenFStream(file, path, std::ios_base::in);
|
OpenFStream(file, path, std::ios_base::in);
|
||||||
|
@ -158,7 +177,7 @@ int main(int argc, char** argv) {
|
||||||
{"password", required_argument, 0, 'w'},
|
{"password", required_argument, 0, 'w'},
|
||||||
{"preferred-game", required_argument, 0, 'g'},
|
{"preferred-game", required_argument, 0, 'g'},
|
||||||
{"preferred-game-id", required_argument, 0, 'i'},
|
{"preferred-game-id", required_argument, 0, 'i'},
|
||||||
{"username", required_argument, 0, 'u'},
|
{"username", optional_argument, 0, 'u'},
|
||||||
{"token", required_argument, 0, 't'},
|
{"token", required_argument, 0, 't'},
|
||||||
{"web-api-url", required_argument, 0, 'a'},
|
{"web-api-url", required_argument, 0, 'a'},
|
||||||
{"ban-list-file", required_argument, 0, 'b'},
|
{"ban-list-file", required_argument, 0, 'b'},
|
||||||
|
@ -248,10 +267,6 @@ int main(int argc, char** argv) {
|
||||||
"list.\nSet with --ban-list-file <file>\n\n";
|
"list.\nSet with --ban-list-file <file>\n\n";
|
||||||
}
|
}
|
||||||
bool announce = true;
|
bool announce = true;
|
||||||
if (username.empty()) {
|
|
||||||
announce = false;
|
|
||||||
std::cout << "username is empty: Hosting a private room\n\n";
|
|
||||||
}
|
|
||||||
if (token.empty() && announce) {
|
if (token.empty() && announce) {
|
||||||
announce = false;
|
announce = false;
|
||||||
std::cout << "token is empty: Hosting a private room\n\n";
|
std::cout << "token is empty: Hosting a private room\n\n";
|
||||||
|
@ -261,10 +276,17 @@ int main(int argc, char** argv) {
|
||||||
std::cout << "endpoint url is empty: Hosting a private room\n\n";
|
std::cout << "endpoint url is empty: Hosting a private room\n\n";
|
||||||
}
|
}
|
||||||
if (announce) {
|
if (announce) {
|
||||||
std::cout << "Hosting a public room\n\n";
|
if (username.empty()) {
|
||||||
Settings::values.web_api_url = web_api_url;
|
std::cout << "Hosting a public room\n\n";
|
||||||
Settings::values.citra_username = username;
|
Settings::values.web_api_url = web_api_url;
|
||||||
Settings::values.citra_token = token;
|
Settings::values.citra_username = UsernameFromDisplayToken(token);
|
||||||
|
Settings::values.citra_token = TokenFromDisplayToken(token);
|
||||||
|
} else {
|
||||||
|
std::cout << "Hosting a public room\n\n";
|
||||||
|
Settings::values.web_api_url = web_api_url;
|
||||||
|
Settings::values.citra_username = username;
|
||||||
|
Settings::values.citra_token = token;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!announce && enable_citra_mods) {
|
if (!announce && enable_citra_mods) {
|
||||||
enable_citra_mods = false;
|
enable_citra_mods = false;
|
||||||
|
|
Reference in New Issue