From fd8d81f517b5e33a046eeafa5e76f06f24b6abbc Mon Sep 17 00:00:00 2001 From: varjolintu Date: Sun, 27 Sep 2020 20:41:41 +0300 Subject: [PATCH 1/5] Ignore recycle bin on KeePassHTTP migration --- src/browser/BrowserService.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/browser/BrowserService.cpp b/src/browser/BrowserService.cpp index 08c9f88da..9cb2e2729 100644 --- a/src/browser/BrowserService.cpp +++ b/src/browser/BrowserService.cpp @@ -1166,6 +1166,10 @@ bool BrowserService::checkLegacySettings(QSharedPointer db) bool legacySettingsFound = false; QList entries = db->rootGroup()->entriesRecursive(); for (const auto& e : entries) { + if (e->isRecycled()) { + continue; + } + if ((e->attributes()->contains(KEEPASSHTTP_NAME) || e->attributes()->contains(KEEPASSXCBROWSER_NAME)) || (e->title() == KEEPASSHTTP_NAME || e->title().contains(KEEPASSXCBROWSER_NAME, Qt::CaseInsensitive))) { legacySettingsFound = true; From 443b9e4d3706f7cd6aa15fb66a5d474b9303b571 Mon Sep 17 00:00:00 2001 From: Jonathan White Date: Sun, 27 Sep 2020 10:29:46 -0400 Subject: [PATCH 2/5] Introduce AsyncTask::runThenCallback * Fixes #5295 * Introduce a callback approach to AsyncTask instead of entering multiple QEventLoop in the stack. This has additional benefits including not returning to the original stack location and potentially operating on deleted objects (use after free). --- src/core/AsyncTask.h | 22 ++++++++++++++++++++++ src/core/FileWatcher.cpp | 15 +++++++++------ 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/src/core/AsyncTask.h b/src/core/AsyncTask.h index f74d7c738..b113134d9 100644 --- a/src/core/AsyncTask.h +++ b/src/core/AsyncTask.h @@ -58,6 +58,28 @@ namespace AsyncTask return waitForFuture(QtConcurrent::run(task)); } + /** + * Run a given task then call the defined callback. Prevents event loop blocking and + * ensures the validity of the follow-on task through the context. If the context is + * deleted, the callback will not be processed preventing use after free errors. + * + * @param task std::function object to run + * @param context QObject responsible for calling this function + * @param callback std::function object to run after the task completess + */ + template + void runThenCallback(FunctionObject task, QObject* context, FunctionObject2 callback) + { + typedef QFutureWatcher::type> FutureWatcher; + auto future = QtConcurrent::run(task); + auto watcher = new FutureWatcher(context); + QObject::connect(watcher, &QFutureWatcherBase::finished, context, [=]() { + watcher->deleteLater(); + callback(future.result()); + }); + watcher->setFuture(future); + } + }; // namespace AsyncTask #endif // KEEPASSXC_ASYNCTASK_HPP diff --git a/src/core/FileWatcher.cpp b/src/core/FileWatcher.cpp index 2d37734aa..430e60274 100644 --- a/src/core/FileWatcher.cpp +++ b/src/core/FileWatcher.cpp @@ -118,13 +118,16 @@ void FileWatcher::checkFileChanged() // Prevent reentrance m_ignoreFileChange = true; - auto checksum = AsyncTask::runAndWaitForFuture([this]() -> QByteArray { return calculateChecksum(); }); - if (checksum != m_fileChecksum) { - m_fileChecksum = checksum; - m_fileChangeDelayTimer.start(0); - } + AsyncTask::runThenCallback([=] { return calculateChecksum(); }, + this, + [=](QByteArray checksum) { + if (checksum != m_fileChecksum) { + m_fileChecksum = checksum; + m_fileChangeDelayTimer.start(0); + } - m_ignoreFileChange = false; + m_ignoreFileChange = false; + }); } QByteArray FileWatcher::calculateChecksum() From bb7a74b6325983110e3e5fa0ab63dea18b3beca8 Mon Sep 17 00:00:00 2001 From: Jonathan White Date: Sun, 27 Sep 2020 11:34:14 -0400 Subject: [PATCH 3/5] Revert FileDialog filter mods for macOS --- src/gui/FileDialog.cpp | 21 +++------------------ 1 file changed, 3 insertions(+), 18 deletions(-) diff --git a/src/gui/FileDialog.cpp b/src/gui/FileDialog.cpp index df713c44b..406fbe50c 100644 --- a/src/gui/FileDialog.cpp +++ b/src/gui/FileDialog.cpp @@ -21,20 +21,6 @@ #include -namespace -{ - QString modFilter(const QString& filter) - { -#ifdef Q_OS_MACOS - // Fix macOS bug that causes the file dialog to freeze when a dot is included in the filters - // See https://github.com/keepassxreboot/keepassxc/issues/3895#issuecomment-586724167 - auto mod = filter; - return mod.replace("*.", "*"); -#endif - return filter; - } -} // namespace - FileDialog* FileDialog::m_instance(nullptr); QString FileDialog::getOpenFileName(QWidget* parent, @@ -51,7 +37,7 @@ QString FileDialog::getOpenFileName(QWidget* parent, } else { const auto& workingDir = dir.isEmpty() ? config()->get(Config::LastDir).toString() : dir; const auto result = QDir::toNativeSeparators( - QFileDialog::getOpenFileName(parent, caption, workingDir, modFilter(filter), selectedFilter, options)); + QFileDialog::getOpenFileName(parent, caption, workingDir, filter, selectedFilter, options)); #ifdef Q_OS_MACOS // on Mac OS X the focus is lost after closing the native dialog @@ -77,8 +63,7 @@ QStringList FileDialog::getOpenFileNames(QWidget* parent, return results; } else { const auto& workingDir = dir.isEmpty() ? config()->get(Config::LastDir).toString() : dir; - auto results = - QFileDialog::getOpenFileNames(parent, caption, workingDir, modFilter(filter), selectedFilter, options); + auto results = QFileDialog::getOpenFileNames(parent, caption, workingDir, filter, selectedFilter, options); for (auto& path : results) { path = QDir::toNativeSeparators(path); @@ -111,7 +96,7 @@ QString FileDialog::getSaveFileName(QWidget* parent, } else { const auto& workingDir = dir.isEmpty() ? config()->get(Config::LastDir).toString() : dir; const auto result = QDir::toNativeSeparators( - QFileDialog::getSaveFileName(parent, caption, workingDir, modFilter(filter), selectedFilter, options)); + QFileDialog::getSaveFileName(parent, caption, workingDir, filter, selectedFilter, options)); #ifdef Q_OS_MACOS // on Mac OS X the focus is lost after closing the native dialog From 8424acda4d461a2cead730157c3a5ca325e57ab1 Mon Sep 17 00:00:00 2001 From: Jonathan White Date: Sun, 27 Sep 2020 23:04:19 -0400 Subject: [PATCH 4/5] Add username to browser named pipe on Windows * Fixes #5393 --- src/browser/BrowserShared.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/browser/BrowserShared.cpp b/src/browser/BrowserShared.cpp index 08b9fe537..69d0db49f 100644 --- a/src/browser/BrowserShared.cpp +++ b/src/browser/BrowserShared.cpp @@ -37,7 +37,7 @@ namespace BrowserShared : path + serverName; #elif defined(Q_OS_WIN) // Windows uses named pipes - return serverName; + return serverName + "_" + qgetenv("USERNAME"); #else // Q_OS_MACOS and others return QStandardPaths::writableLocation(QStandardPaths::TempLocation) + serverName; #endif From a55bb39f2044f3aa4545ead0cdad840d0898697c Mon Sep 17 00:00:00 2001 From: Jonathan White Date: Sun, 27 Sep 2020 22:49:22 -0400 Subject: [PATCH 5/5] Fix SSH Add/Remove Key Shortcut on macOS * Fixes #5378 * Add Key to SSH Agent is Ctrl + H on all platforms * Remove Key from SSH Agent is Ctrl + Shift + H on all platforms --- src/gui/MainWindow.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp index f5e0541b3..ef2a56aa7 100644 --- a/src/gui/MainWindow.cpp +++ b/src/gui/MainWindow.cpp @@ -258,8 +258,15 @@ MainWindow::MainWindow() m_ui->actionEntryAutoType->setShortcut(Qt::CTRL + Qt::SHIFT + Qt::Key_V); m_ui->actionEntryOpenUrl->setShortcut(Qt::CTRL + Qt::SHIFT + Qt::Key_U); m_ui->actionEntryCopyURL->setShortcut(Qt::CTRL + Qt::Key_U); - m_ui->actionEntryAddToAgent->setShortcut(Qt::CTRL + Qt::Key_H); - m_ui->actionEntryRemoveFromAgent->setShortcut(Qt::CTRL + Qt::SHIFT + Qt::Key_H); + + // 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_ui->actionEntryAddToAgent->setShortcut(modifier + Qt::Key_H); + m_ui->actionEntryRemoveFromAgent->setShortcut(modifier + Qt::SHIFT + Qt::Key_H); #if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0) // Qt 5.10 introduced a new "feature" to hide shortcuts in context menus