mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-02 21:11:25 +12:00
229 lines
6.7 KiB
C++
229 lines
6.7 KiB
C++
#include <QMessageBox>
|
||
#include <QVBoxLayout>
|
||
#include <QHBoxLayout>
|
||
#include <QLabel>
|
||
#include <QPushButton>
|
||
#include <QRegExpValidator>
|
||
#include <QInputDialog>
|
||
#include <thread>
|
||
|
||
#include "rpcn_settings_dialog.h"
|
||
#include "Emu/NP/rpcn_config.h"
|
||
#include "Emu/NP/rpcn_client.h"
|
||
|
||
#include <wolfssl/ssl.h>
|
||
#include <wolfssl/openssl/evp.h>
|
||
|
||
rpcn_settings_dialog::rpcn_settings_dialog(QWidget* parent)
|
||
: QDialog(parent)
|
||
{
|
||
setWindowTitle(tr("RPCN Configuration"));
|
||
setObjectName("rpcn_settings_dialog");
|
||
setMinimumSize(QSize(400, 200));
|
||
|
||
QVBoxLayout* vbox_global = new QVBoxLayout();
|
||
QHBoxLayout* hbox_labels_and_edits = new QHBoxLayout();
|
||
QVBoxLayout* vbox_labels = new QVBoxLayout();
|
||
QVBoxLayout* vbox_edits = new QVBoxLayout();
|
||
QHBoxLayout* hbox_buttons = new QHBoxLayout();
|
||
|
||
QLabel* label_host = new QLabel(tr("Host:"));
|
||
m_edit_host = new QLineEdit();
|
||
QLabel* label_npid = new QLabel(tr("NPID (username):"));
|
||
m_edit_npid = new QLineEdit();
|
||
m_edit_npid->setMaxLength(16);
|
||
m_edit_npid->setValidator(new QRegExpValidator(QRegExp("^[a-zA-Z0-9_\\-]*$"), this));
|
||
QLabel* label_pass = new QLabel(tr("Password:"));
|
||
QPushButton* btn_chg_pass = new QPushButton(tr("Set Password"));
|
||
QLabel *label_token = new QLabel(tr("Token:"));
|
||
m_edit_token = new QLineEdit();
|
||
|
||
QPushButton* btn_create = new QPushButton(tr("Create Account"), this);
|
||
QPushButton* btn_save = new QPushButton(tr("Save"), this);
|
||
|
||
vbox_labels->addWidget(label_host);
|
||
vbox_labels->addWidget(label_npid);
|
||
vbox_labels->addWidget(label_pass);
|
||
vbox_labels->addWidget(label_token);
|
||
|
||
vbox_edits->addWidget(m_edit_host);
|
||
vbox_edits->addWidget(m_edit_npid);
|
||
vbox_edits->addWidget(btn_chg_pass);
|
||
vbox_edits->addWidget(m_edit_token);
|
||
|
||
hbox_buttons->addWidget(btn_create);
|
||
hbox_buttons->addStretch();
|
||
hbox_buttons->addWidget(btn_save);
|
||
|
||
hbox_labels_and_edits->addLayout(vbox_labels);
|
||
hbox_labels_and_edits->addLayout(vbox_edits);
|
||
|
||
vbox_global->addLayout(hbox_labels_and_edits);
|
||
vbox_global->addLayout(hbox_buttons);
|
||
|
||
setLayout(vbox_global);
|
||
|
||
connect(btn_chg_pass, &QAbstractButton::clicked, [this]()
|
||
{
|
||
QString password;
|
||
|
||
while (true)
|
||
{
|
||
bool clicked_ok = false;
|
||
password = QInputDialog::getText(this, "Set/Change Password", "Set your password", QLineEdit::Password, "", &clicked_ok);
|
||
if (!clicked_ok)
|
||
return;
|
||
|
||
if (password.isEmpty())
|
||
{
|
||
QMessageBox::critical(this, tr("Wrong input"), tr("You need to enter a password!"), QMessageBox::Ok);
|
||
}
|
||
else
|
||
{
|
||
break;
|
||
}
|
||
}
|
||
|
||
std::string pass_str = password.toStdString();
|
||
std::string salt_str = "No matter where you go, everybody's connected.";
|
||
|
||
u8 salted_pass[SHA_DIGEST_SIZE];
|
||
|
||
wolfSSL_PKCS5_PBKDF2_HMAC_SHA1(pass_str.c_str(), pass_str.size(), reinterpret_cast<const u8*>(salt_str.c_str()), salt_str.size(), 1000, SHA_DIGEST_SIZE, salted_pass);
|
||
|
||
std::string hash("0000000000000000000000000000000000000000");
|
||
for (u32 i = 0; i < 20; i++)
|
||
{
|
||
constexpr auto pal = "0123456789abcdef";
|
||
hash[i * 2] = pal[salted_pass[i] >> 4];
|
||
hash[1 + i * 2] = pal[salted_pass[i] & 15];
|
||
}
|
||
|
||
g_cfg_rpcn.set_password(hash);
|
||
g_cfg_rpcn.save();
|
||
});
|
||
|
||
connect(btn_save, &QAbstractButton::clicked, [this]()
|
||
{
|
||
if (this->save_config())
|
||
this->close();
|
||
});
|
||
connect(btn_create, &QAbstractButton::clicked, [this]() { this->create_account(); });
|
||
|
||
g_cfg_rpcn.load();
|
||
|
||
m_edit_host->setText(QString::fromStdString(g_cfg_rpcn.get_host()));
|
||
m_edit_npid->setText(QString::fromStdString(g_cfg_rpcn.get_npid()));
|
||
m_edit_token->setText(QString::fromStdString(g_cfg_rpcn.get_token()));
|
||
}
|
||
|
||
bool rpcn_settings_dialog::save_config()
|
||
{
|
||
const auto host = m_edit_host->text().toStdString();
|
||
const auto npid = m_edit_npid->text().toStdString();
|
||
const auto token = m_edit_token->text().toStdString();
|
||
|
||
auto validate = [](const std::string& input) -> bool
|
||
{
|
||
if (input.length() < 3 || input.length() > 16)
|
||
return false;
|
||
|
||
for (const auto c : input)
|
||
{
|
||
if (!std::isalnum(c) && c != '-' && c != '_')
|
||
return false;
|
||
}
|
||
return true;
|
||
};
|
||
|
||
if (host.empty())
|
||
{
|
||
QMessageBox::critical(this, tr("Missing host"), tr("You need to enter a host for rpcn!"), QMessageBox::Ok);
|
||
return false;
|
||
}
|
||
|
||
if (npid.empty() || g_cfg_rpcn.get_password().empty())
|
||
{
|
||
QMessageBox::critical(this, tr("Wrong input"), tr("You need to enter a username and a password!"), QMessageBox::Ok);
|
||
return false;
|
||
}
|
||
|
||
if (!validate(npid))
|
||
{
|
||
QMessageBox::critical(this, tr("Invalid character"), tr("NPID must be between 3 and 16 characters and can only contain '-', '_' or alphanumeric characters."), QMessageBox::Ok);
|
||
return false;
|
||
}
|
||
|
||
g_cfg_rpcn.set_host(host);
|
||
g_cfg_rpcn.set_npid(npid);
|
||
g_cfg_rpcn.set_token(token);
|
||
|
||
g_cfg_rpcn.save();
|
||
|
||
return true;
|
||
}
|
||
|
||
bool rpcn_settings_dialog::create_account()
|
||
{
|
||
// Validate and save
|
||
if (!save_config())
|
||
return false;
|
||
|
||
QString email;
|
||
QRegExpValidator simple_email_validator(QRegExp("^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\\.[a-zA-Z0-9-]+)*$"));
|
||
|
||
while (true)
|
||
{
|
||
bool clicked_ok = false;
|
||
email = QInputDialog::getText(this, "Email address", "An email address is required, please note:\n*A valid email is needed to validate your account.\n*Your email won't be used for anything beyond sending you the token.\n*Upon successful creation a token will be sent to your email which you'll need to login.\n\n", QLineEdit::Normal, "", &clicked_ok);
|
||
if (!clicked_ok)
|
||
return false;
|
||
|
||
int pos = 0;
|
||
if (email.isEmpty() || simple_email_validator.validate(email, pos) != QValidator::Acceptable)
|
||
{
|
||
QMessageBox::critical(this, tr("Wrong input"), tr("You need to enter a valid email!"), QMessageBox::Ok);
|
||
}
|
||
else
|
||
{
|
||
break;
|
||
}
|
||
}
|
||
|
||
const auto rpcn = std::make_shared<rpcn_client>(true);
|
||
|
||
const auto host = g_cfg_rpcn.get_host();
|
||
const auto npid = g_cfg_rpcn.get_npid();
|
||
const auto online_name = npid;
|
||
const auto avatar_url = "https://rpcs3.net/cdn/netplay/DefaultAvatar.png";
|
||
const auto password = g_cfg_rpcn.get_password();
|
||
|
||
std::thread(
|
||
[](const std::shared_ptr<rpcn_client> rpcn)
|
||
{
|
||
while (rpcn.use_count() != 1)
|
||
rpcn->manage_connection();
|
||
|
||
rpcn->disconnect();
|
||
},
|
||
rpcn)
|
||
.detach();
|
||
|
||
if (!rpcn->connect(host))
|
||
{
|
||
QMessageBox::critical(this, tr("Error Connecting"), tr("Failed to connect to RPCN server"), QMessageBox::Ok);
|
||
rpcn->abort();
|
||
return false;
|
||
}
|
||
|
||
if (!rpcn->create_user(npid, password, online_name, avatar_url, email.toStdString()))
|
||
{
|
||
QMessageBox::critical(this, tr("Error Creating Account"), tr("Failed to create the account"), QMessageBox::Ok);
|
||
rpcn->abort();
|
||
return false;
|
||
}
|
||
|
||
QMessageBox::information(this, tr("Account created!"), tr("Your account has been created successfully!\nCheck your email for your token!"), QMessageBox::Ok);
|
||
rpcn->abort();
|
||
return true;
|
||
}
|