From 727094abc6305a21dec23f5c2552f4ab7dc4c5f6 Mon Sep 17 00:00:00 2001 From: Felix Geyer Date: Sat, 26 Sep 2015 12:21:22 +0200 Subject: [PATCH 01/13] Unload auto-type plugins if they run in an unsupported environment. Refs #351 --- src/autotype/AutoType.cpp | 11 +++++- src/autotype/AutoTypePlatformPlugin.h | 1 + src/autotype/test/AutoTypeTest.cpp | 5 +++ src/autotype/test/AutoTypeTest.h | 1 + src/autotype/x11/AutoTypeX11.cpp | 53 ++++++++++++++++++++------- src/autotype/x11/AutoTypeX11.h | 2 + 6 files changed, 57 insertions(+), 16 deletions(-) diff --git a/src/autotype/AutoType.cpp b/src/autotype/AutoType.cpp index 5c3cac065..19c8575f3 100644 --- a/src/autotype/AutoType.cpp +++ b/src/autotype/AutoType.cpp @@ -79,9 +79,16 @@ void AutoType::loadPlugin(const QString& pluginPath) QObject* pluginInstance = m_pluginLoader->instance(); if (pluginInstance) { m_plugin = qobject_cast(pluginInstance); + m_executor = Q_NULLPTR; + if (m_plugin) { - m_executor = m_plugin->createExecutor(); - connect(pluginInstance, SIGNAL(globalShortcutTriggered()), SIGNAL(globalShortcutTriggered())); + if (m_plugin->isAvailable()) { + m_executor = m_plugin->createExecutor(); + connect(pluginInstance, SIGNAL(globalShortcutTriggered()), SIGNAL(globalShortcutTriggered())); + } + else { + unloadPlugin(); + } } } diff --git a/src/autotype/AutoTypePlatformPlugin.h b/src/autotype/AutoTypePlatformPlugin.h index 614c8060b..dadc7a0d2 100644 --- a/src/autotype/AutoTypePlatformPlugin.h +++ b/src/autotype/AutoTypePlatformPlugin.h @@ -26,6 +26,7 @@ class AutoTypePlatformInterface { public: virtual ~AutoTypePlatformInterface() {} + virtual bool isAvailable() = 0; virtual QStringList windowTitles() = 0; virtual WId activeWindow() = 0; virtual QString activeWindowTitle() = 0; diff --git a/src/autotype/test/AutoTypeTest.cpp b/src/autotype/test/AutoTypeTest.cpp index f12014668..a8bcc71af 100644 --- a/src/autotype/test/AutoTypeTest.cpp +++ b/src/autotype/test/AutoTypeTest.cpp @@ -17,6 +17,11 @@ #include "AutoTypeTest.h" +bool AutoTypePlatformTest::isAvailable() +{ + return true; +} + QString AutoTypePlatformTest::keyToString(Qt::Key key) { return QString("[Key0x%1]").arg(key, 0, 16); diff --git a/src/autotype/test/AutoTypeTest.h b/src/autotype/test/AutoTypeTest.h index 940564166..c791c154c 100644 --- a/src/autotype/test/AutoTypeTest.h +++ b/src/autotype/test/AutoTypeTest.h @@ -35,6 +35,7 @@ class AutoTypePlatformTest : public QObject, public: QString keyToString(Qt::Key key) Q_DECL_OVERRIDE; + bool isAvailable() Q_DECL_OVERRIDE; QStringList windowTitles() Q_DECL_OVERRIDE; WId activeWindow() Q_DECL_OVERRIDE; QString activeWindowTitle() Q_DECL_OVERRIDE; diff --git a/src/autotype/x11/AutoTypeX11.cpp b/src/autotype/x11/AutoTypeX11.cpp index 98d68a163..9d5f7be48 100644 --- a/src/autotype/x11/AutoTypeX11.cpp +++ b/src/autotype/x11/AutoTypeX11.cpp @@ -57,6 +57,25 @@ AutoTypePlatformX11::AutoTypePlatformX11() updateKeymap(); } +bool AutoTypePlatformX11::isAvailable() +{ + int ignore; + + if (!XQueryExtension(m_dpy, "XInputExtension", &ignore, &ignore, &ignore)) { + return false; + } + + if (!XQueryExtension(m_dpy, "XTEST", &ignore, &ignore, &ignore)) { + return false; + } + + if (!m_xkb && !getKeyboard()) { + return false; + } + + return true; +} + void AutoTypePlatformX11::unload() { // Restore the KeyboardMapping to its original state. @@ -437,21 +456,10 @@ void AutoTypePlatformX11::updateKeymap() int mod_index, mod_key; XModifierKeymap *modifiers; - if (m_xkb != NULL) XkbFreeKeyboard(m_xkb, XkbAllComponentsMask, True); - - XDeviceInfo* devices; - int num_devices; - XID keyboard_id = XkbUseCoreKbd; - devices = XListInputDevices(m_dpy, &num_devices); - - for (int i = 0; i < num_devices; i++) { - if (QString(devices[i].name) == "Virtual core XTEST keyboard") { - keyboard_id = devices[i].id; - break; - } + if (m_xkb) { + XkbFreeKeyboard(m_xkb, XkbAllComponentsMask, True); } - - m_xkb = XkbGetKeyboard(m_dpy, XkbCompatMapMask | XkbGeometryMask, keyboard_id); + m_xkb = getKeyboard(); XDisplayKeycodes(m_dpy, &m_minKeycode, &m_maxKeycode); if (m_keysymTable != NULL) XFree(m_keysymTable); @@ -537,6 +545,23 @@ int AutoTypePlatformX11::x11ErrorHandler(Display* display, XErrorEvent* error) return 1; } +XkbDescPtr AutoTypePlatformX11::getKeyboard() +{ + XDeviceInfo* devices; + int num_devices; + XID keyboard_id = XkbUseCoreKbd; + devices = XListInputDevices(m_dpy, &num_devices); + + for (int i = 0; i < num_devices; i++) { + if (QString(devices[i].name) == "Virtual core XTEST keyboard") { + keyboard_id = devices[i].id; + break; + } + } + + return XkbGetKeyboard(m_dpy, XkbCompatMapMask | XkbGeometryMask, keyboard_id); +} + // -------------------------------------------------------------------------- // The following code is taken from xvkbd 3.0 and has been slightly modified. // -------------------------------------------------------------------------- diff --git a/src/autotype/x11/AutoTypeX11.h b/src/autotype/x11/AutoTypeX11.h index a2080a84a..99abb2308 100644 --- a/src/autotype/x11/AutoTypeX11.h +++ b/src/autotype/x11/AutoTypeX11.h @@ -42,6 +42,7 @@ class AutoTypePlatformX11 : public QObject, public AutoTypePlatformInterface public: AutoTypePlatformX11(); + bool isAvailable() Q_DECL_OVERRIDE; void unload() Q_DECL_OVERRIDE; QStringList windowTitles() Q_DECL_OVERRIDE; WId activeWindow() Q_DECL_OVERRIDE; @@ -72,6 +73,7 @@ private: void stopCatchXErrors(); static int x11ErrorHandler(Display* display, XErrorEvent* error); + XkbDescPtr getKeyboard(); void updateKeymap(); bool isRemapKeycodeValid(); int AddKeysym(KeySym keysym); From fc8cb7cd14c3184c76321237cc0d6c7d520b9268 Mon Sep 17 00:00:00 2001 From: Felix Geyer Date: Sat, 26 Sep 2015 12:26:24 +0200 Subject: [PATCH 02/13] Check if XListInputDevices returns an error. Refs #351 --- src/autotype/x11/AutoTypeX11.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/autotype/x11/AutoTypeX11.cpp b/src/autotype/x11/AutoTypeX11.cpp index 9d5f7be48..06e5b68dc 100644 --- a/src/autotype/x11/AutoTypeX11.cpp +++ b/src/autotype/x11/AutoTypeX11.cpp @@ -547,10 +547,12 @@ int AutoTypePlatformX11::x11ErrorHandler(Display* display, XErrorEvent* error) XkbDescPtr AutoTypePlatformX11::getKeyboard() { - XDeviceInfo* devices; int num_devices; XID keyboard_id = XkbUseCoreKbd; - devices = XListInputDevices(m_dpy, &num_devices); + XDeviceInfo* devices = XListInputDevices(m_dpy, &num_devices); + if (!devices) { + return Q_NULLPTR; + } for (int i = 0; i < num_devices; i++) { if (QString(devices[i].name) == "Virtual core XTEST keyboard") { From 6b49f8f26b1f54b48a6e16a4c4880d33df776f3b Mon Sep 17 00:00:00 2001 From: Felix Geyer Date: Sat, 26 Sep 2015 12:31:29 +0200 Subject: [PATCH 03/13] Free input device list. Fixes a memory leak. --- src/autotype/x11/AutoTypeX11.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/autotype/x11/AutoTypeX11.cpp b/src/autotype/x11/AutoTypeX11.cpp index 06e5b68dc..6a2b2ab6d 100644 --- a/src/autotype/x11/AutoTypeX11.cpp +++ b/src/autotype/x11/AutoTypeX11.cpp @@ -561,6 +561,8 @@ XkbDescPtr AutoTypePlatformX11::getKeyboard() } } + XFreeDeviceList(devices); + return XkbGetKeyboard(m_dpy, XkbCompatMapMask | XkbGeometryMask, keyboard_id); } From 4f2d56a55fd714bbd0c69eb0d0cd5ee5ccb05d1c Mon Sep 17 00:00:00 2001 From: Felix Geyer Date: Sat, 26 Sep 2015 12:39:27 +0200 Subject: [PATCH 04/13] Fix another small memory leak. --- src/autotype/x11/AutoTypeX11.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/autotype/x11/AutoTypeX11.cpp b/src/autotype/x11/AutoTypeX11.cpp index 6a2b2ab6d..7f26aa08f 100644 --- a/src/autotype/x11/AutoTypeX11.cpp +++ b/src/autotype/x11/AutoTypeX11.cpp @@ -69,8 +69,14 @@ bool AutoTypePlatformX11::isAvailable() return false; } - if (!m_xkb && !getKeyboard()) { - return false; + if (!m_xkb) { + XkbDescPtr kbd = getKeyboard(); + + if (!kbd) { + return false; + } + + XkbFreeKeyboard(kbd, XkbAllComponentsMask, True); } return true; From b8c1829857082a72035cfe028750a0d69bca813f Mon Sep 17 00:00:00 2001 From: Felix Geyer Date: Sun, 27 Sep 2015 23:16:18 +0200 Subject: [PATCH 05/13] Improve tray icon behavior on OS X. Previously the main window had issues on restore: - was sometimes hidden again. - window was unresponsive, all actions disabled. --- src/gui/MainWindow.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp index 77c34f12c..7e8e702ba 100644 --- a/src/gui/MainWindow.cpp +++ b/src/gui/MainWindow.cpp @@ -20,6 +20,7 @@ #include #include +#include #include "autotype/AutoType.h" #include "core/Config.h" @@ -448,7 +449,7 @@ void MainWindow::changeEvent(QEvent *event) && isTrayIconEnabled() && config()->get("GUI/MinimizeToTray").toBool()) { event->ignore(); - hide(); + QTimer::singleShot(0, this, SLOT(hide())); } else { QMainWindow::changeEvent(event); @@ -578,6 +579,7 @@ void MainWindow::toggleWindow() hide(); } else { + setWindowState(windowState() & ~Qt::WindowMinimized); show(); raise(); activateWindow(); From 568dfde07451e8c412130796a5577ed2c9797e8d Mon Sep 17 00:00:00 2001 From: Felix Geyer Date: Mon, 28 Sep 2015 22:00:21 +0200 Subject: [PATCH 06/13] Fix minimum size of AboutDialog. Also make the dialog non-resizeable. Closes #352 --- src/gui/AboutDialog.ui | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/gui/AboutDialog.ui b/src/gui/AboutDialog.ui index 79dd5e1ca..2effbd414 100644 --- a/src/gui/AboutDialog.ui +++ b/src/gui/AboutDialog.ui @@ -14,10 +14,20 @@ About KeePassX + + QLayout::SetFixedSize + - + + + + 0 + 0 + + + @@ -36,6 +46,12 @@ + + + 0 + 0 + + <a href="http://www.keepassx.org/">http://www.keepassx.org/</a> @@ -46,6 +62,12 @@ + + + 0 + 0 + + KeePassX is distributed under the term of the GNU General Public License (GPL) version 2 or (at your option) version 3. From ebeedba072978310507705839fd2151403289dc4 Mon Sep 17 00:00:00 2001 From: Florian Geyer Date: Mon, 28 Sep 2015 22:26:13 +0200 Subject: [PATCH 07/13] Reset visibility state of password field on unlocking. Closes #354 --- src/gui/UnlockDatabaseWidget.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/gui/UnlockDatabaseWidget.cpp b/src/gui/UnlockDatabaseWidget.cpp index 944198be1..242b07a82 100644 --- a/src/gui/UnlockDatabaseWidget.cpp +++ b/src/gui/UnlockDatabaseWidget.cpp @@ -33,5 +33,6 @@ void UnlockDatabaseWidget::clearForms() m_ui->comboKeyFile->clear(); m_ui->checkPassword->setChecked(false); m_ui->checkKeyFile->setChecked(false); + m_ui->buttonTogglePassword->setChecked(false); m_db = Q_NULLPTR; } From 840642394fa7b48884da824c923db1e257992852 Mon Sep 17 00:00:00 2001 From: Felix Geyer Date: Sat, 10 Oct 2015 11:22:17 +0200 Subject: [PATCH 08/13] Cope with focusWidget/activeWindow returning windows that are minimized. --- src/autotype/x11/AutoTypeX11.cpp | 2 +- src/gui/MainWindow.cpp | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/autotype/x11/AutoTypeX11.cpp b/src/autotype/x11/AutoTypeX11.cpp index 7f26aa08f..6a20a88ff 100644 --- a/src/autotype/x11/AutoTypeX11.cpp +++ b/src/autotype/x11/AutoTypeX11.cpp @@ -208,7 +208,7 @@ int AutoTypePlatformX11::platformEventFilter(void* event) && m_currentGlobalKey && xevent->xkey.keycode == m_currentGlobalKeycode && (xevent->xkey.state & m_modifierMask) == m_currentGlobalNativeModifiers - && !QApplication::focusWidget() + && (!QApplication::activeWindow() || QApplication::activeWindow()->isMinimized()) && m_loaded) { if (xevent->type == KeyPress) { Q_EMIT globalShortcutTriggered(); diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp index 7e8e702ba..94cdf2124 100644 --- a/src/gui/MainWindow.cpp +++ b/src/gui/MainWindow.cpp @@ -575,10 +575,11 @@ void MainWindow::trayIconTriggered(QSystemTrayIcon::ActivationReason reason) void MainWindow::toggleWindow() { - if (QApplication::activeWindow() == this) { + if ((QApplication::activeWindow() == this) && isVisible() && !isMinimized()) { hide(); } else { + ensurePolished(); setWindowState(windowState() & ~Qt::WindowMinimized); show(); raise(); From 58ed99d56298ea9302ec81ceeacfcdfdd876c710 Mon Sep 17 00:00:00 2001 From: Felix Geyer Date: Sat, 10 Oct 2015 17:00:50 +0200 Subject: [PATCH 09/13] OS X: Restore main window when clicking on the docker icon. Apparently this worked previously. Maybe a regression in Qt? Refs #326 --- src/gui/Application.cpp | 16 ++++++++++++++++ src/gui/Application.h | 4 ++++ src/main.cpp | 1 + 3 files changed, 21 insertions(+) diff --git a/src/gui/Application.cpp b/src/gui/Application.cpp index 2dede3f8c..ae6931fb7 100644 --- a/src/gui/Application.cpp +++ b/src/gui/Application.cpp @@ -24,9 +24,15 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) + , m_mainWindow(Q_NULLPTR) { } +void Application::setMainWindow(QWidget* mainWindow) +{ + m_mainWindow = mainWindow; +} + bool Application::event(QEvent* event) { // Handle Apple QFileOpenEvent from finder (double click on .kdbx file) @@ -34,6 +40,16 @@ bool Application::event(QEvent* event) Q_EMIT openFile(static_cast(event)->file()); return true; } +#ifdef Q_OS_MAC + // restore main window when clicking on the docker icon + else if ((event->type() == QEvent::ApplicationActivate) && m_mainWindow) { + m_mainWindow->ensurePolished(); + m_mainWindow->setWindowState(m_mainWindow->windowState() & ~Qt::WindowMinimized); + m_mainWindow->show(); + m_mainWindow->raise(); + m_mainWindow->activateWindow(); + } +#endif return QApplication::event(event); } diff --git a/src/gui/Application.h b/src/gui/Application.h index a5f55d4dd..2b789984d 100644 --- a/src/gui/Application.h +++ b/src/gui/Application.h @@ -29,6 +29,7 @@ class Application : public QApplication public: Application(int& argc, char** argv); + void setMainWindow(QWidget* mainWindow); bool event(QEvent* event) Q_DECL_OVERRIDE; #ifdef Q_WS_X11 @@ -37,6 +38,9 @@ public: Q_SIGNALS: void openFile(const QString& filename); + +private: + QWidget* m_mainWindow; }; #endif // KEEPASSX_APPLICATION_H diff --git a/src/main.cpp b/src/main.cpp index 288392c0e..df8493acf 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -82,6 +82,7 @@ int main(int argc, char** argv) MainWindow mainWindow; mainWindow.show(); + app.setMainWindow(&mainWindow); QObject::connect(&app, SIGNAL(openFile(QString)), &mainWindow, SLOT(openDatabase(QString))); From 316a7e6fb7c3a402a5f65421299481c6265e0e6d Mon Sep 17 00:00:00 2001 From: Felix Geyer Date: Sat, 10 Oct 2015 17:02:43 +0200 Subject: [PATCH 10/13] Expose version of used libraries in the About dialog. --- src/crypto/Crypto.cpp | 8 +++++++- src/crypto/Crypto.h | 2 ++ src/gui/AboutDialog.cpp | 7 +++++++ src/gui/AboutDialog.ui | 7 +++++++ 4 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/crypto/Crypto.cpp b/src/crypto/Crypto.cpp index e32e2d2d3..40ec7eafb 100644 --- a/src/crypto/Crypto.cpp +++ b/src/crypto/Crypto.cpp @@ -27,6 +27,7 @@ bool Crypto::m_initalized(false); QString Crypto::m_errorStr; +QString Crypto::m_backendVersion; #if !defined(GCRYPT_VERSION_NUMBER) || (GCRYPT_VERSION_NUMBER < 0x010600) static int gcry_qt_mutex_init(void** p_sys) @@ -80,7 +81,7 @@ bool Crypto::init() #if !defined(GCRYPT_VERSION_NUMBER) || (GCRYPT_VERSION_NUMBER < 0x010600) gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_qt); #endif - gcry_check_version(0); + m_backendVersion = QString::fromLocal8Bit(gcry_check_version(0)); gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0); if (!checkAlgorithms()) { @@ -108,6 +109,11 @@ QString Crypto::errorString() return m_errorStr; } +QString Crypto::backendVersion() +{ + return QString("libgcrypt ").append(m_backendVersion); +} + bool Crypto::backendSelfTest() { return (gcry_control(GCRYCTL_SELFTEST) == 0); diff --git a/src/crypto/Crypto.h b/src/crypto/Crypto.h index b801cbb54..1726865ec 100644 --- a/src/crypto/Crypto.h +++ b/src/crypto/Crypto.h @@ -29,6 +29,7 @@ public: static bool initalized(); static bool backendSelfTest(); static QString errorString(); + static QString backendVersion(); private: Crypto(); @@ -43,6 +44,7 @@ private: static bool m_initalized; static QString m_errorStr; + static QString m_backendVersion; }; #endif // KEEPASSX_CRYPTO_H diff --git a/src/gui/AboutDialog.cpp b/src/gui/AboutDialog.cpp index d4b212d44..6ca02d1aa 100644 --- a/src/gui/AboutDialog.cpp +++ b/src/gui/AboutDialog.cpp @@ -21,6 +21,7 @@ #include "config-keepassx.h" #include "version.h" #include "core/FilePath.h" +#include "crypto/Crypto.h" AboutDialog::AboutDialog(QWidget* parent) : QDialog(parent) @@ -49,6 +50,12 @@ AboutDialog::AboutDialog(QWidget* parent) m_ui->label_git->setText(labelText); } + QString libs = QString("%1\n- Qt %2\n- %3") + .arg(m_ui->label_libs->text()) + .arg(QString::fromLocal8Bit(qVersion())) + .arg(Crypto::backendVersion()); + m_ui->label_libs->setText(libs); + setAttribute(Qt::WA_DeleteOnClose); connect(m_ui->buttonBox, SIGNAL(rejected()), SLOT(close())); } diff --git a/src/gui/AboutDialog.ui b/src/gui/AboutDialog.ui index 2effbd414..0a66b602a 100644 --- a/src/gui/AboutDialog.ui +++ b/src/gui/AboutDialog.ui @@ -86,6 +86,13 @@ + + + + Using: + + + From e98c30f633053a7a8ac125d7ccf83b08a25f3805 Mon Sep 17 00:00:00 2001 From: Felix Geyer Date: Sat, 10 Oct 2015 17:08:56 +0200 Subject: [PATCH 11/13] Disable systray on OS X. It's not useful on that platform. Refs #326 --- src/gui/MainWindow.cpp | 5 +++++ src/gui/SettingsWidget.cpp | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp index 94cdf2124..9a06ac893 100644 --- a/src/gui/MainWindow.cpp +++ b/src/gui/MainWindow.cpp @@ -599,6 +599,11 @@ void MainWindow::lockDatabasesAfterInactivity() bool MainWindow::isTrayIconEnabled() const { +#ifdef Q_OS_MAC + // systray not useful on OS X + return false; +#else return config()->get("GUI/ShowTrayIcon").toBool() && QSystemTrayIcon::isSystemTrayAvailable(); +#endif } diff --git a/src/gui/SettingsWidget.cpp b/src/gui/SettingsWidget.cpp index e774ed21a..8b536a53d 100644 --- a/src/gui/SettingsWidget.cpp +++ b/src/gui/SettingsWidget.cpp @@ -41,6 +41,11 @@ SettingsWidget::SettingsWidget(QWidget* parent) m_generalUi->autoTypeShortcutWidget->setVisible(autoType()->isAvailable()); m_generalUi->autoTypeShortcutLabel->setVisible(autoType()->isAvailable()); +#ifdef Q_OS_MAC + // systray not useful on OS X + m_generalUi->systrayShowCheckBox->setVisible(false); + m_generalUi->systrayMinimizeToTrayCheckBox->setVisible(false); +#endif connect(this, SIGNAL(accepted()), SLOT(saveSettings())); connect(this, SIGNAL(rejected()), SLOT(reject())); From 862941abf6137bdafa905b4d6c7ded72817f5b1d Mon Sep 17 00:00:00 2001 From: Felix Geyer Date: Sat, 10 Oct 2015 17:23:57 +0200 Subject: [PATCH 12/13] TestAutoType: Restore AutoTypeEntryTitleMatch before every test. --- tests/TestAutoType.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/TestAutoType.cpp b/tests/TestAutoType.cpp index 818f57c96..b041e8e90 100644 --- a/tests/TestAutoType.cpp +++ b/tests/TestAutoType.cpp @@ -38,7 +38,6 @@ void TestAutoType::initTestCase() QVERIFY(Crypto::init()); Config::createTempFileInstance(); AutoType::createTestInstance(); - config()->set("AutoTypeEntryTitleMatch", false); config()->set("security/autotypeask", false); QPluginLoader loader(filePath()->pluginPath("keepassx-autotype-test")); @@ -56,6 +55,7 @@ void TestAutoType::initTestCase() void TestAutoType::init() { + config()->set("AutoTypeEntryTitleMatch", false); m_test->clearActions(); m_db = new Database(); @@ -147,8 +147,6 @@ void TestAutoType::testGlobalAutoTypeTitleMatch() void TestAutoType::testGlobalAutoTypeTitleMatchDisabled() { - config()->set("AutoTypeEntryTitleMatch", false); - m_test->setActiveWindowTitle("An Entry Title!"); MessageBox::setNextAnswer(QMessageBox::Ok); m_autoType->performGlobalAutoType(m_dbList); From 820941fd402e3dfcedececdece0294220e31b300 Mon Sep 17 00:00:00 2001 From: Felix Geyer Date: Sat, 10 Oct 2015 17:36:08 +0200 Subject: [PATCH 13/13] Auto-Type: Only require a substring match for regex. This matches the behavior of KeePass. Refs #357 --- src/autotype/AutoType.cpp | 2 +- tests/TestAutoType.cpp | 44 +++++++++++++++++++++++++++++++++++++-- tests/TestAutoType.h | 2 ++ 3 files changed, 45 insertions(+), 3 deletions(-) diff --git a/src/autotype/AutoType.cpp b/src/autotype/AutoType.cpp index 19c8575f3..f1b7e3ec1 100644 --- a/src/autotype/AutoType.cpp +++ b/src/autotype/AutoType.cpp @@ -575,7 +575,7 @@ bool AutoType::windowMatches(const QString& windowTitle, const QString& windowPa { if (windowPattern.startsWith("//") && windowPattern.endsWith("//") && windowPattern.size() >= 4) { QRegExp regExp(windowPattern.mid(2, windowPattern.size() - 4), Qt::CaseInsensitive, QRegExp::RegExp2); - return regExp.exactMatch(windowTitle); + return (regExp.indexIn(windowTitle) != -1); } else { return WildcardMatcher(windowTitle).match(windowPattern); diff --git a/tests/TestAutoType.cpp b/tests/TestAutoType.cpp index b041e8e90..896834808 100644 --- a/tests/TestAutoType.cpp +++ b/tests/TestAutoType.cpp @@ -64,11 +64,12 @@ void TestAutoType::init() m_group = new Group(); m_db->setRootGroup(m_group); + AutoTypeAssociations::Association association; + m_entry1 = new Entry(); m_entry1->setGroup(m_group); m_entry1->setUsername("myuser"); m_entry1->setPassword("mypass"); - AutoTypeAssociations::Association association; association.window = "custom window"; association.sequence = "{username}association{password}"; m_entry1->autoTypeAssociations()->add(association); @@ -77,6 +78,19 @@ void TestAutoType::init() m_entry2->setGroup(m_group); m_entry2->setPassword("myuser"); m_entry2->setTitle("entry title"); + + m_entry3 = new Entry(); + m_entry3->setGroup(m_group); + m_entry3->setPassword("regex"); + association.window = "//REGEX1//"; + association.sequence = "regex1"; + m_entry3->autoTypeAssociations()->add(association); + association.window = "//^REGEX2$//"; + association.sequence = "regex2"; + m_entry3->autoTypeAssociations()->add(association); + association.window = "//^REGEX3-([rd]\\d){2}$//"; + association.sequence = "regex3"; + m_entry3->autoTypeAssociations()->add(association); } void TestAutoType::cleanup() @@ -152,5 +166,31 @@ void TestAutoType::testGlobalAutoTypeTitleMatchDisabled() m_autoType->performGlobalAutoType(m_dbList); QCOMPARE(m_test->actionChars(), QString()); - +} + +void TestAutoType::testGlobalAutoTypeRegExp() +{ + // substring matches are ok + m_test->setActiveWindowTitle("lorem REGEX1 ipsum"); + m_autoType->performGlobalAutoType(m_dbList); + QCOMPARE(m_test->actionChars(), QString("regex1")); + m_test->clearActions(); + + // should be case-insensitive + m_test->setActiveWindowTitle("lorem regex1 ipsum"); + m_autoType->performGlobalAutoType(m_dbList); + QCOMPARE(m_test->actionChars(), QString("regex1")); + m_test->clearActions(); + + // exact match + m_test->setActiveWindowTitle("REGEX2"); + m_autoType->performGlobalAutoType(m_dbList); + QCOMPARE(m_test->actionChars(), QString("regex2")); + m_test->clearActions(); + + // a bit more complicated regex + m_test->setActiveWindowTitle("REGEX3-R2D2"); + m_autoType->performGlobalAutoType(m_dbList); + QCOMPARE(m_test->actionChars(), QString("regex3")); + m_test->clearActions(); } diff --git a/tests/TestAutoType.h b/tests/TestAutoType.h index d46a55969..c12817b1d 100644 --- a/tests/TestAutoType.h +++ b/tests/TestAutoType.h @@ -43,6 +43,7 @@ private Q_SLOTS: void testGlobalAutoTypeWithOneMatch(); void testGlobalAutoTypeTitleMatch(); void testGlobalAutoTypeTitleMatchDisabled(); + void testGlobalAutoTypeRegExp(); private: AutoTypePlatformInterface* m_platform; @@ -53,6 +54,7 @@ private: Group* m_group; Entry* m_entry1; Entry* m_entry2; + Entry* m_entry3; }; #endif // KEEPASSX_TESTAUTOTYPE_H