From 178bea6bbce2e06d375f3e2569fd99cebdcf4083 Mon Sep 17 00:00:00 2001 From: Jonathan White Date: Sun, 27 Oct 2019 21:37:42 -0400 Subject: [PATCH 1/7] Fix building without features * Fix #3684 - Include YubiKey headers in CLI tests * Skip building testguibrowser if browser integration is disabled * Cleanup test CMakeLists --- src/keys/drivers/YubiKeyStub.cpp | 7 +++++++ tests/CMakeLists.txt | 16 +--------------- tests/TestCli.cpp | 2 +- tests/gui/CMakeLists.txt | 5 ++++- 4 files changed, 13 insertions(+), 17 deletions(-) diff --git a/src/keys/drivers/YubiKeyStub.cpp b/src/keys/drivers/YubiKeyStub.cpp index 81e913b0e..1c2fcb8b6 100644 --- a/src/keys/drivers/YubiKeyStub.cpp +++ b/src/keys/drivers/YubiKeyStub.cpp @@ -75,3 +75,10 @@ YubiKey::ChallengeResult YubiKey::challenge(int slot, bool mayBlock, const QByte return ERROR; } + +bool YubiKey::checkSlotIsBlocking(int slot, QString& errorMessage) +{ + Q_UNUSED(slot); + Q_UNUSED(errorMessage); + return false; +} diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 288f64470..9aac1b7d8 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -87,17 +87,7 @@ macro(add_unit_test) endif() endmacro(add_unit_test) -set(TEST_LIBRARIES - keepassx_core - ${keepassxcbrowser_LIB} - ${autotype_LIB} - Qt5::Core - Qt5::Concurrent - Qt5::Widgets - Qt5::Test - ${GCRYPT_LIBRARIES} - ${GPGERROR_LIBRARIES} - ${ZLIB_LIBRARIES}) +set(TEST_LIBRARIES keepassx_core Qt5::Test) set(testsupport_SOURCES modeltest.cpp @@ -108,10 +98,6 @@ set(testsupport_SOURCES add_library(testsupport STATIC ${testsupport_SOURCES}) target_link_libraries(testsupport Qt5::Core Qt5::Concurrent Qt5::Widgets Qt5::Test) -if(YUBIKEY_FOUND) - set(TEST_LIBRARIES ${TEST_LIBRARIES} ${YUBIKEY_LIBRARIES}) -endif() - add_unit_test(NAME testgroup SOURCES TestGroup.cpp LIBS testsupport ${TEST_LIBRARIES}) diff --git a/tests/TestCli.cpp b/tests/TestCli.cpp index 586c39be1..f1f39e9f5 100644 --- a/tests/TestCli.cpp +++ b/tests/TestCli.cpp @@ -21,9 +21,9 @@ #include "core/Bootstrap.h" #include "core/Config.h" #include "core/Global.h" -#include "core/PasswordGenerator.h" #include "core/Tools.h" #include "crypto/Crypto.h" +#include "keys/drivers/YubiKey.h" #include "format/Kdbx3Reader.h" #include "format/Kdbx3Writer.h" #include "format/Kdbx4Reader.h" diff --git a/tests/gui/CMakeLists.txt b/tests/gui/CMakeLists.txt index 168272bac..6a8d21c4a 100644 --- a/tests/gui/CMakeLists.txt +++ b/tests/gui/CMakeLists.txt @@ -16,5 +16,8 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}/..) add_unit_test(NAME testgui SOURCES TestGui.cpp ../util/TemporaryFile.cpp LIBS ${TEST_LIBRARIES}) -add_unit_test(NAME testguibrowser SOURCES TestGuiBrowser.cpp ../util/TemporaryFile.cpp LIBS ${TEST_LIBRARIES}) add_unit_test(NAME testguipixmaps SOURCES TestGuiPixmaps.cpp LIBS ${TEST_LIBRARIES}) + +if(WITH_XC_BROWSER) + add_unit_test(NAME testguibrowser SOURCES TestGuiBrowser.cpp ../util/TemporaryFile.cpp LIBS ${TEST_LIBRARIES}) +endif() From 36e14157bef5788c8b7d4ee83078f9fbfb6704b0 Mon Sep 17 00:00:00 2001 From: Jonathan White Date: Wed, 30 Oct 2019 06:40:56 -0400 Subject: [PATCH 2/7] Significantly reduce impact of FileWatcher hashing (#3724) * Fix #3699 Reduce file watch hashing of open database files from every second to every 30 seconds. Additionally, only hash the first 1024 bytes of the database file. This is valid since most of the header and the entire encrypted portion are changed significantly on every save. --- src/core/Database.cpp | 4 ++-- src/core/FileWatcher.cpp | 17 +++++++++++++---- src/core/FileWatcher.h | 3 ++- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/core/Database.cpp b/src/core/Database.cpp index 944597f56..eb01f7314 100644 --- a/src/core/Database.cpp +++ b/src/core/Database.cpp @@ -158,7 +158,7 @@ bool Database::open(const QString& filePath, QSharedPointer m_initialized = true; emit databaseOpened(); - m_fileWatcher->start(canonicalFilePath()); + m_fileWatcher->start(canonicalFilePath(), 30, 1); setEmitModified(true); return true; @@ -234,7 +234,7 @@ bool Database::saveAs(const QString& filePath, QString* error, bool atomic, bool bool ok = performSave(canonicalFilePath, error, atomic, backup); if (ok) { setFilePath(filePath); - m_fileWatcher->start(canonicalFilePath); + m_fileWatcher->start(canonicalFilePath, 30, 1); } else { // Saving failed, don't rewatch file since it does not represent our database markAsModified(); diff --git a/src/core/FileWatcher.cpp b/src/core/FileWatcher.cpp index 1b39e597d..82328832f 100644 --- a/src/core/FileWatcher.cpp +++ b/src/core/FileWatcher.cpp @@ -42,7 +42,7 @@ FileWatcher::FileWatcher(QObject* parent) m_fileIgnoreDelayTimer.setSingleShot(true); } -void FileWatcher::start(const QString& filePath, int checksumInterval) +void FileWatcher::start(const QString& filePath, int checksumIntervalSeconds, int checksumSizeKibibytes) { stop(); @@ -63,8 +63,14 @@ void FileWatcher::start(const QString& filePath, int checksumInterval) m_fileWatcher.addPath(filePath); m_filePath = filePath; + + // Handle file checksum + m_fileChecksumSizeBytes = checksumSizeKibibytes * 1024; m_fileChecksum = calculateChecksum(); - m_fileChecksumTimer.start(checksumInterval); + if (checksumIntervalSeconds > 0) { + m_fileChecksumTimer.start(checksumIntervalSeconds * 1000); + } + m_ignoreFileChange = false; } @@ -131,9 +137,12 @@ QByteArray FileWatcher::calculateChecksum() QFile file(m_filePath); if (file.open(QFile::ReadOnly)) { QCryptographicHash hash(QCryptographicHash::Sha256); - if (hash.addData(&file)) { - return hash.result(); + if (m_fileChecksumSizeBytes > 0) { + hash.addData(file.read(m_fileChecksumSizeBytes)); + } else { + hash.addData(&file); } + return hash.result(); } return {}; } diff --git a/src/core/FileWatcher.h b/src/core/FileWatcher.h index 3793ae860..fea05fc84 100644 --- a/src/core/FileWatcher.h +++ b/src/core/FileWatcher.h @@ -30,7 +30,7 @@ class FileWatcher : public QObject public: explicit FileWatcher(QObject* parent = nullptr); - void start(const QString& path, int checksumInterval = 1000); + void start(const QString& path, int checksumIntervalSeconds = 0, int checksumSizeKibibytes = -1); void stop(); bool hasSameFileChecksum(); @@ -56,6 +56,7 @@ private: QTimer m_fileChangeDelayTimer; QTimer m_fileIgnoreDelayTimer; QTimer m_fileChecksumTimer; + int m_fileChecksumSizeBytes; bool m_ignoreFileChange; }; From ac7face247723d8c258d36e7f769f293aa9be3f2 Mon Sep 17 00:00:00 2001 From: Sergei Zyubin Date: Wed, 30 Oct 2019 14:53:57 +0100 Subject: [PATCH 3/7] Fix mixed translations for keepassxc-cli (#3732) Fix mixed translations for keepassxc-cli --- share/translations/CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/share/translations/CMakeLists.txt b/share/translations/CMakeLists.txt index 5ca739695..ffd4698b0 100644 --- a/share/translations/CMakeLists.txt +++ b/share/translations/CMakeLists.txt @@ -33,5 +33,9 @@ endif() set(QM_FILES ${QM_FILES} ${QTBASE_TRANSLATIONS}) install(FILES ${QM_FILES} DESTINATION ${DATA_INSTALL_DIR}/translations) + +# Add keepassx_en.qm as a fallback for uncommon english locales +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/keepassx_en_US.qm DESTINATION ${DATA_INSTALL_DIR}/translations RENAME keepassx_en.qm) + add_custom_target(translations DEPENDS ${QM_FILES}) add_dependencies(${PROGNAME} translations) From 98badfb4a2e69df7666839d097c577d6df13a9ed Mon Sep 17 00:00:00 2001 From: asapelkin Date: Thu, 31 Oct 2019 23:44:40 +0300 Subject: [PATCH 4/7] some cppcheck and clang-tidy fixies --- src/cli/Clip.cpp | 2 +- src/cli/Import.cpp | 4 ++-- src/cli/List.cpp | 2 +- src/cli/Locate.cpp | 2 +- src/core/IconDownloader.cpp | 2 +- src/format/OpVaultReader.cpp | 2 ++ tests/TestCsvParser.cpp | 10 +++++----- tests/TestEntryModel.cpp | 4 ++-- tests/TestGroup.cpp | 2 +- 9 files changed, 16 insertions(+), 14 deletions(-) diff --git a/src/cli/Clip.cpp b/src/cli/Clip.cpp index 2b1dfdc1b..482ad8a13 100644 --- a/src/cli/Clip.cpp +++ b/src/cli/Clip.cpp @@ -46,7 +46,7 @@ Clip::Clip() int Clip::executeWithDatabase(QSharedPointer database, QSharedPointer parser) { const QStringList args = parser->positionalArguments(); - QString entryPath = args.at(1); + const QString& entryPath = args.at(1); QString timeout; if (args.size() == 3) { timeout = args.at(2); diff --git a/src/cli/Import.cpp b/src/cli/Import.cpp index ff6fb266b..0907f00ab 100644 --- a/src/cli/Import.cpp +++ b/src/cli/Import.cpp @@ -60,8 +60,8 @@ int Import::execute(const QStringList& arguments) TextStream errorTextStream(Utils::STDERR, QIODevice::WriteOnly); const QStringList args = parser->positionalArguments(); - const QString xmlExportPath = args.at(0); - const QString dbPath = args.at(1); + const QString& xmlExportPath = args.at(0); + const QString& dbPath = args.at(1); if (QFileInfo::exists(dbPath)) { errorTextStream << QObject::tr("File %1 already exists.").arg(dbPath) << endl; diff --git a/src/cli/List.cpp b/src/cli/List.cpp index 62e67aed8..d068cdf53 100644 --- a/src/cli/List.cpp +++ b/src/cli/List.cpp @@ -60,7 +60,7 @@ int List::executeWithDatabase(QSharedPointer database, QSharedPointer< return EXIT_SUCCESS; } - QString groupPath = args.at(1); + const QString& groupPath = args.at(1); Group* group = database->rootGroup()->findGroupByPath(groupPath); if (!group) { errorTextStream << QObject::tr("Cannot find group %1.").arg(groupPath) << endl; diff --git a/src/cli/Locate.cpp b/src/cli/Locate.cpp index eeb37d803..9b574852d 100644 --- a/src/cli/Locate.cpp +++ b/src/cli/Locate.cpp @@ -40,7 +40,7 @@ int Locate::executeWithDatabase(QSharedPointer database, QSharedPointe { const QStringList args = parser->positionalArguments(); - QString searchTerm = args.at(1); + const QString& searchTerm = args.at(1); TextStream outputTextStream(Utils::STDOUT, QIODevice::WriteOnly); TextStream errorTextStream(Utils::STDERR, QIODevice::WriteOnly); diff --git a/src/core/IconDownloader.cpp b/src/core/IconDownloader.cpp index 36047ce2a..fe346becd 100644 --- a/src/core/IconDownloader.cpp +++ b/src/core/IconDownloader.cpp @@ -90,7 +90,7 @@ void IconDownloader::setUrl(const QString& entryUrl) // searching for a match with the returned address(es). bool hostIsIp = false; QList hostAddressess = QHostInfo::fromName(fullyQualifiedDomain).addresses(); - for (auto addr : hostAddressess) { + for (const auto& addr : hostAddressess) { if (addr.toString() == fullyQualifiedDomain) { hostIsIp = true; } diff --git a/src/format/OpVaultReader.cpp b/src/format/OpVaultReader.cpp index 49d62b624..cc72653fd 100644 --- a/src/format/OpVaultReader.cpp +++ b/src/format/OpVaultReader.cpp @@ -341,6 +341,8 @@ OpVaultReader::decodeB64CompositeKeys(const QString& b64, const QByteArray& encK result->errorStr = tr("Unable to decode masterKey: %1").arg(keyKey01.errorString()); return result; } + delete result; + const QByteArray keyKey = keyKey01.getClearText(); return decodeCompositeKeys(keyKey); diff --git a/tests/TestCsvParser.cpp b/tests/TestCsvParser.cpp index 46d254098..f31e30414 100644 --- a/tests/TestCsvParser.cpp +++ b/tests/TestCsvParser.cpp @@ -111,7 +111,7 @@ void TestCsvParser::testEmptySimple() out << ""; QVERIFY(parser->parse(file.data())); t = parser->getCsvTable(); - QVERIFY(t.size() == 0); + QVERIFY(t.isEmpty()); } void TestCsvParser::testEmptyQuoted() @@ -120,7 +120,7 @@ void TestCsvParser::testEmptyQuoted() out << "\"\""; QVERIFY(parser->parse(file.data())); t = parser->getCsvTable(); - QVERIFY(t.size() == 0); + QVERIFY(t.isEmpty()); } void TestCsvParser::testEmptyNewline() @@ -129,14 +129,14 @@ void TestCsvParser::testEmptyNewline() out << "\"\n\""; QVERIFY(parser->parse(file.data())); t = parser->getCsvTable(); - QVERIFY(t.size() == 0); + QVERIFY(t.isEmpty()); } void TestCsvParser::testEmptyFile() { QVERIFY(parser->parse(file.data())); t = parser->getCsvTable(); - QVERIFY(t.size() == 0); + QVERIFY(t.isEmpty()); } void TestCsvParser::testNewline() @@ -281,7 +281,7 @@ void TestCsvParser::testEmptyReparsing() parser->parse(nullptr); QVERIFY(parser->reparse()); t = parser->getCsvTable(); - QVERIFY(t.size() == 0); + QVERIFY(t.isEmpty()); } void TestCsvParser::testReparsing() diff --git a/tests/TestEntryModel.cpp b/tests/TestEntryModel.cpp index e32de2466..670e43aab 100644 --- a/tests/TestEntryModel.cpp +++ b/tests/TestEntryModel.cpp @@ -296,7 +296,7 @@ void TestEntryModel::testProxyModel() QSignalSpy spyColumnRemove(modelProxy, SIGNAL(columnsAboutToBeRemoved(QModelIndex, int, int))); modelProxy->hideColumn(0, true); QCOMPARE(modelProxy->columnCount(), 12); - QVERIFY(spyColumnRemove.size() >= 1); + QVERIFY(!spyColumnRemove.isEmpty()); int oldSpyColumnRemoveSize = spyColumnRemove.size(); modelProxy->hideColumn(0, true); @@ -318,7 +318,7 @@ void TestEntryModel::testProxyModel() QSignalSpy spyColumnInsert(modelProxy, SIGNAL(columnsAboutToBeInserted(QModelIndex, int, int))); modelProxy->hideColumn(0, false); QCOMPARE(modelProxy->columnCount(), 13); - QVERIFY(spyColumnInsert.size() >= 1); + QVERIFY(!spyColumnInsert.isEmpty()); int oldSpyColumnInsertSize = spyColumnInsert.size(); modelProxy->hideColumn(0, false); diff --git a/tests/TestGroup.cpp b/tests/TestGroup.cpp index ae9c59894..9fc39dc64 100644 --- a/tests/TestGroup.cpp +++ b/tests/TestGroup.cpp @@ -1070,7 +1070,7 @@ void TestGroup::testHierarchy() QVERIFY(hierarchy.contains("group3")); hierarchy = group3->hierarchy(0); - QVERIFY(hierarchy.size() == 0); + QVERIFY(hierarchy.isEmpty()); hierarchy = group3->hierarchy(1); QVERIFY(hierarchy.size() == 1); From f4d6b4d13ae810cf1ce231cb03f98106149b9bc7 Mon Sep 17 00:00:00 2001 From: louib Date: Mon, 28 Oct 2019 13:27:29 -0400 Subject: [PATCH 5/7] CLI: do not display protected fields by default. --- share/docs/man/keepassxc-cli.1 | 4 ++++ src/cli/Show.cpp | 21 ++++++++++++++++----- src/cli/Show.h | 1 + tests/TestCli.cpp | 23 +++++++++++++++++++++-- 4 files changed, 42 insertions(+), 7 deletions(-) diff --git a/share/docs/man/keepassxc-cli.1 b/share/docs/man/keepassxc-cli.1 index 15d0fedc1..bcc97efae 100644 --- a/share/docs/man/keepassxc-cli.1 +++ b/share/docs/man/keepassxc-cli.1 @@ -182,6 +182,10 @@ an error if no TOTP is configured for the entry. 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 \fI-t\fP 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. + +.IP "-s, --show-protected" +Shows the protected attributes in clear text. .IP "-t, --totp" Also shows the current TOTP, reporting an error if no TOTP is configured for diff --git a/src/cli/Show.cpp b/src/cli/Show.cpp index 7da1c871c..646d5d90d 100644 --- a/src/cli/Show.cpp +++ b/src/cli/Show.cpp @@ -31,6 +31,11 @@ const QCommandLineOption Show::TotpOption = QCommandLineOption(QStringList() << << "totp", QObject::tr("Show the entry's current TOTP.")); +const QCommandLineOption Show::ProtectedAttributesOption = + QCommandLineOption(QStringList() << "s" + << "show-protected", + QObject::tr("Show the protected attributes in clear text.")); + const QCommandLineOption Show::AttributesOption = QCommandLineOption( QStringList() << "a" << "attributes", @@ -46,6 +51,7 @@ Show::Show() description = QObject::tr("Show an entry's information."); options.append(Show::TotpOption); options.append(Show::AttributesOption); + options.append(Show::ProtectedAttributesOption); positionalArguments.append({QString("entry"), QObject::tr("Name of the entry to show."), QString("")}); } @@ -57,6 +63,7 @@ int Show::executeWithDatabase(QSharedPointer database, QSharedPointer< const QStringList args = parser->positionalArguments(); const QString& entryPath = args.at(1); bool showTotp = parser->isSet(Show::TotpOption); + bool showProtectedAttributes = parser->isSet(Show::ProtectedAttributesOption); QStringList attributes = parser->values(Show::AttributesOption); Entry* entry = database->rootGroup()->findEntryByPath(entryPath); @@ -78,16 +85,20 @@ int Show::executeWithDatabase(QSharedPointer database, QSharedPointer< // Iterate over the attributes and output them line-by-line. bool sawUnknownAttribute = false; - for (const QString& attribute : asConst(attributes)) { - if (!entry->attributes()->contains(attribute)) { + for (const QString& attributeName : asConst(attributes)) { + if (!entry->attributes()->contains(attributeName)) { sawUnknownAttribute = true; - errorTextStream << QObject::tr("ERROR: unknown attribute %1.").arg(attribute) << endl; + errorTextStream << QObject::tr("ERROR: unknown attribute %1.").arg(attributeName) << endl; continue; } if (showAttributeNames) { - outputTextStream << attribute << ": "; + outputTextStream << attributeName << ": "; + } + if (entry->attributes()->isProtected(attributeName) && showAttributeNames && !showProtectedAttributes) { + outputTextStream << "PROTECTED" << endl; + } else { + outputTextStream << entry->resolveMultiplePlaceholders(entry->attributes()->value(attributeName)) << endl; } - outputTextStream << entry->resolveMultiplePlaceholders(entry->attributes()->value(attribute)) << endl; } if (showTotp) { diff --git a/src/cli/Show.h b/src/cli/Show.h index 03700b465..bf76c6973 100644 --- a/src/cli/Show.h +++ b/src/cli/Show.h @@ -29,6 +29,7 @@ public: static const QCommandLineOption TotpOption; static const QCommandLineOption AttributesOption; + static const QCommandLineOption ProtectedAttributesOption; }; #endif // KEEPASSXC_SHOW_H diff --git a/tests/TestCli.cpp b/tests/TestCli.cpp index f1f39e9f5..8a9ab50ce 100644 --- a/tests/TestCli.cpp +++ b/tests/TestCli.cpp @@ -1682,14 +1682,15 @@ void TestCli::testShow() QCOMPARE(m_stdoutFile->readAll(), QByteArray("Title: Sample Entry\n" "UserName: User Name\n" - "Password: Password\n" + "Password: PROTECTED\n" "URL: http://www.somesite.com/\n" "Notes: Notes\n")); qint64 pos = m_stdoutFile->pos(); Utils::Test::setNextPassword("a"); - showCmd.execute({"show", m_dbFile->fileName(), "-q", "/Sample Entry"}); + showCmd.execute({"show", "-s", m_dbFile->fileName(), "/Sample Entry"}); m_stdoutFile->seek(pos); + m_stdoutFile->readLine(); // skip password prompt QCOMPARE(m_stdoutFile->readAll(), QByteArray("Title: Sample Entry\n" "UserName: User Name\n" @@ -1697,6 +1698,17 @@ void TestCli::testShow() "URL: http://www.somesite.com/\n" "Notes: Notes\n")); + pos = m_stdoutFile->pos(); + Utils::Test::setNextPassword("a"); + showCmd.execute({"show", m_dbFile->fileName(), "-q", "/Sample Entry"}); + m_stdoutFile->seek(pos); + QCOMPARE(m_stdoutFile->readAll(), + QByteArray("Title: Sample Entry\n" + "UserName: User Name\n" + "Password: PROTECTED\n" + "URL: http://www.somesite.com/\n" + "Notes: Notes\n")); + pos = m_stdoutFile->pos(); Utils::Test::setNextPassword("a"); showCmd.execute({"show", "-a", "Title", m_dbFile->fileName(), "/Sample Entry"}); @@ -1704,6 +1716,13 @@ void TestCli::testShow() m_stdoutFile->readLine(); // skip password prompt QCOMPARE(m_stdoutFile->readAll(), QByteArray("Sample Entry\n")); + pos = m_stdoutFile->pos(); + Utils::Test::setNextPassword("a"); + showCmd.execute({"show", "-a", "Password", m_dbFile->fileName(), "/Sample Entry"}); + m_stdoutFile->seek(pos); + m_stdoutFile->readLine(); // skip password prompt + QCOMPARE(m_stdoutFile->readAll(), QByteArray("Password\n")); + pos = m_stdoutFile->pos(); Utils::Test::setNextPassword("a"); showCmd.execute({"show", "-a", "Title", "-a", "URL", m_dbFile->fileName(), "/Sample Entry"}); From 38a663163dc778ad8b4ea682ba965a90472347db Mon Sep 17 00:00:00 2001 From: Rafael Sadowski Date: Sat, 26 Oct 2019 22:50:49 +0200 Subject: [PATCH 6/7] Check include malloc.h and malloc_usable_size(3) One some operating systems malloc(3) is not in malloc.h nor in malloc_np.h, instead it is in stdlib.h. In addition, not all systems support malloc_usable_size(3). You could argue it's not safe. This patch tries to be portable and it fix the build on OpenBSD. --- CMakeLists.txt | 8 ++++++++ src/core/Alloc.cpp | 6 ++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 226460987..2c79261f7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -438,6 +438,14 @@ if(UNIX) int main() { prctl(PR_SET_DUMPABLE, 0); return 0; }" HAVE_PR_SET_DUMPABLE) + check_cxx_source_compiles("#include + int main() { return 0; }" + HAVE_MALLOC_H) + + check_cxx_source_compiles("#include + int main() { malloc_usable_size(NULL, 0); return 0; }" + HAVE_MALLOC_USABLE_SIZE) + check_cxx_source_compiles("#include int main() { struct rlimit limit; diff --git a/src/core/Alloc.cpp b/src/core/Alloc.cpp index 967b4e3ef..625386a3f 100644 --- a/src/core/Alloc.cpp +++ b/src/core/Alloc.cpp @@ -23,8 +23,10 @@ #include #elif defined(Q_OS_FREEBSD) #include -#else +#elif defined(HAVE_MALLOC_H) #include +#else +#include #endif #if defined(NDEBUG) && !defined(__cpp_sized_deallocation) @@ -64,7 +66,7 @@ void operator delete(void* ptr) noexcept ::operator delete(ptr, _msize(ptr)); #elif defined(Q_OS_MACOS) ::operator delete(ptr, malloc_size(ptr)); -#elif defined(Q_OS_UNIX) +#elif defined(HAVE_MALLOC_USABLE_SIZE) ::operator delete(ptr, malloc_usable_size(ptr)); #else // whatever OS this is, give up and simply free stuff From 1722397040fc1f8adcc8e555fbad1e5057a9ee20 Mon Sep 17 00:00:00 2001 From: Elvis Angelaccio Date: Sun, 3 Nov 2019 12:00:16 +0100 Subject: [PATCH 7/7] Show application icon in Plasma Wayland sessions (#3777) This is required to show the keepassxc icon on Wayland windows in a Plasma Wayland session. kwin_wayland fetches application icons from .desktop files and it expects the desktop filename to be set on the QGuiApplication instance. Without this, kwin sets a generic Wayland icon as fallback. --- src/main.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main.cpp b/src/main.cpp index 91eb1b73e..5aff860e1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -55,6 +55,10 @@ int main(int argc, char** argv) #endif #endif +#if QT_VERSION >= QT_VERSION_CHECK(5, 7, 0) + QGuiApplication::setDesktopFileName("org.keepassxc.KeePassXC.desktop"); +#endif + Application app(argc, argv); Application::setApplicationName("keepassxc"); Application::setApplicationVersion(KEEPASSXC_VERSION);