diff --git a/src/core/Config.cpp b/src/core/Config.cpp index f874d8fb2..7a60e05b3 100644 --- a/src/core/Config.cpp +++ b/src/core/Config.cpp @@ -73,7 +73,7 @@ static const QHash configStrings = { {Config::AutoTypeStartDelay,{QS("AutoTypeStartDelay"), Roaming, 500}}, {Config::GlobalAutoTypeKey,{QS("GlobalAutoTypeKey"), Roaming, 0}}, {Config::GlobalAutoTypeModifiers,{QS("GlobalAutoTypeModifiers"), Roaming, 0}}, - {Config::IgnoreGroupExpansion,{QS("IgnoreGroupExpansion"), Roaming, true}}, + {Config::TrackNonDataChanges,{QS("TrackNonDataChanges"), Roaming, false}}, {Config::FaviconDownloadTimeout,{QS("FaviconDownloadTimeout"), Roaming, 10}}, {Config::UpdateCheckMessageShown,{QS("UpdateCheckMessageShown"), Roaming, true}}, {Config::UseTouchID,{QS("UseTouchID"), Roaming, false}}, @@ -125,9 +125,9 @@ static const QHash configStrings = { {Config::Security_LockDatabaseMinimize, {QS("Security/LockDatabaseMinimize"), Roaming, false}}, {Config::Security_LockDatabaseScreenLock, {QS("Security/LockDatabaseScreenLock"), Roaming, true}}, {Config::Security_RelockAutoType, {QS("Security/RelockAutoType"), Roaming, false}}, - {Config::Security_PasswordsRepeat, {QS("Security/PasswordsRepeat"), Roaming, false}}, - {Config::Security_PasswordsCleartext, {QS("Security/PasswordsCleartext"), Roaming, false}}, - {Config::Security_PasswordEmptyNoDots, {QS("Security/PasswordEmptyNoDots"), Roaming, true}}, + {Config::Security_PasswordsRepeatVisible, {QS("Security/PasswordsRepeatVisible"), Roaming, true}}, + {Config::Security_PasswordsHidden, {QS("Security/PasswordsHidden"), Roaming, true}}, + {Config::Security_PasswordEmptyPlaceholder, {QS("Security/PasswordEmptyPlaceholder"), Roaming, false}}, {Config::Security_HidePasswordPreviewPanel, {QS("Security/HidePasswordPreviewPanel"), Roaming, true}}, {Config::Security_AutoTypeAsk, {QS("Security/AutotypeAsk"), Roaming, true}}, {Config::Security_IconDownloadFallback, {QS("Security/IconDownloadFallback"), Roaming, false}}, @@ -290,6 +290,7 @@ static const QHash deprecationMap = { {QS("security/IconDownloadFallbackToGoogle"), Config::Security_IconDownloadFallback}, // 2.6.0 + {QS("IgnoreGroupExpansion"), Config::TrackNonDataChanges}, {QS("security/autotypeask"), Config::Security_AutoTypeAsk}, {QS("security/clearclipboard"), Config::Security_ClearClipboard}, {QS("security/clearclipboardtimeout"), Config::Security_ClearClipboardTimeout}, @@ -301,10 +302,10 @@ static const QHash deprecationMap = { {QS("security/lockdatabasescreenlock"), Config::Security_LockDatabaseScreenLock}, {QS("security/relockautotype"), Config::Security_RelockAutoType}, {QS("security/IconDownloadFallback"), Config::Security_IconDownloadFallback}, - {QS("security/passwordscleartext"), Config::Security_PasswordsCleartext}, - {QS("security/passwordemptynodots"), Config::Security_PasswordEmptyNoDots}, + {QS("security/passwordscleartext"), Config::Security_PasswordsHidden}, + {QS("security/passwordemptynodots"), Config::Security_PasswordEmptyPlaceholder}, {QS("security/HidePasswordPreviewPanel"), Config::Security_HidePasswordPreviewPanel}, - {QS("security/passwordsrepeat"), Config::Security_PasswordsRepeat}, + {QS("security/passwordsrepeat"), Config::Security_PasswordsRepeatVisible}, {QS("security/hidenotes"), Config::Security_HideNotes}, {QS("security/resettouchid"), Config::Security_ResetTouchId}, {QS("security/resettouchidtimeout"), Config::Security_ResetTouchIdTimeout}, @@ -353,7 +354,13 @@ void Config::migrate() for (const auto& setting : deprecationMap.keys()) { QVariant value; if (m_settings->contains(setting)) { - value = m_settings->value(setting); + if (setting == QS("IgnoreGroupExpansion") || setting == QS("security/passwordsrepeat") + || setting == QS("security/passwordscleartext") || setting == QS("security/passwordemptynodots")) { + // Keep user's original setting for boolean settings whose meanings were reversed + value = !m_settings->value(setting).toBool(); + } else { + value = m_settings->value(setting); + } m_settings->remove(setting); } else if (m_localSettings && m_localSettings->contains(setting)) { value = m_localSettings->value(setting); diff --git a/src/core/Config.h b/src/core/Config.h index 0914f1cbe..0141edce3 100644 --- a/src/core/Config.h +++ b/src/core/Config.h @@ -57,7 +57,7 @@ public: AutoTypeStartDelay, GlobalAutoTypeKey, GlobalAutoTypeModifiers, - IgnoreGroupExpansion, + TrackNonDataChanges, FaviconDownloadTimeout, UpdateCheckMessageShown, UseTouchID, @@ -107,9 +107,9 @@ public: Security_LockDatabaseMinimize, Security_LockDatabaseScreenLock, Security_RelockAutoType, - Security_PasswordsRepeat, - Security_PasswordsCleartext, - Security_PasswordEmptyNoDots, + Security_PasswordsRepeatVisible, + Security_PasswordsHidden, + Security_PasswordEmptyPlaceholder, Security_HidePasswordPreviewPanel, Security_AutoTypeAsk, Security_IconDownloadFallback, diff --git a/src/core/Group.cpp b/src/core/Group.cpp index acb6d114d..ce29a5cc4 100644 --- a/src/core/Group.cpp +++ b/src/core/Group.cpp @@ -364,7 +364,7 @@ void Group::setExpanded(bool expanded) { if (m_data.isExpanded != expanded) { m_data.isExpanded = expanded; - if (config()->get(Config::IgnoreGroupExpansion).toBool()) { + if (!config()->get(Config::TrackNonDataChanges).toBool()) { updateTimeinfo(); return; } diff --git a/src/gui/ApplicationSettingsWidget.cpp b/src/gui/ApplicationSettingsWidget.cpp index 4dbe40697..9d1f45d49 100644 --- a/src/gui/ApplicationSettingsWidget.cpp +++ b/src/gui/ApplicationSettingsWidget.cpp @@ -196,7 +196,7 @@ void ApplicationSettingsWidget::loadSettings() config()->get(Config::UseGroupIconOnEntryCreation).toBool()); m_generalUi->autoTypeEntryTitleMatchCheckBox->setChecked(config()->get(Config::AutoTypeEntryTitleMatch).toBool()); m_generalUi->autoTypeEntryURLMatchCheckBox->setChecked(config()->get(Config::AutoTypeEntryURLMatch).toBool()); - m_generalUi->ignoreGroupExpansionCheckBox->setChecked(config()->get(Config::IgnoreGroupExpansion).toBool()); + m_generalUi->trackNonDataChangesCheckBox->setChecked(config()->get(Config::TrackNonDataChanges).toBool()); m_generalUi->faviconTimeoutSpinBox->setValue(config()->get(Config::FaviconDownloadTimeout).toInt()); if (!m_generalUi->hideWindowOnCopyCheckBox->isChecked()) { @@ -274,11 +274,12 @@ void ApplicationSettingsWidget::loadSettings() m_secUi->relockDatabaseAutoTypeCheckBox->setChecked(config()->get(Config::Security_RelockAutoType).toBool()); m_secUi->fallbackToSearch->setChecked(config()->get(Config::Security_IconDownloadFallback).toBool()); - m_secUi->passwordCleartextCheckBox->setChecked(config()->get(Config::Security_PasswordsCleartext).toBool()); - m_secUi->passwordShowDotsCheckBox->setChecked(config()->get(Config::Security_PasswordEmptyNoDots).toBool()); + m_secUi->passwordsHiddenCheckBox->setChecked(config()->get(Config::Security_PasswordsHidden).toBool()); + m_secUi->passwordShowDotsCheckBox->setChecked(config()->get(Config::Security_PasswordEmptyPlaceholder).toBool()); m_secUi->passwordPreviewCleartextCheckBox->setChecked( config()->get(Config::Security_HidePasswordPreviewPanel).toBool()); - m_secUi->passwordRepeatCheckBox->setChecked(config()->get(Config::Security_PasswordsRepeat).toBool()); + m_secUi->passwordsRepeatVisibleCheckBox->setChecked( + config()->get(Config::Security_PasswordsRepeatVisible).toBool()); m_secUi->hideNotesCheckBox->setChecked(config()->get(Config::Security_HideNotes).toBool()); m_secUi->touchIDResetCheckBox->setChecked(config()->get(Config::Security_ResetTouchId).toBool()); @@ -322,7 +323,7 @@ void ApplicationSettingsWidget::saveSettings() config()->set(Config::MinimizeOnCopy, m_generalUi->minimizeOnCopyRadioButton->isChecked()); config()->set(Config::DropToBackgroundOnCopy, m_generalUi->dropToBackgroundOnCopyRadioButton->isChecked()); config()->set(Config::UseGroupIconOnEntryCreation, m_generalUi->useGroupIconOnEntryCreationCheckBox->isChecked()); - config()->set(Config::IgnoreGroupExpansion, m_generalUi->ignoreGroupExpansionCheckBox->isChecked()); + config()->set(Config::TrackNonDataChanges, m_generalUi->trackNonDataChangesCheckBox->isChecked()); config()->set(Config::AutoTypeEntryTitleMatch, m_generalUi->autoTypeEntryTitleMatchCheckBox->isChecked()); config()->set(Config::AutoTypeEntryURLMatch, m_generalUi->autoTypeEntryURLMatchCheckBox->isChecked()); config()->set(Config::FaviconDownloadTimeout, m_generalUi->faviconTimeoutSpinBox->value()); @@ -369,11 +370,11 @@ void ApplicationSettingsWidget::saveSettings() config()->set(Config::Security_RelockAutoType, m_secUi->relockDatabaseAutoTypeCheckBox->isChecked()); config()->set(Config::Security_IconDownloadFallback, m_secUi->fallbackToSearch->isChecked()); - config()->set(Config::Security_PasswordsCleartext, m_secUi->passwordCleartextCheckBox->isChecked()); - config()->set(Config::Security_PasswordEmptyNoDots, m_secUi->passwordShowDotsCheckBox->isChecked()); + config()->set(Config::Security_PasswordsHidden, m_secUi->passwordsHiddenCheckBox->isChecked()); + config()->set(Config::Security_PasswordEmptyPlaceholder, m_secUi->passwordShowDotsCheckBox->isChecked()); config()->set(Config::Security_HidePasswordPreviewPanel, m_secUi->passwordPreviewCleartextCheckBox->isChecked()); - config()->set(Config::Security_PasswordsRepeat, m_secUi->passwordRepeatCheckBox->isChecked()); + config()->set(Config::Security_PasswordsRepeatVisible, m_secUi->passwordsRepeatVisibleCheckBox->isChecked()); config()->set(Config::Security_HideNotes, m_secUi->hideNotesCheckBox->isChecked()); config()->set(Config::Security_ResetTouchId, m_secUi->touchIDResetCheckBox->isChecked()); diff --git a/src/gui/ApplicationSettingsWidgetGeneral.ui b/src/gui/ApplicationSettingsWidgetGeneral.ui index 55cb28ac5..86415959c 100644 --- a/src/gui/ApplicationSettingsWidgetGeneral.ui +++ b/src/gui/ApplicationSettingsWidgetGeneral.ui @@ -6,6 +6,8 @@ 0 0 + 559 + 1280 @@ -228,9 +230,9 @@ - + - Don't mark database as modified for non-data changes (e.g., expanding groups) + Mark database as modified for non-data changes (e.g., expanding groups) diff --git a/src/gui/ApplicationSettingsWidgetSecurity.ui b/src/gui/ApplicationSettingsWidgetSecurity.ui index 2310bd07d..c39105c06 100644 --- a/src/gui/ApplicationSettingsWidgetSecurity.ui +++ b/src/gui/ApplicationSettingsWidgetSecurity.ui @@ -7,7 +7,7 @@ 0 0 595 - 541 + 567 @@ -223,23 +223,23 @@ - + - Don't require password repeat when it is visible + Require password repeat when it is visible - + - Don't hide passwords when editing them + Hide passwords when editing them - Don't use placeholder for empty password fields + Use placeholder for empty password fields @@ -302,8 +302,8 @@ touchIDResetOnScreenLockCheckBox lockDatabaseMinimizeCheckBox relockDatabaseAutoTypeCheckBox - passwordRepeatCheckBox - passwordCleartextCheckBox + passwordsRepeatVisibleCheckBox + passwordsHiddenCheckBox passwordShowDotsCheckBox passwordPreviewCleartextCheckBox hideNotesCheckBox diff --git a/src/gui/EntryPreviewWidget.cpp b/src/gui/EntryPreviewWidget.cpp index f0301017c..0a46417e0 100644 --- a/src/gui/EntryPreviewWidget.cpp +++ b/src/gui/EntryPreviewWidget.cpp @@ -186,7 +186,7 @@ void EntryPreviewWidget::setPasswordVisible(bool state) if (state) { m_ui->entryPasswordLabel->setText(password); m_ui->entryPasswordLabel->setCursorPosition(0); - } else if (password.isEmpty() && config()->get(Config::Security_PasswordEmptyNoDots).toBool()) { + } else if (password.isEmpty() && !config()->get(Config::Security_PasswordEmptyPlaceholder).toBool()) { m_ui->entryPasswordLabel->setText(""); } else { m_ui->entryPasswordLabel->setText(QString("\u25cf").repeated(6)); diff --git a/src/gui/PasswordEdit.cpp b/src/gui/PasswordEdit.cpp index 75423fc89..487db8768 100644 --- a/src/gui/PasswordEdit.cpp +++ b/src/gui/PasswordEdit.cpp @@ -111,7 +111,7 @@ void PasswordEdit::setShowPassword(bool show) if (m_repeatPasswordEdit) { m_repeatPasswordEdit->setEchoMode(show ? QLineEdit::Normal : QLineEdit::Password); - if (config()->get(Config::Security_PasswordsRepeat).toBool()) { + if (!config()->get(Config::Security_PasswordsRepeatVisible).toBool()) { m_repeatPasswordEdit->setEnabled(!show); m_repeatPasswordEdit->setText(text()); } else { @@ -166,7 +166,7 @@ void PasswordEdit::updateRepeatStatus() void PasswordEdit::autocompletePassword(const QString& password) { - if (config()->get(Config::Security_PasswordsRepeat).toBool() && echoMode() == QLineEdit::Normal) { + if (!config()->get(Config::Security_PasswordsRepeatVisible).toBool() && echoMode() == QLineEdit::Normal) { setText(password); } } diff --git a/src/gui/entry/EditEntryWidget.cpp b/src/gui/entry/EditEntryWidget.cpp index 8f81d42cc..1b202bf08 100644 --- a/src/gui/entry/EditEntryWidget.cpp +++ b/src/gui/entry/EditEntryWidget.cpp @@ -844,7 +844,7 @@ void EditEntryWidget::setForms(Entry* entry, bool restore) m_mainUi->usernameComboBox->lineEdit()->setText(entry->username()); m_mainUi->urlEdit->setText(entry->url()); m_mainUi->passwordEdit->setText(entry->password()); - m_mainUi->passwordEdit->setShowPassword(config()->get(Config::Security_PasswordsCleartext).toBool()); + m_mainUi->passwordEdit->setShowPassword(!config()->get(Config::Security_PasswordsHidden).toBool()); if (!m_history) { m_mainUi->passwordEdit->enablePasswordGenerator(); } diff --git a/src/gui/entry/EntryModel.cpp b/src/gui/entry/EntryModel.cpp index fae4469ba..3dfdf20bc 100644 --- a/src/gui/entry/EntryModel.cpp +++ b/src/gui/entry/EntryModel.cpp @@ -174,7 +174,7 @@ QVariant EntryModel::data(const QModelIndex& index, int role) const if (attr->isReference(EntryAttributes::PasswordKey)) { result.prepend(tr("Ref: ", "Reference abbreviation")); } - if (entry->password().isEmpty() && config()->get(Config::Security_PasswordEmptyNoDots).toBool()) { + if (entry->password().isEmpty() && !config()->get(Config::Security_PasswordEmptyPlaceholder).toBool()) { result = ""; } return result; diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 96cb5267c..3a74622cb 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -222,6 +222,9 @@ add_unit_test(NAME testdatabase SOURCES TestDatabase.cpp add_unit_test(NAME testtools SOURCES TestTools.cpp LIBS ${TEST_LIBRARIES}) +add_unit_test(NAME testconfig SOURCES TestConfig.cpp + LIBS testsupport ${TEST_LIBRARIES}) + if(WITH_XC_FDOSECRETS) add_unit_test(NAME testfdosecrets SOURCES TestFdoSecrets.cpp LIBS testsupport ${TEST_LIBRARIES}) diff --git a/tests/TestConfig.cpp b/tests/TestConfig.cpp new file mode 100644 index 000000000..23661b046 --- /dev/null +++ b/tests/TestConfig.cpp @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2020 KeePassXC Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "TestConfig.h" + +#include +#include + +#include "config-keepassx-tests.h" +#include "core/Config.h" +#include "util/TemporaryFile.h" + +QTEST_GUILESS_MAIN(TestConfig) + +const QString oldTrueConfigPath = QString(KEEPASSX_TEST_DATA_DIR).append("/OutdatedConfig.ini"); + +// upgrade config file with deprecated settings (all of which are set to non-default values) +void TestConfig::testUpgrade() +{ + TemporaryFile tempFile; + + QVERIFY(tempFile.copyFromFile(oldTrueConfigPath)); + Config::createConfigFromFile(tempFile.fileName()); + + // value of new setting should be opposite the value of deprecated setting + QVERIFY(config()->get(Config::TrackNonDataChanges).toBool()); + QVERIFY(!config()->get(Config::Security_PasswordsRepeatVisible).toBool()); + QVERIFY(!config()->get(Config::Security_PasswordsHidden).toBool()); + QVERIFY(config()->get(Config::Security_PasswordEmptyPlaceholder).toBool()); + + tempFile.remove(); +} diff --git a/tests/TestConfig.h b/tests/TestConfig.h new file mode 100644 index 000000000..d5852acdd --- /dev/null +++ b/tests/TestConfig.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2020 KeePassXC Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef KEEPASSX_TESTCONFIG_H +#define KEEPASSX_TESTCONFIG_H + +#include "core/Config.h" + +class TestConfig : public QObject +{ + Q_OBJECT +private slots: + void testUpgrade(); +}; + +#endif // KEEPASSX_TESTCONFIG_H diff --git a/tests/data/OutdatedConfig.ini b/tests/data/OutdatedConfig.ini new file mode 100644 index 000000000..edc033057 --- /dev/null +++ b/tests/data/OutdatedConfig.ini @@ -0,0 +1,8 @@ +[General] +IgnoreGroupExpansion=false + +[security] +hidepassworddetails=false +passwordemptynodots=false +passwordscleartext=true +passwordsrepeat=true