From 4a917d171d156812ed24320c6de727667ddcabaf Mon Sep 17 00:00:00 2001 From: Jonathan White Date: Tue, 14 Jul 2020 23:55:23 -0400 Subject: [PATCH 01/18] Improve restart requests * Fixes #4959 * Ask to restart when changing languages in application settings. --- src/gui/ApplicationSettingsWidget.cpp | 11 ++++++++++- src/gui/MainWindow.cpp | 15 +++++++++------ 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/gui/ApplicationSettingsWidget.cpp b/src/gui/ApplicationSettingsWidget.cpp index 691115368..8d958ab7a 100644 --- a/src/gui/ApplicationSettingsWidget.cpp +++ b/src/gui/ApplicationSettingsWidget.cpp @@ -27,6 +27,7 @@ #include "core/Global.h" #include "core/Resources.h" #include "core/Translator.h" +#include "gui/MainWindow.h" #include "gui/osutils/OSUtils.h" #include "MessageBox.h" @@ -324,7 +325,15 @@ void ApplicationSettingsWidget::saveSettings() config()->set(Config::AutoTypeEntryURLMatch, m_generalUi->autoTypeEntryURLMatchCheckBox->isChecked()); config()->set(Config::FaviconDownloadTimeout, m_generalUi->faviconTimeoutSpinBox->value()); - config()->set(Config::GUI_Language, m_generalUi->languageComboBox->currentData().toString()); + auto language = m_generalUi->languageComboBox->currentData().toString(); + if (config()->get(Config::GUI_Language) != language) { + QTimer::singleShot(200, [] { + getMainWindow()->restartApp( + tr("You must restart the application to set the new language. Would you like to restart now?")); + }); + } + config()->set(Config::GUI_Language, language); + config()->set(Config::GUI_MovableToolbar, m_generalUi->toolbarMovableCheckBox->isChecked()); config()->set(Config::GUI_MonospaceNotes, m_generalUi->monospaceNotesCheckBox->isChecked()); diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp index 9751a3e77..2ae78157e 100644 --- a/src/gui/MainWindow.cpp +++ b/src/gui/MainWindow.cpp @@ -1679,17 +1679,20 @@ void MainWindow::initViewMenu() } } - connect(themeActions, &QActionGroup::triggered, this, [this](QAction* action) { - if (action->data() != config()->get(Config::GUI_ApplicationTheme)) { - config()->set(Config::GUI_ApplicationTheme, action->data()); + connect(themeActions, &QActionGroup::triggered, this, [this, theme](QAction* action) { + config()->set(Config::GUI_ApplicationTheme, action->data()); + if (action->data() != theme) { restartApp(tr("You must restart the application to apply this setting. Would you like to restart now?")); } }); - m_ui->actionCompactMode->setChecked(config()->get(Config::GUI_CompactMode).toBool()); - connect(m_ui->actionCompactMode, &QAction::toggled, this, [this](bool checked) { + bool compact = config()->get(Config::GUI_CompactMode).toBool(); + m_ui->actionCompactMode->setChecked(compact); + connect(m_ui->actionCompactMode, &QAction::toggled, this, [this, compact](bool checked) { config()->set(Config::GUI_CompactMode, checked); - restartApp(tr("You must restart the application to apply this setting. Would you like to restart now?")); + if (checked != compact) { + restartApp(tr("You must restart the application to apply this setting. Would you like to restart now?")); + } }); m_ui->actionShowToolbar->setChecked(!config()->get(Config::GUI_HideToolbar).toBool()); From e02a63b0616d75c5d6b4f8894d3b25e8b732f784 Mon Sep 17 00:00:00 2001 From: Jonathan White Date: Thu, 9 Jul 2020 21:36:31 -0400 Subject: [PATCH 02/18] Prevent crash if focus widget gets deleted during saving * Fixes #4966 --- src/gui/DatabaseWidget.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gui/DatabaseWidget.cpp b/src/gui/DatabaseWidget.cpp index 61f2b2163..042e2a561 100644 --- a/src/gui/DatabaseWidget.cpp +++ b/src/gui/DatabaseWidget.cpp @@ -1813,7 +1813,7 @@ bool DatabaseWidget::save() m_blockAutoSave = true; ++m_saveAttempts; - auto focusWidget = qApp->focusWidget(); + QPointer focusWidget(qApp->focusWidget()); // TODO: Make this async // Lock out interactions @@ -1887,7 +1887,7 @@ bool DatabaseWidget::saveAs() bool ok = false; if (!newFilePath.isEmpty()) { - auto focusWidget = qApp->focusWidget(); + QPointer focusWidget(qApp->focusWidget()); // Lock out interactions m_entryView->setDisabled(true); From 2631ae682dfeebedada44f960cefc8018ccdd9d3 Mon Sep 17 00:00:00 2001 From: AsavarTzeth Date: Mon, 1 Jul 2019 17:27:58 +0200 Subject: [PATCH 03/18] Add OARS metadata It is usable by both Gnome Software, KDE Discover and web frontends, such as Flathub which now enforces OARS. By using OARS 1.0 all distributions should be supported. Version 1.1 should work almost everywhere, but there are a few notable distributions that still lack GNOME Software >= 3.27.3. In this case it should not matter, because the OARS data is the same for both versions (nothing 1.1 specific is used). You can generate and verify these changes using: https://odrs.gnome.org/oars --- share/linux/org.keepassxc.KeePassXC.appdata.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/share/linux/org.keepassxc.KeePassXC.appdata.xml b/share/linux/org.keepassxc.KeePassXC.appdata.xml index 9227251d6..40264b702 100644 --- a/share/linux/org.keepassxc.KeePassXC.appdata.xml +++ b/share/linux/org.keepassxc.KeePassXC.appdata.xml @@ -614,4 +614,5 @@ + From 02f6a59c1048e1bca275298bc260eb9892388cbb Mon Sep 17 00:00:00 2001 From: AsavarTzeth Date: Sat, 11 Jul 2020 15:00:44 +0200 Subject: [PATCH 04/18] Fix appdata screenshots Update url filenames to reflect updates at keepassxc.org --- share/linux/org.keepassxc.KeePassXC.appdata.xml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/share/linux/org.keepassxc.KeePassXC.appdata.xml b/share/linux/org.keepassxc.KeePassXC.appdata.xml index 40264b702..62c17b333 100644 --- a/share/linux/org.keepassxc.KeePassXC.appdata.xml +++ b/share/linux/org.keepassxc.KeePassXC.appdata.xml @@ -28,23 +28,23 @@ - https://keepassxc.org/images/screenshots/linux/screen_001.png + https://keepassxc.org/images/screenshots/thumbs/welcome_screen.png Create, Import or Open Databases - https://keepassxc.org/images/screenshots/linux/screen_002.png + https://keepassxc.org/images/screenshots/thumbs/database_view.png Organize with Groups and Entries - https://keepassxc.org/images/screenshots/linux/screen_003.png + https://keepassxc.org/images/screenshots/thumbs/edit_entry.png Database Entry - https://keepassxc.org/images/screenshots/linux/screen_004.png + https://keepassxc.org/images/screenshots/thumbs/edit_entry_icons.png Icon Selection for Entry - https://keepassxc.org/images/screenshots/linux/screen_006.png + https://keepassxc.org/images/screenshots/thumbs/password_generator_advanced.png Password Generator From 005d9d368f5cc3ed97975bf564eba6001b4810e0 Mon Sep 17 00:00:00 2001 From: alcroito Date: Mon, 13 Jul 2020 18:31:00 +0200 Subject: [PATCH 05/18] Skip referenced passwords in Health check report Fixes #5036 --- src/core/PasswordHealth.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/PasswordHealth.cpp b/src/core/PasswordHealth.cpp index 6fdbf6c36..750fe39f1 100644 --- a/src/core/PasswordHealth.cpp +++ b/src/core/PasswordHealth.cpp @@ -106,7 +106,7 @@ HealthChecker::HealthChecker(QSharedPointer db) { // Build the cache of re-used passwords for (const auto* entry : db->rootGroup()->entriesRecursive()) { - if (!entry->isRecycled()) { + if (!entry->isRecycled() && !entry->isAttributeReference("Password")) { m_reuse[entry->password()] << QApplication::tr("Used in %1/%2").arg(entry->group()->hierarchy().join('/'), entry->title()); } From 7c39907251a73e91b81f2ae8cc3e0703cb494933 Mon Sep 17 00:00:00 2001 From: Toni Spets Date: Fri, 17 Jul 2020 19:36:24 +0300 Subject: [PATCH 06/18] Substitute tilde with USERPROFILE on Windows The substitution is now more shell-like and tilde is only replaced from the beginning of the path if it is trailed by a slash. --- src/core/Tools.cpp | 6 +++++- tests/TestTools.cpp | 4 ++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/core/Tools.cpp b/src/core/Tools.cpp index 1b3eafcca..d29e92bff 100644 --- a/src/core/Tools.cpp +++ b/src/core/Tools.cpp @@ -331,11 +331,15 @@ namespace Tools #if defined(Q_OS_WIN) QRegularExpression varRe("\\%([A-Za-z][A-Za-z0-9_]*)\\%"); + QString homeEnv = "USERPROFILE"; #else QRegularExpression varRe("\\$([A-Za-z][A-Za-z0-9_]*)"); - subbed.replace("~", environment.value("HOME")); + QString homeEnv = "HOME"; #endif + if (subbed.startsWith("~/") || subbed.startsWith("~\\")) + subbed.replace(0, 1, environment.value(homeEnv)); + QRegularExpressionMatch match; do { diff --git a/tests/TestTools.cpp b/tests/TestTools.cpp index 4809a8bc9..cdce6e04e 100644 --- a/tests/TestTools.cpp +++ b/tests/TestTools.cpp @@ -72,10 +72,14 @@ void TestTools::testEnvSubstitute() #if defined(Q_OS_WIN) environment.insert("HOMEDRIVE", "C:"); environment.insert("HOMEPATH", "\\Users\\User"); + environment.insert("USERPROFILE", "C:\\Users\\User"); QCOMPARE(Tools::envSubstitute("%HOMEDRIVE%%HOMEPATH%\\.ssh\\id_rsa", environment), QString("C:\\Users\\User\\.ssh\\id_rsa")); QCOMPARE(Tools::envSubstitute("start%EMPTY%%EMPTY%%%HOMEDRIVE%%end", environment), QString("start%C:%end")); + QCOMPARE(Tools::envSubstitute("%USERPROFILE%\\.ssh\\id_rsa", environment), + QString("C:\\Users\\User\\.ssh\\id_rsa")); + QCOMPARE(Tools::envSubstitute("~\\.ssh\\id_rsa", environment), QString("C:\\Users\\User\\.ssh\\id_rsa")); #else environment.insert("HOME", QString("/home/user")); environment.insert("USER", QString("user")); From 747be8d6290cd23ac29e70d8a333ce8792fd2ca8 Mon Sep 17 00:00:00 2001 From: Toni Spets Date: Fri, 17 Jul 2020 19:16:24 +0300 Subject: [PATCH 07/18] SSH Agent: Always forget all keys on lock Fixes #5016. --- src/sshagent/SSHAgent.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/sshagent/SSHAgent.cpp b/src/sshagent/SSHAgent.cpp index 20284c685..c43cc37a6 100644 --- a/src/sshagent/SSHAgent.cpp +++ b/src/sshagent/SSHAgent.cpp @@ -447,12 +447,8 @@ void SSHAgent::databaseLocked() if (!removeIdentity(key)) { emit error(m_error); } - it = m_addedKeys.erase(it); - } else { - // don't remove it yet - m_addedKeys[key].second = false; - ++it; } + it = m_addedKeys.erase(it); } } From d6857e654f10a6d451df5546c07e63ae7859e2ed Mon Sep 17 00:00:00 2001 From: Jonathan White Date: Thu, 16 Jul 2020 18:45:30 -0400 Subject: [PATCH 08/18] Fix minor TOTP issues * Fix #5105 - prevent divide-by-zero segfault due to invalid TOTP settings * Clear TOTP settings if attributes are removed --- src/core/Entry.cpp | 2 ++ src/totp/totp.cpp | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/core/Entry.cpp b/src/core/Entry.cpp index 65a271c2e..0322d353c 100644 --- a/src/core/Entry.cpp +++ b/src/core/Entry.cpp @@ -481,6 +481,8 @@ void Entry::updateTotp() m_attributes->value(Totp::ATTRIBUTE_SEED)); } else if (m_attributes->contains(Totp::ATTRIBUTE_OTP)) { m_data.totpSettings = Totp::parseSettings(m_attributes->value(Totp::ATTRIBUTE_OTP)); + } else { + m_data.totpSettings.reset(); } } diff --git a/src/totp/totp.cpp b/src/totp/totp.cpp index 105196fcd..1936cce75 100644 --- a/src/totp/totp.cpp +++ b/src/totp/totp.cpp @@ -113,7 +113,7 @@ QSharedPointer Totp::parseSettings(const QString& rawSettings, c } // Bound digits and step - settings->digits = qMax(1u, settings->digits); + settings->digits = qBound(1u, settings->digits, 10u); settings->step = qBound(1u, settings->step, 60u); // Detect custom settings, used by setup GUI From a5d75e4f4c2e7ccfd118e2cde4ae1c52bb1c6c3f Mon Sep 17 00:00:00 2001 From: Tobias Kortkamp Date: Sat, 18 Jul 2020 14:41:54 +0200 Subject: [PATCH 09/18] Unbreak build with Ninja When using cmake -GNinja the build fails with ninja: error: '/usr/ports/security/keepassxc/work/keepassxc-2.6.0/docs/man/*', needed by 'docs/keepassxc.1', missing and no known rule to make it Signed-off-by: Tobias Kortkamp --- docs/CMakeLists.txt | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/docs/CMakeLists.txt b/docs/CMakeLists.txt index 8a64701cc..9753dad29 100644 --- a/docs/CMakeLists.txt +++ b/docs/CMakeLists.txt @@ -24,18 +24,20 @@ set(DOC_DIR ${CMAKE_CURRENT_SOURCE_DIR}) set(OUT_DIR ${CMAKE_CURRENT_BINARY_DIR}) # Build html documentation on all platforms +file(GLOB html_depends ${DOC_DIR}/topics/* ${DOC_DIR}/styles/* ${DOC_DIR}/images/*) add_custom_command(OUTPUT KeePassXC_GettingStarted.html COMMAND ${ASCIIDOCTOR_EXE} -D ${OUT_DIR} -o KeePassXC_GettingStarted.html ${DOC_DIR}/GettingStarted.adoc - DEPENDS ${DOC_DIR}/topics/* ${DOC_DIR}/styles/* ${DOC_DIR}/images/* ${DOC_DIR}/GettingStarted.adoc + DEPENDS ${html_depends} ${DOC_DIR}/GettingStarted.adoc VERBATIM) add_custom_command(OUTPUT KeePassXC_UserGuide.html COMMAND ${ASCIIDOCTOR_EXE} -D ${OUT_DIR} -o KeePassXC_UserGuide.html ${DOC_DIR}/UserGuide.adoc - DEPENDS ${DOC_DIR}/topics/* ${DOC_DIR}/styles/* ${DOC_DIR}/images/* ${DOC_DIR}/UserGuide.adoc + DEPENDS ${html_depends} ${DOC_DIR}/UserGuide.adoc WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} VERBATIM) +file(GLOB styles_depends ${DOC_DIR}/styles/*) add_custom_command(OUTPUT KeePassXC_KeyboardShortcuts.html COMMAND ${ASCIIDOCTOR_EXE} -D ${OUT_DIR} -o KeePassXC_KeyboardShortcuts.html ${DOC_DIR}/topics/KeyboardShortcuts.adoc - DEPENDS ${DOC_DIR}/topics/KeyboardShortcuts.adoc ${DOC_DIR}/styles/* + DEPENDS ${DOC_DIR}/topics/KeyboardShortcuts.adoc ${styles_depends} VERBATIM) add_custom_target(docs ALL DEPENDS KeePassXC_GettingStarted.html KeePassXC_UserGuide.html KeePassXC_KeyboardShortcuts.html) @@ -50,11 +52,11 @@ install(FILES if(APPLE OR UNIX) add_custom_command(OUTPUT keepassxc.1 COMMAND ${ASCIIDOCTOR_EXE} -D ${OUT_DIR} -b manpage ${DOC_DIR}/man/keepassxc.1.adoc - DEPENDS ${DOC_DIR}/man/* + DEPENDS ${DOC_DIR}/man/keepassxc.1.adoc VERBATIM) add_custom_command(OUTPUT keepassxc-cli.1 COMMAND ${ASCIIDOCTOR_EXE} -D ${OUT_DIR} -b manpage ${DOC_DIR}/man/keepassxc-cli.1.adoc - DEPENDS ${DOC_DIR}/man/* + DEPENDS ${DOC_DIR}/man/keepassxc-cli.1.adoc VERBATIM) add_custom_target(manpages ALL DEPENDS keepassxc.1 keepassxc-cli.1) From e1a264825adf391a3d7a4a78d554690815127f18 Mon Sep 17 00:00:00 2001 From: Jonathan White Date: Sat, 18 Jul 2020 10:20:54 -0400 Subject: [PATCH 10/18] PasswordEdit use CTRL modifier on all platforms * Fixes #5114 --- src/gui/PasswordEdit.cpp | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/gui/PasswordEdit.cpp b/src/gui/PasswordEdit.cpp index 487db8768..943164d4c 100644 --- a/src/gui/PasswordEdit.cpp +++ b/src/gui/PasswordEdit.cpp @@ -50,21 +50,28 @@ PasswordEdit::PasswordEdit(QWidget* parent) passwordFont.setLetterSpacing(QFont::PercentageSpacing, 110); setFont(passwordFont); + // Prevent conflicts with global Mac shortcuts (force Control on all platforms) +#ifdef Q_OS_MAC + auto modifier = Qt::META; +#else + auto modifier = Qt::CTRL; +#endif + m_toggleVisibleAction = new QAction( resources()->icon("password-show-off"), - tr("Toggle Password (%1)").arg(QKeySequence(Qt::CTRL + Qt::Key_H).toString(QKeySequence::NativeText)), + tr("Toggle Password (%1)").arg(QKeySequence(modifier + Qt::Key_H).toString(QKeySequence::NativeText)), nullptr); m_toggleVisibleAction->setCheckable(true); - m_toggleVisibleAction->setShortcut(Qt::CTRL + Qt::Key_H); + m_toggleVisibleAction->setShortcut(modifier + Qt::Key_H); m_toggleVisibleAction->setShortcutContext(Qt::WidgetShortcut); addAction(m_toggleVisibleAction, QLineEdit::TrailingPosition); connect(m_toggleVisibleAction, &QAction::triggered, this, &PasswordEdit::setShowPassword); m_passwordGeneratorAction = new QAction( resources()->icon("password-generator"), - tr("Generate Password (%1)").arg(QKeySequence(Qt::CTRL + Qt::Key_G).toString(QKeySequence::NativeText)), + tr("Generate Password (%1)").arg(QKeySequence(modifier + Qt::Key_G).toString(QKeySequence::NativeText)), nullptr); - m_passwordGeneratorAction->setShortcut(Qt::CTRL + Qt::Key_G); + m_passwordGeneratorAction->setShortcut(modifier + Qt::Key_G); m_passwordGeneratorAction->setShortcutContext(Qt::WidgetShortcut); addAction(m_passwordGeneratorAction, QLineEdit::TrailingPosition); m_passwordGeneratorAction->setVisible(false); From fb7cc673aca0cd69d375c65d0b7bb1ee2804ec6f Mon Sep 17 00:00:00 2001 From: tuxmaster5000 <837503+tuxmaster5000@users.noreply.github.com> Date: Tue, 14 Jul 2020 09:39:23 +0200 Subject: [PATCH 11/18] Add Qt translation dir for RPM packaging --- src/core/Translator.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/core/Translator.cpp b/src/core/Translator.cpp index ff7dafde5..d97a35dd1 100644 --- a/src/core/Translator.cpp +++ b/src/core/Translator.cpp @@ -71,6 +71,8 @@ bool Translator::installTranslator(const QStringList& languages, const QString& QScopedPointer translator(new QTranslator(qApp)); if (translator->load(locale, "keepassx_", "", path)) { return QCoreApplication::installTranslator(translator.take()); + } else if (translator->load(locale, "keepassx_", "", QLibraryInfo::location(QLibraryInfo::TranslationsPath))) { + return QCoreApplication::installTranslator(translator.take()); } } From f3f6ce3943936a024c74c0b1c0c9ebb00ad1199f Mon Sep 17 00:00:00 2001 From: Janek Bevendorff Date: Tue, 7 Jul 2020 20:18:50 +0200 Subject: [PATCH 12/18] Update changelog --- CHANGELOG.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fe0d2f6b4..be1ff1e92 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,8 +4,9 @@ ### Added -- Custom Light and Dark themes [#4110, #4769, #4791, #4796, #4892, #4915] +- Custom Light and Dark themes [#4110, #4769, #4791, #4892, #4915] - Compact mode to use classic Group and Entry line height [#4910] +- New monochrome tray icons [#4796, #4803] - View menu to quickly switch themes, compact mode, and toggle UI elements [#4910] - Search for groups and scope search to matched groups [#4705] - Save Database Backup feature [#4550] @@ -66,9 +67,11 @@ - Improve search help widget displaying on macOS and Linux [#4236] - Return keyboard focus after editing an entry [#4287] - Reset database path after failed "Save As" [#4526] -- Use SHA256 Digest for Windows code signing [#4129] +- Make builds reproducible [#4411] - Improve handling of ccache when building [#4104, #4335] +- Windows: Use correct UI font and size [#4769] - macOS: Properly re-hide application window after browser integration and Auto-Type usage [#4909] +- Linux: Fix version number not embedded in AppImage [#4842] - Auto-Type: Fix crash when performing on new entry [#4132] - Browser: Send legacy HTTP settings to recycle bin [#4589] - Browser: Fix merging browser keys [#4685] From 10dc85923155854ad1f46f6a203f791e0370380d Mon Sep 17 00:00:00 2001 From: Ingo Heimbach Date: Wed, 8 Jul 2020 08:06:40 +0200 Subject: [PATCH 13/18] Add support for the Xfce screensaver --- src/core/ScreenLockListenerDBus.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/core/ScreenLockListenerDBus.cpp b/src/core/ScreenLockListenerDBus.cpp index 66970aee3..2086e3302 100644 --- a/src/core/ScreenLockListenerDBus.cpp +++ b/src/core/ScreenLockListenerDBus.cpp @@ -51,6 +51,13 @@ ScreenLockListenerDBus::ScreenLockListenerDBus(QWidget* parent) this, // receiver SLOT(gnomeSessionStatusChanged(uint))); + sessionBus.connect("org.xfce.ScreenSaver", // service + "/org/xfce/ScreenSaver", // path + "org.xfce.ScreenSaver", // interface + "ActiveChanged", // signal name + this, // receiver + SLOT(freedesktopScreenSaver(bool))); + systemBus.connect("org.freedesktop.login1", // service "/org/freedesktop/login1", // path "org.freedesktop.login1.Manager", // interface From a52b0c5439b273671b2e60143d5eece39aa3f71a Mon Sep 17 00:00:00 2001 From: mihkel-t <47502080+mihkel-t@users.noreply.github.com> Date: Wed, 8 Jul 2020 01:01:29 +0200 Subject: [PATCH 14/18] Add available translations for GenericName Taken from the .ts files, specifically the translations of phrases "Password Manager" and "KeePassXC - cross-platform password manager" (translations of the latter then appropriately cropped, with some help from Google Translate for the scripts I can't read). Also add Estonian translation for Comment. --- share/linux/org.keepassxc.KeePassXC.desktop | 26 +++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/share/linux/org.keepassxc.KeePassXC.desktop b/share/linux/org.keepassxc.KeePassXC.desktop index 541af3c02..693232e9e 100644 --- a/share/linux/org.keepassxc.KeePassXC.desktop +++ b/share/linux/org.keepassxc.KeePassXC.desktop @@ -1,13 +1,39 @@ [Desktop Entry] Name=KeePassXC GenericName=Password Manager +GenericName[ar]=مدير كلمات المرور +GenericName[bg]=Мениджър на пароли +GenericName[ca]=Gestor de contrasenyes +GenericName[cs]=Aplikace pro správu hesel GenericName[da]=Adgangskodehåndtering GenericName[de]=Passwortverwaltung GenericName[es]=Gestor de contraseñas +GenericName[et]=Paroolihaldur +GenericName[fi]=Salasanamanageri GenericName[fr]=Gestionnaire de mot de passe +GenericName[hu]=Jelszókezelő +GenericName[id]=Pengelola Sandi +GenericName[it]=Gestione password +GenericName[ja]=パスワードマネージャー +GenericName[ko]=암호 관리자 +GenericName[lt]=Slaptažodžių tvarkytuvė +GenericName[nb]=Passordhåndterer +GenericName[nl]=Wachtwoordbeheer +GenericName[pl]=Menedżer haseł +GenericName[pt_BR]=Gerenciador de Senhas +GenericName[pt]=Gestor de palavras-passe +GenericName[ro]=Manager de parole GenericName[ru]=менеджер паролей +GenericName[sk]=Správca hesiel +GenericName[sv]=Lösenordshanterare +GenericName[th]=แอพจัดการรหัสผ่าน +GenericName[tr]=Parola yöneticisi +GenericName[uk]=Розпорядник паролів +GenericName[zh_CN]=密码管理器 +GenericName[zh_TW]=密碼管理員 Comment=Community-driven port of the Windows application “KeePass Password Safe” Comment[da]=Fællesskabsdrevet port af Windows-programmet “KeePass Password Safe” +Comment[et]=Kogukonna arendatav port Windowsi programmist KeePass Password Safe Exec=keepassxc %f TryExec=keepassxc Icon=keepassxc From c2bdb48bc642fd85e3d4c5ad6a6234aa389f95ad Mon Sep 17 00:00:00 2001 From: Anton Vanda Date: Mon, 20 Jul 2020 23:45:52 +0300 Subject: [PATCH 15/18] Fix 'db-info' command name to show it right in 'help' * Fixes #5139 --- src/cli/Info.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cli/Info.cpp b/src/cli/Info.cpp index c57472770..800996d64 100644 --- a/src/cli/Info.cpp +++ b/src/cli/Info.cpp @@ -27,7 +27,7 @@ Info::Info() { - name = QString("db-show"); + name = QString("db-info"); description = QObject::tr("Show a database's information."); } From f73855a7f2168957a1a917ea4154445d8e1aa583 Mon Sep 17 00:00:00 2001 From: varjolintu Date: Sun, 7 Jun 2020 10:22:51 +0300 Subject: [PATCH 16/18] Adjust matching with best-matching credentials enabled --- src/browser/BrowserService.cpp | 29 ++++++++--- src/browser/BrowserService.h | 10 ++-- tests/TestBrowser.cpp | 94 +++++++++++++++++++++++++++++----- tests/TestBrowser.h | 1 + 4 files changed, 113 insertions(+), 21 deletions(-) diff --git a/src/browser/BrowserService.cpp b/src/browser/BrowserService.cpp index 1f54e33ca..e0b8dacc2 100644 --- a/src/browser/BrowserService.cpp +++ b/src/browser/BrowserService.cpp @@ -413,7 +413,7 @@ QJsonArray BrowserService::findMatchingEntries(const QString& dbid, } // Sort results - pwEntries = sortEntries(pwEntries, host, submitUrl); + pwEntries = sortEntries(pwEntries, host, submitUrl, url); // Fill the list QJsonArray result; @@ -698,7 +698,10 @@ void BrowserService::convertAttributesToCustomData(QSharedPointer db) } } -QList BrowserService::sortEntries(QList& pwEntries, const QString& host, const QString& entryUrl) +QList BrowserService::sortEntries(QList& pwEntries, + const QString& host, + const QString& entryUrl, + const QString& fullUrl) { QUrl url(entryUrl); if (url.scheme().isEmpty()) { @@ -712,7 +715,7 @@ QList BrowserService::sortEntries(QList& pwEntries, const QStrin // Build map of prioritized entries QMultiMap priorities; for (auto* entry : pwEntries) { - priorities.insert(sortPriority(entry, host, submitUrl, baseSubmitUrl), entry); + priorities.insert(sortPriority(entry, host, submitUrl, baseSubmitUrl, fullUrl), entry); } QList results; @@ -895,7 +898,8 @@ Group* BrowserService::getDefaultEntryGroup(const QSharedPointer& sele int BrowserService::sortPriority(const Entry* entry, const QString& host, const QString& submitUrl, - const QString& baseSubmitUrl) const + const QString& baseSubmitUrl, + const QString& fullUrl) const { QUrl url(entry->url()); if (url.scheme().isEmpty()) { @@ -914,9 +918,12 @@ int BrowserService::sortPriority(const Entry* entry, if (!url.host().contains(".") && url.host() != "localhost") { return 0; } - if (submitUrl == entryURL) { + if (fullUrl == entryURL) { return 100; } + if (submitUrl == entryURL) { + return 95; + } if (submitUrl.startsWith(entryURL) && entryURL != host && baseSubmitUrl != entryURL) { return 90; } @@ -1025,7 +1032,17 @@ bool BrowserService::handleURL(const QString& entryUrl, const QString& url, cons // Match the subdomains with the limited wildcard if (siteQUrl.host().endsWith(entryQUrl.host())) { - return true; + if (!browserSettings()->bestMatchOnly()) { + return true; + } + + // Match the exact subdomain and path, or start of the path when entry's path is longer than plain "/" + if (siteQUrl.host() == entryQUrl.host()) { + if (siteQUrl.path() == entryQUrl.path() + || (entryQUrl.path().size() > 1 && siteQUrl.path().startsWith(entryQUrl.path()))) { + return true; + } + } } return false; diff --git a/src/browser/BrowserService.h b/src/browser/BrowserService.h index 6567a44d0..77635cfe1 100644 --- a/src/browser/BrowserService.h +++ b/src/browser/BrowserService.h @@ -119,7 +119,8 @@ private: QList searchEntries(const QSharedPointer& db, const QString& url, const QString& submitUrl); QList searchEntries(const QString& url, const QString& submitUrl, const StringPairList& keyList); - QList sortEntries(QList& pwEntries, const QString& host, const QString& submitUrl); + QList + sortEntries(QList& pwEntries, const QString& host, const QString& submitUrl, const QString& fullUrl); QList confirmEntries(QList& pwEntriesToConfirm, const QString& url, const QString& host, @@ -130,8 +131,11 @@ private: QJsonArray getChildrenFromGroup(Group* group); Access checkAccess(const Entry* entry, const QString& host, const QString& submitHost, const QString& realm); Group* getDefaultEntryGroup(const QSharedPointer& selectedDb = {}); - int - sortPriority(const Entry* entry, const QString& host, const QString& submitUrl, const QString& baseSubmitUrl) const; + int sortPriority(const Entry* entry, + const QString& host, + const QString& submitUrl, + const QString& baseSubmitUrl, + const QString& fullUrl) const; bool schemeFound(const QString& url); bool removeFirstDomain(QString& hostname); bool handleURL(const QString& entryUrl, const QString& url, const QString& submitUrl); diff --git a/tests/TestBrowser.cpp b/tests/TestBrowser.cpp index 5b2f61178..3e518c1e2 100644 --- a/tests/TestBrowser.cpp +++ b/tests/TestBrowser.cpp @@ -38,6 +38,7 @@ void TestBrowser::initTestCase() { QVERIFY(Crypto::init()); m_browserService = browserService(); + browserSettings()->setBestMatchOnly(false); } void TestBrowser::init() @@ -130,6 +131,7 @@ void TestBrowser::testSortPriority() QString host = "github.com"; QString submitUrl = "https://github.com/session"; QString baseSubmitUrl = "https://github.com"; + QString fullUrl = "https://github.com/login"; QScopedPointer entry1(new Entry()); QScopedPointer entry2(new Entry()); @@ -141,6 +143,7 @@ void TestBrowser::testSortPriority() QScopedPointer entry8(new Entry()); QScopedPointer entry9(new Entry()); QScopedPointer entry10(new Entry()); + QScopedPointer entry11(new Entry()); entry1->setUrl("https://github.com/login"); entry2->setUrl("https://github.com/login"); @@ -152,18 +155,20 @@ void TestBrowser::testSortPriority() entry8->setUrl("github.com/login"); entry9->setUrl("https://github"); // Invalid URL entry10->setUrl("github.com"); + entry11->setUrl("https://github.com/login"); // Exact match // The extension uses the submitUrl as default for comparison - auto res1 = m_browserService->sortPriority(entry1.data(), host, "https://github.com/login", baseSubmitUrl); - auto res2 = m_browserService->sortPriority(entry2.data(), host, submitUrl, baseSubmitUrl); - auto res3 = m_browserService->sortPriority(entry3.data(), host, submitUrl, baseSubmitUrl); - auto res4 = m_browserService->sortPriority(entry4.data(), host, submitUrl, baseSubmitUrl); - auto res5 = m_browserService->sortPriority(entry5.data(), host, submitUrl, baseSubmitUrl); - auto res6 = m_browserService->sortPriority(entry6.data(), host, submitUrl, baseSubmitUrl); - auto res7 = m_browserService->sortPriority(entry7.data(), host, submitUrl, baseSubmitUrl); - auto res8 = m_browserService->sortPriority(entry8.data(), host, submitUrl, baseSubmitUrl); - auto res9 = m_browserService->sortPriority(entry9.data(), host, submitUrl, baseSubmitUrl); - auto res10 = m_browserService->sortPriority(entry10.data(), host, submitUrl, baseSubmitUrl); + auto res1 = m_browserService->sortPriority(entry1.data(), host, "https://github.com/login", baseSubmitUrl, fullUrl); + auto res2 = m_browserService->sortPriority(entry2.data(), host, submitUrl, baseSubmitUrl, baseSubmitUrl); + auto res3 = m_browserService->sortPriority(entry3.data(), host, submitUrl, baseSubmitUrl, fullUrl); + auto res4 = m_browserService->sortPriority(entry4.data(), host, submitUrl, baseSubmitUrl, fullUrl); + auto res5 = m_browserService->sortPriority(entry5.data(), host, submitUrl, baseSubmitUrl, fullUrl); + auto res6 = m_browserService->sortPriority(entry6.data(), host, submitUrl, baseSubmitUrl, fullUrl); + auto res7 = m_browserService->sortPriority(entry7.data(), host, submitUrl, baseSubmitUrl, fullUrl); + auto res8 = m_browserService->sortPriority(entry8.data(), host, submitUrl, baseSubmitUrl, fullUrl); + auto res9 = m_browserService->sortPriority(entry9.data(), host, submitUrl, baseSubmitUrl, fullUrl); + auto res10 = m_browserService->sortPriority(entry10.data(), host, submitUrl, baseSubmitUrl, fullUrl); + auto res11 = m_browserService->sortPriority(entry11.data(), host, submitUrl, baseSubmitUrl, fullUrl); QCOMPARE(res1, 100); QCOMPARE(res2, 40); @@ -175,6 +180,7 @@ void TestBrowser::testSortPriority() QCOMPARE(res8, 0); QCOMPARE(res9, 0); QCOMPARE(res10, 0); + QCOMPARE(res11, 100); } void TestBrowser::testSearchEntries() @@ -382,8 +388,8 @@ void TestBrowser::testSortEntries() auto entries = createEntries(urls, root); browserSettings()->setBestMatchOnly(false); - auto result = - m_browserService->sortEntries(entries, "github.com", "https://github.com/session"); // entries, host, submitUrl + auto result = m_browserService->sortEntries( + entries, "github.com", "https://github.com/session", "https://github.com"); // entries, host, submitUrl QCOMPARE(result.size(), 10); QCOMPARE(result[0]->username(), QString("User 2")); QCOMPARE(result[0]->url(), QString("https://github.com/")); @@ -393,6 +399,15 @@ void TestBrowser::testSortEntries() QCOMPARE(result[2]->url(), QString("https://github.com/login")); QCOMPARE(result[3]->username(), QString("User 3")); QCOMPARE(result[3]->url(), QString("github.com/login")); + + // Test with a perfect match. That should be first in the list. + result = m_browserService->sortEntries( + entries, "github.com", "https://github.com/session", "https://github.com/login_page"); + QCOMPARE(result.size(), 10); + QCOMPARE(result[0]->username(), QString("User 0")); + QCOMPARE(result[0]->url(), QString("https://github.com/login_page")); + QCOMPARE(result[1]->username(), QString("User 2")); + QCOMPARE(result[1]->url(), QString("https://github.com/")); } QList TestBrowser::createEntries(QStringList& urls, Group* root) const @@ -429,3 +444,58 @@ void TestBrowser::testValidURLs() QCOMPARE(Tools::checkUrlValid(i.key()), i.value()); } } + +void TestBrowser::testBestMatchingCredentials() +{ + auto db = QSharedPointer::create(); + auto* root = db->rootGroup(); + + // Test with simple URL entries + QStringList urls = {"https://github.com/loginpage", "https://github.com/justsomepage", "https://github.com/"}; + + auto entries = createEntries(urls, root); + + browserSettings()->setBestMatchOnly(true); + + auto result = m_browserService->searchEntries(db, "https://github.com/loginpage", "https://github.com/loginpage"); + QCOMPARE(result.size(), 1); + QCOMPARE(result[0]->url(), QString("https://github.com/loginpage")); + + result = m_browserService->searchEntries(db, "https://github.com/justsomepage", "https://github.com/justsomepage"); + QCOMPARE(result.size(), 1); + QCOMPARE(result[0]->url(), QString("https://github.com/justsomepage")); + + result = m_browserService->searchEntries(db, "https://github.com/", "https://github.com/"); + m_browserService->sortEntries(entries, "github.com", "https://github.com/", "https://github.com/"); + QCOMPARE(result.size(), 1); + QCOMPARE(result[0]->url(), QString("https://github.com/")); + + browserSettings()->setBestMatchOnly(false); + result = m_browserService->searchEntries(db, "https://github.com/loginpage", "https://github.com/loginpage"); + QCOMPARE(result.size(), 3); + QCOMPARE(result[0]->url(), QString("https://github.com/loginpage")); + + // Test with subdomains + QStringList subdomainsUrls = {"https://sub.github.com/loginpage", + "https://sub.github.com/justsomepage", + "https://bus.github.com/justsomepage"}; + + entries = createEntries(subdomainsUrls, root); + + browserSettings()->setBestMatchOnly(true); + + result = m_browserService->searchEntries( + db, "https://sub.github.com/justsomepage", "https://sub.github.com/justsomepage"); + QCOMPARE(result.size(), 1); + QCOMPARE(result[0]->url(), QString("https://sub.github.com/justsomepage")); + + result = m_browserService->searchEntries(db, "https://github.com/justsomepage", "https://github.com/justsomepage"); + QCOMPARE(result.size(), 1); + QCOMPARE(result[0]->url(), QString("https://github.com/justsomepage")); + + result = m_browserService->searchEntries(db, + "https://sub.github.com/justsomepage?wehavesomeextra=here", + "https://sub.github.com/justsomepage?wehavesomeextra=here"); + QCOMPARE(result.size(), 1); + QCOMPARE(result[0]->url(), QString("https://sub.github.com/justsomepage")); +} diff --git a/tests/TestBrowser.h b/tests/TestBrowser.h index 00f9d7528..c8be3d6ca 100644 --- a/tests/TestBrowser.h +++ b/tests/TestBrowser.h @@ -47,6 +47,7 @@ private slots: void testSubdomainsAndPaths(); void testSortEntries(); void testValidURLs(); + void testBestMatchingCredentials(); private: QList createEntries(QStringList& urls, Group* root) const; From 1d0523ec21b1e46c8ccf53250a3227568d79f082 Mon Sep 17 00:00:00 2001 From: Anees Ahmed Date: Mon, 22 Jun 2020 16:20:45 +0530 Subject: [PATCH 17/18] Add option to Auto-Type just the username/password Fixes #4444 Some websites these days do not present both the "username" and the "password" input box on the same webpage (e.g. Google, Amazon). So no custom sequence is possible to enter both the said attributes in one go. So, two new context menu actions have been added: 1. Perform Auto-Type of just the username 2. Perform Auto-Type of just the password These context menu actions are analogous to "Copy username" and "Copy password", except it avoids sending all characters via clipboard. * Create a sub-menu in the Context Menu of Entry. * The sub-menu offers the following sequences: - {USERNAME} - {USERNAME}{ENTER} - {PASSWORD} - {PASSWORD}{ENTER} --- src/autotype/AutoType.cpp | 15 ++++++++++++- src/autotype/AutoType.h | 1 + src/gui/DatabaseWidget.cpp | 32 +++++++++++++++++++++++++++ src/gui/DatabaseWidget.h | 4 ++++ src/gui/MainWindow.cpp | 29 +++++++++++++++++++++++- src/gui/MainWindow.ui | 45 ++++++++++++++++++++++++++++++++++++++ 6 files changed, 124 insertions(+), 2 deletions(-) diff --git a/src/autotype/AutoType.cpp b/src/autotype/AutoType.cpp index 01ef9d762..913a3c2ad 100644 --- a/src/autotype/AutoType.cpp +++ b/src/autotype/AutoType.cpp @@ -269,7 +269,7 @@ void AutoType::executeAutoTypeActions(const Entry* entry, QWidget* hideWindow, c /** * Single Autotype entry-point function - * Perfom autotype sequence in the active window + * Look up the Auto-Type sequence for the given entry then perfom Auto-Type in the active window */ void AutoType::performAutoType(const Entry* entry, QWidget* hideWindow) { @@ -285,6 +285,19 @@ void AutoType::performAutoType(const Entry* entry, QWidget* hideWindow) executeAutoTypeActions(entry, hideWindow, sequences.first()); } +/** + * Extra Autotype entry-point function + * Perfom Auto-Type of the directly specified sequence in the active window + */ +void AutoType::performAutoTypeWithSequence(const Entry* entry, const QString& sequence, QWidget* hideWindow) +{ + if (!m_plugin) { + return; + } + + executeAutoTypeActions(entry, hideWindow, sequence); +} + void AutoType::startGlobalAutoType() { m_windowForGlobal = m_plugin->activeWindow(); diff --git a/src/autotype/AutoType.h b/src/autotype/AutoType.h index 7f9e3ab22..78cd42f88 100644 --- a/src/autotype/AutoType.h +++ b/src/autotype/AutoType.h @@ -48,6 +48,7 @@ public: static bool checkHighDelay(const QString& string); static bool verifyAutoTypeSyntax(const QString& sequence); void performAutoType(const Entry* entry, QWidget* hideWindow = nullptr); + void performAutoTypeWithSequence(const Entry* entry, const QString& sequence, QWidget* hideWindow = nullptr); inline bool isAvailable() { diff --git a/src/gui/DatabaseWidget.cpp b/src/gui/DatabaseWidget.cpp index 042e2a561..3e1d3192b 100644 --- a/src/gui/DatabaseWidget.cpp +++ b/src/gui/DatabaseWidget.cpp @@ -799,6 +799,38 @@ void DatabaseWidget::performAutoType() } } +void DatabaseWidget::performAutoTypeUsername() +{ + auto currentEntry = currentSelectedEntry(); + if (currentEntry) { + autoType()->performAutoTypeWithSequence(currentEntry, QStringLiteral("{USERNAME}"), window()); + } +} + +void DatabaseWidget::performAutoTypeUsernameEnter() +{ + auto currentEntry = currentSelectedEntry(); + if (currentEntry) { + autoType()->performAutoTypeWithSequence(currentEntry, QStringLiteral("{USERNAME}{ENTER}"), window()); + } +} + +void DatabaseWidget::performAutoTypePassword() +{ + auto currentEntry = currentSelectedEntry(); + if (currentEntry) { + autoType()->performAutoTypeWithSequence(currentEntry, QStringLiteral("{PASSWORD}"), window()); + } +} + +void DatabaseWidget::performAutoTypePasswordEnter() +{ + auto currentEntry = currentSelectedEntry(); + if (currentEntry) { + autoType()->performAutoTypeWithSequence(currentEntry, QStringLiteral("{PASSWORD}{ENTER}"), window()); + } +} + void DatabaseWidget::openUrl() { auto currentEntry = currentSelectedEntry(); diff --git a/src/gui/DatabaseWidget.h b/src/gui/DatabaseWidget.h index a31dfd37b..2564977dc 100644 --- a/src/gui/DatabaseWidget.h +++ b/src/gui/DatabaseWidget.h @@ -186,6 +186,10 @@ public slots: void removeFromAgent(); #endif void performAutoType(); + void performAutoTypeUsername(); + void performAutoTypeUsernameEnter(); + void performAutoTypePassword(); + void performAutoTypePasswordEnter(); void openUrl(); void downloadSelectedFavicons(); void downloadAllFavicons(); diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp index 2ae78157e..d3d624e91 100644 --- a/src/gui/MainWindow.cpp +++ b/src/gui/MainWindow.cpp @@ -126,6 +126,7 @@ MainWindow::MainWindow() m_entryContextMenu->addAction(m_ui->menuEntryTotp->menuAction()); m_entryContextMenu->addSeparator(); m_entryContextMenu->addAction(m_ui->actionEntryAutoType); + m_entryContextMenu->addAction(m_ui->menuEntryAutoTypeWithSequence->menuAction()); m_entryContextMenu->addSeparator(); m_entryContextMenu->addAction(m_ui->actionEntryEdit); m_entryContextMenu->addAction(m_ui->actionEntryClone); @@ -220,7 +221,12 @@ MainWindow::MainWindow() m_ui->toolbarSeparator->setVisible(false); m_showToolbarSeparator = config()->get(Config::GUI_ApplicationTheme).toString() != "classic"; - m_ui->actionEntryAutoType->setVisible(autoType()->isAvailable()); + bool isAutoTypeAvailable = autoType()->isAvailable(); + m_ui->actionEntryAutoType->setVisible(isAutoTypeAvailable); + m_ui->actionEntryAutoTypeUsername->setVisible(isAutoTypeAvailable); + m_ui->actionEntryAutoTypeUsernameEnter->setVisible(isAutoTypeAvailable); + m_ui->actionEntryAutoTypePassword->setVisible(isAutoTypeAvailable); + m_ui->actionEntryAutoTypePasswordEnter->setVisible(isAutoTypeAvailable); m_inactivityTimer = new InactivityTimer(this); connect(m_inactivityTimer, SIGNAL(inactivityDetected()), this, SLOT(lockDatabasesAfterInactivity())); @@ -352,6 +358,11 @@ MainWindow::MainWindow() m_ui->actionEntryEdit->setIcon(resources()->icon("entry-edit")); m_ui->actionEntryDelete->setIcon(resources()->icon("entry-delete")); m_ui->actionEntryAutoType->setIcon(resources()->icon("auto-type")); + m_ui->menuEntryAutoTypeWithSequence->setIcon(resources()->icon("auto-type")); + m_ui->actionEntryAutoTypeUsername->setIcon(resources()->icon("auto-type")); + m_ui->actionEntryAutoTypeUsernameEnter->setIcon(resources()->icon("auto-type")); + m_ui->actionEntryAutoTypePassword->setIcon(resources()->icon("auto-type")); + m_ui->actionEntryAutoTypePasswordEnter->setIcon(resources()->icon("auto-type")); m_ui->actionEntryMoveUp->setIcon(resources()->icon("move-up")); m_ui->actionEntryMoveDown->setIcon(resources()->icon("move-down")); m_ui->actionEntryCopyUsername->setIcon(resources()->icon("username-copy")); @@ -446,6 +457,14 @@ MainWindow::MainWindow() m_actionMultiplexer.connect(m_ui->actionEntryCopyURL, SIGNAL(triggered()), SLOT(copyURL())); m_actionMultiplexer.connect(m_ui->actionEntryCopyNotes, SIGNAL(triggered()), SLOT(copyNotes())); m_actionMultiplexer.connect(m_ui->actionEntryAutoType, SIGNAL(triggered()), SLOT(performAutoType())); + m_actionMultiplexer.connect( + m_ui->actionEntryAutoTypeUsername, SIGNAL(triggered()), SLOT(performAutoTypeUsername())); + m_actionMultiplexer.connect( + m_ui->actionEntryAutoTypeUsernameEnter, SIGNAL(triggered()), SLOT(performAutoTypeUsernameEnter())); + m_actionMultiplexer.connect( + m_ui->actionEntryAutoTypePassword, SIGNAL(triggered()), SLOT(performAutoTypePassword())); + m_actionMultiplexer.connect( + m_ui->actionEntryAutoTypePasswordEnter, SIGNAL(triggered()), SLOT(performAutoTypePasswordEnter())); m_actionMultiplexer.connect(m_ui->actionEntryOpenUrl, SIGNAL(triggered()), SLOT(openUrl())); m_actionMultiplexer.connect(m_ui->actionEntryDownloadIcon, SIGNAL(triggered()), SLOT(downloadSelectedFavicons())); #ifdef WITH_XC_SSHAGENT @@ -711,6 +730,13 @@ void MainWindow::setMenuActionState(DatabaseWidget::Mode mode) m_ui->menuEntryCopyAttribute->setEnabled(singleEntrySelected); m_ui->menuEntryTotp->setEnabled(singleEntrySelected); m_ui->actionEntryAutoType->setEnabled(singleEntrySelected); + m_ui->menuEntryAutoTypeWithSequence->setEnabled(singleEntrySelected); + m_ui->actionEntryAutoTypeUsername->setEnabled(singleEntrySelected && dbWidget->currentEntryHasUsername()); + m_ui->actionEntryAutoTypeUsernameEnter->setEnabled(singleEntrySelected + && dbWidget->currentEntryHasUsername()); + m_ui->actionEntryAutoTypePassword->setEnabled(singleEntrySelected && dbWidget->currentEntryHasPassword()); + m_ui->actionEntryAutoTypePasswordEnter->setEnabled(singleEntrySelected + && dbWidget->currentEntryHasPassword()); m_ui->actionEntryOpenUrl->setEnabled(singleEntrySelected && dbWidget->currentEntryHasUrl()); m_ui->actionEntryTotp->setEnabled(singleEntrySelected && dbWidget->currentEntryHasTotp()); m_ui->actionEntryCopyTotp->setEnabled(singleEntrySelected && dbWidget->currentEntryHasTotp()); @@ -761,6 +787,7 @@ void MainWindow::setMenuActionState(DatabaseWidget::Mode mode) m_ui->actionEntryCopyURL, m_ui->actionEntryOpenUrl, m_ui->actionEntryAutoType, + m_ui->menuEntryAutoTypeWithSequence->menuAction(), m_ui->actionEntryDownloadIcon, m_ui->actionEntryCopyNotes, m_ui->actionEntryCopyTitle, diff --git a/src/gui/MainWindow.ui b/src/gui/MainWindow.ui index 10951f3c0..93488dc05 100644 --- a/src/gui/MainWindow.ui +++ b/src/gui/MainWindow.ui @@ -310,6 +310,18 @@ + + + false + + + Perform Auto-Type Sequence + + + + + + @@ -324,6 +336,7 @@ + @@ -680,6 +693,38 @@ Perform &Auto-Type + + + false + + + {USERNAME} + + + + + false + + + {USERNAME}{ENTER} + + + + + false + + + {PASSWORD} + + + + + false + + + {PASSWORD}{ENTER} + + Download &Favicon From 22e0d8b44231f0ec1721d89d537d8fd1b077a483 Mon Sep 17 00:00:00 2001 From: Shun Sakai Date: Fri, 10 Jul 2020 23:34:08 +0900 Subject: [PATCH 18/18] Improve man pages with useful links and copyright --- docs/man/keepassxc-cli.1.adoc | 62 ++++++++++++++++++---------- docs/man/keepassxc.1.adoc | 38 +++++++++++++---- docs/man/section-copyright.adoc | 19 +++++++++ docs/man/section-notes.adoc | 27 ++++++++++++ docs/man/section-reporting-bugs.adoc | 17 ++++++++ 5 files changed, 135 insertions(+), 28 deletions(-) create mode 100644 docs/man/section-copyright.adoc create mode 100644 docs/man/section-notes.adoc create mode 100644 docs/man/section-reporting-bugs.adoc diff --git a/docs/man/keepassxc-cli.1.adoc b/docs/man/keepassxc-cli.1.adoc index 13d3ec011..d36e00014 100644 --- a/docs/man/keepassxc-cli.1.adoc +++ b/docs/man/keepassxc-cli.1.adoc @@ -1,10 +1,28 @@ +// Copyright (C) 2017 Manolis Agkopian +// 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 . + = keepassxc-cli(1) -:docdate: 2020-07-05 +:docdate: 2020-07-10 :doctype: manpage +:revnumber: 2.6.0 +:mansource: KeePassXC {revnumber} :manmanual: General Commands Manual == NAME -keepassxc-cli - command line interface for the KeePassXC password manager. +keepassxc-cli - command line interface for the KeePassXC password manager == SYNOPSIS *keepassxc-cli* _command_ [_options_] @@ -16,21 +34,21 @@ It provides the ability to query and modify the entries of a KeePass database, d == COMMANDS *add* [_options_] <__database__> <__entry__>:: Adds a new entry to a database. - A password can be generated (_-g_ option), or a prompt can be displayed to input the password (_-p_ option). - The same password generation options as documented for the generate command can be used when the _-g_ option is set. + A password can be generated (*-g* option), or a prompt can be displayed to input the password (*-p* option). + The same password generation options as documented for the generate command can be used when the *-g* option is set. *analyze* [_options_] <__database__>:: Analyzes passwords in a database for weaknesses. *clip* [_options_] <__database__> <__entry__> [_timeout_]:: - Copies an attribute or the current TOTP (if the _-t_ option is specified) of a database entry to the clipboard. - If no attribute name is specified using the _-a_ option, the password is copied. + Copies an attribute or the current TOTP (if the *-t* option is specified) of a database entry to the clipboard. + If no attribute name is specified using the *-a* option, the password is copied. If multiple entries with the same name exist in different groups, only the attribute for the first one is copied. For copying the attribute of an entry in a specific group, the group path to the entry should be specified as well, instead of just the name. Optionally, a timeout in seconds can be specified to automatically clear the clipboard. *close*:: - In interactive mode, closes the currently opened database (see _open_). + In interactive mode, closes the currently opened database (see *open*). *db-create* [_options_] <__database__>:: Creates a new database with a password and/or a key file. @@ -45,8 +63,8 @@ It provides the ability to query and modify the entries of a KeePass database, d *edit* [_options_] <__database__> <__entry__>:: Edits a database entry. - A password can be generated (_-g_ option), or a prompt can be displayed to input the password (_-p_ option). - The same password generation options as documented for the generate command can be used when the _-g_ option is set. + A password can be generated (*-g* option), or a prompt can be displayed to input the password (*-p* option). + The same password generation options as documented for the generate command can be used when the *-g* option is set. *estimate* [_options_] [_password_]:: Estimates the entropy of a password. @@ -54,7 +72,7 @@ It provides the ability to query and modify the entries of a KeePass database, d *exit*:: Exits interactive mode. - Synonymous with _quit_. + Synonymous with *quit*. *export* [_options_] <__database__>:: Exports the content of a database to standard output in the specified format (defaults to XML). @@ -78,7 +96,7 @@ It provides the ability to query and modify the entries of a KeePass database, d *merge* [_options_] <__database1__> <__database2__>:: Merges two databases together. The first database file is going to be replaced by the result of the merge, for that reason it is advisable to keep a backup of the two database files before attempting a merge. - In the case that both databases make use of the same credentials, the _--same-credentials_ or _-s_ option can be used. + In the case that both databases make use of the same credentials, the *--same-credentials* or *-s* option can be used. *mkdir* [_options_] <__database__> <__group__>:: Adds a new group to a database. @@ -88,11 +106,11 @@ It provides the ability to query and modify the entries of a KeePass database, d *open* [_options_] <__database__>:: Opens the given database in a shell-style interactive mode. - This is useful for performing multiple operations on a single database (e.g. _ls_ followed by _show_). + This is useful for performing multiple operations on a single database (e.g. *ls* followed by *show*). *quit*:: Exits interactive mode. - Synonymous with _exit_. + Synonymous with *exit*. *rm* [_options_] <__database__> <__entry__>:: Removes an entry from a database. @@ -107,7 +125,7 @@ It provides the ability to query and modify the entries of a KeePass database, d *show* [_options_] <__database__> <__entry__>:: Shows the title, username, password, URL and notes of a database entry. Can also show the current TOTP. - Regarding the occurrence of multiple entries with the same name in different groups, everything stated in the _clip_ command section also applies here. + Regarding the occurrence of multiple entries with the same name in different groups, everything stated in the *clip* command section also applies here. == OPTIONS === General options @@ -151,7 +169,7 @@ It provides the ability to query and modify the entries of a KeePass database, d Uses the same credentials for unlocking both databases. === Add and edit options -The same password generation options as documented for the generate command can be used with those 2 commands when the -g option is set. +The same password generation options as documented for the generate command can be used with those 2 commands when the *-g* option is set. *-u*, *--username* <__username__>:: Specifies the username of the entry. @@ -183,7 +201,7 @@ The same password generation options as documented for the generate command can *-a*, *--attribute*:: Copies the specified attribute to the clipboard. If no attribute is specified, the password attribute is the default. - For example, "_-a_ username" would copy the username to the clipboard. + For example, "*-a* *username*" would copy the username to the clipboard. [Default: password] *-t*, *--totp*:: @@ -204,7 +222,7 @@ The same password generation options as documented for the generate command can *-a*, *--attributes* <__attribute__>...:: Shows the named attributes. This option can be specified more than once, with each attribute shown one-per-line in the given order. - If no attributes are specified and _-t_ is not specified, a summary of the default attributes is given. + If no attributes are specified and *-t* is not specified, a summary of the default attributes is given. Protected attributes will be displayed in clear text if specified explicitly by this option. *-s*, *--show-protected*:: @@ -274,9 +292,11 @@ The same password generation options as documented for the generate command can Include characters from every selected group. [Default: Disabled] -== REPORTING BUGS -Bugs and feature requests can be reported on GitHub at https://github.com/keepassxreboot/keepassxc/issues. +include::section-notes.adoc[] == AUTHOR -This manual page was originally written by Manolis Agkopian , -and is maintained by the KeePassXC Team . +This manual page was originally written by Manolis Agkopian . + +include::section-reporting-bugs.adoc[] + +include::section-copyright.adoc[] diff --git a/docs/man/keepassxc.1.adoc b/docs/man/keepassxc.1.adoc index 965f7ac46..eb1a44480 100644 --- a/docs/man/keepassxc.1.adoc +++ b/docs/man/keepassxc.1.adoc @@ -1,10 +1,28 @@ +// Copyright (C) 2019 Janek Bevendorff +// 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 . + = keepassxc(1) -:docdate: 2020-07-05 +:docdate: 2020-07-10 :doctype: manpage +:revnumber: 2.6.0 +:mansource: KeePassXC {revnumber} :manmanual: General Commands Manual == NAME -keepassxc - password manager +keepassxc - a modern open-source password manager == SYNOPSIS *keepassxc* [_options_] [_filename(s)_] @@ -23,19 +41,25 @@ Your wallet works offline and requires no Internet connection. Displays version information. *--config* <__config__>:: - Path to a custom config file + Path to a custom config file. *--keyfile* <__keyfile__>:: - Key file of the database + Key file of the database. *--pw-stdin*:: - Read password of the database from stdin + Read password of the database from stdin. *--pw*, *--parent-window* <__handle__>:: - Parent window handle + Parent window handle. *--debug-info*:: Displays debugging information. +include::section-notes.adoc[] + == AUTHOR -This manual page is maintained by the KeePassXC Team . +This manual page was originally written by Janek Bevendorff . + +include::section-reporting-bugs.adoc[] + +include::section-copyright.adoc[] diff --git a/docs/man/section-copyright.adoc b/docs/man/section-copyright.adoc new file mode 100644 index 000000000..ae35017c1 --- /dev/null +++ b/docs/man/section-copyright.adoc @@ -0,0 +1,19 @@ +// 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 . + +== COPYRIGHT +Copyright \(C) 2016-2020 KeePassXC Team + +*KeePassXC* code is licensed under GPL-2 or GPL-3. diff --git a/docs/man/section-notes.adoc b/docs/man/section-notes.adoc new file mode 100644 index 000000000..4c87dfe0b --- /dev/null +++ b/docs/man/section-notes.adoc @@ -0,0 +1,27 @@ +// 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 . + +== NOTES +*Project homepage*:: + https://keepassxc.org + +*QuickStart Guide*:: + https://keepassxc.org/docs/KeePassXC_GettingStarted.html + +*User Guide*:: + https://keepassxc.org/docs/KeePassXC_UserGuide.html + +*Git repository*:: + https://github.com/keepassxreboot/keepassxc.git diff --git a/docs/man/section-reporting-bugs.adoc b/docs/man/section-reporting-bugs.adoc new file mode 100644 index 000000000..e0c0cee37 --- /dev/null +++ b/docs/man/section-reporting-bugs.adoc @@ -0,0 +1,17 @@ +// 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 . + +== REPORTING BUGS +Bugs and feature requests can be reported on GitHub at https://github.com/keepassxreboot/keepassxc/issues.