rpcs3/rpcs3/rpcs3qt/rpcn_settings_dialog.cpp
2020-08-27 20:47:04 +01:00

229 lines
6.7 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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;
}