diff --git a/src/lib/common/Settings.cpp b/src/lib/common/Settings.cpp index 048f8d83c..66fdd8443 100644 --- a/src/lib/common/Settings.cpp +++ b/src/lib/common/Settings.cpp @@ -33,6 +33,8 @@ void Settings::setSettingsFile(const QString &settingsFile) instance()->m_settings = new QSettings(settingsFile, QSettings::IniFormat, instance()); instance()->m_settingsProxy->load(settingsFile); qInfo().noquote() << "settings file changed:" << instance()->m_settings->fileName(); + + instance()->setupScreenName(); } void Settings::setStateFile(const QString &stateFile) @@ -80,6 +82,8 @@ Settings::Settings(QObject *parent) : QObject(parent) const auto stateFile = QStringLiteral("%1/%2.state").arg(stateBase, kAppName); m_stateSettings = new QSettings(stateFile, QSettings::IniFormat, this); + + setupScreenName(); } void Settings::cleanSettings() @@ -104,6 +108,35 @@ void Settings::cleanStateSettings() } } +void Settings::setupScreenName() +{ + if (m_settings->value(Settings::Core::ScreenName).isNull()) + m_settings->setValue(Settings::Core::ScreenName, cleanScreenName(QSysInfo::machineHostName())); +} + +QString Settings::cleanScreenName(const QString &name) +{ + static const auto hyphen = QStringLiteral("-"); + static const auto space = QStringLiteral(" "); + static const auto underscore = QStringLiteral("_"); + static const auto peroid = QStringLiteral("."); + static const auto nothing = QStringLiteral(""); + static const auto nameRegex = QRegularExpression(QStringLiteral("[^\\w\\-\\.]")); + + QString cleanName = name.simplified(); + cleanName.replace(space, underscore); + cleanName.replace(nameRegex, nothing); + while (cleanName.startsWith(hyphen) || cleanName.startsWith(underscore) || cleanName.startsWith(peroid)) + cleanName.removeFirst(); + while (cleanName.endsWith(hyphen) || cleanName.endsWith(underscore) || cleanName.endsWith(peroid)) + cleanName.removeLast(); + if (cleanName.length() > 255) { + cleanName.truncate(255); + cleanName = cleanScreenName(cleanName); + } + return cleanName; +} + int Settings::logLevelToInt(const QString &level) { // Can do this better later ? @@ -152,15 +185,6 @@ QVariant Settings::defaultValue(const QString &key) return true; } - if (key == Core::ScreenName) { - // The localhost name can contain spaces and non word characters - QString name = QSysInfo::machineHostName().simplified(); - name.replace(QLatin1String(" "), QStringLiteral("_")); - static const auto nameRegex = QRegularExpression(QLatin1String("\\W")); - name.replace(nameRegex, QLatin1String("")); - return name; - } - if (key == Gui::WindowGeometry) return QRect(); @@ -287,8 +311,12 @@ void Settings::setValue(const QString &key, const QVariant &value) if (!value.isValid()) settings->remove(key); - else - settings->setValue(key, value); + else { + if (key == Settings::Core::ScreenName) + settings->setValue(key, cleanScreenName(value.toString())); + else + settings->setValue(key, value); + } settings->sync(); Q_EMIT instance()->settingsChanged(key); diff --git a/src/lib/common/Settings.h b/src/lib/common/Settings.h index be0d16982..b66eaada0 100644 --- a/src/lib/common/Settings.h +++ b/src/lib/common/Settings.h @@ -149,6 +149,18 @@ private: void cleanSettings(); void cleanStateSettings(); + /** + * @brief write an initial screen name + */ + void setupScreenName(); + + /** + * @brief cleanScreenName ensure a valid screenName from the provided one + * @param name any string to be used as the screenName + * @return a valid screeName + */ + static QString cleanScreenName(const QString &name); + QSettings *m_settings = nullptr; QSettings *m_stateSettings = nullptr; std::shared_ptr m_settingsProxy; diff --git a/src/unittests/common/SettingsTests.cpp b/src/unittests/common/SettingsTests.cpp index b73f5714f..f2c5a3167 100644 --- a/src/unittests/common/SettingsTests.cpp +++ b/src/unittests/common/SettingsTests.cpp @@ -61,7 +61,8 @@ void SettingsTests::checkValidSettings() QSignalSpy spy(Settings::instance(), &Settings::settingsChanged); QVERIFY(spy.isValid()); - const auto validKeys = Settings::validKeys(); + const auto keysToCheck = QRegularExpression(QLatin1String("[^%1]").arg(Settings::Core::ScreenName)); + const auto validKeys = Settings::validKeys().filter(keysToCheck); for (const auto &setting : validKeys) { const auto value = Settings::value(setting).toString(); QCOMPARE(Settings::defaultValue(setting).toString(), value); @@ -81,4 +82,28 @@ void SettingsTests::checkValidSettings() } } +void SettingsTests::checkCleanScreenName() +{ + const auto input = QStringLiteral("--!_ _-S@c#r$e%e^&*(n)= +Name\n[1]2|3?4--5>6<,7`~/8*90\\.lan--.. .."); + const auto expected = QStringLiteral("Screen_Name_1234--567890.lan"); + + Settings::setValue(Settings::Core::ScreenName, input); + + QCOMPARE(Settings::value(Settings::Core::ScreenName).toString(), expected); +} + +void SettingsTests::checkCleanScreenName_LongName() +{ + QString input; + input.fill('f', 300); + input.prepend('.'); + + QString expected; + expected.fill('f', 255); + + Settings::setValue(Settings::Core::ScreenName, input); + + QCOMPARE(Settings::value(Settings::Core::ScreenName).toString(), expected); +} + QTEST_MAIN(SettingsTests) diff --git a/src/unittests/common/SettingsTests.h b/src/unittests/common/SettingsTests.h index 06223ccc2..72fd401ac 100644 --- a/src/unittests/common/SettingsTests.h +++ b/src/unittests/common/SettingsTests.h @@ -23,6 +23,8 @@ private Q_SLOTS: void tlsTrustedServersDb(); void tlsTrustedClientsDb(); void checkValidSettings(); + void checkCleanScreenName(); + void checkCleanScreenName_LongName(); private: inline static const QString m_settingsPathTemp = QStringLiteral("tmp/test");