mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-09-21 09:05:10 -07:00
* [DeckShare] Open shared decks via links with a gated preview flow - Serialized url-chain dispatcher in IntentUrlParser; queue-drained urlChainFinished(bool) drives the startup auto-connect fallback - Open-shared-deck intent with sequential download state machine, 15s per-item timeout, partial-success offer, livable Cancel via ApplicationModal dlg_login_prompt interactive fallback - Preview dialog: download progress label, share vocab sweep, palette-highlight selection frame, Space/Enter keyboard toggle, NoFocus checkbox, double-click tile opens immediately - Confirm-before-server-migration with one-shot restore to the previous server on failed/cancelled chains (statusChanged settle deferral), hostname-only identity comparisons - Skip credential link when already connected; arrow-key navigation in FlowWidget; card glows use palette highlight - Address code-review M1-M4 and UI/UX QA blockers 1-2 * [DeckShare] End the open-shared-deck files with a trailing newline * [DeckShare] Forward a dependency's cancellation as the owner's own * [DeckShare] Let intent chains opt into the link sign-in dialog * [DeckShare] Track link-intent chains per-run so each can restore its own session * [Settings] Match a server on the exact host and port when adding it * [DeckShare] Confirm the share link's target server before opening a deck * [DeckShare] Reformat the link sign-in intent constructor * [DeckShare] Time the share-list round trip and backstop silently-destroyed intent chains * [Client] Drain a single-instance payload before its handlers read the socket again * [Client] Treat a busy single-instance primary as alive instead of stealing its socket * [DeckShare] Keep arrow-key navigation between flow items inside a scroll area * [Client] Skip the startup connection when a macOS URL launch owns the connection * [Client] Redact share secrets from activation URL logs * [Client] Make the link-connection gates port-aware and keyboard-safe Second-pass review notes for the shared-deck link flow (Cockatrice#7244): - FlowWidget arrow-key navigation is opt-in via addNavigableWidget, so combo/spin controls on the analytics flows keep their own arrow keys - isConnectedTo and the open-deck/join-game preconditions compare the configured server port alongside the host, so a same-host/different-port link cannot resolve its share token or game id on the wrong instance - the link sign-in dialog reuses an existing server entry's saved name instead of renaming it to the raw hostname - skipStartupAutoConnect is cleared once the launch chain connects, so a later mid-session declined link cannot fire the startup fallback - the plain-launch path of SingleInstanceManager no longer blocks on the primary's ACK - link- and server-supplied text is html-escaped in the confirm prompts and shared-deck preview so markup cannot spoof the shown messages --------- Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
370 lines
13 KiB
C++
370 lines
13 KiB
C++
#include "servers_settings.h"
|
|
|
|
#include <QDebug>
|
|
#include <utility>
|
|
|
|
ServersSettings::ServersSettings(const QString &settingPath, QObject *parent)
|
|
: SettingsManager(settingPath + "servers.ini", "server", QString(), parent)
|
|
{
|
|
}
|
|
|
|
void ServersSettings::setPreviousHostLogin(int previous)
|
|
{
|
|
setValue(previous, "previousHostLogin");
|
|
}
|
|
|
|
int ServersSettings::getPreviousHostLogin() const
|
|
{
|
|
QVariant previous = getValue("previousHostLogin");
|
|
return previous == QVariant() ? 1 : previous.toInt();
|
|
}
|
|
|
|
void ServersSettings::setPreviousHostList(QStringList list)
|
|
{
|
|
setValue(list, "previousHosts");
|
|
}
|
|
|
|
QStringList ServersSettings::getPreviousHostList() const
|
|
{
|
|
return getValue("previousHosts").toStringList();
|
|
}
|
|
|
|
void ServersSettings::setPrevioushostName(const QString &name)
|
|
{
|
|
setValue(name, "previousHostName");
|
|
}
|
|
|
|
QString ServersSettings::getSaveName(QString defaultname)
|
|
{
|
|
int index = getPrevioushostindex(getPrevioushostName());
|
|
QVariant saveName = getValue(QString("saveName%1").arg(index), "server", "server_details");
|
|
return saveName == QVariant() ? std::move(defaultname) : saveName.toString();
|
|
}
|
|
|
|
QString ServersSettings::getSite(QString defaultSite)
|
|
{
|
|
int index = getPrevioushostindex(getPrevioushostName());
|
|
QVariant site = getValue(QString("site%1").arg(index), "server", "server_details");
|
|
return site == QVariant() ? std::move(defaultSite) : site.toString();
|
|
}
|
|
|
|
QString ServersSettings::getPrevioushostName() const
|
|
{
|
|
QVariant value = getValue("previousHostName");
|
|
return value == QVariant() ? "Rooster Ranges" : value.toString();
|
|
}
|
|
|
|
int ServersSettings::getPrevioushostindex(const QString &saveName) const
|
|
{
|
|
int size = getValue("totalServers", "server", "server_details").toInt();
|
|
|
|
for (int i = 0; i <= size; ++i) {
|
|
if (saveName == getValue(QString("saveName%1").arg(i), "server", "server_details").toString()) {
|
|
return i;
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
QString ServersSettings::getHostname(QString defaultHost) const
|
|
{
|
|
int index = getPrevioushostindex(getPrevioushostName());
|
|
QVariant hostname = getValue(QString("server%1").arg(index), "server", "server_details");
|
|
return hostname == QVariant() ? std::move(defaultHost) : hostname.toString();
|
|
}
|
|
|
|
QString ServersSettings::getPort(QString defaultPort) const
|
|
{
|
|
int index = getPrevioushostindex(getPrevioushostName());
|
|
QVariant port = getValue(QString("port%1").arg(index), "server", "server_details");
|
|
qCDebug(ServersSettingsLog) << "getPort() index = " << index << " port.val = " << port.toString();
|
|
return port == QVariant() ? std::move(defaultPort) : port.toString();
|
|
}
|
|
|
|
QString ServersSettings::getPlayerName(QString defaultName) const
|
|
{
|
|
int index = getPrevioushostindex(getPrevioushostName());
|
|
QVariant name = getValue(QString("username%1").arg(index), "server", "server_details");
|
|
qCDebug(ServersSettingsLog) << "getPlayerName() index = " << index << " name.val = " << name.toString();
|
|
return name == QVariant() ? std::move(defaultName) : name.toString();
|
|
}
|
|
|
|
QString ServersSettings::getPassword()
|
|
{
|
|
int index = getPrevioushostindex(getPrevioushostName());
|
|
|
|
if (getSavePassword()) {
|
|
return getValue(QString("password%1").arg(index), "server", "server_details").toString();
|
|
}
|
|
|
|
return QString();
|
|
}
|
|
|
|
bool ServersSettings::getSavePassword() const
|
|
{
|
|
int index = getPrevioushostindex(getPrevioushostName());
|
|
bool save = getValue(QString("savePassword%1").arg(index), "server", "server_details").toBool();
|
|
return save;
|
|
}
|
|
|
|
void ServersSettings::setAutoConnect(int autoconnect)
|
|
{
|
|
setValue(autoconnect, "autoConnect");
|
|
}
|
|
|
|
int ServersSettings::getAutoConnect() const
|
|
{
|
|
QVariant autoconnect = getValue("autoConnect");
|
|
return autoconnect == QVariant() ? 0 : autoconnect.toInt();
|
|
}
|
|
|
|
void ServersSettings::setFPHostName(QString hostname)
|
|
{
|
|
setValue(hostname, "fpHostName");
|
|
}
|
|
|
|
QString ServersSettings::getFPHostname(QString defaultHost) const
|
|
{
|
|
QVariant hostname = getValue("fpHostName");
|
|
return hostname == QVariant() ? std::move(defaultHost) : hostname.toString();
|
|
}
|
|
|
|
void ServersSettings::setFPPort(QString port)
|
|
{
|
|
setValue(port, "fpPort");
|
|
}
|
|
|
|
QString ServersSettings::getFPPort(QString defaultPort) const
|
|
{
|
|
QVariant port = getValue("fpPort");
|
|
return port == QVariant() ? std::move(defaultPort) : port.toString();
|
|
}
|
|
|
|
void ServersSettings::setFPPlayerName(QString playerName)
|
|
{
|
|
setValue(playerName, "fpPlayerName");
|
|
}
|
|
|
|
QString ServersSettings::getFPPlayerName(QString defaultName) const
|
|
{
|
|
QVariant name = getValue("fpPlayerName");
|
|
return name == QVariant() ? std::move(defaultName) : name.toString();
|
|
}
|
|
|
|
void ServersSettings::setClearDebugLogStatus(bool abIsChecked)
|
|
{
|
|
setValue(abIsChecked, "saveDebugLog");
|
|
}
|
|
|
|
bool ServersSettings::getClearDebugLogStatus(bool abDefaultValue) const
|
|
{
|
|
QVariant cbFlushLog = getValue("saveDebugLog");
|
|
return cbFlushLog == QVariant() ? abDefaultValue : cbFlushLog.toBool();
|
|
}
|
|
|
|
void ServersSettings::addNewServer(const QString &saveName,
|
|
const QString &serv,
|
|
const QString &port,
|
|
const QString &username,
|
|
const QString &password,
|
|
bool savePassword,
|
|
const QString &site)
|
|
{
|
|
// Match the exact host-plus-port server the caller is adding, so a link or
|
|
// public-server list entry cannot clobber the port (and credentials) of an
|
|
// unrelated entry that happens to share the same hostname.
|
|
const int existingIndex = findServerIndex(serv, port);
|
|
if (existingIndex >= 0) {
|
|
updateServerFields(existingIndex, saveName, username, password, savePassword, site);
|
|
return;
|
|
}
|
|
|
|
int index = getValue("totalServers", "server", "server_details").toInt() + 1;
|
|
|
|
setValue(saveName, QString("saveName%1").arg(index), "server", "server_details");
|
|
setValue(serv, QString("server%1").arg(index), "server", "server_details");
|
|
setValue(port, QString("port%1").arg(index), "server", "server_details");
|
|
setValue(username, QString("username%1").arg(index), "server", "server_details");
|
|
setValue(savePassword, QString("savePassword%1").arg(index), "server", "server_details");
|
|
setValue(index, "totalServers", "server", "server_details");
|
|
setValue(password, QString("password%1").arg(index), "server", "server_details");
|
|
setValue(site, QString("site%1").arg(index), "server", "server_details");
|
|
}
|
|
|
|
void ServersSettings::removeServer(QString servAddr)
|
|
{
|
|
int size = getValue("totalServers", "server", "server_details").toInt();
|
|
|
|
bool found = false;
|
|
for (int i = 0; i <= size; ++i) {
|
|
if (!found) {
|
|
// find entry and overwrite it
|
|
if (servAddr == getValue(QString("server%1").arg(i), "server", "server_details").toString()) {
|
|
found = true;
|
|
}
|
|
} else {
|
|
// move all other entries after it one back, overwriting the previous one
|
|
int previous = i - 1; // we delete only one entry
|
|
setValue(getValue(QString("server%1").arg(i), "server", "server_details"),
|
|
QString("server%1").arg(previous), "server", "server_details");
|
|
setValue(getValue(QString("port%1").arg(i), "server", "server_details"), QString("port%1").arg(previous),
|
|
"server", "server_details");
|
|
setValue(getValue(QString("username%1").arg(i), "server", "server_details"),
|
|
QString("username%1").arg(previous), "server", "server_details");
|
|
setValue(getValue(QString("savePassword%1").arg(i), "server", "server_details"),
|
|
QString("savePassword%1").arg(previous), "server", "server_details");
|
|
setValue(getValue(QString("password%1").arg(i), "server", "server_details"),
|
|
QString("password%1").arg(previous), "server", "server_details");
|
|
setValue(getValue(QString("saveName%1").arg(i), "server", "server_details"),
|
|
QString("saveName%1").arg(previous), "server", "server_details");
|
|
setValue(getValue(QString("site%1").arg(i), "server", "server_details"), QString("site%1").arg(previous),
|
|
"server", "server_details");
|
|
}
|
|
}
|
|
|
|
// if we have deleted an entry, adjust the total
|
|
if (found) {
|
|
setValue(size - 1, "totalServers", "server", "server_details");
|
|
|
|
// delete last value
|
|
deleteValue(QString("server%1").arg(size), "server", "server_details");
|
|
deleteValue(QString("port%1").arg(size), "server", "server_details");
|
|
deleteValue(QString("username%1").arg(size), "server", "server_details");
|
|
deleteValue(QString("savePassword%1").arg(size), "server", "server_details");
|
|
deleteValue(QString("password%1").arg(size), "server", "server_details");
|
|
deleteValue(QString("saveName%1").arg(size), "server", "server_details");
|
|
deleteValue(QString("site%1").arg(size), "server", "server_details");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Will only update fields with new values, ignores empty values
|
|
*/
|
|
bool ServersSettings::updateExistingServerWithoutLoss(QString saveName, QString serv, QString port, QString site)
|
|
{
|
|
int size = getValue("totalServers", "server", "server_details").toInt();
|
|
|
|
for (int i = 0; i <= size; ++i) {
|
|
if (serv == getValue(QString("server%1").arg(i), "server", "server_details").toString()) {
|
|
if (!port.isEmpty()) {
|
|
setValue(port, QString("port%1").arg(i), "server", "server_details");
|
|
}
|
|
|
|
if (!site.isEmpty()) {
|
|
setValue(site, QString("site%1").arg(i), "server", "server_details");
|
|
}
|
|
|
|
setValue(saveName, QString("saveName%1").arg(i), "server", "server_details");
|
|
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool ServersSettings::updateExistingServer(QString saveName,
|
|
QString serv,
|
|
QString port,
|
|
QString username,
|
|
QString password,
|
|
bool savePassword,
|
|
QString site)
|
|
{
|
|
int size = getValue("totalServers", "server", "server_details").toInt();
|
|
|
|
for (int i = 0; i <= size; ++i) {
|
|
if (serv == getValue(QString("server%1").arg(i), "server", "server_details").toString()) {
|
|
setValue(port, QString("port%1").arg(i), "server", "server_details");
|
|
updateServerFields(i, saveName, username, password, savePassword, site);
|
|
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void ServersSettings::updateServerFields(int index,
|
|
const QString &saveName,
|
|
const QString &username,
|
|
const QString &password,
|
|
bool savePassword,
|
|
const QString &site)
|
|
{
|
|
if (!username.isEmpty()) {
|
|
setValue(username, QString("username%1").arg(index), "server", "server_details");
|
|
}
|
|
|
|
if (savePassword && !password.isEmpty()) {
|
|
setValue(password, QString("password%1").arg(index), "server", "server_details");
|
|
} else {
|
|
setValue(QString(), QString("password%1").arg(index), "server", "server_details");
|
|
}
|
|
|
|
if (!site.isEmpty()) {
|
|
setValue(site, QString("site%1").arg(index), "server", "server_details");
|
|
}
|
|
|
|
setValue(savePassword, QString("savePassword%1").arg(index), "server", "server_details");
|
|
setValue(saveName, QString("saveName%1").arg(index), "server", "server_details");
|
|
}
|
|
|
|
int ServersSettings::findServerIndex(const QString &host, const QString &port) const
|
|
{
|
|
int size = getValue("totalServers", "server", "server_details").toInt();
|
|
|
|
for (int i = 0; i <= size; ++i) {
|
|
QString storedHost = getValue(QString("server%1").arg(i), "server", "server_details").toString();
|
|
QString storedPort = getValue(QString("port%1").arg(i), "server", "server_details").toString();
|
|
|
|
if (storedHost == host && storedPort == port) {
|
|
return i;
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
int ServersSettings::findHostIndex(const QString &host) const
|
|
{
|
|
int size = getValue("totalServers", "server", "server_details").toInt();
|
|
|
|
for (int i = 0; i <= size; ++i) {
|
|
QString storedHost = getValue(QString("server%1").arg(i), "server", "server_details").toString();
|
|
|
|
if (storedHost.compare(host, Qt::CaseInsensitive) == 0) {
|
|
return i;
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
bool ServersSettings::hasUsername(const QString &host, const QString &port) const
|
|
{
|
|
int index = findServerIndex(host, port);
|
|
if (index < 0) {
|
|
return false;
|
|
}
|
|
|
|
QString user = getValue(QString("username%1").arg(index), "server", "server_details").toString();
|
|
return !user.isEmpty();
|
|
}
|
|
|
|
bool ServersSettings::hasCredentials(const QString &host, const QString &port) const
|
|
{
|
|
int index = findServerIndex(host, port);
|
|
if (index < 0) {
|
|
return false;
|
|
}
|
|
|
|
bool save = getValue(QString("savePassword%1").arg(index), "server", "server_details").toBool();
|
|
QString password = getValue(QString("password%1").arg(index), "server", "server_details").toString();
|
|
|
|
return save && !password.isEmpty();
|
|
}
|
|
|
|
bool ServersSettings::hasLoginData(const QString &host, const QString &port) const
|
|
{
|
|
return hasUsername(host, port) && hasCredentials(host, port);
|
|
}
|