Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/core/Config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@ static const QHash<Config::ConfigKey, ConfigDirective> configStrings = {
{Config::KeeShare_Own, {QS("KeeShare/Own"), Roaming, {}}},
{Config::KeeShare_Foreign, {QS("KeeShare/Foreign"), Roaming, {}}},
{Config::KeeShare_Active, {QS("KeeShare/Active"), Roaming, {}}},
{Config::KeeShare_DeviceId, {QS("KeeShare/DeviceId"), Local, {}}},

// PasswordGenerator
{Config::PasswordGenerator_LowerCase, {QS("PasswordGenerator/LowerCase"), Roaming, true}},
Expand Down
1 change: 1 addition & 0 deletions src/core/Config.h
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ class Config : public QObject
KeeShare_Own,
KeeShare_Foreign,
KeeShare_Active,
KeeShare_DeviceId,

PasswordGenerator_LowerCase,
PasswordGenerator_UpperCase,
Expand Down
36 changes: 36 additions & 0 deletions src/keeshare/KeeShare.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@
#include "gui/DatabaseIcons.h"
#include "keeshare/ShareObserver.h"

#include <QRegularExpression>
#include <QSysInfo>

namespace
{
static const QString KeeShare_Reference("KeeShare/Reference");
Expand Down Expand Up @@ -51,6 +54,39 @@ void KeeShare::init(QObject* parent)
m_instance = new KeeShare(parent);
}

QString KeeShare::deviceId()
{
auto id = config()->get(Config::KeeShare_DeviceId).toString();
if (id.isEmpty()) {
// Generate fallback from machine unique ID, truncated to 7 chars
auto machineId = QSysInfo::machineUniqueId();
if (!machineId.isEmpty()) {
// machineUniqueId() on Linux returns a hex string directly from /etc/machine-id
id = QString::fromLatin1(machineId).left(7).toUpper();
} else {
// Last resort: use hostname
id = QSysInfo::machineHostName();
}
setDeviceId(id);
// Re-read the sanitized value
id = config()->get(Config::KeeShare_DeviceId).toString();
}
return id;
}
Comment thread
Lcstyle marked this conversation as resolved.

void KeeShare::setDeviceId(const QString& id)
{
// All sanitization consolidated here: strip non-alphanumeric, enforce max
// length, and fall back to DEFAULT if empty
QString sanitized = id;
sanitized.remove(QRegularExpression("[^A-Za-z0-9]"));
sanitized.truncate(32);
if (sanitized.isEmpty()) {
sanitized = QStringLiteral("DEFAULT");
}
config()->set(Config::KeeShare_DeviceId, sanitized);
}
Comment on lines +77 to +88
Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The device ID sanitization removes all non-alphanumeric characters but doesn't validate the resulting length or format. If sanitization results in an empty string after removing special characters, the function sets it to "DEFAULT". However, this doesn't prevent potential issues with extremely long device IDs or device IDs that start with numbers or special patterns. Consider adding validation for minimum/maximum length and perhaps enforcing that it starts with a letter.

Copilot uses AI. Check for mistakes.

KeeShareSettings::Own KeeShare::own()
{
// Read existing own certificate or generate a new one if none available
Expand Down
3 changes: 3 additions & 0 deletions src/keeshare/KeeShare.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ class KeeShare : public QObject
static const Group* resolveSharedGroup(const Group* group);
static QString sharingLabel(const Group* group);

static QString deviceId();
static void setDeviceId(const QString& id);

static KeeShareSettings::Own own();
static void setOwn(const KeeShareSettings::Own& own);

Expand Down
11 changes: 11 additions & 0 deletions src/keeshare/KeeShareSettings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
#include "gui/DatabaseIcons.h"

#include <QDataStream>
#include <QDir>
#include <QFileInfo>
#include <QTextCodec>
#include <QXmlStreamWriter>

Expand Down Expand Up @@ -286,6 +288,15 @@ namespace KeeShareSettings
return (type & ImportFrom) != 0 && !path.isEmpty();
}

bool Reference::isPerDeviceMode(const QDir& baseDir) const
{
if (path.isEmpty()) {
return false;
}
const QString resolvedPath = baseDir.absoluteFilePath(path);
return QFileInfo(resolvedPath).isDir();
}

bool Reference::operator<(const Reference& other) const
{
if (type != other.type) {
Expand Down
3 changes: 3 additions & 0 deletions src/keeshare/KeeShareSettings.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
#include <QSharedPointer>
#include <QUuid>

class QDir;

namespace Botan
{
class Private_Key;
Expand Down Expand Up @@ -133,6 +135,7 @@ namespace KeeShareSettings
bool isValid() const;
bool isExporting() const;
bool isImporting() const;
bool isPerDeviceMode(const QDir& baseDir) const;
bool operator<(const Reference& other) const;
bool operator==(const Reference& other) const;

Expand Down
14 changes: 14 additions & 0 deletions src/keeshare/SettingsWidgetKeeShare.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "gui/MessageBox.h"
#include "keeshare/KeeShare.h"

#include <QRegularExpressionValidator>
#include <QStandardItemModel>
#include <QStandardPaths>
#include <QTextStream>
Expand All @@ -33,6 +34,9 @@ SettingsWidgetKeeShare::SettingsWidgetKeeShare(QWidget* parent)
{
m_ui->setupUi(this);

m_ui->deviceIdEdit->setValidator(
new QRegularExpressionValidator(QRegularExpression("[A-Za-z0-9]{0,32}"), this));

connect(m_ui->ownCertificateSignerEdit, SIGNAL(textChanged(QString)), SLOT(setVerificationExporter(QString)));
connect(m_ui->generateOwnCerticateButton, SIGNAL(clicked(bool)), SLOT(generateCertificate()));
}
Expand All @@ -47,6 +51,8 @@ void SettingsWidgetKeeShare::loadSettings()
m_ui->enableExportCheckBox->setChecked(active.out);
m_ui->enableImportCheckBox->setChecked(active.in);

m_ui->deviceIdEdit->setText(KeeShare::deviceId());

m_own = KeeShare::own();
updateOwnCertificate();
}
Expand All @@ -68,6 +74,14 @@ void SettingsWidgetKeeShare::saveSettings()
KeeShare::setOwn(m_own);
KeeShare::setActive(active);

auto deviceId = m_ui->deviceIdEdit->text().trimmed();
if (!deviceId.isEmpty()) {
KeeShare::setDeviceId(deviceId);
} else {
// Clear stored ID so it will be auto-detected next time
config()->set(Config::KeeShare_DeviceId, QString());
}
Comment on lines +77 to +83
Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The device ID should be cleared from config when the user clears the field, not just when they enter a new value. If a user has a custom device ID and wants to return to the auto-detected value, clearing the field should achieve that. Currently, clearing the field doesn't clear the stored config value.

Copilot uses AI. Check for mistakes.

config()->set(Config::KeeShare_QuietSuccess, m_ui->quietSuccessCheckBox->isChecked());
}

Expand Down
42 changes: 42 additions & 0 deletions src/keeshare/SettingsWidgetKeeShare.ui
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,48 @@
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="deviceIdentityGroupBox">
<property name="title">
<string>Device Identity</string>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<item row="0" column="0">
<widget class="QLabel" name="deviceIdLabel">
<property name="text">
<string>Device ID:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="deviceIdEdit">
<property name="accessibleName">
<string>Device ID field</string>
</property>
<property name="toolTip">
<string>Unique identifier for this device in per-device sync mode (alphanumeric only)</string>
</property>
<property name="placeholderText">
<string>Auto-detected from system</string>
</property>
</widget>
Comment on lines +85 to +95
Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The device ID field in the UI doesn't provide real-time validation feedback to the user. When a user enters special characters, they won't know those characters will be stripped until they save and reload the settings. Consider adding a validator to the QLineEdit (using QRegularExpressionValidator with pattern "[A-Za-z0-9]*") or connecting to textChanged to show immediate feedback about which characters are allowed.

Copilot uses AI. Check for mistakes.
</item>
<item row="0" column="2">
<spacer name="deviceIdSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="ownCertificateGroupBox">
<property name="title">
Expand Down
Loading