From e17bee8e3158f60b48b908e996024c0a49012712 Mon Sep 17 00:00:00 2001 From: Jonathan White Date: Tue, 27 Feb 2018 21:34:54 -0500 Subject: [PATCH 001/267] Properly rename argon2 symbols on Win32 builds --- cmake/FindArgon2.cmake | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cmake/FindArgon2.cmake b/cmake/FindArgon2.cmake index c0fb53b4..bb2f5811 100644 --- a/cmake/FindArgon2.cmake +++ b/cmake/FindArgon2.cmake @@ -21,7 +21,9 @@ if (MINGW) message(STATUS "Patching libargon2...\n") execute_process(COMMAND objcopy --redefine-sym argon2_hash=libargon2_argon2_hash + --redefine-sym _argon2_hash=_libargon2_argon2_hash --redefine-sym argon2_error_message=libargon2_argon2_error_message + --redefine-sym _argon2_error_message=_libargon2_argon2_error_message ${ARGON2_SYS_LIBRARIES} ${CMAKE_BINARY_DIR}/libargon2_patched.a WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) find_library(ARGON2_LIBRARIES libargon2_patched.a PATHS ${CMAKE_BINARY_DIR} NO_DEFAULT_PATH) From 5a9099393899a88a6eb30527505360e533b3b7ca Mon Sep 17 00:00:00 2001 From: Jonathan White Date: Tue, 27 Feb 2018 21:42:57 -0500 Subject: [PATCH 002/267] Force snapcraft builds to be release builds --- snapcraft.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/snapcraft.yaml b/snapcraft.yaml index f4b90661..70117418 100644 --- a/snapcraft.yaml +++ b/snapcraft.yaml @@ -28,6 +28,7 @@ parts: - -DCMAKE_BUILD_TYPE=Release - -DCMAKE_INSTALL_PREFIX=/usr - -DKEEPASSXC_DIST_TYPE=Snap + - -DKEEPASSXC_BUILD_TYPE=Release - -DWITH_TESTS=OFF - -DWITH_XC_ALL=ON build-packages: From 3f7f1aa47f3d94fd86bab489ec627de034bb1d10 Mon Sep 17 00:00:00 2001 From: Thomas Klausner Date: Wed, 28 Feb 2018 16:31:21 +0100 Subject: [PATCH 003/267] Fix build on NetBSD. (#1557) * Fix build on NetBSD. --- src/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 69526967..f7616dce 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -175,7 +175,7 @@ if(APPLE) core/MacPasteboard.cpp ) endif() -if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux" OR ${CMAKE_SYSTEM_NAME} STREQUAL "OpenBSD") +if(UNIX AND NOT APPLE) set(keepassx_SOURCES ${keepassx_SOURCES} core/ScreenLockListenerDBus.h core/ScreenLockListenerDBus.cpp From cdd68527099bbf2724f742e9a5b1e39c650bb259 Mon Sep 17 00:00:00 2001 From: Steven Noonan Date: Mon, 5 Mar 2018 09:10:38 -0800 Subject: [PATCH 004/267] KdbxReader::readDatabase: abort if reading magic numbers fails Building with -flto caught the fact that we were ignoring the return value of readMagicNumbers(), which potentially left the value of 'sig2' uninitialized. Signed-off-by: Steven Noonan --- src/format/KdbxReader.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/format/KdbxReader.cpp b/src/format/KdbxReader.cpp index 36ff6d19..5393b743 100644 --- a/src/format/KdbxReader.cpp +++ b/src/format/KdbxReader.cpp @@ -71,7 +71,9 @@ Database* KdbxReader::readDatabase(QIODevice* device, const CompositeKey& key, b // read KDBX magic numbers quint32 sig1, sig2; - readMagicNumbers(&headerStream, sig1, sig2, m_kdbxVersion); + if (!readMagicNumbers(&headerStream, sig1, sig2, m_kdbxVersion)) { + return nullptr; + } m_kdbxSignature = qMakePair(sig1, sig2); // mask out minor version From 46e8e3dbbce6e1a52bdbc8dcec20e60e766dfc2a Mon Sep 17 00:00:00 2001 From: Thomas Luzat Date: Thu, 8 Mar 2018 10:20:25 +0100 Subject: [PATCH 005/267] Test speedup (#1678) * Tests: Speed up AutoType testing Decrease default autotype delay to 1 to improve test suite speed by seconds. This shaves multiple seconds off the whole test suite. In some cases, the largest part. Also, initialize config just creating the test instance, just in case that it ever depends on the configuration values at that point already. * Tests: Speed up Kdbx4 testing This speeds up the Kdbx4 tests by using parameters optimized for speed for the key derivation functions. On an i7-6700K the tests run close to 50% faster with this change (about 1.5s vs. 3s). --- tests/TestAutoType.cpp | 3 ++- tests/TestKdbx4.cpp | 30 +++++++++++++++++++++++------- tests/TestKdbx4.h | 2 ++ 3 files changed, 27 insertions(+), 8 deletions(-) diff --git a/tests/TestAutoType.cpp b/tests/TestAutoType.cpp index 25790e3b..5eaed66a 100644 --- a/tests/TestAutoType.cpp +++ b/tests/TestAutoType.cpp @@ -35,8 +35,9 @@ void TestAutoType::initTestCase() { QVERIFY(Crypto::init()); Config::createTempFileInstance(); - AutoType::createTestInstance(); + config()->set("AutoTypeDelay", 1); config()->set("security/autotypeask", false); + AutoType::createTestInstance(); QPluginLoader loader(filePath()->pluginPath("keepassx-autotype-test")); loader.setLoadHints(QLibrary::ResolveAllSymbolsHint); diff --git a/tests/TestKdbx4.cpp b/tests/TestKdbx4.cpp index 4bbff1fe..f0ef1bfa 100644 --- a/tests/TestKdbx4.cpp +++ b/tests/TestKdbx4.cpp @@ -34,8 +34,8 @@ QTEST_GUILESS_MAIN(TestKdbx4) void TestKdbx4::initTestCaseImpl() { - m_xmlDb->changeKdf(KeePass2::uuidToKdf(KeePass2::KDF_ARGON2)); - m_kdbxSourceDb->changeKdf(KeePass2::uuidToKdf(KeePass2::KDF_ARGON2)); + m_xmlDb->changeKdf(fastKdf(KeePass2::uuidToKdf(KeePass2::KDF_ARGON2))); + m_kdbxSourceDb->changeKdf(fastKdf(KeePass2::uuidToKdf(KeePass2::KDF_ARGON2))); } Database* TestKdbx4::readXml(const QString& path, bool strictMode, bool& hasError, QString& errorString) @@ -93,7 +93,7 @@ void TestKdbx4::readKdbx(const QString& path, CompositeKey const& key, QScopedPo void TestKdbx4::writeKdbx(QIODevice* device, Database* db, bool& hasError, QString& errorString) { if (db->kdf()->uuid() == KeePass2::KDF_AES_KDBX3) { - db->changeKdf(KeePass2::uuidToKdf(KeePass2::KDF_ARGON2)); + db->changeKdf(fastKdf(KeePass2::uuidToKdf(KeePass2::KDF_ARGON2))); } KeePass2Writer writer; hasError = writer.writeDatabase(device, db); @@ -137,6 +137,7 @@ void TestKdbx4::testFormat400Upgrade() QFETCH(quint32, expectedVersion); QScopedPointer sourceDb(new Database()); + sourceDb->changeKdf(fastKdf(sourceDb->kdf())); sourceDb->metadata()->setName("Wubba lubba dub dub"); QCOMPARE(sourceDb->kdf()->uuid(), KeePass2::KDF_AES_KDBX3); // default is legacy AES-KDF @@ -148,7 +149,7 @@ void TestKdbx4::testFormat400Upgrade() buffer.open(QBuffer::ReadWrite); // upgrade to KDBX 4 by changing KDF and Cipher - sourceDb->changeKdf(KeePass2::uuidToKdf(kdfUuid)); + sourceDb->changeKdf(fastKdf(KeePass2::uuidToKdf(kdfUuid))); sourceDb->setCipher(cipherUuid); // CustomData in meta should not cause any version change @@ -235,6 +236,7 @@ void TestKdbx4::testUpgradeMasterKeyIntegrity() compositeKey.addChallengeResponseKey(crKey); QScopedPointer db(new Database()); + db->changeKdf(fastKdf(db->kdf())); db->setKey(compositeKey); // upgrade the database by a specific method @@ -243,11 +245,11 @@ void TestKdbx4::testUpgradeMasterKeyIntegrity() } else if (upgradeAction == "meta-customdata") { db->metadata()->customData()->set("abc", "def"); } else if (upgradeAction == "kdf-aes-kdbx3") { - db->changeKdf(KeePass2::uuidToKdf(KeePass2::KDF_AES_KDBX3)); + db->changeKdf(fastKdf(KeePass2::uuidToKdf(KeePass2::KDF_AES_KDBX3))); } else if (upgradeAction == "kdf-argon2") { - db->changeKdf(KeePass2::uuidToKdf(KeePass2::KDF_ARGON2)); + db->changeKdf(fastKdf(KeePass2::uuidToKdf(KeePass2::KDF_ARGON2))); } else if (upgradeAction == "kdf-aes-kdbx4") { - db->changeKdf(KeePass2::uuidToKdf(KeePass2::KDF_AES_KDBX4)); + db->changeKdf(fastKdf(KeePass2::uuidToKdf(KeePass2::KDF_AES_KDBX4))); } else if (upgradeAction == "public-customdata") { db->publicCustomData().insert("abc", "def"); } else if (upgradeAction == "rootgroup-customdata") { @@ -403,3 +405,17 @@ void TestKdbx4::testCustomData() QCOMPARE(newEntry->customData()->value(customDataKey1), customData1); QCOMPARE(newEntry->customData()->value(customDataKey2), customData2); } + +QSharedPointer TestKdbx4::fastKdf(QSharedPointer kdf) +{ + kdf->setRounds(1); + + if (kdf->uuid() == KeePass2::KDF_ARGON2) { + kdf->processParameters({ + {KeePass2::KDFPARAM_ARGON2_MEMORY, 1024}, + {KeePass2::KDFPARAM_ARGON2_PARALLELISM, 1} + }); + } + + return kdf; +} diff --git a/tests/TestKdbx4.h b/tests/TestKdbx4.h index efb3449f..e278ebb0 100644 --- a/tests/TestKdbx4.h +++ b/tests/TestKdbx4.h @@ -44,6 +44,8 @@ protected: void readKdbx(QIODevice* device, CompositeKey const& key, QScopedPointer& db, bool& hasError, QString& errorString) override; void writeKdbx(QIODevice* device, Database* db, bool& hasError, QString& errorString) override; + + QSharedPointer fastKdf(QSharedPointer kdf); }; #endif // KEEPASSXC_TEST_KDBX4_H From e718e9f5e5547654685b043b73ff8c4ee2256e0c Mon Sep 17 00:00:00 2001 From: Edward Jones Date: Tue, 13 Mar 2018 19:55:37 +0000 Subject: [PATCH 006/267] Fix file dialog filter translations --- src/browser/BrowserOptionDialog.cpp | 4 ++-- src/gui/DatabaseTabWidget.cpp | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/browser/BrowserOptionDialog.cpp b/src/browser/BrowserOptionDialog.cpp index 693e62d2..1ad7e8b3 100755 --- a/src/browser/BrowserOptionDialog.cpp +++ b/src/browser/BrowserOptionDialog.cpp @@ -130,9 +130,9 @@ void BrowserOptionDialog::saveSettings() void BrowserOptionDialog::showProxyLocationFileDialog() { #ifdef Q_OS_WIN - QString fileTypeFilter(tr("Executable Files (*.exe);;All Files (*.*)")); + QString fileTypeFilter(QString("%1 (*.exe);;%2 (*.*)").arg(tr("Executable Files"), tr("All Files"))); #else - QString fileTypeFilter(tr("Executable Files (*)")); + QString fileTypeFilter(QString("%1 (*)").arg(tr("Executable Files"))); #endif auto proxyLocation = QFileDialog::getOpenFileName(this, tr("Select custom proxy location"), QFileInfo(QCoreApplication::applicationDirPath()).filePath(), diff --git a/src/gui/DatabaseTabWidget.cpp b/src/gui/DatabaseTabWidget.cpp index b3963f7b..ef25e90f 100644 --- a/src/gui/DatabaseTabWidget.cpp +++ b/src/gui/DatabaseTabWidget.cpp @@ -181,8 +181,9 @@ void DatabaseTabWidget::openDatabase(const QString& fileName, const QString& pw, void DatabaseTabWidget::importCsv() { + QString filter = QString("%1 (*.csv);;%2 (*)").arg(tr("CSV file"), tr("All files")); QString fileName = fileDialog()->getOpenFileName(this, tr("Open CSV file"), QString(), - tr("CSV file") + " (*.csv);;" + tr("All files (*)")); + filter); if (fileName.isEmpty()) { return; @@ -213,8 +214,9 @@ void DatabaseTabWidget::mergeDatabase(const QString& fileName) void DatabaseTabWidget::importKeePass1Database() { + QString filter = QString("%1 (*.kdb);;%2 (*)").arg(tr("KeePass 1 database"), tr("All files")); QString fileName = fileDialog()->getOpenFileName(this, tr("Open KeePass 1 database"), QString(), - tr("KeePass 1 database") + " (*.kdb);;" + tr("All files (*)")); + filter); if (fileName.isEmpty()) { return; From 3def6a3bc472832b98d1b257288eaf06a360ecf7 Mon Sep 17 00:00:00 2001 From: Edward Jones Date: Tue, 13 Mar 2018 19:59:08 +0000 Subject: [PATCH 007/267] Fix weird base strings and reduce concatenation --- src/browser/BrowserService.cpp | 2 +- src/core/CsvParser.cpp | 2 +- src/core/Database.cpp | 2 +- src/gui/AboutDialog.cpp | 4 ++-- src/gui/ChangeMasterKeyWidget.cpp | 4 ++-- src/gui/DatabaseOpenWidget.cpp | 2 +- src/gui/DatabaseRepairWidget.cpp | 2 +- src/gui/SearchWidget.cpp | 2 +- src/gui/TotpDialog.cpp | 2 +- src/gui/csvImport/CsvImportWidget.cpp | 16 ++++++++-------- src/gui/csvImport/CsvParserModel.cpp | 7 ++++--- src/gui/entry/EditEntryWidget.cpp | 4 ++-- src/gui/entry/EntryAttachmentsWidget.cpp | 2 +- 13 files changed, 26 insertions(+), 25 deletions(-) diff --git a/src/browser/BrowserService.cpp b/src/browser/BrowserService.cpp index fb89e8bc..e59411ae 100644 --- a/src/browser/BrowserService.cpp +++ b/src/browser/BrowserService.cpp @@ -437,7 +437,7 @@ void BrowserService::removeSharedEncryptionKeys() if (keysToRemove.isEmpty()) { QMessageBox::information(0, tr("KeePassXC: No keys found"), - tr("No shared encryption keys found in KeePassXC Settings."), + tr("No shared encryption keys found in KeePassXC settings."), QMessageBox::Ok); return; } diff --git a/src/core/CsvParser.cpp b/src/core/CsvParser.cpp index 6a963fc4..2032e8f6 100644 --- a/src/core/CsvParser.cpp +++ b/src/core/CsvParser.cpp @@ -84,7 +84,7 @@ bool CsvParser::readFile(QFile *device) { m_array.replace("\r\n", "\n"); m_array.replace("\r", "\n"); if (0 == m_array.size()) - appendStatusMsg(QObject::tr("file empty !\n")); + appendStatusMsg(QObject::tr("file empty").append("\n")); m_isFileLoaded = true; } return m_isFileLoaded; diff --git a/src/core/Database.cpp b/src/core/Database.cpp index 8fe8d04c..0c2d06b3 100644 --- a/src/core/Database.cpp +++ b/src/core/Database.cpp @@ -477,7 +477,7 @@ Database* Database::unlockFromStdin(QString databaseFilename, QString keyFilenam FileKey fileKey; QString errorMessage; if (!fileKey.load(keyFilename, &errorMessage)) { - errorTextStream << QObject::tr("Failed to load key file %1 : %2").arg(keyFilename, errorMessage); + errorTextStream << QObject::tr("Failed to load key file %1: %2").arg(keyFilename, errorMessage); errorTextStream << endl; return nullptr; } diff --git a/src/gui/AboutDialog.cpp b/src/gui/AboutDialog.cpp index adfdea0a..249807ee 100644 --- a/src/gui/AboutDialog.cpp +++ b/src/gui/AboutDialog.cpp @@ -53,9 +53,9 @@ AboutDialog::AboutDialog(QWidget* parent) } QString debugInfo = "KeePassXC - "; - debugInfo.append(tr("Version %1\n").arg(KEEPASSX_VERSION)); + debugInfo.append(tr("Version %1").arg(KEEPASSX_VERSION).append("\n")); #ifndef KEEPASSXC_BUILD_TYPE_RELEASE - debugInfo.append(tr("Build Type: %1\n").arg(KEEPASSXC_BUILD_TYPE)); + debugInfo.append(tr("Build Type: %1").arg(KEEPASSXC_BUILD_TYPE).append("\n")); #endif if (!commitHash.isEmpty()) { debugInfo.append(tr("Revision: %1").arg(commitHash.left(7)).append("\n")); diff --git a/src/gui/ChangeMasterKeyWidget.cpp b/src/gui/ChangeMasterKeyWidget.cpp index 28a0991d..79fd2712 100644 --- a/src/gui/ChangeMasterKeyWidget.cpp +++ b/src/gui/ChangeMasterKeyWidget.cpp @@ -85,7 +85,7 @@ void ChangeMasterKeyWidget::createKeyFile() QString errorMsg; bool created = FileKey::create(fileName, &errorMsg); if (!created) { - m_ui->messageWidget->showMessage(tr("Unable to create Key File : ").append(errorMsg), MessageWidget::Error); + m_ui->messageWidget->showMessage(tr("Unable to create key file: %1").arg(errorMsg), MessageWidget::Error); } else { m_ui->keyFileCombo->setEditText(fileName); @@ -159,7 +159,7 @@ void ChangeMasterKeyWidget::generateKey() QString fileKeyName = m_ui->keyFileCombo->currentText(); if (!fileKey.load(fileKeyName, &errorMsg)) { m_ui->messageWidget->showMessage( - tr("Failed to set %1 as the Key file:\n%2").arg(fileKeyName, errorMsg), MessageWidget::Error); + tr("Failed to set %1 as the key file:\n%2").arg(fileKeyName, errorMsg), MessageWidget::Error); return; } if (fileKey.type() != FileKey::Hashed) { diff --git a/src/gui/DatabaseOpenWidget.cpp b/src/gui/DatabaseOpenWidget.cpp index 3af0c6e8..a9311023 100644 --- a/src/gui/DatabaseOpenWidget.cpp +++ b/src/gui/DatabaseOpenWidget.cpp @@ -214,7 +214,7 @@ QSharedPointer DatabaseOpenWidget::databaseKey() QString keyFilename = m_ui->comboKeyFile->currentText(); QString errorMsg; if (!key.load(keyFilename, &errorMsg)) { - m_ui->messageWidget->showMessage(tr("Can't open key file").append(":\n").append(errorMsg), + m_ui->messageWidget->showMessage(tr("Can't open key file:\n%1").arg(errorMsg), MessageWidget::Error); return QSharedPointer(); } diff --git a/src/gui/DatabaseRepairWidget.cpp b/src/gui/DatabaseRepairWidget.cpp index d3dddf14..aa9613a2 100644 --- a/src/gui/DatabaseRepairWidget.cpp +++ b/src/gui/DatabaseRepairWidget.cpp @@ -50,7 +50,7 @@ void DatabaseRepairWidget::openDatabase() QString keyFilename = m_ui->comboKeyFile->currentText(); QString errorMsg; if (!key.load(keyFilename, &errorMsg)) { - MessageBox::warning(this, tr("Error"), tr("Can't open key file").append(":\n").append(errorMsg)); + MessageBox::warning(this, tr("Error"), tr("Can't open key file:\n%1").arg(errorMsg)); emit editFinished(false); return; } diff --git a/src/gui/SearchWidget.cpp b/src/gui/SearchWidget.cpp index ed3a50b2..bf961ecb 100644 --- a/src/gui/SearchWidget.cpp +++ b/src/gui/SearchWidget.cpp @@ -47,7 +47,7 @@ SearchWidget::SearchWidget(QWidget* parent) m_ui->searchEdit->installEventFilter(this); QMenu* searchMenu = new QMenu(); - m_actionCaseSensitive = searchMenu->addAction(tr("Case Sensitive"), this, SLOT(updateCaseSensitive())); + m_actionCaseSensitive = searchMenu->addAction(tr("Case sensitive"), this, SLOT(updateCaseSensitive())); m_actionCaseSensitive->setObjectName("actionSearchCaseSensitive"); m_actionCaseSensitive->setCheckable(true); diff --git a/src/gui/TotpDialog.cpp b/src/gui/TotpDialog.cpp index 7325d253..1529db0d 100644 --- a/src/gui/TotpDialog.cpp +++ b/src/gui/TotpDialog.cpp @@ -72,7 +72,7 @@ void TotpDialog::updateProgressBar() void TotpDialog::updateSeconds() { uint epoch = QDateTime::currentDateTime().toTime_t() - 1; - m_ui->timerLabel->setText(tr("Expires in") + " " + QString::number(m_step - (epoch % m_step)) + " " + tr("seconds")); + m_ui->timerLabel->setText(tr("Expires in %n second(s)", "", m_step - (epoch % m_step))); } void TotpDialog::updateTotp() diff --git a/src/gui/csvImport/CsvImportWidget.cpp b/src/gui/csvImport/CsvImportWidget.cpp index ad56a873..c2c2aa03 100644 --- a/src/gui/csvImport/CsvImportWidget.cpp +++ b/src/gui/csvImport/CsvImportWidget.cpp @@ -151,10 +151,10 @@ void CsvImportWidget::updatePreview() { if (m_ui->checkBoxFieldNames->isChecked()) { columnName = m_parserModel->getCsvTable().at(0).at(i); if (columnName.isEmpty()) - columnName = "<" + tr("Empty fieldname ") + QString::number(++emptyId) + ">"; + columnName = "<" + tr("Empty fieldname %1").arg(++emptyId) + ">"; list << columnName; } else { - list << QString(tr("column ")) + QString::number(i); + list << QString(tr("column %1").arg(i)); } } m_comboModel->setStringList(list); @@ -176,7 +176,7 @@ void CsvImportWidget::load(const QString& filename, Database* const db) { m_ui->labelFilename->setText(filename); Group* group = m_db->rootGroup(); group->setUuid(Uuid::random()); - group->setNotes(tr("Imported from CSV file").append("\n").append(tr("Original data: ")) + filename); + group->setNotes(tr("Imported from CSV file\nOriginal data: %1").arg(filename)); parse(); } @@ -188,7 +188,7 @@ void CsvImportWidget::parse() { updatePreview(); QApplication::restoreOverrideCursor(); if (!good) - m_ui->messageWidget->showMessage(tr("Error(s) detected in CSV file !").append("\n") + m_ui->messageWidget->showMessage(tr("Error(s) detected in CSV file!").append("\n") .append(formatStatusText()), MessageWidget::Warning); else m_ui->messageWidget->setHidden(true); @@ -201,8 +201,8 @@ QString CsvImportWidget::formatStatusText() const { int items = text.count('\n'); if (items > 2) { return text.section('\n', 0, 1) - .append("\n[").append(QString::number(items - 2)) - .append(tr(" more messages skipped]")); + .append("\n") + .append(tr("[%n more message(s) skipped]", "", items - 2)); } if (items == 1) { text.append(QString("\n")); @@ -247,8 +247,8 @@ void CsvImportWidget::writeDatabase() { KeePass2Writer writer; writer.writeDatabase(&buffer, m_db); if (writer.hasError()) - MessageBox::warning(this, tr("Error"), tr("CSV import: writer has errors:\n") - .append((writer.errorString())), QMessageBox::Ok, QMessageBox::Ok); + MessageBox::warning(this, tr("Error"), tr("CSV import: writer has errors:\n%1") + .arg(writer.errorString()), QMessageBox::Ok, QMessageBox::Ok); emit editFinished(true); } diff --git a/src/gui/csvImport/CsvParserModel.cpp b/src/gui/csvImport/CsvParserModel.cpp index 29f389df..eb2793f8 100644 --- a/src/gui/csvImport/CsvParserModel.cpp +++ b/src/gui/csvImport/CsvParserModel.cpp @@ -31,9 +31,10 @@ void CsvParserModel::setFilename(const QString& filename) { } QString CsvParserModel::getFileInfo(){ - QString a(tr("%n byte(s), ", nullptr, getFileSize())); - a.append(tr("%n row(s), ", nullptr, getCsvRows())); - a.append(tr("%n column(s)", nullptr, qMax(0, getCsvCols() - 1))); + QString a(tr("%1, %2, %3", "file info: bytes, rows, columns") + .arg(tr("%n byte(s)", nullptr, getFileSize())) + .arg(tr("%n row(s)", nullptr, getCsvRows())) + .arg(tr("%n column(s)", nullptr, qMax(0, getCsvCols() - 1)))); return a; } diff --git a/src/gui/entry/EditEntryWidget.cpp b/src/gui/entry/EditEntryWidget.cpp index 4d12dd16..4759af7a 100644 --- a/src/gui/entry/EditEntryWidget.cpp +++ b/src/gui/entry/EditEntryWidget.cpp @@ -916,7 +916,7 @@ void EditEntryWidget::insertAttribute() int i = 1; while (m_entryAttributes->keys().contains(name)) { - name = QString("%1 %2").arg(tr("New attribute")).arg(i); + name = tr("New attribute %1").arg(i); i++; } @@ -979,7 +979,7 @@ void EditEntryWidget::displayAttribute(QModelIndex index, bool showProtected) if (index.isValid()) { QString key = m_attributesModel->keyByIndex(index); if (showProtected) { - m_advancedUi->attributesEdit->setPlainText(tr("[PROTECTED]") + " " + tr("Press reveal to view or edit")); + m_advancedUi->attributesEdit->setPlainText(tr("[PROTECTED] Press reveal to view or edit")); m_advancedUi->attributesEdit->setEnabled(false); m_advancedUi->revealAttributeButton->setEnabled(true); m_advancedUi->protectAttributeButton->setChecked(true); diff --git a/src/gui/entry/EntryAttachmentsWidget.cpp b/src/gui/entry/EntryAttachmentsWidget.cpp index 16908361..78b6d741 100644 --- a/src/gui/entry/EntryAttachmentsWidget.cpp +++ b/src/gui/entry/EntryAttachmentsWidget.cpp @@ -162,7 +162,7 @@ void EntryAttachmentsWidget::removeSelectedAttachments() } const QString question = tr("Are you sure you want to remove %n attachment(s)?", "", indexes.count()); - QMessageBox::StandardButton answer = MessageBox::question(this, tr("Confirm Remove"), + QMessageBox::StandardButton answer = MessageBox::question(this, tr("Confirm remove"), question, QMessageBox::Yes | QMessageBox::No); if (answer == QMessageBox::Yes) { QStringList keys; From e66adfbf68bb0d4820ccfa0a36221ec9c898ba5e Mon Sep 17 00:00:00 2001 From: Edward Jones Date: Tue, 13 Mar 2018 20:02:38 +0000 Subject: [PATCH 008/267] Make more strings translatable Includes making certain modifiers (like "[locked]") positionable, in case languages put this before the word --- src/core/CsvParser.cpp | 6 ++---- src/core/Entry.cpp | 2 +- src/core/Group.cpp | 4 ++-- src/format/Kdbx3Reader.cpp | 10 +++++----- src/format/KdbxXmlReader.cpp | 5 +++-- src/format/KeePass1Reader.cpp | 2 +- src/gui/AboutDialog.cpp | 12 ++++++------ src/gui/DatabaseTabWidget.cpp | 4 ++-- src/gui/DetailsWidget.cpp | 2 +- src/gui/MainWindow.cpp | 2 +- 10 files changed, 24 insertions(+), 25 deletions(-) diff --git a/src/core/CsvParser.cpp b/src/core/CsvParser.cpp index 2032e8f6..4fc4281b 100644 --- a/src/core/CsvParser.cpp +++ b/src/core/CsvParser.cpp @@ -377,10 +377,8 @@ int CsvParser::getCsvRows() const { void CsvParser::appendStatusMsg(QString s, bool isCritical) { - m_statusMsg += s - .append(": (row,col) " + QString::number(m_currRow)) - .append(",") - .append(QString::number(m_currCol)) + m_statusMsg += QObject::tr("%1: (row, col) %2,%3") + .arg(s, m_currRow, m_currCol) .append("\n"); m_isGood = !isCritical; } diff --git a/src/core/Entry.cpp b/src/core/Entry.cpp index 25ef6b50..00fec506 100644 --- a/src/core/Entry.cpp +++ b/src/core/Entry.cpp @@ -681,7 +681,7 @@ Entry* Entry::clone(CloneFlags flags) const } if (flags & CloneRenameTitle) - entry->setTitle(entry->title() + tr(" - Clone", "Suffix added to cloned entries")); + entry->setTitle(tr("%1 - Clone").arg(entry->title())); return entry; } diff --git a/src/core/Group.cpp b/src/core/Group.cpp index 69267265..262a4af8 100644 --- a/src/core/Group.cpp +++ b/src/core/Group.cpp @@ -616,7 +616,7 @@ QString Group::print(bool recursive, int depth) QString indentation = QString(" ").repeated(depth); if (entries().isEmpty() && children().isEmpty()) { - response += indentation + "[empty]\n"; + response += indentation + tr("[empty]", "group has no children") + "\n"; return response; } @@ -911,7 +911,7 @@ void Group::markOlderEntry(Entry* entry) { entry->attributes()->set( "merged", - QString("older entry merged from database \"%1\"").arg(entry->group()->database()->metadata()->name())); + tr("older entry merged from database \"%1\"").arg(entry->group()->database()->metadata()->name())); } bool Group::resolveSearchingEnabled() const diff --git a/src/format/Kdbx3Reader.cpp b/src/format/Kdbx3Reader.cpp index 84f7db67..82d59bc6 100644 --- a/src/format/Kdbx3Reader.cpp +++ b/src/format/Kdbx3Reader.cpp @@ -42,7 +42,7 @@ Database* Kdbx3Reader::readDatabaseImpl(QIODevice* device, const QByteArray& hea if (m_masterSeed.isEmpty() || m_encryptionIV.isEmpty() || m_streamStartBytes.isEmpty() || m_protectedStreamKey.isEmpty() || m_db->cipher().isNull()) { - raiseError("missing database headers"); + raiseError(tr("missing database headers")); return nullptr; } @@ -134,7 +134,7 @@ Database* Kdbx3Reader::readDatabaseImpl(QIODevice* device, const QByteArray& hea if (!xmlReader.headerHash().isEmpty()) { QByteArray headerHash = CryptoHash::hash(headerData, CryptoHash::Sha256); if (headerHash != xmlReader.headerHash()) { - raiseError("Header doesn't match hash"); + raiseError(tr("Header doesn't match hash")); return nullptr; } } @@ -146,7 +146,7 @@ bool Kdbx3Reader::readHeaderField(StoreDataStream& headerStream) { QByteArray fieldIDArray = headerStream.read(1); if (fieldIDArray.size() != 1) { - raiseError("Invalid header id size"); + raiseError(tr("Invalid header id size")); return false; } char fieldID = fieldIDArray.at(0); @@ -154,7 +154,7 @@ bool Kdbx3Reader::readHeaderField(StoreDataStream& headerStream) bool ok; auto fieldLen = Endian::readSizedInt(&headerStream, KeePass2::BYTEORDER, &ok); if (!ok) { - raiseError("Invalid header field length"); + raiseError(tr("Invalid header field length")); return false; } @@ -162,7 +162,7 @@ bool Kdbx3Reader::readHeaderField(StoreDataStream& headerStream) if (fieldLen != 0) { fieldData = headerStream.read(fieldLen); if (fieldData.size() != fieldLen) { - raiseError("Invalid header data length"); + raiseError(tr("Invalid header data length")); return false; } } diff --git a/src/format/KdbxXmlReader.cpp b/src/format/KdbxXmlReader.cpp index 0eb9e1c6..77ec2604 100644 --- a/src/format/KdbxXmlReader.cpp +++ b/src/format/KdbxXmlReader.cpp @@ -179,8 +179,9 @@ QString KdbxXmlReader::errorString() const { if (m_error) { return m_errorStr; - }if (m_xml.hasError()) { - return QString("XML error:\n%1\nLine %2, column %3") + } + if (m_xml.hasError()) { + return tr("XML error:\n%1\nLine %2, column %3") .arg(m_xml.errorString()) .arg(m_xml.lineNumber()) .arg(m_xml.columnNumber()); diff --git a/src/format/KeePass1Reader.cpp b/src/format/KeePass1Reader.cpp index 39085707..02810b98 100644 --- a/src/format/KeePass1Reader.cpp +++ b/src/format/KeePass1Reader.cpp @@ -363,7 +363,7 @@ SymmetricCipherStream* KeePass1Reader::testKeys(const QString& password, const Q cipherStream->reset(); cipherStream->close(); if (!m_device->seek(contentPos)) { - QString msg = "unable to seek to content position"; + QString msg = tr("unable to seek to content position"); if (!m_device->errorString().isEmpty()) { msg.append("\n").append(m_device->errorString()); } diff --git a/src/gui/AboutDialog.cpp b/src/gui/AboutDialog.cpp index 249807ee..10f42cd7 100644 --- a/src/gui/AboutDialog.cpp +++ b/src/gui/AboutDialog.cpp @@ -82,23 +82,23 @@ AboutDialog::AboutDialog(QWidget* parent) QString extensions; #ifdef WITH_XC_AUTOTYPE - extensions += "\n- Auto-Type"; + extensions += "\n- " + tr("Auto-Type"); #endif #ifdef WITH_XC_BROWSER - extensions += "\n- Browser Integration"; + extensions += "\n- " + tr("Browser Integration"); #endif #ifdef WITH_XC_HTTP - extensions += "\n- Legacy Browser Integration (KeePassHTTP)"; + extensions += "\n- " + tr("Legacy Browser Integration (KeePassHTTP)"); #endif #ifdef WITH_XC_SSHAGENT - extensions += "\n- SSH Agent"; + extensions += "\n- " + tr("SSH Agent"); #endif #ifdef WITH_XC_YUBIKEY - extensions += "\n- YubiKey"; + extensions += "\n- " + tr("YubiKey"); #endif if (extensions.isEmpty()) - extensions = " None"; + extensions = " " + tr("None"); debugInfo.append(tr("Enabled extensions:").append(extensions)); diff --git a/src/gui/DatabaseTabWidget.cpp b/src/gui/DatabaseTabWidget.cpp index ef25e90f..832512e9 100644 --- a/src/gui/DatabaseTabWidget.cpp +++ b/src/gui/DatabaseTabWidget.cpp @@ -534,12 +534,12 @@ void DatabaseTabWidget::updateTabName(Database* db) if (db->metadata()->name().isEmpty()) { tabName = tr("New database"); } else { - tabName = QString("%1 [%2]").arg(db->metadata()->name(), tr("New database")); + tabName = tr("%1 [New database]", "tab modifier").arg(db->metadata()->name()); } } if (dbStruct.dbWidget->currentMode() == DatabaseWidget::LockedMode) { - tabName.append(QString(" [%1]").arg(tr("locked"))); + tabName = tr("%1 [locked]", "tab modifier").arg(tabName); } if (dbStruct.modified) { diff --git a/src/gui/DetailsWidget.cpp b/src/gui/DetailsWidget.cpp index 77de2466..fcf8ecb5 100644 --- a/src/gui/DetailsWidget.cpp +++ b/src/gui/DetailsWidget.cpp @@ -216,7 +216,7 @@ void DetailsWidget::updateEntryAttributesTab() if (m_currentEntry->attributes()->isProtected(key)) { value = "" + tr("[PROTECTED]") + ""; } - attributesText.append(QString("%1: %2
").arg(key, value)); + attributesText.append(tr("%1: %2", "attributes line").arg(key, value).append("
")); } m_ui->entryAttributesEdit->setText(attributesText); } diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp index 1822c48d..2e059544 100644 --- a/src/gui/MainWindow.cpp +++ b/src/gui/MainWindow.cpp @@ -673,7 +673,7 @@ void MainWindow::updateWindowTitle() customWindowTitlePart.remove(customWindowTitlePart.size() - 1, 1); } if (m_ui->tabWidget->readOnly(tabWidgetIndex)) { - customWindowTitlePart.append(QString(" [%1]").arg(tr("read-only"))); + customWindowTitlePart = tr("%1 [read-only]", "window title modifier").arg(customWindowTitlePart); } m_ui->actionDatabaseSave->setEnabled(m_ui->tabWidget->canSave(tabWidgetIndex)); } else if (stackedWidgetIndex == 1) { From 963a7802d13996bc3e1d396ce4b8172f123db2bc Mon Sep 17 00:00:00 2001 From: Edward Jones Date: Tue, 13 Mar 2018 20:03:59 +0000 Subject: [PATCH 009/267] Fix pluralization of confirmation prompts --- src/gui/DatabaseWidget.cpp | 46 +++++++++++++++++-------------------- src/gui/EditWidgetIcons.cpp | 7 +++--- 2 files changed, 25 insertions(+), 28 deletions(-) diff --git a/src/gui/DatabaseWidget.cpp b/src/gui/DatabaseWidget.cpp index 0573a018..bc8fc3f7 100644 --- a/src/gui/DatabaseWidget.cpp +++ b/src/gui/DatabaseWidget.cpp @@ -479,23 +479,21 @@ void DatabaseWidget::deleteEntries() bool inRecycleBin = Tools::hasChild(m_db->metadata()->recycleBin(), selectedEntries.first()); if (inRecycleBin || !m_db->metadata()->recycleBinEnabled()) { - QMessageBox::StandardButton result; - + QString prompt; if (selected.size() == 1) { - result = MessageBox::question( - this, tr("Delete entry?"), - tr("Do you really want to delete the entry \"%1\" for good?") - .arg(selectedEntries.first()->title().toHtmlEscaped()), - QMessageBox::Yes | QMessageBox::No); + prompt = tr("Do you really want to delete the entry \"%1\" for good?") + .arg(selectedEntries.first()->title().toHtmlEscaped()); } else { - result = MessageBox::question( - this, tr("Delete entries?"), - tr("Do you really want to delete %1 entries for good?") - .arg(selected.size()), - QMessageBox::Yes | QMessageBox::No); + prompt = tr("Do you really want to delete %n entry(s) for good?", "", selected.size()); } + QMessageBox::StandardButton result = MessageBox::question( + this, + tr("Delete entry(s)?", "", selected.size()), + prompt, + QMessageBox::Yes | QMessageBox::No); + if (result == QMessageBox::Yes) { for (Entry* entry : asConst(selectedEntries)) { delete entry; @@ -504,22 +502,20 @@ void DatabaseWidget::deleteEntries() } } else { - QMessageBox::StandardButton result; - + QString prompt; if (selected.size() == 1) { - result = MessageBox::question( - this, tr("Move entry to recycle bin?"), - tr("Do you really want to move entry \"%1\" to the recycle bin?") - .arg(selectedEntries.first()->title().toHtmlEscaped()), - QMessageBox::Yes | QMessageBox::No); - } - else { - result = MessageBox::question( - this, tr("Move entries to recycle bin?"), - tr("Do you really want to move %n entry(s) to the recycle bin?", 0, selected.size()), - QMessageBox::Yes | QMessageBox::No); + prompt = tr("Do you really want to move entry \"%1\" to the recycle bin?") + .arg(selectedEntries.first()->title().toHtmlEscaped()); + } else { + prompt = tr("Do you really want to move %n entry(s) to the recycle bin?", "", selected.size()); } + QMessageBox::StandardButton result = MessageBox::question( + this, + tr("Move entry(s) to recycle bin?", "", selected.size()), + prompt, + QMessageBox::Yes | QMessageBox::No); + if (result == QMessageBox::No) { return; } diff --git a/src/gui/EditWidgetIcons.cpp b/src/gui/EditWidgetIcons.cpp index af4476ac..a70e0dca 100644 --- a/src/gui/EditWidgetIcons.cpp +++ b/src/gui/EditWidgetIcons.cpp @@ -305,9 +305,10 @@ void EditWidgetIcons::removeCustomIcon() int iconUseCount = entriesWithSameIcon.size() + groupsWithSameIcon.size(); if (iconUseCount > 0) { QMessageBox::StandardButton ans = MessageBox::question(this, tr("Confirm Delete"), - tr("This icon is used by %1 entries, and will be replaced " - "by the default icon. Are you sure you want to delete it?") - .arg(iconUseCount), QMessageBox::Yes | QMessageBox::No); + tr("This icon is used by %n entry(s), and will be replaced " + "by the default icon. Are you sure you want to delete it?", + "", iconUseCount), + QMessageBox::Yes | QMessageBox::No); if (ans == QMessageBox::No) { // Early out, nothing is changed From 7e75d040550232ccc6ae191a0c132b9708b227f0 Mon Sep 17 00:00:00 2001 From: dinony Date: Sun, 18 Mar 2018 01:10:00 +0100 Subject: [PATCH 010/267] Docs (#1749) Update build instructions --- INSTALL.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/INSTALL.md b/INSTALL.md index 86048b50..41a948b5 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -59,15 +59,22 @@ To update the project from within the project's folder, you can run the followin git pull ``` +For a stable build, it is recommended to checkout the master branch. + +```bash +git checkout master +``` + Navigate to the directory where you have downloaded KeePassXC and type these commands: ``` cd directory-where-sources-live mkdir build cd build -cmake -DWITH_TESTS=OFF ...and other options - see below... +cmake -DWITH_XC_ALL=ON .. make ``` + These steps place the compiled KeePassXC binary inside the `./build/src/` directory. (Note the cmake notes/options below.) From 78ef6f0d04578b4bfaea35c25a92b09c607d228a Mon Sep 17 00:00:00 2001 From: Daniel Wilches Date: Sat, 10 Mar 2018 19:31:43 -0800 Subject: [PATCH 011/267] Grey out Apply button when there are no changes Resolves #1313 What this commit does: * Whenever the Apply button is pressed, and if the save was successful, then the Apply button is disabled. * Each subwidget used by EditEntryWidget has now a signal called `widgetUpdated` that is emitted when the widgets' internal content changes. The EditEntryWidget subscribes to that signal to know when to enable the Apply button (by calling `entryUpdated()`). * There are some views that are not isolated in their own widgets (`m_advancedUi`, for example) so in those cases I invoked `entryUpdated()` directly whenever I detected an update: * some updates occur directly in a Qt widget like when editing the text of a QLineItem, so in that case I connected the widget's signals directly to the `entryUpdated()` slot. * some updates occur in EditEntryWidget, so in those cases the invocation to `entryUpdated()` is made as soon as the change is detected (for example when the user has confirmed an action in a dialog). A known problem: there are some situations when the Apply button will get enabled even if there are no changes, this is because the app changes the value of a field by itself so it's considered an update (for example, clicking on the "Reveal" button changes the text shown in a text field). The solution to this can be a bit complicated: disabling temporarily the `entryUpdated()` whenever the app is going to do an action with such side-effects. So I preferred to let the Apply button get enabled in those cases. --- src/gui/EditWidget.cpp | 8 +++ src/gui/EditWidget.h | 1 + src/gui/EditWidgetIcons.cpp | 11 ++++ src/gui/EditWidgetIcons.h | 1 + src/gui/entry/EditEntryWidget.cpp | 78 +++++++++++++++++++++++- src/gui/entry/EditEntryWidget.h | 2 + src/gui/entry/EntryAttachmentsWidget.cpp | 2 + src/gui/entry/EntryAttachmentsWidget.h | 1 + 8 files changed, 102 insertions(+), 2 deletions(-) diff --git a/src/gui/EditWidget.cpp b/src/gui/EditWidget.cpp index 65c6306e..5f05a428 100644 --- a/src/gui/EditWidget.cpp +++ b/src/gui/EditWidget.cpp @@ -117,6 +117,14 @@ bool EditWidget::readOnly() const return m_readOnly; } +void EditWidget::enableApplyButton(bool enabled) +{ + QPushButton* applyButton = m_ui->buttonBox->button(QDialogButtonBox::Apply); + if (applyButton) { + applyButton->setEnabled(enabled); + } +} + void EditWidget::showMessage(const QString& text, MessageWidget::MessageType type) { m_ui->messageWidget->setCloseButtonVisible(false); diff --git a/src/gui/EditWidget.h b/src/gui/EditWidget.h index 442365b9..38179a77 100644 --- a/src/gui/EditWidget.h +++ b/src/gui/EditWidget.h @@ -47,6 +47,7 @@ public: QLabel* headlineLabel(); void setReadOnly(bool readOnly); bool readOnly() const; + void enableApplyButton(bool enabled); signals: void apply(); diff --git a/src/gui/EditWidgetIcons.cpp b/src/gui/EditWidgetIcons.cpp index a70e0dca..e02ad952 100644 --- a/src/gui/EditWidgetIcons.cpp +++ b/src/gui/EditWidgetIcons.cpp @@ -66,6 +66,13 @@ EditWidgetIcons::EditWidgetIcons(QWidget* parent) connect(m_ui->deleteButton, SIGNAL(clicked()), SLOT(removeCustomIcon())); connect(m_ui->faviconButton, SIGNAL(clicked()), SLOT(downloadFavicon())); + connect(m_ui->defaultIconsRadio, SIGNAL(toggled(bool)), this, SIGNAL(widgetUpdated())); + connect(m_ui->defaultIconsRadio, SIGNAL(toggled(bool)), this, SIGNAL(widgetUpdated())); + connect(m_ui->defaultIconsView->selectionModel(), SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)), + this, SIGNAL(widgetUpdated())); + connect(m_ui->customIconsView->selectionModel(), SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)), + this, SIGNAL(widgetUpdated())); + m_ui->faviconButton->setVisible(false); } @@ -268,6 +275,8 @@ void EditWidgetIcons::addCustomIcon(const QImage& icon) updateRadioButtonCustomIcons(); QModelIndex index = m_customIconModel->indexFromUuid(uuid); m_ui->customIconsView->setCurrentIndex(index); + + emit widgetUpdated(); } } @@ -347,6 +356,8 @@ void EditWidgetIcons::removeCustomIcon() } else { m_ui->defaultIconsView->setCurrentIndex(m_defaultIconModel->index(Group::DefaultIconNumber)); } + + emit widgetUpdated(); } } } diff --git a/src/gui/EditWidgetIcons.h b/src/gui/EditWidgetIcons.h index 7b5edf80..0f875a8a 100644 --- a/src/gui/EditWidgetIcons.h +++ b/src/gui/EditWidgetIcons.h @@ -62,6 +62,7 @@ public slots: signals: void messageEditEntry(QString, MessageWidget::MessageType); void messageEditEntryDismiss(); + void widgetUpdated(); private slots: void downloadFavicon(); diff --git a/src/gui/entry/EditEntryWidget.cpp b/src/gui/entry/EditEntryWidget.cpp index 95ce7ee6..b29012e8 100644 --- a/src/gui/entry/EditEntryWidget.cpp +++ b/src/gui/entry/EditEntryWidget.cpp @@ -95,6 +95,7 @@ EditEntryWidget::EditEntryWidget(QWidget* parent) #endif setupProperties(); setupHistory(); + setupEntryUpdate(); connect(this, SIGNAL(accepted()), SLOT(acceptEntry())); connect(this, SIGNAL(rejected()), SLOT(cancel())); @@ -227,6 +228,59 @@ void EditEntryWidget::setupHistory() connect(m_historyUi->deleteAllButton, SIGNAL(clicked()), SLOT(deleteAllHistoryEntries())); } +void EditEntryWidget::setupEntryUpdate() +{ + // Entry tab + connect(m_mainUi->titleEdit, SIGNAL(textChanged(const QString&)), this, SLOT(setUnsavedChanges())); + connect(m_mainUi->usernameEdit, SIGNAL(textChanged(const QString&)), this, SLOT(setUnsavedChanges())); + connect(m_mainUi->passwordEdit, SIGNAL(textChanged(const QString&)), this, SLOT(setUnsavedChanges())); + connect(m_mainUi->passwordRepeatEdit, SIGNAL(textChanged(const QString&)), this, SLOT(setUnsavedChanges())); + connect(m_mainUi->urlEdit, SIGNAL(textChanged(const QString&)), this, SLOT(setUnsavedChanges())); + connect(m_mainUi->expireCheck, SIGNAL(stateChanged(int)), this, SLOT(setUnsavedChanges())); + connect(m_mainUi->notesEnabled, SIGNAL(stateChanged(int)), this, SLOT(setUnsavedChanges())); + connect(m_mainUi->expireDatePicker, SIGNAL(dateTimeChanged(const QDateTime&)), this, SLOT(setUnsavedChanges())); + connect(m_mainUi->notesEdit, SIGNAL(textChanged()), this, SLOT(setUnsavedChanges())); + + // Advanced tab + connect(m_advancedUi->attributesEdit, SIGNAL(textChanged()), this, SLOT(setUnsavedChanges())); + connect(m_advancedUi->protectAttributeButton, SIGNAL(stateChanged(int)), this, SLOT(setUnsavedChanges())); + connect(m_advancedUi->fgColorCheckBox, SIGNAL(stateChanged(int)), this, SLOT(setUnsavedChanges())); + connect(m_advancedUi->bgColorCheckBox, SIGNAL(stateChanged(int)), this, SLOT(setUnsavedChanges())); + connect(m_advancedUi->attachmentsWidget, SIGNAL(widgetUpdated()), this, SLOT(setUnsavedChanges())); + + // Icon tab + connect(m_iconsWidget, SIGNAL(widgetUpdated()), this, SLOT(setUnsavedChanges())); + + // Auto-Type tab + connect(m_autoTypeUi->enableButton, SIGNAL(stateChanged(int)), this, SLOT(setUnsavedChanges())); + connect(m_autoTypeUi->customWindowSequenceButton, SIGNAL(stateChanged(int)), this, SLOT(setUnsavedChanges())); + connect(m_autoTypeUi->inheritSequenceButton, SIGNAL(toggled(bool)), this, SLOT(setUnsavedChanges())); + connect(m_autoTypeUi->customSequenceButton, SIGNAL(toggled(bool)), this, SLOT(setUnsavedChanges())); + connect(m_autoTypeUi->windowSequenceEdit, SIGNAL(textChanged(const QString&)), this, SLOT(setUnsavedChanges())); + connect(m_autoTypeUi->sequenceEdit, SIGNAL(textChanged(const QString&)), this, SLOT(setUnsavedChanges())); + connect(m_autoTypeUi->windowTitleCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(setUnsavedChanges())); + connect(m_autoTypeUi->windowTitleCombo, SIGNAL(editTextChanged(const QString&)), this, SLOT(setUnsavedChanges())); + + // Properties and History tabs don't need extra connections + +#ifdef WITH_XC_SSHAGENT + // SSH Agent tab + if (config()->get("SSHAgent", false).toBool()) { + connect(m_sshAgentUi->attachmentRadioButton, SIGNAL(toggled(bool)), this, SLOT(setUnsavedChanges())); + connect(m_sshAgentUi->externalFileRadioButton, SIGNAL(toggled(bool)), this, SLOT(setUnsavedChanges())); + connect(m_sshAgentUi->attachmentComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(setUnsavedChanges())); + connect(m_sshAgentUi->attachmentComboBox, SIGNAL(editTextChanged(const QString&)), this, SLOT(setUnsavedChanges())); + connect(m_sshAgentUi->externalFileEdit, SIGNAL(textChanged(const QString&)), this, SLOT(setUnsavedChanges())); + connect(m_sshAgentUi->publicKeyEdit, SIGNAL(textChanged()), this, SLOT(setUnsavedChanges())); + connect(m_sshAgentUi->addKeyToAgentCheckBox, SIGNAL(stateChanged(int)), this, SLOT(setUnsavedChanges())); + connect(m_sshAgentUi->removeKeyFromAgentCheckBox, SIGNAL(stateChanged(int)), this, SLOT(setUnsavedChanges())); + connect(m_sshAgentUi->requireUserConfirmationCheckBox, SIGNAL(stateChanged(int)), this, SLOT(setUnsavedChanges())); + connect(m_sshAgentUi->lifetimeCheckBox, SIGNAL(stateChanged(int)), this, SLOT(setUnsavedChanges())); + connect(m_sshAgentUi->lifetimeSpinBox, SIGNAL(valueChanged(int)), this, SLOT(setUnsavedChanges())); + } +#endif +} + void EditEntryWidget::emitHistoryEntryActivated(const QModelIndex& index) { Q_ASSERT(!m_history); @@ -581,7 +635,6 @@ void EditEntryWidget::loadEntry(Entry* entry, bool create, bool history, const Q m_database = database; m_create = create; m_history = history; - m_saved = false; if (history) { setHeadline(QString("%1 > %2").arg(parentName, tr("Entry history"))); @@ -601,6 +654,9 @@ void EditEntryWidget::loadEntry(Entry* entry, bool create, bool history, const Q setCurrentPage(0); setPageHidden(m_historyWidget, m_history || m_entry->historyItems().count() < 1); + + // Force the user to Save/Apply/Discard new entries + setUnsavedChanges(m_create); } void EditEntryWidget::setForms(const Entry* entry, bool restore) @@ -780,7 +836,7 @@ bool EditEntryWidget::commitEntry() } updateEntryData(m_entry); - m_saved = true; + setUnsavedChanges(false); if (!m_create) { m_entry->endUpdate(); @@ -940,6 +996,8 @@ void EditEntryWidget::insertAttribute() m_advancedUi->attributesView->setCurrentIndex(index); m_advancedUi->attributesView->edit(index); + + setUnsavedChanges(true); } void EditEntryWidget::editCurrentAttribute() @@ -950,6 +1008,7 @@ void EditEntryWidget::editCurrentAttribute() if (index.isValid()) { m_advancedUi->attributesView->edit(index); + setUnsavedChanges(true); } } @@ -963,6 +1022,7 @@ void EditEntryWidget::removeCurrentAttribute() if (MessageBox::question(this, tr("Confirm Remove"), tr("Are you sure you want to remove this attribute?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) { m_entryAttributes->remove(m_attributesModel->keyByIndex(index)); + setUnsavedChanges(true); } } } @@ -1047,9 +1107,11 @@ void EditEntryWidget::revealCurrentAttribute() if (! m_advancedUi->attributesEdit->isEnabled()) { QModelIndex index = m_advancedUi->attributesView->currentIndex(); if (index.isValid()) { + bool oldBlockSignals = m_advancedUi->attributesEdit->blockSignals(true); QString key = m_attributesModel->keyByIndex(index); m_advancedUi->attributesEdit->setPlainText(m_entryAttributes->value(key)); m_advancedUi->attributesEdit->setEnabled(true); + m_advancedUi->attributesEdit->blockSignals(oldBlockSignals); } } } @@ -1083,6 +1145,7 @@ void EditEntryWidget::insertAutoTypeAssoc() m_autoTypeUi->assocView->setCurrentIndex(newIndex); loadCurrentAssoc(newIndex); m_autoTypeUi->windowTitleCombo->setFocus(); + setUnsavedChanges(true); } void EditEntryWidget::removeAutoTypeAssoc() @@ -1091,6 +1154,7 @@ void EditEntryWidget::removeAutoTypeAssoc() if (currentIndex.isValid()) { m_autoTypeAssoc->remove(currentIndex.row()); + setUnsavedChanges(true); } } @@ -1153,6 +1217,7 @@ void EditEntryWidget::restoreHistoryEntry() QModelIndex index = m_sortModel->mapToSource(m_historyUi->historyView->currentIndex()); if (index.isValid()) { setForms(m_historyModel->entryFromIndex(index), true); + setUnsavedChanges(true); } } @@ -1166,6 +1231,7 @@ void EditEntryWidget::deleteHistoryEntry() } else { m_historyUi->deleteAllButton->setEnabled(false); } + setUnsavedChanges(true); } } @@ -1178,6 +1244,7 @@ void EditEntryWidget::deleteAllHistoryEntries() else { m_historyUi->deleteAllButton->setEnabled(false); } + setUnsavedChanges(true); } QMenu* EditEntryWidget::createPresetsMenu() @@ -1229,5 +1296,12 @@ void EditEntryWidget::pickColor() QColor newColor = colorDialog.getColor(oldColor); if (newColor.isValid()) { setupColorButton(isForeground, newColor); + setUnsavedChanges(true); } } + +void EditEntryWidget::setUnsavedChanges(bool hasUnsaved) +{ + m_saved = !hasUnsaved; + enableApplyButton(hasUnsaved); +} diff --git a/src/gui/entry/EditEntryWidget.h b/src/gui/entry/EditEntryWidget.h index 9b2a919c..863d6505 100644 --- a/src/gui/entry/EditEntryWidget.h +++ b/src/gui/entry/EditEntryWidget.h @@ -100,6 +100,7 @@ private slots: void useExpiryPreset(QAction* action); void toggleHideNotes(bool visible); void pickColor(); + void setUnsavedChanges(bool hasUnsaved = true); #ifdef WITH_XC_SSHAGENT void updateSSHAgent(); void updateSSHAgentAttachment(); @@ -122,6 +123,7 @@ private: #endif void setupProperties(); void setupHistory(); + void setupEntryUpdate(); void setupColorButton(bool foreground, const QColor& color); bool passwordsEqual(); diff --git a/src/gui/entry/EntryAttachmentsWidget.cpp b/src/gui/entry/EntryAttachmentsWidget.cpp index 78b6d741..d420d9d6 100644 --- a/src/gui/entry/EntryAttachmentsWidget.cpp +++ b/src/gui/entry/EntryAttachmentsWidget.cpp @@ -147,6 +147,7 @@ void EntryAttachmentsWidget::insertAttachments() if (!insertAttachments(filenames, errorMessage)) { errorOccurred(errorMessage); } + emit widgetUpdated(); } void EntryAttachmentsWidget::removeSelectedAttachments() @@ -170,6 +171,7 @@ void EntryAttachmentsWidget::removeSelectedAttachments() keys.append(m_attachmentsModel->keyByIndex(index)); } m_entryAttachments->remove(keys); + emit widgetUpdated(); } } diff --git a/src/gui/entry/EntryAttachmentsWidget.h b/src/gui/entry/EntryAttachmentsWidget.h index 5fd19415..590060ae 100644 --- a/src/gui/entry/EntryAttachmentsWidget.h +++ b/src/gui/entry/EntryAttachmentsWidget.h @@ -39,6 +39,7 @@ signals: void errorOccurred(const QString& error); void readOnlyChanged(bool readOnly); void buttonsVisibleChanged(bool isButtonsVisible); + void widgetUpdated(); private slots: void insertAttachments(); From 240939ce3b83267cbb0e203b32ead6d45d0919a4 Mon Sep 17 00:00:00 2001 From: Daniel Wilches Date: Sat, 17 Mar 2018 14:31:15 -0700 Subject: [PATCH 012/267] Request confirmation to discard unsaved changes Solves #1181 --- src/gui/entry/EditEntryWidget.cpp | 13 +++++++++++++ tests/gui/TestGui.cpp | 1 + 2 files changed, 14 insertions(+) diff --git a/src/gui/entry/EditEntryWidget.cpp b/src/gui/entry/EditEntryWidget.cpp index b29012e8..8163a648 100644 --- a/src/gui/entry/EditEntryWidget.cpp +++ b/src/gui/entry/EditEntryWidget.cpp @@ -927,6 +927,19 @@ void EditEntryWidget::cancel() m_entry->setIcon(Entry::DefaultIconNumber); } + if (!m_saved) { + auto result = MessageBox::question(this, QString(), tr("Entry has unsaved changes"), + QMessageBox::Cancel | QMessageBox::Save | QMessageBox::Discard, + QMessageBox::Cancel); + if (result == QMessageBox::Cancel) { + return; + } + if (result == QMessageBox::Save) { + commitEntry(); + m_saved = true; + } + } + clear(); emit editFinished(m_saved); diff --git a/tests/gui/TestGui.cpp b/tests/gui/TestGui.cpp index 54203c28..c736ea48 100644 --- a/tests/gui/TestGui.cpp +++ b/tests/gui/TestGui.cpp @@ -492,6 +492,7 @@ void TestGui::testAddEntry() // Add entry "something 5" but click cancel button (does NOT add entry) QTest::mouseClick(entryNewWidget, Qt::LeftButton); QTest::keyClicks(titleEdit, "something 5"); + MessageBox::setNextAnswer(QMessageBox::Discard); QTest::mouseClick(editEntryWidgetButtonBox->button(QDialogButtonBox::Cancel), Qt::LeftButton); QApplication::processEvents(); From 410d88bf9944dfe1e79c6f7d8f747c32a8924e3f Mon Sep 17 00:00:00 2001 From: Jonathan White Date: Sat, 31 Mar 2018 11:36:18 -0400 Subject: [PATCH 013/267] Remove KeePassHttp plugin and qhttp (#1752) Remove KeePassHttp plugin and qhttp --- CMakeLists.txt | 8 - COPYING | 4 - INSTALL.md | 6 +- docs/QUICKSTART.md | 5 +- src/CMakeLists.txt | 3 - src/config-keepassx.h.cmake | 1 - src/gui/AboutDialog.cpp | 3 - src/gui/MainWindow.cpp | 79 - src/gui/MainWindow.h | 1 - src/http/AccessControlDialog.cpp | 61 - src/http/AccessControlDialog.h | 48 - src/http/AccessControlDialog.ui | 69 - src/http/CMakeLists.txt | 21 - src/http/EntryConfig.cpp | 107 - src/http/EntryConfig.h | 59 - src/http/HttpPasswordGeneratorWidget.cpp | 152 - src/http/HttpPasswordGeneratorWidget.h | 58 - src/http/HttpPasswordGeneratorWidget.ui | 220 -- src/http/HttpSettings.cpp | 270 -- src/http/HttpSettings.h | 78 - src/http/OptionDialog.cpp | 102 - src/http/OptionDialog.h | 49 - src/http/OptionDialog.ui | 301 -- src/http/Protocol.cpp | 557 ---- src/http/Protocol.h | 212 -- src/http/Server.cpp | 236 -- src/http/Server.h | 84 - src/http/Service.cpp | 603 ---- src/http/Service.h | 66 - src/http/qhttp/CMakeLists.txt | 18 - src/http/qhttp/LICENSE | 22 - src/http/qhttp/README.md | 229 -- src/http/qhttp/http-parser/LICENSE-MIT | 23 - src/http/qhttp/http-parser/README.md | 246 -- src/http/qhttp/http-parser/http_parser.c | 2476 ----------------- src/http/qhttp/http-parser/http_parser.h | 432 --- src/http/qhttp/private/httpparser.hxx | 119 - src/http/qhttp/private/httpreader.hxx | 78 - src/http/qhttp/private/httpwriter.hxx | 112 - src/http/qhttp/private/qhttpbase.hpp | 52 - .../qhttp/private/qhttpclient_private.hpp | 222 -- .../private/qhttpclientrequest_private.hpp | 57 - .../private/qhttpclientresponse_private.hpp | 51 - .../qhttp/private/qhttpserver_private.hpp | 90 - .../private/qhttpserverconnection_private.hpp | 201 -- .../private/qhttpserverrequest_private.hpp | 51 - .../private/qhttpserverresponse_private.hpp | 62 - src/http/qhttp/private/qsocket.hpp | 131 - src/http/qhttp/qhttpabstracts.cpp | 114 - src/http/qhttp/qhttpabstracts.hpp | 190 -- src/http/qhttp/qhttpclient.cpp | 286 -- src/http/qhttp/qhttpclient.hpp | 179 -- src/http/qhttp/qhttpclientrequest.cpp | 97 - src/http/qhttp/qhttpclientrequest.hpp | 63 - src/http/qhttp/qhttpclientresponse.cpp | 66 - src/http/qhttp/qhttpclientresponse.hpp | 73 - src/http/qhttp/qhttpfwd.hpp | 216 -- src/http/qhttp/qhttpserver.cpp | 118 - src/http/qhttp/qhttpserver.hpp | 131 - src/http/qhttp/qhttpserverconnection.cpp | 217 -- src/http/qhttp/qhttpserverconnection.hpp | 87 - src/http/qhttp/qhttpserverrequest.cpp | 81 - src/http/qhttp/qhttpserverrequest.hpp | 82 - src/http/qhttp/qhttpserverresponse.cpp | 90 - src/http/qhttp/qhttpserverresponse.hpp | 70 - tests/config-keepassx-tests.h.cmake | 1 - 66 files changed, 7 insertions(+), 10289 deletions(-) delete mode 100644 src/http/AccessControlDialog.cpp delete mode 100644 src/http/AccessControlDialog.h delete mode 100644 src/http/AccessControlDialog.ui delete mode 100644 src/http/CMakeLists.txt delete mode 100644 src/http/EntryConfig.cpp delete mode 100644 src/http/EntryConfig.h delete mode 100644 src/http/HttpPasswordGeneratorWidget.cpp delete mode 100644 src/http/HttpPasswordGeneratorWidget.h delete mode 100644 src/http/HttpPasswordGeneratorWidget.ui delete mode 100644 src/http/HttpSettings.cpp delete mode 100644 src/http/HttpSettings.h delete mode 100644 src/http/OptionDialog.cpp delete mode 100644 src/http/OptionDialog.h delete mode 100644 src/http/OptionDialog.ui delete mode 100644 src/http/Protocol.cpp delete mode 100644 src/http/Protocol.h delete mode 100644 src/http/Server.cpp delete mode 100644 src/http/Server.h delete mode 100644 src/http/Service.cpp delete mode 100644 src/http/Service.h delete mode 100644 src/http/qhttp/CMakeLists.txt delete mode 100644 src/http/qhttp/LICENSE delete mode 100644 src/http/qhttp/README.md delete mode 100644 src/http/qhttp/http-parser/LICENSE-MIT delete mode 100644 src/http/qhttp/http-parser/README.md delete mode 100644 src/http/qhttp/http-parser/http_parser.c delete mode 100644 src/http/qhttp/http-parser/http_parser.h delete mode 100644 src/http/qhttp/private/httpparser.hxx delete mode 100644 src/http/qhttp/private/httpreader.hxx delete mode 100644 src/http/qhttp/private/httpwriter.hxx delete mode 100644 src/http/qhttp/private/qhttpbase.hpp delete mode 100644 src/http/qhttp/private/qhttpclient_private.hpp delete mode 100644 src/http/qhttp/private/qhttpclientrequest_private.hpp delete mode 100644 src/http/qhttp/private/qhttpclientresponse_private.hpp delete mode 100644 src/http/qhttp/private/qhttpserver_private.hpp delete mode 100644 src/http/qhttp/private/qhttpserverconnection_private.hpp delete mode 100644 src/http/qhttp/private/qhttpserverrequest_private.hpp delete mode 100644 src/http/qhttp/private/qhttpserverresponse_private.hpp delete mode 100644 src/http/qhttp/private/qsocket.hpp delete mode 100644 src/http/qhttp/qhttpabstracts.cpp delete mode 100644 src/http/qhttp/qhttpabstracts.hpp delete mode 100644 src/http/qhttp/qhttpclient.cpp delete mode 100644 src/http/qhttp/qhttpclient.hpp delete mode 100644 src/http/qhttp/qhttpclientrequest.cpp delete mode 100644 src/http/qhttp/qhttpclientrequest.hpp delete mode 100644 src/http/qhttp/qhttpclientresponse.cpp delete mode 100644 src/http/qhttp/qhttpclientresponse.hpp delete mode 100644 src/http/qhttp/qhttpfwd.hpp delete mode 100644 src/http/qhttp/qhttpserver.cpp delete mode 100644 src/http/qhttp/qhttpserver.hpp delete mode 100644 src/http/qhttp/qhttpserverconnection.cpp delete mode 100644 src/http/qhttp/qhttpserverconnection.hpp delete mode 100644 src/http/qhttp/qhttpserverrequest.cpp delete mode 100644 src/http/qhttp/qhttpserverrequest.hpp delete mode 100644 src/http/qhttp/qhttpserverresponse.cpp delete mode 100644 src/http/qhttp/qhttpserverresponse.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index a4593356..188873b9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -45,22 +45,14 @@ set(WITH_XC_ALL OFF CACHE BOOLEAN "Build in all available plugins") option(WITH_XC_AUTOTYPE "Include Auto-Type." ON) option(WITH_XC_NETWORKING "Include networking code (e.g. for downlading website icons)." OFF) option(WITH_XC_BROWSER "Include browser integration with keepassxc-browser." OFF) -option(WITH_XC_HTTP "Include KeePassHTTP-compatible browser integration (deprecated, implies WITH_NETWORKING)." OFF) option(WITH_XC_YUBIKEY "Include YubiKey support." OFF) option(WITH_XC_SSHAGENT "Include SSH agent support." OFF) -if(WITH_XC_HTTP) - message(WARNING "KeePassHTTP support has been deprecated and will be removed in a future version. Please use WITH_XC_BROWSER instead!\n" - "For enabling / disabling network access code, WITH_XC_HTTP has been replaced by WITH_XC_NETWORKING.") - set(WITH_XC_NETWORKING ON CACHE BOOL "Include networking code (e.g. for downlading website icons)." FORCE) -endif() - if(WITH_XC_ALL) # Enable all options set(WITH_XC_AUTOTYPE ON) set(WITH_XC_NETWORKING ON) set(WITH_XC_BROWSER ON) - set(WITH_XC_HTTP ON) # Deprecated set(WITH_XC_YUBIKEY ON) set(WITH_XC_SSHAGENT ON) endif() diff --git a/COPYING b/COPYING index 19565055..8095ef06 100644 --- a/COPYING +++ b/COPYING @@ -226,10 +226,6 @@ Files: src/zxcvbn/zxcvbn.* Copyright: 2015-2017, Tony Evans License: MIT -Files: src/http/qhttp/* -Copyright: 2014, Amir Zamani -License: MIT - Files: src/gui/KMessageWidget.h src/gui/KMessageWidget.cpp Copyright: 2011 Aurélien Gâteau diff --git a/INSTALL.md b/INSTALL.md index 41a948b5..1a23397d 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -93,10 +93,12 @@ These steps place the compiled KeePassXC binary inside the `./build/src/` direct ``` -DWITH_XC_AUTOTYPE=[ON|OFF] Enable/Disable Auto-Type (default: ON) - -DWITH_XC_HTTP=[ON|OFF] Enable/Disable KeePassHTTP and custom icon downloads (default: OFF) -DWITH_XC_YUBIKEY=[ON|OFF] Enable/Disable YubiKey HMAC-SHA1 authentication support (default: OFF) -DWITH_XC_BROWSER=[ON|OFF] Enable/Disable KeePassXC-Browser extension support (default: OFF) - + -DWITH_XC_NETWORKING=[ON|OFF] Enable/Disable Networking support (favicon download) (default: OFF) + + -DWITH_XC_ALL=[ON|OFF] Enable/Disable compiling all plugins above (default: OFF) + -DWITH_TESTS=[ON|OFF] Enable/Disable building of unit tests (default: ON) -DWITH_GUI_TESTS=[ON|OFF] Enable/Disable building of GUI tests (default: OFF) -DWITH_DEV_BUILD=[ON|OFF] Enable/Disable deprecated method warnings (default: OFF) diff --git a/docs/QUICKSTART.md b/docs/QUICKSTART.md index b4b2d38c..8b694888 100644 --- a/docs/QUICKSTART.md +++ b/docs/QUICKSTART.md @@ -24,9 +24,10 @@ for all your websites, programs, etc. ## Setting up Browser Integration with KeePassXC * *Within KeePassXC*, go to **Tools->Settings** (on macOS, go to **KeePassXC->Preferences**.) -* In **Browser Integration**, check **Enable KeePassHTTP server** +* In **Browser Integration**, check **Enable KeePassXC browser integration** +* Right below that, click the checkbox for the browser(s) you use Leave the other options at their defaults. -* *In your default web browser,* install the KeePassHTTP-Connector extension/add-on. Instructions for [Firefox](https://addons.mozilla.org/en-US/firefox/addon/keepasshttp-connector/?src=api) or [Chrome](https://chrome.google.com/webstore/detail/keepasshttp-connector/dafgdjggglmmknipkhngniifhplpcldb?utm_source=chrome-app-launcher-info-dialog) +* *In your default web browser,* install the KeePassXC Browser extension/add-on. Instructions for [Firefox](https://addons.mozilla.org/en-US/firefox/addon/keepassxc-browser/) or [Chrome](https://chrome.google.com/webstore/detail/keepassxc-browser/oboonakemofpalcgghocfoadofidjkkk) * Click the KeePassXC icon in the upper-right corner. You'll see the dialog below. * Click the blue Connect button to make the browser extension connect to the KeePassXC application. KeePassXC Connect dialog diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b3c7a650..747848c5 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -197,11 +197,9 @@ set(keepassx_SOURCES_MAINEXE add_feature_info(Auto-Type WITH_XC_AUTOTYPE "Automatic password typing") add_feature_info(Networking WITH_XC_NETWORKING "Compile KeePassXC with network access code (e.g. for downloading website icons)") add_feature_info(KeePassXC-Browser WITH_XC_BROWSER "Browser integration with KeePassXC-Browser") -add_feature_info(KeePassHTTP WITH_XC_HTTP "Browser integration compatible with ChromeIPass and PassIFox (deprecated, implies Networking)") add_feature_info(SSHAgent WITH_XC_SSHAGENT "SSH agent integration compatible with KeeAgent") add_feature_info(YubiKey WITH_XC_YUBIKEY "YubiKey HMAC-SHA1 challenge-response") -add_subdirectory(http) if(WITH_XC_NETWORKING) find_package(CURL REQUIRED) endif() @@ -254,7 +252,6 @@ add_library(keepassx_core STATIC ${keepassx_SOURCES}) set_target_properties(keepassx_core PROPERTIES COMPILE_DEFINITIONS KEEPASSX_BUILDING_CORE) target_link_libraries(keepassx_core autotype - ${keepassxchttp_LIB} ${keepassxcbrowser_LIB} ${sshagent_LIB} Qt5::Core diff --git a/src/config-keepassx.h.cmake b/src/config-keepassx.h.cmake index 9f3952b0..8bbea9ea 100644 --- a/src/config-keepassx.h.cmake +++ b/src/config-keepassx.h.cmake @@ -15,7 +15,6 @@ #cmakedefine WITH_XC_AUTOTYPE #cmakedefine WITH_XC_NETWORKING #cmakedefine WITH_XC_BROWSER -#cmakedefine WITH_XC_HTTP #cmakedefine WITH_XC_YUBIKEY #cmakedefine WITH_XC_SSHAGENT diff --git a/src/gui/AboutDialog.cpp b/src/gui/AboutDialog.cpp index 10f42cd7..73d8ec55 100644 --- a/src/gui/AboutDialog.cpp +++ b/src/gui/AboutDialog.cpp @@ -87,9 +87,6 @@ AboutDialog::AboutDialog(QWidget* parent) #ifdef WITH_XC_BROWSER extensions += "\n- " + tr("Browser Integration"); #endif -#ifdef WITH_XC_HTTP - extensions += "\n- " + tr("Legacy Browser Integration (KeePassHTTP)"); -#endif #ifdef WITH_XC_SSHAGENT extensions += "\n- " + tr("SSH Agent"); #endif diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp index 1465cf87..8549d8f8 100644 --- a/src/gui/MainWindow.cpp +++ b/src/gui/MainWindow.cpp @@ -39,12 +39,6 @@ #include "gui/MessageBox.h" #include "gui/SearchWidget.h" -#ifdef WITH_XC_HTTP -#include "http/Service.h" -#include "http/HttpSettings.h" -#include "http/OptionDialog.h" -#endif - #ifdef WITH_XC_SSHAGENT #include "sshagent/AgentSettingsPage.h" #include "sshagent/SSHAgent.h" @@ -65,53 +59,6 @@ #include "gui/SettingsWidget.h" #include "gui/PasswordGeneratorWidget.h" -#ifdef WITH_XC_HTTP -class HttpPlugin: public ISettingsPage -{ -public: - HttpPlugin(DatabaseTabWidget* tabWidget) - { - m_service = new Service(tabWidget); - } - - ~HttpPlugin() = default; - - QString name() override - { - return QObject::tr("Legacy Browser Integration"); - } - - QIcon icon() override - { - return FilePath::instance()->icon("apps", "internet-web-browser"); - } - - QWidget * createWidget() override - { - OptionDialog* dlg = new OptionDialog(); - QObject::connect(dlg, SIGNAL(removeSharedEncryptionKeys()), m_service, SLOT(removeSharedEncryptionKeys())); - QObject::connect(dlg, SIGNAL(removeStoredPermissions()), m_service, SLOT(removeStoredPermissions())); - return dlg; - } - - void loadSettings(QWidget* widget) override - { - qobject_cast(widget)->loadSettings(); - } - - void saveSettings(QWidget* widget) override - { - qobject_cast(widget)->saveSettings(); - if (HttpSettings::isEnabled()) - m_service->start(); - else - m_service->stop(); - } -private: - Service* m_service; -}; -#endif - #ifdef WITH_XC_BROWSER class BrowserPlugin: public ISettingsPage { @@ -193,9 +140,6 @@ MainWindow::MainWindow() #ifdef WITH_XC_BROWSER m_ui->settingsWidget->addSettingsPage(new BrowserPlugin(m_ui->tabWidget)); #endif -#ifdef WITH_XC_HTTP - m_ui->settingsWidget->addSettingsPage(new HttpPlugin(m_ui->tabWidget)); -#endif #ifdef WITH_XC_SSHAGENT SSHAgent::init(this); connect(SSHAgent::instance(), SIGNAL(error(QString)), this, SLOT(showErrorMessage(QString))); @@ -419,21 +363,12 @@ MainWindow::MainWindow() m_ui->globalMessageWidget->showMessage( tr("Access error for config file %1").arg(config()->getFileName()), MessageWidget::Error); } -#ifdef WITH_XC_HTTP - if (config()->get("Http/Enabled", false).toBool() && config()->get("Http/DeprecationNoticeShown", 0).toInt() < 3) { - // show message after global widget dismissed all messages - connect(m_ui->globalMessageWidget, SIGNAL(hideAnimationFinished()), this, SLOT(showKeePassHTTPDeprecationNotice())); - } -#endif #ifndef KEEPASSXC_BUILD_TYPE_RELEASE m_ui->globalMessageWidget->showMessage(tr("WARNING: You are using an unstable build of KeePassXC!\n" "There is a high risk of corruption, maintain a backup of your databases.\n" "This version is not meant for production use."), MessageWidget::Warning, -1); -#else - // Show the HTTP deprecation message if enabled above - emit m_ui->globalMessageWidget->hideAnimationFinished(); #endif } @@ -441,20 +376,6 @@ MainWindow::~MainWindow() { } -void MainWindow::showKeePassHTTPDeprecationNotice() -{ - int warningNum = config()->get("Http/DeprecationNoticeShown", 0).toInt(); - displayGlobalMessage(tr("

It looks like you are using KeePassHTTP for browser integration. " - "This feature has been deprecated and will be removed in the future.
" - "Please switch to KeePassXC-Browser instead! For help with migration, " - "visit our " - "migration guide (warning %1 of 3).

").arg(warningNum + 1), - MessageWidget::Warning, true, -1); - - config()->set("Http/DeprecationNoticeShown", warningNum + 1); - disconnect(m_ui->globalMessageWidget, SIGNAL(hideAnimationFinished()), this, SLOT(showKeePassHTTPDeprecationNotice())); -} - void MainWindow::showErrorMessage(const QString& message) { m_ui->globalMessageWidget->showMessage(message, MessageWidget::Error); diff --git a/src/gui/MainWindow.h b/src/gui/MainWindow.h index 20e54891..5ce69523 100644 --- a/src/gui/MainWindow.h +++ b/src/gui/MainWindow.h @@ -103,7 +103,6 @@ private slots: void repairDatabase(); void hideTabMessage(); void handleScreenLock(); - void showKeePassHTTPDeprecationNotice(); void showErrorMessage(const QString& message); private: diff --git a/src/http/AccessControlDialog.cpp b/src/http/AccessControlDialog.cpp deleted file mode 100644 index 30ab3f21..00000000 --- a/src/http/AccessControlDialog.cpp +++ /dev/null @@ -1,61 +0,0 @@ -/* -* Copyright (C) 2013 Francois Ferrand -* Copyright (C) 2017 KeePassXC Team -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 2 or (at your option) -* version 3 of the License. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -*/ - -#include "AccessControlDialog.h" -#include "ui_AccessControlDialog.h" -#include "core/Entry.h" - -AccessControlDialog::AccessControlDialog(QWidget *parent) : - QDialog(parent), - ui(new Ui::AccessControlDialog()) -{ - this->setWindowFlags(windowFlags() | Qt::WindowStaysOnTopHint); - - ui->setupUi(this); - connect(ui->allowButton, SIGNAL(clicked()), this, SLOT(accept())); - connect(ui->denyButton, SIGNAL(clicked()), this, SLOT(reject())); -} - -AccessControlDialog::~AccessControlDialog() -{ -} - -void AccessControlDialog::setUrl(const QString &url) -{ - ui->label->setText(QString(tr("%1 has requested access to passwords for the following item(s).\n" - "Please select whether you want to allow access.")).arg(QUrl(url).host())); -} - -void AccessControlDialog::setItems(const QList &items) -{ - for (Entry* entry: items) { - QString title = entry->resolveMultiplePlaceholders(entry->title()); - QString username = entry->resolveMultiplePlaceholders(entry->username()); - ui->itemsList->addItem(title + " - " + username); - } -} - -bool AccessControlDialog::remember() const -{ - return ui->rememberDecisionCheckBox->isChecked(); -} - -void AccessControlDialog::setRemember(bool r) -{ - ui->rememberDecisionCheckBox->setChecked(r); -} diff --git a/src/http/AccessControlDialog.h b/src/http/AccessControlDialog.h deleted file mode 100644 index 76392eff..00000000 --- a/src/http/AccessControlDialog.h +++ /dev/null @@ -1,48 +0,0 @@ -/* -* Copyright (C) 2013 Francois Ferrand -* Copyright (C) 2017 KeePassXC Team -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 2 or (at your option) -* version 3 of the License. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -*/ - -#ifndef ACCESSCONTROLDIALOG_H -#define ACCESSCONTROLDIALOG_H - -#include -#include - -class Entry; - -namespace Ui { -class AccessControlDialog; -} - -class AccessControlDialog : public QDialog -{ - Q_OBJECT - -public: - explicit AccessControlDialog(QWidget *parent = nullptr); - ~AccessControlDialog(); - - void setUrl(const QString & url); - void setItems(const QList & items); - bool remember() const; - void setRemember(bool r); - -private: - QScopedPointer ui; -}; - -#endif // ACCESSCONTROLDIALOG_H diff --git a/src/http/AccessControlDialog.ui b/src/http/AccessControlDialog.ui deleted file mode 100644 index 37d477ee..00000000 --- a/src/http/AccessControlDialog.ui +++ /dev/null @@ -1,69 +0,0 @@ - - - AccessControlDialog - - - - 0 - 0 - 400 - 221 - - - - KeePassXC HTTP Confirm Access - - - - - - - - - - - - - - - - Remember this decision - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Allow - - - - - - - Deny - - - - - - - - - - diff --git a/src/http/CMakeLists.txt b/src/http/CMakeLists.txt deleted file mode 100644 index 962f78c3..00000000 --- a/src/http/CMakeLists.txt +++ /dev/null @@ -1,21 +0,0 @@ -if(WITH_XC_HTTP) - add_subdirectory(qhttp) - - include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) - - set(keepasshttp_SOURCES - AccessControlDialog.cpp - EntryConfig.cpp - HttpPasswordGeneratorWidget.cpp - HttpSettings.cpp - OptionDialog.cpp - Protocol.cpp - Server.cpp - Service.cpp - ) - - add_library(keepasshttp STATIC ${keepasshttp_SOURCES}) - target_link_libraries(keepasshttp PUBLIC qhttp Qt5::Core Qt5::Concurrent Qt5::Widgets Qt5::Network) - - set(keepassxchttp_LIB keepasshttp PARENT_SCOPE) -endif() diff --git a/src/http/EntryConfig.cpp b/src/http/EntryConfig.cpp deleted file mode 100644 index 309afafa..00000000 --- a/src/http/EntryConfig.cpp +++ /dev/null @@ -1,107 +0,0 @@ -/* -* Copyright (C) 2013 Francois Ferrand -* Copyright (C) 2017 KeePassXC Team -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 2 or (at your option) -* version 3 of the License. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -*/ - -#include "EntryConfig.h" -#include -#include "core/Entry.h" -#include "core/EntryAttributes.h" -#include "http/Protocol.h" - -static const char KEEPASSHTTP_NAME[] = "KeePassHttp Settings"; //TODO: duplicated string (also in Service.cpp) - -EntryConfig::EntryConfig(QObject *parent) : - QObject(parent) -{ -} - -QStringList EntryConfig::allowedHosts() const -{ - return m_allowedHosts.toList(); -} - -void EntryConfig::setAllowedHosts(const QStringList &allowedHosts) -{ - m_allowedHosts = allowedHosts.toSet(); -} - -QStringList EntryConfig::deniedHosts() const -{ - return m_deniedHosts.toList(); -} - -void EntryConfig::setDeniedHosts(const QStringList &deniedHosts) -{ - m_deniedHosts = deniedHosts.toSet(); -} - -bool EntryConfig::isAllowed(const QString &host) -{ - return m_allowedHosts.contains(host); -} - -void EntryConfig::allow(const QString &host) -{ - m_allowedHosts.insert(host); - m_deniedHosts.remove(host); -} - -bool EntryConfig::isDenied(const QString &host) -{ - return m_deniedHosts.contains(host); -} - -void EntryConfig::deny(const QString &host) -{ - m_deniedHosts.insert(host); - m_allowedHosts.remove(host); -} - -QString EntryConfig::realm() const -{ - return m_realm; -} - -void EntryConfig::setRealm(const QString &realm) -{ - m_realm = realm; -} - -bool EntryConfig::load(const Entry *entry) -{ - QString s = entry->attributes()->value(KEEPASSHTTP_NAME); - if (s.isEmpty()) - return false; - - QJsonDocument doc = QJsonDocument::fromJson(s.toUtf8()); - if (doc.isNull()) - return false; - - QVariantMap map = doc.object().toVariantMap(); - for(QVariantMap::iterator iter = map.begin(); iter != map.end(); ++iter) { - setProperty(iter.key().toLatin1(), iter.value()); - } - return true; -} - -void EntryConfig::save(Entry *entry) -{ - QVariantMap v = qobject2qvariant(this); - QJsonObject o = QJsonObject::fromVariantMap(v); - QByteArray json = QJsonDocument(o).toJson(QJsonDocument::Compact); - entry->attributes()->set(KEEPASSHTTP_NAME, json); -} diff --git a/src/http/EntryConfig.h b/src/http/EntryConfig.h deleted file mode 100644 index d5e9876e..00000000 --- a/src/http/EntryConfig.h +++ /dev/null @@ -1,59 +0,0 @@ -/* -* Copyright (C) 2013 Francois Ferrand -* Copyright (C) 2017 KeePassXC Team -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 2 or (at your option) -* version 3 of the License. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -*/ - -#ifndef ENTRYCONFIG_H -#define ENTRYCONFIG_H - -#include -#include -#include -#include - -class Entry; - -class EntryConfig : public QObject -{ - Q_OBJECT - Q_PROPERTY(QStringList Allow READ allowedHosts WRITE setAllowedHosts) - Q_PROPERTY(QStringList Deny READ deniedHosts WRITE setDeniedHosts ) - Q_PROPERTY(QString Realm READ realm WRITE setRealm ) - -public: - EntryConfig(QObject * object = 0); - - bool load(const Entry * entry); - void save(Entry * entry); - bool isAllowed(const QString & host); - void allow(const QString & host); - bool isDenied(const QString & host); - void deny(const QString & host); - QString realm() const; - void setRealm(const QString &realm); - -private: - QStringList allowedHosts() const; - void setAllowedHosts(const QStringList &allowedHosts); - QStringList deniedHosts() const; - void setDeniedHosts(const QStringList &deniedHosts); - - QSet m_allowedHosts; - QSet m_deniedHosts; - QString m_realm; -}; - -#endif // ENTRYCONFIG_H diff --git a/src/http/HttpPasswordGeneratorWidget.cpp b/src/http/HttpPasswordGeneratorWidget.cpp deleted file mode 100644 index f08bc3d3..00000000 --- a/src/http/HttpPasswordGeneratorWidget.cpp +++ /dev/null @@ -1,152 +0,0 @@ -/* -* Copyright (C) 2013 Francois Ferrand -* Copyright (C) 2017 KeePassXC Team -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 2 or (at your option) -* version 3 of the License. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -*/ - -#include "HttpPasswordGeneratorWidget.h" -#include "ui_HttpPasswordGeneratorWidget.h" - -#include - -#include "core/Config.h" -#include "core/PasswordGenerator.h" -#include "core/FilePath.h" - -HttpPasswordGeneratorWidget::HttpPasswordGeneratorWidget(QWidget* parent) - : QWidget(parent) - , m_updatingSpinBox(false) - , m_generator(new PasswordGenerator()) - , m_ui(new Ui::HttpPasswordGeneratorWidget()) -{ - m_ui->setupUi(this); - - connect(m_ui->sliderLength, SIGNAL(valueChanged(int)), SLOT(sliderMoved())); - connect(m_ui->spinBoxLength, SIGNAL(valueChanged(int)), SLOT(spinBoxChanged())); - - connect(m_ui->optionButtons, SIGNAL(buttonClicked(int)), SLOT(updateGenerator())); - - loadSettings(); - reset(); -} - -HttpPasswordGeneratorWidget::~HttpPasswordGeneratorWidget() -{ -} - -void HttpPasswordGeneratorWidget::loadSettings() -{ - m_ui->checkBoxLower->setChecked(config()->get("Http/generator/LowerCase", PasswordGenerator::DefaultLower).toBool()); - m_ui->checkBoxUpper->setChecked(config()->get("Http/generator/UpperCase", PasswordGenerator::DefaultUpper).toBool()); - m_ui->checkBoxNumbers->setChecked(config()->get("Http/generator/Numbers", PasswordGenerator::DefaultNumbers).toBool()); - m_ui->checkBoxSpecialChars->setChecked(config()->get("Http/generator/SpecialChars", PasswordGenerator::DefaultSpecial).toBool()); - m_ui->checkBoxSpecialChars->setChecked(config()->get("Http/generator/EASCII", PasswordGenerator::DefaultEASCII).toBool()); - - m_ui->checkBoxExcludeAlike->setChecked(config()->get("Http/generator/ExcludeAlike", PasswordGenerator::DefaultLookAlike).toBool()); - m_ui->checkBoxEnsureEvery->setChecked(config()->get("Http/generator/EnsureEvery", PasswordGenerator::DefaultFromEveryGroup).toBool()); - - m_ui->spinBoxLength->setValue(config()->get("Http/generator/Length", PasswordGenerator::DefaultLength).toInt()); -} - -void HttpPasswordGeneratorWidget::saveSettings() -{ - config()->set("Http/generator/LowerCase", m_ui->checkBoxLower->isChecked()); - config()->set("Http/generator/UpperCase", m_ui->checkBoxUpper->isChecked()); - config()->set("Http/generator/Numbers", m_ui->checkBoxNumbers->isChecked()); - config()->set("Http/generator/SpecialChars", m_ui->checkBoxSpecialChars->isChecked()); - config()->set("Http/generator/EASCII", m_ui->checkBoxExtASCII->isChecked()); - - config()->set("Http/generator/ExcludeAlike", m_ui->checkBoxExcludeAlike->isChecked()); - config()->set("Http/generator/EnsureEvery", m_ui->checkBoxEnsureEvery->isChecked()); - - config()->set("Http/generator/Length", m_ui->spinBoxLength->value()); -} - -void HttpPasswordGeneratorWidget::reset() -{ - updateGenerator(); -} - -void HttpPasswordGeneratorWidget::sliderMoved() -{ - if (m_updatingSpinBox) { - return; - } - - m_ui->spinBoxLength->setValue(m_ui->sliderLength->value()); - - updateGenerator(); -} - -void HttpPasswordGeneratorWidget::spinBoxChanged() -{ - // Interlock so that we don't update twice - this causes issues as the spinbox can go higher than slider - m_updatingSpinBox = true; - - m_ui->sliderLength->setValue(m_ui->spinBoxLength->value()); - - m_updatingSpinBox = false; - - updateGenerator(); -} - -PasswordGenerator::CharClasses HttpPasswordGeneratorWidget::charClasses() -{ - PasswordGenerator::CharClasses classes; - - if (m_ui->checkBoxLower->isChecked()) { - classes |= PasswordGenerator::LowerLetters; - } - - if (m_ui->checkBoxUpper->isChecked()) { - classes |= PasswordGenerator::UpperLetters; - } - - if (m_ui->checkBoxNumbers->isChecked()) { - classes |= PasswordGenerator::Numbers; - } - - if (m_ui->checkBoxSpecialChars->isChecked()) { - classes |= PasswordGenerator::SpecialCharacters; - } - - if (m_ui->checkBoxExtASCII->isChecked()) { - classes |= PasswordGenerator::EASCII; - } - - return classes; -} - -PasswordGenerator::GeneratorFlags HttpPasswordGeneratorWidget::generatorFlags() -{ - PasswordGenerator::GeneratorFlags flags; - - if (m_ui->checkBoxExcludeAlike->isChecked()) { - flags |= PasswordGenerator::ExcludeLookAlike; - } - - if (m_ui->checkBoxEnsureEvery->isChecked()) { - flags |= PasswordGenerator::CharFromEveryGroup; - } - - return flags; -} - -void HttpPasswordGeneratorWidget::updateGenerator() -{ - m_generator->setLength(m_ui->spinBoxLength->value()); - m_generator->setCharClasses(charClasses()); - m_generator->setFlags(generatorFlags()); -} diff --git a/src/http/HttpPasswordGeneratorWidget.h b/src/http/HttpPasswordGeneratorWidget.h deleted file mode 100644 index 8ef6091b..00000000 --- a/src/http/HttpPasswordGeneratorWidget.h +++ /dev/null @@ -1,58 +0,0 @@ -/* -* Copyright (C) 2013 Francois Ferrand -* Copyright (C) 2017 KeePassXC Team -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 2 or (at your option) -* version 3 of the License. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -*/ - -#ifndef KEEPASSX_HTTPPASSWORDGENERATORWIDGET_H -#define KEEPASSX_HTTPPASSWORDGENERATORWIDGET_H - -#include -#include - -#include "core/PasswordGenerator.h" - -namespace Ui { - class HttpPasswordGeneratorWidget; -} - -class HttpPasswordGeneratorWidget : public QWidget -{ - Q_OBJECT - -public: - explicit HttpPasswordGeneratorWidget(QWidget* parent = nullptr); - ~HttpPasswordGeneratorWidget(); - void loadSettings(); - void saveSettings(); - void reset(); - -private slots: - void sliderMoved(); - void spinBoxChanged(); - - void updateGenerator(); - -private: - bool m_updatingSpinBox; - - PasswordGenerator::CharClasses charClasses(); - PasswordGenerator::GeneratorFlags generatorFlags(); - - const QScopedPointer m_generator; - const QScopedPointer m_ui; -}; - -#endif // KEEPASSX_PASSWORDGENERATORWIDGET_H diff --git a/src/http/HttpPasswordGeneratorWidget.ui b/src/http/HttpPasswordGeneratorWidget.ui deleted file mode 100644 index 71df8873..00000000 --- a/src/http/HttpPasswordGeneratorWidget.ui +++ /dev/null @@ -1,220 +0,0 @@ - - - HttpPasswordGeneratorWidget - - - - 0 - 0 - 500 - 181 - - - - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - - Length: - - - - - - - - - 1 - - - 64 - - - Qt::Horizontal - - - QSlider::TicksBelow - - - 8 - - - - - - - 1 - - - 999 - - - - - - - - - - - Character Types - - - - - - - - Upper Case Letters - - - A-Z - - - true - - - optionButtons - - - - - - - Lower Case Letters - - - a-z - - - true - - - optionButtons - - - - - - - Numbers - - - 0-9 - - - true - - - optionButtons - - - - - - - Special Characters - - - /*_& ... - - - true - - - optionButtons - - - - - - - Extended ASCII - - - Extended ASCII - - - true - - - optionButtons - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - Exclude look-alike characters - - - optionButtons - - - - - - - Ensure that the password contains characters from every group - - - optionButtons - - - - - - - - - - sliderLength - spinBoxLength - checkBoxUpper - checkBoxLower - checkBoxNumbers - checkBoxSpecialChars - checkBoxExcludeAlike - checkBoxEnsureEvery - - - - - - - false - - - - diff --git a/src/http/HttpSettings.cpp b/src/http/HttpSettings.cpp deleted file mode 100644 index 7ff0dbaa..00000000 --- a/src/http/HttpSettings.cpp +++ /dev/null @@ -1,270 +0,0 @@ -/* -* Copyright (C) 2013 Francois Ferrand -* Copyright (C) 2017 KeePassXC Team -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 2 or (at your option) -* version 3 of the License. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -*/ - -#include "HttpSettings.h" -#include "core/Config.h" - -PasswordGenerator HttpSettings::m_generator; - -bool HttpSettings::isEnabled() -{ - return config()->get("Http/Enabled", false).toBool(); -} - -void HttpSettings::setEnabled(bool enabled) -{ - config()->set("Http/Enabled", enabled); -} - -bool HttpSettings::showNotification() -{ - return config()->get("Http/ShowNotification", true).toBool(); -} - -void HttpSettings::setShowNotification(bool showNotification) -{ - config()->set("Http/ShowNotification", showNotification); -} - -bool HttpSettings::bestMatchOnly() -{ - return config()->get("Http/BestMatchOnly", false).toBool(); -} - -void HttpSettings::setBestMatchOnly(bool bestMatchOnly) -{ - config()->set("Http/BestMatchOnly", bestMatchOnly); -} - -bool HttpSettings::unlockDatabase() -{ - return config()->get("Http/UnlockDatabase", true).toBool(); -} - -void HttpSettings::setUnlockDatabase(bool unlockDatabase) -{ - config()->set("Http/UnlockDatabase", unlockDatabase); -} - -bool HttpSettings::matchUrlScheme() -{ - return config()->get("Http/MatchUrlScheme", true).toBool(); -} - -void HttpSettings::setMatchUrlScheme(bool matchUrlScheme) -{ - config()->set("Http/MatchUrlScheme", matchUrlScheme); -} - -bool HttpSettings::sortByUsername() -{ - return config()->get("Http/SortByUsername", false).toBool(); -} - -void HttpSettings::setSortByUsername(bool sortByUsername) -{ - config()->set("Http/SortByUsername", sortByUsername); -} - -bool HttpSettings::sortByTitle() -{ - return !sortByUsername(); -} - -void HttpSettings::setSortByTitle(bool sortByUsertitle) -{ - setSortByUsername(!sortByUsertitle); -} - -bool HttpSettings::alwaysAllowAccess() -{ - return config()->get("Http/AlwaysAllowAccess", false).toBool(); -} - -void HttpSettings::setAlwaysAllowAccess(bool alwaysAllowAccess) -{ - config()->set("Http/AlwaysAllowAccess", alwaysAllowAccess); -} - -bool HttpSettings::alwaysAllowUpdate() -{ - return config()->get("Http/AlwaysAllowUpdate", false).toBool(); -} - -void HttpSettings::setAlwaysAllowUpdate(bool alwaysAllowUpdate) -{ - config()->set("Http/AlwaysAllowUpdate", alwaysAllowUpdate); -} - -bool HttpSettings::searchInAllDatabases() -{ - return config()->get("Http/SearchInAllDatabases", false).toBool(); -} - -void HttpSettings::setSearchInAllDatabases(bool searchInAllDatabases) -{ - config()->set("Http/SearchInAllDatabases", searchInAllDatabases); -} - -bool HttpSettings::supportKphFields() -{ - return config()->get("Http/SupportKphFields", true).toBool(); -} - -void HttpSettings::setSupportKphFields(bool supportKphFields) -{ - config()->set("Http/SupportKphFields", supportKphFields); -} - -int HttpSettings::httpPort() -{ - static const int PORT = 19455; - - return config()->get("Http/Port", PORT).toInt(); -} - -void HttpSettings::setHttpPort(int port) -{ - config()->set("Http/Port", port); -} - -bool HttpSettings::passwordUseNumbers() -{ - return config()->get("Http/generator/Numbers", PasswordGenerator::DefaultNumbers).toBool(); -} - -void HttpSettings::setPasswordUseNumbers(bool useNumbers) -{ - config()->set("Http/generator/Numbers", useNumbers); -} - -bool HttpSettings::passwordUseLowercase() -{ - return config()->get("Http/generator/LowerCase", PasswordGenerator::DefaultLower).toBool(); -} - -void HttpSettings::setPasswordUseLowercase(bool useLowercase) -{ - config()->set("Http/generator/LowerCase", useLowercase); -} - -bool HttpSettings::passwordUseUppercase() -{ - return config()->get("Http/generator/UpperCase", PasswordGenerator::DefaultUpper).toBool(); -} - -void HttpSettings::setPasswordUseUppercase(bool useUppercase) -{ - config()->set("Http/generator/UpperCase", useUppercase); -} - -bool HttpSettings::passwordUseSpecial() -{ - return config()->get("Http/generator/SpecialChars", PasswordGenerator::DefaultSpecial).toBool(); -} - -void HttpSettings::setPasswordUseSpecial(bool useSpecial) -{ - config()->set("Http/generator/SpecialChars", useSpecial); -} - -bool HttpSettings::passwordUseEASCII() -{ - return config()->get("Http/generator/EASCII", PasswordGenerator::DefaultEASCII).toBool(); -} - -void HttpSettings::setPasswordUseEASCII(bool useExtended) -{ - config()->set("Http/generator/EASCII", useExtended); -} - -bool HttpSettings::passwordEveryGroup() -{ - return config()->get("Http/generator/EnsureEvery", PasswordGenerator::DefaultFromEveryGroup).toBool(); -} - -void HttpSettings::setPasswordEveryGroup(bool everyGroup) -{ - config()->get("Http/generator/EnsureEvery", everyGroup); -} - -bool HttpSettings::passwordExcludeAlike() -{ - return config()->get("Http/generator/ExcludeAlike", PasswordGenerator::DefaultLookAlike).toBool(); -} - -void HttpSettings::setPasswordExcludeAlike(bool excludeAlike) -{ - config()->set("Http/generator/ExcludeAlike", excludeAlike); -} - -int HttpSettings::passwordLength() -{ - return config()->get("Http/generator/Length", PasswordGenerator::DefaultLength).toInt(); -} - -void HttpSettings::setPasswordLength(int length) -{ - config()->set("Http/generator/Length", length); - m_generator.setLength(length); -} - -PasswordGenerator::CharClasses HttpSettings::passwordCharClasses() -{ - PasswordGenerator::CharClasses classes; - if (passwordUseLowercase()) { - classes |= PasswordGenerator::LowerLetters; - } - if (passwordUseUppercase()) { - classes |= PasswordGenerator::UpperLetters; - } - if (passwordUseNumbers()) { - classes |= PasswordGenerator::Numbers; - } - if (passwordUseSpecial()) { - classes |= PasswordGenerator::SpecialCharacters; - } - if (passwordUseEASCII()) { - classes |= PasswordGenerator::EASCII; - } - return classes; -} - -PasswordGenerator::GeneratorFlags HttpSettings::passwordGeneratorFlags() -{ - PasswordGenerator::GeneratorFlags flags; - if (passwordExcludeAlike()) - flags |= PasswordGenerator::ExcludeLookAlike; - if (passwordEveryGroup()) - flags |= PasswordGenerator::CharFromEveryGroup; - return flags; -} - -QString HttpSettings::generatePassword() -{ - m_generator.setLength(passwordLength()); - m_generator.setCharClasses(passwordCharClasses()); - m_generator.setFlags(passwordGeneratorFlags()); - - return m_generator.generatePassword(); -} - -int HttpSettings::getbits() -{ - return m_generator.getbits(); -} diff --git a/src/http/HttpSettings.h b/src/http/HttpSettings.h deleted file mode 100644 index 63c2963c..00000000 --- a/src/http/HttpSettings.h +++ /dev/null @@ -1,78 +0,0 @@ -/* -* Copyright (C) 2013 Francois Ferrand -* Copyright (C) 2017 KeePassXC Team -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 2 or (at your option) -* version 3 of the License. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -*/ - -#ifndef HTTPSETTINGS_H -#define HTTPSETTINGS_H - -#include "core/PasswordGenerator.h" - -class HttpSettings -{ -public: - static bool isEnabled(); - static void setEnabled(bool enabled); - - static bool showNotification(); //TODO!! - static void setShowNotification(bool showNotification); - static bool bestMatchOnly(); //TODO!! - static void setBestMatchOnly(bool bestMatchOnly); - static bool unlockDatabase(); //TODO!! - static void setUnlockDatabase(bool unlockDatabase); - static bool matchUrlScheme(); - static void setMatchUrlScheme(bool matchUrlScheme); - static bool sortByUsername(); - static void setSortByUsername(bool sortByUsername = true); - static bool sortByTitle(); - static void setSortByTitle(bool sortByUsertitle = true); - static bool alwaysAllowAccess(); - static void setAlwaysAllowAccess(bool alwaysAllowAccess); - static bool alwaysAllowUpdate(); - static void setAlwaysAllowUpdate(bool alwaysAllowUpdate); - static bool searchInAllDatabases();//TODO!! - static void setSearchInAllDatabases(bool searchInAllDatabases); - static bool supportKphFields(); - static void setSupportKphFields(bool supportKphFields); - static int httpPort(); - static void setHttpPort(int port); - - static bool passwordUseNumbers(); - static void setPasswordUseNumbers(bool useNumbers); - static bool passwordUseLowercase(); - static void setPasswordUseLowercase(bool useLowercase); - static bool passwordUseUppercase(); - static void setPasswordUseUppercase(bool useUppercase); - static bool passwordUseSpecial(); - static void setPasswordUseSpecial(bool useSpecial); - static bool passwordUseEASCII(); - static void setPasswordUseEASCII(bool useExtended); - static bool passwordEveryGroup(); - static void setPasswordEveryGroup(bool everyGroup); - static bool passwordExcludeAlike(); - static void setPasswordExcludeAlike(bool excludeAlike); - static int passwordLength(); - static void setPasswordLength(int length); - static PasswordGenerator::CharClasses passwordCharClasses(); - static PasswordGenerator::GeneratorFlags passwordGeneratorFlags(); - static QString generatePassword(); - static int getbits(); - -private: - static PasswordGenerator m_generator; -}; - -#endif // HTTPSETTINGS_H diff --git a/src/http/OptionDialog.cpp b/src/http/OptionDialog.cpp deleted file mode 100644 index dd5a51f7..00000000 --- a/src/http/OptionDialog.cpp +++ /dev/null @@ -1,102 +0,0 @@ -/* -* Copyright (C) 2013 Francois Ferrand -* Copyright (C) 2017 KeePassXC Team -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 2 or (at your option) -* version 3 of the License. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -*/ - -#include "OptionDialog.h" -#include "ui_OptionDialog.h" -#include "HttpSettings.h" - -#include "core/FilePath.h" - -#include - -OptionDialog::OptionDialog(QWidget *parent) : - QWidget(parent), - m_ui(new Ui::OptionDialog()) -{ - m_ui->setupUi(this); - connect(m_ui->removeSharedEncryptionKeys, SIGNAL(clicked()), this, SIGNAL(removeSharedEncryptionKeys())); - connect(m_ui->removeStoredPermissions, SIGNAL(clicked()), this, SIGNAL(removeStoredPermissions())); - - m_ui->warningWidget->showMessage(tr("Warning: The following options can be dangerous!"), MessageWidget::Warning); - m_ui->warningWidget->setCloseButtonVisible(false); - m_ui->warningWidget->setAutoHideTimeout(MessageWidget::DisableAutoHide); - - m_ui->tabWidget->setEnabled(m_ui->enableHttpServer->isChecked()); - connect(m_ui->enableHttpServer, SIGNAL(toggled(bool)), m_ui->tabWidget, SLOT(setEnabled(bool))); - - m_ui->deprecationNotice->showMessage(tr("

KeePassHTTP has been deprecated and will be removed in the future.
" - "Please switch to KeePassXC-Browser instead! For help with migration, visit " - "our " - "migration guide.

"), MessageWidget::Warning); - m_ui->deprecationNotice->setCloseButtonVisible(false); - m_ui->deprecationNotice->setAutoHideTimeout(-1); - connect(m_ui->deprecationNotice, &MessageWidget::linkActivated, &MessageWidget::openHttpUrl); -} - -OptionDialog::~OptionDialog() -{ -} - -void OptionDialog::loadSettings() -{ - HttpSettings settings; - m_ui->enableHttpServer->setChecked(settings.isEnabled()); - - m_ui->showNotification->setChecked(settings.showNotification()); - m_ui->bestMatchOnly->setChecked(settings.bestMatchOnly()); - m_ui->unlockDatabase->setChecked(settings.unlockDatabase()); - m_ui->matchUrlScheme->setChecked(settings.matchUrlScheme()); - if (settings.sortByUsername()) - m_ui->sortByUsername->setChecked(true); - else - m_ui->sortByTitle->setChecked(true); - m_ui->httpPort->setText(QString::number(settings.httpPort())); - - m_ui->alwaysAllowAccess->setChecked(settings.alwaysAllowAccess()); - m_ui->alwaysAllowUpdate->setChecked(settings.alwaysAllowUpdate()); - m_ui->searchInAllDatabases->setChecked(settings.searchInAllDatabases()); - m_ui->supportKphFields->setChecked(settings.supportKphFields()); - - m_ui->passwordGenerator->loadSettings(); -} - -void OptionDialog::saveSettings() -{ - HttpSettings settings; - settings.setEnabled(m_ui->enableHttpServer->isChecked()); - - settings.setShowNotification(m_ui->showNotification->isChecked()); - settings.setBestMatchOnly(m_ui->bestMatchOnly->isChecked()); - settings.setUnlockDatabase(m_ui->unlockDatabase->isChecked()); - settings.setMatchUrlScheme(m_ui->matchUrlScheme->isChecked()); - settings.setSortByUsername(m_ui->sortByUsername->isChecked()); - - int port = m_ui->httpPort->text().toInt(); - if (port < 1024) { - QMessageBox::warning(this, tr("Cannot bind to privileged ports"), - tr("Cannot bind to privileged ports below 1024!\nUsing default port 19455.")); - port = 19455; - } - settings.setHttpPort(port); - settings.setAlwaysAllowAccess(m_ui->alwaysAllowAccess->isChecked()); - settings.setAlwaysAllowUpdate(m_ui->alwaysAllowUpdate->isChecked()); - settings.setSearchInAllDatabases(m_ui->searchInAllDatabases->isChecked()); - settings.setSupportKphFields(m_ui->supportKphFields->isChecked()); - - m_ui->passwordGenerator->saveSettings(); -} diff --git a/src/http/OptionDialog.h b/src/http/OptionDialog.h deleted file mode 100644 index 6139f929..00000000 --- a/src/http/OptionDialog.h +++ /dev/null @@ -1,49 +0,0 @@ -/* -* Copyright (C) 2013 Francois Ferrand -* Copyright (C) 2017 KeePassXC Team -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 2 or (at your option) -* version 3 of the License. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -*/ - -#ifndef OPTIONDIALOG_H -#define OPTIONDIALOG_H - -#include -#include - -namespace Ui { -class OptionDialog; -} - -class OptionDialog : public QWidget -{ - Q_OBJECT - -public: - explicit OptionDialog(QWidget *parent = nullptr); - ~OptionDialog(); - -public slots: - void loadSettings(); - void saveSettings(); - -signals: - void removeSharedEncryptionKeys(); - void removeStoredPermissions(); - -private: - QScopedPointer m_ui; -}; - -#endif // OPTIONDIALOG_H diff --git a/src/http/OptionDialog.ui b/src/http/OptionDialog.ui deleted file mode 100644 index 472f9f62..00000000 --- a/src/http/OptionDialog.ui +++ /dev/null @@ -1,301 +0,0 @@ - - - OptionDialog - - - - 0 - 0 - 803 - 433 - - - - Dialog - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - This is required for accessing your databases from ChromeIPass or PassIFox - - - Enable KeePassHTTP server - - - - - - - - - - 0 - - - - General - - - - - - Sh&ow a notification when credentials are requested - - - true - - - - - - - Only returns the best matches for a specific URL instead of all entries for the whole domain. - - - &Return only best matching entries - - - - - - - Re&quest to unlock the database if it is locked - - - true - - - - - - - Only entries with the same scheme (http://, https://, ftp://, ...) are returned. - - - &Match URL schemes - - - - - - - Sort matching entries by &username - - - - - - - Sort &matching entries by title - - - - - - - R&emove all shared encryption keys from active database - - - - - - - Re&move all stored permissions from entries in active database - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - Password Generator - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - Advanced - - - - - - - 0 - 0 - - - - - - - - Always allow &access to entries - - - - - - - Always allow &updating entries - - - - - - - Only the selected database has to be connected with a client. - - - Searc&h in all opened databases for matching entries - - - - - - - Automatically creating or updating string fields is not supported. - - - &Return advanced string fields which start with "KPH: " - - - - - - - Qt::Vertical - - - QSizePolicy::Fixed - - - - 20 - 20 - - - - - - - - - - - 0 - 0 - - - - HTTP Port: - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - - - - - 0 - 0 - - - - d0000 - - - Default port: 19455 - - - - - - - KeePassXC will listen to this port on 127.0.0.1 - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - - - - HttpPasswordGeneratorWidget - QWidget -
http/HttpPasswordGeneratorWidget.h
- 1 -
- - MessageWidget - QWidget -
gui/MessageWidget.h
- 1 -
-
- - -
diff --git a/src/http/Protocol.cpp b/src/http/Protocol.cpp deleted file mode 100644 index d6d5557a..00000000 --- a/src/http/Protocol.cpp +++ /dev/null @@ -1,557 +0,0 @@ -/* -* Copyright (C) 2013 Francois Ferrand -* Copyright (C) 2017 KeePassXC Team -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 2 or (at your option) -* version 3 of the License. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -*/ - -#include "Protocol.h" -#include - -#include "crypto/Random.h" -#include "crypto/SymmetricCipher.h" -#include "crypto/SymmetricCipherGcrypt.h" -#include "core/Global.h" - -namespace KeepassHttpProtocol -{ -static const char * const STR_GET_LOGINS = "get-logins"; -static const char * const STR_GET_LOGINS_COUNT = "get-logins-count"; -static const char * const STR_GET_ALL_LOGINS = "get-all-logins"; -static const char * const STR_SET_LOGIN = "set-login"; -static const char * const STR_ASSOCIATE = "associate"; -static const char * const STR_TEST_ASSOCIATE = "test-associate"; -static const char * const STR_GENERATE_PASSWORD = "generate-password"; -static const char * const STR_VERSION = "1.8.4.2"; - -}/*namespace KeepassHttpProtocol*/ - -using namespace KeepassHttpProtocol; - -QVariantMap qobject2qvariant( const QObject* object, const QStringList& ignoredProperties ) -{ - QVariantMap result; - const QMetaObject *metaobject = object->metaObject(); - int count = metaobject->propertyCount(); - for (int i=0; iproperty(i); - const char *name = metaproperty.name(); - - if (ignoredProperties.contains(QLatin1String(name)) || (!metaproperty.isReadable())) - continue; - - QVariant value = object->property(name); - result[QLatin1String(name)] = value; - } - return result; -} - -static QHash createStringHash() -{ - QHash hash; - hash.insert(STR_GET_LOGINS, GET_LOGINS); - hash.insert(STR_GET_LOGINS_COUNT, GET_LOGINS_COUNT); - hash.insert(STR_GET_ALL_LOGINS, GET_ALL_LOGINS); - hash.insert(STR_SET_LOGIN, SET_LOGIN); - hash.insert(STR_ASSOCIATE, ASSOCIATE); - hash.insert(STR_TEST_ASSOCIATE, TEST_ASSOCIATE); - hash.insert(STR_GENERATE_PASSWORD,GENERATE_PASSWORD); - return hash; -} - -static RequestType parseRequest(const QString &str) -{ - static const QHash REQUEST_STRINGS = createStringHash(); - return REQUEST_STRINGS.value(str, INVALID); -} - -static QByteArray decode64(QString s) -{ - return QByteArray::fromBase64(s.toLatin1()); -} - -static QString encode64(QByteArray b) -{ - return QString::fromLatin1(b.toBase64()); -} - -static QByteArray decrypt2(const QByteArray & data, SymmetricCipherGcrypt & cipher) -{ - //Ensure we get full blocks only - if (data.length() <= 0 || data.length() % cipher.blockSize()) - return QByteArray(); - - //Decrypt - cipher.reset(); - bool ok; - QByteArray buffer = cipher.process(data, &ok); - - //Remove PKCS#7 padding - buffer.chop(buffer.at(buffer.length()-1)); - return buffer; -} - -static QString decrypt(const QString &data, SymmetricCipherGcrypt & cipher) -{ - return QString::fromUtf8(decrypt2(decode64(data), cipher)); -} - -static QByteArray encrypt2(const QByteArray & data, SymmetricCipherGcrypt & cipher) -{ - //Add PKCS#7 padding - const int blockSize = cipher.blockSize(); - const int paddingSize = blockSize - data.size() % blockSize; - - //Encrypt - QByteArray buffer = data + QByteArray(paddingSize, paddingSize); - cipher.reset(); - Q_UNUSED(cipher.processInPlace(buffer)); - return buffer; -} - -static QString encrypt(const QString & data, SymmetricCipherGcrypt & cipher) -{ - return encode64(encrypt2(data.toUtf8(), cipher)); -} - - -//////////////////////////////////////////////////////////////////////////////////////////////////// -/// Request -//////////////////////////////////////////////////////////////////////////////////////////////////// - -Request::Request(): - m_requestType(INVALID), - m_cipher(SymmetricCipher::Aes256, SymmetricCipher::Cbc, SymmetricCipher::Decrypt) -{ - m_cipher.init(); -} - -QString Request::nonce() const -{ - return m_nonce; -} - -void Request::setNonce(const QString &nonce) -{ - m_nonce = nonce; -} - -QString Request::verifier() const -{ - return m_verifier; -} - -void Request::setVerifier(const QString &verifier) -{ - m_verifier = verifier; -} - -QString Request::id() const -{ - return m_id; -} - -void Request::setId(const QString &id) -{ - m_id = id; -} - -QString Request::key() const -{ - return m_key; -} - -void Request::setKey(const QString &key) -{ - m_key = key; -} - -QString Request::submitUrl() const -{ - //Q_ASSERT(m_cipher.isValid()); - return decrypt(m_submitUrl, m_cipher); -} - -void Request::setSubmitUrl(const QString &submitUrl) -{ - m_submitUrl = submitUrl; -} - -QString Request::url() const -{ - //Q_ASSERT(m_cipher.isValid()); - return decrypt(m_url, m_cipher); -} - -void Request::setUrl(const QString &url) -{ - m_url = url; -} - -QString Request::realm() const -{ - //Q_ASSERT(m_cipher.isValid()); - return decrypt(m_realm, m_cipher); -} - -void Request::setRealm(const QString &realm) -{ - m_realm = realm; -} - -QString Request::login() const -{ - //Q_ASSERT(m_cipher.isValid()); - return decrypt(m_login, m_cipher); -} - -void Request::setLogin(const QString &login) -{ - m_login = login; -} - -QString Request::uuid() const -{ - //Q_ASSERT(m_cipher.isValid()); - return decrypt(m_uuid, m_cipher); -} - -void Request::setUuid(const QString &uuid) -{ - m_uuid = uuid; -} - -QString Request::password() const -{ - //Q_ASSERT(m_cipher.isValid()); - return decrypt(m_password, m_cipher); -} - -void Request::setPassword(const QString &password) -{ - m_password = password; -} - -bool Request::sortSelection() const -{ - return m_sortSelection; -} - -void Request::setSortSelection(bool sortSelection) -{ - m_sortSelection = sortSelection; -} - -KeepassHttpProtocol::RequestType Request::requestType() const -{ - return parseRequest(m_requestType); -} - -QString Request::requestTypeStr() const -{ - return m_requestType; -} - -void Request::setRequestType(const QString &requestType) -{ - m_requestType = requestType; -} - -bool Request::CheckVerifier(const QString &key) const -{ - //Q_ASSERT(!m_cipher.isValid()); - - m_cipher.setKey(decode64(key)); - m_cipher.setIv(decode64(m_nonce)); - - return decrypt(m_verifier, m_cipher) == m_nonce; -} - -bool Request::fromJson(QString text) -{ - QJsonDocument doc = QJsonDocument::fromJson(text.toUtf8()); - if (doc.isNull()) - return false; - - m_requestType.clear(); - QVariantMap map = doc.object().toVariantMap(); - for(QVariantMap::iterator iter = map.begin(); iter != map.end(); ++iter) { - setProperty(iter.key().toLatin1(), iter.value()); - } - - return requestType() != INVALID; -} - - -//////////////////////////////////////////////////////////////////////////////////////////////////// -/// Response -//////////////////////////////////////////////////////////////////////////////////////////////////// - -Response::Response(const Request &request, QString hash): - m_requestType(request.requestTypeStr()), - m_success(false), - m_count(-1), - m_version(STR_VERSION), - m_hash(hash), - m_cipher(SymmetricCipher::Aes256, SymmetricCipher::Cbc, SymmetricCipher::Encrypt) -{ - m_cipher.init(); -} - -void Response::setVerifier(QString key) -{ - //Q_ASSERT(!m_cipher.isValid()); - - m_cipher.setKey(decode64(key)); - - //Generate new IV - const QByteArray iv = randomGen()->randomArray(m_cipher.blockSize()); - m_cipher.setIv(iv); - m_nonce = encode64(iv); - - //Encrypt - m_verifier = encrypt(m_nonce, m_cipher); -} - -QString Response::toJson() -{ - QJsonObject json; - - int count = metaObject()->propertyCount(); - for (int i=0; iproperty(i); - const char *name = metaproperty.name(); - json.insert(QString(name), QJsonValue::fromVariant(this->property(name))); - } - - QJsonDocument doc(json); - return doc.toJson(QJsonDocument::Compact); -} - -KeepassHttpProtocol::RequestType Response::requestType() const -{ - return parseRequest(m_requestType); -} - -QString Response::requestTypeStr() const -{ - return m_requestType; -} - -QString Response::verifier() const -{ - return m_verifier; -} - -QString Response::nonce() const -{ - return m_nonce; -} - -QVariant Response::count() const -{ - return m_count < 0 ? QVariant() : QVariant(m_count); -} - -void Response::setCount(int count) -{ - m_count = count; -} - -QVariant Response::getEntries() const -{ - if (m_count < 0 || m_entries.isEmpty()) - return QVariant(); - - QList res; - res.reserve(m_entries.size()); - for (const Entry& entry: asConst(m_entries)) { - res.append(qobject2qvariant(&entry)); - } - return res; -} - -void Response::setEntries(const QList &entries) -{ - //Q_ASSERT(m_cipher.isValid()); - - m_count = entries.count(); - - QList encryptedEntries; - encryptedEntries.reserve(m_count); - for (const Entry& entry: entries) { - Entry encryptedEntry(encrypt(entry.name(), m_cipher), - encrypt(entry.login(), m_cipher), - entry.password().isNull() ? QString() : encrypt(entry.password(), m_cipher), - encrypt(entry.uuid(), m_cipher)); - const auto stringFields = entry.stringFields(); - for (const StringField& field: stringFields) { - encryptedEntry.addStringField(encrypt(field.key(), m_cipher), - encrypt(field.value(), m_cipher)); - } - encryptedEntries << encryptedEntry; - } - m_entries = encryptedEntries; -} - -QString Response::hash() const -{ - return m_hash; -} - -QString Response::version() const -{ - return m_version; -} - -QString Response::id() const -{ - return m_id; -} - -void Response::setId(const QString &id) -{ - m_id = id; -} - -bool Response::success() const -{ - return m_success; -} - -void Response::setSuccess() -{ - m_success = true; -} - -QString Response::error() const -{ - return m_error; -} - -void Response::setError(const QString &error) -{ - m_success = false; - m_error = error; -} - - -//////////////////////////////////////////////////////////////////////////////////////////////////// -/// Entry -//////////////////////////////////////////////////////////////////////////////////////////////////// - -Entry::Entry() -{} - -Entry::Entry(QString name, QString login, QString password, QString uuid): - m_login(login), - m_password(password), - m_uuid(uuid), - m_name(name) -{} - -Entry::Entry(const Entry & other): - QObject(), - m_login(other.m_login), - m_password(other.m_password), - m_uuid(other.m_uuid), - m_name(other.m_name), - m_stringFields(other.m_stringFields) -{} - -Entry & Entry::operator=(const Entry & other) -{ - m_login = other.m_login; - m_password = other.m_password; - m_uuid = other.m_uuid; - m_name = other.m_name; - m_stringFields = other.m_stringFields; - return *this; -} - -QString Entry::login() const -{ - return m_login; -} - -QString Entry::name() const -{ - return m_name; -} - -QString Entry::uuid() const -{ - return m_uuid; -} - -QString Entry::password() const -{ - return m_password; -} - -QList Entry::stringFields() const -{ - return m_stringFields; -} - -void Entry::addStringField(const QString &key, const QString &value) -{ - m_stringFields.append(StringField(key, value)); -} - -QVariant Entry::getStringFields() const -{ - if (m_stringFields.isEmpty()) - return QVariant(); - - QList res; - res.reserve(m_stringFields.size()); - for (const StringField& stringfield: asConst(m_stringFields)) { - res.append(qobject2qvariant(&stringfield)); - } - return res; -} - - -//////////////////////////////////////////////////////////////////////////////////////////////////// -/// StringField -//////////////////////////////////////////////////////////////////////////////////////////////////// - -StringField::StringField() -{} - -StringField::StringField(const QString &key, const QString &value): - m_key(key), m_value(value) -{} - -StringField::StringField(const StringField &other): - QObject(NULL), m_key(other.m_key), m_value(other.m_value) -{} - -StringField &StringField::operator =(const StringField &other) -{ - m_key = other.m_key; - m_value = other.m_value; - return *this; -} - -QString StringField::key() const -{ - return m_key; -} - -QString StringField::value() const -{ - return m_value; -} diff --git a/src/http/Protocol.h b/src/http/Protocol.h deleted file mode 100644 index ff48fe58..00000000 --- a/src/http/Protocol.h +++ /dev/null @@ -1,212 +0,0 @@ -/* -* Copyright (C) 2013 Francois Ferrand -* Copyright (C) 2017 KeePassXC Team -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 2 or (at your option) -* version 3 of the License. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -*/ - -#ifndef RESPONSE_H -#define RESPONSE_H - -#include -#include "crypto/SymmetricCipherGcrypt.h" - -QVariantMap qobject2qvariant( const QObject* object, const QStringList& ignoredProperties = QStringList(QString(QLatin1String("objectName"))) ); - -namespace KeepassHttpProtocol { - -enum RequestType { - INVALID = -1, - GET_LOGINS, - GET_LOGINS_COUNT, - GET_ALL_LOGINS, - SET_LOGIN, - ASSOCIATE, - TEST_ASSOCIATE, - GENERATE_PASSWORD -}; - -//TODO: use QByteArray whenever possible? - -class Request : public QObject -{ - Q_OBJECT - Q_PROPERTY(QString RequestType READ requestTypeStr WRITE setRequestType ) - Q_PROPERTY(bool SortSelection READ sortSelection WRITE setSortSelection) - Q_PROPERTY(QString Login READ login WRITE setLogin ) - Q_PROPERTY(QString Password READ password WRITE setPassword ) - Q_PROPERTY(QString Uuid READ uuid WRITE setUuid ) - Q_PROPERTY(QString Url READ url WRITE setUrl ) - Q_PROPERTY(QString SubmitUrl READ submitUrl WRITE setSubmitUrl ) - Q_PROPERTY(QString Key READ key WRITE setKey ) - Q_PROPERTY(QString Id READ id WRITE setId ) - Q_PROPERTY(QString Verifier READ verifier WRITE setVerifier ) - Q_PROPERTY(QString Nonce READ nonce WRITE setNonce ) - Q_PROPERTY(QString Realm READ realm WRITE setRealm ) - -public: - Request(); - bool fromJson(QString text); - - KeepassHttpProtocol::RequestType requestType() const; - QString requestTypeStr() const; - bool sortSelection() const; - QString login() const; - QString password() const; - QString uuid() const; - QString url() const; - QString submitUrl() const; - QString key() const; - QString id() const; - QString verifier() const; - QString nonce() const; - QString realm() const; - bool CheckVerifier(const QString & key) const; - -private: - void setRequestType(const QString &requestType); - void setSortSelection(bool sortSelection); - void setLogin(const QString &login); - void setPassword(const QString &password); - void setUuid(const QString &uuid); - void setUrl(const QString &url); - void setSubmitUrl(const QString &submitUrl); - void setKey(const QString &key); - void setId(const QString &id); - void setVerifier(const QString &verifier); - void setNonce(const QString &nonce); - void setRealm(const QString &realm); - - QString m_requestType; - bool m_sortSelection; - QString m_login; - QString m_password; - QString m_uuid; - QString m_url; - QString m_submitUrl; - QString m_key; - QString m_id; - QString m_verifier; - QString m_nonce; - QString m_realm; - mutable SymmetricCipherGcrypt m_cipher; -}; - -class StringField : public QObject -{ - Q_OBJECT - Q_PROPERTY(QString Key READ key ) - Q_PROPERTY(QString Value READ value) - -public: - StringField(); - StringField(const QString& key, const QString& value); - StringField(const StringField & other); - StringField &operator =(const StringField &other); - - QString key() const; - QString value() const; - -private: - QString m_key; - QString m_value; -}; - -class Entry : public QObject -{ - Q_OBJECT - Q_PROPERTY(QString Login READ login ) - Q_PROPERTY(QString Password READ password ) - Q_PROPERTY(QString Uuid READ uuid ) - Q_PROPERTY(QString Name READ name ) - Q_PROPERTY(QVariant StringFields READ getStringFields) - -public: - Entry(); - Entry(QString name, QString login, QString password, QString uuid); - Entry(const Entry & other); - Entry &operator =(const Entry &other); - - QString login() const; - QString password() const; - QString uuid() const; - QString name() const; - QList stringFields() const; - void addStringField(const QString& key, const QString& value); - -private: - QVariant getStringFields() const; - - QString m_login; - QString m_password; - QString m_uuid; - QString m_name; - QList m_stringFields; -}; - -class Response : public QObject -{ - Q_OBJECT - Q_PROPERTY(QString RequestType READ requestTypeStr) - Q_PROPERTY(QString Error READ error ) - Q_PROPERTY(bool Success READ success ) - Q_PROPERTY(QString Id READ id ) - Q_PROPERTY(QString Version READ version ) - Q_PROPERTY(QString Hash READ hash ) - Q_PROPERTY(QVariant Count READ count ) - Q_PROPERTY(QVariant Entries READ getEntries ) - Q_PROPERTY(QString Nonce READ nonce ) - Q_PROPERTY(QString Verifier READ verifier ) - -public: - Response(const Request &request, QString hash); - - KeepassHttpProtocol::RequestType requestType() const; - QString error() const; - void setError(const QString &error = QString()); - bool success() const; - void setSuccess(); - QString id() const; - void setId(const QString &id); - QString version() const; - QString hash() const; - QVariant count() const; - void setCount(int count); - QVariant getEntries() const; - void setEntries(const QList &entries); - QString nonce() const; - QString verifier() const; - void setVerifier(QString key); - - QString toJson(); - -private: - QString requestTypeStr() const; - - QString m_requestType; - QString m_error; - bool m_success; - QString m_id; - int m_count; - QString m_version; - QString m_hash; - QList m_entries; - QString m_nonce; - QString m_verifier; - mutable SymmetricCipherGcrypt m_cipher; -}; - -}/*namespace KeepassHttpProtocol*/ - -#endif // RESPONSE_H diff --git a/src/http/Server.cpp b/src/http/Server.cpp deleted file mode 100644 index 08c5b20b..00000000 --- a/src/http/Server.cpp +++ /dev/null @@ -1,236 +0,0 @@ -/* -* Copyright (C) 2013 Francois Ferrand -* Copyright (C) 2017 KeePassXC Team -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 2 or (at your option) -* version 3 of the License. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -*/ - -#include -#include -#include -#include - -#include "qhttp/qhttpserver.hpp" -#include "qhttp/qhttpserverresponse.hpp" -#include "qhttp/qhttpserverrequest.hpp" - -#include "Server.h" -#include "Protocol.h" -#include "HttpSettings.h" -#include "crypto/Crypto.h" - -using namespace KeepassHttpProtocol; -using namespace qhttp::server; - -Server::Server(QObject *parent) : - QObject(parent), - m_started(false), - m_server(nullptr) -{ - -} - -void Server::testAssociate(const Request& r, Response * protocolResp) -{ - if (r.id().isEmpty()) - return; //ping - - QString key = getKey(r.id()); - if (key.isEmpty() || !r.CheckVerifier(key)) - return; - - protocolResp->setSuccess(); - protocolResp->setId(r.id()); - protocolResp->setVerifier(key); -} - -void Server::associate(const Request& r, Response * protocolResp) -{ - if (!r.CheckVerifier(r.key())) - return; - - QString id = storeKey(r.key()); - if (id.isEmpty()) - return; - - protocolResp->setSuccess(); - protocolResp->setId(id); - protocolResp->setVerifier(r.key()); -} - -void Server::getLogins(const Request &r, Response *protocolResp) -{ - QString key = getKey(r.id()); - if (!r.CheckVerifier(key)) - return; - - protocolResp->setSuccess(); - protocolResp->setId(r.id()); - protocolResp->setVerifier(key); - QList entries = findMatchingEntries(r.id(), r.url(), r.submitUrl(), r.realm()); //TODO: filtering, request confirmation [in db adaptation layer?] - if (r.sortSelection()) { - //TODO: sorting (in db adaptation layer? here?) - } - protocolResp->setEntries(entries); -} - -void Server::getLoginsCount(const Request &r, Response *protocolResp) -{ - QString key = getKey(r.id()); - if (!r.CheckVerifier(key)) - return; - - protocolResp->setSuccess(); - protocolResp->setId(r.id()); - protocolResp->setVerifier(key); - protocolResp->setCount(countMatchingEntries(r.id(), r.url(), r.submitUrl(), r.realm())); -} - -void Server::getAllLogins(const Request &r, Response *protocolResp) -{ - QString key = getKey(r.id()); - if (!r.CheckVerifier(key)) - return; - - protocolResp->setSuccess(); - protocolResp->setId(r.id()); - protocolResp->setVerifier(key); - protocolResp->setEntries(searchAllEntries(r.id())); //TODO: ensure there is no password --> change API? -} - -void Server::setLogin(const Request &r, Response *protocolResp) -{ - QString key = getKey(r.id()); - if (!r.CheckVerifier(key)) - return; - - QString uuid = r.uuid(); - if (uuid.isEmpty()) - addEntry(r.id(), r.login(), r.password(), r.url(), r.submitUrl(), r.realm()); - else - updateEntry(r.id(), r.uuid(), r.login(), r.password(), r.url()); - - protocolResp->setSuccess(); - protocolResp->setId(r.id()); - protocolResp->setVerifier(key); -} - -void Server::generatePassword(const Request &r, Response *protocolResp) -{ - QString key = getKey(r.id()); - if (!r.CheckVerifier(key)) - return; - - QString password = generatePassword(); - QString bits = QString::number(HttpSettings::getbits()); - - protocolResp->setSuccess(); - protocolResp->setId(r.id()); - protocolResp->setVerifier(key); - protocolResp->setEntries(QList() << Entry("generate-password", bits, password, "generate-password")); - - int size = password.capacity(); - volatile auto* mem = reinterpret_cast(password.data()); - while (size--) { - *mem++ = 0; - } -} - -void Server::handleRequest(const QByteArray& data, QHttpResponse* response) -{ - Request r; - if (!r.fromJson(data)) - return; - - QByteArray hash = QCryptographicHash::hash( - (getDatabaseRootUuid() + getDatabaseRecycleBinUuid()).toUtf8(), - QCryptographicHash::Sha1).toHex(); - - Response protocolResp(r, QString::fromLatin1(hash)); - switch(r.requestType()) { - case INVALID: break; - case GET_LOGINS: getLogins(r, &protocolResp); break; - case GET_LOGINS_COUNT: getLoginsCount(r, &protocolResp); break; - case GET_ALL_LOGINS: getAllLogins(r, &protocolResp); break; - case SET_LOGIN: setLogin(r, &protocolResp); break; - case ASSOCIATE: associate(r, &protocolResp); break; - case TEST_ASSOCIATE: testAssociate(r, &protocolResp); break; - case GENERATE_PASSWORD: generatePassword(r, &protocolResp); break; - } - - QString out = protocolResp.toJson().toUtf8(); - - // THIS IS A FAKE HACK!!! - // the real "error" is a misbehavior in the QJSON qobject2qvariant method - // 1. getLogins returns an empty QList into protocolResp->m_entries - // in toJson() function the following happened: - // 2. QJson::QObjectHelper::qobject2qvariant marks m_entries as invalid !!! - // 3. QJson::Serializer write out Entries as null instead of empty list - //(4. ChromeIPass tries to access Entries.length and fails with null pointer exception) - // the fake workaround replaces the (wrong) "Entries":null with "Entries:[] to give - // chromeIPass (and passIFox) en empty list - int pos1 = out.indexOf("\"Count\":0,"); - int pos2 = out.indexOf("\"Entries\":null,"); - if (pos1 != -1 && pos2 != -1) { - out.replace(pos2, 15, "\"Entries\":[],"); - } - - response->setStatusCode(qhttp::ESTATUS_OK); - response->addHeader("Content-Type", "application/json"); - response->end(out.toUtf8()); -} - -void Server::start(void) -{ - if (m_started) - return; - - // local loopback hardcoded, since KeePassHTTP handshake - // is not safe against interception - QHostAddress address("127.0.0.1"); - int port = HttpSettings::httpPort(); - - m_server = new QHttpServer(this); - m_server->listen(address, port); - connect(m_server, SIGNAL(newRequest(QHttpRequest*, QHttpResponse*)), this, SLOT(onNewRequest(QHttpRequest*, QHttpResponse*))); - - m_started = true; -} - -void Server::stop(void) -{ - if (!m_started) - return; - - m_server->stopListening(); - m_server->deleteLater(); - m_started = false; -} - -void Server::onNewRequest(QHttpRequest* request, QHttpResponse* response) -{ - if (!isDatabaseOpened()) { - if (!openDatabase()) { - response->setStatusCode(qhttp::ESTATUS_SERVICE_UNAVAILABLE); - response->end(); - return; - } - } - - request->collectData(1024); - - request->onEnd([=]() { - this->handleRequest(request->collectedData(), response); - }); -} diff --git a/src/http/Server.h b/src/http/Server.h deleted file mode 100644 index 08cdfa24..00000000 --- a/src/http/Server.h +++ /dev/null @@ -1,84 +0,0 @@ -/* -* Copyright (C) 2013 Francois Ferrand -* Copyright (C) 2017 KeePassXC Team -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 2 or (at your option) -* version 3 of the License. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -*/ - -#ifndef SERVER_H -#define SERVER_H - -#include -#include - -namespace qhttp { - namespace server { - class QHttpServer; - class QHttpRequest; - class QHttpResponse; - } -} - -namespace KeepassHttpProtocol { - -using namespace qhttp::server; - -class Request; -class Response; -class Entry; - -class Server : public QObject -{ - Q_OBJECT -public: - explicit Server(QObject *parent = 0); - - virtual bool isDatabaseOpened() const = 0; - virtual bool openDatabase() = 0; - virtual QString getDatabaseRootUuid() = 0; - virtual QString getDatabaseRecycleBinUuid() = 0; - virtual QString getKey(const QString &id) = 0; - virtual QString storeKey(const QString &key) = 0; - virtual QList findMatchingEntries(const QString &id, const QString &url, const QString & submitUrl, const QString & realm) = 0; - virtual int countMatchingEntries(const QString &id, const QString &url, const QString & submitUrl, const QString & realm) = 0; - virtual QList searchAllEntries(const QString &id) = 0; - virtual void addEntry(const QString &id, const QString &login, const QString &password, const QString &url, const QString &submitUrl, const QString &realm) = 0; - virtual void updateEntry(const QString &id, const QString &uuid, const QString &login, const QString &password, const QString &url) = 0; - virtual QString generatePassword() = 0; - -public slots: - void start(); - void stop(); - -private slots: - void onNewRequest(QHttpRequest* request, QHttpResponse* response); - void handleRequest(const QByteArray& data, QHttpResponse* response); - -private: - void testAssociate(const KeepassHttpProtocol::Request &r, KeepassHttpProtocol::Response *protocolResp); - void associate(const KeepassHttpProtocol::Request &r, KeepassHttpProtocol::Response *protocolResp); - void getLogins(const KeepassHttpProtocol::Request &r, KeepassHttpProtocol::Response *protocolResp); - void getLoginsCount(const KeepassHttpProtocol::Request &r, KeepassHttpProtocol::Response *protocolResp); - void getAllLogins(const KeepassHttpProtocol::Request &r, KeepassHttpProtocol::Response *protocolResp); - void setLogin(const KeepassHttpProtocol::Request &r, KeepassHttpProtocol::Response *protocolResp); - void generatePassword(const KeepassHttpProtocol::Request &r, KeepassHttpProtocol::Response *protocolResp); - - bool m_started; - - QHttpServer* m_server; -}; - -} /*namespace KeepassHttpProtocol*/ - -#endif // SERVER_H diff --git a/src/http/Service.cpp b/src/http/Service.cpp deleted file mode 100644 index 7f74a3ae..00000000 --- a/src/http/Service.cpp +++ /dev/null @@ -1,603 +0,0 @@ -/* -* Copyright (C) 2013 Francois Ferrand -* Copyright (C) 2017 KeePassXC Team -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 2 or (at your option) -* version 3 of the License. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -*/ - -#include -#include -#include - -#include "Service.h" -#include "Protocol.h" -#include "EntryConfig.h" -#include "AccessControlDialog.h" -#include "HttpSettings.h" - -#include "core/Database.h" -#include "core/Entry.h" -#include "core/Global.h" -#include "core/Group.h" -#include "core/EntrySearcher.h" -#include "core/Metadata.h" -#include "core/Uuid.h" -#include "core/PasswordGenerator.h" - -#include - -static const unsigned char KEEPASSHTTP_UUID_DATA[] = { - 0x34, 0x69, 0x7a, 0x40, 0x8a, 0x5b, 0x41, 0xc0, - 0x9f, 0x36, 0x89, 0x7d, 0x62, 0x3e, 0xcb, 0x31 -}; -static const Uuid KEEPASSHTTP_UUID = Uuid(QByteArray::fromRawData(reinterpret_cast(KEEPASSHTTP_UUID_DATA), sizeof(KEEPASSHTTP_UUID_DATA))); -static const char KEEPASSHTTP_NAME[] = "KeePassHttp Settings"; -static const char ASSOCIATE_KEY_PREFIX[] = "AES Key: "; -static const char KEEPASSHTTP_GROUP_NAME[] = "KeePassHttp Passwords"; //Group where new KeePassHttp password are stored -static int KEEPASSHTTP_DEFAULT_ICON = 1; -//private const int DEFAULT_NOTIFICATION_TIME = 5000; - -Service::Service(DatabaseTabWidget* parent) : - KeepassHttpProtocol::Server(parent), - m_dbTabWidget(parent) -{ - if (HttpSettings::isEnabled()) - start(); -} - -Entry* Service::getConfigEntry(bool create) -{ - if (DatabaseWidget * dbWidget = m_dbTabWidget->currentDatabaseWidget()) - if (Database * db = dbWidget->database()) { - Entry* entry = db->resolveEntry(KEEPASSHTTP_UUID); - if (!entry && create) { - entry = new Entry(); - entry->setTitle(QLatin1String(KEEPASSHTTP_NAME)); - entry->setUuid(KEEPASSHTTP_UUID); - entry->setAutoTypeEnabled(false); - entry->setGroup(db->rootGroup()); - } else if (entry && entry->group() == db->metadata()->recycleBin()) { - if (create) - entry->setGroup(db->rootGroup()); - else - entry = NULL; - } - return entry; - } - return NULL; -} - -bool Service::isDatabaseOpened() const -{ - if (DatabaseWidget* dbWidget = m_dbTabWidget->currentDatabaseWidget()) - switch(dbWidget->currentMode()) { - case DatabaseWidget::None: - case DatabaseWidget::LockedMode: - break; - - case DatabaseWidget::ViewMode: - case DatabaseWidget::EditMode: - return true; - default: - break; - } - return false; -} - -bool Service::openDatabase() -{ - if (!HttpSettings::unlockDatabase()) - return false; - if (DatabaseWidget * dbWidget = m_dbTabWidget->currentDatabaseWidget()) { - switch(dbWidget->currentMode()) { - case DatabaseWidget::None: - case DatabaseWidget::LockedMode: - break; - - case DatabaseWidget::ViewMode: - case DatabaseWidget::EditMode: - return true; - default: - break; - } - } - //if (HttpSettings::showNotification() - // && !ShowNotification(QString("%0: %1 is requesting access, click to allow or deny") - // .arg(id).arg(submitHost.isEmpty() ? host : submithost)); - // return false; - m_dbTabWidget->activateWindow(); - //Wait a bit for DB to be open... (w/ asynchronous reply?) - return false; -} - -QString Service::getDatabaseRootUuid() -{ - if (DatabaseWidget* dbWidget = m_dbTabWidget->currentDatabaseWidget()) - if (Database* db = dbWidget->database()) - if (Group* rootGroup = db->rootGroup()) - return rootGroup->uuid().toHex(); - return QString(); -} - -QString Service::getDatabaseRecycleBinUuid() -{ - if (DatabaseWidget* dbWidget = m_dbTabWidget->currentDatabaseWidget()) - if (Database* db = dbWidget->database()) - if (Group* recycleBin = db->metadata()->recycleBin()) - return recycleBin->uuid().toHex(); - return QString(); -} - -QString Service::getKey(const QString &id) -{ - if (Entry* config = getConfigEntry()) - return config->attributes()->value(QLatin1String(ASSOCIATE_KEY_PREFIX) + id); - return QString(); -} - -QString Service::storeKey(const QString &key) -{ - QString id; - if (Entry* config = getConfigEntry(true)) { - - //ShowNotification("New key association requested") - - do { - bool ok; - //Indicate who wants to associate, and request user to enter the 'name' of association key - id = QInputDialog::getText(0, - tr("KeePassXC: New key association request"), - tr("You have received an association " - "request for the above key.\n" - "If you would like to allow it access " - "to your KeePassXC database\n" - "give it a unique name to identify and accept it."), - QLineEdit::Normal, QString(), &ok); - if (!ok || id.isEmpty()) - return QString(); - - //Warn if association key already exists - } while(config->attributes()->contains(QLatin1String(ASSOCIATE_KEY_PREFIX) + id) && - QMessageBox::warning(0, tr("KeePassXC: Overwrite existing key?"), - tr("A shared encryption-key with the name \"%1\" already exists.\nDo you want to overwrite it?").arg(id), - QMessageBox::Yes | QMessageBox::No) == QMessageBox::No); - - config->attributes()->set(QLatin1String(ASSOCIATE_KEY_PREFIX) + id, key, true); - } - return id; -} - -bool Service::matchUrlScheme(const QString & url) -{ - QString str = url.left(8).toLower(); - return str.startsWith("http://") || - str.startsWith("https://") || - str.startsWith("ftp://") || - str.startsWith("ftps://"); -} - -bool Service::removeFirstDomain(QString & hostname) -{ - int pos = hostname.indexOf("."); - if (pos < 0) - return false; - hostname = hostname.mid(pos + 1); - return !hostname.isEmpty(); -} - -QList Service::searchEntries(Database* db, const QString& hostname) -{ - QList entries; - if (Group* rootGroup = db->rootGroup()) { - const auto results = EntrySearcher().search(hostname, rootGroup, Qt::CaseInsensitive); - for (Entry* entry: results) { - QString title = entry->title(); - QString url = entry->webUrl(); - - //Filter to match hostname in Title and Url fields - if ( (!title.isEmpty() && hostname.contains(title)) - || (!url.isEmpty() && hostname.contains(url)) - || (matchUrlScheme(title) && hostname.endsWith(QUrl(title).host())) - || (matchUrlScheme(url) && hostname.endsWith(QUrl(url).host())) ) - entries.append(entry); - } - } - return entries; -} - -QList Service::searchEntries(const QString& text) -{ - //Get the list of databases to search - QList databases; - if (HttpSettings::searchInAllDatabases()) { - for (int i = 0; i < m_dbTabWidget->count(); i++) - if (DatabaseWidget* dbWidget = qobject_cast(m_dbTabWidget->widget(i))) - if (Database* db = dbWidget->database()) - databases << db; - } - else if (DatabaseWidget* dbWidget = m_dbTabWidget->currentDatabaseWidget()) { - if (Database* db = dbWidget->database()) - databases << db; - } - - //Search entries matching the hostname - QString hostname = QUrl(text).host(); - QList entries; - do { - for (Database* db: asConst(databases)) { - entries << searchEntries(db, hostname); - } - } while(entries.isEmpty() && removeFirstDomain(hostname)); - - return entries; -} - -Service::Access Service::checkAccess(const Entry *entry, const QString & host, const QString & submitHost, const QString & realm) -{ - EntryConfig config; - if (!config.load(entry)) - return Unknown; //not configured - if ((config.isAllowed(host)) && (submitHost.isEmpty() || config.isAllowed(submitHost))) - return Allowed; //allowed - if ((config.isDenied(host)) || (!submitHost.isEmpty() && config.isDenied(submitHost))) - return Denied; //denied - if (!realm.isEmpty() && config.realm() != realm) - return Denied; - return Unknown; //not configured for this host -} - -KeepassHttpProtocol::Entry Service::prepareEntry(const Entry* entry) -{ - KeepassHttpProtocol::Entry res(entry->resolveMultiplePlaceholders(entry->title()), - entry->resolveMultiplePlaceholders(entry->username()), - entry->resolveMultiplePlaceholders(entry->password()), - entry->uuid().toHex()); - if (HttpSettings::supportKphFields()) { - const EntryAttributes * attr = entry->attributes(); - const auto keys = attr->keys(); - for (const QString& key: keys) { - if (key.startsWith(QLatin1String("KPH: "))) { - res.addStringField(key, entry->resolveMultiplePlaceholders(attr->value(key))); - } - } - } - return res; -} - -int Service::sortPriority(const Entry* entry, const QString& host, const QString& submitUrl, const QString& baseSubmitUrl) const -{ - QUrl url(entry->url()); - if (url.scheme().isEmpty()) - url.setScheme("http"); - const QString entryURL = url.toString(QUrl::StripTrailingSlash); - const QString baseEntryURL = url.toString(QUrl::StripTrailingSlash | QUrl::RemovePath | QUrl::RemoveQuery | QUrl::RemoveFragment); - - if (submitUrl == entryURL) - return 100; - if (submitUrl.startsWith(entryURL) && entryURL != host && baseSubmitUrl != entryURL) - return 90; - if (submitUrl.startsWith(baseEntryURL) && entryURL != host && baseSubmitUrl != baseEntryURL) - return 80; - if (entryURL == host) - return 70; - if (entryURL == baseSubmitUrl) - return 60; - if (entryURL.startsWith(submitUrl)) - return 50; - if (entryURL.startsWith(baseSubmitUrl) && baseSubmitUrl != host) - return 40; - if (submitUrl.startsWith(entryURL)) - return 30; - if (submitUrl.startsWith(baseEntryURL)) - return 20; - if (entryURL.startsWith(host)) - return 10; - if (host.startsWith(entryURL)) - return 5; - return 0; -} - -class Service::SortEntries -{ -public: - SortEntries(const QHash& priorities, const QString & field): - m_priorities(priorities), m_field(field) - {} - - bool operator()(const Entry* left, const Entry* right) const - { - int res = m_priorities.value(left) - m_priorities.value(right); - if (res == 0) - return QString::localeAwareCompare(left->attributes()->value(m_field), right->attributes()->value(m_field)) < 0; - return res < 0; - } - -private: - const QHash& m_priorities; - const QString m_field; -}; - -QList Service::findMatchingEntries(const QString& /*id*/, const QString& url, const QString& submitUrl, const QString& realm) -{ - const bool alwaysAllowAccess = HttpSettings::alwaysAllowAccess(); - const QString host = QUrl(url).host(); - const QString submitHost = QUrl(submitUrl).host(); - - //Check entries for authorization - QList pwEntriesToConfirm; - QList pwEntries; - const auto entries = searchEntries(url); - for (Entry* entry: entries) { - switch(checkAccess(entry, host, submitHost, realm)) { - case Denied: - continue; - - case Unknown: - if (alwaysAllowAccess) - pwEntries.append(entry); - else - pwEntriesToConfirm.append(entry); - break; - - case Allowed: - pwEntries.append(entry); - break; - } - } - - //If unsure, ask user for confirmation - //if (!pwEntriesToConfirm.isEmpty() - // && HttpSettings::showNotification() - // && !ShowNotification(QString("%0: %1 is requesting access, click to allow or deny") - // .arg(id).arg(submitHost.isEmpty() ? host : submithost)); - // pwEntriesToConfirm.clear(); //timeout --> do not request confirmation - - if (!pwEntriesToConfirm.isEmpty()) { - - AccessControlDialog dlg; - dlg.setUrl(url); - dlg.setItems(pwEntriesToConfirm); - //dlg.setRemember(); //TODO: setting! - - int res = dlg.exec(); - if (dlg.remember()) { - for (Entry* entry: asConst(pwEntriesToConfirm)) { - EntryConfig config; - config.load(entry); - if (res == QDialog::Accepted) { - config.allow(host); - if (!submitHost.isEmpty() && host != submitHost) - config.allow(submitHost); - } else if (res == QDialog::Rejected) { - config.deny(host); - if (!submitHost.isEmpty() && host != submitHost) - config.deny(submitHost); - } - if (!realm.isEmpty()) - config.setRealm(realm); - config.save(entry); - } - } - if (res == QDialog::Accepted) - pwEntries.append(pwEntriesToConfirm); - } - - //Sort results - const bool sortSelection = true; - if (sortSelection) { - QUrl url(submitUrl); - if (url.scheme().isEmpty()) - url.setScheme("http"); - const QString submitUrl = url.toString(QUrl::StripTrailingSlash); - const QString baseSubmitURL = url.toString(QUrl::StripTrailingSlash | QUrl::RemovePath | QUrl::RemoveQuery | QUrl::RemoveFragment); - - //Cache priorities - QHash priorities; - priorities.reserve(pwEntries.size()); - for (const Entry* entry: asConst(pwEntries)) { - priorities.insert(entry, sortPriority(entry, host, submitUrl, baseSubmitURL)); - } - - //Sort by priorities - std::sort(pwEntries.begin(), pwEntries.end(), SortEntries(priorities, HttpSettings::sortByTitle() ? "Title" : "UserName")); - } - - //Fill the list - QList result; - result.reserve(pwEntries.count()); - for (Entry* entry: asConst(pwEntries)) { - result << prepareEntry(entry); - } - return result; -} - -int Service::countMatchingEntries(const QString &, const QString &url, const QString &, const QString &) -{ - return searchEntries(url).count(); -} - -QList Service::searchAllEntries(const QString &) -{ - QList result; - if (DatabaseWidget* dbWidget = m_dbTabWidget->currentDatabaseWidget()) { - if (Database* db = dbWidget->database()) { - if (Group* rootGroup = db->rootGroup()) { - const auto entries = rootGroup->entriesRecursive(); - for (Entry* entry: entries) { - if (!entry->url().isEmpty() || QUrl(entry->title()).isValid()) { - result << KeepassHttpProtocol::Entry(entry->title(), entry->username(), - QString(), entry->uuid().toHex()); - } - } - } - } - } - return result; -} - -Group * Service::findCreateAddEntryGroup() -{ - if (DatabaseWidget * dbWidget = m_dbTabWidget->currentDatabaseWidget()) - if (Database * db = dbWidget->database()) - if (Group * rootGroup = db->rootGroup()) { - //TODO: setting to decide where new keys are created - const QString groupName = QLatin1String(KEEPASSHTTP_GROUP_NAME); - - const auto groups = rootGroup->groupsRecursive(true); - for (const Group * g: groups) { - if (g->name() == groupName) { - return db->resolveGroup(g->uuid()); - } - } - - Group * group; - group = new Group(); - group->setUuid(Uuid::random()); - group->setName(groupName); - group->setIcon(KEEPASSHTTP_DEFAULT_ICON); - group->setParent(rootGroup); - return group; - } - return NULL; -} - -void Service::addEntry(const QString &, const QString &login, const QString &password, const QString &url, const QString &submitUrl, const QString &realm) -{ - if (Group * group = findCreateAddEntryGroup()) { - Entry * entry = new Entry(); - entry->setUuid(Uuid::random()); - entry->setTitle(QUrl(url).host()); - entry->setUrl(url); - entry->setIcon(KEEPASSHTTP_DEFAULT_ICON); - entry->setUsername(login); - entry->setPassword(password); - entry->setGroup(group); - - const QString host = QUrl(url).host(); - const QString submitHost = QUrl(submitUrl).host(); - EntryConfig config; - config.allow(host); - if (!submitHost.isEmpty()) - config.allow(submitHost); - if (!realm.isEmpty()) - config.setRealm(realm); - config.save(entry); - } -} - -void Service::updateEntry(const QString &, const QString &uuid, const QString &login, const QString &password, const QString &url) -{ - if (DatabaseWidget * dbWidget = m_dbTabWidget->currentDatabaseWidget()) - if (Database * db = dbWidget->database()) - if (Entry * entry = db->resolveEntry(Uuid::fromHex(uuid))) { - QString u = entry->username(); - if (u != login || entry->password() != password) { - //ShowNotification(QString("%0: You have an entry change prompt waiting, click to activate").arg(requestId)); - if ( HttpSettings::alwaysAllowUpdate() - || QMessageBox::warning(0, tr("KeePassXC: Update Entry"), - tr("Do you want to update the information in %1 - %2?") - .arg(QUrl(url).host().toHtmlEscaped()).arg(u.toHtmlEscaped()), - QMessageBox::Yes|QMessageBox::No) == QMessageBox::Yes ) { - entry->beginUpdate(); - entry->setUsername(login); - entry->setPassword(password); - entry->endUpdate(); - } - } - } -} - -QString Service::generatePassword() -{ - return HttpSettings::generatePassword(); -} - -void Service::removeSharedEncryptionKeys() -{ - if (!isDatabaseOpened()) { - QMessageBox::critical(0, tr("KeePassXC: Database locked!"), - tr("The active database is locked!\n" - "Please unlock the selected database or choose another one which is unlocked."), - QMessageBox::Ok); - } else if (Entry* entry = getConfigEntry()) { - QStringList keysToRemove; - const auto keys = entry->attributes()->keys(); - for (const QString& key: keys) { - if (key.startsWith(ASSOCIATE_KEY_PREFIX)) { - keysToRemove << key; - } - } - - if(keysToRemove.count()) { - entry->beginUpdate(); - for (const QString& key: asConst(keysToRemove)) { - entry->attributes()->remove(key); - } - entry->endUpdate(); - - const int count = keysToRemove.count(); - QMessageBox::information(0, tr("KeePassXC: Removed keys from database"), - tr("Successfully removed %n encryption-key(s) from KeePassX/Http Settings.", "", count), - QMessageBox::Ok); - } else { - QMessageBox::information(0, tr("KeePassXC: No keys found"), - tr("No shared encryption-keys found in KeePassHttp Settings."), - QMessageBox::Ok); - } - } else { - QMessageBox::information(0, tr("KeePassXC: Settings not available!"), - tr("The active database does not contain an entry of KeePassHttp Settings."), - QMessageBox::Ok); - } -} - -void Service::removeStoredPermissions() -{ - if (!isDatabaseOpened()) { - QMessageBox::critical(0, tr("KeePassXC: Database locked!"), - tr("The active database is locked!\n" - "Please unlock the selected database or choose another one which is unlocked."), - QMessageBox::Ok); - } else { - Database * db = m_dbTabWidget->currentDatabaseWidget()->database(); - QList entries = db->rootGroup()->entriesRecursive(); - - QProgressDialog progress(tr("Removing stored permissions..."), tr("Abort"), 0, entries.count()); - progress.setWindowModality(Qt::WindowModal); - - uint counter = 0; - for (Entry* entry: asConst(entries)) { - if (progress.wasCanceled()) - return; - if (entry->attributes()->contains(KEEPASSHTTP_NAME)) { - entry->beginUpdate(); - entry->attributes()->remove(KEEPASSHTTP_NAME); - entry->endUpdate(); - counter ++; - } - progress.setValue(progress.value() + 1); - } - progress.reset(); - - if (counter > 0) { - QMessageBox::information(0, tr("KeePassXC: Removed permissions"), - tr("Successfully removed permissions from %n entries.", "", counter), - QMessageBox::Ok); - } else { - QMessageBox::information(0, tr("KeePassXC: No entry with permissions found!"), - tr("The active database does not contain an entry with permissions."), - QMessageBox::Ok); - } - } -} diff --git a/src/http/Service.h b/src/http/Service.h deleted file mode 100644 index d60d884b..00000000 --- a/src/http/Service.h +++ /dev/null @@ -1,66 +0,0 @@ -/* -* Copyright (C) 2013 Francois Ferrand -* Copyright (C) 2017 KeePassXC Team -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 2 or (at your option) -* version 3 of the License. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -*/ - -#ifndef SERVICE_H -#define SERVICE_H - -#include -#include "gui/DatabaseTabWidget.h" -#include "Server.h" - -class Service : public KeepassHttpProtocol::Server -{ - Q_OBJECT - -public: - explicit Service(DatabaseTabWidget* parent = 0); - - virtual bool isDatabaseOpened() const; - virtual bool openDatabase(); - virtual QString getDatabaseRootUuid(); - virtual QString getDatabaseRecycleBinUuid(); - virtual QString getKey(const QString& id); - virtual QString storeKey(const QString& key); - virtual QList findMatchingEntries(const QString& id, const QString& url, const QString& submitUrl, const QString& realm); - virtual int countMatchingEntries(const QString& id, const QString& url, const QString& submitUrl, const QString& realm); - virtual QList searchAllEntries(const QString& id); - virtual void addEntry(const QString& id, const QString& login, const QString& password, const QString& url, const QString& submitUrl, const QString& realm); - virtual void updateEntry(const QString& id, const QString& uuid, const QString& login, const QString& password, const QString& url); - virtual QString generatePassword(); - -public slots: - void removeSharedEncryptionKeys(); - void removeStoredPermissions(); - -private: - enum Access { Denied, Unknown, Allowed}; - Entry* getConfigEntry(bool create = false); - bool matchUrlScheme(const QString& url); - Access checkAccess(const Entry* entry, const QString& host, const QString& submitHost, const QString& realm); - bool removeFirstDomain(QString& hostname); - Group *findCreateAddEntryGroup(); - class SortEntries; - int sortPriority(const Entry *entry, const QString &host, const QString &submitUrl, const QString &baseSubmitUrl) const; - KeepassHttpProtocol::Entry prepareEntry(const Entry* entry); - QList searchEntries(Database* db, const QString& hostname); - QList searchEntries(const QString& text); - - DatabaseTabWidget * const m_dbTabWidget; -}; - -#endif // SERVICE_H diff --git a/src/http/qhttp/CMakeLists.txt b/src/http/qhttp/CMakeLists.txt deleted file mode 100644 index 3b4965b3..00000000 --- a/src/http/qhttp/CMakeLists.txt +++ /dev/null @@ -1,18 +0,0 @@ -project(qhttp) - -set(qhttp_SOURCES - qhttpabstracts.cpp - qhttpserverconnection.cpp - qhttpserverrequest.cpp - qhttpserverresponse.cpp - qhttpserver.cpp - qhttpclientrequest.cpp - qhttpclientresponse.cpp - qhttpclient.cpp - http-parser/http_parser.c -) - -add_library(qhttp STATIC ${qhttp_SOURCES}) -target_compile_definitions(qhttp PUBLIC QHTTP_MEMORY_LOG=0 QHTTP_EXPORT) -target_include_directories(qhttp PRIVATE .) -target_link_libraries(qhttp Qt5::Core Qt5::Network) \ No newline at end of file diff --git a/src/http/qhttp/LICENSE b/src/http/qhttp/LICENSE deleted file mode 100644 index a7d9ae47..00000000 --- a/src/http/qhttp/LICENSE +++ /dev/null @@ -1,22 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2014 Amir Zamani - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - diff --git a/src/http/qhttp/README.md b/src/http/qhttp/README.md deleted file mode 100644 index a359c2ff..00000000 --- a/src/http/qhttp/README.md +++ /dev/null @@ -1,229 +0,0 @@ -# QHttp - - -### Table of contents -- [About](#about) -- [Sample codes](#sample-codes) -- [Features](#features) -- [Setup](#setup) -- [Multi-threading](#multi-threading) -- [Source tree](#source-tree) -- [Disclaimer](#disclaimer) -- [License](#license) - -## About -[TOC](#table-of-contents) - -`QHttp` is a lightweight, asynchronous and fast HTTP library, containing both server and client side classes for managing connections, parsing and building HTTP requests and responses. this project is inspired by [nikhilm/qhttpserver](https://github.com/nikhilm/qhttpserver) effort to implement a Qt HTTP server. `QHttp` pushes the idea further by implementing client classes and better memory management, a lot more Node.js-like API, ... - -* the fantastic [nodejs/http-parser](https://github.com/nodejs/http-parser) is the core parser of HTTP requests (server mode) and responses (client mode). - -* By using `std::function` and `c++11 lambda`, the API is intentionally similar to the [Node.js' http module](http://nodejs.org/api/http.html). Asynchronous and non-blocking HTTP programming is quite easy with `QHttp`. have a look at [sample codes](#sample-codes). - -* the objective of `QHttp` is being light weight with a simple API for Qt developers to implement RESTful web services in private (internal) zones. [more](#disclaimer) - - - -## Sample codes -[TOC](#table-of-contents) - -a HelloWorld **HTTP server** by `QHttp` looks like: -``` cpp -int main(int argc, char** argv) { - QCoreApplication app(argc, argv); - - using namespace qhttp::server; - QHttpServer server(&app); - // listening on 0.0.0.0:8080 - server.listen(QHostAddress::Any, 8080, [](QHttpRequest* req, QHttpResponse* res) { - - res->setStatusCode(qhttp::ESTATUS_OK); // http status 200 - //res->addHeader("connection", "close"); // optional, it's the default header - res->end("Hello World!\n"); // the response body data - // by "connection: close", the req and res objects will be deleted automatically. - }); - - if ( !server.isListening() ) { - fprintf(stderr, "failed. can not listen at port 8080!\n"); - return -1; - } - - return app.exec(); -} -``` - -to request weather information by **HTTP client**: -```cpp -int main(int argc, char** argv) { - QCoreApplication app(argc, argv); - - using namespace qhttp::client; - QHttpClient client(&app); - QByteArray httpBody; - - QUrl weatherUrl("http://api.openweathermap.org/data/2.5/weather?q=tehran,ir&units=metric&mode=xml"); - - client.request(qhttp::EHTTP_GET, weatherUrl, [&httpBody](QHttpResponse* res) { - // response handler, called when the HTTP headers of the response are ready - - // gather HTTP response data - res->onData([&httpBody](const QByteArray& chunk) { - httpBody.append(chunk); - }); - - // called when all data in HTTP response have been read. - res->onEnd([&httpBody]() { - // print the XML body of the response - puts("\n[incoming response:]"); - puts(httpBody.constData()); - puts("\n\n"); - - QCoreApplication::instance()->quit(); - }); - - // just for fun! print incoming headers: - puts("\n[Headers:]"); - const qhttp::THeaderHash& hs = res->headers(); - for ( auto cit = hs.constBegin(); cit != hs.constEnd(); cit++) { - printf("%s : %s\n", cit.key().constData(), cit.value().constData()); - } - }); - - // set a timeout for making the request - client.setConnectingTimeOut(10000, []{ - qDebug("connecting to HTTP server timed out!"); - QCoreApplication::quit(); - }); - - - return app.exec(); -} -``` - - -## Features -[TOC](#table-of-contents) - -* the only dependencies are: [Qt 5](http://qt-project.org/downloads), [c++11](http://en.wikipedia.org/wiki/C%2B%2B11) and [joyent/http-parser](https://github.com/joyent/http-parser) - -* both TCP and UNIX (local) sockets are supported as backend. - -* separate `namespace`s for server and client classes. - -* HTTP server classes: [QHttpServer](./src/qhttpserver.hpp), [QHttpConnection](./src/qhttpserverconnection.hpp), [QHttpRequest](./src/qhttpserverrequest.hpp) and [QHttpResponse](./src/qhttpserverresponse.hpp). - -* HTTP client classes: [QHttpClient](./src/qhttpclient.hpp), [QHttpRequest](./src/qhttpclientrequest.hpp) and [QHttpResponse](./src/qhttpclientresponse.hpp). - -* **automatic memory management** of objects. Instances of connections, requests and replies will be deleted automatically when socket drops or disconnected. - -* **PIMPL** (Private classes) to achieve better ABI compatibility and cleaner API. - -* **Asynchronous** and **non-blocking**. You can handle thousands of concurrent HTTP connections efficiently by a single thread, although a multi-threaded HTTP server is easy to implement. - -* **high throughput**, I have tried the `QHttp` and [gason++](https://github.com/azadkuh/gason--) to implement a REST/Json web service on an Ubuntu VPS (dual core + 512MB ram) with more than **5800** connections per second (stress test). On a MacBook Pro (i5 4258U 4cores with HT + 8096MB ram), `QHttp` easily reaches to more than **11700** connections / second. Generally `QHttp` is **1.5x ~ 3x** faster than `Node.js` depending on your machine / OS. check [benchmark app](./example/benchmard/README.md) to measure your system. - -* Tested under **Linux** (Ubuntu 12.04 LTS, 14.04 LTS, g++) and **OS X** (10.9/10.10/10.11, clang). Easily portable where ever Qt 5 works. (tested by some users on Windows7/msvc2013 and Windows8.1/msvc2015) - - -## Setup -[TOC](#table-of-contents) - -instructions: -```bash -# first clone this repository: -$> git clone --depth=1 https://github.com/azadkuh/qhttp.git -b master -$> cd qhttp - -# prepare dependencies: -$> ./update-dependencies.sh - -# now build the library and the examples -$> qmake qhttp.pro -$> make -j 8 -``` - -## Multi-threading -[TOC](#table-of-contents) - -As `QHttp` is **asynchronous** and **non-blocking**, your app can handle thousands of concurrent HTTP connections by a single thread. - -in some rare scenarios you may want to use multiple handler threads (although it's not the best solution): - -* there are some blocking APIs (QSql, system calls, ...) in your connection handler (adopting asynchronous layer over the blocking API is a better approach). - -* the hardware has lots of free cores and the measurement shows that the load on the main `QHttp` thread is close to highest limit. There you can spawn some other handler threads. - - -[benchmark example](./example/benchmark/README.md) shows how to implement a single or multi threaded HTTP app (both server and client). This example uses worker `QThread` and `QObject::moveToThread()` for worker objects. see also: [Subclassing no longer recommended way of using QThread](http://qt-project.org/doc/note_revisions/5/8/view). - -**Note**: -> moving objects between threads is an expensive job, more ever the locking/unlocking mechanism, creating or stopping threads, ... cost even more! so using multiple threads in an application is not guaranteed to get better performance, but it's guaranteed to add more complexity, nasty bugs and headache! - -see why other top performer networking libraries as ZeroMQ are concurrent but not multi-threaded by default: - -* [ZeroMQ : Multithreading Magic](http://zeromq.org/blog:multithreading-magic) -* [Node.js : about](http://nodejs.org/about/) - - -## Source tree -[TOC](#table-of-contents) - - -* **`3rdparty/`**: -will contain `http-parser` source tree as the only dependency. -this directory is created by setup. see also: [setup](#setup). - -* **`example/`**: -contains some sample applications representing the `QHttp` usage: - * **`helloworld/`**: - the HelloWorld example of `QHttp`, both server + client are represented. - see: [README@helloworld](./example/helloworld/README.md) - - * **`basic-server/`**: - a basic HTTP server shows how to collect the request body, and respond to the clients. - see: [README@basic-server](./example/basic-server/README.md) - - - * **`benchmark/`**: - a simple utility to measure the throughput (requests per second) of `QHttp` as a REST/Json server. this app provides both the server and attacking clients. - see: [README@benchmark](./example/benchmark/README.md) - - * **`nodejs/`**: - Node.js implementation of `benchmark/` in server mode. Provided for benchmarking `QHttp` with `Node.js` as a RESTFul service app. - see: [README@nodejs](./example/nodejs/README.md) - - -* **`src/`**: -holds the source code of `QHttp`. server classes are prefixed by `qhttpserver*` and client classes by `qhttpclient*`. - * **`private/`**: - Private classes of the library. see: [d-pointers](https://qt-project.org/wiki/Dpointer). - -* **`tmp/`**: -a temporary directory which is created while `make`ing the library and holds all the `.o`, `moc files`, etc. - -* **`xbin/`**: -all the executable and binaries will be placed on this folder by `make`. - - - - -## Disclaimer -[TOC](#table-of-contents) - -* Implementing a lightweight and simple HTTP server/client in Qt with Node.js like API, is the main purpose of `QHttp`. - -* There are lots of features in a full blown HTTP server which are out of scope of this small library, although those can be added on top of `QHttp`. - -* The client classes are by no mean designed as a `QNetworkAccessManager` replacement. `QHttpClient` is simpler and lighter, for serious scenarios just use `QNetworkAccessManager`. - -* I'm a busy person. - - -> If you have any ideas, critiques, suggestions or whatever you want to call it, please open an issue. I'll be happy to hear from you what you'd see in this lib. I think about all suggestions, and I try to add those that make sense. - - -## License -[TOC](#table-of-contents) - -Distributed under the MIT license. Copyright (c) 2014, Amir Zamani. - diff --git a/src/http/qhttp/http-parser/LICENSE-MIT b/src/http/qhttp/http-parser/LICENSE-MIT deleted file mode 100644 index 58010b38..00000000 --- a/src/http/qhttp/http-parser/LICENSE-MIT +++ /dev/null @@ -1,23 +0,0 @@ -http_parser.c is based on src/http/ngx_http_parse.c from NGINX copyright -Igor Sysoev. - -Additional changes are licensed under the same terms as NGINX and -copyright Joyent, Inc. and other Node contributors. All rights reserved. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to -deal in the Software without restriction, including without limitation the -rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -sell copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -IN THE SOFTWARE. diff --git a/src/http/qhttp/http-parser/README.md b/src/http/qhttp/http-parser/README.md deleted file mode 100644 index 439b3099..00000000 --- a/src/http/qhttp/http-parser/README.md +++ /dev/null @@ -1,246 +0,0 @@ -HTTP Parser -=========== - -[![Build Status](https://api.travis-ci.org/nodejs/http-parser.svg?branch=master)](https://travis-ci.org/nodejs/http-parser) - -This is a parser for HTTP messages written in C. It parses both requests and -responses. The parser is designed to be used in performance HTTP -applications. It does not make any syscalls nor allocations, it does not -buffer data, it can be interrupted at anytime. Depending on your -architecture, it only requires about 40 bytes of data per message -stream (in a web server that is per connection). - -Features: - - * No dependencies - * Handles persistent streams (keep-alive). - * Decodes chunked encoding. - * Upgrade support - * Defends against buffer overflow attacks. - -The parser extracts the following information from HTTP messages: - - * Header fields and values - * Content-Length - * Request method - * Response status code - * Transfer-Encoding - * HTTP version - * Request URL - * Message body - - -Usage ------ - -One `http_parser` object is used per TCP connection. Initialize the struct -using `http_parser_init()` and set the callbacks. That might look something -like this for a request parser: -```c -http_parser_settings settings; -settings.on_url = my_url_callback; -settings.on_header_field = my_header_field_callback; -/* ... */ - -http_parser *parser = malloc(sizeof(http_parser)); -http_parser_init(parser, HTTP_REQUEST); -parser->data = my_socket; -``` - -When data is received on the socket execute the parser and check for errors. - -```c -size_t len = 80*1024, nparsed; -char buf[len]; -ssize_t recved; - -recved = recv(fd, buf, len, 0); - -if (recved < 0) { - /* Handle error. */ -} - -/* Start up / continue the parser. - * Note we pass recved==0 to signal that EOF has been received. - */ -nparsed = http_parser_execute(parser, &settings, buf, recved); - -if (parser->upgrade) { - /* handle new protocol */ -} else if (nparsed != recved) { - /* Handle error. Usually just close the connection. */ -} -``` - -HTTP needs to know where the end of the stream is. For example, sometimes -servers send responses without Content-Length and expect the client to -consume input (for the body) until EOF. To tell http_parser about EOF, give -`0` as the fourth parameter to `http_parser_execute()`. Callbacks and errors -can still be encountered during an EOF, so one must still be prepared -to receive them. - -Scalar valued message information such as `status_code`, `method`, and the -HTTP version are stored in the parser structure. This data is only -temporally stored in `http_parser` and gets reset on each new message. If -this information is needed later, copy it out of the structure during the -`headers_complete` callback. - -The parser decodes the transfer-encoding for both requests and responses -transparently. That is, a chunked encoding is decoded before being sent to -the on_body callback. - - -The Special Problem of Upgrade ------------------------------- - -HTTP supports upgrading the connection to a different protocol. An -increasingly common example of this is the WebSocket protocol which sends -a request like - - GET /demo HTTP/1.1 - Upgrade: WebSocket - Connection: Upgrade - Host: example.com - Origin: http://example.com - WebSocket-Protocol: sample - -followed by non-HTTP data. - -(See [RFC6455](https://tools.ietf.org/html/rfc6455) for more information the -WebSocket protocol.) - -To support this, the parser will treat this as a normal HTTP message without a -body, issuing both on_headers_complete and on_message_complete callbacks. However -http_parser_execute() will stop parsing at the end of the headers and return. - -The user is expected to check if `parser->upgrade` has been set to 1 after -`http_parser_execute()` returns. Non-HTTP data begins at the buffer supplied -offset by the return value of `http_parser_execute()`. - - -Callbacks ---------- - -During the `http_parser_execute()` call, the callbacks set in -`http_parser_settings` will be executed. The parser maintains state and -never looks behind, so buffering the data is not necessary. If you need to -save certain data for later usage, you can do that from the callbacks. - -There are two types of callbacks: - -* notification `typedef int (*http_cb) (http_parser*);` - Callbacks: on_message_begin, on_headers_complete, on_message_complete. -* data `typedef int (*http_data_cb) (http_parser*, const char *at, size_t length);` - Callbacks: (requests only) on_url, - (common) on_header_field, on_header_value, on_body; - -Callbacks must return 0 on success. Returning a non-zero value indicates -error to the parser, making it exit immediately. - -For cases where it is necessary to pass local information to/from a callback, -the `http_parser` object's `data` field can be used. -An example of such a case is when using threads to handle a socket connection, -parse a request, and then give a response over that socket. By instantiation -of a thread-local struct containing relevant data (e.g. accepted socket, -allocated memory for callbacks to write into, etc), a parser's callbacks are -able to communicate data between the scope of the thread and the scope of the -callback in a threadsafe manner. This allows http-parser to be used in -multi-threaded contexts. - -Example: -```c - typedef struct { - socket_t sock; - void* buffer; - int buf_len; - } custom_data_t; - - -int my_url_callback(http_parser* parser, const char *at, size_t length) { - /* access to thread local custom_data_t struct. - Use this access save parsed data for later use into thread local - buffer, or communicate over socket - */ - parser->data; - ... - return 0; -} - -... - -void http_parser_thread(socket_t sock) { - int nparsed = 0; - /* allocate memory for user data */ - custom_data_t *my_data = malloc(sizeof(custom_data_t)); - - /* some information for use by callbacks. - * achieves thread -> callback information flow */ - my_data->sock = sock; - - /* instantiate a thread-local parser */ - http_parser *parser = malloc(sizeof(http_parser)); - http_parser_init(parser, HTTP_REQUEST); /* initialise parser */ - /* this custom data reference is accessible through the reference to the - parser supplied to callback functions */ - parser->data = my_data; - - http_parser_settings settings; /* set up callbacks */ - settings.on_url = my_url_callback; - - /* execute parser */ - nparsed = http_parser_execute(parser, &settings, buf, recved); - - ... - /* parsed information copied from callback. - can now perform action on data copied into thread-local memory from callbacks. - achieves callback -> thread information flow */ - my_data->buffer; - ... -} - -``` - -In case you parse HTTP message in chunks (i.e. `read()` request line -from socket, parse, read half headers, parse, etc) your data callbacks -may be called more than once. Http-parser guarantees that data pointer is only -valid for the lifetime of callback. You can also `read()` into a heap allocated -buffer to avoid copying memory around if this fits your application. - -Reading headers may be a tricky task if you read/parse headers partially. -Basically, you need to remember whether last header callback was field or value -and apply the following logic: - - (on_header_field and on_header_value shortened to on_h_*) - ------------------------ ------------ -------------------------------------------- - | State (prev. callback) | Callback | Description/action | - ------------------------ ------------ -------------------------------------------- - | nothing (first call) | on_h_field | Allocate new buffer and copy callback data | - | | | into it | - ------------------------ ------------ -------------------------------------------- - | value | on_h_field | New header started. | - | | | Copy current name,value buffers to headers | - | | | list and allocate new buffer for new name | - ------------------------ ------------ -------------------------------------------- - | field | on_h_field | Previous name continues. Reallocate name | - | | | buffer and append callback data to it | - ------------------------ ------------ -------------------------------------------- - | field | on_h_value | Value for current header started. Allocate | - | | | new buffer and copy callback data to it | - ------------------------ ------------ -------------------------------------------- - | value | on_h_value | Value continues. Reallocate value buffer | - | | | and append callback data to it | - ------------------------ ------------ -------------------------------------------- - - -Parsing URLs ------------- - -A simplistic zero-copy URL parser is provided as `http_parser_parse_url()`. -Users of this library may wish to use it to parse URLs constructed from -consecutive `on_url` callbacks. - -See examples of reading in headers: - -* [partial example](http://gist.github.com/155877) in C -* [from http-parser tests](http://github.com/joyent/http-parser/blob/37a0ff8/test.c#L403) in C -* [from Node library](http://github.com/joyent/node/blob/842eaf4/src/http.js#L284) in Javascript diff --git a/src/http/qhttp/http-parser/http_parser.c b/src/http/qhttp/http-parser/http_parser.c deleted file mode 100644 index ab48d0cb..00000000 --- a/src/http/qhttp/http-parser/http_parser.c +++ /dev/null @@ -1,2476 +0,0 @@ -/* Based on src/http/ngx_http_parse.c from NGINX copyright Igor Sysoev - * - * Additional changes are licensed under the same terms as NGINX and - * copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ -#include "http_parser.h" -#include -#include -#include -#include -#include -#include - -#ifndef ULLONG_MAX -# define ULLONG_MAX ((uint64_t) -1) /* 2^64-1 */ -#endif - -#ifndef MIN -# define MIN(a,b) ((a) < (b) ? (a) : (b)) -#endif - -#ifndef ARRAY_SIZE -# define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) -#endif - -#ifndef BIT_AT -# define BIT_AT(a, i) \ - (!!((unsigned int) (a)[(unsigned int) (i) >> 3] & \ - (1 << ((unsigned int) (i) & 7)))) -#endif - -#ifndef ELEM_AT -# define ELEM_AT(a, i, v) ((unsigned int) (i) < ARRAY_SIZE(a) ? (a)[(i)] : (v)) -#endif - -#define SET_ERRNO(e) \ -do { \ - parser->http_errno = (e); \ -} while(0) - -#define CURRENT_STATE() p_state -#define UPDATE_STATE(V) p_state = (enum state) (V); -#define RETURN(V) \ -do { \ - parser->state = CURRENT_STATE(); \ - return (V); \ -} while (0); -#define REEXECUTE() \ - goto reexecute; \ - - -#ifdef __GNUC__ -# define LIKELY(X) __builtin_expect(!!(X), 1) -# define UNLIKELY(X) __builtin_expect(!!(X), 0) -#else -# define LIKELY(X) (X) -# define UNLIKELY(X) (X) -#endif - - -/* Run the notify callback FOR, returning ER if it fails */ -#define CALLBACK_NOTIFY_(FOR, ER) \ -do { \ - assert(HTTP_PARSER_ERRNO(parser) == HPE_OK); \ - \ - if (LIKELY(settings->on_##FOR)) { \ - parser->state = CURRENT_STATE(); \ - if (UNLIKELY(0 != settings->on_##FOR(parser))) { \ - SET_ERRNO(HPE_CB_##FOR); \ - } \ - UPDATE_STATE(parser->state); \ - \ - /* We either errored above or got paused; get out */ \ - if (UNLIKELY(HTTP_PARSER_ERRNO(parser) != HPE_OK)) { \ - return (ER); \ - } \ - } \ -} while (0) - -/* Run the notify callback FOR and consume the current byte */ -#define CALLBACK_NOTIFY(FOR) CALLBACK_NOTIFY_(FOR, p - data + 1) - -/* Run the notify callback FOR and don't consume the current byte */ -#define CALLBACK_NOTIFY_NOADVANCE(FOR) CALLBACK_NOTIFY_(FOR, p - data) - -/* Run data callback FOR with LEN bytes, returning ER if it fails */ -#define CALLBACK_DATA_(FOR, LEN, ER) \ -do { \ - assert(HTTP_PARSER_ERRNO(parser) == HPE_OK); \ - \ - if (FOR##_mark) { \ - if (LIKELY(settings->on_##FOR)) { \ - parser->state = CURRENT_STATE(); \ - if (UNLIKELY(0 != \ - settings->on_##FOR(parser, FOR##_mark, (LEN)))) { \ - SET_ERRNO(HPE_CB_##FOR); \ - } \ - UPDATE_STATE(parser->state); \ - \ - /* We either errored above or got paused; get out */ \ - if (UNLIKELY(HTTP_PARSER_ERRNO(parser) != HPE_OK)) { \ - return (ER); \ - } \ - } \ - FOR##_mark = NULL; \ - } \ -} while (0) - -/* Run the data callback FOR and consume the current byte */ -#define CALLBACK_DATA(FOR) \ - CALLBACK_DATA_(FOR, p - FOR##_mark, p - data + 1) - -/* Run the data callback FOR and don't consume the current byte */ -#define CALLBACK_DATA_NOADVANCE(FOR) \ - CALLBACK_DATA_(FOR, p - FOR##_mark, p - data) - -/* Set the mark FOR; non-destructive if mark is already set */ -#define MARK(FOR) \ -do { \ - if (!FOR##_mark) { \ - FOR##_mark = p; \ - } \ -} while (0) - -/* Don't allow the total size of the HTTP headers (including the status - * line) to exceed HTTP_MAX_HEADER_SIZE. This check is here to protect - * embedders against denial-of-service attacks where the attacker feeds - * us a never-ending header that the embedder keeps buffering. - * - * This check is arguably the responsibility of embedders but we're doing - * it on the embedder's behalf because most won't bother and this way we - * make the web a little safer. HTTP_MAX_HEADER_SIZE is still far bigger - * than any reasonable request or response so this should never affect - * day-to-day operation. - */ -#define COUNT_HEADER_SIZE(V) \ -do { \ - parser->nread += (V); \ - if (UNLIKELY(parser->nread > (HTTP_MAX_HEADER_SIZE))) { \ - SET_ERRNO(HPE_HEADER_OVERFLOW); \ - goto error; \ - } \ -} while (0) - - -#define PROXY_CONNECTION "proxy-connection" -#define CONNECTION "connection" -#define CONTENT_LENGTH "content-length" -#define TRANSFER_ENCODING "transfer-encoding" -#define UPGRADE "upgrade" -#define CHUNKED "chunked" -#define KEEP_ALIVE "keep-alive" -#define CLOSE "close" - - -static const char *method_strings[] = - { -#define XX(num, name, string) #string, - HTTP_METHOD_MAP(XX) -#undef XX - }; - - -/* Tokens as defined by rfc 2616. Also lowercases them. - * token = 1* - * separators = "(" | ")" | "<" | ">" | "@" - * | "," | ";" | ":" | "\" | <"> - * | "/" | "[" | "]" | "?" | "=" - * | "{" | "}" | SP | HT - */ -static const char tokens[256] = { -/* 0 nul 1 soh 2 stx 3 etx 4 eot 5 enq 6 ack 7 bel */ - 0, 0, 0, 0, 0, 0, 0, 0, -/* 8 bs 9 ht 10 nl 11 vt 12 np 13 cr 14 so 15 si */ - 0, 0, 0, 0, 0, 0, 0, 0, -/* 16 dle 17 dc1 18 dc2 19 dc3 20 dc4 21 nak 22 syn 23 etb */ - 0, 0, 0, 0, 0, 0, 0, 0, -/* 24 can 25 em 26 sub 27 esc 28 fs 29 gs 30 rs 31 us */ - 0, 0, 0, 0, 0, 0, 0, 0, -/* 32 sp 33 ! 34 " 35 # 36 $ 37 % 38 & 39 ' */ - 0, '!', 0, '#', '$', '%', '&', '\'', -/* 40 ( 41 ) 42 * 43 + 44 , 45 - 46 . 47 / */ - 0, 0, '*', '+', 0, '-', '.', 0, -/* 48 0 49 1 50 2 51 3 52 4 53 5 54 6 55 7 */ - '0', '1', '2', '3', '4', '5', '6', '7', -/* 56 8 57 9 58 : 59 ; 60 < 61 = 62 > 63 ? */ - '8', '9', 0, 0, 0, 0, 0, 0, -/* 64 @ 65 A 66 B 67 C 68 D 69 E 70 F 71 G */ - 0, 'a', 'b', 'c', 'd', 'e', 'f', 'g', -/* 72 H 73 I 74 J 75 K 76 L 77 M 78 N 79 O */ - 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', -/* 80 P 81 Q 82 R 83 S 84 T 85 U 86 V 87 W */ - 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', -/* 88 X 89 Y 90 Z 91 [ 92 \ 93 ] 94 ^ 95 _ */ - 'x', 'y', 'z', 0, 0, 0, '^', '_', -/* 96 ` 97 a 98 b 99 c 100 d 101 e 102 f 103 g */ - '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', -/* 104 h 105 i 106 j 107 k 108 l 109 m 110 n 111 o */ - 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', -/* 112 p 113 q 114 r 115 s 116 t 117 u 118 v 119 w */ - 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', -/* 120 x 121 y 122 z 123 { 124 | 125 } 126 ~ 127 del */ - 'x', 'y', 'z', 0, '|', 0, '~', 0 }; - - -static const int8_t unhex[256] = - {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 - ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 - ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 - , 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1 - ,-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1 - ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 - ,-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1 - ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 - }; - - -#if HTTP_PARSER_STRICT -# define T(v) 0 -#else -# define T(v) v -#endif - - -static const uint8_t normal_url_char[32] = { -/* 0 nul 1 soh 2 stx 3 etx 4 eot 5 enq 6 ack 7 bel */ - 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0, -/* 8 bs 9 ht 10 nl 11 vt 12 np 13 cr 14 so 15 si */ - 0 | T(2) | 0 | 0 | T(16) | 0 | 0 | 0, -/* 16 dle 17 dc1 18 dc2 19 dc3 20 dc4 21 nak 22 syn 23 etb */ - 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0, -/* 24 can 25 em 26 sub 27 esc 28 fs 29 gs 30 rs 31 us */ - 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0, -/* 32 sp 33 ! 34 " 35 # 36 $ 37 % 38 & 39 ' */ - 0 | 2 | 4 | 0 | 16 | 32 | 64 | 128, -/* 40 ( 41 ) 42 * 43 + 44 , 45 - 46 . 47 / */ - 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, -/* 48 0 49 1 50 2 51 3 52 4 53 5 54 6 55 7 */ - 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, -/* 56 8 57 9 58 : 59 ; 60 < 61 = 62 > 63 ? */ - 1 | 2 | 4 | 8 | 16 | 32 | 64 | 0, -/* 64 @ 65 A 66 B 67 C 68 D 69 E 70 F 71 G */ - 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, -/* 72 H 73 I 74 J 75 K 76 L 77 M 78 N 79 O */ - 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, -/* 80 P 81 Q 82 R 83 S 84 T 85 U 86 V 87 W */ - 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, -/* 88 X 89 Y 90 Z 91 [ 92 \ 93 ] 94 ^ 95 _ */ - 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, -/* 96 ` 97 a 98 b 99 c 100 d 101 e 102 f 103 g */ - 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, -/* 104 h 105 i 106 j 107 k 108 l 109 m 110 n 111 o */ - 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, -/* 112 p 113 q 114 r 115 s 116 t 117 u 118 v 119 w */ - 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, -/* 120 x 121 y 122 z 123 { 124 | 125 } 126 ~ 127 del */ - 1 | 2 | 4 | 8 | 16 | 32 | 64 | 0, }; - -#undef T - -enum state - { s_dead = 1 /* important that this is > 0 */ - - , s_start_req_or_res - , s_res_or_resp_H - , s_start_res - , s_res_H - , s_res_HT - , s_res_HTT - , s_res_HTTP - , s_res_first_http_major - , s_res_http_major - , s_res_first_http_minor - , s_res_http_minor - , s_res_first_status_code - , s_res_status_code - , s_res_status_start - , s_res_status - , s_res_line_almost_done - - , s_start_req - - , s_req_method - , s_req_spaces_before_url - , s_req_schema - , s_req_schema_slash - , s_req_schema_slash_slash - , s_req_server_start - , s_req_server - , s_req_server_with_at - , s_req_path - , s_req_query_string_start - , s_req_query_string - , s_req_fragment_start - , s_req_fragment - , s_req_http_start - , s_req_http_H - , s_req_http_HT - , s_req_http_HTT - , s_req_http_HTTP - , s_req_first_http_major - , s_req_http_major - , s_req_first_http_minor - , s_req_http_minor - , s_req_line_almost_done - - , s_header_field_start - , s_header_field - , s_header_value_discard_ws - , s_header_value_discard_ws_almost_done - , s_header_value_discard_lws - , s_header_value_start - , s_header_value - , s_header_value_lws - - , s_header_almost_done - - , s_chunk_size_start - , s_chunk_size - , s_chunk_parameters - , s_chunk_size_almost_done - - , s_headers_almost_done - , s_headers_done - - /* Important: 's_headers_done' must be the last 'header' state. All - * states beyond this must be 'body' states. It is used for overflow - * checking. See the PARSING_HEADER() macro. - */ - - , s_chunk_data - , s_chunk_data_almost_done - , s_chunk_data_done - - , s_body_identity - , s_body_identity_eof - - , s_message_done - }; - - -#define PARSING_HEADER(state) (state <= s_headers_done) - - -enum header_states - { h_general = 0 - , h_C - , h_CO - , h_CON - - , h_matching_connection - , h_matching_proxy_connection - , h_matching_content_length - , h_matching_transfer_encoding - , h_matching_upgrade - - , h_connection - , h_content_length - , h_transfer_encoding - , h_upgrade - - , h_matching_transfer_encoding_chunked - , h_matching_connection_token_start - , h_matching_connection_keep_alive - , h_matching_connection_close - , h_matching_connection_upgrade - , h_matching_connection_token - - , h_transfer_encoding_chunked - , h_connection_keep_alive - , h_connection_close - , h_connection_upgrade - }; - -enum http_host_state - { - s_http_host_dead = 1 - , s_http_userinfo_start - , s_http_userinfo - , s_http_host_start - , s_http_host_v6_start - , s_http_host - , s_http_host_v6 - , s_http_host_v6_end - , s_http_host_v6_zone_start - , s_http_host_v6_zone - , s_http_host_port_start - , s_http_host_port -}; - -/* Macros for character classes; depends on strict-mode */ -#define CR '\r' -#define LF '\n' -#define LOWER(c) (unsigned char)(c | 0x20) -#define IS_ALPHA(c) (LOWER(c) >= 'a' && LOWER(c) <= 'z') -#define IS_NUM(c) ((c) >= '0' && (c) <= '9') -#define IS_ALPHANUM(c) (IS_ALPHA(c) || IS_NUM(c)) -#define IS_HEX(c) (IS_NUM(c) || (LOWER(c) >= 'a' && LOWER(c) <= 'f')) -#define IS_MARK(c) ((c) == '-' || (c) == '_' || (c) == '.' || \ - (c) == '!' || (c) == '~' || (c) == '*' || (c) == '\'' || (c) == '(' || \ - (c) == ')') -#define IS_USERINFO_CHAR(c) (IS_ALPHANUM(c) || IS_MARK(c) || (c) == '%' || \ - (c) == ';' || (c) == ':' || (c) == '&' || (c) == '=' || (c) == '+' || \ - (c) == '$' || (c) == ',') - -#define STRICT_TOKEN(c) (tokens[(unsigned char)c]) - -#if HTTP_PARSER_STRICT -#define TOKEN(c) (tokens[(unsigned char)c]) -#define IS_URL_CHAR(c) (BIT_AT(normal_url_char, (unsigned char)c)) -#define IS_HOST_CHAR(c) (IS_ALPHANUM(c) || (c) == '.' || (c) == '-') -#else -#define TOKEN(c) ((c == ' ') ? ' ' : tokens[(unsigned char)c]) -#define IS_URL_CHAR(c) \ - (BIT_AT(normal_url_char, (unsigned char)c) || ((c) & 0x80)) -#define IS_HOST_CHAR(c) \ - (IS_ALPHANUM(c) || (c) == '.' || (c) == '-' || (c) == '_') -#endif - -/** - * Verify that a char is a valid visible (printable) US-ASCII - * character or %x80-FF - **/ -#define IS_HEADER_CHAR(ch) \ - (ch == CR || ch == LF || ch == 9 || ((unsigned char)ch > 31 && ch != 127)) - -#define start_state (parser->type == HTTP_REQUEST ? s_start_req : s_start_res) - - -#if HTTP_PARSER_STRICT -# define STRICT_CHECK(cond) \ -do { \ - if (cond) { \ - SET_ERRNO(HPE_STRICT); \ - goto error; \ - } \ -} while (0) -# define NEW_MESSAGE() (http_should_keep_alive(parser) ? start_state : s_dead) -#else -# define STRICT_CHECK(cond) -# define NEW_MESSAGE() start_state -#endif - - -/* Map errno values to strings for human-readable output */ -#define HTTP_STRERROR_GEN(n, s) { "HPE_" #n, s }, -static struct { - const char *name; - const char *description; -} http_strerror_tab[] = { - HTTP_ERRNO_MAP(HTTP_STRERROR_GEN) -}; -#undef HTTP_STRERROR_GEN - -int http_message_needs_eof(const http_parser *parser); - -/* Our URL parser. - * - * This is designed to be shared by http_parser_execute() for URL validation, - * hence it has a state transition + byte-for-byte interface. In addition, it - * is meant to be embedded in http_parser_parse_url(), which does the dirty - * work of turning state transitions URL components for its API. - * - * This function should only be invoked with non-space characters. It is - * assumed that the caller cares about (and can detect) the transition between - * URL and non-URL states by looking for these. - */ -static enum state -parse_url_char(enum state s, const char ch) -{ - if (ch == ' ' || ch == '\r' || ch == '\n') { - return s_dead; - } - -#if HTTP_PARSER_STRICT - if (ch == '\t' || ch == '\f') { - return s_dead; - } -#endif - - switch (s) { - case s_req_spaces_before_url: - /* Proxied requests are followed by scheme of an absolute URI (alpha). - * All methods except CONNECT are followed by '/' or '*'. - */ - - if (ch == '/' || ch == '*') { - return s_req_path; - } - - if (IS_ALPHA(ch)) { - return s_req_schema; - } - - break; - - case s_req_schema: - if (IS_ALPHA(ch)) { - return s; - } - - if (ch == ':') { - return s_req_schema_slash; - } - - break; - - case s_req_schema_slash: - if (ch == '/') { - return s_req_schema_slash_slash; - } - - break; - - case s_req_schema_slash_slash: - if (ch == '/') { - return s_req_server_start; - } - - break; - - case s_req_server_with_at: - if (ch == '@') { - return s_dead; - } - - /* FALLTHROUGH */ - case s_req_server_start: - case s_req_server: - if (ch == '/') { - return s_req_path; - } - - if (ch == '?') { - return s_req_query_string_start; - } - - if (ch == '@') { - return s_req_server_with_at; - } - - if (IS_USERINFO_CHAR(ch) || ch == '[' || ch == ']') { - return s_req_server; - } - - break; - - case s_req_path: - if (IS_URL_CHAR(ch)) { - return s; - } - - switch (ch) { - case '?': - return s_req_query_string_start; - - case '#': - return s_req_fragment_start; - } - - break; - - case s_req_query_string_start: - case s_req_query_string: - if (IS_URL_CHAR(ch)) { - return s_req_query_string; - } - - switch (ch) { - case '?': - /* allow extra '?' in query string */ - return s_req_query_string; - - case '#': - return s_req_fragment_start; - } - - break; - - case s_req_fragment_start: - if (IS_URL_CHAR(ch)) { - return s_req_fragment; - } - - switch (ch) { - case '?': - return s_req_fragment; - - case '#': - return s; - } - - break; - - case s_req_fragment: - if (IS_URL_CHAR(ch)) { - return s; - } - - switch (ch) { - case '?': - case '#': - return s; - } - - break; - - default: - break; - } - - /* We should never fall out of the switch above unless there's an error */ - return s_dead; -} - -size_t http_parser_execute (http_parser *parser, - const http_parser_settings *settings, - const char *data, - size_t len) -{ - char c, ch; - int8_t unhex_val; - const char *p = data; - const char *header_field_mark = 0; - const char *header_value_mark = 0; - const char *url_mark = 0; - const char *body_mark = 0; - const char *status_mark = 0; - enum state p_state = (enum state) parser->state; - const unsigned int lenient = parser->lenient_http_headers; - - /* We're in an error state. Don't bother doing anything. */ - if (HTTP_PARSER_ERRNO(parser) != HPE_OK) { - return 0; - } - - if (len == 0) { - switch (CURRENT_STATE()) { - case s_body_identity_eof: - /* Use of CALLBACK_NOTIFY() here would erroneously return 1 byte read if - * we got paused. - */ - CALLBACK_NOTIFY_NOADVANCE(message_complete); - return 0; - - case s_dead: - case s_start_req_or_res: - case s_start_res: - case s_start_req: - return 0; - - default: - SET_ERRNO(HPE_INVALID_EOF_STATE); - return 1; - } - } - - - if (CURRENT_STATE() == s_header_field) - header_field_mark = data; - if (CURRENT_STATE() == s_header_value) - header_value_mark = data; - switch (CURRENT_STATE()) { - case s_req_path: - case s_req_schema: - case s_req_schema_slash: - case s_req_schema_slash_slash: - case s_req_server_start: - case s_req_server: - case s_req_server_with_at: - case s_req_query_string_start: - case s_req_query_string: - case s_req_fragment_start: - case s_req_fragment: - url_mark = data; - break; - case s_res_status: - status_mark = data; - break; - default: - break; - } - - for (p=data; p != data + len; p++) { - ch = *p; - - if (PARSING_HEADER(CURRENT_STATE())) - COUNT_HEADER_SIZE(1); - -reexecute: - switch (CURRENT_STATE()) { - - case s_dead: - /* this state is used after a 'Connection: close' message - * the parser will error out if it reads another message - */ - if (LIKELY(ch == CR || ch == LF)) - break; - - SET_ERRNO(HPE_CLOSED_CONNECTION); - goto error; - - case s_start_req_or_res: - { - if (ch == CR || ch == LF) - break; - parser->flags = 0; - parser->content_length = ULLONG_MAX; - - if (ch == 'H') { - UPDATE_STATE(s_res_or_resp_H); - - CALLBACK_NOTIFY(message_begin); - } else { - parser->type = HTTP_REQUEST; - UPDATE_STATE(s_start_req); - REEXECUTE(); - } - - break; - } - - case s_res_or_resp_H: - if (ch == 'T') { - parser->type = HTTP_RESPONSE; - UPDATE_STATE(s_res_HT); - } else { - if (UNLIKELY(ch != 'E')) { - SET_ERRNO(HPE_INVALID_CONSTANT); - goto error; - } - - parser->type = HTTP_REQUEST; - parser->method = HTTP_HEAD; - parser->index = 2; - UPDATE_STATE(s_req_method); - } - break; - - case s_start_res: - { - parser->flags = 0; - parser->content_length = ULLONG_MAX; - - switch (ch) { - case 'H': - UPDATE_STATE(s_res_H); - break; - - case CR: - case LF: - break; - - default: - SET_ERRNO(HPE_INVALID_CONSTANT); - goto error; - } - - CALLBACK_NOTIFY(message_begin); - break; - } - - case s_res_H: - STRICT_CHECK(ch != 'T'); - UPDATE_STATE(s_res_HT); - break; - - case s_res_HT: - STRICT_CHECK(ch != 'T'); - UPDATE_STATE(s_res_HTT); - break; - - case s_res_HTT: - STRICT_CHECK(ch != 'P'); - UPDATE_STATE(s_res_HTTP); - break; - - case s_res_HTTP: - STRICT_CHECK(ch != '/'); - UPDATE_STATE(s_res_first_http_major); - break; - - case s_res_first_http_major: - if (UNLIKELY(ch < '0' || ch > '9')) { - SET_ERRNO(HPE_INVALID_VERSION); - goto error; - } - - parser->http_major = ch - '0'; - UPDATE_STATE(s_res_http_major); - break; - - /* major HTTP version or dot */ - case s_res_http_major: - { - if (ch == '.') { - UPDATE_STATE(s_res_first_http_minor); - break; - } - - if (!IS_NUM(ch)) { - SET_ERRNO(HPE_INVALID_VERSION); - goto error; - } - - parser->http_major *= 10; - parser->http_major += ch - '0'; - - if (UNLIKELY(parser->http_major > 999)) { - SET_ERRNO(HPE_INVALID_VERSION); - goto error; - } - - break; - } - - /* first digit of minor HTTP version */ - case s_res_first_http_minor: - if (UNLIKELY(!IS_NUM(ch))) { - SET_ERRNO(HPE_INVALID_VERSION); - goto error; - } - - parser->http_minor = ch - '0'; - UPDATE_STATE(s_res_http_minor); - break; - - /* minor HTTP version or end of request line */ - case s_res_http_minor: - { - if (ch == ' ') { - UPDATE_STATE(s_res_first_status_code); - break; - } - - if (UNLIKELY(!IS_NUM(ch))) { - SET_ERRNO(HPE_INVALID_VERSION); - goto error; - } - - parser->http_minor *= 10; - parser->http_minor += ch - '0'; - - if (UNLIKELY(parser->http_minor > 999)) { - SET_ERRNO(HPE_INVALID_VERSION); - goto error; - } - - break; - } - - case s_res_first_status_code: - { - if (!IS_NUM(ch)) { - if (ch == ' ') { - break; - } - - SET_ERRNO(HPE_INVALID_STATUS); - goto error; - } - parser->status_code = ch - '0'; - UPDATE_STATE(s_res_status_code); - break; - } - - case s_res_status_code: - { - if (!IS_NUM(ch)) { - switch (ch) { - case ' ': - UPDATE_STATE(s_res_status_start); - break; - case CR: - UPDATE_STATE(s_res_line_almost_done); - break; - case LF: - UPDATE_STATE(s_header_field_start); - break; - default: - SET_ERRNO(HPE_INVALID_STATUS); - goto error; - } - break; - } - - parser->status_code *= 10; - parser->status_code += ch - '0'; - - if (UNLIKELY(parser->status_code > 999)) { - SET_ERRNO(HPE_INVALID_STATUS); - goto error; - } - - break; - } - - case s_res_status_start: - { - if (ch == CR) { - UPDATE_STATE(s_res_line_almost_done); - break; - } - - if (ch == LF) { - UPDATE_STATE(s_header_field_start); - break; - } - - MARK(status); - UPDATE_STATE(s_res_status); - parser->index = 0; - break; - } - - case s_res_status: - if (ch == CR) { - UPDATE_STATE(s_res_line_almost_done); - CALLBACK_DATA(status); - break; - } - - if (ch == LF) { - UPDATE_STATE(s_header_field_start); - CALLBACK_DATA(status); - break; - } - - break; - - case s_res_line_almost_done: - STRICT_CHECK(ch != LF); - UPDATE_STATE(s_header_field_start); - break; - - case s_start_req: - { - if (ch == CR || ch == LF) - break; - parser->flags = 0; - parser->content_length = ULLONG_MAX; - - if (UNLIKELY(!IS_ALPHA(ch))) { - SET_ERRNO(HPE_INVALID_METHOD); - goto error; - } - - parser->method = (enum http_method) 0; - parser->index = 1; - switch (ch) { - case 'A': parser->method = HTTP_ACL; break; - case 'B': parser->method = HTTP_BIND; break; - case 'C': parser->method = HTTP_CONNECT; /* or COPY, CHECKOUT */ break; - case 'D': parser->method = HTTP_DELETE; break; - case 'G': parser->method = HTTP_GET; break; - case 'H': parser->method = HTTP_HEAD; break; - case 'L': parser->method = HTTP_LOCK; /* or LINK */ break; - case 'M': parser->method = HTTP_MKCOL; /* or MOVE, MKACTIVITY, MERGE, M-SEARCH, MKCALENDAR */ break; - case 'N': parser->method = HTTP_NOTIFY; break; - case 'O': parser->method = HTTP_OPTIONS; break; - case 'P': parser->method = HTTP_POST; - /* or PROPFIND|PROPPATCH|PUT|PATCH|PURGE */ - break; - case 'R': parser->method = HTTP_REPORT; /* or REBIND */ break; - case 'S': parser->method = HTTP_SUBSCRIBE; /* or SEARCH */ break; - case 'T': parser->method = HTTP_TRACE; break; - case 'U': parser->method = HTTP_UNLOCK; /* or UNSUBSCRIBE, UNBIND, UNLINK */ break; - default: - SET_ERRNO(HPE_INVALID_METHOD); - goto error; - } - UPDATE_STATE(s_req_method); - - CALLBACK_NOTIFY(message_begin); - - break; - } - - case s_req_method: - { - const char *matcher; - if (UNLIKELY(ch == '\0')) { - SET_ERRNO(HPE_INVALID_METHOD); - goto error; - } - - matcher = method_strings[parser->method]; - if (ch == ' ' && matcher[parser->index] == '\0') { - UPDATE_STATE(s_req_spaces_before_url); - } else if (ch == matcher[parser->index]) { - ; /* nada */ - } else if (IS_ALPHA(ch)) { - - switch (parser->method << 16 | parser->index << 8 | ch) { -#define XX(meth, pos, ch, new_meth) \ - case (HTTP_##meth << 16 | pos << 8 | ch): \ - parser->method = HTTP_##new_meth; break; - - XX(POST, 1, 'U', PUT) - XX(POST, 1, 'A', PATCH) - XX(CONNECT, 1, 'H', CHECKOUT) - XX(CONNECT, 2, 'P', COPY) - XX(MKCOL, 1, 'O', MOVE) - XX(MKCOL, 1, 'E', MERGE) - XX(MKCOL, 2, 'A', MKACTIVITY) - XX(MKCOL, 3, 'A', MKCALENDAR) - XX(SUBSCRIBE, 1, 'E', SEARCH) - XX(REPORT, 2, 'B', REBIND) - XX(POST, 1, 'R', PROPFIND) - XX(PROPFIND, 4, 'P', PROPPATCH) - XX(PUT, 2, 'R', PURGE) - XX(LOCK, 1, 'I', LINK) - XX(UNLOCK, 2, 'S', UNSUBSCRIBE) - XX(UNLOCK, 2, 'B', UNBIND) - XX(UNLOCK, 3, 'I', UNLINK) -#undef XX - - default: - SET_ERRNO(HPE_INVALID_METHOD); - goto error; - } - } else if (ch == '-' && - parser->index == 1 && - parser->method == HTTP_MKCOL) { - parser->method = HTTP_MSEARCH; - } else { - SET_ERRNO(HPE_INVALID_METHOD); - goto error; - } - - ++parser->index; - break; - } - - case s_req_spaces_before_url: - { - if (ch == ' ') break; - - MARK(url); - if (parser->method == HTTP_CONNECT) { - UPDATE_STATE(s_req_server_start); - } - - UPDATE_STATE(parse_url_char(CURRENT_STATE(), ch)); - if (UNLIKELY(CURRENT_STATE() == s_dead)) { - SET_ERRNO(HPE_INVALID_URL); - goto error; - } - - break; - } - - case s_req_schema: - case s_req_schema_slash: - case s_req_schema_slash_slash: - case s_req_server_start: - { - switch (ch) { - /* No whitespace allowed here */ - case ' ': - case CR: - case LF: - SET_ERRNO(HPE_INVALID_URL); - goto error; - default: - UPDATE_STATE(parse_url_char(CURRENT_STATE(), ch)); - if (UNLIKELY(CURRENT_STATE() == s_dead)) { - SET_ERRNO(HPE_INVALID_URL); - goto error; - } - } - - break; - } - - case s_req_server: - case s_req_server_with_at: - case s_req_path: - case s_req_query_string_start: - case s_req_query_string: - case s_req_fragment_start: - case s_req_fragment: - { - switch (ch) { - case ' ': - UPDATE_STATE(s_req_http_start); - CALLBACK_DATA(url); - break; - case CR: - case LF: - parser->http_major = 0; - parser->http_minor = 9; - UPDATE_STATE((ch == CR) ? - s_req_line_almost_done : - s_header_field_start); - CALLBACK_DATA(url); - break; - default: - UPDATE_STATE(parse_url_char(CURRENT_STATE(), ch)); - if (UNLIKELY(CURRENT_STATE() == s_dead)) { - SET_ERRNO(HPE_INVALID_URL); - goto error; - } - } - break; - } - - case s_req_http_start: - switch (ch) { - case 'H': - UPDATE_STATE(s_req_http_H); - break; - case ' ': - break; - default: - SET_ERRNO(HPE_INVALID_CONSTANT); - goto error; - } - break; - - case s_req_http_H: - STRICT_CHECK(ch != 'T'); - UPDATE_STATE(s_req_http_HT); - break; - - case s_req_http_HT: - STRICT_CHECK(ch != 'T'); - UPDATE_STATE(s_req_http_HTT); - break; - - case s_req_http_HTT: - STRICT_CHECK(ch != 'P'); - UPDATE_STATE(s_req_http_HTTP); - break; - - case s_req_http_HTTP: - STRICT_CHECK(ch != '/'); - UPDATE_STATE(s_req_first_http_major); - break; - - /* first digit of major HTTP version */ - case s_req_first_http_major: - if (UNLIKELY(ch < '1' || ch > '9')) { - SET_ERRNO(HPE_INVALID_VERSION); - goto error; - } - - parser->http_major = ch - '0'; - UPDATE_STATE(s_req_http_major); - break; - - /* major HTTP version or dot */ - case s_req_http_major: - { - if (ch == '.') { - UPDATE_STATE(s_req_first_http_minor); - break; - } - - if (UNLIKELY(!IS_NUM(ch))) { - SET_ERRNO(HPE_INVALID_VERSION); - goto error; - } - - parser->http_major *= 10; - parser->http_major += ch - '0'; - - if (UNLIKELY(parser->http_major > 999)) { - SET_ERRNO(HPE_INVALID_VERSION); - goto error; - } - - break; - } - - /* first digit of minor HTTP version */ - case s_req_first_http_minor: - if (UNLIKELY(!IS_NUM(ch))) { - SET_ERRNO(HPE_INVALID_VERSION); - goto error; - } - - parser->http_minor = ch - '0'; - UPDATE_STATE(s_req_http_minor); - break; - - /* minor HTTP version or end of request line */ - case s_req_http_minor: - { - if (ch == CR) { - UPDATE_STATE(s_req_line_almost_done); - break; - } - - if (ch == LF) { - UPDATE_STATE(s_header_field_start); - break; - } - - /* XXX allow spaces after digit? */ - - if (UNLIKELY(!IS_NUM(ch))) { - SET_ERRNO(HPE_INVALID_VERSION); - goto error; - } - - parser->http_minor *= 10; - parser->http_minor += ch - '0'; - - if (UNLIKELY(parser->http_minor > 999)) { - SET_ERRNO(HPE_INVALID_VERSION); - goto error; - } - - break; - } - - /* end of request line */ - case s_req_line_almost_done: - { - if (UNLIKELY(ch != LF)) { - SET_ERRNO(HPE_LF_EXPECTED); - goto error; - } - - UPDATE_STATE(s_header_field_start); - break; - } - - case s_header_field_start: - { - if (ch == CR) { - UPDATE_STATE(s_headers_almost_done); - break; - } - - if (ch == LF) { - /* they might be just sending \n instead of \r\n so this would be - * the second \n to denote the end of headers*/ - UPDATE_STATE(s_headers_almost_done); - REEXECUTE(); - } - - c = TOKEN(ch); - - if (UNLIKELY(!c)) { - SET_ERRNO(HPE_INVALID_HEADER_TOKEN); - goto error; - } - - MARK(header_field); - - parser->index = 0; - UPDATE_STATE(s_header_field); - - switch (c) { - case 'c': - parser->header_state = h_C; - break; - - case 'p': - parser->header_state = h_matching_proxy_connection; - break; - - case 't': - parser->header_state = h_matching_transfer_encoding; - break; - - case 'u': - parser->header_state = h_matching_upgrade; - break; - - default: - parser->header_state = h_general; - break; - } - break; - } - - case s_header_field: - { - const char* start = p; - for (; p != data + len; p++) { - ch = *p; - c = TOKEN(ch); - - if (!c) - break; - - switch (parser->header_state) { - case h_general: - break; - - case h_C: - parser->index++; - parser->header_state = (c == 'o' ? h_CO : h_general); - break; - - case h_CO: - parser->index++; - parser->header_state = (c == 'n' ? h_CON : h_general); - break; - - case h_CON: - parser->index++; - switch (c) { - case 'n': - parser->header_state = h_matching_connection; - break; - case 't': - parser->header_state = h_matching_content_length; - break; - default: - parser->header_state = h_general; - break; - } - break; - - /* connection */ - - case h_matching_connection: - parser->index++; - if (parser->index > sizeof(CONNECTION)-1 - || c != CONNECTION[parser->index]) { - parser->header_state = h_general; - } else if (parser->index == sizeof(CONNECTION)-2) { - parser->header_state = h_connection; - } - break; - - /* proxy-connection */ - - case h_matching_proxy_connection: - parser->index++; - if (parser->index > sizeof(PROXY_CONNECTION)-1 - || c != PROXY_CONNECTION[parser->index]) { - parser->header_state = h_general; - } else if (parser->index == sizeof(PROXY_CONNECTION)-2) { - parser->header_state = h_connection; - } - break; - - /* content-length */ - - case h_matching_content_length: - parser->index++; - if (parser->index > sizeof(CONTENT_LENGTH)-1 - || c != CONTENT_LENGTH[parser->index]) { - parser->header_state = h_general; - } else if (parser->index == sizeof(CONTENT_LENGTH)-2) { - parser->header_state = h_content_length; - } - break; - - /* transfer-encoding */ - - case h_matching_transfer_encoding: - parser->index++; - if (parser->index > sizeof(TRANSFER_ENCODING)-1 - || c != TRANSFER_ENCODING[parser->index]) { - parser->header_state = h_general; - } else if (parser->index == sizeof(TRANSFER_ENCODING)-2) { - parser->header_state = h_transfer_encoding; - } - break; - - /* upgrade */ - - case h_matching_upgrade: - parser->index++; - if (parser->index > sizeof(UPGRADE)-1 - || c != UPGRADE[parser->index]) { - parser->header_state = h_general; - } else if (parser->index == sizeof(UPGRADE)-2) { - parser->header_state = h_upgrade; - } - break; - - case h_connection: - case h_content_length: - case h_transfer_encoding: - case h_upgrade: - if (ch != ' ') parser->header_state = h_general; - break; - - default: - assert(0 && "Unknown header_state"); - break; - } - } - - COUNT_HEADER_SIZE(p - start); - - if (p == data + len) { - --p; - break; - } - - if (ch == ':') { - UPDATE_STATE(s_header_value_discard_ws); - CALLBACK_DATA(header_field); - break; - } - - SET_ERRNO(HPE_INVALID_HEADER_TOKEN); - goto error; - } - - case s_header_value_discard_ws: - if (ch == ' ' || ch == '\t') break; - - if (ch == CR) { - UPDATE_STATE(s_header_value_discard_ws_almost_done); - break; - } - - if (ch == LF) { - UPDATE_STATE(s_header_value_discard_lws); - break; - } - - /* FALLTHROUGH */ - - case s_header_value_start: - { - MARK(header_value); - - UPDATE_STATE(s_header_value); - parser->index = 0; - - c = LOWER(ch); - - switch (parser->header_state) { - case h_upgrade: - parser->flags |= F_UPGRADE; - parser->header_state = h_general; - break; - - case h_transfer_encoding: - /* looking for 'Transfer-Encoding: chunked' */ - if ('c' == c) { - parser->header_state = h_matching_transfer_encoding_chunked; - } else { - parser->header_state = h_general; - } - break; - - case h_content_length: - if (UNLIKELY(!IS_NUM(ch))) { - SET_ERRNO(HPE_INVALID_CONTENT_LENGTH); - goto error; - } - - if (parser->flags & F_CONTENTLENGTH) { - SET_ERRNO(HPE_UNEXPECTED_CONTENT_LENGTH); - goto error; - } - - parser->flags |= F_CONTENTLENGTH; - parser->content_length = ch - '0'; - break; - - case h_connection: - /* looking for 'Connection: keep-alive' */ - if (c == 'k') { - parser->header_state = h_matching_connection_keep_alive; - /* looking for 'Connection: close' */ - } else if (c == 'c') { - parser->header_state = h_matching_connection_close; - } else if (c == 'u') { - parser->header_state = h_matching_connection_upgrade; - } else { - parser->header_state = h_matching_connection_token; - } - break; - - /* Multi-value `Connection` header */ - case h_matching_connection_token_start: - break; - - default: - parser->header_state = h_general; - break; - } - break; - } - - case s_header_value: - { - const char* start = p; - enum header_states h_state = (enum header_states) parser->header_state; - for (; p != data + len; p++) { - ch = *p; - if (ch == CR) { - UPDATE_STATE(s_header_almost_done); - parser->header_state = h_state; - CALLBACK_DATA(header_value); - break; - } - - if (ch == LF) { - UPDATE_STATE(s_header_almost_done); - COUNT_HEADER_SIZE(p - start); - parser->header_state = h_state; - CALLBACK_DATA_NOADVANCE(header_value); - REEXECUTE(); - } - - if (!lenient && !IS_HEADER_CHAR(ch)) { - SET_ERRNO(HPE_INVALID_HEADER_TOKEN); - goto error; - } - - c = LOWER(ch); - - switch (h_state) { - case h_general: - { - const char* p_cr; - const char* p_lf; - size_t limit = data + len - p; - - limit = MIN(limit, HTTP_MAX_HEADER_SIZE); - - p_cr = (const char*) memchr(p, CR, limit); - p_lf = (const char*) memchr(p, LF, limit); - if (p_cr != NULL) { - if (p_lf != NULL && p_cr >= p_lf) - p = p_lf; - else - p = p_cr; - } else if (UNLIKELY(p_lf != NULL)) { - p = p_lf; - } else { - p = data + len; - } - --p; - - break; - } - - case h_connection: - case h_transfer_encoding: - assert(0 && "Shouldn't get here."); - break; - - case h_content_length: - { - uint64_t t; - - if (ch == ' ') break; - - if (UNLIKELY(!IS_NUM(ch))) { - SET_ERRNO(HPE_INVALID_CONTENT_LENGTH); - parser->header_state = h_state; - goto error; - } - - t = parser->content_length; - t *= 10; - t += ch - '0'; - - /* Overflow? Test against a conservative limit for simplicity. */ - if (UNLIKELY((ULLONG_MAX - 10) / 10 < parser->content_length)) { - SET_ERRNO(HPE_INVALID_CONTENT_LENGTH); - parser->header_state = h_state; - goto error; - } - - parser->content_length = t; - break; - } - - /* Transfer-Encoding: chunked */ - case h_matching_transfer_encoding_chunked: - parser->index++; - if (parser->index > sizeof(CHUNKED)-1 - || c != CHUNKED[parser->index]) { - h_state = h_general; - } else if (parser->index == sizeof(CHUNKED)-2) { - h_state = h_transfer_encoding_chunked; - } - break; - - case h_matching_connection_token_start: - /* looking for 'Connection: keep-alive' */ - if (c == 'k') { - h_state = h_matching_connection_keep_alive; - /* looking for 'Connection: close' */ - } else if (c == 'c') { - h_state = h_matching_connection_close; - } else if (c == 'u') { - h_state = h_matching_connection_upgrade; - } else if (STRICT_TOKEN(c)) { - h_state = h_matching_connection_token; - } else if (c == ' ' || c == '\t') { - /* Skip lws */ - } else { - h_state = h_general; - } - break; - - /* looking for 'Connection: keep-alive' */ - case h_matching_connection_keep_alive: - parser->index++; - if (parser->index > sizeof(KEEP_ALIVE)-1 - || c != KEEP_ALIVE[parser->index]) { - h_state = h_matching_connection_token; - } else if (parser->index == sizeof(KEEP_ALIVE)-2) { - h_state = h_connection_keep_alive; - } - break; - - /* looking for 'Connection: close' */ - case h_matching_connection_close: - parser->index++; - if (parser->index > sizeof(CLOSE)-1 || c != CLOSE[parser->index]) { - h_state = h_matching_connection_token; - } else if (parser->index == sizeof(CLOSE)-2) { - h_state = h_connection_close; - } - break; - - /* looking for 'Connection: upgrade' */ - case h_matching_connection_upgrade: - parser->index++; - if (parser->index > sizeof(UPGRADE) - 1 || - c != UPGRADE[parser->index]) { - h_state = h_matching_connection_token; - } else if (parser->index == sizeof(UPGRADE)-2) { - h_state = h_connection_upgrade; - } - break; - - case h_matching_connection_token: - if (ch == ',') { - h_state = h_matching_connection_token_start; - parser->index = 0; - } - break; - - case h_transfer_encoding_chunked: - if (ch != ' ') h_state = h_general; - break; - - case h_connection_keep_alive: - case h_connection_close: - case h_connection_upgrade: - if (ch == ',') { - if (h_state == h_connection_keep_alive) { - parser->flags |= F_CONNECTION_KEEP_ALIVE; - } else if (h_state == h_connection_close) { - parser->flags |= F_CONNECTION_CLOSE; - } else if (h_state == h_connection_upgrade) { - parser->flags |= F_CONNECTION_UPGRADE; - } - h_state = h_matching_connection_token_start; - parser->index = 0; - } else if (ch != ' ') { - h_state = h_matching_connection_token; - } - break; - - default: - UPDATE_STATE(s_header_value); - h_state = h_general; - break; - } - } - parser->header_state = h_state; - - COUNT_HEADER_SIZE(p - start); - - if (p == data + len) - --p; - break; - } - - case s_header_almost_done: - { - if (UNLIKELY(ch != LF)) { - SET_ERRNO(HPE_LF_EXPECTED); - goto error; - } - - UPDATE_STATE(s_header_value_lws); - break; - } - - case s_header_value_lws: - { - if (ch == ' ' || ch == '\t') { - UPDATE_STATE(s_header_value_start); - REEXECUTE(); - } - - /* finished the header */ - switch (parser->header_state) { - case h_connection_keep_alive: - parser->flags |= F_CONNECTION_KEEP_ALIVE; - break; - case h_connection_close: - parser->flags |= F_CONNECTION_CLOSE; - break; - case h_transfer_encoding_chunked: - parser->flags |= F_CHUNKED; - break; - case h_connection_upgrade: - parser->flags |= F_CONNECTION_UPGRADE; - break; - default: - break; - } - - UPDATE_STATE(s_header_field_start); - REEXECUTE(); - } - - case s_header_value_discard_ws_almost_done: - { - STRICT_CHECK(ch != LF); - UPDATE_STATE(s_header_value_discard_lws); - break; - } - - case s_header_value_discard_lws: - { - if (ch == ' ' || ch == '\t') { - UPDATE_STATE(s_header_value_discard_ws); - break; - } else { - switch (parser->header_state) { - case h_connection_keep_alive: - parser->flags |= F_CONNECTION_KEEP_ALIVE; - break; - case h_connection_close: - parser->flags |= F_CONNECTION_CLOSE; - break; - case h_connection_upgrade: - parser->flags |= F_CONNECTION_UPGRADE; - break; - case h_transfer_encoding_chunked: - parser->flags |= F_CHUNKED; - break; - default: - break; - } - - /* header value was empty */ - MARK(header_value); - UPDATE_STATE(s_header_field_start); - CALLBACK_DATA_NOADVANCE(header_value); - REEXECUTE(); - } - } - - case s_headers_almost_done: - { - STRICT_CHECK(ch != LF); - - if (parser->flags & F_TRAILING) { - /* End of a chunked request */ - UPDATE_STATE(s_message_done); - CALLBACK_NOTIFY_NOADVANCE(chunk_complete); - REEXECUTE(); - } - - /* Cannot use chunked encoding and a content-length header together - per the HTTP specification. */ - if ((parser->flags & F_CHUNKED) && - (parser->flags & F_CONTENTLENGTH)) { - SET_ERRNO(HPE_UNEXPECTED_CONTENT_LENGTH); - goto error; - } - - UPDATE_STATE(s_headers_done); - - /* Set this here so that on_headers_complete() callbacks can see it */ - parser->upgrade = - ((parser->flags & (F_UPGRADE | F_CONNECTION_UPGRADE)) == - (F_UPGRADE | F_CONNECTION_UPGRADE) || - parser->method == HTTP_CONNECT); - - /* Here we call the headers_complete callback. This is somewhat - * different than other callbacks because if the user returns 1, we - * will interpret that as saying that this message has no body. This - * is needed for the annoying case of recieving a response to a HEAD - * request. - * - * We'd like to use CALLBACK_NOTIFY_NOADVANCE() here but we cannot, so - * we have to simulate it by handling a change in errno below. - */ - if (settings->on_headers_complete) { - switch (settings->on_headers_complete(parser)) { - case 0: - break; - - case 2: - parser->upgrade = 1; -#if __GNUC__ >= 7 - __attribute__ ((fallthrough)); -#endif - - case 1: - parser->flags |= F_SKIPBODY; - break; - - default: - SET_ERRNO(HPE_CB_headers_complete); - RETURN(p - data); /* Error */ - } - } - - if (HTTP_PARSER_ERRNO(parser) != HPE_OK) { - RETURN(p - data); - } - - REEXECUTE(); - } - - case s_headers_done: - { - int hasBody; - STRICT_CHECK(ch != LF); - - parser->nread = 0; - - hasBody = parser->flags & F_CHUNKED || - (parser->content_length > 0 && parser->content_length != ULLONG_MAX); - if (parser->upgrade && (parser->method == HTTP_CONNECT || - (parser->flags & F_SKIPBODY) || !hasBody)) { - /* Exit, the rest of the message is in a different protocol. */ - UPDATE_STATE(NEW_MESSAGE()); - CALLBACK_NOTIFY(message_complete); - RETURN((p - data) + 1); - } - - if (parser->flags & F_SKIPBODY) { - UPDATE_STATE(NEW_MESSAGE()); - CALLBACK_NOTIFY(message_complete); - } else if (parser->flags & F_CHUNKED) { - /* chunked encoding - ignore Content-Length header */ - UPDATE_STATE(s_chunk_size_start); - } else { - if (parser->content_length == 0) { - /* Content-Length header given but zero: Content-Length: 0\r\n */ - UPDATE_STATE(NEW_MESSAGE()); - CALLBACK_NOTIFY(message_complete); - } else if (parser->content_length != ULLONG_MAX) { - /* Content-Length header given and non-zero */ - UPDATE_STATE(s_body_identity); - } else { - if (!http_message_needs_eof(parser)) { - /* Assume content-length 0 - read the next */ - UPDATE_STATE(NEW_MESSAGE()); - CALLBACK_NOTIFY(message_complete); - } else { - /* Read body until EOF */ - UPDATE_STATE(s_body_identity_eof); - } - } - } - - break; - } - - case s_body_identity: - { - uint64_t to_read = MIN(parser->content_length, - (uint64_t) ((data + len) - p)); - - assert(parser->content_length != 0 - && parser->content_length != ULLONG_MAX); - - /* The difference between advancing content_length and p is because - * the latter will automaticaly advance on the next loop iteration. - * Further, if content_length ends up at 0, we want to see the last - * byte again for our message complete callback. - */ - MARK(body); - parser->content_length -= to_read; - p += to_read - 1; - - if (parser->content_length == 0) { - UPDATE_STATE(s_message_done); - - /* Mimic CALLBACK_DATA_NOADVANCE() but with one extra byte. - * - * The alternative to doing this is to wait for the next byte to - * trigger the data callback, just as in every other case. The - * problem with this is that this makes it difficult for the test - * harness to distinguish between complete-on-EOF and - * complete-on-length. It's not clear that this distinction is - * important for applications, but let's keep it for now. - */ - CALLBACK_DATA_(body, p - body_mark + 1, p - data); - REEXECUTE(); - } - - break; - } - - /* read until EOF */ - case s_body_identity_eof: - MARK(body); - p = data + len - 1; - - break; - - case s_message_done: - UPDATE_STATE(NEW_MESSAGE()); - CALLBACK_NOTIFY(message_complete); - if (parser->upgrade) { - /* Exit, the rest of the message is in a different protocol. */ - RETURN((p - data) + 1); - } - break; - - case s_chunk_size_start: - { - assert(parser->nread == 1); - assert(parser->flags & F_CHUNKED); - - unhex_val = unhex[(unsigned char)ch]; - if (UNLIKELY(unhex_val == -1)) { - SET_ERRNO(HPE_INVALID_CHUNK_SIZE); - goto error; - } - - parser->content_length = unhex_val; - UPDATE_STATE(s_chunk_size); - break; - } - - case s_chunk_size: - { - uint64_t t; - - assert(parser->flags & F_CHUNKED); - - if (ch == CR) { - UPDATE_STATE(s_chunk_size_almost_done); - break; - } - - unhex_val = unhex[(unsigned char)ch]; - - if (unhex_val == -1) { - if (ch == ';' || ch == ' ') { - UPDATE_STATE(s_chunk_parameters); - break; - } - - SET_ERRNO(HPE_INVALID_CHUNK_SIZE); - goto error; - } - - t = parser->content_length; - t *= 16; - t += unhex_val; - - /* Overflow? Test against a conservative limit for simplicity. */ - if (UNLIKELY((ULLONG_MAX - 16) / 16 < parser->content_length)) { - SET_ERRNO(HPE_INVALID_CONTENT_LENGTH); - goto error; - } - - parser->content_length = t; - break; - } - - case s_chunk_parameters: - { - assert(parser->flags & F_CHUNKED); - /* just ignore this shit. TODO check for overflow */ - if (ch == CR) { - UPDATE_STATE(s_chunk_size_almost_done); - break; - } - break; - } - - case s_chunk_size_almost_done: - { - assert(parser->flags & F_CHUNKED); - STRICT_CHECK(ch != LF); - - parser->nread = 0; - - if (parser->content_length == 0) { - parser->flags |= F_TRAILING; - UPDATE_STATE(s_header_field_start); - } else { - UPDATE_STATE(s_chunk_data); - } - CALLBACK_NOTIFY(chunk_header); - break; - } - - case s_chunk_data: - { - uint64_t to_read = MIN(parser->content_length, - (uint64_t) ((data + len) - p)); - - assert(parser->flags & F_CHUNKED); - assert(parser->content_length != 0 - && parser->content_length != ULLONG_MAX); - - /* See the explanation in s_body_identity for why the content - * length and data pointers are managed this way. - */ - MARK(body); - parser->content_length -= to_read; - p += to_read - 1; - - if (parser->content_length == 0) { - UPDATE_STATE(s_chunk_data_almost_done); - } - - break; - } - - case s_chunk_data_almost_done: - assert(parser->flags & F_CHUNKED); - assert(parser->content_length == 0); - STRICT_CHECK(ch != CR); - UPDATE_STATE(s_chunk_data_done); - CALLBACK_DATA(body); - break; - - case s_chunk_data_done: - assert(parser->flags & F_CHUNKED); - STRICT_CHECK(ch != LF); - parser->nread = 0; - UPDATE_STATE(s_chunk_size_start); - CALLBACK_NOTIFY(chunk_complete); - break; - - default: - assert(0 && "unhandled state"); - SET_ERRNO(HPE_INVALID_INTERNAL_STATE); - goto error; - } - } - - /* Run callbacks for any marks that we have leftover after we ran our of - * bytes. There should be at most one of these set, so it's OK to invoke - * them in series (unset marks will not result in callbacks). - * - * We use the NOADVANCE() variety of callbacks here because 'p' has already - * overflowed 'data' and this allows us to correct for the off-by-one that - * we'd otherwise have (since CALLBACK_DATA() is meant to be run with a 'p' - * value that's in-bounds). - */ - - assert(((header_field_mark ? 1 : 0) + - (header_value_mark ? 1 : 0) + - (url_mark ? 1 : 0) + - (body_mark ? 1 : 0) + - (status_mark ? 1 : 0)) <= 1); - - CALLBACK_DATA_NOADVANCE(header_field); - CALLBACK_DATA_NOADVANCE(header_value); - CALLBACK_DATA_NOADVANCE(url); - CALLBACK_DATA_NOADVANCE(body); - CALLBACK_DATA_NOADVANCE(status); - - RETURN(len); - -error: - if (HTTP_PARSER_ERRNO(parser) == HPE_OK) { - SET_ERRNO(HPE_UNKNOWN); - } - - RETURN(p - data); -} - - -/* Does the parser need to see an EOF to find the end of the message? */ -int -http_message_needs_eof (const http_parser *parser) -{ - if (parser->type == HTTP_REQUEST) { - return 0; - } - - /* See RFC 2616 section 4.4 */ - if (parser->status_code / 100 == 1 || /* 1xx e.g. Continue */ - parser->status_code == 204 || /* No Content */ - parser->status_code == 304 || /* Not Modified */ - parser->flags & F_SKIPBODY) { /* response to a HEAD request */ - return 0; - } - - if ((parser->flags & F_CHUNKED) || parser->content_length != ULLONG_MAX) { - return 0; - } - - return 1; -} - - -int -http_should_keep_alive (const http_parser *parser) -{ - if (parser->http_major > 0 && parser->http_minor > 0) { - /* HTTP/1.1 */ - if (parser->flags & F_CONNECTION_CLOSE) { - return 0; - } - } else { - /* HTTP/1.0 or earlier */ - if (!(parser->flags & F_CONNECTION_KEEP_ALIVE)) { - return 0; - } - } - - return !http_message_needs_eof(parser); -} - - -const char * -http_method_str (enum http_method m) -{ - return ELEM_AT(method_strings, m, ""); -} - - -void -http_parser_init (http_parser *parser, enum http_parser_type t) -{ - void *data = parser->data; /* preserve application data */ - memset(parser, 0, sizeof(*parser)); - parser->data = data; - parser->type = t; - parser->state = (t == HTTP_REQUEST ? s_start_req : (t == HTTP_RESPONSE ? s_start_res : s_start_req_or_res)); - parser->http_errno = HPE_OK; -} - -void -http_parser_settings_init(http_parser_settings *settings) -{ - memset(settings, 0, sizeof(*settings)); -} - -const char * -http_errno_name(enum http_errno err) { - assert(((size_t) err) < ARRAY_SIZE(http_strerror_tab)); - return http_strerror_tab[err].name; -} - -const char * -http_errno_description(enum http_errno err) { - assert(((size_t) err) < ARRAY_SIZE(http_strerror_tab)); - return http_strerror_tab[err].description; -} - -static enum http_host_state -http_parse_host_char(enum http_host_state s, const char ch) { - switch(s) { - case s_http_userinfo: - case s_http_userinfo_start: - if (ch == '@') { - return s_http_host_start; - } - - if (IS_USERINFO_CHAR(ch)) { - return s_http_userinfo; - } - break; - - case s_http_host_start: - if (ch == '[') { - return s_http_host_v6_start; - } - - if (IS_HOST_CHAR(ch)) { - return s_http_host; - } - - break; - - case s_http_host: - if (IS_HOST_CHAR(ch)) { - return s_http_host; - } - - /* FALLTHROUGH */ - case s_http_host_v6_end: - if (ch == ':') { - return s_http_host_port_start; - } - - break; - - case s_http_host_v6: - if (ch == ']') { - return s_http_host_v6_end; - } - - /* FALLTHROUGH */ - case s_http_host_v6_start: - if (IS_HEX(ch) || ch == ':' || ch == '.') { - return s_http_host_v6; - } - - if (s == s_http_host_v6 && ch == '%') { - return s_http_host_v6_zone_start; - } - break; - - case s_http_host_v6_zone: - if (ch == ']') { - return s_http_host_v6_end; - } - - /* FALLTHROUGH */ - case s_http_host_v6_zone_start: - /* RFC 6874 Zone ID consists of 1*( unreserved / pct-encoded) */ - if (IS_ALPHANUM(ch) || ch == '%' || ch == '.' || ch == '-' || ch == '_' || - ch == '~') { - return s_http_host_v6_zone; - } - break; - - case s_http_host_port: - case s_http_host_port_start: - if (IS_NUM(ch)) { - return s_http_host_port; - } - - break; - - default: - break; - } - return s_http_host_dead; -} - -static int -http_parse_host(const char * buf, struct http_parser_url *u, int found_at) { - enum http_host_state s; - - const char *p; - size_t buflen = u->field_data[UF_HOST].off + u->field_data[UF_HOST].len; - - assert(u->field_set & (1 << UF_HOST)); - - u->field_data[UF_HOST].len = 0; - - s = found_at ? s_http_userinfo_start : s_http_host_start; - - for (p = buf + u->field_data[UF_HOST].off; p < buf + buflen; p++) { - enum http_host_state new_s = http_parse_host_char(s, *p); - - if (new_s == s_http_host_dead) { - return 1; - } - - switch(new_s) { - case s_http_host: - if (s != s_http_host) { - u->field_data[UF_HOST].off = p - buf; - } - u->field_data[UF_HOST].len++; - break; - - case s_http_host_v6: - if (s != s_http_host_v6) { - u->field_data[UF_HOST].off = p - buf; - } - u->field_data[UF_HOST].len++; - break; - - case s_http_host_v6_zone_start: - case s_http_host_v6_zone: - u->field_data[UF_HOST].len++; - break; - - case s_http_host_port: - if (s != s_http_host_port) { - u->field_data[UF_PORT].off = p - buf; - u->field_data[UF_PORT].len = 0; - u->field_set |= (1 << UF_PORT); - } - u->field_data[UF_PORT].len++; - break; - - case s_http_userinfo: - if (s != s_http_userinfo) { - u->field_data[UF_USERINFO].off = p - buf ; - u->field_data[UF_USERINFO].len = 0; - u->field_set |= (1 << UF_USERINFO); - } - u->field_data[UF_USERINFO].len++; - break; - - default: - break; - } - s = new_s; - } - - /* Make sure we don't end somewhere unexpected */ - switch (s) { - case s_http_host_start: - case s_http_host_v6_start: - case s_http_host_v6: - case s_http_host_v6_zone_start: - case s_http_host_v6_zone: - case s_http_host_port_start: - case s_http_userinfo: - case s_http_userinfo_start: - return 1; - default: - break; - } - - return 0; -} - -void -http_parser_url_init(struct http_parser_url *u) { - memset(u, 0, sizeof(*u)); -} - -int -http_parser_parse_url(const char *buf, size_t buflen, int is_connect, - struct http_parser_url *u) -{ - enum state s; - const char *p; - enum http_parser_url_fields uf, old_uf; - int found_at = 0; - - u->port = u->field_set = 0; - s = is_connect ? s_req_server_start : s_req_spaces_before_url; - old_uf = UF_MAX; - - for (p = buf; p < buf + buflen; p++) { - s = parse_url_char(s, *p); - - /* Figure out the next field that we're operating on */ - switch (s) { - case s_dead: - return 1; - - /* Skip delimeters */ - case s_req_schema_slash: - case s_req_schema_slash_slash: - case s_req_server_start: - case s_req_query_string_start: - case s_req_fragment_start: - continue; - - case s_req_schema: - uf = UF_SCHEMA; - break; - - case s_req_server_with_at: - found_at = 1; -#if __GNUC__ >= 7 - __attribute__ ((fallthrough)); -#endif - - /* FALLTROUGH */ - case s_req_server: - uf = UF_HOST; - break; - - case s_req_path: - uf = UF_PATH; - break; - - case s_req_query_string: - uf = UF_QUERY; - break; - - case s_req_fragment: - uf = UF_FRAGMENT; - break; - - default: - assert(!"Unexpected state"); - return 1; - } - - /* Nothing's changed; soldier on */ - if (uf == old_uf) { - u->field_data[uf].len++; - continue; - } - - u->field_data[uf].off = p - buf; - u->field_data[uf].len = 1; - - u->field_set |= (1 << uf); - old_uf = uf; - } - - /* host must be present if there is a schema */ - /* parsing http:///toto will fail */ - if ((u->field_set & (1 << UF_SCHEMA)) && - (u->field_set & (1 << UF_HOST)) == 0) { - return 1; - } - - if (u->field_set & (1 << UF_HOST)) { - if (http_parse_host(buf, u, found_at) != 0) { - return 1; - } - } - - /* CONNECT requests can only contain "hostname:port" */ - if (is_connect && u->field_set != ((1 << UF_HOST)|(1 << UF_PORT))) { - return 1; - } - - if (u->field_set & (1 << UF_PORT)) { - /* Don't bother with endp; we've already validated the string */ - unsigned long v = strtoul(buf + u->field_data[UF_PORT].off, NULL, 10); - - /* Ports have a max value of 2^16 */ - if (v > 0xffff) { - return 1; - } - - u->port = (uint16_t) v; - } - - return 0; -} - -void -http_parser_pause(http_parser *parser, int paused) { - /* Users should only be pausing/unpausing a parser that is not in an error - * state. In non-debug builds, there's not much that we can do about this - * other than ignore it. - */ - if (HTTP_PARSER_ERRNO(parser) == HPE_OK || - HTTP_PARSER_ERRNO(parser) == HPE_PAUSED) { - SET_ERRNO((paused) ? HPE_PAUSED : HPE_OK); - } else { - assert(0 && "Attempting to pause parser in error state"); - } -} - -int -http_body_is_final(const struct http_parser *parser) { - return parser->state == s_message_done; -} - -unsigned long -http_parser_version(void) { - return HTTP_PARSER_VERSION_MAJOR * 0x10000 | - HTTP_PARSER_VERSION_MINOR * 0x00100 | - HTTP_PARSER_VERSION_PATCH * 0x00001; -} diff --git a/src/http/qhttp/http-parser/http_parser.h b/src/http/qhttp/http-parser/http_parser.h deleted file mode 100644 index 005db96e..00000000 --- a/src/http/qhttp/http-parser/http_parser.h +++ /dev/null @@ -1,432 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ -#ifndef http_parser_h -#define http_parser_h -#ifdef __cplusplus -extern "C" { -#endif - -/* Also update SONAME in the Makefile whenever you change these. */ -#define HTTP_PARSER_VERSION_MAJOR 2 -#define HTTP_PARSER_VERSION_MINOR 7 -#define HTTP_PARSER_VERSION_PATCH 1 - -#include -#if defined(_WIN32) && !defined(__MINGW32__) && \ - (!defined(_MSC_VER) || _MSC_VER<1600) && !defined(__WINE__) -#include -#include -typedef __int8 int8_t; -typedef unsigned __int8 uint8_t; -typedef __int16 int16_t; -typedef unsigned __int16 uint16_t; -typedef __int32 int32_t; -typedef unsigned __int32 uint32_t; -typedef __int64 int64_t; -typedef unsigned __int64 uint64_t; -#else -#include -#endif - -/* Compile with -DHTTP_PARSER_STRICT=0 to make less checks, but run - * faster - */ -#ifndef HTTP_PARSER_STRICT -# define HTTP_PARSER_STRICT 1 -#endif - -/* Maximium header size allowed. If the macro is not defined - * before including this header then the default is used. To - * change the maximum header size, define the macro in the build - * environment (e.g. -DHTTP_MAX_HEADER_SIZE=). To remove - * the effective limit on the size of the header, define the macro - * to a very large number (e.g. -DHTTP_MAX_HEADER_SIZE=0x7fffffff) - */ -#ifndef HTTP_MAX_HEADER_SIZE -# define HTTP_MAX_HEADER_SIZE (80*1024) -#endif - -typedef struct http_parser http_parser; -typedef struct http_parser_settings http_parser_settings; - - -/* Callbacks should return non-zero to indicate an error. The parser will - * then halt execution. - * - * The one exception is on_headers_complete. In a HTTP_RESPONSE parser - * returning '1' from on_headers_complete will tell the parser that it - * should not expect a body. This is used when receiving a response to a - * HEAD request which may contain 'Content-Length' or 'Transfer-Encoding: - * chunked' headers that indicate the presence of a body. - * - * Returning `2` from on_headers_complete will tell parser that it should not - * expect neither a body nor any futher responses on this connection. This is - * useful for handling responses to a CONNECT request which may not contain - * `Upgrade` or `Connection: upgrade` headers. - * - * http_data_cb does not return data chunks. It will be called arbitrarily - * many times for each string. E.G. you might get 10 callbacks for "on_url" - * each providing just a few characters more data. - */ -typedef int (*http_data_cb) (http_parser*, const char *at, size_t length); -typedef int (*http_cb) (http_parser*); - - -/* Status Codes */ -#define HTTPPARSER_HTTP_STATUS_MAP(XX) \ - XX(100, CONTINUE, Continue) \ - XX(101, SWITCHING_PROTOCOLS, Switching Protocols) \ - XX(102, PROCESSING, Processing) \ - XX(200, OK, OK) \ - XX(201, CREATED, Created) \ - XX(202, ACCEPTED, Accepted) \ - XX(203, NON_AUTHORITATIVE_INFORMATION, Non-Authoritative Information) \ - XX(204, NO_CONTENT, No Content) \ - XX(205, RESET_CONTENT, Reset Content) \ - XX(206, PARTIAL_CONTENT, Partial Content) \ - XX(207, MULTI_STATUS, Multi-Status) \ - XX(208, ALREADY_REPORTED, Already Reported) \ - XX(226, IM_USED, IM Used) \ - XX(300, MULTIPLE_CHOICES, Multiple Choices) \ - XX(301, MOVED_PERMANENTLY, Moved Permanently) \ - XX(302, FOUND, Found) \ - XX(303, SEE_OTHER, See Other) \ - XX(304, NOT_MODIFIED, Not Modified) \ - XX(305, USE_PROXY, Use Proxy) \ - XX(307, TEMPORARY_REDIRECT, Temporary Redirect) \ - XX(308, PERMANENT_REDIRECT, Permanent Redirect) \ - XX(400, BAD_REQUEST, Bad Request) \ - XX(401, UNAUTHORIZED, Unauthorized) \ - XX(402, PAYMENT_REQUIRED, Payment Required) \ - XX(403, FORBIDDEN, Forbidden) \ - XX(404, NOT_FOUND, Not Found) \ - XX(405, METHOD_NOT_ALLOWED, Method Not Allowed) \ - XX(406, NOT_ACCEPTABLE, Not Acceptable) \ - XX(407, PROXY_AUTHENTICATION_REQUIRED, Proxy Authentication Required) \ - XX(408, REQUEST_TIMEOUT, Request Timeout) \ - XX(409, CONFLICT, Conflict) \ - XX(410, GONE, Gone) \ - XX(411, LENGTH_REQUIRED, Length Required) \ - XX(412, PRECONDITION_FAILED, Precondition Failed) \ - XX(413, PAYLOAD_TOO_LARGE, Payload Too Large) \ - XX(414, URI_TOO_LONG, URI Too Long) \ - XX(415, UNSUPPORTED_MEDIA_TYPE, Unsupported Media Type) \ - XX(416, RANGE_NOT_SATISFIABLE, Range Not Satisfiable) \ - XX(417, EXPECTATION_FAILED, Expectation Failed) \ - XX(421, MISDIRECTED_REQUEST, Misdirected Request) \ - XX(422, UNPROCESSABLE_ENTITY, Unprocessable Entity) \ - XX(423, LOCKED, Locked) \ - XX(424, FAILED_DEPENDENCY, Failed Dependency) \ - XX(426, UPGRADE_REQUIRED, Upgrade Required) \ - XX(428, PRECONDITION_REQUIRED, Precondition Required) \ - XX(429, TOO_MANY_REQUESTS, Too Many Requests) \ - XX(431, REQUEST_HEADER_FIELDS_TOO_LARGE, Request Header Fields Too Large) \ - XX(451, UNAVAILABLE_FOR_LEGAL_REASONS, Unavailable For Legal Reasons) \ - XX(500, INTERNAL_SERVER_ERROR, Internal Server Error) \ - XX(501, NOT_IMPLEMENTED, Not Implemented) \ - XX(502, BAD_GATEWAY, Bad Gateway) \ - XX(503, SERVICE_UNAVAILABLE, Service Unavailable) \ - XX(504, GATEWAY_TIMEOUT, Gateway Timeout) \ - XX(505, HTTP_VERSION_NOT_SUPPORTED, HTTP Version Not Supported) \ - XX(506, VARIANT_ALSO_NEGOTIATES, Variant Also Negotiates) \ - XX(507, INSUFFICIENT_STORAGE, Insufficient Storage) \ - XX(508, LOOP_DETECTED, Loop Detected) \ - XX(510, NOT_EXTENDED, Not Extended) \ - XX(511, NETWORK_AUTHENTICATION_REQUIRED, Network Authentication Required) - -enum http_status - { -#define XX(num, name, string) HTTP_STATUS_##name = num, - HTTPPARSER_HTTP_STATUS_MAP(XX) -#undef XX - }; - - -/* Request Methods */ -#define HTTP_METHOD_MAP(XX) \ - XX(0, DELETE, DELETE) \ - XX(1, GET, GET) \ - XX(2, HEAD, HEAD) \ - XX(3, POST, POST) \ - XX(4, PUT, PUT) \ - /* pathological */ \ - XX(5, CONNECT, CONNECT) \ - XX(6, OPTIONS, OPTIONS) \ - XX(7, TRACE, TRACE) \ - /* WebDAV */ \ - XX(8, COPY, COPY) \ - XX(9, LOCK, LOCK) \ - XX(10, MKCOL, MKCOL) \ - XX(11, MOVE, MOVE) \ - XX(12, PROPFIND, PROPFIND) \ - XX(13, PROPPATCH, PROPPATCH) \ - XX(14, SEARCH, SEARCH) \ - XX(15, UNLOCK, UNLOCK) \ - XX(16, BIND, BIND) \ - XX(17, REBIND, REBIND) \ - XX(18, UNBIND, UNBIND) \ - XX(19, ACL, ACL) \ - /* subversion */ \ - XX(20, REPORT, REPORT) \ - XX(21, MKACTIVITY, MKACTIVITY) \ - XX(22, CHECKOUT, CHECKOUT) \ - XX(23, MERGE, MERGE) \ - /* upnp */ \ - XX(24, MSEARCH, M-SEARCH) \ - XX(25, NOTIFY, NOTIFY) \ - XX(26, SUBSCRIBE, SUBSCRIBE) \ - XX(27, UNSUBSCRIBE, UNSUBSCRIBE) \ - /* RFC-5789 */ \ - XX(28, PATCH, PATCH) \ - XX(29, PURGE, PURGE) \ - /* CalDAV */ \ - XX(30, MKCALENDAR, MKCALENDAR) \ - /* RFC-2068, section 19.6.1.2 */ \ - XX(31, LINK, LINK) \ - XX(32, UNLINK, UNLINK) \ - -enum http_method - { -#define XX(num, name, string) HTTP_##name = num, - HTTP_METHOD_MAP(XX) -#undef XX - }; - - -enum http_parser_type { HTTP_REQUEST, HTTP_RESPONSE, HTTP_BOTH }; - - -/* Flag values for http_parser.flags field */ -enum flags - { F_CHUNKED = 1 << 0 - , F_CONNECTION_KEEP_ALIVE = 1 << 1 - , F_CONNECTION_CLOSE = 1 << 2 - , F_CONNECTION_UPGRADE = 1 << 3 - , F_TRAILING = 1 << 4 - , F_UPGRADE = 1 << 5 - , F_SKIPBODY = 1 << 6 - , F_CONTENTLENGTH = 1 << 7 - }; - - -/* Map for errno-related constants - * - * The provided argument should be a macro that takes 2 arguments. - */ -#define HTTP_ERRNO_MAP(XX) \ - /* No error */ \ - XX(OK, "success") \ - \ - /* Callback-related errors */ \ - XX(CB_message_begin, "the on_message_begin callback failed") \ - XX(CB_url, "the on_url callback failed") \ - XX(CB_header_field, "the on_header_field callback failed") \ - XX(CB_header_value, "the on_header_value callback failed") \ - XX(CB_headers_complete, "the on_headers_complete callback failed") \ - XX(CB_body, "the on_body callback failed") \ - XX(CB_message_complete, "the on_message_complete callback failed") \ - XX(CB_status, "the on_status callback failed") \ - XX(CB_chunk_header, "the on_chunk_header callback failed") \ - XX(CB_chunk_complete, "the on_chunk_complete callback failed") \ - \ - /* Parsing-related errors */ \ - XX(INVALID_EOF_STATE, "stream ended at an unexpected time") \ - XX(HEADER_OVERFLOW, \ - "too many header bytes seen; overflow detected") \ - XX(CLOSED_CONNECTION, \ - "data received after completed connection: close message") \ - XX(INVALID_VERSION, "invalid HTTP version") \ - XX(INVALID_STATUS, "invalid HTTP status code") \ - XX(INVALID_METHOD, "invalid HTTP method") \ - XX(INVALID_URL, "invalid URL") \ - XX(INVALID_HOST, "invalid host") \ - XX(INVALID_PORT, "invalid port") \ - XX(INVALID_PATH, "invalid path") \ - XX(INVALID_QUERY_STRING, "invalid query string") \ - XX(INVALID_FRAGMENT, "invalid fragment") \ - XX(LF_EXPECTED, "LF character expected") \ - XX(INVALID_HEADER_TOKEN, "invalid character in header") \ - XX(INVALID_CONTENT_LENGTH, \ - "invalid character in content-length header") \ - XX(UNEXPECTED_CONTENT_LENGTH, \ - "unexpected content-length header") \ - XX(INVALID_CHUNK_SIZE, \ - "invalid character in chunk size header") \ - XX(INVALID_CONSTANT, "invalid constant string") \ - XX(INVALID_INTERNAL_STATE, "encountered unexpected internal state")\ - XX(STRICT, "strict mode assertion failed") \ - XX(PAUSED, "parser is paused") \ - XX(UNKNOWN, "an unknown error occurred") - - -/* Define HPE_* values for each errno value above */ -#define HTTP_ERRNO_GEN(n, s) HPE_##n, -enum http_errno { - HTTP_ERRNO_MAP(HTTP_ERRNO_GEN) -}; -#undef HTTP_ERRNO_GEN - - -/* Get an http_errno value from an http_parser */ -#define HTTP_PARSER_ERRNO(p) ((enum http_errno) (p)->http_errno) - - -struct http_parser { - /** PRIVATE **/ - unsigned int type : 2; /* enum http_parser_type */ - unsigned int flags : 8; /* F_* values from 'flags' enum; semi-public */ - unsigned int state : 7; /* enum state from http_parser.c */ - unsigned int header_state : 7; /* enum header_state from http_parser.c */ - unsigned int index : 7; /* index into current matcher */ - unsigned int lenient_http_headers : 1; - - uint32_t nread; /* # bytes read in various scenarios */ - uint64_t content_length; /* # bytes in body (0 if no Content-Length header) */ - - /** READ-ONLY **/ - unsigned short http_major; - unsigned short http_minor; - unsigned int status_code : 16; /* responses only */ - unsigned int method : 8; /* requests only */ - unsigned int http_errno : 7; - - /* 1 = Upgrade header was present and the parser has exited because of that. - * 0 = No upgrade header present. - * Should be checked when http_parser_execute() returns in addition to - * error checking. - */ - unsigned int upgrade : 1; - - /** PUBLIC **/ - void *data; /* A pointer to get hook to the "connection" or "socket" object */ -}; - - -struct http_parser_settings { - http_cb on_message_begin; - http_data_cb on_url; - http_data_cb on_status; - http_data_cb on_header_field; - http_data_cb on_header_value; - http_cb on_headers_complete; - http_data_cb on_body; - http_cb on_message_complete; - /* When on_chunk_header is called, the current chunk length is stored - * in parser->content_length. - */ - http_cb on_chunk_header; - http_cb on_chunk_complete; -}; - - -enum http_parser_url_fields - { UF_SCHEMA = 0 - , UF_HOST = 1 - , UF_PORT = 2 - , UF_PATH = 3 - , UF_QUERY = 4 - , UF_FRAGMENT = 5 - , UF_USERINFO = 6 - , UF_MAX = 7 - }; - - -/* Result structure for http_parser_parse_url(). - * - * Callers should index into field_data[] with UF_* values iff field_set - * has the relevant (1 << UF_*) bit set. As a courtesy to clients (and - * because we probably have padding left over), we convert any port to - * a uint16_t. - */ -struct http_parser_url { - uint16_t field_set; /* Bitmask of (1 << UF_*) values */ - uint16_t port; /* Converted UF_PORT string */ - - struct { - uint16_t off; /* Offset into buffer in which field starts */ - uint16_t len; /* Length of run in buffer */ - } field_data[UF_MAX]; -}; - - -/* Returns the library version. Bits 16-23 contain the major version number, - * bits 8-15 the minor version number and bits 0-7 the patch level. - * Usage example: - * - * unsigned long version = http_parser_version(); - * unsigned major = (version >> 16) & 255; - * unsigned minor = (version >> 8) & 255; - * unsigned patch = version & 255; - * printf("http_parser v%u.%u.%u\n", major, minor, patch); - */ -unsigned long http_parser_version(void); - -void http_parser_init(http_parser *parser, enum http_parser_type type); - - -/* Initialize http_parser_settings members to 0 - */ -void http_parser_settings_init(http_parser_settings *settings); - - -/* Executes the parser. Returns number of parsed bytes. Sets - * `parser->http_errno` on error. */ -size_t http_parser_execute(http_parser *parser, - const http_parser_settings *settings, - const char *data, - size_t len); - - -/* If http_should_keep_alive() in the on_headers_complete or - * on_message_complete callback returns 0, then this should be - * the last message on the connection. - * If you are the server, respond with the "Connection: close" header. - * If you are the client, close the connection. - */ -int http_should_keep_alive(const http_parser *parser); - -/* Returns a string version of the HTTP method. */ -const char *http_method_str(enum http_method m); - -/* Return a string name of the given error */ -const char *http_errno_name(enum http_errno err); - -/* Return a string description of the given error */ -const char *http_errno_description(enum http_errno err); - -/* Initialize all http_parser_url members to 0 */ -void http_parser_url_init(struct http_parser_url *u); - -/* Parse a URL; return nonzero on failure */ -int http_parser_parse_url(const char *buf, size_t buflen, - int is_connect, - struct http_parser_url *u); - -/* Pause or un-pause the parser; a nonzero value pauses */ -void http_parser_pause(http_parser *parser, int paused); - -/* Checks if this is the final chunk of the body. */ -int http_body_is_final(const http_parser *parser); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/src/http/qhttp/private/httpparser.hxx b/src/http/qhttp/private/httpparser.hxx deleted file mode 100644 index 8dfea18e..00000000 --- a/src/http/qhttp/private/httpparser.hxx +++ /dev/null @@ -1,119 +0,0 @@ -/** @file httpparser.hxx - * - * @copyright (C) 2016 - * @date 2016.05.26 - * @version 1.0.0 - * @author amir zamani - * - */ - -#ifndef __QHTTP_HTTPPARSER_HXX__ -#define __QHTTP_HTTPPARSER_HXX__ - -#include "qhttpbase.hpp" -/////////////////////////////////////////////////////////////////////////////// -namespace qhttp { -namespace details { -/////////////////////////////////////////////////////////////////////////////// - - -/// base HttpParser based on joyent http_parser -template -class HttpParser -{ -public: - explicit HttpParser(http_parser_type type) { - // create http_parser object - iparser.data = static_cast(this); - http_parser_init(&iparser, type); - - memset(&iparserSettings, 0, sizeof(http_parser_settings)); - iparserSettings.on_message_begin = onMessageBegin; - iparserSettings.on_url = onUrl; - iparserSettings.on_status = onStatus; - iparserSettings.on_header_field = onHeaderField; - iparserSettings.on_header_value = onHeaderValue; - iparserSettings.on_headers_complete = onHeadersComplete; - iparserSettings.on_body = onBody; - iparserSettings.on_message_complete = onMessageComplete; - } - - size_t parse(const char* data, size_t length) { - return http_parser_execute(&iparser, - &iparserSettings, - data, - length); - } - -public: // callback functions for http_parser_settings - static int onMessageBegin(http_parser* p) { - return me(p)->messageBegin(p); - } - - static int onUrl(http_parser* p, const char* at, size_t length) { - return me(p)->url(p, at, length); - } - - static int onStatus(http_parser* p, const char* at, size_t length) { - return me(p)->status(p, at, length); - } - - static int onHeaderField(http_parser* p, const char* at, size_t length) { - return me(p)->headerField(p, at, length); - } - - static int onHeaderValue(http_parser* p, const char* at, size_t length) { - return me(p)->headerValue(p, at, length); - } - - static int onHeadersComplete(http_parser* p) { - return me(p)->headersComplete(p); - } - - static int onBody(http_parser* p, const char* at, size_t length) { - return me(p)->body(p, at, length); - } - - static int onMessageComplete(http_parser* p) { - return me(p)->messageComplete(p); - } - - -protected: - // The ones we are reading in from the parser - QByteArray itempHeaderField; - QByteArray itempHeaderValue; - // if connection has a timeout, these fields will be used - quint32 itimeOut = 0; - QBasicTimer itimer; - // uniform socket object - QSocket isocket; - // if connection should persist - bool ikeepAlive = false; - - // joyent http_parser - http_parser iparser; - http_parser_settings iparserSettings; - - static TImpl* me(http_parser* p) { - return static_cast(p->data); - } -}; // - -/// basic request parser (server) -template -struct HttpRequestParser : public HttpParser { - HttpRequestParser() : HttpParser(HTTP_REQUEST) {} -}; - -/// basic response parser (clinet) -template -struct HttpResponseParser : public HttpParser { - HttpResponseParser() : HttpParser(HTTP_RESPONSE) {} -}; - -/////////////////////////////////////////////////////////////////////////////// -} // namespace details -} // namespace qhttp -/////////////////////////////////////////////////////////////////////////////// -#endif // __QHTTP_HTTPPARSER_HXX__ diff --git a/src/http/qhttp/private/httpreader.hxx b/src/http/qhttp/private/httpreader.hxx deleted file mode 100644 index 338ed2a2..00000000 --- a/src/http/qhttp/private/httpreader.hxx +++ /dev/null @@ -1,78 +0,0 @@ -/** @file httpreader.hxx - * - * @copyright (C) 2016 - * @date 2016.05.26 - * @version 1.0.0 - * @author amir zamani - * - */ - -#ifndef __QHTTP_HTTPREADER_HXX__ -#define __QHTTP_HTTPREADER_HXX__ - -#include "qhttpbase.hpp" -/////////////////////////////////////////////////////////////////////////////// -namespace qhttp { -namespace details { -/////////////////////////////////////////////////////////////////////////////// - -// usage in client::QHttpResponse, server::QHttpRequest -template -class HttpReader : public TBase -{ -public: - enum TReadState { - EEmpty, - EPartial, - EComplete, - ESent - }; - -public: - void collectData(int atMost) { - icollectRequired = true; - icollectCapacity = atMost; - icollectedData.clear(); - if ( atMost > 0 ) - icollectedData.reserve(atMost); - } - - bool append(const char* data, size_t length) { - if ( !icollectRequired ) // not allowed to collect data - return false; - - int newLength = icollectedData.length() + static_cast(length); - - if ( icollectCapacity > 0 && newLength > icollectCapacity ) - return false; // the capacity is full - - icollectedData.append(data, length); - return true; - } - - // call cb if the message is not finalized yet - template - void finalizeSending(Func cb) { - if ( ireadState != EComplete ) { - ireadState = EComplete; - isuccessful = true; - - cb(); - } - } - -public: - bool isuccessful = false; - TReadState ireadState = EEmpty; - - /// shall I collect incoming body data by myself? - bool icollectRequired = false; - int icollectCapacity = 0; - QByteArray icollectedData; -}; - -/////////////////////////////////////////////////////////////////////////////// -} // namespace details -} // namespace qhttp -/////////////////////////////////////////////////////////////////////////////// -#endif // __QHTTP_HTTPREADER_HXX__ diff --git a/src/http/qhttp/private/httpwriter.hxx b/src/http/qhttp/private/httpwriter.hxx deleted file mode 100644 index 2e9bedfe..00000000 --- a/src/http/qhttp/private/httpwriter.hxx +++ /dev/null @@ -1,112 +0,0 @@ -/** @file httpwriter.hxx - * - * @copyright (C) 2016 - * @date 2016.05.26 - * @version 1.0.0 - * @author amir zamani - * - */ - -#ifndef __QHTTP_HTTPWRITER_HXX__ -#define __QHTTP_HTTPWRITER_HXX__ - -#include "qhttpbase.hpp" - -/////////////////////////////////////////////////////////////////////////////// -namespace qhttp { -namespace details { -/////////////////////////////////////////////////////////////////////////////// - -// usage in client::QHttpRequest, server::QHttpResponse -template -class HttpWriter : public TBase -{ -public: - bool addHeader(const QByteArray &field, const QByteArray &value) { - if ( ifinished ) - return false; - - TBase::iheaders.insert(field.toLower(), value); - return true; - } - - bool writeHeader(const QByteArray& field, const QByteArray& value) { - if ( ifinished ) - return false; - - QByteArray buffer = QByteArray(field) - .append(": ") - .append(value) - .append("\r\n"); - - isocket.writeRaw(buffer); - return true; - } - - bool writeData(const QByteArray& data) { - if ( ifinished ) - return false; - - ensureWritingHeaders(); - isocket.writeRaw(data); - return true; - } - - bool endPacket(const QByteArray& data) { - if ( !writeData(data) ) - return false; - - isocket.flush(); - ifinished = true; - return true; - } - - void ensureWritingHeaders() { - if ( ifinished || iheaderWritten ) - return; - - TImpl* me = static_cast(this); - isocket.writeRaw(me->makeTitle()); - writeHeaders(); - - iheaderWritten = true; - } - - void writeHeaders(bool doFlush = false) { - if ( ifinished || iheaderWritten ) - return; - - if ( TBase::iheaders.keyHasValue("connection", "keep-alive") ) - ikeepAlive = true; - else - TBase::iheaders.insert("connection", "close"); - - TImpl* me = static_cast(this); - me->prepareHeadersToWrite(); - - for ( auto cit = TBase::iheaders.constBegin(); cit != TBase::iheaders.constEnd(); cit++ ) { - const QByteArray& field = cit.key(); - const QByteArray& value = cit.value(); - - writeHeader(field, value); - } - - isocket.writeRaw("\r\n"); - if ( doFlush ) - isocket.flush(); - } - -public: - QSocket isocket; - - bool ifinished = false; - bool iheaderWritten = false; - bool ikeepAlive = false; -}; - - -/////////////////////////////////////////////////////////////////////////////// -} // namespace details -} // namespace qhttp -/////////////////////////////////////////////////////////////////////////////// -#endif // __QHTTP_HTTPWRITER_HXX__ diff --git a/src/http/qhttp/private/qhttpbase.hpp b/src/http/qhttp/private/qhttpbase.hpp deleted file mode 100644 index 81bae4f5..00000000 --- a/src/http/qhttp/private/qhttpbase.hpp +++ /dev/null @@ -1,52 +0,0 @@ -/** base classes for private implementations. - * https://github.com/azadkuh/qhttp - * - * @author amir zamani - * @version 2.0.0 - * @date 2014-07-11 - */ - -#ifndef QHTTPBASE_HPP -#define QHTTPBASE_HPP - -#include "qhttpfwd.hpp" - -#include "qsocket.hpp" -#include -#include - -#include "http-parser/http_parser.h" - -/////////////////////////////////////////////////////////////////////////////// -namespace qhttp { -namespace details { -/////////////////////////////////////////////////////////////////////////////// - -struct HttpBase -{ - QString iversion; - THeaderHash iheaders; -}; // struct HttpBase - -/////////////////////////////////////////////////////////////////////////////// - -struct HttpRequestBase : public HttpBase -{ - QUrl iurl; - THttpMethod imethod; -}; // HttpRequestBase - -/////////////////////////////////////////////////////////////////////////////// - -struct HttpResponseBase : public HttpBase -{ - TStatusCode istatus = ESTATUS_BAD_REQUEST; - - HttpResponseBase() { iversion = "1.1"; } -}; // HttpResponseBase - -/////////////////////////////////////////////////////////////////////////////// -} // namespace details -} // namespace qhttp -/////////////////////////////////////////////////////////////////////////////// -#endif // QHTTPBASE_HPP diff --git a/src/http/qhttp/private/qhttpclient_private.hpp b/src/http/qhttp/private/qhttpclient_private.hpp deleted file mode 100644 index 9c6cd098..00000000 --- a/src/http/qhttp/private/qhttpclient_private.hpp +++ /dev/null @@ -1,222 +0,0 @@ -/** private imeplementation. - * https://github.com/azadkuh/qhttp - * - * @author amir zamani - * @version 2.0.0 - * @date 2014-07-11 - */ - -#ifndef QHTTPCLIENT_PRIVATE_HPP -#define QHTTPCLIENT_PRIVATE_HPP -/////////////////////////////////////////////////////////////////////////////// - -#include "qhttpclient.hpp" -#include "httpparser.hxx" -#include "qhttpclientrequest_private.hpp" -#include "qhttpclientresponse_private.hpp" - -/////////////////////////////////////////////////////////////////////////////// -namespace qhttp { -namespace client { -/////////////////////////////////////////////////////////////////////////////// - -class QHttpClientPrivate : - public details::HttpResponseParser -{ - Q_DECLARE_PUBLIC(QHttpClient) - -public: - explicit QHttpClientPrivate(QHttpClient* q) : q_ptr(q) { - QObject::connect( - q_func(), &QHttpClient::disconnected, - [this](){ release(); } - ); - - QHTTP_LINE_DEEPLOG - } - - virtual ~QHttpClientPrivate() { - QHTTP_LINE_DEEPLOG - } - - void release() { - // if socket drops and http_parser can not call messageComplete, - // dispatch the ilastResponse - finalizeConnection(); - - isocket.disconnectAllQtConnections(); - isocket.release(); - - if ( ilastRequest ) { - ilastRequest->deleteLater(); - ilastRequest = nullptr; - } - - if ( ilastResponse ) { - ilastResponse->deleteLater(); - ilastResponse = nullptr; - } - - // must be called! or the later http_parser_execute() may fail - http_parser_init(&iparser, HTTP_RESPONSE); - } - - void initializeSocket() { - // no need to reconnect. do nothing and simply return - if ( ikeepAlive ) - return; - - // close previous connection now! - // instead being called by emitted disconnected signal - release(); - - ikeepAlive = false; - - // create a tcp connection - if ( isocket.ibackendType == ETcpSocket ) { - initTcpSocket(); - - } else if ( isocket.ibackendType == ESslSocket ) { - initSslSocket(); - - } else if ( isocket.ibackendType == ELocalSocket ) { - initLocalSocket(); - } - } - -public: - int messageBegin(http_parser* parser); - int url(http_parser*, const char*, size_t) { - return 0; // not used in parsing incoming response. - } - int status(http_parser* parser, const char* at, size_t length) ; - int headerField(http_parser* parser, const char* at, size_t length); - int headerValue(http_parser* parser, const char* at, size_t length); - int headersComplete(http_parser* parser); - int body(http_parser* parser, const char* at, size_t length); - int messageComplete(http_parser* parser); - -protected: - void onConnected() { - iconnectingTimer.stop(); - - if ( itimeOut > 0 ) - itimer.start(itimeOut, Qt::CoarseTimer, q_func()); - - if ( ireqHandler ) - ireqHandler(ilastRequest); - else - q_func()->onRequestReady(ilastRequest); - } - - void onReadyRead() { - while ( isocket.bytesAvailable() > 0 ) { - char buffer[4097] = {0}; - size_t readLength = static_cast(isocket.readRaw(buffer, 4096)); - - parse(buffer, readLength); - } - } - - void finalizeConnection() { - if ( ilastResponse == nullptr ) - return; - - ilastResponse->d_func()->finalizeSending([this]{ - emit ilastResponse->end(); - }); - } - -private: - void initTcpSocket() { - QTcpSocket* sok = new QTcpSocket(q_func()); - isocket.itcpSocket = sok; - - QObject::connect( - sok, &QTcpSocket::connected, - [this](){ onConnected(); } - ); - QObject::connect( - sok, &QTcpSocket::readyRead, - [this](){ onReadyRead(); } - ); - QObject::connect( - sok, &QTcpSocket::bytesWritten, - [this](qint64){ - const auto& ts = isocket.itcpSocket; - if ( ts->bytesToWrite() == 0 && ilastRequest ) - emit ilastRequest->allBytesWritten(); - }); - QObject::connect( - sok, &QTcpSocket::disconnected, - q_func(), &QHttpClient::disconnected - ); - } - - void initSslSocket() { - QSslSocket* sok = new QSslSocket(q_func()); - isocket.itcpSocket = sok; - - QObject::connect( - sok, &QSslSocket::encrypted, - [this](){ onConnected(); } - ); - QObject::connect( - sok, &QSslSocket::readyRead, - [this](){ onReadyRead(); } - ); - QObject::connect( - sok, &QSslSocket::bytesWritten, - [this](qint64){ - const auto& ts = isocket.itcpSocket; - if ( ts->bytesToWrite() == 0 && ilastRequest ) - emit ilastRequest->allBytesWritten(); - }); - QObject::connect( - sok, &QSslSocket::disconnected, - q_func(), &QHttpClient::disconnected - ); - } - - void initLocalSocket() { - QLocalSocket* sok = new QLocalSocket(q_func()); - isocket.ilocalSocket = sok; - - QObject::connect( - sok, &QLocalSocket::connected, - [this](){ onConnected(); } - ); - QObject::connect( - sok, &QLocalSocket::readyRead, - [this](){ onReadyRead(); } - ); - QObject::connect( - sok, &QLocalSocket::bytesWritten, - [this](qint64){ - const auto* ls = isocket.ilocalSocket; - if ( ls->bytesToWrite() == 0 && ilastRequest ) - emit ilastRequest->allBytesWritten(); - }); - QObject::connect( - sok, &QLocalSocket::disconnected, - q_func(), &QHttpClient::disconnected - ); - } - -protected: - QHttpClient* const q_ptr; - - QHttpRequest* ilastRequest = nullptr; - QHttpResponse* ilastResponse = nullptr; - TRequstHandler ireqHandler; - TResponseHandler irespHandler; - - QBasicTimer iconnectingTimer; -}; - -/////////////////////////////////////////////////////////////////////////////// -} // namespace client -} // namespace qhttp -/////////////////////////////////////////////////////////////////////////////// - -#endif // QHTTPCLIENT_PRIVATE_HPP diff --git a/src/http/qhttp/private/qhttpclientrequest_private.hpp b/src/http/qhttp/private/qhttpclientrequest_private.hpp deleted file mode 100644 index 703fcc40..00000000 --- a/src/http/qhttp/private/qhttpclientrequest_private.hpp +++ /dev/null @@ -1,57 +0,0 @@ -/** private imeplementation. - * https://github.com/azadkuh/qhttp - * - * @author amir zamani - * @version 2.0.0 - * @date 2014-07-11 - */ - -#ifndef QHTTPCLIENT_REQUEST_PRIVATE_HPP -#define QHTTPCLIENT_REQUEST_PRIVATE_HPP -/////////////////////////////////////////////////////////////////////////////// -#include "httpwriter.hxx" -#include "qhttpclient.hpp" -#include "qhttpclientrequest.hpp" - -#include - -/////////////////////////////////////////////////////////////////////////////// -namespace qhttp { -namespace client { -/////////////////////////////////////////////////////////////////////////////// -class QHttpRequestPrivate : - public details::HttpWriter -{ - Q_DECLARE_PUBLIC(QHttpRequest) - -public: - explicit QHttpRequestPrivate(QHttpClient* cli, QHttpRequest* q) : q_ptr(q), iclient(cli) { - QHTTP_LINE_DEEPLOG - } - - virtual ~QHttpRequestPrivate() { - QHTTP_LINE_DEEPLOG - } - - void initialize() { - iversion = "1.1"; - - isocket.ibackendType = iclient->backendType(); - isocket.itcpSocket = iclient->tcpSocket(); - isocket.ilocalSocket = iclient->localSocket(); - } - - QByteArray makeTitle(); - - void prepareHeadersToWrite(); - -protected: - QHttpRequest* const q_ptr; - QHttpClient* const iclient; -}; - -/////////////////////////////////////////////////////////////////////////////// -} // namespace client -} // namespace qhttp -/////////////////////////////////////////////////////////////////////////////// -#endif // QHTTPCLIENT_REQUEST_PRIVATE_HPP diff --git a/src/http/qhttp/private/qhttpclientresponse_private.hpp b/src/http/qhttp/private/qhttpclientresponse_private.hpp deleted file mode 100644 index 4c216f1d..00000000 --- a/src/http/qhttp/private/qhttpclientresponse_private.hpp +++ /dev/null @@ -1,51 +0,0 @@ -/** private imeplementation. - * https://github.com/azadkuh/qhttp - * - * @author amir zamani - * @version 2.0.0 - * @date 2014-07-11 - */ - -#ifndef QHTTPCLIENT_RESPONSE_PRIVATE_HPP -#define QHTTPCLIENT_RESPONSE_PRIVATE_HPP -/////////////////////////////////////////////////////////////////////////////// - -#include "httpreader.hxx" -#include "qhttpclient.hpp" -#include "qhttpclientresponse.hpp" - -/////////////////////////////////////////////////////////////////////////////// -namespace qhttp { -namespace client { -/////////////////////////////////////////////////////////////////////////////// -class QHttpResponsePrivate : - public details::HttpReader -{ - Q_DECLARE_PUBLIC(QHttpResponse) - QHttpResponse* const q_ptr; - -public: - explicit QHttpResponsePrivate(QHttpClient* cli, QHttpResponse* q) - : q_ptr(q), iclient(cli) { - QHTTP_LINE_DEEPLOG - } - - virtual ~QHttpResponsePrivate() { - QHTTP_LINE_DEEPLOG - } - - void initialize() { - } - -public: - QString icustomStatusMessage; - -protected: - QHttpClient* const iclient; -}; - -/////////////////////////////////////////////////////////////////////////////// -} // namespace client -} // namespace qhttp -/////////////////////////////////////////////////////////////////////////////// -#endif // QHTTPCLIENT_RESPONSE_PRIVATE_HPP diff --git a/src/http/qhttp/private/qhttpserver_private.hpp b/src/http/qhttp/private/qhttpserver_private.hpp deleted file mode 100644 index e7c081af..00000000 --- a/src/http/qhttp/private/qhttpserver_private.hpp +++ /dev/null @@ -1,90 +0,0 @@ -/** private imeplementation. - * https://github.com/azadkuh/qhttp - * - * @author amir zamani - * @version 2.0.0 - * @date 2014-07-11 - */ - -#ifndef QHTTPSERVER_PRIVATE_HPP -#define QHTTPSERVER_PRIVATE_HPP -/////////////////////////////////////////////////////////////////////////////// - -#include "qhttpserver.hpp" -#include "qhttpserverconnection.hpp" -#include "qhttpserverrequest.hpp" -#include "qhttpserverresponse.hpp" - -#include -#include -/////////////////////////////////////////////////////////////////////////////// -namespace qhttp { -namespace server { -/////////////////////////////////////////////////////////////////////////////// - -class QHttpServerPrivate -{ -public: - template - class BackendServer : public TServer - { - public: - QHttpServer* iserver; - - explicit BackendServer(QHttpServer* s) : TServer(s), iserver(s) { - } - - protected: - // if it's a QTcpServer - virtual void incomingConnection(qintptr socketDescriptor) { - iserver->incomingConnection(socketDescriptor); - } - - // if it's a QLocalServer - virtual void incomingConnection(quintptr socketDescriptor) { - iserver->incomingConnection(static_cast(socketDescriptor)); - } - }; - - using TTcpServer = QScopedPointer>; - using TLocalServer = QScopedPointer>; - -public: - quint32 itimeOut = 0; - TServerHandler ihandler = nullptr; - - TBackend ibackend = ETcpSocket; - - TTcpServer itcpServer; - TLocalServer ilocalServer; - -public: - explicit QHttpServerPrivate() { - QHTTP_LINE_DEEPLOG - } - - virtual ~QHttpServerPrivate() { - QHTTP_LINE_DEEPLOG - } - - void initialize(TBackend backend, QHttpServer* parent) { - ibackend = backend; - - if ( ibackend == ETcpSocket || ibackend == ESslSocket ) { - itcpServer.reset( new BackendServer(parent) ); - ilocalServer.reset( nullptr ); - - } else if ( ibackend == ELocalSocket ) { - itcpServer.reset( nullptr ); - ilocalServer.reset( new BackendServer(parent) ); - } - } - -}; - -/////////////////////////////////////////////////////////////////////////////// -} // namespace server -} // namespace qhttp -/////////////////////////////////////////////////////////////////////////////// - -#endif // QHTTPSERVER_PRIVATE_HPP diff --git a/src/http/qhttp/private/qhttpserverconnection_private.hpp b/src/http/qhttp/private/qhttpserverconnection_private.hpp deleted file mode 100644 index 53b349fa..00000000 --- a/src/http/qhttp/private/qhttpserverconnection_private.hpp +++ /dev/null @@ -1,201 +0,0 @@ -/** private imeplementation. - * https://github.com/azadkuh/qhttp - * - * @author amir zamani - * @version 2.0.0 - * @date 2014-07-11 - */ - -#ifndef QHTTPSERVER_CONNECTION_PRIVATE_HPP -#define QHTTPSERVER_CONNECTION_PRIVATE_HPP -/////////////////////////////////////////////////////////////////////////////// - -#include "qhttpserverconnection.hpp" -#include "httpparser.hxx" -#include "qhttpserverrequest.hpp" -#include "qhttpserverresponse.hpp" - -#include "private/qhttpserverrequest_private.hpp" -#include "private/qhttpserverresponse_private.hpp" - -#include -#include -/////////////////////////////////////////////////////////////////////////////// -namespace qhttp { -namespace server { -/////////////////////////////////////////////////////////////////////////////// -class QHttpConnectionPrivate : - public details::HttpRequestParser -{ - Q_DECLARE_PUBLIC(QHttpConnection) - -public: - explicit QHttpConnectionPrivate(QHttpConnection* q) : q_ptr(q) { - - QObject::connect( - q_func(), &QHttpConnection::disconnected, - [this](){ release(); } - ); - - QHTTP_LINE_DEEPLOG - } - - virtual ~QHttpConnectionPrivate() { - QHTTP_LINE_DEEPLOG - } - - void createSocket(qintptr sokDesc, TBackend bend) { - isocket.ibackendType = bend; - - if ( bend == ETcpSocket ) { - initTcpSocket(sokDesc); - - } else if ( bend == ESslSocket) { - initSslSocket(sokDesc); - - } else if ( bend == ELocalSocket ) { - initLocalSocket(sokDesc); - } - } - - void release() { - // if socket drops and http_parser can not call - // messageComplete, dispatch the ilastRequest - finalizeConnection(); - - isocket.disconnectAllQtConnections(); - isocket.release(); - - if ( ilastRequest ) { - ilastRequest->deleteLater(); - ilastRequest = nullptr; - } - - if ( ilastResponse ) { - ilastResponse->deleteLater(); - ilastResponse = nullptr; - } - - q_func()->deleteLater(); - } - -public: - void onReadyRead() { - while ( isocket.bytesAvailable() > 0 ) { - char buffer[4097] = {0}; - size_t readLength = static_cast(isocket.readRaw(buffer, 4096)); - - parse(buffer, readLength); - } - } - - void finalizeConnection() { - if ( ilastRequest == nullptr ) - return; - - ilastRequest->d_func()->finalizeSending([this]{ - emit ilastRequest->end(); - }); - } - -public: - int messageBegin(http_parser* parser); - int url(http_parser* parser, const char* at, size_t length); - int status(http_parser*, const char*, size_t) { - return 0; // not used in parsing incoming request. - } - int headerField(http_parser* parser, const char* at, size_t length); - int headerValue(http_parser* parser, const char* at, size_t length); - int headersComplete(http_parser* parser); - int body(http_parser* parser, const char* at, size_t length); - int messageComplete(http_parser* parser); - -private: - void initTcpSocket(qintptr sokDesc) { - QTcpSocket* sok = new QTcpSocket( q_func() ); - isocket.itcpSocket = sok; - sok->setSocketDescriptor(sokDesc); - - QObject::connect( - sok, &QTcpSocket::readyRead, - [this](){ onReadyRead(); } - ); - QObject::connect( - sok, &QTcpSocket::bytesWritten, - [this](){ - auto btw = isocket.itcpSocket->bytesToWrite(); - if ( btw == 0 && ilastResponse ) - emit ilastResponse->allBytesWritten(); - }); - QObject::connect( - sok, &QTcpSocket::disconnected, - q_func(), &QHttpConnection::disconnected, - Qt::QueuedConnection - ); - } - - void initSslSocket(qintptr sokDesc) { - QSslSocket* sok = new QSslSocket( q_func() ); - isocket.itcpSocket = sok; - sok->setSocketDescriptor(sokDesc); - - QObject::connect( - sok, &QSslSocket::readyRead, - [this](){ onReadyRead(); } - ); - QObject::connect( - sok, &QSslSocket::bytesWritten, - [this](){ - auto btw = isocket.itcpSocket->bytesToWrite(); - if ( btw == 0 && ilastResponse ) - emit ilastResponse->allBytesWritten(); - }); - QObject::connect( - sok, &QSslSocket::disconnected, - q_func(), &QHttpConnection::disconnected, - Qt::QueuedConnection - ); - } - - void initLocalSocket(qintptr sokDesc) { - QLocalSocket* sok = new QLocalSocket( q_func() ); - isocket.ilocalSocket = sok; - sok->setSocketDescriptor(sokDesc); - - QObject::connect( - sok, &QLocalSocket::readyRead, - [this](){ onReadyRead(); } - ); - QObject::connect( - sok, &QLocalSocket::bytesWritten, - [this](){ - auto btw = isocket.ilocalSocket->bytesToWrite(); - if ( btw == 0 && ilastResponse ) - emit ilastResponse->allBytesWritten(); - }); - QObject::connect( - sok, &QLocalSocket::disconnected, - q_func(), &QHttpConnection::disconnected, - Qt::QueuedConnection - ); - } - -protected: - QHttpConnection* const q_ptr; - - QByteArray itempUrl; - - // Since there can only be one request/response pair per connection at any - // time even with pipelining. - QHttpRequest* ilastRequest = nullptr; - QHttpResponse* ilastResponse = nullptr; - - TServerHandler ihandler = nullptr; - -}; - -/////////////////////////////////////////////////////////////////////////////// -} // namespace server -} // namespace qhttp -/////////////////////////////////////////////////////////////////////////////// -#endif // QHTTPSERVER_CONNECTION_PRIVATE_HPP diff --git a/src/http/qhttp/private/qhttpserverrequest_private.hpp b/src/http/qhttp/private/qhttpserverrequest_private.hpp deleted file mode 100644 index c101d0b1..00000000 --- a/src/http/qhttp/private/qhttpserverrequest_private.hpp +++ /dev/null @@ -1,51 +0,0 @@ -/** private imeplementation. - * https://github.com/azadkuh/qhttp - * - * @author amir zamani - * @version 2.0.0 - * @date 2014-07-11 - */ - -#ifndef QHTTPSERVER_REQUEST_PRIVATE_HPP -#define QHTTPSERVER_REQUEST_PRIVATE_HPP -/////////////////////////////////////////////////////////////////////////////// - -#include "httpreader.hxx" -#include "qhttpserverrequest.hpp" -#include "qhttpserverconnection.hpp" - -/////////////////////////////////////////////////////////////////////////////// -namespace qhttp { -namespace server { -/////////////////////////////////////////////////////////////////////////////// -class QHttpRequestPrivate : - public details::HttpReader -{ -protected: - Q_DECLARE_PUBLIC(QHttpRequest) - QHttpRequest* const q_ptr; - -public: - explicit QHttpRequestPrivate(QHttpConnection* conn, QHttpRequest* q) : q_ptr(q), iconnection(conn) { - QHTTP_LINE_DEEPLOG - } - - virtual ~QHttpRequestPrivate() { - QHTTP_LINE_DEEPLOG - } - - void initialize() { - } - -public: - QString iremoteAddress; - quint16 iremotePort = 0; - - QHttpConnection* const iconnection = nullptr; -}; - -/////////////////////////////////////////////////////////////////////////////// -} // namespace server -} // namespace qhttp -/////////////////////////////////////////////////////////////////////////////// -#endif // QHTTPSERVER_REQUEST_PRIVATE_HPP diff --git a/src/http/qhttp/private/qhttpserverresponse_private.hpp b/src/http/qhttp/private/qhttpserverresponse_private.hpp deleted file mode 100644 index 6c1cd4d9..00000000 --- a/src/http/qhttp/private/qhttpserverresponse_private.hpp +++ /dev/null @@ -1,62 +0,0 @@ -/** private imeplementation. - * https://github.com/azadkuh/qhttp - * - * @author amir zamani - * @version 2.0.0 - * @date 2014-07-11 - */ - -#ifndef QHTTPSERVER_RESPONSE_PRIVATE_HPP -#define QHTTPSERVER_RESPONSE_PRIVATE_HPP -/////////////////////////////////////////////////////////////////////////////// -#include "httpwriter.hxx" -#include "qhttpserverresponse.hpp" -#include "qhttpserver.hpp" -#include "qhttpserverconnection.hpp" - -#include -#include -#include - -/////////////////////////////////////////////////////////////////////////////// -namespace qhttp { -namespace server { -/////////////////////////////////////////////////////////////////////////////// -class QHttpResponsePrivate : - public details::HttpWriter -{ - Q_DECLARE_PUBLIC(QHttpResponse) - -public: - explicit QHttpResponsePrivate(QHttpConnection* conn, QHttpResponse* q) - : q_ptr(q), iconnection(conn) { - QHTTP_LINE_DEEPLOG - } - - virtual ~QHttpResponsePrivate() { - QHTTP_LINE_DEEPLOG - } - - void initialize() { - isocket.ibackendType = iconnection->backendType(); - isocket.ilocalSocket = iconnection->localSocket(); - isocket.itcpSocket = iconnection->tcpSocket(); - - QObject::connect(iconnection, &QHttpConnection::disconnected, - q_func(), &QHttpResponse::deleteLater); - } - - QByteArray makeTitle(); - - void prepareHeadersToWrite(); - -protected: - QHttpResponse* const q_ptr; - QHttpConnection* const iconnection; -}; - -/////////////////////////////////////////////////////////////////////////////// -} // namespace server -} // namespace qhttp -/////////////////////////////////////////////////////////////////////////////// -#endif // QHTTPSERVER_RESPONSE_PRIVATE_HPP diff --git a/src/http/qhttp/private/qsocket.hpp b/src/http/qhttp/private/qsocket.hpp deleted file mode 100644 index 06b35c55..00000000 --- a/src/http/qhttp/private/qsocket.hpp +++ /dev/null @@ -1,131 +0,0 @@ -/** @file qsocket.hpp - * - * @copyright (C) 2016 - * @date 2016.05.26 - * @version 1.0.0 - * @author amir zamani - * - */ - -#ifndef __QHTTP_SOCKET_HPP__ -#define __QHTTP_SOCKET_HPP__ - -#include "qhttpfwd.hpp" - -#include -#include -#include -#include -/////////////////////////////////////////////////////////////////////////////// -namespace qhttp { -namespace details { -/////////////////////////////////////////////////////////////////////////////// - -/** an adapter for different socket types. - * the main purpose of QHttp was to create a small HTTP server with ability to - * support UNIX sockets (QLocalSocket) - */ -class QSocket -{ -public: - void close() { - if ( itcpSocket ) - itcpSocket->close(); - - if ( ilocalSocket ) - ilocalSocket->close(); - } - - void release() { - close(); - if ( itcpSocket ) - itcpSocket->deleteLater(); - - if ( ilocalSocket ) - ilocalSocket->deleteLater(); - - itcpSocket = nullptr; - ilocalSocket = nullptr; - } - - void flush() { - if ( itcpSocket ) - itcpSocket->flush(); - - else if ( ilocalSocket ) - ilocalSocket->flush(); - } - - bool isOpen() const { - if ( ibackendType == ETcpSocket && itcpSocket ) - return itcpSocket->isOpen() - && itcpSocket->state() == QTcpSocket::ConnectedState; - - else if ( ibackendType == ELocalSocket && ilocalSocket ) - return ilocalSocket->isOpen() - && ilocalSocket->state() == QLocalSocket::ConnectedState; - - return false; - } - - void connectTo(const QUrl& url) { - if ( ilocalSocket ) - ilocalSocket->connectToServer(url.path()); - } - - void connectTo(const QString& host, quint16 port) { - if ( itcpSocket ) { - if ( ibackendType == ESslSocket ) - static_cast(itcpSocket)->connectToHostEncrypted(host, port); - else - itcpSocket->connectToHost(host, port); - } - } - - qint64 readRaw(char* buffer, int maxlen) { - if ( itcpSocket ) - return itcpSocket->read(buffer, maxlen); - - else if ( ilocalSocket ) - return ilocalSocket->read(buffer, maxlen); - - return 0; - } - - void writeRaw(const QByteArray& data) { - if ( itcpSocket ) - itcpSocket->write(data); - - else if ( ilocalSocket ) - ilocalSocket->write(data); - } - - qint64 bytesAvailable() { - if ( itcpSocket ) - return itcpSocket->bytesAvailable(); - - else if ( ilocalSocket ) - return ilocalSocket->bytesAvailable(); - - return 0; - } - - void disconnectAllQtConnections() { - if ( itcpSocket ) - QObject::disconnect(itcpSocket, 0, 0, 0); - - if ( ilocalSocket ) - QObject::disconnect(ilocalSocket, 0, 0, 0); - } - -public: - TBackend ibackendType = ETcpSocket; - QTcpSocket* itcpSocket = nullptr; - QLocalSocket* ilocalSocket = nullptr; -}; // class QSocket - -/////////////////////////////////////////////////////////////////////////////// -} // namespace details -} // namespace qhttp -/////////////////////////////////////////////////////////////////////////////// -#endif // __QHTTP_SOCKET_HPP__ diff --git a/src/http/qhttp/qhttpabstracts.cpp b/src/http/qhttp/qhttpabstracts.cpp deleted file mode 100644 index a29a90b9..00000000 --- a/src/http/qhttp/qhttpabstracts.cpp +++ /dev/null @@ -1,114 +0,0 @@ -#include "qhttpabstracts.hpp" -#include "http-parser/http_parser.h" - -/////////////////////////////////////////////////////////////////////////////// -namespace qhttp { -/////////////////////////////////////////////////////////////////////////////// -#if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0)) -# error "to compile QHttp classes, Qt 5.0 or later is needed." -#endif - -#define QHTTPABSTRACTS_HTTP_STATUS_MAP(XX) \ - XX(100, "Continue") \ - XX(101, "Switching Protocols") \ - /* RFC 2518) obsoleted by RFC 4918 */ \ - XX(102, "Processing") \ - XX(200, "OK") \ - XX(201, "Created") \ - XX(202, "Accepted") \ - XX(203, "Non-Authoritative Information") \ - XX(204, "No Content") \ - XX(205, "Reset Content") \ - XX(206, "Partial Content") \ - /* RFC 4918 */ \ - XX(207, "Multi-Status") \ - XX(300, "Multiple Choices") \ - XX(301, "Moved Permanently") \ - XX(302, "Moved Temporarily") \ - XX(303, "See Other") \ - XX(304, "Not Modified") \ - XX(305, "Use Proxy") \ - XX(307, "Temporary Redirect") \ - XX(400, "Bad Request") \ - XX(401, "Unauthorized") \ - XX(402, "Payment Required") \ - XX(403, "Forbidden") \ - XX(404, "Not Found") \ - XX(405, "Method Not Allowed") \ - XX(406, "Not Acceptable") \ - XX(407, "Proxy Authentication Required") \ - XX(408, "Request Time-out") \ - XX(409, "Conflict") \ - XX(410, "Gone") \ - XX(411, "Length Required") \ - XX(412, "Precondition Failed") \ - XX(413, "Request Entity Too Large") \ - XX(414, "Request-URI Too Large") \ - XX(415, "Unsupported Media Type") \ - XX(416, "Requested Range Not Satisfiable") \ - XX(417, "Expectation Failed") \ - /* RFC 2324 */ \ - XX(418, "I\"m a teapot") \ - /* RFC 4918 */ \ - XX(422, "Unprocessable Entity") \ - /* RFC 4918 */ \ - XX(423, "Locked") \ - /* RFC 4918 */ \ - XX(424, "Failed Dependency") \ - /* RFC 4918 */ \ - XX(425, "Unordered Collection") \ - /* RFC 2817 */ \ - XX(426, "Upgrade Required") \ - XX(500, "Internal Server Error") \ - XX(501, "Not Implemented") \ - XX(502, "Bad Gateway") \ - XX(503, "Service Unavailable") \ - XX(504, "Gateway Time-out") \ - XX(505, "HTTP Version not supported") \ - /* RFC 2295 */ \ - XX(506, "Variant Also Negotiates") \ - /* RFC 4918 */ \ - XX(507, "Insufficient Storage") \ - XX(509, "Bandwidth Limit Exceeded") \ - /* RFC 2774 */ \ - XX(510, "Not Extended") - -#define PATCH_STATUS_CODES(n,s) {n, s}, -static struct { - int code; - const char* message; -} g_status_codes[] { - QHTTPABSTRACTS_HTTP_STATUS_MAP(PATCH_STATUS_CODES) -}; -#undef PATCH_STATUS_CODES - -/////////////////////////////////////////////////////////////////////////////// - -const char* -Stringify::toString(TStatusCode code) { - size_t count = sizeof(g_status_codes) / sizeof(g_status_codes[0]); - for ( size_t i = 0; i < count; i++ ) { - if ( g_status_codes[i].code == code ) - return g_status_codes[i].message; - } - - return nullptr; -} - -const char* -Stringify::toString(THttpMethod method) { - return http_method_str(static_cast(method)); -} - -/////////////////////////////////////////////////////////////////////////////// - -QHttpAbstractInput::QHttpAbstractInput(QObject* parent) : QObject(parent) { -} - -QHttpAbstractOutput::QHttpAbstractOutput(QObject *parent) : QObject(parent) { -} - - -/////////////////////////////////////////////////////////////////////////////// -} // namespace qhttp -/////////////////////////////////////////////////////////////////////////////// diff --git a/src/http/qhttp/qhttpabstracts.hpp b/src/http/qhttp/qhttpabstracts.hpp deleted file mode 100644 index 005b9ce5..00000000 --- a/src/http/qhttp/qhttpabstracts.hpp +++ /dev/null @@ -1,190 +0,0 @@ -/** interfaces of QHttp' incomming and outgoing classes. - * https://github.com/azadkuh/qhttp - * - * @author amir zamani - * @version 2.0.0 - * @date 2014-07-11 - */ - -#ifndef QHTTPABSTRACTS_HPP -#define QHTTPABSTRACTS_HPP - -/////////////////////////////////////////////////////////////////////////////// -#include "qhttpfwd.hpp" - -#include -#include -/////////////////////////////////////////////////////////////////////////////// -namespace qhttp { -/////////////////////////////////////////////////////////////////////////////// - -/** a utility class to give the string representation of qhttp types. */ -class QHTTP_API Stringify -{ -public: - /** returns the standard message for an HTTP status code. */ - static const char* toString(TStatusCode); - - /** returns the standars name of an HTTP method. */ - static const char* toString(THttpMethod); -}; - -/////////////////////////////////////////////////////////////////////////////// - -/** an interface for input (incoming) HTTP packets. - * server::QHttpRequest or client::QHttpResponse inherit from this class. */ -class QHTTP_API QHttpAbstractInput : public QObject -{ - Q_OBJECT - -public: - /** Return all the headers in the incomming packet. - * This returns a reference. If you want to store headers - * somewhere else, where the request may be deleted, - * make sure you store them as a copy. - * @note All header names are lowercase . */ - virtual const THeaderHash& headers() const=0; - - /** The HTTP version of the packet. - * @return A string in the form of "x.x" */ - virtual const QString& httpVersion() const=0; - - /** If this packet was successfully received. - * Set before end() has been emitted, stating whether - * the message was properly received. This is false - * until the receiving the full request has completed. */ - virtual bool isSuccessful() const=0; - -signals: - /** Emitted when new body data has been received. - * @param data Received data. - * @note This may be emitted zero or more times depending on the transfer type. - * @see onData(); - */ - void data(QByteArray data); - - /** Emitted when the incomming packet has been fully received. - * @note The no more data() signals will be emitted after this. - * @see onEnd(); - */ - void end(); - -public: - /** optionally set a handler for data() signal. - * @param dataHandler a std::function or lambda handler to receive incoming data. - * @note if you set this handler, the data() signal won't be emitted anymore. - */ - template - void onData(Func f) { - QObject::connect(this, &QHttpAbstractInput::data, f); - } - - - /** optionally set a handler for end() signal. - * @param endHandler a std::function or lambda handler to receive end notification. - * @note if you set this handler, the end() signal won't be emitted anymore. - */ - template - void onEnd(Func f) { - QObject::connect(this, &QHttpAbstractInput::end, f); - } - -public: - /** tries to collect all the incoming data internally. - * @note if you call this method, data() signal won't be emitted and - * onData() will have no effect. - * - * @param atMost maximum acceptable incoming data. if the incoming data - * exceeds this value, the connection won't read any more data and - * end() signal will be emitted. - * default value (-1) means read data as "content-length" or unlimited if - * the body size is unknown. - */ - virtual void collectData(int atMost = -1) =0; - - /** returns the collected data requested by collectData(). */ - virtual const QByteArray& collectedData()const =0; - - -public: - virtual ~QHttpAbstractInput() = default; - - explicit QHttpAbstractInput(QObject* parent); - - Q_DISABLE_COPY(QHttpAbstractInput) -}; - -/////////////////////////////////////////////////////////////////////////////// - -/** an interface for output (outgoing) HTTP packets. - * server::QHttpResponse or client::QHttpRequest inherit from this class. */ -class QHTTP_API QHttpAbstractOutput : public QObject -{ - Q_OBJECT - -public: - /** changes the HTTP version string ex: "1.1" or "1.0". - * version is "1.1" set by default. */ - virtual void setVersion(const QString& versionString)=0; - - /** helper function. @sa addHeader */ - template - void addHeaderValue(const QByteArray &field, T value); - - /** adds an HTTP header to the packet. - * @note this method does not actually write anything to socket, just prepares the headers(). */ - virtual void addHeader(const QByteArray& field, const QByteArray& value)=0; - - /** returns all the headers that already been set. */ - virtual THeaderHash& headers()=0; - - /** writes a block of data into the HTTP packet. - * @note headers are written (flushed) before any data. - * @warning after calling this method add a new header, set staus code, set Url have no effect! */ - virtual void write(const QByteArray &data)=0; - - /** ends (finishes) the outgoing packet by calling write(). - * headers and data will be flushed to the underlying socket. - * - * @sa write() */ - virtual void end(const QByteArray &data = QByteArray())=0; - -signals: - /** Emitted when all the data has been sent. - * this signal indicates that the underlaying socket has transmitted all - * of it's buffered data. */ - void allBytesWritten(); - - /** Emitted when the packet is finished and reports if it was the last packet. - * if it was the last packet (google for "Connection: keep-alive / close") - * the http connection (socket) will be closed automatically. */ - void done(bool wasTheLastPacket); - -public: - virtual ~QHttpAbstractOutput() = default; - -protected: - explicit QHttpAbstractOutput(QObject* parent); - - Q_DISABLE_COPY(QHttpAbstractOutput) -}; - -template<> inline void -QHttpAbstractOutput::addHeaderValue(const QByteArray &field, int value) { - addHeader(field, QString::number(value).toLatin1()); -} - -template<> inline void -QHttpAbstractOutput::addHeaderValue(const QByteArray &field, size_t value) { - addHeader(field, QString::number(value).toLatin1()); -} - -template<> inline void -QHttpAbstractOutput::addHeaderValue(const QByteArray &field, QString value) { - addHeader(field, value.toUtf8()); -} - -/////////////////////////////////////////////////////////////////////////////// -} // namespace qhttp -/////////////////////////////////////////////////////////////////////////////// -#endif // QHTTPABSTRACTS_HPP diff --git a/src/http/qhttp/qhttpclient.cpp b/src/http/qhttp/qhttpclient.cpp deleted file mode 100644 index b77645ec..00000000 --- a/src/http/qhttp/qhttpclient.cpp +++ /dev/null @@ -1,286 +0,0 @@ -#include "private/qhttpclient_private.hpp" - -#include -/////////////////////////////////////////////////////////////////////////////// -namespace qhttp { -namespace client { -/////////////////////////////////////////////////////////////////////////////// -QHttpClient::QHttpClient(QObject *parent) - : QObject(parent), d_ptr(new QHttpClientPrivate(this)) { - QHTTP_LINE_LOG -} - -QHttpClient::QHttpClient(QHttpClientPrivate &dd, QObject *parent) - : QObject(parent), d_ptr(&dd) { - QHTTP_LINE_LOG -} - -QHttpClient::~QHttpClient() { - QHTTP_LINE_LOG -} - -quint32 -QHttpClient::timeOut() const { - return d_func()->itimeOut; -} - -void -QHttpClient::setTimeOut(quint32 t) { - d_func()->itimeOut = t; -} - -bool -QHttpClient::isOpen() const { - return d_func()->isocket.isOpen(); -} - -void -QHttpClient::killConnection() { - Q_D(QHttpClient); - - d->iconnectingTimer.stop(); - d->itimer.stop(); - d->isocket.close(); -} - -TBackend -QHttpClient::backendType() const { - return d_func()->isocket.ibackendType; -} - -QTcpSocket* -QHttpClient::tcpSocket() const { - return d_func()->isocket.itcpSocket; -} - -QLocalSocket* -QHttpClient::localSocket() const { - return d_func()->isocket.ilocalSocket; -} - -void -QHttpClient::setConnectingTimeOut(quint32 timeout) { - Q_D(QHttpClient); - - if ( timeout == 0 ) { - d->iconnectingTimer.stop(); - - } else { - d->iconnectingTimer.start(timeout, - Qt::CoarseTimer, - this - ); - } -} - -bool -QHttpClient::request(THttpMethod method, QUrl url, - const TRequstHandler &reqHandler, - const TResponseHandler &resHandler) { - Q_D(QHttpClient); - - d->ireqHandler = nullptr; - d->irespHandler = nullptr; - - // if url is a local file (UNIX socket) the host could be empty! - if ( !url.isValid() || url.isEmpty() /*|| url.host().isEmpty()*/ ) - return false; - - // process handlers - if ( resHandler ) { - d->irespHandler = resHandler; - - if ( reqHandler ) - d->ireqHandler = reqHandler; - else - d->ireqHandler = [](QHttpRequest* req) ->void { - req->addHeader("connection", "close"); - req->end(); - }; - } - - auto requestCreator = [this, method, url]() { - // create request object - if ( d_ptr->ilastRequest ) - d_ptr->ilastRequest->deleteLater(); - - d_ptr->ilastRequest = new QHttpRequest(this); - QObject::connect(d_ptr->ilastRequest, &QHttpRequest::done, [this](bool wasTheLastPacket){ - d_ptr->ikeepAlive = !wasTheLastPacket; - }); - - d_ptr->ilastRequest->d_ptr->imethod = method; - d_ptr->ilastRequest->d_ptr->iurl = url; - }; - - // connecting to host/server must be the last thing. (after all function handlers and ...) - // check for type - if ( url.scheme().toLower() == QLatin1String("file") ) { - d->isocket.ibackendType = ELocalSocket; - d->initializeSocket(); - - requestCreator(); - - if ( d->isocket.isOpen() ) - d->onConnected(); - else - d->isocket.connectTo(url); - - } else { - bool ssl = url.scheme() == "https"; - - d->isocket.ibackendType = ssl ? ESslSocket : ETcpSocket; - d->initializeSocket(); - - requestCreator(); - - if ( d->isocket.isOpen() ) - d->onConnected(); - else - d->isocket.connectTo(url.host(), url.port(ssl ? 443 : 80)); - } - - return true; -} - -void -QHttpClient::timerEvent(QTimerEvent *e) { - Q_D(QHttpClient); - - if ( e->timerId() == d->itimer.timerId() ) { - killConnection(); - - } else if ( e->timerId() == d->iconnectingTimer.timerId() ) { - d->iconnectingTimer.stop(); - emit connectingTimeOut(); - } -} - -void -QHttpClient::onRequestReady(QHttpRequest *req) { - emit httpConnected(req); -} - -void -QHttpClient::onResponseReady(QHttpResponse *res) { - emit newResponse(res); -} - -/////////////////////////////////////////////////////////////////////////////// - -// if server closes the connection, ends the response or by any other reason -// the socket disconnects, then the irequest and iresponse instances may have -// been deleted. In these situations reading more http body or emitting end() -// for incoming request are not possible: -// if ( ilastRequest == nullptr ) -// return 0; - - - -int -QHttpClientPrivate::messageBegin(http_parser*) { - itempHeaderField.clear(); - itempHeaderValue.clear(); - - return 0; -} - -int -QHttpClientPrivate::status(http_parser* parser, const char* at, size_t length) { - if ( ilastResponse ) - ilastResponse->deleteLater(); - - ilastResponse = new QHttpResponse(q_func()); - ilastResponse->d_func()->istatus = static_cast(parser->status_code); - ilastResponse->d_func()->iversion = QString("%1.%2") - .arg(parser->http_major) - .arg(parser->http_minor); - ilastResponse->d_func()->icustomStatusMessage = QString::fromUtf8(at, length); - - return 0; -} - -int -QHttpClientPrivate::headerField(http_parser*, const char* at, size_t length) { - if ( ilastResponse == nullptr ) - return 0; - - // insert the header we parsed previously - // into the header map - if ( !itempHeaderField.isEmpty() && !itempHeaderValue.isEmpty() ) { - // header names are always lower-cased - ilastResponse->d_func()->iheaders.insert( - itempHeaderField.toLower(), - itempHeaderValue.toLower() - ); - // clear header value. this sets up a nice - // feedback loop where the next time - // HeaderValue is called, it can simply append - itempHeaderField.clear(); - itempHeaderValue.clear(); - } - - itempHeaderField.append(at, length); - return 0; -} - -int -QHttpClientPrivate::headerValue(http_parser*, const char* at, size_t length) { - - itempHeaderValue.append(at, length); - return 0; -} - -int -QHttpClientPrivate::headersComplete(http_parser*) { - if ( ilastResponse == nullptr ) - return 0; - - // Insert last remaining header - ilastResponse->d_func()->iheaders.insert( - itempHeaderField.toLower(), - itempHeaderValue.toLower() - ); - - if ( irespHandler ) - irespHandler(ilastResponse); - else - q_func()->onResponseReady(ilastResponse); - - return 0; -} - -int -QHttpClientPrivate::body(http_parser*, const char* at, size_t length) { - if ( ilastResponse == nullptr ) - return 0; - - ilastResponse->d_func()->ireadState = QHttpResponsePrivate::EPartial; - - if ( ilastResponse->d_func()->icollectRequired ) { - if ( !ilastResponse->d_func()->append(at, length) ) { - // forcefully dispatch the ilastResponse - finalizeConnection(); - } - - return 0; - } - - emit ilastResponse->data(QByteArray(at, length)); - return 0; -} - -int -QHttpClientPrivate::messageComplete(http_parser*) { - if ( ilastResponse == nullptr ) - return 0; - - // response is done - finalizeConnection(); - return 0; -} - -/////////////////////////////////////////////////////////////////////////////// -} // namespace client -} // namespace qhttp -/////////////////////////////////////////////////////////////////////////////// diff --git a/src/http/qhttp/qhttpclient.hpp b/src/http/qhttp/qhttpclient.hpp deleted file mode 100644 index f73e7b7f..00000000 --- a/src/http/qhttp/qhttpclient.hpp +++ /dev/null @@ -1,179 +0,0 @@ -/** HTTP client class. - * https://github.com/azadkuh/qhttp - * - * @author amir zamani - * @version 2.0.0 - * @date 2014-07-11 - */ - -#ifndef QHTTPCLIENT_HPP -#define QHTTPCLIENT_HPP - -/////////////////////////////////////////////////////////////////////////////// -#include "qhttpfwd.hpp" - -#include -#include -#include - -/////////////////////////////////////////////////////////////////////////////// -namespace qhttp { -namespace client { -/////////////////////////////////////////////////////////////////////////////// -using TRequstHandler = std::function; -using TResponseHandler = std::function; - -/** a simple and async HTTP client class which sends a request to an HTTP server and parses the - * corresponding response. - * This class internally handles the memory management and life cycle of QHttpRequest and - * QHttpResponse instances. you do not have to manually delete or keep their pointers. - * in fact the QHttpRequest and QHttpResponse object will be deleted when the internal socket - * disconnects. - */ -class QHTTP_API QHttpClient : public QObject -{ - Q_OBJECT - - Q_PROPERTY(quint32 timeOut READ timeOut WRITE setTimeOut) - -public: - explicit QHttpClient(QObject *parent = nullptr); - - virtual ~QHttpClient(); - - /** tries to connect to a HTTP server. - * when the connection is made, the reqHandler will be called - * and when the response is ready, resHandler will be called. - * @note httpConnected() and newResponse() won't be emitted. - * - * @param method an HTTP method, ex: GET, POST, ... - * @param url specifies server's address, port and optional path and query strings. - * if url starts with socket:// the request will be made on QLocalSocket, otherwise - * normal QTcpSocket will be used. - * @param resHandler response handler (a lambda, std::function object, ...) - * @return true if the url is valid or false (no connection will be made). - */ - bool request(THttpMethod method, QUrl url, - const TRequstHandler& reqHandler, - const TResponseHandler& resHandler); - - /** tries to connect to a HTTP server. - * when the connection is made, a default request handler is called automatically ( - * simply calls req->end()) and when the response is ready, resHandler will be called. - * @note httpConnected() and newResponse() won't be emitted. - * - * @param method an HTTP method, ex: GET, POST, ... - * @param url specifies server's address, port and optional path and query strings. - * @param resHandler response handler (a lambda, std::function object, ...) - * @return true if the url is valid or false (no connection will be made). - */ - inline bool request(THttpMethod method, QUrl url, const TResponseHandler& resHandler) { - return request(method, url, nullptr, resHandler); - } - - /** tries to connect to a HTTP server. - * when the connection is made, creates and emits a QHttpRequest instance - * by @sa httpConnected(QHttpRequest*). - * @note both httpConnected() and newResponse() may be emitted. - * - * @param method an HTTP method, ex: GET, POST, ... - * @param url specifies server's address, port and optional path and query strings. - * @return true if the url is valid or false (no connection will be made). - */ - inline bool request(THttpMethod method, QUrl url) { - return request(method, url, nullptr, nullptr); - } - - /** checks if the connetion to the server is open. */ - bool isOpen() const; - - /** forcefully close the connection. */ - void killConnection(); - - - /** returns time-out value [mSec] for ESTABLISHED connections (sockets). - * @sa setTimeOut(). */ - quint32 timeOut()const; - - /** set time-out for ESTABLISHED connections in miliseconds [mSec]. - * each (already opened) connection will be forcefully closed after this timeout. - * a zero (0) value disables timer for new connections. */ - void setTimeOut(quint32); - - /** set a time-out [mSec] for making a new connection (make a request). - * if connecting to server takes more than this time-out value, - * the @sa timedOut(quint32) signal will be emitted and connection will be killed. - * 0 (default) timeout value means to disable this timer. - */ - void setConnectingTimeOut(quint32); - - template - void setConnectingTimeOut(quint32 timeout, Handler&& func) { - setConnectingTimeOut(timeout); - QObject::connect(this, &QHttpClient::connectingTimeOut, - std::forward(func) - ); - } - - /** returns the backend type of this client. */ - TBackend backendType() const; - - /** returns tcp socket of the connection if backend() == ETcpSocket. */ - QTcpSocket* tcpSocket() const; - - /** returns local socket of the connection if backend() == ELocalSocket. */ - QLocalSocket* localSocket() const; - -signals: - /** emitted when a new HTTP connection to the server is established. - * if you overload onRequestReady this signal won't be emitted. - * @sa onRequestReady - * @sa QHttpRequest - */ - void httpConnected(QHttpRequest* req); - - /** emitted when a new response is received from the server. - * if you overload onResponseReady this signal won't be emitted. - * @sa onResponseReady - * @sa QHttpResponse - */ - void newResponse(QHttpResponse* res); - - /** emitted when the HTTP connection drops or being disconnected. */ - void disconnected(); - - /// emitted when fails to connect to a HTTP server. @sa setConnectingTimeOut() - void connectingTimeOut(); - - -protected: - /** called when a new HTTP connection is established. - * you can overload this method, the default implementaion only emits connected(). - * @param req use this request instance for assinging the - * request headers and sending optional body. - * @see httpConnected(QHttpRequest*) - */ - virtual void onRequestReady(QHttpRequest* req); - - /** called when a new response is received from the server. - * you can overload this method, the default implementaion only emits newResponse(). - * @param res use this instance for reading incoming response. - * @see newResponse(QHttpResponse*) - */ - virtual void onResponseReady(QHttpResponse* res); - -protected: - explicit QHttpClient(QHttpClientPrivate&, QObject*); - - void timerEvent(QTimerEvent*) override; - - Q_DECLARE_PRIVATE(QHttpClient) - Q_DISABLE_COPY(QHttpClient) - QScopedPointer d_ptr; -}; - -/////////////////////////////////////////////////////////////////////////////// -} // namespace client -} // namespace qhttp -/////////////////////////////////////////////////////////////////////////////// -#endif // define QHTTPCLIENT_HPP diff --git a/src/http/qhttp/qhttpclientrequest.cpp b/src/http/qhttp/qhttpclientrequest.cpp deleted file mode 100644 index 6d7cd234..00000000 --- a/src/http/qhttp/qhttpclientrequest.cpp +++ /dev/null @@ -1,97 +0,0 @@ -#include "private/qhttpclientrequest_private.hpp" -#include "qhttpclient.hpp" -/////////////////////////////////////////////////////////////////////////////// -namespace qhttp { -namespace client { -/////////////////////////////////////////////////////////////////////////////// -QHttpRequest::QHttpRequest(QHttpClient* cli) - : QHttpAbstractOutput(cli) , d_ptr(new QHttpRequestPrivate(cli, this)) { - d_ptr->initialize(); - QHTTP_LINE_LOG -} - -QHttpRequest::QHttpRequest(QHttpRequestPrivate& dd, QHttpClient* cli) - : QHttpAbstractOutput(cli) , d_ptr(&dd) { - d_ptr->initialize(); - QHTTP_LINE_LOG -} - -QHttpRequest::~QHttpRequest() { - QHTTP_LINE_LOG -} - -void -QHttpRequest::setVersion(const QString &versionString) { - d_func()->iversion = versionString; -} - -void -QHttpRequest::addHeader(const QByteArray &field, const QByteArray &value) { - d_func()->addHeader(field, value); -} - -THeaderHash& -QHttpRequest::headers() { - return d_func()->iheaders; -} - -void -QHttpRequest::write(const QByteArray &data) { - d_func()->writeData(data); -} - -void -QHttpRequest::end(const QByteArray &data) { - Q_D(QHttpRequest); - - if ( d->endPacket(data) ) - emit done(!d->ikeepAlive); -} - -QHttpClient* -QHttpRequest::connection() const { - return d_func()->iclient; -} - -/////////////////////////////////////////////////////////////////////////////// -QByteArray -QHttpRequestPrivate::makeTitle() { - - QByteArray title; - title.reserve(512); - title.append(qhttp::Stringify::toString(imethod)) - .append(" "); - - QByteArray path = iurl.path(QUrl::FullyEncoded).toLatin1(); - if ( path.size() == 0 ) - path = "/"; - title.append(path); - - if ( iurl.hasQuery() ) - title.append("?").append(iurl.query(QUrl::FullyEncoded).toLatin1()); - - - title.append(" HTTP/") - .append(iversion.toLatin1()) - .append("\r\n"); - - return title; -} - -void -QHttpRequestPrivate::prepareHeadersToWrite() { - - if ( !iheaders.contains("host") ) { - QString portStr = ( -1 != iurl.port() ) ? - QString(":%1").arg(iurl.port()) : ""; - - iheaders.insert("host", - QString("%1%2").arg(iurl.host()).arg(portStr).toLatin1() - ); - } -} - -/////////////////////////////////////////////////////////////////////////////// -} // namespace client -} // namespace qhttp -/////////////////////////////////////////////////////////////////////////////// diff --git a/src/http/qhttp/qhttpclientrequest.hpp b/src/http/qhttp/qhttpclientrequest.hpp deleted file mode 100644 index 6a875062..00000000 --- a/src/http/qhttp/qhttpclientrequest.hpp +++ /dev/null @@ -1,63 +0,0 @@ -/** HTTP request from a client. - * https://github.com/azadkuh/qhttp - * - * @author amir zamani - * @version 2.0.0 - * @date 2014-07-11 - */ - -#ifndef QHTTPCLIENT_REQUEST_HPP -#define QHTTPCLIENT_REQUEST_HPP - -/////////////////////////////////////////////////////////////////////////////// -#include "qhttpabstracts.hpp" -#include -/////////////////////////////////////////////////////////////////////////////// -namespace qhttp { -namespace client { -/////////////////////////////////////////////////////////////////////////////// -/** a class for building a new HTTP request. - * the life cycle of this class and the memory management is handled by QHttpClient. - * @sa QHttpClient - */ -class QHTTP_API QHttpRequest : public QHttpAbstractOutput -{ - Q_OBJECT - -public: - virtual ~QHttpRequest(); - -public: // QHttpAbstractOutput methods: - /** @see QHttpAbstractOutput::setVersion(). */ - void setVersion(const QString& versionString) override; - - /** @see QHttpAbstractOutput::addHeader(). */ - void addHeader(const QByteArray& field, const QByteArray& value) override; - - /** @see QHttpAbstractOutput::headers(). */ - THeaderHash& headers() override; - - /** @see QHttpAbstractOutput::write(). */ - void write(const QByteArray &data) override; - - /** @see QHttpAbstractOutput::end(). */ - void end(const QByteArray &data = QByteArray()) override; - -public: - /** returns parent QHttpClient object. */ - QHttpClient* connection() const; - -protected: - explicit QHttpRequest(QHttpClient*); - explicit QHttpRequest(QHttpRequestPrivate&, QHttpClient*); - friend class QHttpClient; - - Q_DECLARE_PRIVATE(QHttpRequest) - QScopedPointer d_ptr; -}; - -/////////////////////////////////////////////////////////////////////////////// -} // namespace client -} // namespace qhttp -/////////////////////////////////////////////////////////////////////////////// -#endif // define QHTTPCLIENT_REQUEST_HPP diff --git a/src/http/qhttp/qhttpclientresponse.cpp b/src/http/qhttp/qhttpclientresponse.cpp deleted file mode 100644 index 182d2b0f..00000000 --- a/src/http/qhttp/qhttpclientresponse.cpp +++ /dev/null @@ -1,66 +0,0 @@ -#include "private/qhttpclientresponse_private.hpp" -#include "qhttpclient.hpp" -/////////////////////////////////////////////////////////////////////////////// -namespace qhttp { -namespace client { -/////////////////////////////////////////////////////////////////////////////// -QHttpResponse::QHttpResponse(QHttpClient *cli) - : QHttpAbstractInput(cli), d_ptr(new QHttpResponsePrivate(cli, this)) { - d_ptr->initialize(); - QHTTP_LINE_LOG -} - -QHttpResponse::QHttpResponse(QHttpResponsePrivate &dd, QHttpClient *cli) - : QHttpAbstractInput(cli), d_ptr(&dd) { - d_ptr->initialize(); - QHTTP_LINE_LOG -} - -QHttpResponse::~QHttpResponse() { - QHTTP_LINE_LOG -} - -TStatusCode -QHttpResponse::status() const { - return d_func()->istatus; -} - -const QString& -QHttpResponse::statusString() const { - return d_func()->icustomStatusMessage; -} - -const QString& -QHttpResponse::httpVersion() const { - return d_func()->iversion; -} - -const THeaderHash& -QHttpResponse::headers() const { - return d_func()->iheaders; -} - -bool -QHttpResponse::isSuccessful() const { - return d_func()->isuccessful; -} - -void -QHttpResponse::collectData(int atMost) { - d_func()->collectData(atMost); -} - -const QByteArray& -QHttpResponse::collectedData() const { - return d_func()->icollectedData; -} - -QHttpClient* -QHttpResponse::connection() const { - return d_func()->iclient; -} - -/////////////////////////////////////////////////////////////////////////////// -} // namespace client -} // namespace qhttp -/////////////////////////////////////////////////////////////////////////////// diff --git a/src/http/qhttp/qhttpclientresponse.hpp b/src/http/qhttp/qhttpclientresponse.hpp deleted file mode 100644 index 37024f0c..00000000 --- a/src/http/qhttp/qhttpclientresponse.hpp +++ /dev/null @@ -1,73 +0,0 @@ -/** HTTP response received by client. - * https://github.com/azadkuh/qhttp - * - * @author amir zamani - * @version 2.0.0 - * @date 2014-07-11 - */ - -#ifndef QHTTPCLIENT_RESPONSE_HPP -#define QHTTPCLIENT_RESPONSE_HPP -/////////////////////////////////////////////////////////////////////////////// - -#include "qhttpabstracts.hpp" - -#include -/////////////////////////////////////////////////////////////////////////////// -namespace qhttp { -namespace client { -/////////////////////////////////////////////////////////////////////////////// -/** a class for reading incoming HTTP response from a server. - * the life cycle of this class and the memory management is handled by QHttpClient. - * @sa QHttpClient - */ -class QHTTP_API QHttpResponse : public QHttpAbstractInput -{ - Q_OBJECT - -public: - virtual ~QHttpResponse(); - -public: // QHttpAbstractInput methods: - /** @see QHttpAbstractInput::headers(). */ - const THeaderHash& headers() const override; - - /** @see QHttpAbstractInput::httpVersion(). */ - const QString& httpVersion() const override; - - /** @see QHttpAbstractInput::isSuccessful(). */ - bool isSuccessful() const override; - - /** @see QHttpAbstractInput::collectData(). */ - void collectData(int atMost = -1) override; - - /** @see QHttpAbstractInput::collectedData(). */ - const QByteArray& collectedData()const override; - - -public: - /** The status code of this response. */ - TStatusCode status() const ; - - /** The server status message as string. - * may be slightly different than: @code qhttp::Stringify::toString(status()); @endcode - * depending on implementation of HTTP server. */ - const QString& statusString() const; - - /** returns parent QHttpClient object. */ - QHttpClient* connection() const; - -protected: - explicit QHttpResponse(QHttpClient*); - explicit QHttpResponse(QHttpResponsePrivate&, QHttpClient*); - friend class QHttpClientPrivate; - - Q_DECLARE_PRIVATE(QHttpResponse) - QScopedPointer d_ptr; -}; - -/////////////////////////////////////////////////////////////////////////////// -} // namespace client -} // namespace qhttp -/////////////////////////////////////////////////////////////////////////////// -#endif // define QHTTPCLIENT_RESPONSE_HPP diff --git a/src/http/qhttp/qhttpfwd.hpp b/src/http/qhttp/qhttpfwd.hpp deleted file mode 100644 index d6f38db8..00000000 --- a/src/http/qhttp/qhttpfwd.hpp +++ /dev/null @@ -1,216 +0,0 @@ -/** forward declarations and general definitions of the QHttp. - * https://github.com/azadkuh/qhttp - * - * @author amir zamani - * @version 2.0.0 - * @date 2014-07-11 - */ - -#ifndef QHTTPFWD_HPP -#define QHTTPFWD_HPP -/////////////////////////////////////////////////////////////////////////////// -#include -#include -#include - -#include -/////////////////////////////////////////////////////////////////////////////// -// Qt -class QTcpServer; -class QTcpSocket; -class QLocalServer; -class QLocalSocket; - -// http_parser -struct http_parser_settings; -struct http_parser; - -/////////////////////////////////////////////////////////////////////////////// -namespace qhttp { -/////////////////////////////////////////////////////////////////////////////// - -/** A map of request or response headers. */ -class THeaderHash : public QHash -{ -public: - /** checks for a header item, regardless of the case of the characters. */ - bool has(const QByteArray& key) const { - return contains(key.toLower()); - } - - /** checks if a header has the specified value ignoring the case of the characters. */ - bool keyHasValue(const QByteArray& key, const QByteArray& value) const { - if ( !contains(key) ) - return false; - - const QByteArray& v = QHash::value(key); - return qstrnicmp(value.constData(), v.constData(), v.size()) == 0; - } -}; - -/// QHash/QMap iterators are incompatibility with range for -template -void for_each(Iterator first, Iterator last, Func&& f) { - while ( first != last ) { - f( first ); - ++first; - } -} - - -/** Request method enumeration. - * @note Taken from http_parser.h */ -enum THttpMethod { - EHTTP_DELETE = 0, ///< DELETE - EHTTP_GET = 1, ///< GET - EHTTP_HEAD = 2, ///< HEAD - EHTTP_POST = 3, ///< POST - EHTTP_PUT = 4, ///< PUT - /* pathological */ - EHTTP_CONNECT = 5, ///< CONNECT - EHTTP_OPTIONS = 6, ///< OPTIONS - EHTTP_TRACE = 7, ///< TRACE - /* webdav */ - EHTTP_COPY = 8, ///< COPY - EHTTP_LOCK = 9, ///< LOCK - EHTTP_MKCOL = 10, ///< MKCOL - EHTTP_MOVE = 11, ///< MOVE - EHTTP_PROPFIND = 12, ///< PROPFIND - EHTTP_PROPPATCH = 13, ///< PROPPATCH - EHTTP_SEARCH = 14, ///< SEARCH - EHTTP_UNLOCK = 15, ///< UNLOCK - EHTTP_BIND = 16, ///< BIND - EHTTP_REBIND = 17, ///< REBIND - EHTTP_UNBIND = 18, ///< UNBIND - EHTTP_ACL = 19, ///< ACL - /* subversion */ - EHTTP_REPORT = 20, ///< REPORT - EHTTP_MKACTIVITY = 21, ///< MKACTIVITY - EHTTP_CHECKOUT = 22, ///< CHECKOUT - EHTTP_MERGE = 23, ///< MERGE - /* upnp */ - EHTTP_MSEARCH = 24, ///< M-SEARCH - EHTTP_NOTIFY = 25, ///< NOTIFY - EHTTP_SUBSCRIBE = 26, ///< SUBSCRIBE - EHTTP_UNSUBSCRIBE = 27, ///< UNSUBSCRIBE - /* RFC-5789 */ - EHTTP_PATCH = 28, ///< PATCH - EHTTP_PURGE = 29, ///< PURGE - /* CalDAV */ - EHTTP_MKCALENDAR = 30, ///< MKCALENDAR - /* RFC-2068, section 19.6.1.2 */ - EHTTP_LINK = 31, ///< LINK - EHTTP_UNLINK = 32, ///< UNLINK -}; - -/** HTTP status codes. */ -enum TStatusCode { - ESTATUS_CONTINUE = 100, - ESTATUS_SWITCH_PROTOCOLS = 101, - ESTATUS_OK = 200, - ESTATUS_CREATED = 201, - ESTATUS_ACCEPTED = 202, - ESTATUS_NON_AUTHORITATIVE_INFORMATION = 203, - ESTATUS_NO_CONTENT = 204, - ESTATUS_RESET_CONTENT = 205, - ESTATUS_PARTIAL_CONTENT = 206, - ESTATUS_MULTI_STATUS = 207, - ESTATUS_MULTIPLE_CHOICES = 300, - ESTATUS_MOVED_PERMANENTLY = 301, - ESTATUS_FOUND = 302, - ESTATUS_SEE_OTHER = 303, - ESTATUS_NOT_MODIFIED = 304, - ESTATUS_USE_PROXY = 305, - ESTATUS_TEMPORARY_REDIRECT = 307, - ESTATUS_BAD_REQUEST = 400, - ESTATUS_UNAUTHORIZED = 401, - ESTATUS_PAYMENT_REQUIRED = 402, - ESTATUS_FORBIDDEN = 403, - ESTATUS_NOT_FOUND = 404, - ESTATUS_METHOD_NOT_ALLOWED = 405, - ESTATUS_NOT_ACCEPTABLE = 406, - ESTATUS_PROXY_AUTHENTICATION_REQUIRED = 407, - ESTATUS_REQUEST_TIMEOUT = 408, - ESTATUS_CONFLICT = 409, - ESTATUS_GONE = 410, - ESTATUS_LENGTH_REQUIRED = 411, - ESTATUS_PRECONDITION_FAILED = 412, - ESTATUS_REQUEST_ENTITY_TOO_LARGE = 413, - ESTATUS_REQUEST_URI_TOO_LONG = 414, - ESTATUS_REQUEST_UNSUPPORTED_MEDIA_TYPE = 415, - ESTATUS_REQUESTED_RANGE_NOT_SATISFIABLE = 416, - ESTATUS_EXPECTATION_FAILED = 417, - ESTATUS_INTERNAL_SERVER_ERROR = 500, - ESTATUS_NOT_IMPLEMENTED = 501, - ESTATUS_BAD_GATEWAY = 502, - ESTATUS_SERVICE_UNAVAILABLE = 503, - ESTATUS_GATEWAY_TIMEOUT = 504, - ESTATUS_HTTP_VERSION_NOT_SUPPORTED = 505 -}; - -/** The backend of QHttp library. */ -enum TBackend { - ETcpSocket = 0, ///< client / server work on top of TCP/IP stack. (default) - ESslSocket = 1, ///< client / server work on SSL/TLS tcp stack. - ELocalSocket = 2 ///< client / server work on local socket (unix socket). -}; - -/////////////////////////////////////////////////////////////////////////////// -namespace server { -/////////////////////////////////////////////////////////////////////////////// -class QHttpServer; -class QHttpConnection; -class QHttpRequest; -class QHttpResponse; - -// Privte classes -class QHttpServerPrivate; -class QHttpConnectionPrivate; -class QHttpRequestPrivate; -class QHttpResponsePrivate; - -using TServerHandler = std::function; - -/////////////////////////////////////////////////////////////////////////////// -} // namespace server -/////////////////////////////////////////////////////////////////////////////// -namespace client { -/////////////////////////////////////////////////////////////////////////////// -class QHttpClient; -class QHttpRequest; -class QHttpResponse; - -// Private classes -class QHttpClientPrivate; -class QHttpRequestPrivate; -class QHttpResponsePrivate; -/////////////////////////////////////////////////////////////////////////////// -} // namespace client -/////////////////////////////////////////////////////////////////////////////// -#ifdef Q_OS_WIN -# if defined(QHTTP_EXPORT) -# define QHTTP_API __declspec(dllexport) -# else -# define QHTTP_API __declspec(dllimport) -# endif -#else -# define QHTTP_API -#endif - - -#if QHTTP_MEMORY_LOG > 0 -# define QHTTP_LINE_LOG fprintf(stderr, "%s(): obj = %p @ %s[%d]\n",\ - __FUNCTION__, this, __FILE__, __LINE__); -#else -# define QHTTP_LINE_LOG -#endif - -#if QHTTP_MEMORY_LOG > 1 -# define QHTTP_LINE_DEEPLOG QHTTP_LINE_LOG -#else -# define QHTTP_LINE_DEEPLOG -#endif -/////////////////////////////////////////////////////////////////////////////// -} // namespace qhttp -/////////////////////////////////////////////////////////////////////////////// -#endif // define QHTTPFWD_HPP diff --git a/src/http/qhttp/qhttpserver.cpp b/src/http/qhttp/qhttpserver.cpp deleted file mode 100644 index a9c6a082..00000000 --- a/src/http/qhttp/qhttpserver.cpp +++ /dev/null @@ -1,118 +0,0 @@ -#include "private/qhttpserver_private.hpp" - -/////////////////////////////////////////////////////////////////////////////// -namespace qhttp { -namespace server { -/////////////////////////////////////////////////////////////////////////////// - -QHttpServer::QHttpServer(QObject *parent) - : QObject(parent), d_ptr(new QHttpServerPrivate) { -} - -QHttpServer::QHttpServer(QHttpServerPrivate &dd, QObject *parent) - : QObject(parent), d_ptr(&dd) { -} - -QHttpServer::~QHttpServer() { - stopListening(); -} - -bool -QHttpServer::listen(const QString &socketOrPort, const TServerHandler &handler) { - Q_D(QHttpServer); - - bool isNumber = false; - quint16 tcpPort = socketOrPort.toUShort(&isNumber); - if ( isNumber && tcpPort > 0 ) - return listen(QHostAddress::Any, tcpPort, handler); - - d->initialize(ELocalSocket, this); - d->ihandler = handler; - return d->ilocalServer->listen(socketOrPort); -} - -bool -QHttpServer::listen(const QHostAddress& address, quint16 port, const qhttp::server::TServerHandler& handler) { - Q_D(QHttpServer); - - d->initialize(d->ibackend, this); - d->ihandler = handler; - return d->itcpServer->listen(address, port); -} - -bool -QHttpServer::isListening() const { - const Q_D(QHttpServer); - - if ( ( d->ibackend == ETcpSocket || d->ibackend == ESslSocket ) && d->itcpServer ) - return d->itcpServer->isListening(); - - else if ( d->ibackend == ELocalSocket && d->ilocalServer ) - return d->ilocalServer->isListening(); - - return false; -} - -void -QHttpServer::stopListening() { - Q_D(QHttpServer); - - if ( d->itcpServer ) - d->itcpServer->close(); - - if ( d->ilocalServer ) { - d->ilocalServer->close(); - QLocalServer::removeServer( d->ilocalServer->fullServerName() ); - } -} - -quint32 -QHttpServer::timeOut() const { - return d_func()->itimeOut; -} - -void -QHttpServer::setTimeOut(quint32 newValue) { - d_func()->itimeOut = newValue; -} - -TBackend -QHttpServer::backendType() const { - return d_func()->ibackend; -} - -QTcpServer* -QHttpServer::tcpServer() const { - return d_func()->itcpServer.data(); -} - -QLocalServer* -QHttpServer::localServer() const { - return d_func()->ilocalServer.data(); -} - -void -QHttpServer::incomingConnection(qintptr handle) { - QHttpConnection* conn = new QHttpConnection(this); - conn->setSocketDescriptor(handle, backendType()); - conn->setTimeOut(d_func()->itimeOut); - - emit newConnection(conn); - - Q_D(QHttpServer); - if ( d->ihandler ) - QObject::connect(conn, &QHttpConnection::newRequest, d->ihandler); - else - incomingConnection(conn); -} - -void -QHttpServer::incomingConnection(QHttpConnection *connection) { - QObject::connect(connection, &QHttpConnection::newRequest, - this, &QHttpServer::newRequest); -} - -/////////////////////////////////////////////////////////////////////////////// -} // namespace server -} // namespace qhttp -/////////////////////////////////////////////////////////////////////////////// diff --git a/src/http/qhttp/qhttpserver.hpp b/src/http/qhttp/qhttpserver.hpp deleted file mode 100644 index 4e492e35..00000000 --- a/src/http/qhttp/qhttpserver.hpp +++ /dev/null @@ -1,131 +0,0 @@ -/** HTTP server class. - * https://github.com/azadkuh/qhttp - * - * @author amir zamani - * @version 2.0.0 - * @date 2014-07-11 - */ - -#ifndef QHTTPSERVER_HPP -#define QHTTPSERVER_HPP - -/////////////////////////////////////////////////////////////////////////////// -#include "qhttpfwd.hpp" - -#include -#include -/////////////////////////////////////////////////////////////////////////////// -namespace qhttp { -namespace server { -/////////////////////////////////////////////////////////////////////////////// - -/** The QHttpServer class is a fast, async (non-blocking) HTTP server. */ -class QHTTP_API QHttpServer : public QObject -{ - Q_OBJECT - - Q_PROPERTY(quint32 timeOut READ timeOut WRITE setTimeOut) - -public: - /** construct a new HTTP Server. */ - explicit QHttpServer(QObject *parent = nullptr); - - virtual ~QHttpServer(); - - /** starts a TCP or Local (unix domain socket) server. - * if you provide a server handler, the newRequest() signal won't be emitted. - * - * @param socketOrPort could be a tcp port number as "8080" or a unix socket name as - * "/tmp/sample.socket" or "sample.socket". - * @param handler optional server handler (a lambda, std::function, ...) - * @return false if listening fails. - */ - bool listen(const QString& socketOrPort, - const TServerHandler& handler = nullptr); - - /** starts a TCP server on specified address and port. - * if you provide a server handler, the newRequest() signal won't be emitted. - * - * @param address listening address as QHostAddress::Any. - * @param port listening port. - * @param handler optional server handler (a lambda, std::function, ...) - * @return false if listening fails. - */ - bool listen(const QHostAddress& address, quint16 port, - const TServerHandler& handler = nullptr); - - /** @overload listen() */ - bool listen(quint16 port) { - return listen(QHostAddress::Any, port); - } - - /** returns true if server successfully listens. @sa listen() */ - bool isListening() const; - - /** closes the server and stops from listening. */ - void stopListening(); - - /** returns timeout value [mSec] for open connections (sockets). - * @sa setTimeOut(). */ - quint32 timeOut()const; - - /** set time-out for new open connections in miliseconds [mSec]. - * new incoming connections will be forcefully closed after this time out. - * a zero (0) value disables timer for new connections. */ - void setTimeOut(quint32); - - /** returns the QHttpServer's backend type. */ - TBackend backendType() const; - -signals: - /** emitted when a client makes a new request to the server if you do not override - * incomingConnection(QHttpConnection *connection); - * @sa incommingConnection(). */ - void newRequest(QHttpRequest *request, QHttpResponse *response); - - /** emitted when a new connection comes to the server if you do not override - * incomingConnection(QHttpConnection *connection); - * @sa incomingConnection(); */ - void newConnection(QHttpConnection* connection); - -protected: - /** returns the tcp server instance if the backend() == ETcpSocket. */ - QTcpServer* tcpServer() const; - - /** returns the local server instance if the backend() == ELocalSocket. */ - QLocalServer* localServer() const; - - - /** is called when server accepts a new connection. - * you can override this function for using a thread-pool or ... some other reasons. - * - * the default implementation just connects QHttpConnection::newRequest signal. - * @note if you override this method, the signal won't be emitted by QHttpServer. - * (perhaps, you do not need it anymore). - * - * @param connection New incoming connection. */ - virtual void incomingConnection(QHttpConnection* connection); - - /** overrides QTcpServer::incomingConnection() to make a new QHttpConnection. - * override this function if you like to create your derived QHttpConnection instances. - * - * @note if you override this method, incomingConnection(QHttpConnection*) or - * newRequest(QHttpRequest *, QHttpResponse *) signal won't be called. - * - * @see example/benchmark/server.cpp to see how to override. - */ - virtual void incomingConnection(qintptr handle); - -private: - explicit QHttpServer(QHttpServerPrivate&, QObject *parent); - - Q_DECLARE_PRIVATE(QHttpServer) - Q_DISABLE_COPY(QHttpServer) - QScopedPointer d_ptr; -}; - -/////////////////////////////////////////////////////////////////////////////// -} // namespace server -} // namespace qhttp -/////////////////////////////////////////////////////////////////////////////// -#endif // define QHTTPSERVER_HPP diff --git a/src/http/qhttp/qhttpserverconnection.cpp b/src/http/qhttp/qhttpserverconnection.cpp deleted file mode 100644 index 7345c83b..00000000 --- a/src/http/qhttp/qhttpserverconnection.cpp +++ /dev/null @@ -1,217 +0,0 @@ -#include "private/qhttpserverconnection_private.hpp" - -/////////////////////////////////////////////////////////////////////////////// -namespace qhttp { -namespace server { -/////////////////////////////////////////////////////////////////////////////// -QHttpConnection::QHttpConnection(QObject *parent) - : QObject(parent), d_ptr(new QHttpConnectionPrivate(this)) { - QHTTP_LINE_LOG -} - -QHttpConnection::QHttpConnection(QHttpConnectionPrivate& dd, QObject* parent) - : QObject(parent), d_ptr(&dd) { - QHTTP_LINE_LOG -} - -void -QHttpConnection::setSocketDescriptor(qintptr sokDescriptor, TBackend backendType) { - d_ptr->createSocket(sokDescriptor, backendType); -} - -QHttpConnection::~QHttpConnection() { - QHTTP_LINE_LOG -} - -void -QHttpConnection::setTimeOut(quint32 miliSeconds) { - if ( miliSeconds != 0 ) { - d_func()->itimeOut = miliSeconds; - d_func()->itimer.start(miliSeconds, Qt::CoarseTimer, this); - } -} - -void -QHttpConnection::killConnection() { - d_func()->isocket.close(); -} - -TBackend -QHttpConnection::backendType() const { - return d_func()->isocket.ibackendType; -} - -QTcpSocket* -QHttpConnection::tcpSocket() const { - return d_func()->isocket.itcpSocket; -} - -QLocalSocket* -QHttpConnection::localSocket() const { - return d_func()->isocket.ilocalSocket; -} - -void -QHttpConnection::onHandler(const TServerHandler &handler) { - d_func()->ihandler = handler; -} - -void -QHttpConnection::timerEvent(QTimerEvent *) { - killConnection(); -} - -/////////////////////////////////////////////////////////////////////////////// - -// if user closes the connection, ends the response or by any other reason the -// socket disconnects, then the irequest and iresponse instances may have -// been deleted. In these situations reading more http body or emitting end() -// for incoming request are not possible: -// if ( ilastRequest == nullptr ) -// return 0; - - -int -QHttpConnectionPrivate::messageBegin(http_parser*) { - itempUrl.clear(); - itempUrl.reserve(128); - - if ( ilastRequest ) - ilastRequest->deleteLater(); - - ilastRequest = new QHttpRequest(q_func()); - return 0; -} - -int -QHttpConnectionPrivate::url(http_parser*, const char* at, size_t length) { - Q_ASSERT(ilastRequest); - - itempUrl.append(at, length); - return 0; -} - -int -QHttpConnectionPrivate::headerField(http_parser*, const char* at, size_t length) { - if ( ilastRequest == nullptr ) - return 0; - - // insert the header we parsed previously - // into the header map - if ( !itempHeaderField.isEmpty() && !itempHeaderValue.isEmpty() ) { - // header names are always lower-cased - ilastRequest->d_func()->iheaders.insert( - itempHeaderField.toLower(), - itempHeaderValue.toLower() - ); - // clear header value. this sets up a nice - // feedback loop where the next time - // HeaderValue is called, it can simply append - itempHeaderField.clear(); - itempHeaderValue.clear(); - } - - itempHeaderField.append(at, length); - return 0; -} - -int -QHttpConnectionPrivate::headerValue(http_parser*, const char* at, size_t length) { - if ( ilastRequest == nullptr ) - return 0; - - itempHeaderValue.append(at, length); - return 0; -} - -int -QHttpConnectionPrivate::headersComplete(http_parser* parser) { - if ( ilastRequest == nullptr ) - return 0; - - ilastRequest->d_func()->iurl = QUrl(itempUrl); - - // set method - ilastRequest->d_func()->imethod = - static_cast(parser->method); - - // set version - ilastRequest->d_func()->iversion = QString("%1.%2") - .arg(parser->http_major) - .arg(parser->http_minor); - - // Insert last remaining header - ilastRequest->d_func()->iheaders.insert( - itempHeaderField.toLower(), - itempHeaderValue.toLower() - ); - - // set client information - if ( isocket.ibackendType == ETcpSocket || isocket.ibackendType == ESslSocket ) { - ilastRequest->d_func()->iremoteAddress = isocket.itcpSocket->peerAddress().toString(); - ilastRequest->d_func()->iremotePort = isocket.itcpSocket->peerPort(); - - } else if ( isocket.ibackendType == ELocalSocket ) { - ilastRequest->d_func()->iremoteAddress = isocket.ilocalSocket->fullServerName(); - ilastRequest->d_func()->iremotePort = 0; // not used in local sockets - } - - if ( ilastResponse ) - ilastResponse->deleteLater(); - ilastResponse = new QHttpResponse(q_func()); - - if ( parser->http_major < 1 || parser->http_minor < 1 ) - ilastResponse->d_func()->ikeepAlive = false; - - // close the connection if response was the last packet - QObject::connect(ilastResponse, &QHttpResponse::done, [this](bool wasTheLastPacket){ - ikeepAlive = !wasTheLastPacket; - if ( wasTheLastPacket ) { - isocket.flush(); - isocket.close(); - } - }); - - // we are good to go! - if ( ihandler ) - ihandler(ilastRequest, ilastResponse); - else - emit q_ptr->newRequest(ilastRequest, ilastResponse); - - return 0; -} - -int -QHttpConnectionPrivate::body(http_parser*, const char* at, size_t length) { - if ( ilastRequest == nullptr ) - return 0; - - ilastRequest->d_func()->ireadState = QHttpRequestPrivate::EPartial; - - if ( ilastRequest->d_func()->icollectRequired ) { - if ( !ilastRequest->d_func()->append(at, length) ) { - // forcefully dispatch the ilastRequest - finalizeConnection(); - } - - return 0; - } - - emit ilastRequest->data(QByteArray(at, length)); - return 0; -} - -int -QHttpConnectionPrivate::messageComplete(http_parser*) { - if ( ilastRequest == nullptr ) - return 0; - - // request is done - finalizeConnection(); - return 0; -} - -/////////////////////////////////////////////////////////////////////////////// -} // namespace server -} // namespace qhttp -/////////////////////////////////////////////////////////////////////////////// diff --git a/src/http/qhttp/qhttpserverconnection.hpp b/src/http/qhttp/qhttpserverconnection.hpp deleted file mode 100644 index b908665c..00000000 --- a/src/http/qhttp/qhttpserverconnection.hpp +++ /dev/null @@ -1,87 +0,0 @@ -/** HTTP connection class. - * https://github.com/azadkuh/qhttp - * - * @author amir zamani - * @version 2.0.0 - * @date 2014-07-11 - */ - -#ifndef QHTTPSERVER_CONNECTION_HPP -#define QHTTPSERVER_CONNECTION_HPP -/////////////////////////////////////////////////////////////////////////////// -#include "qhttpfwd.hpp" - -#include - -/////////////////////////////////////////////////////////////////////////////// -namespace qhttp { -namespace server { -/////////////////////////////////////////////////////////////////////////////// -/** a HTTP connection in the server. - * this class controls the HTTP connetion and handles life cycle and the memory management - * of QHttpRequest and QHttpResponse instances autoamtically. - */ -class QHTTP_API QHttpConnection : public QObject -{ - Q_OBJECT - -public: - virtual ~QHttpConnection(); - - /** set an optional timer event to close the connection. */ - void setTimeOut(quint32 miliSeconds); - - /** forcefully kills (closes) a connection. */ - void killConnection(); - - /** optionally set a handler for connection class. - * @note if you set this handler, the newRequest() signal won't be emitted. - */ - void onHandler(const TServerHandler& handler); - - /** returns the backend type of the connection. */ - TBackend backendType() const; - - /** returns connected socket if the backend() == ETcpSocket. */ - QTcpSocket* tcpSocket() const; - - /** returns connected socket if the backend() == ELocalSocket. */ - QLocalSocket* localSocket() const; - - /** creates a new QHttpConnection based on arguments. */ - static - QHttpConnection* create(qintptr sokDescriptor, TBackend backendType, QObject* parent) { - QHttpConnection* conn = new QHttpConnection(parent); - conn->setSocketDescriptor(sokDescriptor, backendType); - return conn; - } - -signals: - /** emitted when a pair of HTTP request and response are ready to interact. - * @param req incoming request by the client. - * @param res outgoing response to the client. - */ - void newRequest(QHttpRequest* req, QHttpResponse* res); - - /** emitted when the tcp/local socket, disconnects. */ - void disconnected(); - -protected: - explicit QHttpConnection(QObject *parent); - explicit QHttpConnection(QHttpConnectionPrivate&, QObject *); - - void setSocketDescriptor(qintptr sokDescriptor, TBackend backendType); - void timerEvent(QTimerEvent*) override; - - Q_DISABLE_COPY(QHttpConnection) - Q_DECLARE_PRIVATE(QHttpConnection) - QScopedPointer d_ptr; - - friend class QHttpServer; -}; - -/////////////////////////////////////////////////////////////////////////////// -} // namespace server -} // namespace qhttp -/////////////////////////////////////////////////////////////////////////////// -#endif // #define QHTTPSERVER_CONNECTION_HPP diff --git a/src/http/qhttp/qhttpserverrequest.cpp b/src/http/qhttp/qhttpserverrequest.cpp deleted file mode 100644 index 87787fa3..00000000 --- a/src/http/qhttp/qhttpserverrequest.cpp +++ /dev/null @@ -1,81 +0,0 @@ -#include "private/qhttpserverrequest_private.hpp" - -/////////////////////////////////////////////////////////////////////////////// -namespace qhttp { -namespace server { -/////////////////////////////////////////////////////////////////////////////// -QHttpRequest::QHttpRequest(QHttpConnection *conn) - : QHttpAbstractInput(conn), d_ptr(new QHttpRequestPrivate(conn, this)) { - d_ptr->initialize(); - QHTTP_LINE_LOG -} - -QHttpRequest::QHttpRequest(QHttpRequestPrivate &dd, QHttpConnection *conn) - : QHttpAbstractInput(conn), d_ptr(&dd) { - d_ptr->initialize(); - QHTTP_LINE_LOG -} - -QHttpRequest::~QHttpRequest() { - QHTTP_LINE_LOG -} - -THttpMethod -QHttpRequest::method() const { - return d_func()->imethod; -} - -const QString -QHttpRequest::methodString() const { - return http_method_str(static_cast(d_func()->imethod)); -} - -const QUrl& -QHttpRequest::url() const { - return d_func()->iurl; -} - -const QString& -QHttpRequest::httpVersion() const { - return d_func()->iversion; -} - -const THeaderHash& -QHttpRequest::headers() const { - return d_func()->iheaders; -} - -const QString& -QHttpRequest::remoteAddress() const { - return d_func()->iremoteAddress; -} - -quint16 -QHttpRequest::remotePort() const { - return d_func()->iremotePort; -} - -bool -QHttpRequest::isSuccessful() const { - return d_func()->isuccessful; -} - -void -QHttpRequest::collectData(int atMost) { - d_func()->collectData(atMost); -} - -const QByteArray& -QHttpRequest::collectedData() const { - return d_func()->icollectedData; -} - -QHttpConnection* -QHttpRequest::connection() const { - return d_ptr->iconnection; -} - -/////////////////////////////////////////////////////////////////////////////// -} // namespace server -} // namespace qhttp -/////////////////////////////////////////////////////////////////////////////// diff --git a/src/http/qhttp/qhttpserverrequest.hpp b/src/http/qhttp/qhttpserverrequest.hpp deleted file mode 100644 index 4001c710..00000000 --- a/src/http/qhttp/qhttpserverrequest.hpp +++ /dev/null @@ -1,82 +0,0 @@ -/** HTTP request which is received by the server. - * https://github.com/azadkuh/qhttp - * - * @author amir zamani - * @version 2.0.0 - * @date 2014-07-11 - */ - -#ifndef QHTTPSERVER_REQUEST_HPP -#define QHTTPSERVER_REQUEST_HPP -/////////////////////////////////////////////////////////////////////////////// - -#include "qhttpabstracts.hpp" - -#include -/////////////////////////////////////////////////////////////////////////////// -namespace qhttp { -namespace server { -/////////////////////////////////////////////////////////////////////////////// -/** The QHttpRequest class represents the header and body data sent by the client. - * The class is read-only. - * @sa QHttpConnection - */ -class QHTTP_API QHttpRequest : public QHttpAbstractInput -{ - Q_OBJECT - -public: - virtual ~QHttpRequest(); - -public: // QHttpAbstractInput methods: - /** @see QHttpAbstractInput::headers(). */ - const THeaderHash& headers() const override; - - /** @see QHttpAbstractInput::httpVersion(). */ - const QString& httpVersion() const override; - - /** @see QHttpAbstractInput::isSuccessful(). */ - bool isSuccessful() const override; - - /** @see QHttpAbstractInput::collectData(). */ - void collectData(int atMost = -1) override; - - /** @see QHttpAbstractInput::collectedData(). */ - const QByteArray& collectedData()const override; - - -public: - /** The method used for the request. */ - THttpMethod method() const ; - - /** Returns the method string for the request. - * @note This will plainly transform the enum into a string HTTP_GET -> "HTTP_GET". */ - const QString methodString() const; - - /** The complete URL for the request. - * This includes the path and query string. @sa path(). */ - const QUrl& url() const; - - /** IP Address of the client in dotted decimal format. */ - const QString& remoteAddress() const; - - /** Outbound connection port for the client. */ - quint16 remotePort() const; - - /** returns the parent QHttpConnection object. */ - QHttpConnection* connection() const; - -protected: - explicit QHttpRequest(QHttpConnection*); - explicit QHttpRequest(QHttpRequestPrivate&, QHttpConnection*); - friend class QHttpConnectionPrivate; - - Q_DECLARE_PRIVATE(QHttpRequest) - QScopedPointer d_ptr; -}; - -/////////////////////////////////////////////////////////////////////////////// -} // namespace server -} // namespace qhttp -/////////////////////////////////////////////////////////////////////////////// -#endif // define QHTTPSERVER_REQUEST_HPP diff --git a/src/http/qhttp/qhttpserverresponse.cpp b/src/http/qhttp/qhttpserverresponse.cpp deleted file mode 100644 index 5e60746e..00000000 --- a/src/http/qhttp/qhttpserverresponse.cpp +++ /dev/null @@ -1,90 +0,0 @@ -#include "private/qhttpserverresponse_private.hpp" - -/////////////////////////////////////////////////////////////////////////////// -namespace qhttp { -namespace server { -/////////////////////////////////////////////////////////////////////////////// -QHttpResponse::QHttpResponse(QHttpConnection* conn) - : QHttpAbstractOutput(conn) , d_ptr(new QHttpResponsePrivate(conn, this)) { - d_ptr->initialize(); - QHTTP_LINE_LOG -} - -QHttpResponse::QHttpResponse(QHttpResponsePrivate& dd, QHttpConnection* conn) - : QHttpAbstractOutput(conn) , d_ptr(&dd) { - d_ptr->initialize(); - QHTTP_LINE_LOG -} - -QHttpResponse::~QHttpResponse() { - QHTTP_LINE_LOG -} - -void -QHttpResponse::setStatusCode(TStatusCode code) { - d_func()->istatus = code; -} - -void -QHttpResponse::setVersion(const QString &versionString) { - d_func()->iversion = versionString; -} - -void -QHttpResponse::addHeader(const QByteArray &field, const QByteArray &value) { - d_func()->addHeader(field, value); -} - -THeaderHash& -QHttpResponse::headers() { - return d_func()->iheaders; -} - -void -QHttpResponse::write(const QByteArray &data) { - d_func()->writeData(data); -} - -void -QHttpResponse::end(const QByteArray &data) { - Q_D(QHttpResponse); - - if ( d->endPacket(data) ) - emit done(!d->ikeepAlive); -} - -QHttpConnection* -QHttpResponse::connection() const { - return d_func()->iconnection; -} - -/////////////////////////////////////////////////////////////////////////////// -QByteArray -QHttpResponsePrivate::makeTitle() { - - QString title = QString("HTTP/%1 %2 %3\r\n") - .arg(iversion) - .arg(istatus) - .arg(Stringify::toString(istatus)); - - return title.toLatin1(); -} - -void -QHttpResponsePrivate::prepareHeadersToWrite() { - - if ( !iheaders.contains("date") ) { - // Sun, 06 Nov 1994 08:49:37 GMT - RFC 822. Use QLocale::c() so english is used for month and - // day. - QString dateString = QLocale::c(). - toString(QDateTime::currentDateTimeUtc(), - "ddd, dd MMM yyyy hh:mm:ss") - .append(" GMT"); - addHeader("date", dateString.toLatin1()); - } -} - -/////////////////////////////////////////////////////////////////////////////// -} // namespace server -} // namespace qhttp -/////////////////////////////////////////////////////////////////////////////// diff --git a/src/http/qhttp/qhttpserverresponse.hpp b/src/http/qhttp/qhttpserverresponse.hpp deleted file mode 100644 index d066712a..00000000 --- a/src/http/qhttp/qhttpserverresponse.hpp +++ /dev/null @@ -1,70 +0,0 @@ -/** HTTP response from a server. - * https://github.com/azadkuh/qhttp - * - * @author amir zamani - * @version 2.0.0 - * @date 2014-07-11 - */ - -#ifndef QHTTPSERVER_RESPONSE_HPP -#define QHTTPSERVER_RESPONSE_HPP - -/////////////////////////////////////////////////////////////////////////////// - -#include "qhttpabstracts.hpp" - -/////////////////////////////////////////////////////////////////////////////// -namespace qhttp { -namespace server { -/////////////////////////////////////////////////////////////////////////////// -/** The QHttpResponse class handles sending data back to the client as a response to a request. - * @sa QHttpConnection - */ -class QHTTP_API QHttpResponse : public QHttpAbstractOutput -{ - Q_OBJECT - -public: - virtual ~QHttpResponse(); - -public: - /** set the response HTTP status code. @sa TStatusCode. - * default value is ESTATUS_BAD_REQUEST. - * @sa write() - */ - void setStatusCode(TStatusCode code); - -public: // QHttpAbstractOutput methods: - /** @see QHttpAbstractOutput::setVersion(). */ - void setVersion(const QString& versionString) override; - - /** @see QHttpAbstractOutput::addHeader(). */ - void addHeader(const QByteArray& field, const QByteArray& value) override; - - /** @see QHttpAbstractOutput::headers(). */ - THeaderHash& headers() override; - - /** @see QHttpAbstractOutput::write(). */ - void write(const QByteArray &data) override; - - /** @see QHttpAbstractOutput::end(). */ - void end(const QByteArray &data = QByteArray()) override; - -public: - /** returns the parent QHttpConnection object. */ - QHttpConnection* connection() const; - -protected: - explicit QHttpResponse(QHttpConnection*); - explicit QHttpResponse(QHttpResponsePrivate&, QHttpConnection*); - friend class QHttpConnectionPrivate; - - Q_DECLARE_PRIVATE(QHttpResponse) - QScopedPointer d_ptr; -}; - -/////////////////////////////////////////////////////////////////////////////// -} // namespace server -} // namespace qhttp -/////////////////////////////////////////////////////////////////////////////// -#endif // define QHTTPSERVER_RESPONSE_HPP diff --git a/tests/config-keepassx-tests.h.cmake b/tests/config-keepassx-tests.h.cmake index 26204f7d..7b5a14f5 100644 --- a/tests/config-keepassx-tests.h.cmake +++ b/tests/config-keepassx-tests.h.cmake @@ -5,7 +5,6 @@ #define KEEPASSX_TEST_DATA_DIR "${KEEPASSX_TEST_DATA_DIR}" -#cmakedefine WITH_XC_HTTP #cmakedefine WITH_XC_AUTOTYPE #cmakedefine WITH_XC_YUBIKEY From 07bc9a7b4b7765d8795d064c8aa621f088483f8a Mon Sep 17 00:00:00 2001 From: Louis-Bertrand Varin Date: Sun, 14 Jan 2018 10:11:00 -0500 Subject: [PATCH 014/267] Add ClangFormat rules --- .clang-format | 2 +- .github/CONTRIBUTING.md | 7 +++-- CMakeLists.txt | 2 ++ cmake/CLangFormat.cmake | 59 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 67 insertions(+), 3 deletions(-) create mode 100644 cmake/CLangFormat.cmake diff --git a/.clang-format b/.clang-format index 3838b6b1..64ab822b 100644 --- a/.clang-format +++ b/.clang-format @@ -30,7 +30,7 @@ BraceWrapping: BeforeCatch: false BeforeElse: false IndentBraces: false -BreakBeforeBinaryOperators: None +BreakBeforeBinaryOperators: NonAssignment BreakBeforeBraces: Custom BreakBeforeTernaryOperators: true BreakConstructorInitializersBeforeComma: true diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 4f937513..f82f7508 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -108,9 +108,12 @@ The Branch Strategy is based on [git-flow-lite](http://nvie.com/posts/a-successf ### Coding styleguide -This project follows the [Qt Coding Style](https://wiki.qt.io/Qt_Coding_Style). All submissions are expected to follow this style. +The coding style of the project is enforced using llvm's `clang-format` formatting tool. A thorough description +of the coding style can be found in the `.clang-format` file, but the main conventions are presented here. -In particular, code must stick to the following rules: +Formatting can be performed automatically by calling `make format` from the `build/` directory. + +Note that [formatting can be disabled on a piece of code](https://clang.llvm.org/docs/ClangFormatStyleOptions.html#disabling-formatting-on-a-piece-of-code) if manual formatting is deemed more readable. #### Naming convention `lowerCamelCase` diff --git a/CMakeLists.txt b/CMakeLists.txt index 188873b9..871f5d63 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -279,6 +279,8 @@ if(WITH_TESTS) enable_testing() endif(WITH_TESTS) +include(CLangFormat) + if(UNIX AND NOT APPLE) find_package(Qt5 COMPONENTS Core Network Concurrent Widgets Test LinguistTools DBus REQUIRED) elseif(APPLE) diff --git a/cmake/CLangFormat.cmake b/cmake/CLangFormat.cmake new file mode 100644 index 00000000..6c26ef7c --- /dev/null +++ b/cmake/CLangFormat.cmake @@ -0,0 +1,59 @@ +# Copyright (C) 2017 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 . + +set(EXCLUDED_DIRS + # third-party directories + zxcvbn/ + http/qhttp/ + streams/QtIOCompressor + # objective-c directories + autotype/mac +) + +set(EXCLUDED_FILES + # third-party files + streams/qtiocompressor.cpp + streams/qtiocompressor.h + gui/KMessageWidget.h + gui/KMessageWidget.cpp + tests/modeltest.cpp + tests/modeltest.h + # objective-c files + core/ScreenLockListenerMac.h + core/ScreenLockListenerMac.cpp +) + +file(GLOB_RECURSE ALL_SOURCE_FILES *.cpp *.h) +foreach (SOURCE_FILE ${ALL_SOURCE_FILES}) + foreach (EXCLUDED_DIR ${EXCLUDED_DIRS}) + string(FIND ${SOURCE_FILE} ${EXCLUDED_DIR} SOURCE_FILE_EXCLUDED) + if (NOT ${SOURCE_FILE_EXCLUDED} EQUAL -1) + list(REMOVE_ITEM ALL_SOURCE_FILES ${SOURCE_FILE}) + endif () + endforeach () + foreach (EXCLUDED_FILE ${EXCLUDED_FILES}) + if (${SOURCE_FILE} MATCHES ".*${EXCLUDED_FILE}$") + list(REMOVE_ITEM ALL_SOURCE_FILES ${SOURCE_FILE}) + endif () + endforeach () +endforeach () + +add_custom_target( + format + COMMAND clang-format + -style=file + -i + ${ALL_SOURCE_FILES} +) From 0b6eb3b30e2cdfe715404c53c214be2b067afe85 Mon Sep 17 00:00:00 2001 From: Janek Bevendorff Date: Wed, 28 Feb 2018 14:26:52 +0100 Subject: [PATCH 015/267] Use xargs to avoid long command lines --- cmake/CLangFormat.cmake | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/cmake/CLangFormat.cmake b/cmake/CLangFormat.cmake index 6c26ef7c..88c45cec 100644 --- a/cmake/CLangFormat.cmake +++ b/cmake/CLangFormat.cmake @@ -52,8 +52,5 @@ endforeach () add_custom_target( format - COMMAND clang-format - -style=file - -i - ${ALL_SOURCE_FILES} + COMMAND echo ${ALL_SOURCE_FILES} | xargs clang-format -style=file -i ) From 3eb917055e6756b38def59917d6d074aafa64473 Mon Sep 17 00:00:00 2001 From: Louis-Bertrand Varin Date: Wed, 21 Feb 2018 21:27:55 -0500 Subject: [PATCH 016/267] Add ClangFormat exceptions --- cmake/CLangFormat.cmake | 7 +++++- src/autotype/AutoType.h | 2 +- src/autotype/windows/AutoTypeWindows.cpp | 2 ++ src/autotype/xcb/KeySymMap.h | 2 ++ src/core/DatabaseIcons.cpp | 3 +++ src/format/KdbxWriter.h | 2 ++ src/format/KeePass2.h | 30 ++++++++++++------------ tests/TestKdbx4.cpp | 2 ++ tests/TestKeePass2Format.cpp | 2 ++ tests/TestKeys.cpp | 2 ++ 10 files changed, 37 insertions(+), 17 deletions(-) diff --git a/cmake/CLangFormat.cmake b/cmake/CLangFormat.cmake index 88c45cec..2cb046bb 100644 --- a/cmake/CLangFormat.cmake +++ b/cmake/CLangFormat.cmake @@ -16,7 +16,7 @@ set(EXCLUDED_DIRS # third-party directories zxcvbn/ - http/qhttp/ + http/ streams/QtIOCompressor # objective-c directories autotype/mac @@ -28,6 +28,11 @@ set(EXCLUDED_FILES streams/qtiocompressor.h gui/KMessageWidget.h gui/KMessageWidget.cpp + gui/MainWindowAdaptor.h + gui/MainWindowAdaptor.cpp + sshagent/bcrypt_pbkdf.cpp + sshagent/blf.h + sshagent/blowfish.c tests/modeltest.cpp tests/modeltest.h # objective-c files diff --git a/src/autotype/AutoType.h b/src/autotype/AutoType.h index 55adac7d..ad60bd76 100644 --- a/src/autotype/AutoType.h +++ b/src/autotype/AutoType.h @@ -1,4 +1,4 @@ - /* +/* * Copyright (C) 2012 Felix Geyer * Copyright (C) 2017 KeePassXC Team * diff --git a/src/autotype/windows/AutoTypeWindows.cpp b/src/autotype/windows/AutoTypeWindows.cpp index 3ff2343b..c3c2c30a 100644 --- a/src/autotype/windows/AutoTypeWindows.cpp +++ b/src/autotype/windows/AutoTypeWindows.cpp @@ -173,6 +173,7 @@ void AutoTypePlatformWin::sendKey(Qt::Key key, bool isKeyDown) ::SendInput(1, &in, sizeof(INPUT)); } +// clang-format off // // Translate qt key code to windows virtual key code // see: https://msdn.microsoft.com/en-us/library/windows/desktop/dd375731%28v=vs.85%29.aspx @@ -426,6 +427,7 @@ BOOL AutoTypePlatformWin::isExtendedKey(DWORD nativeKeyCode) return FALSE; } } +// clang-format on // // Translate qt key modifiers to windows modifiers diff --git a/src/autotype/xcb/KeySymMap.h b/src/autotype/xcb/KeySymMap.h index 55022feb..2e73da53 100644 --- a/src/autotype/xcb/KeySymMap.h +++ b/src/autotype/xcb/KeySymMap.h @@ -4,6 +4,7 @@ const int AutoTypePlatformX11::m_unicodeToKeysymLen = 632; +// clang-format off const uint AutoTypePlatformX11::m_unicodeToKeysymKeys[] = { 0x0100, 0x0101, 0x0102, 0x0103, 0x0104, 0x0105, 0x0106, 0x0107, 0x0108, 0x0109, 0x010a, 0x010b, 0x010c, 0x010d, 0x010e, 0x010f, @@ -167,3 +168,4 @@ const uint AutoTypePlatformX11::m_unicodeToKeysymValues[] = { 0x04ac, 0x04d4, 0x04ad, 0x04d5, 0x04ae, 0x04d6, 0x04d7, 0x04d8, 0x04d9, 0x04da, 0x04db, 0x04dc, 0x04a6, 0x04dd, 0x04a5, 0x04b0 }; +// clang-format on diff --git a/src/core/DatabaseIcons.cpp b/src/core/DatabaseIcons.cpp index 4e62f79e..e53c6aa2 100644 --- a/src/core/DatabaseIcons.cpp +++ b/src/core/DatabaseIcons.cpp @@ -22,6 +22,8 @@ DatabaseIcons* DatabaseIcons::m_instance(nullptr); const int DatabaseIcons::IconCount(69); const int DatabaseIcons::ExpiredIconIndex(45); + +// clang-format off const char* const DatabaseIcons::m_indexToName[] = { "C00_Password.png", "C01_Package_Network.png", @@ -93,6 +95,7 @@ const char* const DatabaseIcons::m_indexToName[] = { "C67_Certificate.png", "C68_BlackBerry.png" }; +// clang-format on QImage DatabaseIcons::icon(int index) { diff --git a/src/format/KdbxWriter.h b/src/format/KdbxWriter.h index 5aa41766..8fec336d 100644 --- a/src/format/KdbxWriter.h +++ b/src/format/KdbxWriter.h @@ -23,7 +23,9 @@ #include +// clang-format off #define CHECK_RETURN_FALSE(x) if (!(x)) return false; +// clang-format on class QIODevice; class Database; diff --git a/src/format/KeePass2.h b/src/format/KeePass2.h index 67779121..a46df7fa 100644 --- a/src/format/KeePass2.h +++ b/src/format/KeePass2.h @@ -1,19 +1,19 @@ /* - * Copyright (C) 2010 Felix Geyer - * - * 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 (C) 2010 Felix Geyer + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ #ifndef KEEPASSX_KEEPASS2_H #define KEEPASSX_KEEPASS2_H diff --git a/tests/TestKdbx4.cpp b/tests/TestKdbx4.cpp index f0ef1bfa..1d50b8e7 100644 --- a/tests/TestKdbx4.cpp +++ b/tests/TestKdbx4.cpp @@ -182,6 +182,7 @@ void TestKdbx4::testFormat400Upgrade() QCOMPARE(*targetDb->rootGroup()->customData(), *sourceDb->rootGroup()->customData()); } +// clang-format off void TestKdbx4::testFormat400Upgrade_data() { QTest::addColumn("kdfUuid"); @@ -213,6 +214,7 @@ void TestKdbx4::testFormat400Upgrade_data() QTest::newRow("AES-KDF + Twofish + CustomData") << KeePass2::KDF_AES_KDBX4 << KeePass2::CIPHER_TWOFISH << true << kdbx4; QTest::newRow("AES-KDF (legacy) + Twofish + CustomData") << KeePass2::KDF_AES_KDBX3 << KeePass2::CIPHER_TWOFISH << true << kdbx4; } +// clang-format on void TestKdbx4::testUpgradeMasterKeyIntegrity() { diff --git a/tests/TestKeePass2Format.cpp b/tests/TestKeePass2Format.cpp index a493c617..266047be 100644 --- a/tests/TestKeePass2Format.cpp +++ b/tests/TestKeePass2Format.cpp @@ -357,6 +357,7 @@ void TestKeePass2Format::testXmlBroken() QCOMPARE(hasError, expectError); } +// clang-format off void TestKeePass2Format::testXmlBroken_data() { QTest::addColumn("baseName"); @@ -381,6 +382,7 @@ void TestKeePass2Format::testXmlBroken_data() QTest::newRow("BrokenDifferentEntryHistoryUuid (strict)") << "BrokenDifferentEntryHistoryUuid" << true << true; QTest::newRow("BrokenDifferentEntryHistoryUuid (not strict)") << "BrokenDifferentEntryHistoryUuid" << false << false; } +// clang-format on void TestKeePass2Format::testXmlEmptyUuids() { diff --git a/tests/TestKeys.cpp b/tests/TestKeys.cpp index f39d3aa7..e2b7010b 100644 --- a/tests/TestKeys.cpp +++ b/tests/TestKeys.cpp @@ -110,6 +110,7 @@ void TestKeys::testFileKey() QCOMPARE(db->metadata()->name(), QString("%1 Database").arg(name)); } +// clang-format off void TestKeys::testFileKey_data() { QTest::addColumn("type"); @@ -120,6 +121,7 @@ void TestKeys::testFileKey_data() QTest::newRow("Hex") << FileKey::FixedBinaryHex << QString("Hex"); QTest::newRow("Hashed") << FileKey::Hashed << QString("Hashed"); } +// clang-format on void TestKeys::testCreateFileKey() { From 74efc57369b068a0f93cb84ac68b6c17f64c8abe Mon Sep 17 00:00:00 2001 From: Louis-Bertrand Varin Date: Sat, 31 Mar 2018 12:15:51 -0400 Subject: [PATCH 017/267] Removed http/ from excluded dirs. --- cmake/CLangFormat.cmake | 1 - 1 file changed, 1 deletion(-) diff --git a/cmake/CLangFormat.cmake b/cmake/CLangFormat.cmake index 2cb046bb..8c26db93 100644 --- a/cmake/CLangFormat.cmake +++ b/cmake/CLangFormat.cmake @@ -16,7 +16,6 @@ set(EXCLUDED_DIRS # third-party directories zxcvbn/ - http/ streams/QtIOCompressor # objective-c directories autotype/mac From 8324d03f0a015e62b6182843b4478226a5197090 Mon Sep 17 00:00:00 2001 From: Louis-Bertrand Varin Date: Sat, 31 Mar 2018 16:01:30 -0400 Subject: [PATCH 018/267] Formatting the code. --- src/autotype/AutoType.cpp | 69 +-- src/autotype/AutoType.h | 5 +- src/autotype/AutoTypeAction.cpp | 4 - src/autotype/AutoTypeAction.h | 10 +- src/autotype/AutoTypePlatformPlugin.h | 8 +- src/autotype/AutoTypeSelectDialog.cpp | 4 +- src/autotype/AutoTypeSelectView.cpp | 3 +- src/autotype/ShortcutWidget.cpp | 9 +- src/autotype/WildcardMatcher.cpp | 6 +- src/autotype/test/AutoTypeTest.h | 6 +- src/autotype/test/AutoTypeTestInterface.h | 4 +- src/autotype/windows/AutoTypeWindows.cpp | 11 +- src/autotype/windows/AutoTypeWindows.h | 3 +- src/autotype/xcb/AutoTypeXCB.cpp | 114 ++--- src/autotype/xcb/AutoTypeXCB.h | 10 +- src/browser/BrowserAccessControlDialog.cpp | 11 +- src/browser/BrowserAccessControlDialog.h | 5 +- src/browser/BrowserAction.cpp | 82 ++-- src/browser/BrowserAction.h | 73 +-- src/browser/BrowserClients.cpp | 12 +- src/browser/BrowserClients.h | 35 +- src/browser/BrowserEntryConfig.cpp | 7 +- src/browser/BrowserEntryConfig.h | 10 +- src/browser/BrowserOptionDialog.cpp | 21 +- src/browser/BrowserOptionDialog.h | 7 +- src/browser/BrowserService.cpp | 143 +++--- src/browser/BrowserService.h | 99 +++-- src/browser/BrowserSettings.cpp | 36 +- src/browser/BrowserSettings.h | 12 +- src/browser/HostInstaller.cpp | 143 +++--- src/browser/HostInstaller.h | 30 +- src/browser/NativeMessagingBase.cpp | 9 +- src/browser/NativeMessagingBase.h | 36 +- src/browser/NativeMessagingHost.cpp | 24 +- src/browser/NativeMessagingHost.h | 42 +- src/browser/Variant.h | 3 +- src/cli/Diceware.cpp | 15 +- src/cli/Edit.cpp | 5 +- src/cli/Extract.cpp | 4 +- src/cli/Generate.cpp | 32 +- src/cli/Show.cpp | 14 +- src/core/AsyncTask.h | 60 +-- src/core/AutoTypeAssociations.cpp | 3 +- src/core/AutoTypeMatch.cpp | 14 +- src/core/Config.cpp | 14 +- src/core/Config.h | 5 +- src/core/CsvParser.cpp | 179 +++++--- src/core/CsvParser.h | 80 ++-- src/core/CustomData.cpp | 2 +- src/core/CustomData.h | 3 +- src/core/Database.cpp | 7 +- src/core/Database.h | 5 +- src/core/DatabaseIcons.cpp | 3 +- src/core/DatabaseIcons.h | 3 +- src/core/Endian.h | 82 ++-- src/core/Entry.cpp | 87 ++-- src/core/Entry.h | 23 +- src/core/EntryAttachments.cpp | 14 +- src/core/EntryAttributes.cpp | 23 +- src/core/EntrySearcher.cpp | 23 +- src/core/EntrySearcher.h | 1 - src/core/Exporter.h | 4 +- src/core/FilePath.cpp | 42 +- src/core/FilePath.h | 3 +- src/core/Global.h | 26 +- src/core/Group.cpp | 66 ++- src/core/Group.h | 28 +- src/core/InactivityTimer.cpp | 6 +- src/core/ListDeleter.h | 11 +- src/core/MacPasteboard.cpp | 27 +- src/core/MacPasteboard.h | 15 +- src/core/Metadata.cpp | 19 +- src/core/Metadata.h | 2 +- src/core/PassphraseGenerator.cpp | 12 +- src/core/PasswordGenerator.cpp | 11 +- src/core/PasswordGenerator.h | 14 +- src/core/ScreenLockListener.cpp | 10 +- src/core/ScreenLockListener.h | 3 +- src/core/ScreenLockListenerDBus.cpp | 82 ++-- src/core/ScreenLockListenerDBus.h | 4 +- src/core/ScreenLockListenerPrivate.cpp | 2 +- src/core/ScreenLockListenerWin.cpp | 11 +- src/core/ScreenLockListenerWin.h | 6 +- src/core/SignalMultiplexer.cpp | 6 +- src/core/TimeDelta.cpp | 7 +- src/core/Tools.cpp | 464 ++++++++++---------- src/core/Tools.h | 48 +- src/core/Translator.cpp | 13 +- src/core/Uuid.cpp | 6 +- src/core/Uuid.h | 2 +- src/crypto/Crypto.cpp | 30 +- src/crypto/Random.cpp | 1 - src/crypto/Random.h | 7 +- src/crypto/SymmetricCipher.h | 2 +- src/crypto/SymmetricCipherBackend.h | 4 +- src/crypto/SymmetricCipherGcrypt.cpp | 9 +- src/crypto/SymmetricCipherGcrypt.h | 5 +- src/crypto/argon2/argon2.h | 2 +- src/crypto/kdf/AesKdf.cpp | 7 +- src/crypto/kdf/AesKdf.h | 8 +- src/crypto/kdf/Argon2Kdf.cpp | 35 +- src/crypto/kdf/Argon2Kdf.h | 3 +- src/crypto/kdf/Kdf.h | 1 - src/crypto/kdf/Kdf_p.h | 4 +- src/format/Kdbx3Reader.cpp | 18 +- src/format/Kdbx3Reader.h | 10 +- src/format/Kdbx3Writer.cpp | 33 +- src/format/Kdbx3Writer.h | 4 +- src/format/Kdbx4Reader.cpp | 26 +- src/format/Kdbx4Reader.h | 8 +- src/format/Kdbx4Writer.cpp | 43 +- src/format/Kdbx4Writer.h | 2 +- src/format/KdbxReader.cpp | 4 +- src/format/KdbxReader.h | 9 +- src/format/KdbxWriter.h | 10 +- src/format/KdbxXmlReader.cpp | 28 +- src/format/KdbxXmlReader.h | 10 +- src/format/KdbxXmlWriter.cpp | 64 ++- src/format/KdbxXmlWriter.h | 4 +- src/format/KeePass1Reader.cpp | 131 ++---- src/format/KeePass1Reader.h | 12 +- src/format/KeePass2.cpp | 13 +- src/format/KeePass2.h | 216 ++++----- src/format/KeePass2RandomStream.cpp | 6 +- src/format/KeePass2RandomStream.h | 2 +- src/format/KeePass2Reader.cpp | 2 +- src/format/KeePass2Reader.h | 15 +- src/format/KeePass2Repair.cpp | 10 +- src/format/KeePass2Writer.cpp | 13 +- src/format/KeePass2Writer.h | 2 +- src/gui/AboutDialog.cpp | 23 +- src/gui/AboutDialog.h | 3 +- src/gui/Application.cpp | 62 +-- src/gui/Application.h | 2 +- src/gui/CategoryListWidget.cpp | 44 +- src/gui/CategoryListWidget.h | 14 +- src/gui/ChangeMasterKeyWidget.cpp | 43 +- src/gui/ChangeMasterKeyWidget.h | 3 +- src/gui/Clipboard.cpp | 3 +- src/gui/Clipboard.h | 3 +- src/gui/CloneDialog.cpp | 2 +- src/gui/CloneDialog.h | 9 +- src/gui/DatabaseOpenWidget.cpp | 32 +- src/gui/DatabaseOpenWidget.h | 3 +- src/gui/DatabaseRepairWidget.cpp | 16 +- src/gui/DatabaseSettingsWidget.cpp | 45 +- src/gui/DatabaseSettingsWidget.h | 18 +- src/gui/DatabaseTabWidget.cpp | 129 +++--- src/gui/DatabaseTabWidget.h | 5 +- src/gui/DatabaseWidget.cpp | 228 +++++----- src/gui/DatabaseWidget.h | 13 +- src/gui/DatabaseWidgetStateSync.cpp | 21 +- src/gui/DetailsWidget.cpp | 27 +- src/gui/DetailsWidget.h | 3 +- src/gui/DialogyWidget.cpp | 34 +- src/gui/DragTabBar.cpp | 9 +- src/gui/EditWidget.cpp | 8 +- src/gui/EditWidget.h | 5 +- src/gui/EditWidgetIcons.cpp | 79 ++-- src/gui/EditWidgetIcons.h | 5 +- src/gui/EditWidgetProperties.cpp | 28 +- src/gui/EditWidgetProperties.h | 5 +- src/gui/FileDialog.cpp | 58 +-- src/gui/FileDialog.h | 36 +- src/gui/Font.h | 5 +- src/gui/IconModels.cpp | 9 +- src/gui/KeePass1OpenWidget.cpp | 13 +- src/gui/LineEdit.cpp | 11 +- src/gui/MainWindow.cpp | 386 ++++++++-------- src/gui/MainWindow.h | 27 +- src/gui/MessageBox.cpp | 24 +- src/gui/MessageBox.h | 12 +- src/gui/MessageWidget.cpp | 4 +- src/gui/PasswordEdit.cpp | 10 +- src/gui/PasswordGeneratorWidget.cpp | 25 +- src/gui/PasswordGeneratorWidget.h | 9 +- src/gui/SearchWidget.cpp | 1 - src/gui/SearchWidget.h | 3 +- src/gui/SettingsWidget.cpp | 91 ++-- src/gui/SettingsWidget.h | 18 +- src/gui/SetupTotpDialog.cpp | 11 +- src/gui/SetupTotpDialog.h | 9 +- src/gui/TotpDialog.cpp | 2 - src/gui/TotpDialog.h | 9 +- src/gui/UnlockDatabaseDialog.cpp | 2 +- src/gui/UnlockDatabaseDialog.h | 2 +- src/gui/UnlockDatabaseWidget.cpp | 2 +- src/gui/WelcomeWidget.cpp | 18 +- src/gui/WelcomeWidget.h | 5 +- src/gui/csvImport/CsvImportWidget.cpp | 161 ++++--- src/gui/csvImport/CsvImportWidget.h | 14 +- src/gui/csvImport/CsvImportWizard.cpp | 6 +- src/gui/csvImport/CsvImportWizard.h | 10 +- src/gui/csvImport/CsvParserModel.cpp | 67 +-- src/gui/csvImport/CsvParserModel.h | 15 +- src/gui/entry/AutoTypeAssociationsModel.cpp | 17 +- src/gui/entry/AutoTypeMatchModel.cpp | 3 +- src/gui/entry/AutoTypeMatchView.cpp | 3 +- src/gui/entry/EditEntryWidget.cpp | 155 ++++--- src/gui/entry/EditEntryWidget.h | 8 +- src/gui/entry/EditEntryWidget_p.h | 3 +- src/gui/entry/EntryAttachmentsModel.cpp | 8 +- src/gui/entry/EntryAttachmentsModel.h | 3 +- src/gui/entry/EntryAttachmentsWidget.cpp | 35 +- src/gui/entry/EntryAttachmentsWidget.h | 5 +- src/gui/entry/EntryAttributesModel.cpp | 35 +- src/gui/entry/EntryHistoryModel.cpp | 6 +- src/gui/entry/EntryModel.cpp | 10 +- src/gui/entry/EntryView.cpp | 9 +- src/gui/entry/EntryView.h | 4 +- src/gui/group/EditGroupWidget.cpp | 36 +- src/gui/group/EditGroupWidget.h | 3 +- src/gui/group/GroupModel.cpp | 63 +-- src/gui/group/GroupModel.h | 4 +- src/gui/group/GroupView.cpp | 12 +- src/gui/widgets/ElidedLabel.cpp | 7 +- src/gui/widgets/ElidedLabel.h | 4 +- src/keys/ChallengeResponseKey.h | 4 +- src/keys/CompositeKey.cpp | 2 +- src/keys/CompositeKey.h | 6 +- src/keys/FileKey.cpp | 3 +- src/keys/FileKey.h | 5 +- src/keys/Key.h | 4 +- src/keys/YkChallengeResponseKey.cpp | 20 +- src/keys/YkChallengeResponseKey.h | 1 - src/keys/drivers/YubiKey.cpp | 13 +- src/keys/drivers/YubiKey.h | 10 +- src/keys/drivers/YubiKeyStub.cpp | 4 +- src/main.cpp | 35 +- src/proxy/NativeMessagingHost.cpp | 17 +- src/proxy/NativeMessagingHost.h | 2 +- src/proxy/keepassxc-proxy.cpp | 14 +- src/sshagent/ASN1Key.cpp | 16 +- src/sshagent/AgentSettingsPage.cpp | 1 - src/sshagent/AgentSettingsPage.h | 2 +- src/sshagent/AgentSettingsWidget.cpp | 2 +- src/sshagent/AgentSettingsWidget.h | 5 +- src/sshagent/BinaryStream.cpp | 33 +- src/sshagent/BinaryStream.h | 4 +- src/sshagent/KeeAgentSettings.cpp | 4 +- src/sshagent/KeeAgentSettings.h | 4 +- src/sshagent/OpenSSHKey.cpp | 8 +- src/sshagent/OpenSSHKey.h | 2 +- src/sshagent/SSHAgent.cpp | 15 +- src/sshagent/SSHAgent.h | 22 +- src/sshagent/includes.h | 3 +- src/streams/HashedBlockStream.cpp | 17 +- src/streams/HmacBlockStream.h | 4 +- src/streams/LayeredStream.cpp | 10 +- src/streams/SymmetricCipherStream.cpp | 28 +- src/streams/SymmetricCipherStream.h | 6 +- src/totp/totp.cpp | 26 +- src/totp/totp.h | 4 +- tests/FailDevice.cpp | 6 +- tests/TestAutoType.cpp | 37 +- tests/TestCryptoHash.cpp | 9 +- tests/TestCsvExporter.cpp | 12 +- tests/TestCsvParser.cpp | 52 ++- tests/TestCsvParser.h | 5 +- tests/TestDatabase.cpp | 10 +- tests/TestDeletedObjects.cpp | 22 +- tests/TestEntry.cpp | 123 +++--- tests/TestEntryModel.cpp | 38 +- tests/TestEntrySearcher.cpp | 3 +- tests/TestEntrySearcher.h | 1 - tests/TestGlobal.h | 64 ++- tests/TestGroup.cpp | 7 +- tests/TestGroup.h | 2 +- tests/TestGroupModel.cpp | 16 +- tests/TestKdbx2.cpp | 6 +- tests/TestKdbx2.h | 2 +- tests/TestKdbx3.cpp | 25 +- tests/TestKdbx3.h | 17 +- tests/TestKdbx4.cpp | 63 +-- tests/TestKdbx4.h | 16 +- tests/TestKeePass1Reader.cpp | 3 +- tests/TestKeePass2Format.cpp | 23 +- tests/TestKeePass2Format.h | 18 +- tests/TestKeePass2RandomStream.cpp | 4 - tests/TestKeys.cpp | 5 +- tests/TestMerge.cpp | 1 - tests/TestModified.cpp | 4 +- tests/TestOpenSSHKey.cpp | 202 ++++----- tests/TestRandom.cpp | 2 - tests/TestSymmetricCipher.cpp | 177 +++----- tests/TestTotp.cpp | 76 ++-- tests/TestWildcardMatcher.cpp | 3 +- tests/TestYkChallengeResponseKey.cpp | 4 +- tests/TestYkChallengeResponseKey.h | 2 +- tests/gui/TemporaryFile.cpp | 4 +- tests/gui/TemporaryFile.h | 6 +- tests/gui/TestGui.cpp | 94 ++-- tests/gui/TestGui.h | 12 +- tests/mock/MockChallengeResponseKey.h | 2 +- 294 files changed, 3796 insertions(+), 3740 deletions(-) mode change 100755 => 100644 src/browser/BrowserAccessControlDialog.cpp mode change 100755 => 100644 src/browser/BrowserAccessControlDialog.h mode change 100755 => 100644 src/browser/BrowserAction.cpp mode change 100755 => 100644 src/browser/BrowserAction.h mode change 100755 => 100644 src/browser/BrowserClients.cpp mode change 100755 => 100644 src/browser/BrowserClients.h mode change 100755 => 100644 src/browser/BrowserOptionDialog.cpp mode change 100755 => 100644 src/browser/BrowserOptionDialog.h mode change 100755 => 100644 src/browser/BrowserSettings.cpp mode change 100755 => 100644 src/browser/BrowserSettings.h mode change 100755 => 100644 src/browser/NativeMessagingHost.cpp mode change 100755 => 100644 src/browser/NativeMessagingHost.h mode change 100755 => 100644 src/proxy/NativeMessagingHost.cpp mode change 100755 => 100644 src/proxy/NativeMessagingHost.h diff --git a/src/autotype/AutoType.cpp b/src/autotype/AutoType.cpp index 3f44a994..e215f726 100644 --- a/src/autotype/AutoType.cpp +++ b/src/autotype/AutoType.cpp @@ -20,7 +20,7 @@ #include #include -#include +#include #include "config-keepassx.h" @@ -304,8 +304,8 @@ void AutoType::performGlobalAutoType(const QList& dbList) auto* msgBox = new QMessageBox(); msgBox->setAttribute(Qt::WA_DeleteOnClose); msgBox->setWindowTitle(tr("Auto-Type - KeePassXC")); - msgBox->setText(tr("Couldn't find an entry that matches the window title:").append("\n\n") - .append(windowTitle)); + msgBox->setText( + tr("Couldn't find an entry that matches the window title:").append("\n\n").append(windowTitle)); msgBox->setIcon(QMessageBox::Information); msgBox->setStandardButtons(QMessageBox::Ok); msgBox->show(); @@ -323,8 +323,7 @@ void AutoType::performGlobalAutoType(const QList& dbList) auto* selectDialog = new AutoTypeSelectDialog(); // connect slots, both of which must unlock the m_inGlobalAutoTypeDialog mutex - connect(selectDialog, SIGNAL(matchActivated(AutoTypeMatch)), - SLOT(performAutoTypeFromGlobal(AutoTypeMatch))); + connect(selectDialog, SIGNAL(matchActivated(AutoTypeMatch)), SLOT(performAutoTypeFromGlobal(AutoTypeMatch))); connect(selectDialog, SIGNAL(rejected()), SLOT(autoTypeRejectedFromGlobal())); selectDialog->setMatchList(matchList); @@ -449,11 +448,11 @@ QList AutoType::createActionFromTemplate(const QString& tmpl, c list.append(new AutoTypeKey(Qt::Key_Left)); } else if (tmplName.compare("right", Qt::CaseInsensitive) == 0) { list.append(new AutoTypeKey(Qt::Key_Right)); - } else if (tmplName.compare("insert", Qt::CaseInsensitive) == 0 || - tmplName.compare("ins", Qt::CaseInsensitive) == 0) { + } else if (tmplName.compare("insert", Qt::CaseInsensitive) == 0 + || tmplName.compare("ins", Qt::CaseInsensitive) == 0) { list.append(new AutoTypeKey(Qt::Key_Insert)); - } else if (tmplName.compare("delete", Qt::CaseInsensitive) == 0 || - tmplName.compare("del", Qt::CaseInsensitive) == 0) { + } else if (tmplName.compare("delete", Qt::CaseInsensitive) == 0 + || tmplName.compare("del", Qt::CaseInsensitive) == 0) { list.append(new AutoTypeKey(Qt::Key_Delete)); } else if (tmplName.compare("home", Qt::CaseInsensitive) == 0) { list.append(new AutoTypeKey(Qt::Key_Home)); @@ -463,8 +462,9 @@ QList AutoType::createActionFromTemplate(const QString& tmpl, c list.append(new AutoTypeKey(Qt::Key_PageUp)); } else if (tmplName.compare("pgdown", Qt::CaseInsensitive) == 0) { list.append(new AutoTypeKey(Qt::Key_PageDown)); - } else if (tmplName.compare("backspace", Qt::CaseInsensitive) == 0 || - tmplName.compare("bs", Qt::CaseInsensitive) == 0 || tmplName.compare("bksp", Qt::CaseInsensitive) == 0) { + } else if (tmplName.compare("backspace", Qt::CaseInsensitive) == 0 + || tmplName.compare("bs", Qt::CaseInsensitive) == 0 + || tmplName.compare("bksp", Qt::CaseInsensitive) == 0) { list.append(new AutoTypeKey(Qt::Key_Backspace)); } else if (tmplName.compare("break", Qt::CaseInsensitive) == 0) { list.append(new AutoTypeKey(Qt::Key_Pause)); @@ -591,13 +591,13 @@ QList AutoType::autoTypeSequences(const Entry* entry, const QString& wi } } - if (config()->get("AutoTypeEntryTitleMatch").toBool() && - windowMatchesTitle(windowTitle, entry->resolvePlaceholder(entry->title()))) { + if (config()->get("AutoTypeEntryTitleMatch").toBool() + && windowMatchesTitle(windowTitle, entry->resolvePlaceholder(entry->title()))) { sequenceList.append(entry->effectiveAutoTypeSequence()); } - if (config()->get("AutoTypeEntryURLMatch").toBool() && - windowMatchesUrl(windowTitle, entry->resolvePlaceholder(entry->url()))) { + if (config()->get("AutoTypeEntryURLMatch").toBool() + && windowMatchesUrl(windowTitle, entry->resolvePlaceholder(entry->url()))) { sequenceList.append(entry->effectiveAutoTypeSequence()); } @@ -605,7 +605,7 @@ QList AutoType::autoTypeSequences(const Entry* entry, const QString& wi return sequenceList; } } else { - sequenceList.append(entry->effectiveAutoTypeSequence()); + sequenceList.append(entry->effectiveAutoTypeSequence()); } return sequenceList; @@ -659,7 +659,7 @@ bool AutoType::checkSyntax(const QString& string) QString allowRepetition = "(?:\\s\\d+)?"; // the ":" allows custom commands with syntax S:Field // exclude BEEP otherwise will be checked as valid - QString normalCommands = "(?!BEEP\\s)[A-Z:]*" + allowRepetition; + QString normalCommands = "(?!BEEP\\s)[A-Z:]*" + allowRepetition; QString specialLiterals = "[\\^\\%\\(\\)~\\{\\}\\[\\]\\+]" + allowRepetition; QString functionKeys = "(?:F[1-9]" + allowRepetition + "|F1[0-2])" + allowRepetition; QString numpad = "NUMPAD\\d" + allowRepetition; @@ -673,9 +673,21 @@ bool AutoType::checkSyntax(const QString& string) // a normal string not in parentheses QString fixedStrings = "[^\\^\\%~\\+@\\{\\}]*"; - QRegularExpression autoTypeSyntax("^(?:" + shortcutKeys + "|" + fixedStrings + "|\\{(?:" + normalCommands + "|" + specialLiterals + - "|" + functionKeys + "|" + numpad + "|" + delay + "|" + beep + "|" + vkey + ")\\}|\\{" + customAttributes + "\\})*$", - QRegularExpression::CaseInsensitiveOption); + QRegularExpression autoTypeSyntax( + "^(?:" + shortcutKeys + "|" + fixedStrings + "|\\{(?:" + normalCommands + "|" + specialLiterals + "|" + + functionKeys + + "|" + + numpad + + "|" + + delay + + "|" + + beep + + "|" + + vkey + + ")\\}|\\{" + + customAttributes + + "\\})*$", + QRegularExpression::CaseInsensitiveOption); QRegularExpressionMatch match = autoTypeSyntax.match(string); return match.hasMatch(); } @@ -686,7 +698,7 @@ bool AutoType::checkSyntax(const QString& string) bool AutoType::checkHighDelay(const QString& string) { // 5 digit numbers(10 seconds) are too much - QRegularExpression highDelay("\\{DELAY\\s\\d{5,}\\}", QRegularExpression::CaseInsensitiveOption); + QRegularExpression highDelay("\\{DELAY\\s\\d{5,}\\}", QRegularExpression::CaseInsensitiveOption); QRegularExpressionMatch match = highDelay.match(string); return match.hasMatch(); } @@ -697,7 +709,7 @@ bool AutoType::checkHighDelay(const QString& string) bool AutoType::checkSlowKeypress(const QString& string) { // 3 digit numbers(100 milliseconds) are too much - QRegularExpression slowKeypress("\\{DELAY=\\d{3,}\\}", QRegularExpression::CaseInsensitiveOption); + QRegularExpression slowKeypress("\\{DELAY=\\d{3,}\\}", QRegularExpression::CaseInsensitiveOption); QRegularExpressionMatch match = slowKeypress.match(string); return match.hasMatch(); } @@ -724,7 +736,9 @@ bool AutoType::verifyAutoTypeSyntax(const QString& sequence) return false; } else if (AutoType::checkHighDelay(sequence)) { QMessageBox::StandardButton reply; - reply = QMessageBox::question(nullptr, tr("Auto-Type"), + reply = QMessageBox::question( + nullptr, + tr("Auto-Type"), tr("This Auto-Type command contains a very long delay. Do you really want to proceed?")); if (reply == QMessageBox::No) { @@ -732,7 +746,9 @@ bool AutoType::verifyAutoTypeSyntax(const QString& sequence) } } else if (AutoType::checkSlowKeypress(sequence)) { QMessageBox::StandardButton reply; - reply = QMessageBox::question(nullptr, tr("Auto-Type"), + reply = QMessageBox::question( + nullptr, + tr("Auto-Type"), tr("This Auto-Type command contains very slow key presses. Do you really want to proceed?")); if (reply == QMessageBox::No) { @@ -740,8 +756,9 @@ bool AutoType::verifyAutoTypeSyntax(const QString& sequence) } } else if (AutoType::checkHighRepetition(sequence)) { QMessageBox::StandardButton reply; - reply = QMessageBox::question(nullptr, tr("Auto-Type"), - tr("This Auto-Type command contains arguments which are repeated very often. Do you really want to proceed?")); + reply = + QMessageBox::question(nullptr, tr("Auto-Type"), tr("This Auto-Type command contains arguments which are " + "repeated very often. Do you really want to proceed?")); if (reply == QMessageBox::No) { return false; diff --git a/src/autotype/AutoType.h b/src/autotype/AutoType.h index ad60bd76..28b36bd8 100644 --- a/src/autotype/AutoType.h +++ b/src/autotype/AutoType.h @@ -19,10 +19,10 @@ #ifndef KEEPASSX_AUTOTYPE_H #define KEEPASSX_AUTOTYPE_H +#include #include #include #include -#include #include "core/AutoTypeMatch.h" @@ -47,8 +47,7 @@ public: static bool checkSlowKeypress(const QString& string); static bool checkHighDelay(const QString& string); static bool verifyAutoTypeSyntax(const QString& sequence); - void performAutoType(const Entry* entry, - QWidget* hideWindow = nullptr); + void performAutoType(const Entry* entry, QWidget* hideWindow = nullptr); inline bool isAvailable() { diff --git a/src/autotype/AutoTypeAction.cpp b/src/autotype/AutoTypeAction.cpp index 64dae796..0beb19b3 100644 --- a/src/autotype/AutoTypeAction.cpp +++ b/src/autotype/AutoTypeAction.cpp @@ -34,7 +34,6 @@ void AutoTypeChar::accept(AutoTypeExecutor* executor) executor->execChar(this); } - AutoTypeKey::AutoTypeKey(Qt::Key key) : key(key) { @@ -50,7 +49,6 @@ void AutoTypeKey::accept(AutoTypeExecutor* executor) executor->execKey(this); } - AutoTypeDelay::AutoTypeDelay(int delayMs) : delayMs(delayMs) { @@ -66,7 +64,6 @@ void AutoTypeDelay::accept(AutoTypeExecutor* executor) executor->execDelay(this); } - AutoTypeClearField::AutoTypeClearField() { } @@ -81,7 +78,6 @@ void AutoTypeClearField::accept(AutoTypeExecutor* executor) executor->execClearField(this); } - void AutoTypeExecutor::execDelay(AutoTypeDelay* action) { Tools::wait(action->delayMs); diff --git a/src/autotype/AutoTypeAction.h b/src/autotype/AutoTypeAction.h index 7f0d829c..263566dd 100644 --- a/src/autotype/AutoTypeAction.h +++ b/src/autotype/AutoTypeAction.h @@ -19,8 +19,8 @@ #define KEEPASSX_AUTOTYPEACTION_H #include -#include #include +#include #include "core/Global.h" @@ -29,7 +29,9 @@ class AutoTypeExecutor; class KEEPASSX_EXPORT AutoTypeAction { public: - virtual ~AutoTypeAction() {} + virtual ~AutoTypeAction() + { + } virtual AutoTypeAction* clone() = 0; virtual void accept(AutoTypeExecutor* executor) = 0; }; @@ -75,7 +77,9 @@ public: class KEEPASSX_EXPORT AutoTypeExecutor { public: - virtual ~AutoTypeExecutor() {} + virtual ~AutoTypeExecutor() + { + } virtual void execChar(AutoTypeChar* action) = 0; virtual void execKey(AutoTypeKey* action) = 0; virtual void execDelay(AutoTypeDelay* action); diff --git a/src/autotype/AutoTypePlatformPlugin.h b/src/autotype/AutoTypePlatformPlugin.h index 2945e98c..898b04e6 100644 --- a/src/autotype/AutoTypePlatformPlugin.h +++ b/src/autotype/AutoTypePlatformPlugin.h @@ -25,7 +25,9 @@ class AutoTypePlatformInterface { public: - virtual ~AutoTypePlatformInterface() {} + virtual ~AutoTypePlatformInterface() + { + } virtual bool isAvailable() = 0; virtual QStringList windowTitles() = 0; virtual WId activeWindow() = 0; @@ -35,7 +37,9 @@ public: virtual int platformEventFilter(void* event) = 0; virtual int initialTimeout() = 0; virtual bool raiseWindow(WId window) = 0; - virtual void unload() {} + virtual void unload() + { + } virtual AutoTypeExecutor* createExecutor() = 0; diff --git a/src/autotype/AutoTypeSelectDialog.cpp b/src/autotype/AutoTypeSelectDialog.cpp index eae9e6ff..a4fd98de 100644 --- a/src/autotype/AutoTypeSelectDialog.cpp +++ b/src/autotype/AutoTypeSelectDialog.cpp @@ -61,7 +61,7 @@ AutoTypeSelectDialog::AutoTypeSelectDialog(QWidget* parent) connect(m_view, SIGNAL(activated(QModelIndex)), SLOT(emitMatchActivated(QModelIndex))); connect(m_view, SIGNAL(clicked(QModelIndex)), SLOT(emitMatchActivated(QModelIndex))); - connect(m_view->model(), SIGNAL(rowsRemoved(QModelIndex,int,int)), SLOT(matchRemoved())); + connect(m_view->model(), SIGNAL(rowsRemoved(QModelIndex, int, int)), SLOT(matchRemoved())); connect(m_view, SIGNAL(rejected()), SLOT(reject())); layout->addWidget(m_view); @@ -109,7 +109,7 @@ void AutoTypeSelectDialog::matchRemoved() if (m_rejected) { return; } - + if (m_view->model()->rowCount() == 0) { reject(); } diff --git a/src/autotype/AutoTypeSelectView.cpp b/src/autotype/AutoTypeSelectView.cpp index e4dba051..cfa11367 100644 --- a/src/autotype/AutoTypeSelectView.cpp +++ b/src/autotype/AutoTypeSelectView.cpp @@ -36,8 +36,7 @@ void AutoTypeSelectView::mouseMoveEvent(QMouseEvent* event) if (index.isValid()) { setCurrentIndex(index); setCursor(Qt::PointingHandCursor); - } - else { + } else { unsetCursor(); } diff --git a/src/autotype/ShortcutWidget.cpp b/src/autotype/ShortcutWidget.cpp index 56a37401..95174e43 100644 --- a/src/autotype/ShortcutWidget.cpp +++ b/src/autotype/ShortcutWidget.cpp @@ -50,8 +50,7 @@ void ShortcutWidget::setShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers) if (autoType()->registerGlobalShortcut(m_key, m_modifiers)) { setStyleSheet(""); - } - else { + } else { setStyleSheet("background-color: #FF9696;"); } } @@ -112,14 +111,12 @@ void ShortcutWidget::keyEvent(QKeyEvent* event) if (!release && !keyIsModifier) { if (modifiers != 0) { setShortcut(key, modifiers); - } - else { + } else { resetShortcut(); setStyleSheet(""); displayShortcut(key, modifiers); } - } - else { + } else { if (m_locked) { resetShortcut(); setStyleSheet(""); diff --git a/src/autotype/WildcardMatcher.cpp b/src/autotype/WildcardMatcher.cpp index ad83f9b0..bac78589 100644 --- a/src/autotype/WildcardMatcher.cpp +++ b/src/autotype/WildcardMatcher.cpp @@ -33,8 +33,7 @@ bool WildcardMatcher::match(const QString& pattern) if (patternContainsWildcard()) { return matchWithWildcards(); - } - else { + } else { return patternEqualsText(); } } @@ -63,8 +62,7 @@ bool WildcardMatcher::matchWithWildcards() bool WildcardMatcher::startOrEndDoesNotMatch(const QStringList& parts) { - return !m_text.startsWith(parts.first(), Sensitivity) || - !m_text.endsWith(parts.last(), Sensitivity); + return !m_text.startsWith(parts.first(), Sensitivity) || !m_text.endsWith(parts.last(), Sensitivity); } bool WildcardMatcher::partsMatch(const QStringList& parts) diff --git a/src/autotype/test/AutoTypeTest.h b/src/autotype/test/AutoTypeTest.h index d9a86c3d..849a3b24 100644 --- a/src/autotype/test/AutoTypeTest.h +++ b/src/autotype/test/AutoTypeTest.h @@ -20,13 +20,11 @@ #include -#include "autotype/AutoTypePlatformPlugin.h" #include "autotype/AutoTypeAction.h" +#include "autotype/AutoTypePlatformPlugin.h" #include "autotype/test/AutoTypeTestInterface.h" -class AutoTypePlatformTest : public QObject, - public AutoTypePlatformInterface, - public AutoTypeTestInterface +class AutoTypePlatformTest : public QObject, public AutoTypePlatformInterface, public AutoTypeTestInterface { Q_OBJECT Q_PLUGIN_METADATA(IID "org.keepassx.AutoTypePlatformInterface") diff --git a/src/autotype/test/AutoTypeTestInterface.h b/src/autotype/test/AutoTypeTestInterface.h index 7ee6f21a..7681f2ec 100644 --- a/src/autotype/test/AutoTypeTestInterface.h +++ b/src/autotype/test/AutoTypeTestInterface.h @@ -23,7 +23,9 @@ class AutoTypeTestInterface { public: - virtual ~AutoTypeTestInterface() {} + virtual ~AutoTypeTestInterface() + { + } virtual void setActiveWindowTitle(const QString& title) = 0; virtual QString actionChars() = 0; diff --git a/src/autotype/windows/AutoTypeWindows.cpp b/src/autotype/windows/AutoTypeWindows.cpp index c3c2c30a..634f6893 100644 --- a/src/autotype/windows/AutoTypeWindows.cpp +++ b/src/autotype/windows/AutoTypeWindows.cpp @@ -94,7 +94,7 @@ void AutoTypePlatformWin::unregisterGlobalShortcut(Qt::Key key, Qt::KeyboardModi // int AutoTypePlatformWin::platformEventFilter(void* event) { - MSG *msg = static_cast(event); + MSG* msg = static_cast(event); if (msg->message == WM_HOTKEY && msg->wParam == HOTKEY_ID) { emit globalShortcutTriggered(); @@ -480,17 +480,14 @@ BOOL AutoTypePlatformWin::isAltTabWindow(HWND hwnd) // // Window title enum proc // -BOOL CALLBACK AutoTypePlatformWin::windowTitleEnumProc( - _In_ HWND hwnd, - _In_ LPARAM lParam -) +BOOL CALLBACK AutoTypePlatformWin::windowTitleEnumProc(_In_ HWND hwnd, _In_ LPARAM lParam) { if (!isAltTabWindow(hwnd)) { // Skip window return TRUE; } - QStringList *list = reinterpret_cast(lParam); + QStringList* list = reinterpret_cast(lParam); QString title = windowTitle(hwnd); if (!title.isEmpty()) { @@ -508,7 +505,7 @@ QString AutoTypePlatformWin::windowTitle(HWND hwnd) wchar_t title[MAX_WINDOW_TITLE_LENGTH]; int count = ::GetWindowTextW(hwnd, title, MAX_WINDOW_TITLE_LENGTH); - return QString::fromUtf16(reinterpret_cast(title), count); + return QString::fromUtf16(reinterpret_cast(title), count); } // diff --git a/src/autotype/windows/AutoTypeWindows.h b/src/autotype/windows/AutoTypeWindows.h index 88b9a9fd..33d61ef2 100644 --- a/src/autotype/windows/AutoTypeWindows.h +++ b/src/autotype/windows/AutoTypeWindows.h @@ -22,8 +22,8 @@ #include #include -#include "autotype/AutoTypePlatformPlugin.h" #include "autotype/AutoTypeAction.h" +#include "autotype/AutoTypePlatformPlugin.h" class AutoTypePlatformWin : public QObject, public AutoTypePlatformInterface { @@ -72,4 +72,3 @@ private: }; #endif // KEEPASSX_AUTOTYPEWINDOWS_H - diff --git a/src/autotype/xcb/AutoTypeXCB.cpp b/src/autotype/xcb/AutoTypeXCB.cpp index 1946c888..e6f4496c 100644 --- a/src/autotype/xcb/AutoTypeXCB.cpp +++ b/src/autotype/xcb/AutoTypeXCB.cpp @@ -40,11 +40,14 @@ AutoTypePlatformX11::AutoTypePlatformX11() m_atomUtf8String = XInternAtom(m_dpy, "UTF8_STRING", True); m_atomNetActiveWindow = XInternAtom(m_dpy, "_NET_ACTIVE_WINDOW", True); - m_classBlacklist << "desktop_window" << "gnome-panel"; // Gnome - m_classBlacklist << "kdesktop" << "kicker"; // KDE 3 + m_classBlacklist << "desktop_window" + << "gnome-panel"; // Gnome + m_classBlacklist << "kdesktop" + << "kicker"; // KDE 3 m_classBlacklist << "Plasma"; // KDE 4 m_classBlacklist << "plasmashell"; // KDE 5 - m_classBlacklist << "xfdesktop" << "xfce4-panel"; // Xfce 4 + m_classBlacklist << "xfdesktop" + << "xfce4-panel"; // Xfce 4 m_currentGlobalKey = static_cast(0); m_currentGlobalModifiers = 0; @@ -146,12 +149,9 @@ bool AutoTypePlatformX11::registerGlobalShortcut(Qt::Key key, Qt::KeyboardModifi startCatchXErrors(); XGrabKey(m_dpy, keycode, nativeModifiers, m_rootWindow, True, GrabModeAsync, GrabModeAsync); - XGrabKey(m_dpy, keycode, nativeModifiers | Mod2Mask, m_rootWindow, True, GrabModeAsync, - GrabModeAsync); - XGrabKey(m_dpy, keycode, nativeModifiers | LockMask, m_rootWindow, True, GrabModeAsync, - GrabModeAsync); - XGrabKey(m_dpy, keycode, nativeModifiers | Mod2Mask | LockMask, m_rootWindow, True, - GrabModeAsync, GrabModeAsync); + XGrabKey(m_dpy, keycode, nativeModifiers | Mod2Mask, m_rootWindow, True, GrabModeAsync, GrabModeAsync); + XGrabKey(m_dpy, keycode, nativeModifiers | LockMask, m_rootWindow, True, GrabModeAsync, GrabModeAsync); + XGrabKey(m_dpy, keycode, nativeModifiers | Mod2Mask | LockMask, m_rootWindow, True, GrabModeAsync, GrabModeAsync); stopCatchXErrors(); if (!m_xErrorOccurred) { @@ -160,8 +160,7 @@ bool AutoTypePlatformX11::registerGlobalShortcut(Qt::Key key, Qt::KeyboardModifi m_currentGlobalKeycode = keycode; m_currentGlobalNativeModifiers = nativeModifiers; return true; - } - else { + } else { unregisterGlobalShortcut(key, modifiers); return false; } @@ -211,29 +210,26 @@ int AutoTypePlatformX11::platformEventFilter(void* event) if (type == XCB_KEY_PRESS || type == XCB_KEY_RELEASE) { xcb_key_press_event_t* keyPressEvent = static_cast(event); if (keyPressEvent->detail == m_currentGlobalKeycode - && (keyPressEvent->state & m_modifierMask) == m_currentGlobalNativeModifiers - && (!QApplication::activeWindow() || QApplication::activeWindow()->isMinimized()) - && m_loaded) { + && (keyPressEvent->state & m_modifierMask) == m_currentGlobalNativeModifiers + && (!QApplication::activeWindow() || QApplication::activeWindow()->isMinimized()) + && m_loaded) { if (type == XCB_KEY_PRESS) { emit globalShortcutTriggered(); } return 1; } - } - else if (type == XCB_MAPPING_NOTIFY) { + } else if (type == XCB_MAPPING_NOTIFY) { xcb_mapping_notify_event_t* mappingNotifyEvent = static_cast(event); if (mappingNotifyEvent->request == XCB_MAPPING_KEYBOARD - || mappingNotifyEvent->request == XCB_MAPPING_MODIFIER) - { + || mappingNotifyEvent->request == XCB_MAPPING_MODIFIER) { XMappingEvent xMappingEvent; memset(&xMappingEvent, 0, sizeof(xMappingEvent)); xMappingEvent.type = MappingNotify; xMappingEvent.display = m_dpy; if (mappingNotifyEvent->request == XCB_MAPPING_KEYBOARD) { xMappingEvent.request = MappingKeyboard; - } - else { + } else { xMappingEvent.request = MappingModifier; } xMappingEvent.first_keycode = mappingNotifyEvent->first_keycode; @@ -263,13 +259,12 @@ QString AutoTypePlatformX11::windowTitle(Window window, bool useBlacklist) // the window manager spec says we should read _NET_WM_NAME first, then fall back to WM_NAME - int retVal = XGetWindowProperty(m_dpy, window, m_atomNetWmName, 0, 1000, False, m_atomUtf8String, - &type, &format, &nitems, &after, &data); + int retVal = XGetWindowProperty( + m_dpy, window, m_atomNetWmName, 0, 1000, False, m_atomUtf8String, &type, &format, &nitems, &after, &data); if ((retVal == 0) && data) { title = QString::fromUtf8(reinterpret_cast(data)); - } - else { + } else { XTextProperty textProp; retVal = XGetTextProperty(m_dpy, window, &textProp, m_atomWmName); if ((retVal != 0) && textProp.value) { @@ -278,12 +273,10 @@ QString AutoTypePlatformX11::windowTitle(Window window, bool useBlacklist) if (textProp.encoding == m_atomUtf8String) { title = QString::fromUtf8(reinterpret_cast(textProp.value)); - } - else if ((XmbTextPropertyToTextList(m_dpy, &textProp, &textList, &count) == 0) - && textList && (count > 0)) { + } else if ((XmbTextPropertyToTextList(m_dpy, &textProp, &textList, &count) == 0) && textList + && (count > 0)) { title = QString::fromLocal8Bit(textList[0]); - } - else if (textProp.encoding == m_atomString) { + } else if (textProp.encoding == m_atomString) { title = QString::fromLocal8Bit(reinterpret_cast(textProp.value)); } @@ -386,8 +379,8 @@ bool AutoTypePlatformX11::isTopLevelWindow(Window window) unsigned long nitems; unsigned long after; unsigned char* data = Q_NULLPTR; - int retVal = XGetWindowProperty(m_dpy, window, m_atomWmState, 0, 2, False, m_atomWmState, &type, &format, - &nitems, &after, &data); + int retVal = XGetWindowProperty( + m_dpy, window, m_atomWmState, 0, 2, False, m_atomWmState, &type, &format, &nitems, &after, &data); bool result = false; @@ -408,15 +401,12 @@ KeySym AutoTypePlatformX11::charToKeySym(const QChar& ch) ushort unicode = ch.unicode(); /* first check for Latin-1 characters (1:1 mapping) */ - if ((unicode >= 0x0020 && unicode <= 0x007e) - || (unicode >= 0x00a0 && unicode <= 0x00ff)) { + if ((unicode >= 0x0020 && unicode <= 0x007e) || (unicode >= 0x00a0 && unicode <= 0x00ff)) { return unicode; } /* mapping table generated from keysymdef.h */ - const uint* match = Tools::binaryFind(m_unicodeToKeysymKeys, - m_unicodeToKeysymKeys + m_unicodeToKeysymLen, - unicode); + const uint* match = Tools::binaryFind(m_unicodeToKeysymKeys, m_unicodeToKeysymKeys + m_unicodeToKeysymLen, unicode); int index = match - m_unicodeToKeysymKeys; if (index != m_unicodeToKeysymLen) { return m_unicodeToKeysymValues[index]; @@ -483,8 +473,7 @@ KeySym AutoTypePlatformX11::keyToKeySym(Qt::Key key) default: if (key >= Qt::Key_F1 && key <= Qt::Key_F16) { return XK_F1 + (key - Qt::Key_F1); - } - else { + } else { return NoSymbol; } } @@ -493,13 +482,13 @@ KeySym AutoTypePlatformX11::keyToKeySym(Qt::Key key) /* * Update the keyboard and modifier mapping. * We need the KeyboardMapping for AddKeysym. - * Modifier mapping is required for clearing the modifiers. + * Modifier mapping is required for clearing the modifiers. */ void AutoTypePlatformX11::updateKeymap() { int keycode, inx; int mod_index, mod_key; - XModifierKeymap *modifiers; + XModifierKeymap* modifiers; if (m_xkb) { XkbFreeKeyboard(m_xkb, XkbAllComponentsMask, True); @@ -507,10 +496,9 @@ void AutoTypePlatformX11::updateKeymap() m_xkb = getKeyboard(); XDisplayKeycodes(m_dpy, &m_minKeycode, &m_maxKeycode); - if (m_keysymTable != NULL) XFree(m_keysymTable); - m_keysymTable = XGetKeyboardMapping(m_dpy, - m_minKeycode, m_maxKeycode - m_minKeycode + 1, - &m_keysymPerKeycode); + if (m_keysymTable != NULL) + XFree(m_keysymTable); + m_keysymTable = XGetKeyboardMapping(m_dpy, m_minKeycode, m_maxKeycode - m_minKeycode + 1, &m_keysymPerKeycode); /* determine the keycode to use for remapped keys */ inx = (m_remapKeycode - m_minKeycode) * m_keysymPerKeycode; @@ -518,16 +506,16 @@ void AutoTypePlatformX11::updateKeymap() for (keycode = m_minKeycode; keycode <= m_maxKeycode; keycode++) { inx = (keycode - m_minKeycode) * m_keysymPerKeycode; if (m_keysymTable[inx] == NoSymbol) { - m_remapKeycode = keycode; - m_currentRemapKeysym = NoSymbol; - break; + m_remapKeycode = keycode; + m_currentRemapKeysym = NoSymbol; + break; } } } /* determine the keycode to use for modifiers */ modifiers = XGetModifierMapping(m_dpy); - for (mod_index = ShiftMapIndex; mod_index <= Mod5MapIndex; mod_index ++) { + for (mod_index = ShiftMapIndex; mod_index <= Mod5MapIndex; mod_index++) { m_modifier_keycode[mod_index] = 0; for (mod_key = 0; mod_key < modifiers->max_keypermod; mod_key++) { keycode = modifiers->modifiermap[mod_index * modifiers->max_keypermod + mod_key]; @@ -625,7 +613,7 @@ int AutoTypePlatformX11::AddKeysym(KeySym keysym) return 0; } - int inx = (m_remapKeycode- m_minKeycode) * m_keysymPerKeycode; + int inx = (m_remapKeycode - m_minKeycode) * m_keysymPerKeycode; m_keysymTable[inx] = keysym; m_currentRemapKeysym = keysym; @@ -644,7 +632,7 @@ int AutoTypePlatformX11::AddKeysym(KeySym keysym) void AutoTypePlatformX11::SendKeyEvent(unsigned keycode, bool press) { XSync(m_dpy, False); - int (*oldHandler) (Display*, XErrorEvent*) = XSetErrorHandler(MyErrorHandler); + int (*oldHandler)(Display*, XErrorEvent*) = XSetErrorHandler(MyErrorHandler); XTestFakeKeyEvent(m_dpy, keycode, press, 0); XFlush(m_dpy); @@ -659,7 +647,7 @@ void AutoTypePlatformX11::SendKeyEvent(unsigned keycode, bool press) void AutoTypePlatformX11::SendModifiers(unsigned int mask, bool press) { int mod_index; - for (mod_index = ShiftMapIndex; mod_index <= Mod5MapIndex; mod_index ++) { + for (mod_index = ShiftMapIndex; mod_index <= Mod5MapIndex; mod_index++) { if (mask & (1 << mod_index)) { SendKeyEvent(m_modifier_keycode[mod_index], press); } @@ -670,7 +658,7 @@ void AutoTypePlatformX11::SendModifiers(unsigned int mask, bool press) * Determines the keycode and modifier mask for the given * keysym. */ -int AutoTypePlatformX11::GetKeycode(KeySym keysym, unsigned int *mask) +int AutoTypePlatformX11::GetKeycode(KeySym keysym, unsigned int* mask) { int keycode = XKeysymToKeycode(m_dpy, keysym); @@ -688,15 +676,15 @@ int AutoTypePlatformX11::GetKeycode(KeySym keysym, unsigned int *mask) return 0; } -bool AutoTypePlatformX11::keysymModifiers(KeySym keysym, int keycode, unsigned int *mask) +bool AutoTypePlatformX11::keysymModifiers(KeySym keysym, int keycode, unsigned int* mask) { int shift, mod; unsigned int mods_rtrn; /* determine whether there is a combination of the modifiers (Mod1-Mod5) with or without shift which returns keysym */ - for (shift = 0; shift < 2; shift ++) { - for (mod = ControlMapIndex; mod <= Mod5MapIndex; mod ++) { + for (shift = 0; shift < 2; shift++) { + for (mod = ControlMapIndex; mod <= Mod5MapIndex; mod++) { KeySym keysym_rtrn; *mask = (mod == ControlMapIndex) ? shift : shift | (1 << mod); XkbTranslateKeyCode(m_xkb, keycode, *mask, &mods_rtrn, &keysym_rtrn); @@ -709,8 +697,6 @@ bool AutoTypePlatformX11::keysymModifiers(KeySym keysym, int keycode, unsigned i return false; } - - /* * Send sequence of KeyPressed/KeyReleased events to the focused * window to simulate keyboard. If modifiers (shift, control, etc) @@ -753,7 +739,7 @@ void AutoTypePlatformX11::SendKey(KeySym keysym, unsigned int modifiers) if (!modifiers) { // check every release_check_mask individually if it affects the keysym we would generate // if it doesn't we probably don't need to release it - for (int mod_index = ShiftMapIndex; mod_index <= Mod5MapIndex; mod_index ++) { + for (int mod_index = ShiftMapIndex; mod_index <= Mod5MapIndex; mod_index++) { if (release_check_mask & (1 << mod_index)) { unsigned int mods_rtrn; KeySym keysym_rtrn; @@ -768,7 +754,8 @@ void AutoTypePlatformX11::SendKey(KeySym keysym, unsigned int modifiers) // finally check if the combination of pressed modifiers that we chose to ignore affects the keysym unsigned int mods_rtrn; KeySym keysym_rtrn; - XkbTranslateKeyCode(m_xkb, keycode, wanted_mask | (release_check_mask & ~release_mask), &mods_rtrn, &keysym_rtrn); + XkbTranslateKeyCode( + m_xkb, keycode, wanted_mask | (release_check_mask & ~release_mask), &mods_rtrn, &keysym_rtrn); if (keysym_rtrn != keysym) { // oh well, release all the modifiers we don't want release_mask = release_check_mask; @@ -810,7 +797,6 @@ int AutoTypePlatformX11::MyErrorHandler(Display* my_dpy, XErrorEvent* event) return 0; } - AutoTypeExecutorX11::AutoTypeExecutorX11(AutoTypePlatformX11* platform) : m_platform(platform) { @@ -844,7 +830,6 @@ void AutoTypeExecutorX11::execClearField(AutoTypeClearField* action = nullptr) nanosleep(&ts, nullptr); } - int AutoTypePlatformX11::initialTimeout() { return 500; @@ -870,15 +855,12 @@ bool AutoTypePlatformX11::raiseWindow(WId window) QWidget* activeWindow = QApplication::activeWindow(); if (activeWindow) { event.xclient.data.l[2] = activeWindow->internalWinId(); - } - else { + } else { event.xclient.data.l[2] = 0; } event.xclient.data.l[3] = 0; event.xclient.data.l[4] = 0; - XSendEvent(m_dpy, m_rootWindow, False, - SubstructureRedirectMask | SubstructureNotifyMask, - &event); + XSendEvent(m_dpy, m_rootWindow, False, SubstructureRedirectMask | SubstructureNotifyMask, &event); XFlush(m_dpy); return true; diff --git a/src/autotype/xcb/AutoTypeXCB.h b/src/autotype/xcb/AutoTypeXCB.h index 600e001a..f339c7c0 100644 --- a/src/autotype/xcb/AutoTypeXCB.h +++ b/src/autotype/xcb/AutoTypeXCB.h @@ -22,16 +22,16 @@ #include #include -#include #include #include +#include +#include #include #include -#include -#include "autotype/AutoTypePlatformPlugin.h" #include "autotype/AutoTypeAction.h" +#include "autotype/AutoTypePlatformPlugin.h" #define N_MOD_INDICES (Mod5MapIndex + 1) @@ -81,8 +81,8 @@ private: void AddModifier(KeySym keysym); void SendKeyEvent(unsigned keycode, bool press); void SendModifiers(unsigned int mask, bool press); - int GetKeycode(KeySym keysym, unsigned int *mask); - bool keysymModifiers(KeySym keysym, int keycode, unsigned int *mask); + int GetKeycode(KeySym keysym, unsigned int* mask); + bool keysymModifiers(KeySym keysym, int keycode, unsigned int* mask); static int MyErrorHandler(Display* my_dpy, XErrorEvent* event); diff --git a/src/browser/BrowserAccessControlDialog.cpp b/src/browser/BrowserAccessControlDialog.cpp old mode 100755 new mode 100644 index 7090a4d1..51abf2e9 --- a/src/browser/BrowserAccessControlDialog.cpp +++ b/src/browser/BrowserAccessControlDialog.cpp @@ -17,12 +17,12 @@ */ #include "BrowserAccessControlDialog.h" -#include "ui_BrowserAccessControlDialog.h" #include "core/Entry.h" +#include "ui_BrowserAccessControlDialog.h" -BrowserAccessControlDialog::BrowserAccessControlDialog(QWidget* parent) : - QDialog(parent), - ui(new Ui::BrowserAccessControlDialog()) +BrowserAccessControlDialog::BrowserAccessControlDialog(QWidget* parent) + : QDialog(parent) + , ui(new Ui::BrowserAccessControlDialog()) { this->setWindowFlags(windowFlags() | Qt::WindowStaysOnTopHint); @@ -38,7 +38,8 @@ BrowserAccessControlDialog::~BrowserAccessControlDialog() void BrowserAccessControlDialog::setUrl(const QString& url) { ui->label->setText(QString(tr("%1 has requested access to passwords for the following item(s).\n" - "Please select whether you want to allow access.")).arg(QUrl(url).host())); + "Please select whether you want to allow access.")) + .arg(QUrl(url).host())); } void BrowserAccessControlDialog::setItems(const QList& items) diff --git a/src/browser/BrowserAccessControlDialog.h b/src/browser/BrowserAccessControlDialog.h old mode 100755 new mode 100644 index d2a66ce0..9f24a1e1 --- a/src/browser/BrowserAccessControlDialog.h +++ b/src/browser/BrowserAccessControlDialog.h @@ -24,8 +24,9 @@ class Entry; -namespace Ui { -class BrowserAccessControlDialog; +namespace Ui +{ + class BrowserAccessControlDialog; } class BrowserAccessControlDialog : public QDialog diff --git a/src/browser/BrowserAction.cpp b/src/browser/BrowserAction.cpp old mode 100755 new mode 100644 index b15d8ed5..1a2fdf6e --- a/src/browser/BrowserAction.cpp +++ b/src/browser/BrowserAction.cpp @@ -16,21 +16,20 @@ * along with this program. If not, see . */ -#include -#include #include "BrowserAction.h" #include "BrowserSettings.h" +#include "config-keepassx.h" #include "sodium.h" #include "sodium/crypto_box.h" #include "sodium/randombytes.h" -#include "config-keepassx.h" +#include +#include -BrowserAction::BrowserAction(BrowserService& browserService) : - m_mutex(QMutex::Recursive), - m_browserService(browserService), - m_associated(false) +BrowserAction::BrowserAction(BrowserService& browserService) + : m_mutex(QMutex::Recursive) + , m_browserService(browserService) + , m_associated(false) { - } QJsonObject BrowserAction::readResponse(const QJsonObject& json) @@ -62,7 +61,6 @@ QJsonObject BrowserAction::readResponse(const QJsonObject& json) return handleAction(json); } - // Private functions /////////////////////// @@ -80,7 +78,7 @@ QJsonObject BrowserAction::handleAction(const QJsonObject& json) } else if (action.compare("associate", Qt::CaseSensitive) == 0) { return handleAssociate(json, action); } else if (action.compare("test-associate", Qt::CaseSensitive) == 0) { - return handleTestAssociate(json, action); + return handleTestAssociate(json, action); } else if (action.compare("get-logins", Qt::CaseSensitive) == 0) { return handleGetLogins(json, action); } else if (action.compare("generate-password", Qt::CaseSensitive) == 0) { @@ -270,7 +268,7 @@ QJsonObject BrowserAction::handleGeneratePassword(const QJsonObject& json, const QJsonArray arr; QJsonObject passwd; - passwd["login"] = QString::number(password.length() * 8); //bits; + passwd["login"] = QString::number(password.length() * 8); // bits; passwd["password"] = password; arr.append(passwd); @@ -386,31 +384,49 @@ QJsonObject BrowserAction::buildResponse(const QString& action, const QJsonObjec QString BrowserAction::getErrorMessage(const int errorCode) const { switch (errorCode) { - case ERROR_KEEPASS_DATABASE_NOT_OPENED: return QObject::tr("Database not opened"); - case ERROR_KEEPASS_DATABASE_HASH_NOT_RECEIVED: return QObject::tr("Database hash not available"); - case ERROR_KEEPASS_CLIENT_PUBLIC_KEY_NOT_RECEIVED: return QObject::tr("Client public key not received"); - case ERROR_KEEPASS_CANNOT_DECRYPT_MESSAGE: return QObject::tr("Cannot decrypt message"); - case ERROR_KEEPASS_TIMEOUT_OR_NOT_CONNECTED: return QObject::tr("Timeout or cannot connect to KeePassXC"); - case ERROR_KEEPASS_ACTION_CANCELLED_OR_DENIED: return QObject::tr("Action cancelled or denied"); - case ERROR_KEEPASS_CANNOT_ENCRYPT_MESSAGE: return QObject::tr("Cannot encrypt message or public key not found. Is Native Messaging enabled in KeePassXC?"); - case ERROR_KEEPASS_ASSOCIATION_FAILED: return QObject::tr("KeePassXC association failed, try again"); - case ERROR_KEEPASS_KEY_CHANGE_FAILED: return QObject::tr("Key change was not successful"); - case ERROR_KEEPASS_ENCRYPTION_KEY_UNRECOGNIZED: return QObject::tr("Encryption key is not recognized"); - case ERROR_KEEPASS_NO_SAVED_DATABASES_FOUND: return QObject::tr("No saved databases found"); - case ERROR_KEEPASS_INCORRECT_ACTION: return QObject::tr("Incorrect action"); - case ERROR_KEEPASS_EMPTY_MESSAGE_RECEIVED: return QObject::tr("Empty message received"); - case ERROR_KEEPASS_NO_URL_PROVIDED: return QObject::tr("No URL provided"); - case ERROR_KEEPASS_NO_LOGINS_FOUND: return QObject::tr("No logins found"); - default: return QObject::tr("Unknown error"); + case ERROR_KEEPASS_DATABASE_NOT_OPENED: + return QObject::tr("Database not opened"); + case ERROR_KEEPASS_DATABASE_HASH_NOT_RECEIVED: + return QObject::tr("Database hash not available"); + case ERROR_KEEPASS_CLIENT_PUBLIC_KEY_NOT_RECEIVED: + return QObject::tr("Client public key not received"); + case ERROR_KEEPASS_CANNOT_DECRYPT_MESSAGE: + return QObject::tr("Cannot decrypt message"); + case ERROR_KEEPASS_TIMEOUT_OR_NOT_CONNECTED: + return QObject::tr("Timeout or cannot connect to KeePassXC"); + case ERROR_KEEPASS_ACTION_CANCELLED_OR_DENIED: + return QObject::tr("Action cancelled or denied"); + case ERROR_KEEPASS_CANNOT_ENCRYPT_MESSAGE: + return QObject::tr("Cannot encrypt message or public key not found. Is Native Messaging enabled in KeePassXC?"); + case ERROR_KEEPASS_ASSOCIATION_FAILED: + return QObject::tr("KeePassXC association failed, try again"); + case ERROR_KEEPASS_KEY_CHANGE_FAILED: + return QObject::tr("Key change was not successful"); + case ERROR_KEEPASS_ENCRYPTION_KEY_UNRECOGNIZED: + return QObject::tr("Encryption key is not recognized"); + case ERROR_KEEPASS_NO_SAVED_DATABASES_FOUND: + return QObject::tr("No saved databases found"); + case ERROR_KEEPASS_INCORRECT_ACTION: + return QObject::tr("Incorrect action"); + case ERROR_KEEPASS_EMPTY_MESSAGE_RECEIVED: + return QObject::tr("Empty message received"); + case ERROR_KEEPASS_NO_URL_PROVIDED: + return QObject::tr("No URL provided"); + case ERROR_KEEPASS_NO_LOGINS_FOUND: + return QObject::tr("No logins found"); + default: + return QObject::tr("Unknown error"); } } QString BrowserAction::getDatabaseHash() { QMutexLocker locker(&m_mutex); - QByteArray hash = QCryptographicHash::hash( - (m_browserService.getDatabaseRootUuid() + m_browserService.getDatabaseRecycleBinUuid()).toUtf8(), - QCryptographicHash::Sha256).toHex(); + QByteArray hash = + QCryptographicHash::hash( + (m_browserService.getDatabaseRootUuid() + m_browserService.getDatabaseRecycleBinUuid()).toUtf8(), + QCryptographicHash::Sha256) + .toHex(); return QString(hash); } @@ -463,8 +479,8 @@ QString BrowserAction::encrypt(const QString plaintext, const QString nonce) } if (crypto_box_easy(e.data(), m.data(), m.size(), n.data(), ck.data(), sk.data()) == 0) { - QByteArray res = getQByteArray(e.data(), (crypto_box_MACBYTES + ma.length())); - return res.toBase64(); + QByteArray res = getQByteArray(e.data(), (crypto_box_MACBYTES + ma.length())); + return res.toBase64(); } return QString(); @@ -491,7 +507,7 @@ QByteArray BrowserAction::decrypt(const QString encrypted, const QString nonce) } if (crypto_box_open_easy(d.data(), m.data(), ma.length(), n.data(), ck.data(), sk.data()) == 0) { - return getQByteArray(d.data(), std::char_traits::length(reinterpret_cast(d.data()))); + return getQByteArray(d.data(), std::char_traits::length(reinterpret_cast(d.data()))); } return QByteArray(); diff --git a/src/browser/BrowserAction.h b/src/browser/BrowserAction.h old mode 100755 new mode 100644 index c4d59d3c..46fb9d04 --- a/src/browser/BrowserAction.h +++ b/src/browser/BrowserAction.h @@ -19,32 +19,33 @@ #ifndef BROWSERACTION_H #define BROWSERACTION_H -#include -#include +#include "BrowserService.h" #include #include -#include "BrowserService.h" +#include +#include class BrowserAction : public QObject { Q_OBJECT - enum { - ERROR_KEEPASS_DATABASE_NOT_OPENED = 1, - ERROR_KEEPASS_DATABASE_HASH_NOT_RECEIVED = 2, - ERROR_KEEPASS_CLIENT_PUBLIC_KEY_NOT_RECEIVED = 3, - ERROR_KEEPASS_CANNOT_DECRYPT_MESSAGE = 4, - ERROR_KEEPASS_TIMEOUT_OR_NOT_CONNECTED = 5, - ERROR_KEEPASS_ACTION_CANCELLED_OR_DENIED = 6, - ERROR_KEEPASS_CANNOT_ENCRYPT_MESSAGE = 7, - ERROR_KEEPASS_ASSOCIATION_FAILED = 8, - ERROR_KEEPASS_KEY_CHANGE_FAILED = 9, - ERROR_KEEPASS_ENCRYPTION_KEY_UNRECOGNIZED = 10, - ERROR_KEEPASS_NO_SAVED_DATABASES_FOUND = 11, - ERROR_KEEPASS_INCORRECT_ACTION = 12, - ERROR_KEEPASS_EMPTY_MESSAGE_RECEIVED = 13, - ERROR_KEEPASS_NO_URL_PROVIDED = 14, - ERROR_KEEPASS_NO_LOGINS_FOUND = 15 + enum + { + ERROR_KEEPASS_DATABASE_NOT_OPENED = 1, + ERROR_KEEPASS_DATABASE_HASH_NOT_RECEIVED = 2, + ERROR_KEEPASS_CLIENT_PUBLIC_KEY_NOT_RECEIVED = 3, + ERROR_KEEPASS_CANNOT_DECRYPT_MESSAGE = 4, + ERROR_KEEPASS_TIMEOUT_OR_NOT_CONNECTED = 5, + ERROR_KEEPASS_ACTION_CANCELLED_OR_DENIED = 6, + ERROR_KEEPASS_CANNOT_ENCRYPT_MESSAGE = 7, + ERROR_KEEPASS_ASSOCIATION_FAILED = 8, + ERROR_KEEPASS_KEY_CHANGE_FAILED = 9, + ERROR_KEEPASS_ENCRYPTION_KEY_UNRECOGNIZED = 10, + ERROR_KEEPASS_NO_SAVED_DATABASES_FOUND = 11, + ERROR_KEEPASS_INCORRECT_ACTION = 12, + ERROR_KEEPASS_EMPTY_MESSAGE_RECEIVED = 13, + ERROR_KEEPASS_NO_URL_PROVIDED = 14, + ERROR_KEEPASS_NO_LOGINS_FOUND = 15 }; public: @@ -54,8 +55,8 @@ public: QJsonObject readResponse(const QJsonObject& json); public slots: - void removeSharedEncryptionKeys(); - void removeStoredPermissions(); + void removeSharedEncryptionKeys(); + void removeStoredPermissions(); private: QJsonObject handleAction(const QJsonObject& json); @@ -71,28 +72,28 @@ private: QJsonObject buildMessage(const QString& nonce) const; QJsonObject buildResponse(const QString& action, const QJsonObject& message, const QString& nonce); QJsonObject getErrorReply(const QString& action, const int errorCode) const; - QString getErrorMessage(const int errorCode) const; - QString getDatabaseHash(); + QString getErrorMessage(const int errorCode) const; + QString getDatabaseHash(); - QString encryptMessage(const QJsonObject& message, const QString& nonce); + QString encryptMessage(const QJsonObject& message, const QString& nonce); QJsonObject decryptMessage(const QString& message, const QString& nonce, const QString& action = QString()); - QString encrypt(const QString plaintext, const QString nonce); - QByteArray decrypt(const QString encrypted, const QString nonce); + QString encrypt(const QString plaintext, const QString nonce); + QByteArray decrypt(const QString encrypted, const QString nonce); - QString getBase64FromKey(const uchar* array, const uint len); - QByteArray getQByteArray(const uchar* array, const uint len) const; + QString getBase64FromKey(const uchar* array, const uint len); + QByteArray getQByteArray(const uchar* array, const uint len) const; QJsonObject getJsonObject(const uchar* pArray, const uint len) const; QJsonObject getJsonObject(const QByteArray ba) const; - QByteArray base64Decode(const QString str); - QString incrementNonce(const QString& nonce); + QByteArray base64Decode(const QString str); + QString incrementNonce(const QString& nonce); private: - QMutex m_mutex; - BrowserService& m_browserService; - QString m_clientPublicKey; - QString m_publicKey; - QString m_secretKey; - bool m_associated; + QMutex m_mutex; + BrowserService& m_browserService; + QString m_clientPublicKey; + QString m_publicKey; + QString m_secretKey; + bool m_associated; }; #endif // BROWSERACTION_H diff --git a/src/browser/BrowserClients.cpp b/src/browser/BrowserClients.cpp old mode 100755 new mode 100644 index 9c47fdd4..c994ef1d --- a/src/browser/BrowserClients.cpp +++ b/src/browser/BrowserClients.cpp @@ -16,13 +16,13 @@ * along with this program. If not, see . */ -#include -#include #include "BrowserClients.h" +#include +#include -BrowserClients::BrowserClients(BrowserService& browserService) : - m_mutex(QMutex::Recursive), - m_browserService(browserService) +BrowserClients::BrowserClients(BrowserService& browserService) + : m_mutex(QMutex::Recursive) + , m_browserService(browserService) { m_clients.reserve(1000); } @@ -63,7 +63,7 @@ QString BrowserClients::getClientID(const QJsonObject& json) const BrowserClients::ClientPtr BrowserClients::getClient(const QString& clientID) { QMutexLocker locker(&m_mutex); - for (const auto &i : m_clients) { + for (const auto& i : m_clients) { if (i->clientID.compare(clientID, Qt::CaseSensitive) == 0) { return i; } diff --git a/src/browser/BrowserClients.h b/src/browser/BrowserClients.h old mode 100755 new mode 100644 index f9052e7d..b725154a --- a/src/browser/BrowserClients.h +++ b/src/browser/BrowserClients.h @@ -19,22 +19,27 @@ #ifndef BROWSERCLIENTS_H #define BROWSERCLIENTS_H -#include -#include -#include -#include -#include #include "BrowserAction.h" +#include +#include +#include +#include +#include class BrowserClients { - struct Client { - Client(const QString& id, QSharedPointer ba) : clientID(id), browserAction(ba) {} - QString clientID; - QSharedPointer browserAction; + struct Client + { + Client(const QString& id, QSharedPointer ba) + : clientID(id) + , browserAction(ba) + { + } + QString clientID; + QSharedPointer browserAction; }; - typedef QSharedPointer ClientPtr; + typedef QSharedPointer ClientPtr; public: BrowserClients(BrowserService& browserService); @@ -44,13 +49,13 @@ public: private: QJsonObject byteArrayToJson(const QByteArray& arr) const; - QString getClientID(const QJsonObject& json) const; - ClientPtr getClient(const QString& clientID); + QString getClientID(const QJsonObject& json) const; + ClientPtr getClient(const QString& clientID); private: - QMutex m_mutex; - QVector m_clients; - BrowserService& m_browserService; + QMutex m_mutex; + QVector m_clients; + BrowserService& m_browserService; }; #endif // BROWSERCLIENTS_H diff --git a/src/browser/BrowserEntryConfig.cpp b/src/browser/BrowserEntryConfig.cpp index 36d0c733..90d9f107 100644 --- a/src/browser/BrowserEntryConfig.cpp +++ b/src/browser/BrowserEntryConfig.cpp @@ -17,15 +17,14 @@ */ #include "BrowserEntryConfig.h" -#include #include "core/Entry.h" #include "core/EntryAttributes.h" +#include static const char KEEPASSBROWSER_NAME[] = "KeePassXC-Browser Settings"; - -BrowserEntryConfig::BrowserEntryConfig(QObject* parent) : - QObject(parent) +BrowserEntryConfig::BrowserEntryConfig(QObject* parent) + : QObject(parent) { } diff --git a/src/browser/BrowserEntryConfig.h b/src/browser/BrowserEntryConfig.h index 0ffaf985..3b808b7e 100644 --- a/src/browser/BrowserEntryConfig.h +++ b/src/browser/BrowserEntryConfig.h @@ -19,11 +19,11 @@ #ifndef BROWSERENTRYCONFIG_H #define BROWSERENTRYCONFIG_H +#include "Variant.h" #include +#include #include #include -#include -#include "Variant.h" class Entry; @@ -31,8 +31,8 @@ class BrowserEntryConfig : public QObject { Q_OBJECT Q_PROPERTY(QStringList Allow READ allowedHosts WRITE setAllowedHosts) - Q_PROPERTY(QStringList Deny READ deniedHosts WRITE setDeniedHosts ) - Q_PROPERTY(QString Realm READ realm WRITE setRealm ) + Q_PROPERTY(QStringList Deny READ deniedHosts WRITE setDeniedHosts) + Q_PROPERTY(QString Realm READ realm WRITE setRealm) public: BrowserEntryConfig(QObject* object = 0); @@ -54,7 +54,7 @@ private: QSet m_allowedHosts; QSet m_deniedHosts; - QString m_realm; + QString m_realm; }; #endif // BROWSERENTRYCONFIG_H diff --git a/src/browser/BrowserOptionDialog.cpp b/src/browser/BrowserOptionDialog.cpp old mode 100755 new mode 100644 index 1ad7e8b3..707d6032 --- a/src/browser/BrowserOptionDialog.cpp +++ b/src/browser/BrowserOptionDialog.cpp @@ -18,23 +18,24 @@ */ #include "BrowserOptionDialog.h" -#include "ui_BrowserOptionDialog.h" -#include "config-keepassx.h" #include "BrowserSettings.h" +#include "config-keepassx.h" #include "core/FilePath.h" +#include "ui_BrowserOptionDialog.h" -#include #include +#include -BrowserOptionDialog::BrowserOptionDialog(QWidget* parent) : - QWidget(parent), - m_ui(new Ui::BrowserOptionDialog()) +BrowserOptionDialog::BrowserOptionDialog(QWidget* parent) + : QWidget(parent) + , m_ui(new Ui::BrowserOptionDialog()) { m_ui->setupUi(this); connect(m_ui->removeSharedEncryptionKeys, SIGNAL(clicked()), this, SIGNAL(removeSharedEncryptionKeys())); connect(m_ui->removeStoredPermissions, SIGNAL(clicked()), this, SIGNAL(removeStoredPermissions())); - m_ui->warningWidget->showMessage(tr("Warning: The following options can be dangerous!"), MessageWidget::Warning); + m_ui->warningWidget->showMessage(tr("Warning: The following options can be dangerous!"), + MessageWidget::Warning); m_ui->warningWidget->setCloseButtonVisible(false); m_ui->warningWidget->setAutoHideTimeout(-1); @@ -95,7 +96,8 @@ void BrowserOptionDialog::loadSettings() m_ui->enableBrowserSupport->setChecked(false); m_ui->enableBrowserSupport->setEnabled(false); m_ui->browserGlobalWarningWidget->showMessage( - tr("We're sorry, but KeePassXC-Browser is not supported for Snap releases at the moment."), MessageWidget::Warning); + tr("We're sorry, but KeePassXC-Browser is not supported for Snap releases at the moment."), + MessageWidget::Warning); m_ui->browserGlobalWarningWidget->setCloseButtonVisible(false); m_ui->browserGlobalWarningWidget->setAutoHideTimeout(-1); #endif @@ -134,7 +136,8 @@ void BrowserOptionDialog::showProxyLocationFileDialog() #else QString fileTypeFilter(QString("%1 (*)").arg(tr("Executable Files"))); #endif - auto proxyLocation = QFileDialog::getOpenFileName(this, tr("Select custom proxy location"), + auto proxyLocation = QFileDialog::getOpenFileName(this, + tr("Select custom proxy location"), QFileInfo(QCoreApplication::applicationDirPath()).filePath(), fileTypeFilter); m_ui->customProxyLocation->setText(proxyLocation); diff --git a/src/browser/BrowserOptionDialog.h b/src/browser/BrowserOptionDialog.h old mode 100755 new mode 100644 index b562f6c1..a48504df --- a/src/browser/BrowserOptionDialog.h +++ b/src/browser/BrowserOptionDialog.h @@ -20,11 +20,12 @@ #ifndef BROWSEROPTIONDIALOG_H #define BROWSEROPTIONDIALOG_H -#include #include +#include -namespace Ui { -class BrowserOptionDialog; +namespace Ui +{ + class BrowserOptionDialog; } class BrowserOptionDialog : public QWidget diff --git a/src/browser/BrowserService.cpp b/src/browser/BrowserService.cpp index e59411ae..331bc6b7 100644 --- a/src/browser/BrowserService.cpp +++ b/src/browser/BrowserService.cpp @@ -17,41 +17,43 @@ * along with this program. If not, see . */ -#include -#include -#include -#include #include "BrowserService.h" -#include "BrowserSettings.h" -#include "BrowserEntryConfig.h" #include "BrowserAccessControlDialog.h" +#include "BrowserEntryConfig.h" +#include "BrowserSettings.h" #include "core/Database.h" -#include "core/Group.h" #include "core/EntrySearcher.h" +#include "core/Group.h" #include "core/Metadata.h" -#include "core/Uuid.h" #include "core/PasswordGenerator.h" +#include "core/Uuid.h" #include "gui/MainWindow.h" - +#include +#include +#include +#include // de887cc3-0363-43b8-974b-5911b8816224 -static const unsigned char KEEPASSXCBROWSER_UUID_DATA[] = { - 0xde, 0x88, 0x7c, 0xc3, 0x03, 0x63, 0x43, 0xb8, - 0x97, 0x4b, 0x59, 0x11, 0xb8, 0x81, 0x62, 0x24 -}; -static const Uuid KEEPASSXCBROWSER_UUID = Uuid(QByteArray::fromRawData(reinterpret_cast(KEEPASSXCBROWSER_UUID_DATA), sizeof(KEEPASSXCBROWSER_UUID_DATA))); +static const unsigned char KEEPASSXCBROWSER_UUID_DATA[] = + {0xde, 0x88, 0x7c, 0xc3, 0x03, 0x63, 0x43, 0xb8, 0x97, 0x4b, 0x59, 0x11, 0xb8, 0x81, 0x62, 0x24}; +static const Uuid KEEPASSXCBROWSER_UUID = + Uuid(QByteArray::fromRawData(reinterpret_cast(KEEPASSXCBROWSER_UUID_DATA), + sizeof(KEEPASSXCBROWSER_UUID_DATA))); static const char KEEPASSXCBROWSER_NAME[] = "KeePassXC-Browser Settings"; static const char ASSOCIATE_KEY_PREFIX[] = "Public Key: "; static const char KEEPASSXCBROWSER_GROUP_NAME[] = "KeePassXC-Browser Passwords"; -static int KEEPASSXCBROWSER_DEFAULT_ICON = 1; +static int KEEPASSXCBROWSER_DEFAULT_ICON = 1; -BrowserService::BrowserService(DatabaseTabWidget* parent) : - m_dbTabWidget(parent), - m_dialogActive(false) +BrowserService::BrowserService(DatabaseTabWidget* parent) + : m_dbTabWidget(parent) + , m_dialogActive(false) { connect(m_dbTabWidget, SIGNAL(databaseLocked(DatabaseWidget*)), this, SLOT(databaseLocked(DatabaseWidget*))); connect(m_dbTabWidget, SIGNAL(databaseUnlocked(DatabaseWidget*)), this, SLOT(databaseUnlocked(DatabaseWidget*))); - connect(m_dbTabWidget, SIGNAL(activateDatabaseChanged(DatabaseWidget*)), this, SLOT(activateDatabaseChanged(DatabaseWidget*))); + connect(m_dbTabWidget, + SIGNAL(activateDatabaseChanged(DatabaseWidget*)), + this, + SLOT(activateDatabaseChanged(DatabaseWidget*))); } bool BrowserService::isDatabaseOpened() const @@ -62,7 +64,6 @@ bool BrowserService::isDatabaseOpened() const } return dbWidget->currentMode() == DatabaseWidget::ViewMode || dbWidget->currentMode() == DatabaseWidget::EditMode; - } bool BrowserService::openDatabase(bool triggerUnlock) @@ -167,9 +168,8 @@ QString BrowserService::storeKey(const QString& key) QString id; if (thread() != QThread::currentThread()) { - QMetaObject::invokeMethod(this, "storeKey", Qt::BlockingQueuedConnection, - Q_RETURN_ARG(QString, id), - Q_ARG(const QString&, key)); + QMetaObject::invokeMethod( + this, "storeKey", Qt::BlockingQueuedConnection, Q_RETURN_ARG(QString, id), Q_ARG(const QString&, key)); return id; } @@ -185,8 +185,8 @@ QString BrowserService::storeKey(const QString& key) QInputDialog keyDialog; keyDialog.setWindowTitle(tr("KeePassXC: New key association request")); keyDialog.setLabelText(tr("You have received an association request for the above key.\n\n" - "If you would like to allow it access to your KeePassXC database,\n" - "give it a unique name to identify and accept it.")); + "If you would like to allow it access to your KeePassXC database,\n" + "give it a unique name to identify and accept it.")); keyDialog.setOkButtonText(tr("Save and allow access")); keyDialog.setWindowFlags(keyDialog.windowFlags() | Qt::WindowStaysOnTopHint); keyDialog.show(); @@ -202,7 +202,8 @@ QString BrowserService::storeKey(const QString& key) contains = config->attributes()->contains(QLatin1String(ASSOCIATE_KEY_PREFIX) + id); if (contains) { - dialogResult = QMessageBox::warning(nullptr, tr("KeePassXC: Overwrite existing key?"), + dialogResult = QMessageBox::warning(nullptr, + tr("KeePassXC: Overwrite existing key?"), tr("A shared encryption key with the name \"%1\" " "already exists.\nDo you want to overwrite it?") .arg(id), @@ -224,11 +225,16 @@ QString BrowserService::getKey(const QString& id) return config->attributes()->value(QLatin1String(ASSOCIATE_KEY_PREFIX) + id); } -QJsonArray BrowserService::findMatchingEntries(const QString& id, const QString& url, const QString& submitUrl, const QString& realm) +QJsonArray BrowserService::findMatchingEntries(const QString& id, + const QString& url, + const QString& submitUrl, + const QString& realm) { QJsonArray result; if (thread() != QThread::currentThread()) { - QMetaObject::invokeMethod(this, "findMatchingEntries", Qt::BlockingQueuedConnection, + QMetaObject::invokeMethod(this, + "findMatchingEntries", + Qt::BlockingQueuedConnection, Q_RETURN_ARG(QJsonArray, result), Q_ARG(const QString&, id), Q_ARG(const QString&, url), @@ -283,7 +289,12 @@ QJsonArray BrowserService::findMatchingEntries(const QString& id, const QString& return result; } -void BrowserService::addEntry(const QString&, const QString& login, const QString& password, const QString& url, const QString& submitUrl, const QString& realm) +void BrowserService::addEntry(const QString&, + const QString& login, + const QString& password, + const QString& url, + const QString& submitUrl, + const QString& realm) { Group* group = findCreateAddEntryGroup(); if (!group) { @@ -313,10 +324,16 @@ void BrowserService::addEntry(const QString&, const QString& login, const QStrin config.save(entry); } -void BrowserService::updateEntry(const QString& id, const QString& uuid, const QString& login, const QString& password, const QString& url) +void BrowserService::updateEntry(const QString& id, + const QString& uuid, + const QString& login, + const QString& password, + const QString& url) { if (thread() != QThread::currentThread()) { - QMetaObject::invokeMethod(this, "updateEntry", Qt::BlockingQueuedConnection, + QMetaObject::invokeMethod(this, + "updateEntry", + Qt::BlockingQueuedConnection, Q_ARG(const QString&, id), Q_ARG(const QString&, uuid), Q_ARG(const QString&, login), @@ -339,13 +356,15 @@ void BrowserService::updateEntry(const QString& id, const QString& uuid, const Q return; } - if (username.compare(login, Qt::CaseSensitive) != 0 || entry->password().compare(password, Qt::CaseSensitive) != 0) { + if (username.compare(login, Qt::CaseSensitive) != 0 + || entry->password().compare(password, Qt::CaseSensitive) != 0) { QMessageBox::StandardButton dialogResult = QMessageBox::No; if (!BrowserSettings::alwaysAllowUpdate()) { - dialogResult = QMessageBox::warning(0, tr("KeePassXC: Update Entry"), - tr("Do you want to update the information in %1 - %2?") - .arg(QUrl(url).host()).arg(username), - QMessageBox::Yes|QMessageBox::No); + dialogResult = QMessageBox::warning( + 0, + tr("KeePassXC: Update Entry"), + tr("Do you want to update the information in %1 - %2?").arg(QUrl(url).host()).arg(username), + QMessageBox::Yes | QMessageBox::No); } if (BrowserSettings::alwaysAllowUpdate() || dialogResult == QMessageBox::Yes) { @@ -370,11 +389,10 @@ QList BrowserService::searchEntries(Database* db, const QString& hostnam QString url = entry->url(); // Filter to match hostname in Title and Url fields - if ((!title.isEmpty() && hostname.contains(title)) - || (!url.isEmpty() && hostname.contains(url)) + if ((!title.isEmpty() && hostname.contains(title)) || (!url.isEmpty() && hostname.contains(url)) || (matchUrlScheme(title) && hostname.endsWith(QUrl(title).host())) - || (matchUrlScheme(url) && hostname.endsWith(QUrl(url).host())) ) { - entries.append(entry); + || (matchUrlScheme(url) && hostname.endsWith(QUrl(url).host()))) { + entries.append(entry); } } @@ -413,7 +431,8 @@ QList BrowserService::searchEntries(const QString& text) void BrowserService::removeSharedEncryptionKeys() { if (!isDatabaseOpened()) { - QMessageBox::critical(0, tr("KeePassXC: Database locked!"), + QMessageBox::critical(0, + tr("KeePassXC: Database locked!"), tr("The active database is locked!\n" "Please unlock the selected database or choose another one which is unlocked."), QMessageBox::Ok); @@ -422,7 +441,8 @@ void BrowserService::removeSharedEncryptionKeys() Entry* entry = getConfigEntry(); if (!entry) { - QMessageBox::information(0, tr("KeePassXC: Settings not available!"), + QMessageBox::information(0, + tr("KeePassXC: Settings not available!"), tr("The active database does not contain a settings entry."), QMessageBox::Ok); return; @@ -436,7 +456,8 @@ void BrowserService::removeSharedEncryptionKeys() } if (keysToRemove.isEmpty()) { - QMessageBox::information(0, tr("KeePassXC: No keys found"), + QMessageBox::information(0, + tr("KeePassXC: No keys found"), tr("No shared encryption keys found in KeePassXC settings."), QMessageBox::Ok); return; @@ -449,16 +470,17 @@ void BrowserService::removeSharedEncryptionKeys() entry->endUpdate(); const int count = keysToRemove.count(); - QMessageBox::information(0, tr("KeePassXC: Removed keys from database"), + QMessageBox::information(0, + tr("KeePassXC: Removed keys from database"), tr("Successfully removed %n encryption key(s) from KeePassXC settings.", "", count), QMessageBox::Ok); - } void BrowserService::removeStoredPermissions() { if (!isDatabaseOpened()) { - QMessageBox::critical(0, tr("KeePassXC: Database locked!"), + QMessageBox::critical(0, + tr("KeePassXC: Database locked!"), tr("The active database is locked!\n" "Please unlock the selected database or choose another one which is unlocked."), QMessageBox::Ok); @@ -492,11 +514,13 @@ void BrowserService::removeStoredPermissions() progress.reset(); if (counter > 0) { - QMessageBox::information(0, tr("KeePassXC: Removed permissions"), + QMessageBox::information(0, + tr("KeePassXC: Removed permissions"), tr("Successfully removed permissions from %n entry(s).", "", counter), QMessageBox::Ok); } else { - QMessageBox::information(0, tr("KeePassXC: No entry with permissions found!"), + QMessageBox::information(0, + tr("KeePassXC: No entry with permissions found!"), tr("The active database does not contain an entry with permissions."), QMessageBox::Ok); } @@ -510,7 +534,8 @@ QList BrowserService::sortEntries(QList& pwEntries, const QStrin } const QString submitUrl = url.toString(QUrl::StripTrailingSlash); - const QString baseSubmitUrl = url.toString(QUrl::StripTrailingSlash | QUrl::RemovePath | QUrl::RemoveQuery | QUrl::RemoveFragment); + const QString baseSubmitUrl = + url.toString(QUrl::StripTrailingSlash | QUrl::RemovePath | QUrl::RemoveQuery | QUrl::RemoveFragment); QMultiMap priorities; for (const Entry* entry : pwEntries) { @@ -529,7 +554,11 @@ QList BrowserService::sortEntries(QList& pwEntries, const QStrin return pwEntries; } -bool BrowserService::confirmEntries(QList& pwEntriesToConfirm, const QString& url, const QString& host, const QString& submitHost, const QString& realm) +bool BrowserService::confirmEntries(QList& pwEntriesToConfirm, + const QString& url, + const QString& host, + const QString& submitHost, + const QString& realm) { if (pwEntriesToConfirm.isEmpty() || m_dialogActive) { return false; @@ -593,7 +622,8 @@ QJsonObject BrowserService::prepareEntry(const Entry* entry) return res; } -BrowserService::Access BrowserService::checkAccess(const Entry* entry, const QString& host, const QString& submitHost, const QString& realm) +BrowserService::Access +BrowserService::checkAccess(const Entry* entry, const QString& host, const QString& submitHost, const QString& realm) { BrowserEntryConfig config; if (!config.load(entry)) { @@ -623,7 +653,8 @@ Group* BrowserService::findCreateAddEntryGroup() return nullptr; } - const QString groupName = QLatin1String(KEEPASSXCBROWSER_GROUP_NAME); //TODO: setting to decide where new keys are created + const QString groupName = + QLatin1String(KEEPASSXCBROWSER_GROUP_NAME); // TODO: setting to decide where new keys are created for (const Group* g : rootGroup->groupsRecursive(true)) { if (g->name() == groupName) { @@ -639,14 +670,18 @@ Group* BrowserService::findCreateAddEntryGroup() return group; } -int BrowserService::sortPriority(const Entry* entry, const QString& host, const QString& submitUrl, const QString& baseSubmitUrl) const +int BrowserService::sortPriority(const Entry* entry, + const QString& host, + const QString& submitUrl, + const QString& baseSubmitUrl) const { QUrl url(entry->url()); if (url.scheme().isEmpty()) { url.setScheme("http"); } const QString entryURL = url.toString(QUrl::StripTrailingSlash); - const QString baseEntryURL = url.toString(QUrl::StripTrailingSlash | QUrl::RemovePath | QUrl::RemoveQuery | QUrl::RemoveFragment); + const QString baseEntryURL = + url.toString(QUrl::StripTrailingSlash | QUrl::RemovePath | QUrl::RemoveQuery | QUrl::RemoveFragment); if (submitUrl == entryURL) { return 100; diff --git a/src/browser/BrowserService.h b/src/browser/BrowserService.h index 5a96e1ec..127c4f6a 100644 --- a/src/browser/BrowserService.h +++ b/src/browser/BrowserService.h @@ -20,63 +20,86 @@ #ifndef BROWSERSERVICE_H #define BROWSERSERVICE_H -#include -#include -#include "gui/DatabaseTabWidget.h" #include "core/Entry.h" +#include "gui/DatabaseTabWidget.h" +#include +#include -enum { max_length = 16*1024 }; +enum +{ + max_length = 16 * 1024 +}; class BrowserService : public QObject { Q_OBJECT public: - explicit BrowserService(DatabaseTabWidget* parent); + explicit BrowserService(DatabaseTabWidget* parent); - bool isDatabaseOpened() const; - bool openDatabase(bool triggerUnlock); - QString getDatabaseRootUuid(); - QString getDatabaseRecycleBinUuid(); - Entry* getConfigEntry(bool create = false); - QString getKey(const QString& id); - void addEntry(const QString& id, const QString& login, const QString& password, const QString& url, const QString& submitUrl, const QString& realm); - QList searchEntries(Database* db, const QString& hostname); - QList searchEntries(const QString& text); - void removeSharedEncryptionKeys(); - void removeStoredPermissions(); + bool isDatabaseOpened() const; + bool openDatabase(bool triggerUnlock); + QString getDatabaseRootUuid(); + QString getDatabaseRecycleBinUuid(); + Entry* getConfigEntry(bool create = false); + QString getKey(const QString& id); + void addEntry(const QString& id, + const QString& login, + const QString& password, + const QString& url, + const QString& submitUrl, + const QString& realm); + QList searchEntries(Database* db, const QString& hostname); + QList searchEntries(const QString& text); + void removeSharedEncryptionKeys(); + void removeStoredPermissions(); public slots: - QJsonArray findMatchingEntries(const QString& id, const QString& url, const QString& submitUrl, const QString& realm); - QString storeKey(const QString& key); - void updateEntry(const QString& id, const QString& uuid, const QString& login, const QString& password, const QString& url); - void databaseLocked(DatabaseWidget* dbWidget); - void databaseUnlocked(DatabaseWidget* dbWidget); - void activateDatabaseChanged(DatabaseWidget* dbWidget); - void lockDatabase(); + QJsonArray + findMatchingEntries(const QString& id, const QString& url, const QString& submitUrl, const QString& realm); + QString storeKey(const QString& key); + void updateEntry(const QString& id, + const QString& uuid, + const QString& login, + const QString& password, + const QString& url); + void databaseLocked(DatabaseWidget* dbWidget); + void databaseUnlocked(DatabaseWidget* dbWidget); + void activateDatabaseChanged(DatabaseWidget* dbWidget); + void lockDatabase(); signals: - void databaseLocked(); - void databaseUnlocked(); - void databaseChanged(); + void databaseLocked(); + void databaseUnlocked(); + void databaseChanged(); private: - enum Access { Denied, Unknown, Allowed}; + enum Access + { + Denied, + Unknown, + Allowed + }; private: - QList sortEntries(QList& pwEntries, const QString& host, const QString& submitUrl); - bool confirmEntries(QList& pwEntriesToConfirm, const QString& url, const QString& host, const QString& submitHost, const QString& realm); - QJsonObject prepareEntry(const Entry* entry); - Access checkAccess(const Entry* entry, const QString& host, const QString& submitHost, const QString& realm); - Group* findCreateAddEntryGroup(); - int sortPriority(const Entry* entry, const QString &host, const QString& submitUrl, const QString& baseSubmitUrl) const; - bool matchUrlScheme(const QString& url); - bool removeFirstDomain(QString& hostname); - Database* getDatabase(); + QList sortEntries(QList& pwEntries, const QString& host, const QString& submitUrl); + bool confirmEntries(QList& pwEntriesToConfirm, + const QString& url, + const QString& host, + const QString& submitHost, + const QString& realm); + QJsonObject prepareEntry(const Entry* entry); + Access checkAccess(const Entry* entry, const QString& host, const QString& submitHost, const QString& realm); + Group* findCreateAddEntryGroup(); + int + sortPriority(const Entry* entry, const QString& host, const QString& submitUrl, const QString& baseSubmitUrl) const; + bool matchUrlScheme(const QString& url); + bool removeFirstDomain(QString& hostname); + Database* getDatabase(); private: - DatabaseTabWidget* const m_dbTabWidget; - bool m_dialogActive; + DatabaseTabWidget* const m_dbTabWidget; + bool m_dialogActive; }; #endif // BROWSERSERVICE_H diff --git a/src/browser/BrowserSettings.cpp b/src/browser/BrowserSettings.cpp old mode 100755 new mode 100644 index ecaf8e23..4a75797f --- a/src/browser/BrowserSettings.cpp +++ b/src/browser/BrowserSettings.cpp @@ -177,36 +177,48 @@ void BrowserSettings::setUpdateBinaryPath(bool enabled) config()->set("Browser/UpdateBinaryPath", enabled); } -bool BrowserSettings::chromeSupport() { +bool BrowserSettings::chromeSupport() +{ return m_hostInstaller.checkIfInstalled(HostInstaller::SupportedBrowsers::CHROME); } -void BrowserSettings::setChromeSupport(bool enabled) { - m_hostInstaller.installBrowser(HostInstaller::SupportedBrowsers::CHROME, enabled, supportBrowserProxy(), customProxyLocation()); +void BrowserSettings::setChromeSupport(bool enabled) +{ + m_hostInstaller.installBrowser( + HostInstaller::SupportedBrowsers::CHROME, enabled, supportBrowserProxy(), customProxyLocation()); } -bool BrowserSettings::chromiumSupport() { +bool BrowserSettings::chromiumSupport() +{ return m_hostInstaller.checkIfInstalled(HostInstaller::SupportedBrowsers::CHROMIUM); } -void BrowserSettings::setChromiumSupport(bool enabled) { - m_hostInstaller.installBrowser(HostInstaller::SupportedBrowsers::CHROMIUM, enabled, supportBrowserProxy(), customProxyLocation()); +void BrowserSettings::setChromiumSupport(bool enabled) +{ + m_hostInstaller.installBrowser( + HostInstaller::SupportedBrowsers::CHROMIUM, enabled, supportBrowserProxy(), customProxyLocation()); } -bool BrowserSettings::firefoxSupport() { +bool BrowserSettings::firefoxSupport() +{ return m_hostInstaller.checkIfInstalled(HostInstaller::SupportedBrowsers::FIREFOX); } -void BrowserSettings::setFirefoxSupport(bool enabled) { - m_hostInstaller.installBrowser(HostInstaller::SupportedBrowsers::FIREFOX, enabled, supportBrowserProxy(), customProxyLocation()); +void BrowserSettings::setFirefoxSupport(bool enabled) +{ + m_hostInstaller.installBrowser( + HostInstaller::SupportedBrowsers::FIREFOX, enabled, supportBrowserProxy(), customProxyLocation()); } -bool BrowserSettings::vivaldiSupport() { +bool BrowserSettings::vivaldiSupport() +{ return m_hostInstaller.checkIfInstalled(HostInstaller::SupportedBrowsers::VIVALDI); } -void BrowserSettings::setVivaldiSupport(bool enabled) { - m_hostInstaller.installBrowser(HostInstaller::SupportedBrowsers::VIVALDI, enabled, supportBrowserProxy(), customProxyLocation()); +void BrowserSettings::setVivaldiSupport(bool enabled) +{ + m_hostInstaller.installBrowser( + HostInstaller::SupportedBrowsers::VIVALDI, enabled, supportBrowserProxy(), customProxyLocation()); } bool BrowserSettings::passwordUseNumbers() diff --git a/src/browser/BrowserSettings.h b/src/browser/BrowserSettings.h old mode 100755 new mode 100644 index eb59fa5a..ac4a8449 --- a/src/browser/BrowserSettings.h +++ b/src/browser/BrowserSettings.h @@ -20,9 +20,9 @@ #ifndef BROWSERSETTINGS_H #define BROWSERSETTINGS_H -#include "core/PasswordGenerator.h" -#include "core/PassphraseGenerator.h" #include "HostInstaller.h" +#include "core/PassphraseGenerator.h" +#include "core/PasswordGenerator.h" class BrowserSettings { @@ -30,9 +30,9 @@ public: static bool isEnabled(); static void setEnabled(bool enabled); - static bool showNotification(); //TODO!! + static bool showNotification(); // TODO!! static void setShowNotification(bool showNotification); - static bool bestMatchOnly(); //TODO!! + static bool bestMatchOnly(); // TODO!! static void setBestMatchOnly(bool bestMatchOnly); static bool unlockDatabase(); static void setUnlockDatabase(bool unlockDatabase); @@ -46,7 +46,7 @@ public: static void setAlwaysAllowAccess(bool alwaysAllowAccess); static bool alwaysAllowUpdate(); static void setAlwaysAllowUpdate(bool alwaysAllowUpdate); - static bool searchInAllDatabases();//TODO!! + static bool searchInAllDatabases(); // TODO!! static void setSearchInAllDatabases(bool searchInAllDatabases); static bool supportKphFields(); static void setSupportKphFields(bool supportKphFields); @@ -88,7 +88,7 @@ public: static void setPasswordEveryGroup(bool everyGroup); static bool passwordExcludeAlike(); static void setPasswordExcludeAlike(bool excludeAlike); - static int passwordLength(); + static int passwordLength(); static void setPasswordLength(int length); static PasswordGenerator::CharClasses passwordCharClasses(); static PasswordGenerator::GeneratorFlags passwordGeneratorFlags(); diff --git a/src/browser/HostInstaller.cpp b/src/browser/HostInstaller.cpp index 9b27ab1c..95d202a2 100644 --- a/src/browser/HostInstaller.cpp +++ b/src/browser/HostInstaller.cpp @@ -18,43 +18,45 @@ #include "HostInstaller.h" #include "config-keepassx.h" +#include #include #include -#include #include #include -#include -#include #include +#include +#include const QString HostInstaller::HOST_NAME = "org.keepassxc.keepassxc_browser"; const QStringList HostInstaller::ALLOWED_ORIGINS = QStringList() - << "chrome-extension://iopaggbpplllidnfmcghoonnokmjoicf/" - << "chrome-extension://oboonakemofpalcgghocfoadofidjkkk/"; + << "chrome-extension://iopaggbpplllidnfmcghoonnokmjoicf/" + << "chrome-extension://oboonakemofpalcgghocfoadofidjkkk/"; -const QStringList HostInstaller::ALLOWED_EXTENSIONS = QStringList() - << "keepassxc-browser@keepassxc.org"; +const QStringList HostInstaller::ALLOWED_EXTENSIONS = QStringList() << "keepassxc-browser@keepassxc.org"; #if defined(Q_OS_OSX) - const QString HostInstaller::TARGET_DIR_CHROME = "/Library/Application Support/Google/Chrome/NativeMessagingHosts"; - const QString HostInstaller::TARGET_DIR_CHROMIUM = "/Library/Application Support/Chromium/NativeMessagingHosts"; - const QString HostInstaller::TARGET_DIR_FIREFOX = "/Library/Application Support/Mozilla/NativeMessagingHosts"; - const QString HostInstaller::TARGET_DIR_VIVALDI = "/Library/Application Support/Vivaldi/NativeMessagingHosts"; +const QString HostInstaller::TARGET_DIR_CHROME = "/Library/Application Support/Google/Chrome/NativeMessagingHosts"; +const QString HostInstaller::TARGET_DIR_CHROMIUM = "/Library/Application Support/Chromium/NativeMessagingHosts"; +const QString HostInstaller::TARGET_DIR_FIREFOX = "/Library/Application Support/Mozilla/NativeMessagingHosts"; +const QString HostInstaller::TARGET_DIR_VIVALDI = "/Library/Application Support/Vivaldi/NativeMessagingHosts"; #elif defined(Q_OS_LINUX) - const QString HostInstaller::TARGET_DIR_CHROME = "/.config/google-chrome/NativeMessagingHosts"; - const QString HostInstaller::TARGET_DIR_CHROMIUM = "/.config/chromium/NativeMessagingHosts"; - const QString HostInstaller::TARGET_DIR_FIREFOX = "/.mozilla/native-messaging-hosts"; - const QString HostInstaller::TARGET_DIR_VIVALDI = "/.config/vivaldi/NativeMessagingHosts"; +const QString HostInstaller::TARGET_DIR_CHROME = "/.config/google-chrome/NativeMessagingHosts"; +const QString HostInstaller::TARGET_DIR_CHROMIUM = "/.config/chromium/NativeMessagingHosts"; +const QString HostInstaller::TARGET_DIR_FIREFOX = "/.mozilla/native-messaging-hosts"; +const QString HostInstaller::TARGET_DIR_VIVALDI = "/.config/vivaldi/NativeMessagingHosts"; #elif defined(Q_OS_WIN) - const QString HostInstaller::TARGET_DIR_CHROME = "HKEY_CURRENT_USER\\Software\\Google\\Chrome\\NativeMessagingHosts\\" + HostInstaller::HOST_NAME; - const QString HostInstaller::TARGET_DIR_CHROMIUM = "HKEY_CURRENT_USER\\Software\\Chromium\\NativeMessagingHosts\\" + HostInstaller::HOST_NAME; - const QString HostInstaller::TARGET_DIR_FIREFOX = "HKEY_CURRENT_USER\\Software\\Mozilla\\NativeMessagingHosts\\" + HostInstaller::HOST_NAME; - const QString HostInstaller::TARGET_DIR_VIVALDI = "HKEY_CURRENT_USER\\Software\\Vivaldi\\NativeMessagingHosts\\" + HostInstaller::HOST_NAME; +const QString HostInstaller::TARGET_DIR_CHROME = + "HKEY_CURRENT_USER\\Software\\Google\\Chrome\\NativeMessagingHosts\\" + HostInstaller::HOST_NAME; +const QString HostInstaller::TARGET_DIR_CHROMIUM = + "HKEY_CURRENT_USER\\Software\\Chromium\\NativeMessagingHosts\\" + HostInstaller::HOST_NAME; +const QString HostInstaller::TARGET_DIR_FIREFOX = + "HKEY_CURRENT_USER\\Software\\Mozilla\\NativeMessagingHosts\\" + HostInstaller::HOST_NAME; +const QString HostInstaller::TARGET_DIR_VIVALDI = + "HKEY_CURRENT_USER\\Software\\Vivaldi\\NativeMessagingHosts\\" + HostInstaller::HOST_NAME; #endif HostInstaller::HostInstaller() { - } bool HostInstaller::checkIfInstalled(SupportedBrowsers browser) @@ -68,34 +70,39 @@ bool HostInstaller::checkIfInstalled(SupportedBrowsers browser) #endif } -void HostInstaller::installBrowser(SupportedBrowsers browser, const bool& enabled, const bool& proxy, const QString& location) +void HostInstaller::installBrowser(SupportedBrowsers browser, + const bool& enabled, + const bool& proxy, + const QString& location) { if (enabled) { - #ifdef Q_OS_WIN - // Create a registry key - QSettings settings(getTargetPath(browser), QSettings::NativeFormat); - if (!registryEntryFound(settings)) { - settings.setValue("Default", getPath(browser)); - } - #endif - // Always create the script file - QJsonObject script = constructFile(browser, proxy, location); - if (!saveFile(browser, script)) { - QMessageBox::critical(0, tr("KeePassXC: Cannot save file!"), - tr("Cannot save the native messaging script file."), QMessageBox::Ok); - } - } else { - // Remove the script file - QString fileName = getPath(browser); - QFile::remove(fileName); - #ifdef Q_OS_WIN - // Remove the registry entry - QSettings settings(getTargetPath(browser), QSettings::NativeFormat); - if (registryEntryFound(settings)) { - settings.remove("Default"); - } - #endif - } +#ifdef Q_OS_WIN + // Create a registry key + QSettings settings(getTargetPath(browser), QSettings::NativeFormat); + if (!registryEntryFound(settings)) { + settings.setValue("Default", getPath(browser)); + } +#endif + // Always create the script file + QJsonObject script = constructFile(browser, proxy, location); + if (!saveFile(browser, script)) { + QMessageBox::critical(0, + tr("KeePassXC: Cannot save file!"), + tr("Cannot save the native messaging script file."), + QMessageBox::Ok); + } + } else { + // Remove the script file + QString fileName = getPath(browser); + QFile::remove(fileName); +#ifdef Q_OS_WIN + // Remove the registry entry + QSettings settings(getTargetPath(browser), QSettings::NativeFormat); + if (registryEntryFound(settings)) { + settings.remove("Default"); + } +#endif + } } void HostInstaller::updateBinaryPaths(const bool& proxy, const QString& location) @@ -110,22 +117,32 @@ void HostInstaller::updateBinaryPaths(const bool& proxy, const QString& location QString HostInstaller::getTargetPath(SupportedBrowsers browser) const { switch (browser) { - case SupportedBrowsers::CHROME: return HostInstaller::TARGET_DIR_CHROME; - case SupportedBrowsers::CHROMIUM: return HostInstaller::TARGET_DIR_CHROMIUM; - case SupportedBrowsers::FIREFOX: return HostInstaller::TARGET_DIR_FIREFOX; - case SupportedBrowsers::VIVALDI: return HostInstaller::TARGET_DIR_VIVALDI; - default: return QString(); + case SupportedBrowsers::CHROME: + return HostInstaller::TARGET_DIR_CHROME; + case SupportedBrowsers::CHROMIUM: + return HostInstaller::TARGET_DIR_CHROMIUM; + case SupportedBrowsers::FIREFOX: + return HostInstaller::TARGET_DIR_FIREFOX; + case SupportedBrowsers::VIVALDI: + return HostInstaller::TARGET_DIR_VIVALDI; + default: + return QString(); } } QString HostInstaller::getBrowserName(SupportedBrowsers browser) const { switch (browser) { - case SupportedBrowsers::CHROME: return "chrome"; - case SupportedBrowsers::CHROMIUM: return "chromium"; - case SupportedBrowsers::FIREFOX: return "firefox"; - case SupportedBrowsers::VIVALDI: return "vivaldi"; - default: return QString(); + case SupportedBrowsers::CHROME: + return "chrome"; + case SupportedBrowsers::CHROMIUM: + return "chromium"; + case SupportedBrowsers::FIREFOX: + return "firefox"; + case SupportedBrowsers::VIVALDI: + return "vivaldi"; + default: + return QString(); } } @@ -142,7 +159,7 @@ QString HostInstaller::getPath(SupportedBrowsers browser) const } QString winPath = QString("%1/%2_%3.json").arg(userPath, HostInstaller::HOST_NAME, getBrowserName(browser)); - winPath.replace("/","\\"); + winPath.replace("/", "\\"); return winPath; #else QString path = getTargetPath(browser); @@ -184,16 +201,16 @@ QJsonObject HostInstaller::constructFile(SupportedBrowsers browser, const bool& path = QFileInfo(QCoreApplication::applicationFilePath()).absoluteFilePath(); } #ifdef Q_OS_WIN - path.replace("/","\\"); + path.replace("/", "\\"); #endif -#endif // #ifdef KEEPASSXC_DIST_APPIMAGE +#endif // #ifdef KEEPASSXC_DIST_APPIMAGE QJsonObject script; - script["name"] = HostInstaller::HOST_NAME; - script["description"] = "KeePassXC integration with native messaging support"; - script["path"] = path; - script["type"] = "stdio"; + script["name"] = HostInstaller::HOST_NAME; + script["description"] = "KeePassXC integration with native messaging support"; + script["path"] = path; + script["type"] = "stdio"; QJsonArray arr; if (browser == SupportedBrowsers::FIREFOX) { diff --git a/src/browser/HostInstaller.h b/src/browser/HostInstaller.h index c3fc8562..2fac0609 100644 --- a/src/browser/HostInstaller.h +++ b/src/browser/HostInstaller.h @@ -19,8 +19,8 @@ #ifndef HOSTINSTALLER_H #define HOSTINSTALLER_H -#include #include +#include #include class HostInstaller : public QObject @@ -28,27 +28,31 @@ class HostInstaller : public QObject Q_OBJECT public: - enum SupportedBrowsers : int { - CHROME = 0, - CHROMIUM = 1, - FIREFOX = 2, - VIVALDI = 3 + enum SupportedBrowsers : int + { + CHROME = 0, + CHROMIUM = 1, + FIREFOX = 2, + VIVALDI = 3 }; public: HostInstaller(); bool checkIfInstalled(SupportedBrowsers browser); - void installBrowser(SupportedBrowsers browser, const bool& enabled, const bool& proxy = false, const QString& location = ""); + void installBrowser(SupportedBrowsers browser, + const bool& enabled, + const bool& proxy = false, + const QString& location = ""); void updateBinaryPaths(const bool& proxy, const QString& location = ""); private: - QString getTargetPath(SupportedBrowsers browser) const; - QString getBrowserName(SupportedBrowsers browser) const; - QString getPath(SupportedBrowsers browser) const; - QString getInstallDir(SupportedBrowsers browser) const; + QString getTargetPath(SupportedBrowsers browser) const; + QString getBrowserName(SupportedBrowsers browser) const; + QString getPath(SupportedBrowsers browser) const; + QString getInstallDir(SupportedBrowsers browser) const; QJsonObject constructFile(SupportedBrowsers browser, const bool& proxy, const QString& location); - bool registryEntryFound(const QSettings& settings); - bool saveFile(SupportedBrowsers browser, const QJsonObject& script); + bool registryEntryFound(const QSettings& settings); + bool saveFile(SupportedBrowsers browser, const QJsonObject& script); private: static const QString HOST_NAME; diff --git a/src/browser/NativeMessagingBase.cpp b/src/browser/NativeMessagingBase.cpp index f61a3604..64a6df48 100644 --- a/src/browser/NativeMessagingBase.cpp +++ b/src/browser/NativeMessagingBase.cpp @@ -20,9 +20,9 @@ #include #if defined(Q_OS_UNIX) && !defined(Q_OS_LINUX) -#include #include #include +#include #include #endif @@ -51,7 +51,7 @@ void NativeMessagingBase::newNativeMessage() { #if defined(Q_OS_UNIX) && !defined(Q_OS_LINUX) struct kevent ev[1]; - struct timespec ts = { 5, 0 }; + struct timespec ts = {5, 0}; int fd = kqueue(); if (fd == -1) { @@ -123,7 +123,8 @@ void NativeMessagingBase::sendReply(const QString& reply) if (!reply.isEmpty()) { QByteArray bytes = reply.toUtf8(); uint len = bytes.size(); - std::cout << char(((len>>0) & 0xFF)) << char(((len>>8) & 0xFF)) << char(((len>>16) & 0xFF)) << char(((len>>24) & 0xFF)); + std::cout << char(((len >> 0) & 0xFF)) << char(((len >> 8) & 0xFF)) << char(((len >> 16) & 0xFF)) + << char(((len >> 24) & 0xFF)); std::cout << reply.toStdString() << std::flush; } } @@ -136,7 +137,7 @@ QString NativeMessagingBase::getLocalServerPath() const // Use XDG_RUNTIME_DIR instead of /tmp/ if it's available QString path = QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation) + "/kpxc_server"; return path.isEmpty() ? "/tmp/kpxc_server" : path; -#else // Q_OS_MAC and others +#else // Q_OS_MAC and others return "/tmp/kpxc_server"; #endif } diff --git a/src/browser/NativeMessagingBase.h b/src/browser/NativeMessagingBase.h index 4253b758..e9ee2cc7 100644 --- a/src/browser/NativeMessagingBase.h +++ b/src/browser/NativeMessagingBase.h @@ -19,16 +19,16 @@ #ifndef NATIVEMESSAGINGBASE_H #define NATIVEMESSAGINGBASE_H -#include -#include -#include +#include #include -#include -#include -#include +#include +#include #include #include -#include +#include +#include +#include +#include #include #include @@ -41,21 +41,21 @@ public: ~NativeMessagingBase() = default; protected slots: - void newNativeMessage(); + void newNativeMessage(); protected: - virtual void readLength() = 0; - virtual void readStdIn(const quint32 length) = 0; - void readNativeMessages(); - QString jsonToString(const QJsonObject& json) const; - void sendReply(const QJsonObject& json); - void sendReply(const QString& reply); - QString getLocalServerPath() const; + virtual void readLength() = 0; + virtual void readStdIn(const quint32 length) = 0; + void readNativeMessages(); + QString jsonToString(const QJsonObject& json) const; + void sendReply(const QJsonObject& json); + void sendReply(const QString& reply); + QString getLocalServerPath() const; protected: - QAtomicInteger m_running; + QAtomicInteger m_running; QSharedPointer m_notifier; - QFuture m_future; + QFuture m_future; }; -#endif // NATIVEMESSAGINGBASE_H +#endif // NATIVEMESSAGINGBASE_H diff --git a/src/browser/NativeMessagingHost.cpp b/src/browser/NativeMessagingHost.cpp old mode 100755 new mode 100644 index 0101e944..7c26ea08 --- a/src/browser/NativeMessagingHost.cpp +++ b/src/browser/NativeMessagingHost.cpp @@ -16,18 +16,18 @@ * along with this program. If not, see . */ +#include "NativeMessagingHost.h" +#include "BrowserSettings.h" +#include "sodium.h" #include #include #include -#include "sodium.h" -#include "NativeMessagingHost.h" -#include "BrowserSettings.h" -NativeMessagingHost::NativeMessagingHost(DatabaseTabWidget* parent) : - NativeMessagingBase(), - m_mutex(QMutex::Recursive), - m_browserClients(m_browserService), - m_browserService(parent) +NativeMessagingHost::NativeMessagingHost(DatabaseTabWidget* parent) + : NativeMessagingBase() + , m_mutex(QMutex::Recursive) + , m_browserClients(m_browserService) + , m_browserService(parent) { m_localServer.reset(new QLocalServer(this)); m_localServer->setSocketOptions(QLocalServer::UserAccessOption); @@ -61,12 +61,14 @@ void NativeMessagingHost::run() // Update KeePassXC/keepassxc-proxy binary paths to Native Messaging scripts if (BrowserSettings::updateBinaryPath()) { - BrowserSettings::updateBinaryPaths(BrowserSettings::useCustomProxy() ? BrowserSettings::customProxyLocation() : ""); + BrowserSettings::updateBinaryPaths(BrowserSettings::useCustomProxy() ? BrowserSettings::customProxyLocation() + : ""); } m_running.store(true); #ifdef Q_OS_WIN - m_future = QtConcurrent::run(this, static_cast(&NativeMessagingHost::readNativeMessages)); + m_future = + QtConcurrent::run(this, static_cast(&NativeMessagingHost::readNativeMessages)); #endif if (BrowserSettings::supportBrowserProxy()) { @@ -101,7 +103,7 @@ void NativeMessagingHost::readLength() if (!std::cin.eof() && length > 0) { readStdIn(length); } else { - m_notifier->setEnabled(false); + m_notifier->setEnabled(false); } } diff --git a/src/browser/NativeMessagingHost.h b/src/browser/NativeMessagingHost.h old mode 100755 new mode 100644 index 80825237..0239acd3 --- a/src/browser/NativeMessagingHost.h +++ b/src/browser/NativeMessagingHost.h @@ -19,9 +19,9 @@ #ifndef NATIVEMESSAGINGHOST_H #define NATIVEMESSAGINGHOST_H -#include "NativeMessagingBase.h" #include "BrowserClients.h" #include "BrowserService.h" +#include "NativeMessagingBase.h" #include "gui/DatabaseTabWidget.h" class NativeMessagingHost : public NativeMessagingBase @@ -31,37 +31,37 @@ class NativeMessagingHost : public NativeMessagingBase typedef QList SocketList; public: - explicit NativeMessagingHost(DatabaseTabWidget* parent = 0); + explicit NativeMessagingHost(DatabaseTabWidget* parent = 0); ~NativeMessagingHost(); - int init(); - void run(); - void stop(); + int init(); + void run(); + void stop(); public slots: - void removeSharedEncryptionKeys(); - void removeStoredPermissions(); + void removeSharedEncryptionKeys(); + void removeStoredPermissions(); signals: - void quit(); + void quit(); private: - void readLength(); - void readStdIn(const quint32 length); - void sendReplyToAllClients(const QJsonObject& json); + void readLength(); + void readStdIn(const quint32 length); + void sendReplyToAllClients(const QJsonObject& json); private slots: - void databaseLocked(); - void databaseUnlocked(); - void newLocalConnection(); - void newLocalMessage(); - void disconnectSocket(); + void databaseLocked(); + void databaseUnlocked(); + void newLocalConnection(); + void newLocalMessage(); + void disconnectSocket(); private: - QMutex m_mutex; - BrowserClients m_browserClients; - BrowserService m_browserService; - QSharedPointer m_localServer; - SocketList m_socketList; + QMutex m_mutex; + BrowserClients m_browserClients; + BrowserService m_browserService; + QSharedPointer m_localServer; + SocketList m_socketList; }; #endif // NATIVEMESSAGINGHOST_H diff --git a/src/browser/Variant.h b/src/browser/Variant.h index e467b421..8acdbaa5 100644 --- a/src/browser/Variant.h +++ b/src/browser/Variant.h @@ -20,6 +20,7 @@ #include -QVariantMap qo2qv(const QObject* object, const QStringList& ignoredProperties = QStringList(QString(QLatin1String("objectName")))); +QVariantMap qo2qv(const QObject* object, + const QStringList& ignoredProperties = QStringList(QString(QLatin1String("objectName")))); #endif // VARIANT_H diff --git a/src/cli/Diceware.cpp b/src/cli/Diceware.cpp index c71b57d7..4cdda0a7 100644 --- a/src/cli/Diceware.cpp +++ b/src/cli/Diceware.cpp @@ -42,14 +42,15 @@ int Diceware::execute(const QStringList& arguments) QCommandLineParser parser; parser.setApplicationDescription(this->description); - QCommandLineOption words(QStringList() << "W" << "words", - QObject::tr("Word count for the diceware passphrase."), - QObject::tr("count")); + QCommandLineOption words(QStringList() << "W" + << "words", + QObject::tr("Word count for the diceware passphrase."), + QObject::tr("count")); parser.addOption(words); QCommandLineOption wordlistFile(QStringList() << "w" - << "word-list", - QObject::tr("Wordlist for the diceware generator.\n[Default: EFF English]"), - QObject::tr("path")); + << "word-list", + QObject::tr("Wordlist for the diceware generator.\n[Default: EFF English]"), + QObject::tr("path")); parser.addOption(wordlistFile); parser.process(arguments); @@ -78,7 +79,7 @@ int Diceware::execute(const QStringList& arguments) outputTextStream << parser.helpText().replace("keepassxc-cli", "keepassxc-cli diceware"); return EXIT_FAILURE; } - + QString password = dicewareGenerator.generatePassphrase(); outputTextStream << password << endl; diff --git a/src/cli/Edit.cpp b/src/cli/Edit.cpp index 967ddd8e..056a0a59 100644 --- a/src/cli/Edit.cpp +++ b/src/cli/Edit.cpp @@ -115,8 +115,9 @@ int Edit::execute(const QStringList& arguments) return EXIT_FAILURE; } - if (parser.value("username").isEmpty() && parser.value("url").isEmpty() && parser.value("title").isEmpty() && - !parser.isSet(prompt) && !parser.isSet(generate)) { + if (parser.value("username").isEmpty() && parser.value("url").isEmpty() && parser.value("title").isEmpty() + && !parser.isSet(prompt) + && !parser.isSet(generate)) { qCritical("Not changing any field for entry %s.", qPrintable(entryPath)); return EXIT_FAILURE; } diff --git a/src/cli/Extract.cpp b/src/cli/Extract.cpp index b48d5a6a..089a784d 100644 --- a/src/cli/Extract.cpp +++ b/src/cli/Extract.cpp @@ -84,8 +84,8 @@ int Extract::execute(const QStringList& arguments) if (fileKey.type() != FileKey::Hashed) { errorTextStream << QObject::tr("WARNING: You are using a legacy key file format which may become\n" - "unsupported in the future.\n\n" - "Please consider generating a new key file."); + "unsupported in the future.\n\n" + "Please consider generating a new key file."); errorTextStream << endl; } diff --git a/src/cli/Generate.cpp b/src/cli/Generate.cpp index eb8fea5e..45b67259 100644 --- a/src/cli/Generate.cpp +++ b/src/cli/Generate.cpp @@ -42,24 +42,20 @@ int Generate::execute(const QStringList& arguments) QCommandLineParser parser; parser.setApplicationDescription(this->description); - QCommandLineOption len(QStringList() << "L" << "length", - QObject::tr("Length of the generated password."), - QObject::tr("length")); + QCommandLineOption len(QStringList() << "L" + << "length", + QObject::tr("Length of the generated password."), + QObject::tr("length")); parser.addOption(len); - QCommandLineOption lower(QStringList() << "l", - QObject::tr("Use lowercase characters in the generated password.")); + QCommandLineOption lower(QStringList() << "l", QObject::tr("Use lowercase characters in the generated password.")); parser.addOption(lower); - QCommandLineOption upper(QStringList() << "u", - QObject::tr("Use uppercase characters in the generated password.")); + QCommandLineOption upper(QStringList() << "u", QObject::tr("Use uppercase characters in the generated password.")); parser.addOption(upper); - QCommandLineOption numeric(QStringList() << "n", - QObject::tr("Use numbers in the generated password.")); + QCommandLineOption numeric(QStringList() << "n", QObject::tr("Use numbers in the generated password.")); parser.addOption(numeric); - QCommandLineOption special(QStringList() << "s", - QObject::tr("Use special characters in the generated password.")); + QCommandLineOption special(QStringList() << "s", QObject::tr("Use special characters in the generated password.")); parser.addOption(special); - QCommandLineOption extended(QStringList() << "e", - QObject::tr("Use extended ASCII in the generated password.")); + QCommandLineOption extended(QStringList() << "e", QObject::tr("Use extended ASCII in the generated password.")); parser.addOption(extended); parser.process(arguments); @@ -81,19 +77,19 @@ int Generate::execute(const QStringList& arguments) PasswordGenerator::CharClasses classes = 0x0; if (parser.isSet(lower)) { - classes |= PasswordGenerator::LowerLetters; + classes |= PasswordGenerator::LowerLetters; } if (parser.isSet(upper)) { - classes |= PasswordGenerator::UpperLetters; + classes |= PasswordGenerator::UpperLetters; } if (parser.isSet(numeric)) { - classes |= PasswordGenerator::Numbers; + classes |= PasswordGenerator::Numbers; } if (parser.isSet(special)) { - classes |= PasswordGenerator::SpecialCharacters; + classes |= PasswordGenerator::SpecialCharacters; } if (parser.isSet(extended)) { - classes |= PasswordGenerator::EASCII; + classes |= PasswordGenerator::EASCII; } passwordGenerator.setCharClasses(classes); diff --git a/src/cli/Show.cpp b/src/cli/Show.cpp index 54561b1f..be188c75 100644 --- a/src/cli/Show.cpp +++ b/src/cli/Show.cpp @@ -49,12 +49,14 @@ int Show::execute(const QStringList& arguments) QObject::tr("Key file of the database."), QObject::tr("path")); parser.addOption(keyFile); - QCommandLineOption attributes(QStringList() << "a" - << "attributes", - QObject::tr("Names of the attributes to show. " - "This option can be specified more than once, with each attribute shown one-per-line in the given order. " - "If no attributes are specified, a summary of the default attributes is given."), - QObject::tr("attribute")); + QCommandLineOption attributes( + QStringList() << "a" + << "attributes", + QObject::tr( + "Names of the attributes to show. " + "This option can be specified more than once, with each attribute shown one-per-line in the given order. " + "If no attributes are specified, a summary of the default attributes is given."), + QObject::tr("attribute")); parser.addOption(attributes); parser.addPositionalArgument("entry", QObject::tr("Name of the entry to show.")); parser.process(arguments); diff --git a/src/core/AsyncTask.h b/src/core/AsyncTask.h index 67cab160..45bb191b 100644 --- a/src/core/AsyncTask.h +++ b/src/core/AsyncTask.h @@ -22,42 +22,42 @@ #include #include - /** * Asynchronously run computations outside the GUI thread. */ namespace AsyncTask { -/** - * Wait for the given future without blocking the event loop. - * - * @param future future to wait for - * @return async task result - */ -template -typename std::result_of::type waitForFuture(QFuture::type> future) -{ - QEventLoop loop; - QFutureWatcher::type> watcher; - QObject::connect(&watcher, SIGNAL(finished()), &loop, SLOT(quit())); - watcher.setFuture(future); - loop.exec(); - return future.result(); -} + /** + * Wait for the given future without blocking the event loop. + * + * @param future future to wait for + * @return async task result + */ + template + typename std::result_of::type + waitForFuture(QFuture::type> future) + { + QEventLoop loop; + QFutureWatcher::type> watcher; + QObject::connect(&watcher, SIGNAL(finished()), &loop, SLOT(quit())); + watcher.setFuture(future); + loop.exec(); + return future.result(); + } -/** - * Run a given task and wait for it to finish without blocking the event loop. - * - * @param task std::function object to run - * @return async task result - */ -template -typename std::result_of::type runAndWaitForFuture(FunctionObject task) -{ - return waitForFuture(QtConcurrent::run(task)); -} + /** + * Run a given task and wait for it to finish without blocking the event loop. + * + * @param task std::function object to run + * @return async task result + */ + template + typename std::result_of::type runAndWaitForFuture(FunctionObject task) + { + return waitForFuture(QtConcurrent::run(task)); + } -}; // namespace AsyncTask +}; // namespace AsyncTask -#endif //KEEPASSXC_ASYNCTASK_HPP +#endif // KEEPASSXC_ASYNCTASK_HPP diff --git a/src/core/AutoTypeAssociations.cpp b/src/core/AutoTypeAssociations.cpp index 04221733..730e38ca 100644 --- a/src/core/AutoTypeAssociations.cpp +++ b/src/core/AutoTypeAssociations.cpp @@ -27,7 +27,6 @@ bool AutoTypeAssociations::Association::operator!=(const AutoTypeAssociations::A return window != other.window || sequence != other.sequence; } - AutoTypeAssociations::AutoTypeAssociations(QObject* parent) : QObject(parent) { @@ -106,7 +105,7 @@ int AutoTypeAssociations::size() const int AutoTypeAssociations::associationsSize() const { int size = 0; - for (const Association &association : m_associations) { + for (const Association& association : m_associations) { size += association.sequence.toUtf8().size() + association.window.toUtf8().size(); } return size; diff --git a/src/core/AutoTypeMatch.cpp b/src/core/AutoTypeMatch.cpp index c1faab9e..9b7940f4 100644 --- a/src/core/AutoTypeMatch.cpp +++ b/src/core/AutoTypeMatch.cpp @@ -19,14 +19,16 @@ #include "AutoTypeMatch.h" AutoTypeMatch::AutoTypeMatch() - : entry(nullptr), - sequence() -{} + : entry(nullptr) + , sequence() +{ +} AutoTypeMatch::AutoTypeMatch(Entry* entry, QString sequence) - : entry(entry), - sequence(sequence) -{} + : entry(entry) + , sequence(sequence) +{ +} bool AutoTypeMatch::operator==(const AutoTypeMatch& other) const { diff --git a/src/core/Config.cpp b/src/core/Config.cpp index 461ab1f7..ccdc24fd 100644 --- a/src/core/Config.cpp +++ b/src/core/Config.cpp @@ -21,8 +21,8 @@ #include #include #include -#include #include +#include Config* Config::m_instance(nullptr); @@ -80,7 +80,7 @@ Config::Config(QObject* parent) QString userPath; QString homePath = QDir::homePath(); - #if defined(Q_OS_UNIX) && !defined(Q_OS_MAC) +#if defined(Q_OS_UNIX) && !defined(Q_OS_MAC) // we can't use QStandardPaths on X11 as it uses XDG_DATA_HOME instead of XDG_CONFIG_HOME QByteArray env = qgetenv("XDG_CONFIG_HOME"); if (env.isEmpty()) { @@ -95,17 +95,17 @@ Config::Config(QObject* parent) } userPath += "/keepassxc/"; - #else +#else userPath = QDir::fromNativeSeparators(QStandardPaths::writableLocation(QStandardPaths::DataLocation)); // storageLocation() appends the application name ("/keepassxc") to the end userPath += "/"; - #endif +#endif - #ifdef QT_DEBUG +#ifdef QT_DEBUG userPath += "keepassxc_debug.ini"; - #else +#else userPath += "keepassxc.ini"; - #endif +#endif init(userPath); } diff --git a/src/core/Config.h b/src/core/Config.h index eb797862..fcb27e2c 100644 --- a/src/core/Config.h +++ b/src/core/Config.h @@ -26,7 +26,7 @@ class QSettings; class Config : public QObject { -Q_OBJECT + Q_OBJECT public: Q_DISABLE_COPY(Config) @@ -54,7 +54,8 @@ private: QHash m_defaults; }; -inline Config* config() { +inline Config* config() +{ return Config::instance(); } diff --git a/src/core/CsvParser.cpp b/src/core/CsvParser.cpp index 4fc4281b..a66c919b 100644 --- a/src/core/CsvParser.cpp +++ b/src/core/CsvParser.cpp @@ -18,8 +18,8 @@ #include "CsvParser.h" -#include #include +#include #include "core/Tools.h" @@ -44,21 +44,24 @@ CsvParser::CsvParser() m_ts.setCodec("UTF-8"); } -CsvParser::~CsvParser() { +CsvParser::~CsvParser() +{ m_csv.close(); } -bool CsvParser::isFileLoaded() { +bool CsvParser::isFileLoaded() +{ return m_isFileLoaded; } -bool CsvParser::reparse() { +bool CsvParser::reparse() +{ reset(); return parseFile(); } - -bool CsvParser::parse(QFile *device) { +bool CsvParser::parse(QFile* device) +{ clear(); if (nullptr == device) { appendStatusMsg(QObject::tr("NULL device"), true); @@ -69,7 +72,8 @@ bool CsvParser::parse(QFile *device) { return parseFile(); } -bool CsvParser::readFile(QFile *device) { +bool CsvParser::readFile(QFile* device) +{ if (device->isOpen()) device->close(); @@ -77,20 +81,20 @@ bool CsvParser::readFile(QFile *device) { if (!Tools::readAllFromDevice(device, m_array)) { appendStatusMsg(QObject::tr("error reading from device"), true); m_isFileLoaded = false; - } - else { + } else { device->close(); m_array.replace("\r\n", "\n"); m_array.replace("\r", "\n"); if (0 == m_array.size()) - appendStatusMsg(QObject::tr("file empty").append("\n")); + appendStatusMsg(QObject::tr("file empty").append("\n")); m_isFileLoaded = true; } return m_isFileLoaded; } -void CsvParser::reset() { +void CsvParser::reset() +{ m_ch = 0; m_currCol = 1; m_currRow = 1; @@ -101,21 +105,23 @@ void CsvParser::reset() { m_statusMsg = ""; m_ts.seek(0); m_table.clear(); - //the following are users' concern :) - //m_comment = '#'; - //m_backslashSyntax = false; - //m_comment = '#'; - //m_qualifier = '"'; - //m_separator = ','; + // the following are users' concern :) + // m_comment = '#'; + // m_backslashSyntax = false; + // m_comment = '#'; + // m_qualifier = '"'; + // m_separator = ','; } -void CsvParser::clear() { +void CsvParser::clear() +{ reset(); m_isFileLoaded = false; m_array.clear(); } -bool CsvParser::parseFile() { +bool CsvParser::parseFile() +{ parseRecord(); while (!m_isEof) { if (!skipEndline()) @@ -128,7 +134,8 @@ bool CsvParser::parseFile() { return m_isGood; } -void CsvParser::parseRecord() { +void CsvParser::parseRecord() +{ CsvRow row; if (isComment()) { skipLine(); @@ -151,19 +158,21 @@ void CsvParser::parseRecord() { m_currCol++; } -void CsvParser::parseField(CsvRow& row) { +void CsvParser::parseField(CsvRow& row) +{ QString field; peek(m_ch); if (!isTerminator(m_ch)) { if (isQualifier(m_ch)) - parseQuoted(field); + parseQuoted(field); else parseSimple(field); } row.push_back(field); } -void CsvParser::parseSimple(QString &s) { +void CsvParser::parseSimple(QString& s) +{ QChar c; getChar(c); while ((isText(c)) && (!m_isEof)) { @@ -174,16 +183,18 @@ void CsvParser::parseSimple(QString &s) { ungetChar(); } -void CsvParser::parseQuoted(QString &s) { - //read and discard initial qualifier (e.g. quote) +void CsvParser::parseQuoted(QString& s) +{ + // read and discard initial qualifier (e.g. quote) getChar(m_ch); parseEscaped(s); - //getChar(m_ch); + // getChar(m_ch); if (!isQualifier(m_ch)) appendStatusMsg(QObject::tr("missing closing quote"), true); } -void CsvParser::parseEscaped(QString &s) { +void CsvParser::parseEscaped(QString& s) +{ parseEscapedText(s); while (processEscapeMark(s, m_ch)) parseEscapedText(s); @@ -191,7 +202,8 @@ void CsvParser::parseEscaped(QString &s) { ungetChar(); } -void CsvParser::parseEscapedText(QString &s) { +void CsvParser::parseEscapedText(QString& s) +{ getChar(m_ch); while ((!isQualifier(m_ch)) && !m_isEof) { s.append(m_ch); @@ -199,19 +211,20 @@ void CsvParser::parseEscapedText(QString &s) { } } -bool CsvParser::processEscapeMark(QString &s, QChar c) { +bool CsvParser::processEscapeMark(QString& s, QChar c) +{ QChar buf; peek(buf); QChar c2; if (true == m_isBackslashSyntax) { - //escape-character syntax, e.g. \" + // escape-character syntax, e.g. \" if (c != '\\') { return false; } - //consume (and append) second qualifier + // consume (and append) second qualifier getChar(c2); if (m_isEof) { - c2='\\'; + c2 = '\\'; s.append('\\'); return false; } else { @@ -219,11 +232,11 @@ bool CsvParser::processEscapeMark(QString &s, QChar c) { return true; } } else { - //double quote syntax, e.g. "" + // double quote syntax, e.g. "" if (!isQualifier(c)) return false; peek(c2); - if (!m_isEof) { //not EOF, can read one char + if (!m_isEof) { // not EOF, can read one char if (isQualifier(c2)) { s.append(c2); getChar(c2); @@ -234,10 +247,11 @@ bool CsvParser::processEscapeMark(QString &s, QChar c) { } } -void CsvParser::fillColumns() { - //fill shorter rows with empty placeholder columns +void CsvParser::fillColumns() +{ + // fill shorter rows with empty placeholder columns for (int i = 0; i < m_table.size(); ++i) { - int gap = m_maxCols-m_table.at(i).size(); + int gap = m_maxCols - m_table.at(i).size(); if (gap > 0) { CsvRow r = m_table.at(i); for (int j = 0; j < gap; ++j) { @@ -248,18 +262,20 @@ void CsvParser::fillColumns() { } } -void CsvParser::skipLine() { +void CsvParser::skipLine() +{ m_ts.readLine(); m_ts.seek(m_ts.pos() - 1); } -bool CsvParser::skipEndline() { +bool CsvParser::skipEndline() +{ getChar(m_ch); return (m_ch == '\n'); } - -void CsvParser::getChar(QChar& c) { +void CsvParser::getChar(QChar& c) +{ m_isEof = m_ts.atEnd(); if (!m_isEof) { m_lastPos = m_ts.pos(); @@ -267,32 +283,37 @@ void CsvParser::getChar(QChar& c) { } } -void CsvParser::ungetChar() { +void CsvParser::ungetChar() +{ if (!m_ts.seek(m_lastPos)) { qWarning("CSV Parser: unget lower bound exceeded"); m_isGood = false; } } -void CsvParser::peek(QChar& c) { +void CsvParser::peek(QChar& c) +{ getChar(c); if (!m_isEof) ungetChar(); } -bool CsvParser::isQualifier(const QChar &c) const { +bool CsvParser::isQualifier(const QChar& c) const +{ if (true == m_isBackslashSyntax && (c != m_qualifier)) return (c == '\\'); else return (c == m_qualifier); } -bool CsvParser::isComment() { +bool CsvParser::isComment() +{ bool result = false; QChar c2; qint64 pos = m_ts.pos(); - do getChar(c2); + do + getChar(c2); while ((isSpace(c2) || isTab(c2)) && (!m_isEof)); if (c2 == m_comment) @@ -301,84 +322,100 @@ bool CsvParser::isComment() { return result; } -bool CsvParser::isText(QChar c) const { - return !( (isCRLF(c)) || (isSeparator(c)) ); +bool CsvParser::isText(QChar c) const +{ + return !((isCRLF(c)) || (isSeparator(c))); } -bool CsvParser::isEmptyRow(CsvRow row) const { +bool CsvParser::isEmptyRow(CsvRow row) const +{ CsvRow::const_iterator it = row.constBegin(); for (; it != row.constEnd(); ++it) - if ( ((*it) != "\n") && ((*it) != "") ) + if (((*it) != "\n") && ((*it) != "")) return false; return true; } -bool CsvParser::isCRLF(const QChar &c) const { +bool CsvParser::isCRLF(const QChar& c) const +{ return (c == '\n'); } -bool CsvParser::isSpace(const QChar &c) const { +bool CsvParser::isSpace(const QChar& c) const +{ return (c == ' '); } -bool CsvParser::isTab(const QChar &c) const { +bool CsvParser::isTab(const QChar& c) const +{ return (c == '\t'); } -bool CsvParser::isSeparator(const QChar &c) const { +bool CsvParser::isSeparator(const QChar& c) const +{ return (c == m_separator); } -bool CsvParser::isTerminator(const QChar &c) const { +bool CsvParser::isTerminator(const QChar& c) const +{ return (isSeparator(c) || (c == '\n') || (c == '\r')); } -void CsvParser::setBackslashSyntax(bool set) { +void CsvParser::setBackslashSyntax(bool set) +{ m_isBackslashSyntax = set; } -void CsvParser::setComment(const QChar &c) { +void CsvParser::setComment(const QChar& c) +{ m_comment = c.unicode(); } -void CsvParser::setCodec(const QString &s) { +void CsvParser::setCodec(const QString& s) +{ m_ts.setCodec(QTextCodec::codecForName(s.toLocal8Bit())); } -void CsvParser::setFieldSeparator(const QChar &c) { +void CsvParser::setFieldSeparator(const QChar& c) +{ m_separator = c.unicode(); } -void CsvParser::setTextQualifier(const QChar &c) { +void CsvParser::setTextQualifier(const QChar& c) +{ m_qualifier = c.unicode(); } -int CsvParser::getFileSize() const { +int CsvParser::getFileSize() const +{ return m_csv.size(); } -const CsvTable CsvParser::getCsvTable() const { +const CsvTable CsvParser::getCsvTable() const +{ return m_table; } -QString CsvParser::getStatus() const { +QString CsvParser::getStatus() const +{ return m_statusMsg; } -int CsvParser::getCsvCols() const { +int CsvParser::getCsvCols() const +{ if ((m_table.size() > 0) && (m_table.at(0).size() > 0)) return m_table.at(0).size(); - else return 0; + else + return 0; } -int CsvParser::getCsvRows() const { +int CsvParser::getCsvRows() const +{ return m_table.size(); } - -void CsvParser::appendStatusMsg(QString s, bool isCritical) { - m_statusMsg += QObject::tr("%1: (row, col) %2,%3") - .arg(s, m_currRow, m_currCol) - .append("\n"); +void CsvParser::appendStatusMsg(QString s, bool isCritical) +{ + m_statusMsg += QObject::tr("%1: (row, col) %2,%3").arg(s, m_currRow, m_currCol).append("\n"); m_isGood = !isCritical; } diff --git a/src/core/CsvParser.h b/src/core/CsvParser.h index 3ab31bf6..32302311 100644 --- a/src/core/CsvParser.h +++ b/src/core/CsvParser.h @@ -19,28 +19,29 @@ #ifndef KEEPASSX_CSVPARSER_H #define KEEPASSX_CSVPARSER_H -#include #include +#include #include #include typedef QStringList CsvRow; typedef QList CsvTable; -class CsvParser { +class CsvParser +{ public: CsvParser(); ~CsvParser(); - //read data from device and parse it - bool parse(QFile *device); + // read data from device and parse it + bool parse(QFile* device); bool isFileLoaded(); - //reparse the same buffer (device is not opened again) + // reparse the same buffer (device is not opened again) bool reparse(); - void setCodec(const QString &s); - void setComment(const QChar &c); - void setFieldSeparator(const QChar &c); - void setTextQualifier(const QChar &c); + void setCodec(const QString& s); + void setComment(const QChar& c); + void setFieldSeparator(const QChar& c); + void setTextQualifier(const QChar& c); void setBackslashSyntax(bool set); int getFileSize() const; int getCsvRows() const; @@ -52,45 +53,45 @@ protected: CsvTable m_table; private: - QByteArray m_array; - QBuffer m_csv; - QChar m_ch; - QChar m_comment; + QByteArray m_array; + QBuffer m_csv; + QChar m_ch; + QChar m_comment; unsigned int m_currCol; unsigned int m_currRow; - bool m_isBackslashSyntax; - bool m_isEof; - bool m_isFileLoaded; - bool m_isGood; - qint64 m_lastPos; - int m_maxCols; - QChar m_qualifier; - QChar m_separator; - QString m_statusMsg; - QTextStream m_ts; + bool m_isBackslashSyntax; + bool m_isEof; + bool m_isFileLoaded; + bool m_isGood; + qint64 m_lastPos; + int m_maxCols; + QChar m_qualifier; + QChar m_separator; + QString m_statusMsg; + QTextStream m_ts; - void getChar(QChar &c); + void getChar(QChar& c); void ungetChar(); - void peek(QChar &c); + void peek(QChar& c); void fillColumns(); - bool isTerminator(const QChar &c) const; - bool isSeparator(const QChar &c) const; - bool isQualifier(const QChar &c) const; - bool processEscapeMark(QString &s, QChar c); + bool isTerminator(const QChar& c) const; + bool isSeparator(const QChar& c) const; + bool isQualifier(const QChar& c) const; + bool processEscapeMark(QString& s, QChar c); bool isText(QChar c) const; bool isComment(); - bool isCRLF(const QChar &c) const; - bool isSpace(const QChar &c) const; - bool isTab(const QChar &c) const; + bool isCRLF(const QChar& c) const; + bool isSpace(const QChar& c) const; + bool isTab(const QChar& c) const; bool isEmptyRow(CsvRow row) const; bool parseFile(); void parseRecord(); - void parseField(CsvRow &row); - void parseSimple(QString &s); - void parseQuoted(QString &s); - void parseEscaped(QString &s); - void parseEscapedText(QString &s); - bool readFile(QFile *device); + void parseField(CsvRow& row); + void parseSimple(QString& s); + void parseQuoted(QString& s); + void parseEscaped(QString& s); + void parseEscapedText(QString& s); + bool readFile(QFile* device); void reset(); void clear(); bool skipEndline(); @@ -98,5 +99,4 @@ private: void appendStatusMsg(QString s, bool isCritical = false); }; -#endif //CSVPARSER_H - +#endif // CSVPARSER_H diff --git a/src/core/CustomData.cpp b/src/core/CustomData.cpp index 61ac2980..ea0a3580 100644 --- a/src/core/CustomData.cpp +++ b/src/core/CustomData.cpp @@ -54,7 +54,7 @@ void CustomData::set(const QString& key, const QString& value) if (addAttribute) { emit aboutToBeAdded(key); - } + } if (addAttribute || changeValue) { m_data.insert(key, value); diff --git a/src/core/CustomData.h b/src/core/CustomData.h index 3a6b64bc..297fd16f 100644 --- a/src/core/CustomData.h +++ b/src/core/CustomData.h @@ -25,7 +25,7 @@ class CustomData : public QObject { -Q_OBJECT + Q_OBJECT public: explicit CustomData(QObject* parent = nullptr); @@ -45,7 +45,6 @@ public: bool operator==(const CustomData& other) const; bool operator!=(const CustomData& other) const; - signals: void modified(); void aboutToBeAdded(const QString& key); diff --git a/src/core/Database.cpp b/src/core/Database.cpp index 0c2d06b3..219a97f3 100644 --- a/src/core/Database.cpp +++ b/src/core/Database.cpp @@ -32,8 +32,8 @@ #include "format/KeePass2.h" #include "format/KeePass2Reader.h" #include "format/KeePass2Writer.h" -#include "keys/PasswordKey.h" #include "keys/FileKey.h" +#include "keys/PasswordKey.h" QHash Database::m_uuidMap; @@ -129,7 +129,8 @@ Entry* Database::findEntryRecursive(const Uuid& uuid, Group* group) Entry* Database::findEntryRecursive(const QString& text, EntryReferenceType referenceType, Group* group) { - Q_ASSERT_X(referenceType != EntryReferenceType::Unknown, "Database::findEntryRecursive", + Q_ASSERT_X(referenceType != EntryReferenceType::Unknown, + "Database::findEntryRecursive", "Can't search entry with \"referenceType\" parameter equal to \"Unknown\""); bool found = false; @@ -335,7 +336,6 @@ void Database::setPublicCustomData(const QVariantMap& customData) m_data.publicCustomData = customData; } - void Database::createRecycleBin() { Group* recycleBin = Group::createRecycleBin(); @@ -407,7 +407,6 @@ void Database::setEmitModified(bool value) m_emitModified = value; } - Uuid Database::uuid() { return m_uuid; diff --git a/src/core/Database.h b/src/core/Database.h index 583ed3ca..26b0ab66 100644 --- a/src/core/Database.h +++ b/src/core/Database.h @@ -23,8 +23,8 @@ #include #include -#include "crypto/kdf/Kdf.h" #include "core/Uuid.h" +#include "crypto/kdf/Kdf.h" #include "keys/CompositeKey.h" class Entry; @@ -101,8 +101,7 @@ public: void setCipher(const Uuid& cipher); void setCompressionAlgo(Database::CompressionAlgorithm algo); void setKdf(QSharedPointer kdf); - bool setKey(const CompositeKey& key, bool updateChangedTime = true, - bool updateTransformSalt = false); + bool setKey(const CompositeKey& key, bool updateChangedTime = true, bool updateTransformSalt = false); bool hasKey() const; bool verifyKey(const CompositeKey& key) const; QVariantMap& publicCustomData(); diff --git a/src/core/DatabaseIcons.cpp b/src/core/DatabaseIcons.cpp index e53c6aa2..ddb4e910 100644 --- a/src/core/DatabaseIcons.cpp +++ b/src/core/DatabaseIcons.cpp @@ -106,8 +106,7 @@ QImage DatabaseIcons::icon(int index) if (!m_iconCache[index].isNull()) { return m_iconCache[index]; - } - else { + } else { QString iconPath = QString("icons/database/").append(m_indexToName[index]); QImage icon(filePath()->dataPath(iconPath)); diff --git a/src/core/DatabaseIcons.h b/src/core/DatabaseIcons.h index a1d9480b..43a6df21 100644 --- a/src/core/DatabaseIcons.h +++ b/src/core/DatabaseIcons.h @@ -46,7 +46,8 @@ private: Q_DISABLE_COPY(DatabaseIcons) }; -inline DatabaseIcons* databaseIcons() { +inline DatabaseIcons* databaseIcons() +{ return DatabaseIcons::instance(); } diff --git a/src/core/Endian.h b/src/core/Endian.h index cd01eb48..c2d87ee3 100644 --- a/src/core/Endian.h +++ b/src/core/Endian.h @@ -20,59 +20,55 @@ #define KEEPASSX_ENDIAN_H #include +#include #include #include -#include namespace Endian { -template -SizedQInt bytesToSizedInt(const QByteArray& ba, QSysInfo::Endian byteOrder) -{ - Q_ASSERT(ba.size() == sizeof(SizedQInt)); + template SizedQInt bytesToSizedInt(const QByteArray& ba, QSysInfo::Endian byteOrder) + { + Q_ASSERT(ba.size() == sizeof(SizedQInt)); - if (byteOrder == QSysInfo::LittleEndian) { - return qFromLittleEndian(reinterpret_cast(ba.constData())); - } - return qFromBigEndian(reinterpret_cast(ba.constData())); -} - -template -SizedQInt readSizedInt(QIODevice* device, QSysInfo::Endian byteOrder, bool* ok) -{ - QByteArray ba = device->read(sizeof(SizedQInt)); - - if (ba.size() != sizeof(SizedQInt)) { - *ok = false; - return 0; - } - *ok = true; - return bytesToSizedInt(ba, byteOrder); -} - -template -QByteArray sizedIntToBytes(SizedQInt num, QSysInfo::Endian byteOrder) -{ - QByteArray ba; - ba.resize(sizeof(SizedQInt)); - - if (byteOrder == QSysInfo::LittleEndian) { - qToLittleEndian(num, reinterpret_cast(ba.data())); - } else { - qToBigEndian(num, reinterpret_cast(ba.data())); + if (byteOrder == QSysInfo::LittleEndian) { + return qFromLittleEndian(reinterpret_cast(ba.constData())); + } + return qFromBigEndian(reinterpret_cast(ba.constData())); } - return ba; -} + template SizedQInt readSizedInt(QIODevice* device, QSysInfo::Endian byteOrder, bool* ok) + { + QByteArray ba = device->read(sizeof(SizedQInt)); -template -bool writeSizedInt(SizedQInt num, QIODevice* device, QSysInfo::Endian byteOrder) -{ - QByteArray ba = sizedIntToBytes(num, byteOrder); - qint64 bytesWritten = device->write(ba); - return (bytesWritten == ba.size()); -} + if (ba.size() != sizeof(SizedQInt)) { + *ok = false; + return 0; + } + *ok = true; + return bytesToSizedInt(ba, byteOrder); + } + + template QByteArray sizedIntToBytes(SizedQInt num, QSysInfo::Endian byteOrder) + { + QByteArray ba; + ba.resize(sizeof(SizedQInt)); + + if (byteOrder == QSysInfo::LittleEndian) { + qToLittleEndian(num, reinterpret_cast(ba.data())); + } else { + qToBigEndian(num, reinterpret_cast(ba.data())); + } + + return ba; + } + + template bool writeSizedInt(SizedQInt num, QIODevice* device, QSysInfo::Endian byteOrder) + { + QByteArray ba = sizedIntToBytes(num, byteOrder); + qint64 bytesWritten = device->write(ba); + return (bytesWritten == ba.size()); + } } // namespace Endian diff --git a/src/core/Entry.cpp b/src/core/Entry.cpp index 00fec506..b63f4c70 100644 --- a/src/core/Entry.cpp +++ b/src/core/Entry.cpp @@ -32,7 +32,6 @@ const int Entry::ResolveMaximumDepth = 10; const QString Entry::AutoTypeSequenceUsername = "{USERNAME}{ENTER}"; const QString Entry::AutoTypeSequencePassword = "{PASSWORD}{ENTER}"; - Entry::Entry() : m_attributes(new EntryAttributes(this)) , m_attachments(new EntryAttachments(this)) @@ -78,8 +77,7 @@ template inline bool Entry::set(T& property, const T& value) property = value; emit modified(); return true; - } - else { + } else { return false; } } @@ -129,14 +127,12 @@ QImage Entry::icon() const { if (m_data.customIcon.isNull()) { return databaseIcons()->icon(m_data.iconNumber); - } - else { + } else { Q_ASSERT(database()); if (database()) { return database()->metadata()->customIcon(m_data.customIcon); - } - else { + } else { return QImage(); } } @@ -146,14 +142,12 @@ QPixmap Entry::iconPixmap() const { if (m_data.customIcon.isNull()) { return databaseIcons()->iconPixmap(m_data.iconNumber); - } - else { + } else { Q_ASSERT(database()); if (database()) { return database()->metadata()->customIconPixmap(m_data.customIcon); - } - else { + } else { return QPixmap(); } } @@ -164,8 +158,7 @@ QPixmap Entry::iconScaledPixmap() const if (m_data.customIcon.isNull()) { // built-in icons are 16x16 so don't need to be scaled return databaseIcons()->iconPixmap(m_data.iconNumber); - } - else { + } else { Q_ASSERT(database()); return database()->metadata()->customIconScaledPixmap(m_data.customIcon); @@ -381,7 +374,7 @@ void Entry::setTotp(const QString& seed, quint8& step, quint8& digits) } QString data; - const Totp::Encoder & enc = Totp::encoders.value(digits, Totp::defaultEncoder); + const Totp::Encoder& enc = Totp::encoders.value(digits, Totp::defaultEncoder); if (m_attributes->hasKey("otp")) { data = QString("key=%1&step=%2&size=%3").arg(seed).arg(step).arg(enc.digits == 0 ? digits : enc.digits); @@ -503,9 +496,9 @@ void Entry::setTitle(const QString& title) void Entry::setUrl(const QString& url) { - bool remove = url != m_attributes->value(EntryAttributes::URLKey) && - (m_attributes->value(EntryAttributes::RememberCmdExecAttr) == "1" || - m_attributes->value(EntryAttributes::RememberCmdExecAttr) == "0"); + bool remove = url != m_attributes->value(EntryAttributes::URLKey) + && (m_attributes->value(EntryAttributes::RememberCmdExecAttr) == "1" + || m_attributes->value(EntryAttributes::RememberCmdExecAttr) == "0"); if (remove) { m_attributes->remove(EntryAttributes::RememberCmdExecAttr); } @@ -640,8 +633,7 @@ Entry* Entry::clone(CloneFlags flags) const entry->setUpdateTimeinfo(false); if (flags & CloneNewUuid) { entry->m_uuid = Uuid::random(); - } - else { + } else { entry->m_uuid = m_uuid; } entry->m_data = m_data; @@ -652,12 +644,14 @@ Entry* Entry::clone(CloneFlags flags) const if (flags & CloneUserAsRef) { // Build the username reference QString username = "{REF:U@I:" + m_uuid.toHex() + "}"; - entry->m_attributes->set(EntryAttributes::UserNameKey, username.toUpper(), m_attributes->isProtected(EntryAttributes::UserNameKey)); + entry->m_attributes->set( + EntryAttributes::UserNameKey, username.toUpper(), m_attributes->isProtected(EntryAttributes::UserNameKey)); } if (flags & ClonePassAsRef) { QString password = "{REF:P@I:" + m_uuid.toHex() + "}"; - entry->m_attributes->set(EntryAttributes::PasswordKey, password.toUpper(), m_attributes->isProtected(EntryAttributes::PasswordKey)); + entry->m_attributes->set( + EntryAttributes::PasswordKey, password.toUpper(), m_attributes->isProtected(EntryAttributes::PasswordKey)); } entry->m_autoTypeAssociations->copyDataFrom(m_autoTypeAssociations); @@ -719,8 +713,7 @@ bool Entry::endUpdate() m_tmpHistoryItem->setUpdateTimeinfo(true); addHistoryItem(m_tmpHistoryItem); truncateHistory(); - } - else { + } else { delete m_tmpHistoryItem; } @@ -933,8 +926,8 @@ void Entry::setGroup(Group* group) // copy custom icon to the new database if (!iconUuid().isNull() && group->database() - && m_group->database()->metadata()->containsCustomIcon(iconUuid()) - && !group->database()->metadata()->containsCustomIcon(iconUuid())) { + && m_group->database()->metadata()->containsCustomIcon(iconUuid()) + && !group->database()->metadata()->containsCustomIcon(iconUuid())) { group->database()->metadata()->addCustomIcon(iconUuid(), icon()); } } @@ -959,8 +952,7 @@ const Database* Entry::database() const { if (m_group) { return m_group->database(); - } - else { + } else { return nullptr; } } @@ -1028,26 +1020,25 @@ Entry::PlaceholderType Entry::placeholderType(const QString& placeholder) const return PlaceholderType::Reference; } - static const QMap placeholders { - { QStringLiteral("{TITLE}"), PlaceholderType::Title }, - { QStringLiteral("{USERNAME}"), PlaceholderType::UserName }, - { QStringLiteral("{PASSWORD}"), PlaceholderType::Password }, - { QStringLiteral("{NOTES}"), PlaceholderType::Notes }, - { QStringLiteral("{TOTP}"), PlaceholderType::Totp }, - { QStringLiteral("{URL}"), PlaceholderType::Url }, - { QStringLiteral("{URL:RMVSCM}"), PlaceholderType::UrlWithoutScheme }, - { QStringLiteral("{URL:WITHOUTSCHEME}"), PlaceholderType::UrlWithoutScheme }, - { QStringLiteral("{URL:SCM}"), PlaceholderType::UrlScheme }, - { QStringLiteral("{URL:SCHEME}"), PlaceholderType::UrlScheme }, - { QStringLiteral("{URL:HOST}"), PlaceholderType::UrlHost }, - { QStringLiteral("{URL:PORT}"), PlaceholderType::UrlPort }, - { QStringLiteral("{URL:PATH}"), PlaceholderType::UrlPath }, - { QStringLiteral("{URL:QUERY}"), PlaceholderType::UrlQuery }, - { QStringLiteral("{URL:FRAGMENT}"), PlaceholderType::UrlFragment }, - { QStringLiteral("{URL:USERINFO}"), PlaceholderType::UrlUserInfo }, - { QStringLiteral("{URL:USERNAME}"), PlaceholderType::UrlUserName }, - { QStringLiteral("{URL:PASSWORD}"), PlaceholderType::UrlPassword } - }; + static const QMap placeholders{ + {QStringLiteral("{TITLE}"), PlaceholderType::Title}, + {QStringLiteral("{USERNAME}"), PlaceholderType::UserName}, + {QStringLiteral("{PASSWORD}"), PlaceholderType::Password}, + {QStringLiteral("{NOTES}"), PlaceholderType::Notes}, + {QStringLiteral("{TOTP}"), PlaceholderType::Totp}, + {QStringLiteral("{URL}"), PlaceholderType::Url}, + {QStringLiteral("{URL:RMVSCM}"), PlaceholderType::UrlWithoutScheme}, + {QStringLiteral("{URL:WITHOUTSCHEME}"), PlaceholderType::UrlWithoutScheme}, + {QStringLiteral("{URL:SCM}"), PlaceholderType::UrlScheme}, + {QStringLiteral("{URL:SCHEME}"), PlaceholderType::UrlScheme}, + {QStringLiteral("{URL:HOST}"), PlaceholderType::UrlHost}, + {QStringLiteral("{URL:PORT}"), PlaceholderType::UrlPort}, + {QStringLiteral("{URL:PATH}"), PlaceholderType::UrlPath}, + {QStringLiteral("{URL:QUERY}"), PlaceholderType::UrlQuery}, + {QStringLiteral("{URL:FRAGMENT}"), PlaceholderType::UrlFragment}, + {QStringLiteral("{URL:USERINFO}"), PlaceholderType::UrlUserInfo}, + {QStringLiteral("{URL:USERNAME}"), PlaceholderType::UrlUserName}, + {QStringLiteral("{URL:PASSWORD}"), PlaceholderType::UrlPassword}}; return placeholders.value(placeholder.toUpper(), PlaceholderType::Unknown); } @@ -1062,7 +1053,7 @@ QString Entry::resolveUrl(const QString& url) const if (newUrl.startsWith("cmd://")) { QStringList cmdList = newUrl.split(" "); - for (int i=1; i < cmdList.size(); ++i) { + for (int i = 1; i < cmdList.size(); ++i) { // Don't pass arguments to the resolveUrl function (they look like URL's) if (!cmdList[i].startsWith("-") && !cmdList[i].startsWith("/")) { return resolveUrl(cmdList[i].remove(QRegExp("'|\""))); diff --git a/src/core/Entry.h b/src/core/Entry.h index 6ddf87de..c096a9a2 100644 --- a/src/core/Entry.h +++ b/src/core/Entry.h @@ -37,7 +37,8 @@ class Database; class Group; -enum class EntryReferenceType { +enum class EntryReferenceType +{ Unknown, Title, UserName, @@ -142,18 +143,20 @@ public: void removeHistoryItems(const QList& historyEntries); void truncateHistory(); - enum CloneFlag { - CloneNoFlags = 0, - CloneNewUuid = 1, // generate a random uuid for the clone - CloneResetTimeInfo = 2, // set all TimeInfo attributes to the current time - CloneIncludeHistory = 4, // clone the history items - CloneRenameTitle = 8, // add "-Clone" after the original title - CloneUserAsRef = 16, // Add the user as a reference to the original entry - ClonePassAsRef = 32, // Add the password as a reference to the original entry + enum CloneFlag + { + CloneNoFlags = 0, + CloneNewUuid = 1, // generate a random uuid for the clone + CloneResetTimeInfo = 2, // set all TimeInfo attributes to the current time + CloneIncludeHistory = 4, // clone the history items + CloneRenameTitle = 8, // add "-Clone" after the original title + CloneUserAsRef = 16, // Add the user as a reference to the original entry + ClonePassAsRef = 32, // Add the password as a reference to the original entry }; Q_DECLARE_FLAGS(CloneFlags, CloneFlag) - enum class PlaceholderType { + enum class PlaceholderType + { NotPlaceholder, Unknown, Title, diff --git a/src/core/EntryAttachments.cpp b/src/core/EntryAttachments.cpp index 4dcc0262..d6d45963 100644 --- a/src/core/EntryAttachments.cpp +++ b/src/core/EntryAttachments.cpp @@ -17,8 +17,8 @@ #include "EntryAttachments.h" -#include #include +#include EntryAttachments::EntryAttachments(QObject* parent) : QObject(parent) @@ -61,8 +61,7 @@ void EntryAttachments::set(const QString& key, const QByteArray& value) if (addAttachment) { emit added(key); - } - else { + } else { emit keyModified(key); } @@ -74,8 +73,7 @@ void EntryAttachments::set(const QString& key, const QByteArray& value) void EntryAttachments::remove(const QString& key) { if (!m_attachments.contains(key)) { - Q_ASSERT_X(false, "EntryAttachments::remove", - qPrintable(QString("Can't find attachment for key %1").arg(key))); + Q_ASSERT_X(false, "EntryAttachments::remove", qPrintable(QString("Can't find attachment for key %1").arg(key))); return; } @@ -94,10 +92,10 @@ void EntryAttachments::remove(const QStringList& keys) } bool isModified = false; - for (const QString &key: keys) { + for (const QString& key : keys) { if (!m_attachments.contains(key)) { - Q_ASSERT_X(false, "EntryAttachments::remove", - qPrintable(QString("Can't find attachment for key %1").arg(key))); + Q_ASSERT_X( + false, "EntryAttachments::remove", qPrintable(QString("Can't find attachment for key %1").arg(key))); continue; } diff --git a/src/core/EntryAttributes.cpp b/src/core/EntryAttributes.cpp index 772a5661..423e9d49 100644 --- a/src/core/EntryAttributes.cpp +++ b/src/core/EntryAttributes.cpp @@ -23,8 +23,8 @@ const QString EntryAttributes::UserNameKey = "UserName"; const QString EntryAttributes::PasswordKey = "Password"; const QString EntryAttributes::URLKey = "URL"; const QString EntryAttributes::NotesKey = "Notes"; -const QStringList EntryAttributes::DefaultAttributes(QStringList() << TitleKey << UserNameKey - << PasswordKey << URLKey << NotesKey); +const QStringList EntryAttributes::DefaultAttributes(QStringList() << TitleKey << UserNameKey << PasswordKey << URLKey + << NotesKey); const QString EntryAttributes::WantedFieldGroupName = "WantedField"; const QString EntryAttributes::SearchInGroupName = "SearchIn"; @@ -113,8 +113,7 @@ void EntryAttributes::set(const QString& key, const QString& value, bool protect emitModified = true; } m_protectedAttributes.insert(key); - } - else if (m_protectedAttributes.remove(key)) { + } else if (m_protectedAttributes.remove(key)) { emitModified = true; } @@ -124,11 +123,9 @@ void EntryAttributes::set(const QString& key, const QString& value, bool protect if (defaultAttribute && changeValue) { emit defaultKeyModified(); - } - else if (addAttribute) { + } else if (addAttribute) { emit added(key); - } - else if (emitModified) { + } else if (emitModified) { emit customKeyModified(key); } } @@ -249,21 +246,19 @@ void EntryAttributes::copyDataFrom(const EntryAttributes* other) bool EntryAttributes::operator==(const EntryAttributes& other) const { - return (m_attributes == other.m_attributes - && m_protectedAttributes == other.m_protectedAttributes); + return (m_attributes == other.m_attributes && m_protectedAttributes == other.m_protectedAttributes); } bool EntryAttributes::operator!=(const EntryAttributes& other) const { - return (m_attributes != other.m_attributes - || m_protectedAttributes != other.m_protectedAttributes); + return (m_attributes != other.m_attributes || m_protectedAttributes != other.m_protectedAttributes); } QRegularExpressionMatch EntryAttributes::matchReference(const QString& text) { static QRegularExpression referenceRegExp( - "\\{REF:(?[TUPANI])@(?[TUPANIO]):(?[^}]+)\\}", - QRegularExpression::CaseInsensitiveOption); + "\\{REF:(?[TUPANI])@(?[TUPANIO]):(?[^}]+)\\}", + QRegularExpression::CaseInsensitiveOption); return referenceRegExp.match(text); } diff --git a/src/core/EntrySearcher.cpp b/src/core/EntrySearcher.cpp index deaefa1a..820646a9 100644 --- a/src/core/EntrySearcher.cpp +++ b/src/core/EntrySearcher.cpp @@ -20,8 +20,7 @@ #include "core/Group.h" -QList EntrySearcher::search(const QString& searchTerm, const Group* group, - Qt::CaseSensitivity caseSensitivity) +QList EntrySearcher::search(const QString& searchTerm, const Group* group, Qt::CaseSensitivity caseSensitivity) { if (!group->resolveSearchingEnabled()) { return QList(); @@ -30,14 +29,14 @@ QList EntrySearcher::search(const QString& searchTerm, const Group* grou return searchEntries(searchTerm, group, caseSensitivity); } -QList EntrySearcher::searchEntries(const QString& searchTerm, const Group* group, - Qt::CaseSensitivity caseSensitivity) +QList +EntrySearcher::searchEntries(const QString& searchTerm, const Group* group, Qt::CaseSensitivity caseSensitivity) { QList searchResult; const QList entryList = group->entries(); for (Entry* entry : entryList) { - searchResult.append(matchEntry(searchTerm, entry, caseSensitivity)); + searchResult.append(matchEntry(searchTerm, entry, caseSensitivity)); } const QList children = group->children(); @@ -54,8 +53,7 @@ QList EntrySearcher::searchEntries(const QString& searchTerm, const Grou return searchResult; } -QList EntrySearcher::matchEntry(const QString& searchTerm, Entry* entry, - Qt::CaseSensitivity caseSensitivity) +QList EntrySearcher::matchEntry(const QString& searchTerm, Entry* entry, Qt::CaseSensitivity caseSensitivity) { const QStringList wordList = searchTerm.split(QRegExp("\\s"), QString::SkipEmptyParts); for (const QString& word : wordList) { @@ -69,10 +67,10 @@ QList EntrySearcher::matchEntry(const QString& searchTerm, Entry* entry, bool EntrySearcher::wordMatch(const QString& word, Entry* entry, Qt::CaseSensitivity caseSensitivity) { - return entry->resolvePlaceholder(entry->title()).contains(word, caseSensitivity) || - entry->resolvePlaceholder(entry->username()).contains(word, caseSensitivity) || - entry->resolvePlaceholder(entry->url()).contains(word, caseSensitivity) || - entry->resolvePlaceholder(entry->notes()).contains(word, caseSensitivity); + return entry->resolvePlaceholder(entry->title()).contains(word, caseSensitivity) + || entry->resolvePlaceholder(entry->username()).contains(word, caseSensitivity) + || entry->resolvePlaceholder(entry->url()).contains(word, caseSensitivity) + || entry->resolvePlaceholder(entry->notes()).contains(word, caseSensitivity); } bool EntrySearcher::matchGroup(const QString& searchTerm, const Group* group, Qt::CaseSensitivity caseSensitivity) @@ -89,6 +87,5 @@ bool EntrySearcher::matchGroup(const QString& searchTerm, const Group* group, Qt bool EntrySearcher::wordMatch(const QString& word, const Group* group, Qt::CaseSensitivity caseSensitivity) { - return group->name().contains(word, caseSensitivity) || - group->notes().contains(word, caseSensitivity); + return group->name().contains(word, caseSensitivity) || group->notes().contains(word, caseSensitivity); } diff --git a/src/core/EntrySearcher.h b/src/core/EntrySearcher.h index da51eebc..34373473 100644 --- a/src/core/EntrySearcher.h +++ b/src/core/EntrySearcher.h @@ -21,7 +21,6 @@ #include - class Group; class Entry; diff --git a/src/core/Exporter.h b/src/core/Exporter.h index dedb1c8a..1dd24b3f 100644 --- a/src/core/Exporter.h +++ b/src/core/Exporter.h @@ -8,7 +8,9 @@ class Exporter { public: virtual Database* exportGroup(Group* group) = 0; - virtual ~Exporter() {} + virtual ~Exporter() + { + } }; #endif // KEEPASSX_EXPORTER_H diff --git a/src/core/FilePath.cpp b/src/core/FilePath.cpp index c6f1907a..80de1f0a 100644 --- a/src/core/FilePath.cpp +++ b/src/core/FilePath.cpp @@ -23,8 +23,8 @@ #include #include "config-keepassx.h" -#include "core/Global.h" #include "core/Config.h" +#include "core/Global.h" FilePath* FilePath::m_instance(nullptr); @@ -32,8 +32,7 @@ QString FilePath::dataPath(const QString& name) { if (name.isEmpty() || name.startsWith('/')) { return m_dataPath + name; - } - else { + } else { return m_dataPath + "/" + name; } } @@ -61,14 +60,12 @@ QString FilePath::pluginPath(const QString& name) if (configuredPluginDir != ".") { if (QDir(configuredPluginDir).isAbsolute()) { pluginPaths << configuredPluginDir; - } - else { - QString relativePluginDir = QString("%1/../%2") - .arg(QCoreApplication::applicationDirPath(), configuredPluginDir); + } else { + QString relativePluginDir = + QString("%1/../%2").arg(QCoreApplication::applicationDirPath(), configuredPluginDir); pluginPaths << QDir(relativePluginDir).canonicalPath(); - QString absolutePluginDir = QString("%1/%2") - .arg(KEEPASSX_PREFIX_DIR, configuredPluginDir); + QString absolutePluginDir = QString("%1/%2").arg(KEEPASSX_PREFIX_DIR, configuredPluginDir); pluginPaths << QDir(absolutePluginDir).canonicalPath(); } } @@ -151,11 +148,11 @@ QIcon FilePath::icon(const QString& category, const QString& name, bool fromThem } if (icon.isNull()) { - const QList pngSizes = { 16, 22, 24, 32, 48, 64, 128 }; + const QList pngSizes = {16, 22, 24, 32, 48, 64, 128}; QString filename; for (int size : pngSizes) { - filename = QString("%1/icons/application/%2x%2/%3.png").arg(m_dataPath, QString::number(size), - combinedName); + filename = + QString("%1/icons/application/%2x%2/%3.png").arg(m_dataPath, QString::number(size), combinedName); if (QFile::exists(filename)) { icon.addFile(filename, QSize(size, size)); } @@ -189,17 +186,16 @@ QIcon FilePath::onOffIcon(const QString& category, const QString& name) if (i == 0) { state = QIcon::Off; stateName = "off"; - } - else { + } else { state = QIcon::On; stateName = "on"; } - const QList pngSizes = { 16, 22, 24, 32, 48, 64, 128 }; + const QList pngSizes = {16, 22, 24, 32, 48, 64, 128}; QString filename; for (int size : pngSizes) { - filename = QString("%1/icons/application/%2x%2/%3-%4.png").arg(m_dataPath, QString::number(size), - combinedName, stateName); + filename = QString("%1/icons/application/%2x%2/%3-%4.png") + .arg(m_dataPath, QString::number(size), combinedName, stateName); if (QFile::exists(filename)) { icon.addFile(filename, QSize(size, size), QIcon::Normal, state); } @@ -229,10 +225,8 @@ FilePath::FilePath() #endif #if defined(Q_OS_UNIX) && !(defined(Q_OS_MAC) && defined(WITH_APP_BUNDLE)) else if (isDataDirAbsolute && testSetDir(KEEPASSX_DATA_DIR)) { - } - else if (!isDataDirAbsolute && testSetDir(QString("%1/../%2").arg(appDirPath, KEEPASSX_DATA_DIR))) { - } - else if (!isDataDirAbsolute && testSetDir(QString("%1/%2").arg(KEEPASSX_PREFIX_DIR, KEEPASSX_DATA_DIR))) { + } else if (!isDataDirAbsolute && testSetDir(QString("%1/../%2").arg(appDirPath, KEEPASSX_DATA_DIR))) { + } else if (!isDataDirAbsolute && testSetDir(QString("%1/%2").arg(KEEPASSX_PREFIX_DIR, KEEPASSX_DATA_DIR))) { } #endif #if defined(Q_OS_MAC) && defined(WITH_APP_BUNDLE) @@ -249,8 +243,7 @@ FilePath::FilePath() if (m_dataPath.isEmpty()) { qWarning("FilePath::DataPath: can't find data dir"); - } - else { + } else { m_dataPath = QDir::cleanPath(m_dataPath); } } @@ -260,8 +253,7 @@ bool FilePath::testSetDir(const QString& dir) if (QFile::exists(dir + "/icons/database/C00_Password.png")) { m_dataPath = dir; return true; - } - else { + } else { return false; } } diff --git a/src/core/FilePath.h b/src/core/FilePath.h index b0f0397e..b304b5f1 100644 --- a/src/core/FilePath.h +++ b/src/core/FilePath.h @@ -50,7 +50,8 @@ private: Q_DISABLE_COPY(FilePath) }; -inline FilePath* filePath() { +inline FilePath* filePath() +{ return FilePath::instance(); } diff --git a/src/core/Global.h b/src/core/Global.h index 1cae4b51..64570b33 100644 --- a/src/core/Global.h +++ b/src/core/Global.h @@ -23,26 +23,30 @@ #include #if defined(Q_OS_WIN) -# if defined(KEEPASSX_BUILDING_CORE) -# define KEEPASSX_EXPORT Q_DECL_IMPORT -# else -# define KEEPASSX_EXPORT Q_DECL_EXPORT -# endif +#if defined(KEEPASSX_BUILDING_CORE) +#define KEEPASSX_EXPORT Q_DECL_IMPORT #else -# define KEEPASSX_EXPORT Q_DECL_EXPORT +#define KEEPASSX_EXPORT Q_DECL_EXPORT +#endif +#else +#define KEEPASSX_EXPORT Q_DECL_EXPORT #endif #ifndef QUINT32_MAX #define QUINT32_MAX 4294967295U #endif -template struct AddConst { typedef const T Type; }; +template struct AddConst +{ + typedef const T Type; +}; // this adds const to non-const objects (like std::as_const) -template -constexpr typename AddConst::Type& asConst(T &t) noexcept { return t; } +template constexpr typename AddConst::Type& asConst(T& t) noexcept +{ + return t; +} // prevent rvalue arguments: -template -void asConst(const T&&) = delete; +template void asConst(const T&&) = delete; #endif // KEEPASSX_GLOBAL_H diff --git a/src/core/Group.cpp b/src/core/Group.cpp index 262a4af8..b8bca108 100644 --- a/src/core/Group.cpp +++ b/src/core/Group.cpp @@ -27,10 +27,10 @@ const int Group::DefaultIconNumber = 48; const int Group::RecycleBinIconNumber = 43; const QString Group::RootAutoTypeSequence = "{USERNAME}{TAB}{PASSWORD}{ENTER}"; -Group::CloneFlags Group::DefaultCloneFlags = static_cast( - Group::CloneNewUuid | Group::CloneResetTimeInfo | Group::CloneIncludeEntries); -Entry::CloneFlags Group::DefaultEntryCloneFlags = static_cast( - Entry::CloneNewUuid | Entry::CloneResetTimeInfo); +Group::CloneFlags Group::DefaultCloneFlags = + static_cast(Group::CloneNewUuid | Group::CloneResetTimeInfo | Group::CloneIncludeEntries); +Entry::CloneFlags Group::DefaultEntryCloneFlags = + static_cast(Entry::CloneNewUuid | Entry::CloneResetTimeInfo); Group::Group() : m_customData(new CustomData(this)) @@ -81,7 +81,8 @@ Group* Group::createRecycleBin() return recycleBin; } -template inline bool Group::set(P& property, const V& value) { +template inline bool Group::set(P& property, const V& value) +{ if (property != value) { property = value; emit modified(); @@ -123,14 +124,12 @@ QImage Group::icon() const { if (m_data.customIcon.isNull()) { return databaseIcons()->icon(m_data.iconNumber); - } - else { + } else { Q_ASSERT(m_db); if (m_db) { return m_db->metadata()->customIcon(m_data.customIcon); - } - else { + } else { return QImage(); } } @@ -140,14 +139,12 @@ QPixmap Group::iconPixmap() const { if (m_data.customIcon.isNull()) { return databaseIcons()->iconPixmap(m_data.iconNumber); - } - else { + } else { Q_ASSERT(m_db); if (m_db) { return m_db->metadata()->customIconPixmap(m_data.customIcon); - } - else { + } else { return QPixmap(); } } @@ -158,14 +155,12 @@ QPixmap Group::iconScaledPixmap() const if (m_data.customIcon.isNull()) { // built-in icons are 16x16 so don't need to be scaled return databaseIcons()->iconPixmap(m_data.iconNumber); - } - else { + } else { Q_ASSERT(m_db); if (m_db) { return m_db->metadata()->customIconScaledPixmap(m_data.customIcon); - } - else { + } else { return QPixmap(); } } @@ -401,9 +396,8 @@ void Group::setParent(Group* parent, int index) recCreateDelObjects(); // copy custom icon to the new database - if (!iconUuid().isNull() && parent->m_db - && m_db->metadata()->containsCustomIcon(iconUuid()) - && !parent->m_db->metadata()->containsCustomIcon(iconUuid())) { + if (!iconUuid().isNull() && parent->m_db && m_db->metadata()->containsCustomIcon(iconUuid()) + && !parent->m_db->metadata()->containsCustomIcon(iconUuid())) { parent->m_db->metadata()->addCustomIcon(iconUuid(), icon()); } } @@ -414,8 +408,7 @@ void Group::setParent(Group* parent, int index) emit aboutToAdd(this, index); Q_ASSERT(index <= parent->m_children.size()); parent->m_children.insert(index, this); - } - else { + } else { emit aboutToMove(this, parent, index); m_parent->m_children.removeAll(this); m_parent = parent; @@ -432,8 +425,7 @@ void Group::setParent(Group* parent, int index) if (!moveWithinDatabase) { emit added(); - } - else { + } else { emit moved(); } } @@ -457,7 +449,7 @@ QStringList Group::hierarchy() const const Group* group = this; const Group* parent = m_parent; hierarchy.prepend(group->name()); - + while (parent) { group = group->parentGroup(); parent = group->parentGroup(); @@ -733,7 +725,6 @@ void Group::merge(const Group* other) resolveGroupConflict(existingGroup, group); existingGroup->merge(group); } - } emit modified(); @@ -849,9 +840,9 @@ void Group::recSetDatabase(Database* db) disconnect(SIGNAL(dataChanged(Group*)), m_db); disconnect(SIGNAL(aboutToRemove(Group*)), m_db); disconnect(SIGNAL(removed()), m_db); - disconnect(SIGNAL(aboutToAdd(Group*,int)), m_db); + disconnect(SIGNAL(aboutToAdd(Group*, int)), m_db); disconnect(SIGNAL(added()), m_db); - disconnect(SIGNAL(aboutToMove(Group*,Group*,int)), m_db); + disconnect(SIGNAL(aboutToMove(Group*, Group*, int)), m_db); disconnect(SIGNAL(moved()), m_db); disconnect(SIGNAL(modified()), m_db); } @@ -869,9 +860,9 @@ void Group::recSetDatabase(Database* db) connect(this, SIGNAL(dataChanged(Group*)), db, SIGNAL(groupDataChanged(Group*))); connect(this, SIGNAL(aboutToRemove(Group*)), db, SIGNAL(groupAboutToRemove(Group*))); connect(this, SIGNAL(removed()), db, SIGNAL(groupRemoved())); - connect(this, SIGNAL(aboutToAdd(Group*,int)), db, SIGNAL(groupAboutToAdd(Group*,int))); + connect(this, SIGNAL(aboutToAdd(Group*, int)), db, SIGNAL(groupAboutToAdd(Group*, int))); connect(this, SIGNAL(added()), db, SIGNAL(groupAdded())); - connect(this, SIGNAL(aboutToMove(Group*,Group*,int)), db, SIGNAL(groupAboutToMove(Group*,Group*,int))); + connect(this, SIGNAL(aboutToMove(Group*, Group*, int)), db, SIGNAL(groupAboutToMove(Group*, Group*, int))); connect(this, SIGNAL(moved()), db, SIGNAL(groupMoved())); connect(this, SIGNAL(modified()), db, SIGNAL(modifiedImmediate())); } @@ -910,8 +901,7 @@ void Group::recCreateDelObjects() void Group::markOlderEntry(Entry* entry) { entry->attributes()->set( - "merged", - tr("older entry merged from database \"%1\"").arg(entry->group()->database()->metadata()->name())); + "merged", tr("older entry merged from database \"%1\"").arg(entry->group()->database()->metadata()->name())); } bool Group::resolveSearchingEnabled() const @@ -920,8 +910,7 @@ bool Group::resolveSearchingEnabled() const case Inherit: if (!m_parent) { return true; - } - else { + } else { return m_parent->resolveSearchingEnabled(); } case Enable: @@ -940,8 +929,7 @@ bool Group::resolveAutoTypeEnabled() const case Inherit: if (!m_parent) { return true; - } - else { + } else { return m_parent->resolveAutoTypeEnabled(); } case Enable: @@ -1003,13 +991,12 @@ void Group::resolveGroupConflict(Group* existingGroup, Group* otherGroup) existingGroup->setName(otherGroup->name()); existingGroup->setNotes(otherGroup->notes()); if (otherGroup->iconNumber() == 0) { - existingGroup->setIcon(otherGroup->iconUuid()); + existingGroup->setIcon(otherGroup->iconUuid()); } else { - existingGroup->setIcon(otherGroup->iconNumber()); + existingGroup->setIcon(otherGroup->iconNumber()); } existingGroup->setExpiryTime(otherGroup->timeInfo().expiryTime()); } - } QStringList Group::locate(QString locateTerm, QString currentPath) @@ -1059,5 +1046,4 @@ Entry* Group::addEntryWithPath(QString entryPath) entry->setGroup(group); return entry; - } diff --git a/src/core/Group.h b/src/core/Group.h index cc923e43..22220e42 100644 --- a/src/core/Group.h +++ b/src/core/Group.h @@ -24,9 +24,9 @@ #include #include +#include "core/CustomData.h" #include "core/Database.h" #include "core/Entry.h" -#include "core/CustomData.h" #include "core/TimeInfo.h" #include "core/Uuid.h" @@ -35,14 +35,26 @@ class Group : public QObject Q_OBJECT public: - enum TriState { Inherit, Enable, Disable }; - enum MergeMode { ModeInherit, KeepBoth, KeepNewer, KeepExisting }; + enum TriState + { + Inherit, + Enable, + Disable + }; + enum MergeMode + { + ModeInherit, + KeepBoth, + KeepNewer, + KeepExisting + }; - enum CloneFlag { - CloneNoFlags = 0, - CloneNewUuid = 1, // generate a random uuid for the clone - CloneResetTimeInfo = 2, // set all TimeInfo attributes to the current time - CloneIncludeEntries = 4, // clone the group entries + enum CloneFlag + { + CloneNoFlags = 0, + CloneNewUuid = 1, // generate a random uuid for the clone + CloneResetTimeInfo = 2, // set all TimeInfo attributes to the current time + CloneIncludeEntries = 4, // clone the group entries }; Q_DECLARE_FLAGS(CloneFlags, CloneFlag) diff --git a/src/core/InactivityTimer.cpp b/src/core/InactivityTimer.cpp index 0cfc8f0d..405970cc 100644 --- a/src/core/InactivityTimer.cpp +++ b/src/core/InactivityTimer.cpp @@ -56,9 +56,9 @@ bool InactivityTimer::eventFilter(QObject* watched, QEvent* event) { const QEvent::Type type = event->type(); - if ( (type >= QEvent::MouseButtonPress && type <= QEvent::KeyRelease) - || (type >= QEvent::HoverEnter && type <= QEvent::HoverMove) - || (type == QEvent::Wheel) ) { + if ((type >= QEvent::MouseButtonPress && type <= QEvent::KeyRelease) + || (type >= QEvent::HoverEnter && type <= QEvent::HoverMove) + || (type == QEvent::Wheel)) { m_timer->start(); } diff --git a/src/core/ListDeleter.h b/src/core/ListDeleter.h index 5687cbb1..6f289546 100644 --- a/src/core/ListDeleter.h +++ b/src/core/ListDeleter.h @@ -20,12 +20,15 @@ #include -template -class ListDeleter +template class ListDeleter { public: - inline explicit ListDeleter(QList* list) : m_list(list) {} - inline ~ListDeleter() { + inline explicit ListDeleter(QList* list) + : m_list(list) + { + } + inline ~ListDeleter() + { qDeleteAll(*m_list); } diff --git a/src/core/MacPasteboard.cpp b/src/core/MacPasteboard.cpp index 98dc6f7a..ae63ea4e 100644 --- a/src/core/MacPasteboard.cpp +++ b/src/core/MacPasteboard.cpp @@ -17,9 +17,13 @@ #include "MacPasteboard.h" -QString MacPasteboard::convertorName() { return QLatin1String("MacPasteboard"); } +QString MacPasteboard::convertorName() +{ + return QLatin1String("MacPasteboard"); +} -QString MacPasteboard::flavorFor(const QString& mimetype) { +QString MacPasteboard::flavorFor(const QString& mimetype) +{ if (mimetype == QLatin1String("text/plain")) { return QLatin1String("public.utf8-plain-text"); } else if (mimetype == QLatin1String("application/x-nspasteboard-concealed-type")) { @@ -38,15 +42,15 @@ QString MacPasteboard::flavorFor(const QString& mimetype) { if (cs == QLatin1String("system")) { return QLatin1String("public.utf8-plain-text"); - } else if (cs == QLatin1String("iso-10646-ucs-2") || - cs == QLatin1String("utf16")) { + } else if (cs == QLatin1String("iso-10646-ucs-2") || cs == QLatin1String("utf16")) { return QLatin1String("public.utf16-plain-text"); } } return QString(); } -QString MacPasteboard::mimeFor(QString flavor) { +QString MacPasteboard::mimeFor(QString flavor) +{ if (flavor == QLatin1String("public.utf8-plain-text")) return QLatin1String("text/plain"); if (flavor == QLatin1String("org.nspasteboard.ConcealedType")) @@ -56,13 +60,15 @@ QString MacPasteboard::mimeFor(QString flavor) { return QString(); } -bool MacPasteboard::canConvert(const QString& mimetype, QString flavor) { +bool MacPasteboard::canConvert(const QString& mimetype, QString flavor) +{ Q_UNUSED(mimetype); Q_UNUSED(flavor); return true; } -QVariant MacPasteboard::convertToMime(const QString& mimetype, QList data, QString flavor) { +QVariant MacPasteboard::convertToMime(const QString& mimetype, QList data, QString flavor) +{ if (data.count() > 1) qWarning("QMime::convertToMime: Cannot handle multiple member data"); const QByteArray& firstData = data.first(); @@ -74,13 +80,13 @@ QVariant MacPasteboard::convertToMime(const QString& mimetype, QList } else if (flavor == QLatin1String("public.utf16-plain-text")) { ret = QTextCodec::codecForName("UTF-16")->toUnicode(firstData); } else { - qWarning("QMime::convertToMime: unhandled mimetype: %s", - qPrintable(mimetype)); + qWarning("QMime::convertToMime: unhandled mimetype: %s", qPrintable(mimetype)); } return ret; } -QList MacPasteboard::convertFromMime(const QString&, QVariant data, QString flavor) { +QList MacPasteboard::convertFromMime(const QString&, QVariant data, QString flavor) +{ QList ret; QString string = data.toString(); if (flavor == QLatin1String("public.utf8-plain-text")) @@ -91,4 +97,3 @@ QList MacPasteboard::convertFromMime(const QString&, QVariant data, ret.append(QTextCodec::codecForName("UTF-16")->fromUnicode(string)); return ret; } - diff --git a/src/core/MacPasteboard.h b/src/core/MacPasteboard.h index d471a096..f2a71e73 100644 --- a/src/core/MacPasteboard.h +++ b/src/core/MacPasteboard.h @@ -19,20 +19,23 @@ #define KEEPASSXC_MACPASTEBOARD_H #include -#include #include +#include class MacPasteboard : public QObject, public QMacPasteboardMime { public: - explicit MacPasteboard() : QMacPasteboardMime(MIME_ALL) {} + explicit MacPasteboard() + : QMacPasteboardMime(MIME_ALL) + { + } QString convertorName() override; - bool canConvert(const QString &mime, QString flav) override; + bool canConvert(const QString& mime, QString flav) override; QString mimeFor(QString flav) override; - QString flavorFor(const QString &mime) override; - QVariant convertToMime(const QString &mime, QList data, QString flav) override; - QList convertFromMime(const QString &mime, QVariant data, QString flav) override; + QString flavorFor(const QString& mime) override; + QVariant convertToMime(const QString& mime, QList data, QString flav) override; + QList convertFromMime(const QString& mime, QVariant data, QString flav) override; }; #endif // KEEPASSXC_MACPASTEBOARD_H diff --git a/src/core/Metadata.cpp b/src/core/Metadata.cpp index 9da2f30d..f8b0fd2f 100644 --- a/src/core/Metadata.cpp +++ b/src/core/Metadata.cpp @@ -15,8 +15,8 @@ * along with this program. If not, see . */ -#include #include "Metadata.h" +#include #include "core/Entry.h" #include "core/Group.h" @@ -61,13 +61,13 @@ template bool Metadata::set(P& property, const V& value) property = value; emit modified(); return true; - } - else { + } else { return false; } } -template bool Metadata::set(P& property, const V& value, QDateTime& dateTime) { +template bool Metadata::set(P& property, const V& value, QDateTime& dateTime) +{ if (property != value) { property = value; if (m_updateDatetime) { @@ -75,8 +75,7 @@ template bool Metadata::set(P& property, const V& value, QDat } emit modified(); return true; - } - else { + } else { return false; } } @@ -402,10 +401,8 @@ void Metadata::addCustomIconScaled(const Uuid& uuid, const QImage& icon) // scale down to 128x128 if icon is larger if (icon.width() > 128 || icon.height() > 128) { - iconScaled = icon.scaled(QSize(128, 128), Qt::KeepAspectRatio, - Qt::SmoothTransformation); - } - else { + iconScaled = icon.scaled(QSize(128, 128), Qt::KeepAspectRatio, Qt::SmoothTransformation); + } else { iconScaled = icon; } @@ -433,7 +430,7 @@ void Metadata::removeCustomIcon(const Uuid& uuid) emit modified(); } -Uuid Metadata::findCustomIcon(const QImage &candidate) +Uuid Metadata::findCustomIcon(const QImage& candidate) { QByteArray hash = hashImage(candidate); return m_customIconsHashes.value(hash, Uuid()); diff --git a/src/core/Metadata.h b/src/core/Metadata.h index a52cb0a7..a40fb502 100644 --- a/src/core/Metadata.h +++ b/src/core/Metadata.h @@ -26,8 +26,8 @@ #include #include -#include "core/Uuid.h" #include "core/CustomData.h" +#include "core/Uuid.h" class Database; class Group; diff --git a/src/core/PassphraseGenerator.cpp b/src/core/PassphraseGenerator.cpp index 88871eb8..f972e0ef 100644 --- a/src/core/PassphraseGenerator.cpp +++ b/src/core/PassphraseGenerator.cpp @@ -17,12 +17,12 @@ #include "PassphraseGenerator.h" -#include #include #include +#include -#include "crypto/Random.h" #include "core/FilePath.h" +#include "crypto/Random.h" const char* PassphraseGenerator::DefaultSeparator = " "; const char* PassphraseGenerator::DefaultWordList = "eff_large.wordlist"; @@ -52,7 +52,6 @@ void PassphraseGenerator::setWordCount(int wordCount) // safe default if something goes wrong m_wordCount = DefaultWordCount; } - } void PassphraseGenerator::setWordList(const QString& path) @@ -82,7 +81,8 @@ void PassphraseGenerator::setDefaultWordList() setWordList(path); } -void PassphraseGenerator::setWordSeparator(const QString& separator) { +void PassphraseGenerator::setWordSeparator(const QString& separator) +{ m_separator = separator; } @@ -91,7 +91,7 @@ QString PassphraseGenerator::generatePassphrase() const Q_ASSERT(isValid()); // In case there was an error loading the wordlist - if(m_wordlist.length() == 0) { + if (m_wordlist.length() == 0) { return QString(); } @@ -107,7 +107,7 @@ QString PassphraseGenerator::generatePassphrase() const bool PassphraseGenerator::isValid() const { if (m_wordCount == 0) { - return false; + return false; } return m_wordlist.size() >= 1000; diff --git a/src/core/PasswordGenerator.cpp b/src/core/PasswordGenerator.cpp index 740fb546..00984d31 100644 --- a/src/core/PasswordGenerator.cpp +++ b/src/core/PasswordGenerator.cpp @@ -45,7 +45,7 @@ void PasswordGenerator::setLength(int length) void PasswordGenerator::setCharClasses(const CharClasses& classes) { if (classes == 0) { - m_classes = DefaultCharset; + m_classes = DefaultCharset; return; } m_classes = classes; @@ -92,8 +92,7 @@ QString PasswordGenerator::generatePassword() const password[i] = password[j]; password[j] = tmp; } - } - else { + } else { for (int i = 0; i < m_length; i++) { int pos = randomGen()->randomUInt(passwordChars.size()); @@ -110,7 +109,7 @@ int PasswordGenerator::getbits() const int bits = 0; QVector passwordChars; - for (const PasswordGroup& group: groups) { + for (const PasswordGroup& group : groups) { bits += group.size(); } @@ -119,13 +118,11 @@ int PasswordGenerator::getbits() const return bits; } - bool PasswordGenerator::isValid() const { if (m_classes == 0) { return false; - } - else if (m_length == 0) { + } else if (m_length == 0) { return false; } diff --git a/src/core/PasswordGenerator.h b/src/core/PasswordGenerator.h index 15a0dcef..d6866b5e 100644 --- a/src/core/PasswordGenerator.h +++ b/src/core/PasswordGenerator.h @@ -30,20 +30,20 @@ class PasswordGenerator public: enum CharClass { - LowerLetters = 0x1, - UpperLetters = 0x2, - Numbers = 0x4, + LowerLetters = 0x1, + UpperLetters = 0x2, + Numbers = 0x4, SpecialCharacters = 0x8, - EASCII = 0x10, - DefaultCharset = LowerLetters | UpperLetters | Numbers + EASCII = 0x10, + DefaultCharset = LowerLetters | UpperLetters | Numbers }; Q_DECLARE_FLAGS(CharClasses, CharClass) enum GeneratorFlag { - ExcludeLookAlike = 0x1, + ExcludeLookAlike = 0x1, CharFromEveryGroup = 0x2, - DefaultFlags = ExcludeLookAlike | CharFromEveryGroup + DefaultFlags = ExcludeLookAlike | CharFromEveryGroup }; Q_DECLARE_FLAGS(GeneratorFlags, GeneratorFlag) diff --git a/src/core/ScreenLockListener.cpp b/src/core/ScreenLockListener.cpp index eb78cd60..2c1ba055 100644 --- a/src/core/ScreenLockListener.cpp +++ b/src/core/ScreenLockListener.cpp @@ -18,11 +18,13 @@ #include "ScreenLockListener.h" #include "ScreenLockListenerPrivate.h" -ScreenLockListener::ScreenLockListener(QWidget* parent): - QObject(parent){ +ScreenLockListener::ScreenLockListener(QWidget* parent) + : QObject(parent) +{ m_listener = ScreenLockListenerPrivate::instance(parent); - connect(m_listener,SIGNAL(screenLocked()), this,SIGNAL(screenLocked())); + connect(m_listener, SIGNAL(screenLocked()), this, SIGNAL(screenLocked())); } -ScreenLockListener::~ScreenLockListener(){ +ScreenLockListener::~ScreenLockListener() +{ } diff --git a/src/core/ScreenLockListener.h b/src/core/ScreenLockListener.h index b4eb81e0..107d342a 100644 --- a/src/core/ScreenLockListener.h +++ b/src/core/ScreenLockListener.h @@ -21,7 +21,8 @@ class ScreenLockListenerPrivate; -class ScreenLockListener : public QObject { +class ScreenLockListener : public QObject +{ Q_OBJECT public: diff --git a/src/core/ScreenLockListenerDBus.cpp b/src/core/ScreenLockListenerDBus.cpp index 03eed58a..5c57861b 100644 --- a/src/core/ScreenLockListenerDBus.cpp +++ b/src/core/ScreenLockListenerDBus.cpp @@ -22,60 +22,54 @@ #include #include -ScreenLockListenerDBus::ScreenLockListenerDBus(QWidget *parent): - ScreenLockListenerPrivate(parent) +ScreenLockListenerDBus::ScreenLockListenerDBus(QWidget* parent) + : ScreenLockListenerPrivate(parent) { QDBusConnection sessionBus = QDBusConnection::sessionBus(); QDBusConnection systemBus = QDBusConnection::systemBus(); - sessionBus.connect( - "org.freedesktop.ScreenSaver", // service - "/org/freedesktop/ScreenSaver", // path - "org.freedesktop.ScreenSaver", // interface - "ActiveChanged", // signal name - this, //receiver - SLOT(freedesktopScreenSaver(bool))); + sessionBus.connect("org.freedesktop.ScreenSaver", // service + "/org/freedesktop/ScreenSaver", // path + "org.freedesktop.ScreenSaver", // interface + "ActiveChanged", // signal name + this, // receiver + SLOT(freedesktopScreenSaver(bool))); - sessionBus.connect( - "org.gnome.ScreenSaver", // service - "/org/gnome/ScreenSaver", // path - "org.gnome.ScreenSaver", // interface - "ActiveChanged", // signal name - this, //receiver - SLOT(freedesktopScreenSaver(bool))); + sessionBus.connect("org.gnome.ScreenSaver", // service + "/org/gnome/ScreenSaver", // path + "org.gnome.ScreenSaver", // interface + "ActiveChanged", // signal name + this, // receiver + SLOT(freedesktopScreenSaver(bool))); - sessionBus.connect( - "org.gnome.SessionManager", // service - "/org/gnome/SessionManager/Presence", // path - "org.gnome.SessionManager.Presence", // interface - "StatusChanged", // signal name - this, //receiver - SLOT(gnomeSessionStatusChanged(uint))); + sessionBus.connect("org.gnome.SessionManager", // service + "/org/gnome/SessionManager/Presence", // path + "org.gnome.SessionManager.Presence", // interface + "StatusChanged", // signal name + this, // receiver + SLOT(gnomeSessionStatusChanged(uint))); - systemBus.connect( - "org.freedesktop.login1", // service - "/org/freedesktop/login1", // path - "org.freedesktop.login1.Manager", // interface - "PrepareForSleep", // signal name - this, //receiver - SLOT(logindPrepareForSleep(bool))); + systemBus.connect("org.freedesktop.login1", // service + "/org/freedesktop/login1", // path + "org.freedesktop.login1.Manager", // interface + "PrepareForSleep", // signal name + this, // receiver + SLOT(logindPrepareForSleep(bool))); QString sessionId = QProcessEnvironment::systemEnvironment().value("XDG_SESSION_ID"); - systemBus.connect( - "", // service - QString("/org/freedesktop/login1/session/") + sessionId, // path - "org.freedesktop.login1.Session", // interface - "Lock", // signal name - this, //receiver - SLOT(unityLocked())); + systemBus.connect("", // service + QString("/org/freedesktop/login1/session/") + sessionId, // path + "org.freedesktop.login1.Session", // interface + "Lock", // signal name + this, // receiver + SLOT(unityLocked())); - sessionBus.connect( - "com.canonical.Unity", // service - "/com/canonical/Unity/Session", // path - "com.canonical.Unity.Session", // interface - "Locked", // signal name - this, //receiver - SLOT(unityLocked())); + sessionBus.connect("com.canonical.Unity", // service + "/com/canonical/Unity/Session", // path + "com.canonical.Unity.Session", // interface + "Locked", // signal name + this, // receiver + SLOT(unityLocked())); } void ScreenLockListenerDBus::gnomeSessionStatusChanged(uint status) diff --git a/src/core/ScreenLockListenerDBus.h b/src/core/ScreenLockListenerDBus.h index 72f308f7..dd6f5ea8 100644 --- a/src/core/ScreenLockListenerDBus.h +++ b/src/core/ScreenLockListenerDBus.h @@ -17,15 +17,15 @@ #ifndef SCREENLOCKLISTENERDBUS_H #define SCREENLOCKLISTENERDBUS_H +#include "ScreenLockListenerPrivate.h" #include #include -#include "ScreenLockListenerPrivate.h" class ScreenLockListenerDBus : public ScreenLockListenerPrivate { Q_OBJECT public: - explicit ScreenLockListenerDBus(QWidget *parent = 0); + explicit ScreenLockListenerDBus(QWidget* parent = 0); private slots: void gnomeSessionStatusChanged(uint status); diff --git a/src/core/ScreenLockListenerPrivate.cpp b/src/core/ScreenLockListenerPrivate.cpp index b36b9a33..1371a0c9 100644 --- a/src/core/ScreenLockListenerPrivate.cpp +++ b/src/core/ScreenLockListenerPrivate.cpp @@ -25,7 +25,7 @@ #endif ScreenLockListenerPrivate::ScreenLockListenerPrivate(QWidget* parent) - : QObject(parent) + : QObject(parent) { } diff --git a/src/core/ScreenLockListenerWin.cpp b/src/core/ScreenLockListenerWin.cpp index 80fa3289..05d01f4c 100644 --- a/src/core/ScreenLockListenerWin.cpp +++ b/src/core/ScreenLockListenerWin.cpp @@ -25,7 +25,7 @@ * See https://msdn.microsoft.com/en-us/library/aa383841(v=vs.85).aspx * See https://blogs.msdn.microsoft.com/oldnewthing/20060104-50/?p=32783 */ -ScreenLockListenerWin::ScreenLockListenerWin(QWidget* parent) +ScreenLockListenerWin::ScreenLockListenerWin(QWidget* parent) : ScreenLockListenerPrivate(parent) , QAbstractNativeEventFilter() { @@ -36,20 +36,17 @@ ScreenLockListenerWin::ScreenLockListenerWin(QWidget* parent) // This call requests a notification from windows when a laptop is closed HPOWERNOTIFY hPnotify = RegisterPowerSettingNotification( - reinterpret_cast(parent->winId()), - &GUID_LIDSWITCH_STATE_CHANGE, DEVICE_NOTIFY_WINDOW_HANDLE); + reinterpret_cast(parent->winId()), &GUID_LIDSWITCH_STATE_CHANGE, DEVICE_NOTIFY_WINDOW_HANDLE); m_powerNotificationHandle = reinterpret_cast(hPnotify); // This call requests a notification for session changes - if (!WTSRegisterSessionNotification( - reinterpret_cast(parent->winId()), - NOTIFY_FOR_THIS_SESSION)) { + if (!WTSRegisterSessionNotification(reinterpret_cast(parent->winId()), NOTIFY_FOR_THIS_SESSION)) { } } ScreenLockListenerWin::~ScreenLockListenerWin() { - HWND h= reinterpret_cast(static_cast(parent())->winId()); + HWND h = reinterpret_cast(static_cast(parent())->winId()); WTSUnRegisterSessionNotification(h); if (m_powerNotificationHandle) { diff --git a/src/core/ScreenLockListenerWin.h b/src/core/ScreenLockListenerWin.h index 6a8380ef..0778c99d 100644 --- a/src/core/ScreenLockListenerWin.h +++ b/src/core/ScreenLockListenerWin.h @@ -17,9 +17,9 @@ #ifndef SCREENLOCKLISTENERWIN_H #define SCREENLOCKLISTENERWIN_H +#include #include #include -#include #include "ScreenLockListenerPrivate.h" @@ -29,10 +29,10 @@ class ScreenLockListenerWin : public ScreenLockListenerPrivate, public QAbstract public: explicit ScreenLockListenerWin(QWidget* parent = 0); ~ScreenLockListenerWin(); - virtual bool nativeEventFilter(const QByteArray &eventType, void* message, long*) override; + virtual bool nativeEventFilter(const QByteArray& eventType, void* message, long*) override; private: - void* m_powerNotificationHandle ; + void* m_powerNotificationHandle; }; #endif // SCREENLOCKLISTENERWIN_H diff --git a/src/core/SignalMultiplexer.cpp b/src/core/SignalMultiplexer.cpp index 0f99b8e6..d1ed89e3 100644 --- a/src/core/SignalMultiplexer.cpp +++ b/src/core/SignalMultiplexer.cpp @@ -131,8 +131,7 @@ void SignalMultiplexer::connect(const Connection& con) if (con.sender) { QObject::connect(con.sender, con.signal, m_currentObject, con.slot); - } - else { + } else { QObject::connect(m_currentObject, con.signal, con.receiver, con.slot); } } @@ -143,8 +142,7 @@ void SignalMultiplexer::disconnect(const Connection& con) if (con.sender) { QObject::disconnect(con.sender, con.signal, m_currentObject, con.slot); - } - else { + } else { QObject::disconnect(m_currentObject, con.signal, con.receiver, con.slot); } } diff --git a/src/core/TimeDelta.cpp b/src/core/TimeDelta.cpp index e2dbdac4..a5331736 100644 --- a/src/core/TimeDelta.cpp +++ b/src/core/TimeDelta.cpp @@ -19,10 +19,9 @@ #include -QDateTime operator+(const QDateTime& dateTime, const TimeDelta& delta) { - return dateTime.addDays(delta.getDays()) - .addMonths(delta.getMonths()) - .addYears(delta.getYears()); +QDateTime operator+(const QDateTime& dateTime, const TimeDelta& delta) +{ + return dateTime.addDays(delta.getDays()).addMonths(delta.getMonths()).addYears(delta.getYears()); } TimeDelta TimeDelta::fromDays(int days) diff --git a/src/core/Tools.cpp b/src/core/Tools.cpp index b9e4be8e..47a0df03 100644 --- a/src/core/Tools.cpp +++ b/src/core/Tools.cpp @@ -20,16 +20,16 @@ #include "Tools.h" #include -#include #include +#include #include #include #include #ifdef Q_OS_WIN +#include // for SetSecurityInfo() #include // for Sleep(), SetDllDirectoryA(), SetSearchPathMode(), ... -#include // for SetSecurityInfo() #endif #ifdef Q_OS_UNIX @@ -47,314 +47,298 @@ #endif #ifdef HAVE_PT_DENY_ATTACH -#include #include +#include #endif -namespace Tools { - -QString humanReadableFileSize(qint64 bytes) +namespace Tools { - double size = bytes; - QStringList units = QStringList() << "B" << "KiB" << "MiB" << "GiB"; - int i = 0; - int maxI = units.size() - 1; + QString humanReadableFileSize(qint64 bytes) + { + double size = bytes; - while ((size >= 1024) && (i < maxI)) { - size /= 1024; - i++; + QStringList units = QStringList() << "B" + << "KiB" + << "MiB" + << "GiB"; + int i = 0; + int maxI = units.size() - 1; + + while ((size >= 1024) && (i < maxI)) { + size /= 1024; + i++; + } + + return QString("%1 %2").arg(QLocale().toString(size, 'f', 2), units.at(i)); } - return QString("%1 %2").arg(QLocale().toString(size, 'f', 2), units.at(i)); -} + bool hasChild(const QObject* parent, const QObject* child) + { + if (!parent || !child) { + return false; + } -bool hasChild(const QObject* parent, const QObject* child) -{ - if (!parent || !child) { + const QObjectList children = parent->children(); + for (QObject* c : children) { + if (child == c || hasChild(c, child)) { + return true; + } + } return false; } - const QObjectList children = parent->children(); - for (QObject* c : children) { - if (child == c || hasChild(c, child)) { + bool readFromDevice(QIODevice* device, QByteArray& data, int size) + { + QByteArray buffer; + buffer.resize(size); + + qint64 readResult = device->read(buffer.data(), size); + if (readResult == -1) { + return false; + } else { + buffer.resize(readResult); + data = buffer; return true; } } - return false; -} -bool readFromDevice(QIODevice* device, QByteArray& data, int size) -{ - QByteArray buffer; - buffer.resize(size); + bool readAllFromDevice(QIODevice* device, QByteArray& data) + { + QByteArray result; + qint64 readBytes = 0; + qint64 readResult; + do { + result.resize(result.size() + 16384); + readResult = device->read(result.data() + readBytes, result.size() - readBytes); + if (readResult > 0) { + readBytes += readResult; + } + } while (readResult > 0); - qint64 readResult = device->read(buffer.data(), size); - if (readResult == -1) { - return false; - } - else { - buffer.resize(readResult); - data = buffer; - return true; - } -} - -bool readAllFromDevice(QIODevice* device, QByteArray& data) -{ - QByteArray result; - qint64 readBytes = 0; - qint64 readResult; - do { - result.resize(result.size() + 16384); - readResult = device->read(result.data() + readBytes, result.size() - readBytes); - if (readResult > 0) { - readBytes += readResult; + if (readResult == -1) { + return false; + } else { + result.resize(static_cast(readBytes)); + data = result; + return true; } - } while (readResult > 0); - - if (readResult == -1) { - return false; } - else { - result.resize(static_cast(readBytes)); - data = result; - return true; + + QString imageReaderFilter() + { + const QList formats = QImageReader::supportedImageFormats(); + QStringList formatsStringList; + + for (const QByteArray& format : formats) { + for (int i = 0; i < format.size(); i++) { + if (!QChar(format.at(i)).isLetterOrNumber()) { + continue; + } + } + + formatsStringList.append("*." + QString::fromLatin1(format).toLower()); + } + + return formatsStringList.join(" "); } -} -QString imageReaderFilter() -{ - const QList formats = QImageReader::supportedImageFormats(); - QStringList formatsStringList; - - for (const QByteArray& format : formats) { - for (int i = 0; i < format.size(); i++) { - if (!QChar(format.at(i)).isLetterOrNumber()) { - continue; + bool isHex(const QByteArray& ba) + { + for (char c : ba) { + if (!((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'))) { + return false; } } - formatsStringList.append("*." + QString::fromLatin1(format).toLower()); + return true; } - return formatsStringList.join(" "); -} + bool isBase64(const QByteArray& ba) + { + QRegExp regexp( + "^(?:[a-z0-9+/]{4})*(?:[a-z0-9+/]{3}=|[a-z0-9+/]{2}==)?$", Qt::CaseInsensitive, QRegExp::RegExp2); -bool isHex(const QByteArray& ba) -{ - for (char c : ba) { - if ( !( (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F') ) ) { - return false; + QString base64 = QString::fromLatin1(ba.constData(), ba.size()); + + return regexp.exactMatch(base64); + } + + void sleep(int ms) + { + Q_ASSERT(ms >= 0); + + if (ms == 0) { + return; } - } - - return true; -} - -bool isBase64(const QByteArray& ba) -{ - QRegExp regexp("^(?:[a-z0-9+/]{4})*(?:[a-z0-9+/]{3}=|[a-z0-9+/]{2}==)?$", - Qt::CaseInsensitive, QRegExp::RegExp2); - - QString base64 = QString::fromLatin1(ba.constData(), ba.size()); - - return regexp.exactMatch(base64); -} - -void sleep(int ms) -{ - Q_ASSERT(ms >= 0); - - if (ms == 0) { - return; - } #ifdef Q_OS_WIN - Sleep(uint(ms)); + Sleep(uint(ms)); #else - timespec ts; - ts.tv_sec = ms / 1000; - ts.tv_nsec = (ms % 1000) * 1000 * 1000; - nanosleep(&ts, nullptr); + timespec ts; + ts.tv_sec = ms / 1000; + ts.tv_nsec = (ms % 1000) * 1000 * 1000; + nanosleep(&ts, nullptr); #endif -} - -void wait(int ms) -{ - Q_ASSERT(ms >= 0); - - if (ms == 0) { - return; } - QElapsedTimer timer; - timer.start(); + void wait(int ms) + { + Q_ASSERT(ms >= 0); - if (ms <= 50) { - QCoreApplication::processEvents(QEventLoop::AllEvents, ms); - sleep(qMax(ms - static_cast(timer.elapsed()), 0)); - } - else { - int timeLeft; - do { - timeLeft = ms - timer.elapsed(); - if (timeLeft > 0) { - QCoreApplication::processEvents(QEventLoop::AllEvents, timeLeft); - sleep(10); - } - } while (!timer.hasExpired(ms)); - } -} + if (ms == 0) { + return; + } -void disableCoreDumps() -{ - // default to true - // there is no point in printing a warning if this is not implemented on the platform - bool success = true; + QElapsedTimer timer; + timer.start(); + + if (ms <= 50) { + QCoreApplication::processEvents(QEventLoop::AllEvents, ms); + sleep(qMax(ms - static_cast(timer.elapsed()), 0)); + } else { + int timeLeft; + do { + timeLeft = ms - timer.elapsed(); + if (timeLeft > 0) { + QCoreApplication::processEvents(QEventLoop::AllEvents, timeLeft); + sleep(10); + } + } while (!timer.hasExpired(ms)); + } + } + + void disableCoreDumps() + { + // default to true + // there is no point in printing a warning if this is not implemented on the platform + bool success = true; #if defined(HAVE_RLIMIT_CORE) - struct rlimit limit; - limit.rlim_cur = 0; - limit.rlim_max = 0; - success = success && (setrlimit(RLIMIT_CORE, &limit) == 0); + struct rlimit limit; + limit.rlim_cur = 0; + limit.rlim_max = 0; + success = success && (setrlimit(RLIMIT_CORE, &limit) == 0); #endif #if defined(HAVE_PR_SET_DUMPABLE) - success = success && (prctl(PR_SET_DUMPABLE, 0) == 0); + success = success && (prctl(PR_SET_DUMPABLE, 0) == 0); #endif - // Mac OS X +// Mac OS X #ifdef HAVE_PT_DENY_ATTACH - success = success && (ptrace(PT_DENY_ATTACH, 0, 0, 0) == 0); + success = success && (ptrace(PT_DENY_ATTACH, 0, 0, 0) == 0); #endif #ifdef Q_OS_WIN - success = success && createWindowsDACL(); + success = success && createWindowsDACL(); #endif - if (!success) { - qWarning("Unable to disable core dumps."); + if (!success) { + qWarning("Unable to disable core dumps."); + } } -} -void setupSearchPaths() -{ + void setupSearchPaths() + { #ifdef Q_OS_WIN - // Make sure Windows doesn't load DLLs from the current working directory - SetDllDirectoryA(""); - SetSearchPathMode(BASE_SEARCH_PATH_ENABLE_SAFE_SEARCHMODE); + // Make sure Windows doesn't load DLLs from the current working directory + SetDllDirectoryA(""); + SetSearchPathMode(BASE_SEARCH_PATH_ENABLE_SAFE_SEARCHMODE); #endif -} + } -// -// This function grants the user associated with the process token minimal access rights and -// denies everything else on Windows. This includes PROCESS_QUERY_INFORMATION and -// PROCESS_VM_READ access rights that are required for MiniDumpWriteDump() or ReadProcessMemory(). -// We do this using a discretionary access control list (DACL). Effectively this prevents -// crash dumps and disallows other processes from accessing our memory. This works as long -// as you do not have admin privileges, since then you are able to grant yourself the -// SeDebugPrivilege or SeTakeOwnershipPrivilege and circumvent the DACL. -// -bool createWindowsDACL() -{ - bool bSuccess = false; + // + // This function grants the user associated with the process token minimal access rights and + // denies everything else on Windows. This includes PROCESS_QUERY_INFORMATION and + // PROCESS_VM_READ access rights that are required for MiniDumpWriteDump() or ReadProcessMemory(). + // We do this using a discretionary access control list (DACL). Effectively this prevents + // crash dumps and disallows other processes from accessing our memory. This works as long + // as you do not have admin privileges, since then you are able to grant yourself the + // SeDebugPrivilege or SeTakeOwnershipPrivilege and circumvent the DACL. + // + bool createWindowsDACL() + { + bool bSuccess = false; #ifdef Q_OS_WIN - // Process token and user - HANDLE hToken = nullptr; - PTOKEN_USER pTokenUser = nullptr; - DWORD cbBufferSize = 0; + // Process token and user + HANDLE hToken = nullptr; + PTOKEN_USER pTokenUser = nullptr; + DWORD cbBufferSize = 0; - // Access control list - PACL pACL = nullptr; - DWORD cbACL = 0; + // Access control list + PACL pACL = nullptr; + DWORD cbACL = 0; - // Open the access token associated with the calling process - if (!OpenProcessToken( - GetCurrentProcess(), - TOKEN_QUERY, - &hToken - )) { - goto Cleanup; - } + // Open the access token associated with the calling process + if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) { + goto Cleanup; + } - // Retrieve the token information in a TOKEN_USER structure - GetTokenInformation( - hToken, - TokenUser, - nullptr, - 0, - &cbBufferSize - ); + // Retrieve the token information in a TOKEN_USER structure + GetTokenInformation(hToken, TokenUser, nullptr, 0, &cbBufferSize); - pTokenUser = static_cast(HeapAlloc(GetProcessHeap(), 0, cbBufferSize)); - if (pTokenUser == nullptr) { - goto Cleanup; - } + pTokenUser = static_cast(HeapAlloc(GetProcessHeap(), 0, cbBufferSize)); + if (pTokenUser == nullptr) { + goto Cleanup; + } - if (!GetTokenInformation( - hToken, - TokenUser, - pTokenUser, - cbBufferSize, - &cbBufferSize - )) { - goto Cleanup; - } + if (!GetTokenInformation(hToken, TokenUser, pTokenUser, cbBufferSize, &cbBufferSize)) { + goto Cleanup; + } - if (!IsValidSid(pTokenUser->User.Sid)) { - goto Cleanup; - } + if (!IsValidSid(pTokenUser->User.Sid)) { + goto Cleanup; + } - // Calculate the amount of memory that must be allocated for the DACL - cbACL = sizeof(ACL) - + sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(pTokenUser->User.Sid); + // Calculate the amount of memory that must be allocated for the DACL + cbACL = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(pTokenUser->User.Sid); - // Create and initialize an ACL - pACL = static_cast(HeapAlloc(GetProcessHeap(), 0, cbACL)); - if (pACL == nullptr) { - goto Cleanup; - } + // Create and initialize an ACL + pACL = static_cast(HeapAlloc(GetProcessHeap(), 0, cbACL)); + if (pACL == nullptr) { + goto Cleanup; + } - if (!InitializeAcl(pACL, cbACL, ACL_REVISION)) { - goto Cleanup; - } + if (!InitializeAcl(pACL, cbACL, ACL_REVISION)) { + goto Cleanup; + } - // Add allowed access control entries, everything else is denied - if (!AddAccessAllowedAce( - pACL, - ACL_REVISION, - SYNCHRONIZE | PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_TERMINATE, // same as protected process - pTokenUser->User.Sid // pointer to the trustee's SID - )) { - goto Cleanup; - } + // Add allowed access control entries, everything else is denied + if (!AddAccessAllowedAce( + pACL, + ACL_REVISION, + SYNCHRONIZE | PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_TERMINATE, // same as protected process + pTokenUser->User.Sid // pointer to the trustee's SID + )) { + goto Cleanup; + } - // Set discretionary access control list - bSuccess = ERROR_SUCCESS == SetSecurityInfo( - GetCurrentProcess(), // object handle - SE_KERNEL_OBJECT, // type of object - DACL_SECURITY_INFORMATION, // change only the objects DACL - nullptr, nullptr, // do not change owner or group - pACL, // DACL specified - nullptr // do not change SACL - ); + // Set discretionary access control list + bSuccess = ERROR_SUCCESS == SetSecurityInfo(GetCurrentProcess(), // object handle + SE_KERNEL_OBJECT, // type of object + DACL_SECURITY_INFORMATION, // change only the objects DACL + nullptr, + nullptr, // do not change owner or group + pACL, // DACL specified + nullptr // do not change SACL + ); -Cleanup: + Cleanup: - if (pACL != nullptr) { - HeapFree(GetProcessHeap(), 0, pACL); - } - if (pTokenUser != nullptr) { - HeapFree(GetProcessHeap(), 0, pTokenUser); - } - if (hToken != nullptr) { - CloseHandle(hToken); - } + if (pACL != nullptr) { + HeapFree(GetProcessHeap(), 0, pACL); + } + if (pTokenUser != nullptr) { + HeapFree(GetProcessHeap(), 0, pTokenUser); + } + if (hToken != nullptr) { + CloseHandle(hToken); + } #endif - return bSuccess; -} + return bSuccess; + } } // namespace Tools diff --git a/src/core/Tools.h b/src/core/Tools.h index b6fa49c0..b1176007 100644 --- a/src/core/Tools.h +++ b/src/core/Tools.h @@ -29,33 +29,33 @@ class QIODevice; -namespace Tools { - -QString humanReadableFileSize(qint64 bytes); -bool hasChild(const QObject* parent, const QObject* child); -bool readFromDevice(QIODevice* device, QByteArray& data, int size = 16384); -bool readAllFromDevice(QIODevice* device, QByteArray& data); -QString imageReaderFilter(); -bool isHex(const QByteArray& ba); -bool isBase64(const QByteArray& ba); -void sleep(int ms); -void wait(int ms); -void disableCoreDumps(); -void setupSearchPaths(); -bool createWindowsDACL(); - -template -RandomAccessIterator binaryFind(RandomAccessIterator begin, RandomAccessIterator end, const T& value) +namespace Tools { - RandomAccessIterator it = std::lower_bound(begin, end, value); - if ((it == end) || (value < *it)) { - return end; + QString humanReadableFileSize(qint64 bytes); + bool hasChild(const QObject* parent, const QObject* child); + bool readFromDevice(QIODevice* device, QByteArray& data, int size = 16384); + bool readAllFromDevice(QIODevice* device, QByteArray& data); + QString imageReaderFilter(); + bool isHex(const QByteArray& ba); + bool isBase64(const QByteArray& ba); + void sleep(int ms); + void wait(int ms); + void disableCoreDumps(); + void setupSearchPaths(); + bool createWindowsDACL(); + + template + RandomAccessIterator binaryFind(RandomAccessIterator begin, RandomAccessIterator end, const T& value) + { + RandomAccessIterator it = std::lower_bound(begin, end, value); + + if ((it == end) || (value < *it)) { + return end; + } else { + return it; + } } - else { - return it; - } -} } // namespace Tools diff --git a/src/core/Translator.cpp b/src/core/Translator.cpp index 34bc7c2e..595dadfa 100644 --- a/src/core/Translator.cpp +++ b/src/core/Translator.cpp @@ -22,8 +22,8 @@ #include #include #include -#include #include +#include #include "config-keepassx.h" #include "core/Config.h" @@ -47,8 +47,7 @@ void Translator::installTranslators() #ifdef QT_DEBUG QString("%1/share/translations").arg(KEEPASSX_BINARY_DIR), #endif - filePath()->dataPath("translations") - }; + filePath()->dataPath("translations")}; bool translationsLoaded = false; for (const QString& path : paths) { @@ -72,10 +71,9 @@ QList> Translator::availableLanguages() #ifdef QT_DEBUG QString("%1/share/translations").arg(KEEPASSX_BINARY_DIR), #endif - filePath()->dataPath("translations") - }; + filePath()->dataPath("translations")}; - QList > languages; + QList> languages; languages.append(QPair("system", "System default")); QRegularExpression regExp("^keepassx_([a-zA-Z_]+)\\.qm$", QRegularExpression::CaseInsensitiveOption); @@ -138,7 +136,8 @@ bool Translator::installQtTranslator(const QString& language, const QString& pat QScopedPointer qtTranslator(new QTranslator(qApp)); if (qtTranslator->load(QString("qtbase_%1").arg(language), path)) { return QCoreApplication::installTranslator(qtTranslator.take()); - } else if (qtTranslator->load(QString("qtbase_%1").arg(language), QLibraryInfo::location(QLibraryInfo::TranslationsPath))) { + } else if (qtTranslator->load(QString("qtbase_%1").arg(language), + QLibraryInfo::location(QLibraryInfo::TranslationsPath))) { return QCoreApplication::installTranslator(qtTranslator.take()); } return false; diff --git a/src/core/Uuid.cpp b/src/core/Uuid.cpp index 1b531159..a0a07aa6 100644 --- a/src/core/Uuid.cpp +++ b/src/core/Uuid.cpp @@ -22,8 +22,8 @@ #include "crypto/Random.h" const int Uuid::Length = 16; -const QRegExp Uuid::HexRegExp = QRegExp(QString("^[0-9A-F]{%1}$").arg(QString::number(Uuid::Length * 2)), - Qt::CaseInsensitive); +const QRegExp Uuid::HexRegExp = + QRegExp(QString("^[0-9A-F]{%1}$").arg(QString::number(Uuid::Length * 2)), Qt::CaseInsensitive); Uuid::Uuid() : m_data(Length, 0) @@ -120,5 +120,5 @@ QDataStream& operator>>(QDataStream& stream, Uuid& uuid) bool Uuid::isUuid(const QString& uuid) { - return Uuid::HexRegExp.exactMatch(uuid); + return Uuid::HexRegExp.exactMatch(uuid); } diff --git a/src/core/Uuid.h b/src/core/Uuid.h index ecb20e0c..169d99dc 100644 --- a/src/core/Uuid.h +++ b/src/core/Uuid.h @@ -19,8 +19,8 @@ #define KEEPASSX_UUID_H #include -#include #include +#include class Uuid { diff --git a/src/crypto/Crypto.cpp b/src/crypto/Crypto.cpp index 7ba78a6b..c8bac11e 100644 --- a/src/crypto/Crypto.cpp +++ b/src/crypto/Crypto.cpp @@ -116,7 +116,8 @@ bool Crypto::checkAlgorithms() bool Crypto::selfTest() { - return testSha256() && testSha512() && testAes256Cbc() && testAes256Ecb() && testTwofish() && testSalsa20() && testChaCha20(); + return testSha256() && testSha512() && testAes256Cbc() && testAes256Ecb() && testTwofish() && testSalsa20() + && testChaCha20(); } void Crypto::raiseError(const QString& str) @@ -127,8 +128,8 @@ void Crypto::raiseError(const QString& str) bool Crypto::testSha256() { - QByteArray sha256Test = CryptoHash::hash("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", - CryptoHash::Sha256); + QByteArray sha256Test = + CryptoHash::hash("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", CryptoHash::Sha256); if (sha256Test != QByteArray::fromHex("248D6A61D20638B8E5C026930C3E6039A33CE45964FF2167F6ECEDD419DB06C1")) { raiseError("SHA-256 mismatch."); @@ -140,10 +141,11 @@ bool Crypto::testSha256() bool Crypto::testSha512() { - QByteArray sha512Test = CryptoHash::hash("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", - CryptoHash::Sha512); + QByteArray sha512Test = + CryptoHash::hash("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", CryptoHash::Sha512); - if (sha512Test != QByteArray::fromHex("204a8fc6dda82f0a0ced7beb8e08a41657c16ef468b228a8279be331a703c33596fd15c13b1b07f9aa1d3bea57789ca031ad85c7a71dd70354ec631238ca3445")) { + if (sha512Test != QByteArray::fromHex("204a8fc6dda82f0a0ced7beb8e08a41657c16ef468b228a8279be331a703c33596fd15c13b1b" + "07f9aa1d3bea57789ca031ad85c7a71dd70354ec631238ca3445")) { raiseError("SHA-512 mismatch."); return false; } @@ -262,7 +264,6 @@ bool Crypto::testTwofish() return false; } - SymmetricCipher twofishDecrypt(SymmetricCipher::Twofish, SymmetricCipher::Cbc, SymmetricCipher::Decrypt); if (!twofishDecrypt.init(key, iv)) { raiseError(twofishEncrypt.errorString()); @@ -289,8 +290,7 @@ bool Crypto::testSalsa20() QByteArray salsa20Cipher = QByteArray::fromHex("B4C0AFA503BE7FC29A62058166D56F8F"); bool ok; - SymmetricCipher salsa20Stream(SymmetricCipher::Salsa20, SymmetricCipher::Stream, - SymmetricCipher::Encrypt); + SymmetricCipher salsa20Stream(SymmetricCipher::Salsa20, SymmetricCipher::Stream, SymmetricCipher::Encrypt); if (!salsa20Stream.init(salsa20Key, salsa20iv)) { raiseError(salsa20Stream.errorString()); return false; @@ -309,15 +309,17 @@ bool Crypto::testSalsa20() return true; } -bool Crypto::testChaCha20() { +bool Crypto::testChaCha20() +{ QByteArray chacha20Key = QByteArray::fromHex("0000000000000000000000000000000000000000000000000000000000000000"); QByteArray chacha20iv = QByteArray::fromHex("0000000000000000"); - QByteArray chacha20Plain = QByteArray::fromHex("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"); - QByteArray chacha20Cipher = QByteArray::fromHex("76b8e0ada0f13d90405d6ae55386bd28bdd219b8a08ded1aa836efcc8b770dc7da41597c5157488d7724e03fb8d84a376a43b8f41518a11cc387b669b2ee6586"); + QByteArray chacha20Plain = QByteArray::fromHex("0000000000000000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000000000"); + QByteArray chacha20Cipher = QByteArray::fromHex("76b8e0ada0f13d90405d6ae55386bd28bdd219b8a08ded1aa836efcc8b770dc7da" + "41597c5157488d7724e03fb8d84a376a43b8f41518a11cc387b669b2ee6586"); bool ok; - SymmetricCipher chacha20Stream(SymmetricCipher::ChaCha20, SymmetricCipher::Stream, - SymmetricCipher::Encrypt); + SymmetricCipher chacha20Stream(SymmetricCipher::ChaCha20, SymmetricCipher::Stream, SymmetricCipher::Encrypt); if (!chacha20Stream.init(chacha20Key, chacha20iv)) { raiseError(chacha20Stream.errorString()); return false; diff --git a/src/crypto/Random.cpp b/src/crypto/Random.cpp index dc0667fa..69c78630 100644 --- a/src/crypto/Random.cpp +++ b/src/crypto/Random.cpp @@ -89,7 +89,6 @@ Random::Random(RandomBackend* backend) { } - void RandomBackendGcrypt::randomize(void* data, int len) { Q_ASSERT(Crypto::initalized()); diff --git a/src/crypto/Random.h b/src/crypto/Random.h index 038ae7ae..1a36c410 100644 --- a/src/crypto/Random.h +++ b/src/crypto/Random.h @@ -25,7 +25,9 @@ class RandomBackend { public: virtual void randomize(void* data, int len) = 0; - virtual ~RandomBackend() {} + virtual ~RandomBackend() + { + } }; class Random @@ -56,7 +58,8 @@ private: Q_DISABLE_COPY(Random) }; -inline Random* randomGen() { +inline Random* randomGen() +{ return Random::instance(); } diff --git a/src/crypto/SymmetricCipher.h b/src/crypto/SymmetricCipher.h index 0c683d22..bf5b60a4 100644 --- a/src/crypto/SymmetricCipher.h +++ b/src/crypto/SymmetricCipher.h @@ -22,9 +22,9 @@ #include #include +#include "core/Uuid.h" #include "crypto/SymmetricCipherBackend.h" #include "format/KeePass2.h" -#include "core/Uuid.h" class SymmetricCipher { diff --git a/src/crypto/SymmetricCipherBackend.h b/src/crypto/SymmetricCipherBackend.h index dd493d2d..27a39177 100644 --- a/src/crypto/SymmetricCipherBackend.h +++ b/src/crypto/SymmetricCipherBackend.h @@ -23,7 +23,9 @@ class SymmetricCipherBackend { public: - virtual ~SymmetricCipherBackend() {} + virtual ~SymmetricCipherBackend() + { + } virtual bool init() = 0; virtual bool setKey(const QByteArray& key) = 0; virtual bool setIv(const QByteArray& iv) = 0; diff --git a/src/crypto/SymmetricCipherGcrypt.cpp b/src/crypto/SymmetricCipherGcrypt.cpp index 97d53cd8..c7a5e6a0 100644 --- a/src/crypto/SymmetricCipherGcrypt.cpp +++ b/src/crypto/SymmetricCipherGcrypt.cpp @@ -20,7 +20,8 @@ #include "config-keepassx.h" #include "crypto/Crypto.h" -SymmetricCipherGcrypt::SymmetricCipherGcrypt(SymmetricCipher::Algorithm algo, SymmetricCipher::Mode mode, +SymmetricCipherGcrypt::SymmetricCipherGcrypt(SymmetricCipher::Algorithm algo, + SymmetricCipher::Mode mode, SymmetricCipher::Direction direction) : m_ctx(nullptr) , m_algo(gcryptAlgo(algo)) @@ -84,8 +85,8 @@ void SymmetricCipherGcrypt::setErrorString(gcry_error_t err) const char* gcryptError = gcry_strerror(err); const char* gcryptErrorSource = gcry_strsource(err); - m_errorString = QString("%1/%2").arg(QString::fromLocal8Bit(gcryptErrorSource), - QString::fromLocal8Bit(gcryptError)); + m_errorString = + QString("%1/%2").arg(QString::fromLocal8Bit(gcryptErrorSource), QString::fromLocal8Bit(gcryptError)); } bool SymmetricCipherGcrypt::init() @@ -94,7 +95,7 @@ bool SymmetricCipherGcrypt::init() gcry_error_t error; - if(m_ctx != nullptr) + if (m_ctx != nullptr) gcry_cipher_close(m_ctx); error = gcry_cipher_open(&m_ctx, m_algo, m_mode, 0); if (error != 0) { diff --git a/src/crypto/SymmetricCipherGcrypt.h b/src/crypto/SymmetricCipherGcrypt.h index 2436c3be..6f806b90 100644 --- a/src/crypto/SymmetricCipherGcrypt.h +++ b/src/crypto/SymmetricCipherGcrypt.h @@ -23,10 +23,11 @@ #include "crypto/SymmetricCipher.h" #include "crypto/SymmetricCipherBackend.h" -class SymmetricCipherGcrypt: public SymmetricCipherBackend +class SymmetricCipherGcrypt : public SymmetricCipherBackend { public: - SymmetricCipherGcrypt(SymmetricCipher::Algorithm algo, SymmetricCipher::Mode mode, + SymmetricCipherGcrypt(SymmetricCipher::Algorithm algo, + SymmetricCipher::Mode mode, SymmetricCipher::Direction direction); ~SymmetricCipherGcrypt(); diff --git a/src/crypto/argon2/argon2.h b/src/crypto/argon2/argon2.h index 8ea6108a..8eba85a6 100644 --- a/src/crypto/argon2/argon2.h +++ b/src/crypto/argon2/argon2.h @@ -31,4 +31,4 @@ #include -#endif //KEEPASSXC_CRYPTO_ARGON2_H +#endif // KEEPASSXC_CRYPTO_ARGON2_H diff --git a/src/crypto/kdf/AesKdf.cpp b/src/crypto/kdf/AesKdf.cpp index 593b01c2..a6f8f71e 100644 --- a/src/crypto/kdf/AesKdf.cpp +++ b/src/crypto/kdf/AesKdf.cpp @@ -19,8 +19,8 @@ #include -#include "format/KeePass2.h" #include "crypto/CryptoHash.h" +#include "format/KeePass2.h" AesKdf::AesKdf() : Kdf::Kdf(KeePass2::KDF_AES_KDBX4) @@ -35,7 +35,7 @@ AesKdf::AesKdf(bool legacyKdbx3) { } -bool AesKdf::processParameters(const QVariantMap &p) +bool AesKdf::processParameters(const QVariantMap& p) { bool ok; int rounds = p.value(KeePass2::KDFPARAM_AES_ROUNDS).toInt(&ok); @@ -84,8 +84,7 @@ bool AesKdf::transform(const QByteArray& raw, QByteArray& result) const bool AesKdf::transformKeyRaw(const QByteArray& key, const QByteArray& seed, int rounds, QByteArray* result) { QByteArray iv(16, 0); - SymmetricCipher cipher(SymmetricCipher::Aes256, SymmetricCipher::Ecb, - SymmetricCipher::Encrypt); + SymmetricCipher cipher(SymmetricCipher::Aes256, SymmetricCipher::Ecb, SymmetricCipher::Encrypt); if (!cipher.init(seed, iv)) { qWarning("AesKdf::transformKeyRaw: error in SymmetricCipher::init: %s", cipher.errorString().toUtf8().data()); return false; diff --git a/src/crypto/kdf/AesKdf.h b/src/crypto/kdf/AesKdf.h index 31ee1fa7..20ef5c47 100644 --- a/src/crypto/kdf/AesKdf.h +++ b/src/crypto/kdf/AesKdf.h @@ -20,7 +20,7 @@ #include "Kdf.h" -class AesKdf: public Kdf +class AesKdf : public Kdf { public: AesKdf(); @@ -35,10 +35,8 @@ protected: int benchmarkImpl(int msec) const override; private: - static bool transformKeyRaw(const QByteArray& key, - const QByteArray& seed, - int rounds, - QByteArray* result) Q_REQUIRED_RESULT; + static bool + transformKeyRaw(const QByteArray& key, const QByteArray& seed, int rounds, QByteArray* result) Q_REQUIRED_RESULT; }; #endif // KEEPASSX_AESKDF_H diff --git a/src/crypto/kdf/Argon2Kdf.cpp b/src/crypto/kdf/Argon2Kdf.cpp index f67c9c1f..3f329845 100644 --- a/src/crypto/kdf/Argon2Kdf.cpp +++ b/src/crypto/kdf/Argon2Kdf.cpp @@ -30,10 +30,10 @@ * or associated data. KeePass uses the latest version of Argon2, v1.3. */ Argon2Kdf::Argon2Kdf() - : Kdf::Kdf(KeePass2::KDF_ARGON2) - , m_version(0x13) - , m_memory(1 << 16) - , m_parallelism(static_cast(QThread::idealThreadCount())) + : Kdf::Kdf(KeePass2::KDF_ARGON2) + , m_version(0x13) + , m_memory(1 << 16) + , m_parallelism(static_cast(QThread::idealThreadCount())) { m_rounds = 1; } @@ -86,7 +86,7 @@ bool Argon2Kdf::setParallelism(quint32 threads) return false; } -bool Argon2Kdf::processParameters(const QVariantMap &p) +bool Argon2Kdf::processParameters(const QVariantMap& p) { QByteArray salt = p.value(KeePass2::KDFPARAM_ARGON2_SALT).toByteArray(); if (!setSeed(salt)) { @@ -161,13 +161,28 @@ bool Argon2Kdf::transform(const QByteArray& raw, QByteArray& result) const return transformKeyRaw(raw, seed(), version(), rounds(), memory(), parallelism(), result); } -bool Argon2Kdf::transformKeyRaw(const QByteArray& key, const QByteArray& seed, quint32 version, - quint32 rounds, quint64 memory, quint32 parallelism, QByteArray& result) +bool Argon2Kdf::transformKeyRaw(const QByteArray& key, + const QByteArray& seed, + quint32 version, + quint32 rounds, + quint64 memory, + quint32 parallelism, + QByteArray& result) { // Time Cost, Mem Cost, Threads/Lanes, Password, length, Salt, length, out, length - int rc = argon2_hash(rounds, memory, parallelism, key.data(), key.size(), - seed.data(), seed.size(), result.data(), result.size(), - nullptr, 0, Argon2_d, version); + int rc = argon2_hash(rounds, + memory, + parallelism, + key.data(), + key.size(), + seed.data(), + seed.size(), + result.data(), + result.size(), + nullptr, + 0, + Argon2_d, + version); if (rc != ARGON2_OK) { qWarning("Argon2 error: %s", argon2_error_message(rc)); return false; diff --git a/src/crypto/kdf/Argon2Kdf.h b/src/crypto/kdf/Argon2Kdf.h index fe62b295..9449f345 100644 --- a/src/crypto/kdf/Argon2Kdf.h +++ b/src/crypto/kdf/Argon2Kdf.h @@ -20,7 +20,8 @@ #include "Kdf.h" -class Argon2Kdf : public Kdf { +class Argon2Kdf : public Kdf +{ public: Argon2Kdf(); diff --git a/src/crypto/kdf/Kdf.h b/src/crypto/kdf/Kdf.h index 216224a6..ab21bc4d 100644 --- a/src/crypto/kdf/Kdf.h +++ b/src/crypto/kdf/Kdf.h @@ -55,7 +55,6 @@ protected: private: class BenchmarkThread; const Uuid m_uuid; - }; #endif // KEEPASSX_KDF_H diff --git a/src/crypto/kdf/Kdf_p.h b/src/crypto/kdf/Kdf_p.h index 5606c0bf..55ad2401 100644 --- a/src/crypto/kdf/Kdf_p.h +++ b/src/crypto/kdf/Kdf_p.h @@ -22,9 +22,9 @@ #ifndef KEEPASSXC_KDF_P_H #define KEEPASSXC_KDF_P_H -class Kdf::BenchmarkThread: public QThread +class Kdf::BenchmarkThread : public QThread { -Q_OBJECT + Q_OBJECT public: explicit BenchmarkThread(int msec, const Kdf* kdf); diff --git a/src/format/Kdbx3Reader.cpp b/src/format/Kdbx3Reader.cpp index 82d59bc6..00b0adeb 100644 --- a/src/format/Kdbx3Reader.cpp +++ b/src/format/Kdbx3Reader.cpp @@ -18,19 +18,21 @@ #include "Kdbx3Reader.h" -#include "core/Group.h" #include "core/Endian.h" +#include "core/Group.h" #include "crypto/CryptoHash.h" -#include "format/KeePass2RandomStream.h" #include "format/KdbxXmlReader.h" +#include "format/KeePass2RandomStream.h" #include "streams/HashedBlockStream.h" #include "streams/QtIOCompressor" #include "streams/SymmetricCipherStream.h" #include -Database* Kdbx3Reader::readDatabaseImpl(QIODevice* device, const QByteArray& headerData, - const CompositeKey& key, bool keepDatabase) +Database* Kdbx3Reader::readDatabaseImpl(QIODevice* device, + const QByteArray& headerData, + const CompositeKey& key, + bool keepDatabase) { Q_ASSERT(m_kdbxVersion <= KeePass2::FILE_VERSION_3_1); @@ -39,8 +41,8 @@ Database* Kdbx3Reader::readDatabaseImpl(QIODevice* device, const QByteArray& hea } // check if all required headers were present - if (m_masterSeed.isEmpty() || m_encryptionIV.isEmpty() - || m_streamStartBytes.isEmpty() || m_protectedStreamKey.isEmpty() + if (m_masterSeed.isEmpty() || m_encryptionIV.isEmpty() || m_streamStartBytes.isEmpty() + || m_protectedStreamKey.isEmpty() || m_db->cipher().isNull()) { raiseError(tr("missing database headers")); return nullptr; @@ -63,8 +65,8 @@ Database* Kdbx3Reader::readDatabaseImpl(QIODevice* device, const QByteArray& hea QByteArray finalKey = hash.result(); SymmetricCipher::Algorithm cipher = SymmetricCipher::cipherToAlgorithm(m_db->cipher()); - SymmetricCipherStream cipherStream(device, cipher, - SymmetricCipher::algorithmMode(cipher), SymmetricCipher::Decrypt); + SymmetricCipherStream cipherStream( + device, cipher, SymmetricCipher::algorithmMode(cipher), SymmetricCipher::Decrypt); if (!cipherStream.init(finalKey, m_encryptionIV)) { raiseError(cipherStream.errorString()); return nullptr; diff --git a/src/format/Kdbx3Reader.h b/src/format/Kdbx3Reader.h index e6290157..41916d0e 100644 --- a/src/format/Kdbx3Reader.h +++ b/src/format/Kdbx3Reader.h @@ -24,13 +24,15 @@ /** * KDBX 2/3 reader implementation. */ -class Kdbx3Reader: public KdbxReader +class Kdbx3Reader : public KdbxReader { -Q_DECLARE_TR_FUNCTIONS(Kdbx3Reader) + Q_DECLARE_TR_FUNCTIONS(Kdbx3Reader) public: - Database* readDatabaseImpl(QIODevice* device, const QByteArray& headerData, - const CompositeKey& key, bool keepDatabase) override; + Database* readDatabaseImpl(QIODevice* device, + const QByteArray& headerData, + const CompositeKey& key, + bool keepDatabase) override; protected: bool readHeaderField(StoreDataStream& headerStream) override; diff --git a/src/format/Kdbx3Writer.cpp b/src/format/Kdbx3Writer.cpp index c2fefff1..866acae0 100644 --- a/src/format/Kdbx3Writer.cpp +++ b/src/format/Kdbx3Writer.cpp @@ -23,9 +23,9 @@ #include "core/Database.h" #include "crypto/CryptoHash.h" #include "crypto/Random.h" +#include "format/KdbxXmlWriter.h" #include "format/KeePass2.h" #include "format/KeePass2RandomStream.h" -#include "format/KdbxXmlWriter.h" #include "streams/HashedBlockStream.h" #include "streams/QtIOCompressor" #include "streams/SymmetricCipherStream.h" @@ -65,23 +65,27 @@ bool Kdbx3Writer::writeDatabase(QIODevice* device, Database* db) writeMagicNumbers(&header, KeePass2::SIGNATURE_1, KeePass2::SIGNATURE_2, KeePass2::FILE_VERSION_3_1); - CHECK_RETURN_FALSE(writeHeaderField(&header, KeePass2::HeaderFieldID::CipherID, db->cipher().toByteArray())); - CHECK_RETURN_FALSE(writeHeaderField(&header, KeePass2::HeaderFieldID::CompressionFlags, - Endian::sizedIntToBytes(db->compressionAlgo(), - KeePass2::BYTEORDER))); + CHECK_RETURN_FALSE( + writeHeaderField(&header, KeePass2::HeaderFieldID::CipherID, db->cipher().toByteArray())); + CHECK_RETURN_FALSE( + writeHeaderField(&header, + KeePass2::HeaderFieldID::CompressionFlags, + Endian::sizedIntToBytes(db->compressionAlgo(), KeePass2::BYTEORDER))); auto kdf = db->kdf(); CHECK_RETURN_FALSE(writeHeaderField(&header, KeePass2::HeaderFieldID::MasterSeed, masterSeed)); CHECK_RETURN_FALSE(writeHeaderField(&header, KeePass2::HeaderFieldID::TransformSeed, kdf->seed())); - CHECK_RETURN_FALSE(writeHeaderField(&header, KeePass2::HeaderFieldID::TransformRounds, - Endian::sizedIntToBytes(kdf->rounds(), - KeePass2::BYTEORDER))); + CHECK_RETURN_FALSE(writeHeaderField(&header, + KeePass2::HeaderFieldID::TransformRounds, + Endian::sizedIntToBytes(kdf->rounds(), KeePass2::BYTEORDER))); CHECK_RETURN_FALSE(writeHeaderField(&header, KeePass2::HeaderFieldID::EncryptionIV, encryptionIV)); - CHECK_RETURN_FALSE(writeHeaderField(&header, KeePass2::HeaderFieldID::ProtectedStreamKey, protectedStreamKey)); + CHECK_RETURN_FALSE( + writeHeaderField(&header, KeePass2::HeaderFieldID::ProtectedStreamKey, protectedStreamKey)); CHECK_RETURN_FALSE(writeHeaderField(&header, KeePass2::HeaderFieldID::StreamStartBytes, startBytes)); - CHECK_RETURN_FALSE(writeHeaderField(&header, KeePass2::HeaderFieldID::InnerRandomStreamID, - Endian::sizedIntToBytes(static_cast( - KeePass2::ProtectedStreamAlgo::Salsa20), - KeePass2::BYTEORDER))); + CHECK_RETURN_FALSE(writeHeaderField( + &header, + KeePass2::HeaderFieldID::InnerRandomStreamID, + Endian::sizedIntToBytes(static_cast(KeePass2::ProtectedStreamAlgo::Salsa20), + KeePass2::BYTEORDER))); CHECK_RETURN_FALSE(writeHeaderField(&header, KeePass2::HeaderFieldID::EndOfHeader, endOfHeader)); header.close(); @@ -93,8 +97,7 @@ bool Kdbx3Writer::writeDatabase(QIODevice* device, Database* db) // write cipher stream SymmetricCipher::Algorithm algo = SymmetricCipher::cipherToAlgorithm(db->cipher()); - SymmetricCipherStream cipherStream(device, algo, - SymmetricCipher::algorithmMode(algo), SymmetricCipher::Encrypt); + SymmetricCipherStream cipherStream(device, algo, SymmetricCipher::algorithmMode(algo), SymmetricCipher::Encrypt); cipherStream.init(finalKey, encryptionIV); if (!cipherStream.open(QIODevice::WriteOnly)) { raiseError(cipherStream.errorString()); diff --git a/src/format/Kdbx3Writer.h b/src/format/Kdbx3Writer.h index 8acc198a..eb98a470 100644 --- a/src/format/Kdbx3Writer.h +++ b/src/format/Kdbx3Writer.h @@ -23,9 +23,9 @@ /** * KDBX2/3 writer implementation. */ -class Kdbx3Writer: public KdbxWriter +class Kdbx3Writer : public KdbxWriter { -Q_DECLARE_TR_FUNCTIONS(Kdbx3Writer) + Q_DECLARE_TR_FUNCTIONS(Kdbx3Writer) public: bool writeDatabase(QIODevice* device, Database* db) override; diff --git a/src/format/Kdbx4Reader.cpp b/src/format/Kdbx4Reader.cpp index 2919db78..92c8187c 100644 --- a/src/format/Kdbx4Reader.cpp +++ b/src/format/Kdbx4Reader.cpp @@ -19,17 +19,19 @@ #include -#include "core/Group.h" #include "core/Endian.h" +#include "core/Group.h" #include "crypto/CryptoHash.h" -#include "format/KeePass2RandomStream.h" #include "format/KdbxXmlReader.h" +#include "format/KeePass2RandomStream.h" #include "streams/HmacBlockStream.h" #include "streams/QtIOCompressor" #include "streams/SymmetricCipherStream.h" -Database* Kdbx4Reader::readDatabaseImpl(QIODevice* device, const QByteArray& headerData, - const CompositeKey& key, bool keepDatabase) +Database* Kdbx4Reader::readDatabaseImpl(QIODevice* device, + const QByteArray& headerData, + const CompositeKey& key, + bool keepDatabase) { Q_ASSERT(m_kdbxVersion == KeePass2::FILE_VERSION_4); @@ -40,9 +42,7 @@ Database* Kdbx4Reader::readDatabaseImpl(QIODevice* device, const QByteArray& hea } // check if all required headers were present - if (m_masterSeed.isEmpty() - || m_encryptionIV.isEmpty() - || m_db->cipher().isNull()) { + if (m_masterSeed.isEmpty() || m_encryptionIV.isEmpty() || m_db->cipher().isNull()) { raiseError(tr("missing database headers")); return nullptr; } @@ -69,8 +69,8 @@ Database* Kdbx4Reader::readDatabaseImpl(QIODevice* device, const QByteArray& hea } QByteArray hmacKey = KeePass2::hmacKey(m_masterSeed, m_db->transformedMasterKey()); - if (headerHmac != CryptoHash::hmac(headerData, - HmacBlockStream::getHmacKey(UINT64_MAX, hmacKey), CryptoHash::Sha256)) { + if (headerHmac + != CryptoHash::hmac(headerData, HmacBlockStream::getHmacKey(UINT64_MAX, hmacKey), CryptoHash::Sha256)) { raiseError(tr("Wrong key or database file is corrupt. (HMAC mismatch)")); return nullptr; } @@ -85,8 +85,8 @@ Database* Kdbx4Reader::readDatabaseImpl(QIODevice* device, const QByteArray& hea raiseError(tr("Unknown cipher")); return nullptr; } - SymmetricCipherStream cipherStream(&hmacStream, cipher, - SymmetricCipher::algorithmMode(cipher), SymmetricCipher::Decrypt); + SymmetricCipherStream cipherStream( + &hmacStream, cipher, SymmetricCipher::algorithmMode(cipher), SymmetricCipher::Decrypt); if (!cipherStream.init(finalKey, m_encryptionIV)) { raiseError(cipherStream.errorString()); return nullptr; @@ -304,8 +304,8 @@ bool Kdbx4Reader::readInnerHeaderField(QIODevice* device) QVariantMap Kdbx4Reader::readVariantMap(QIODevice* device) { bool ok; - quint16 version = Endian::readSizedInt(device, KeePass2::BYTEORDER, &ok) - & KeePass2::VARIANTMAP_CRITICAL_MASK; + quint16 version = + Endian::readSizedInt(device, KeePass2::BYTEORDER, &ok) & KeePass2::VARIANTMAP_CRITICAL_MASK; quint16 maxVersion = KeePass2::VARIANTMAP_VERSION & KeePass2::VARIANTMAP_CRITICAL_MASK; if (!ok || (version > maxVersion)) { //: Translation: variant map = data structure for storing meta data diff --git a/src/format/Kdbx4Reader.h b/src/format/Kdbx4Reader.h index 24d4a914..ce965a7b 100644 --- a/src/format/Kdbx4Reader.h +++ b/src/format/Kdbx4Reader.h @@ -27,11 +27,13 @@ */ class Kdbx4Reader : public KdbxReader { -Q_DECLARE_TR_FUNCTIONS(Kdbx4Reader) + Q_DECLARE_TR_FUNCTIONS(Kdbx4Reader) public: - Database* readDatabaseImpl(QIODevice* device, const QByteArray& headerData, - const CompositeKey& key, bool keepDatabase) override; + Database* readDatabaseImpl(QIODevice* device, + const QByteArray& headerData, + const CompositeKey& key, + bool keepDatabase) override; QHash binaryPoolInverse() const; QHash binaryPool() const; diff --git a/src/format/Kdbx4Writer.cpp b/src/format/Kdbx4Writer.cpp index bd671d9c..43234b1e 100644 --- a/src/format/Kdbx4Writer.cpp +++ b/src/format/Kdbx4Writer.cpp @@ -20,14 +20,14 @@ #include #include -#include "streams/HmacBlockStream.h" +#include "core/CustomData.h" #include "core/Database.h" #include "core/Metadata.h" -#include "core/CustomData.h" #include "crypto/CryptoHash.h" #include "crypto/Random.h" -#include "format/KeePass2RandomStream.h" #include "format/KdbxXmlWriter.h" +#include "format/KeePass2RandomStream.h" +#include "streams/HmacBlockStream.h" #include "streams/QtIOCompressor" #include "streams/SymmetricCipherStream.h" @@ -73,10 +73,12 @@ bool Kdbx4Writer::writeDatabase(QIODevice* device, Database* db) writeMagicNumbers(&header, KeePass2::SIGNATURE_1, KeePass2::SIGNATURE_2, KeePass2::FILE_VERSION_4); - CHECK_RETURN_FALSE(writeHeaderField(&header, KeePass2::HeaderFieldID::CipherID, db->cipher().toByteArray())); - CHECK_RETURN_FALSE(writeHeaderField(&header, KeePass2::HeaderFieldID::CompressionFlags, - Endian::sizedIntToBytes(static_cast(db->compressionAlgo()), - KeePass2::BYTEORDER))); + CHECK_RETURN_FALSE( + writeHeaderField(&header, KeePass2::HeaderFieldID::CipherID, db->cipher().toByteArray())); + CHECK_RETURN_FALSE(writeHeaderField( + &header, + KeePass2::HeaderFieldID::CompressionFlags, + Endian::sizedIntToBytes(static_cast(db->compressionAlgo()), KeePass2::BYTEORDER))); CHECK_RETURN_FALSE(writeHeaderField(&header, KeePass2::HeaderFieldID::MasterSeed, masterSeed)); CHECK_RETURN_FALSE(writeHeaderField(&header, KeePass2::HeaderFieldID::EncryptionIV, encryptionIV)); @@ -94,8 +96,8 @@ bool Kdbx4Writer::writeDatabase(QIODevice* device, Database* db) if (!publicCustomData.isEmpty()) { QByteArray serialized; serializeVariantMap(publicCustomData, serialized); - CHECK_RETURN_FALSE(writeHeaderField( - &header, KeePass2::HeaderFieldID::PublicCustomData, serialized)); + CHECK_RETURN_FALSE( + writeHeaderField(&header, KeePass2::HeaderFieldID::PublicCustomData, serialized)); } CHECK_RETURN_FALSE(writeHeaderField(&header, KeePass2::HeaderFieldID::EndOfHeader, endOfHeader)); @@ -109,8 +111,8 @@ bool Kdbx4Writer::writeDatabase(QIODevice* device, Database* db) // write HMAC-authenticated cipher stream QByteArray hmacKey = KeePass2::hmacKey(masterSeed, db->transformedMasterKey()); - QByteArray headerHmac = CryptoHash::hmac(headerData, HmacBlockStream::getHmacKey(UINT64_MAX, hmacKey), - CryptoHash::Sha256); + QByteArray headerHmac = + CryptoHash::hmac(headerData, HmacBlockStream::getHmacKey(UINT64_MAX, hmacKey), CryptoHash::Sha256); CHECK_RETURN_FALSE(writeData(device, headerHash)); CHECK_RETURN_FALSE(writeData(device, headerHmac)); @@ -123,9 +125,8 @@ bool Kdbx4Writer::writeDatabase(QIODevice* device, Database* db) return false; } - cipherStream.reset(new SymmetricCipherStream(hmacBlockStream.data(), algo, - SymmetricCipher::algorithmMode(algo), - SymmetricCipher::Encrypt)); + cipherStream.reset(new SymmetricCipherStream( + hmacBlockStream.data(), algo, SymmetricCipher::algorithmMode(algo), SymmetricCipher::Encrypt)); if (!cipherStream->init(finalKey, encryptionIV)) { raiseError(cipherStream->errorString()); @@ -153,11 +154,12 @@ bool Kdbx4Writer::writeDatabase(QIODevice* device, Database* db) Q_ASSERT(outputDevice); - CHECK_RETURN_FALSE(writeInnerHeaderField(outputDevice, KeePass2::InnerHeaderFieldID::InnerRandomStreamID, - Endian::sizedIntToBytes(static_cast(KeePass2::ProtectedStreamAlgo::ChaCha20), - KeePass2::BYTEORDER))); - CHECK_RETURN_FALSE(writeInnerHeaderField(outputDevice, KeePass2::InnerHeaderFieldID::InnerRandomStreamKey, - protectedStreamKey)); + CHECK_RETURN_FALSE(writeInnerHeaderField( + outputDevice, + KeePass2::InnerHeaderFieldID::InnerRandomStreamID, + Endian::sizedIntToBytes(static_cast(KeePass2::ProtectedStreamAlgo::ChaCha20), KeePass2::BYTEORDER))); + CHECK_RETURN_FALSE( + writeInnerHeaderField(outputDevice, KeePass2::InnerHeaderFieldID::InnerRandomStreamKey, protectedStreamKey)); // Write attachments to the inner header writeAttachments(outputDevice, db); @@ -208,7 +210,8 @@ bool Kdbx4Writer::writeInnerHeaderField(QIODevice* device, KeePass2::InnerHeader QByteArray fieldIdArr; fieldIdArr[0] = static_cast(fieldId); CHECK_RETURN_FALSE(writeData(device, fieldIdArr)); - CHECK_RETURN_FALSE(writeData(device, Endian::sizedIntToBytes(static_cast(data.size()), KeePass2::BYTEORDER))); + CHECK_RETURN_FALSE( + writeData(device, Endian::sizedIntToBytes(static_cast(data.size()), KeePass2::BYTEORDER))); CHECK_RETURN_FALSE(writeData(device, data)); return true; diff --git a/src/format/Kdbx4Writer.h b/src/format/Kdbx4Writer.h index 90a8e658..c8540245 100644 --- a/src/format/Kdbx4Writer.h +++ b/src/format/Kdbx4Writer.h @@ -25,7 +25,7 @@ */ class Kdbx4Writer : public KdbxWriter { -Q_DECLARE_TR_FUNCTIONS(Kdbx4Writer) + Q_DECLARE_TR_FUNCTIONS(Kdbx4Writer) public: bool writeDatabase(QIODevice* device, Database* db) override; diff --git a/src/format/KdbxReader.cpp b/src/format/KdbxReader.cpp index 5393b743..ade824fb 100644 --- a/src/format/KdbxReader.cpp +++ b/src/format/KdbxReader.cpp @@ -249,8 +249,8 @@ void KdbxReader::setInnerRandomStreamID(const QByteArray& data) } auto id = Endian::bytesToSizedInt(data, KeePass2::BYTEORDER); KeePass2::ProtectedStreamAlgo irsAlgo = KeePass2::idToProtectedStreamAlgo(id); - if (irsAlgo == KeePass2::ProtectedStreamAlgo::InvalidProtectedStreamAlgo || - irsAlgo == KeePass2::ProtectedStreamAlgo::ArcFourVariant) { + if (irsAlgo == KeePass2::ProtectedStreamAlgo::InvalidProtectedStreamAlgo + || irsAlgo == KeePass2::ProtectedStreamAlgo::ArcFourVariant) { raiseError(tr("Invalid inner random stream cipher")); return; } diff --git a/src/format/KdbxReader.h b/src/format/KdbxReader.h index 994cfb7e..23050d28 100644 --- a/src/format/KdbxReader.h +++ b/src/format/KdbxReader.h @@ -33,7 +33,7 @@ class QIODevice; */ class KdbxReader { -Q_DECLARE_TR_FUNCTIONS(KdbxReader) + Q_DECLARE_TR_FUNCTIONS(KdbxReader) public: KdbxReader() = default; @@ -61,8 +61,8 @@ protected: * @param keepDatabase keep database in case of read failure * @return pointer to the read database, nullptr on failure */ - virtual Database* readDatabaseImpl(QIODevice* device, const QByteArray& headerData, - const CompositeKey& key, bool keepDatabase) = 0; + virtual Database* + readDatabaseImpl(QIODevice* device, const QByteArray& headerData, const CompositeKey& key, bool keepDatabase) = 0; /** * Read next header field from stream. @@ -103,5 +103,4 @@ private: QString m_errorStr = ""; }; - -#endif //KEEPASSXC_KDBXREADER_H +#endif // KEEPASSXC_KDBXREADER_H diff --git a/src/format/KdbxWriter.h b/src/format/KdbxWriter.h index 8fec336d..4685797c 100644 --- a/src/format/KdbxWriter.h +++ b/src/format/KdbxWriter.h @@ -35,7 +35,7 @@ class Database; */ class KdbxWriter { -Q_DECLARE_TR_FUNCTIONS(KdbxWriter) + Q_DECLARE_TR_FUNCTIONS(KdbxWriter) public: KdbxWriter() = default; @@ -56,7 +56,6 @@ public: QString errorString() const; protected: - /** * Helper method for writing a KDBX header field to a device. * @@ -74,8 +73,8 @@ protected: QByteArray fieldIdArr; fieldIdArr[0] = static_cast(fieldId); CHECK_RETURN_FALSE(writeData(device, fieldIdArr)); - CHECK_RETURN_FALSE(writeData(device, Endian::sizedIntToBytes(static_cast(data.size()), - KeePass2::BYTEORDER))); + CHECK_RETURN_FALSE(writeData( + device, Endian::sizedIntToBytes(static_cast(data.size()), KeePass2::BYTEORDER))); CHECK_RETURN_FALSE(writeData(device, data)); return true; @@ -88,5 +87,4 @@ protected: QString m_errorStr = ""; }; - -#endif //KEEPASSXC_KDBXWRITER_H +#endif // KEEPASSXC_KDBXWRITER_H diff --git a/src/format/KdbxXmlReader.cpp b/src/format/KdbxXmlReader.cpp index 77ec2604..b10df2eb 100644 --- a/src/format/KdbxXmlReader.cpp +++ b/src/format/KdbxXmlReader.cpp @@ -17,16 +17,16 @@ #include "KdbxXmlReader.h" #include "KeePass2RandomStream.h" -#include "core/Global.h" -#include "core/Tools.h" -#include "core/Entry.h" -#include "core/Group.h" #include "core/DatabaseIcons.h" #include "core/Endian.h" +#include "core/Entry.h" +#include "core/Global.h" +#include "core/Group.h" +#include "core/Tools.h" #include "streams/QtIOCompressor" -#include #include +#include /** * @param version KDBX version @@ -114,13 +114,11 @@ void KdbxXmlReader::readDatabase(QIODevice* device, Database* db, KeePass2Random } if (!m_tmpParent->children().isEmpty()) { - qWarning("KdbxXmlReader::readDatabase: found %d invalid group reference(s)", - m_tmpParent->children().size()); + qWarning("KdbxXmlReader::readDatabase: found %d invalid group reference(s)", m_tmpParent->children().size()); } if (!m_tmpParent->entries().isEmpty()) { - qWarning("KdbxXmlReader::readDatabase: found %d invalid entry reference(s)", - m_tmpParent->children().size()); + qWarning("KdbxXmlReader::readDatabase: found %d invalid entry reference(s)", m_tmpParent->children().size()); } const QSet poolKeys = m_binaryPool.keys().toSet(); @@ -136,7 +134,7 @@ void KdbxXmlReader::readDatabase(QIODevice* device, Database* db, KeePass2Random qWarning("KdbxXmlReader::readDatabase: found unused key \"%s\"", qPrintable(key)); } - QHash >::const_iterator i; + QHash>::const_iterator i; for (i = m_binaryMap.constBegin(); i != m_binaryMap.constEnd(); ++i) { const QPair& target = i.value(); target.first->attachments()->set(target.second, m_binaryPool[i.key()]); @@ -191,8 +189,7 @@ QString KdbxXmlReader::errorString() const bool KdbxXmlReader::isTrueValue(const QStringRef& value) { - return value.compare(QLatin1String("true"), Qt::CaseInsensitive) == 0 - || value == "1"; + return value.compare(QLatin1String("true"), Qt::CaseInsensitive) == 0 || value == "1"; } void KdbxXmlReader::raiseError(const QString& errorMessage) @@ -386,12 +383,10 @@ void KdbxXmlReader::parseBinaries() QXmlStreamAttributes attr = m_xml.attributes(); QString id = attr.value("ID").toString(); - QByteArray data = isTrueValue(attr.value("Compressed")) - ? readCompressedBinary() : readBinary(); + QByteArray data = isTrueValue(attr.value("Compressed")) ? readCompressedBinary() : readBinary(); if (m_binaryPool.contains(id)) { - qWarning("KdbxXmlReader::parseBinaries: overwriting binary item \"%s\"", - qPrintable(id)); + qWarning("KdbxXmlReader::parseBinaries: overwriting binary item \"%s\"", qPrintable(id)); } m_binaryPool.insert(id, data); @@ -1192,4 +1187,3 @@ void KdbxXmlReader::skipCurrentElement() qWarning("KdbxXmlReader::skipCurrentElement: skip element \"%s\"", qPrintable(m_xml.name().toString())); m_xml.skipCurrentElement(); } - diff --git a/src/format/KdbxXmlReader.h b/src/format/KdbxXmlReader.h index 50015182..00c898d1 100644 --- a/src/format/KdbxXmlReader.h +++ b/src/format/KdbxXmlReader.h @@ -18,14 +18,14 @@ #ifndef KEEPASSXC_KDBXXMLREADER_H #define KEEPASSXC_KDBXXMLREADER_H +#include "core/Database.h" #include "core/Metadata.h" #include "core/TimeInfo.h" #include "core/Uuid.h" -#include "core/Database.h" #include -#include #include +#include #include class QIODevice; @@ -38,7 +38,7 @@ class KeePass2RandomStream; */ class KdbxXmlReader { -Q_DECLARE_TR_FUNCTIONS(KdbxXmlReader) + Q_DECLARE_TR_FUNCTIONS(KdbxXmlReader) public: explicit KdbxXmlReader(quint32 version); @@ -112,11 +112,11 @@ protected: QHash m_entries; QHash m_binaryPool; - QHash > m_binaryMap; + QHash> m_binaryMap; QByteArray m_headerHash; bool m_error = false; QString m_errorStr = ""; }; -#endif //KEEPASSXC_KDBXXMLREADER_H +#endif // KEEPASSXC_KDBXXMLREADER_H diff --git a/src/format/KdbxXmlWriter.cpp b/src/format/KdbxXmlWriter.cpp index a546f317..748e16d3 100644 --- a/src/format/KdbxXmlWriter.cpp +++ b/src/format/KdbxXmlWriter.cpp @@ -33,7 +33,10 @@ KdbxXmlWriter::KdbxXmlWriter(quint32 version) { } -void KdbxXmlWriter::writeDatabase(QIODevice* device, Database* db, KeePass2RandomStream* randomStream, const QByteArray& headerHash) +void KdbxXmlWriter::writeDatabase(QIODevice* device, + Database* db, + KeePass2RandomStream* randomStream, + const QByteArray& headerHash) { m_db = db; m_meta = db->metadata(); @@ -64,7 +67,7 @@ void KdbxXmlWriter::writeDatabase(QIODevice* device, Database* db, KeePass2Rando void KdbxXmlWriter::writeDatabase(const QString& filename, Database* db) { QFile file(filename); - file.open(QIODevice::WriteOnly|QIODevice::Truncate); + file.open(QIODevice::WriteOnly | QIODevice::Truncate); writeDatabase(&file, db); } @@ -204,8 +207,7 @@ void KdbxXmlWriter::writeBinaries() buffer.seek(0); data = buffer.readAll(); - } - else { + } else { data = i.key(); } @@ -354,12 +356,12 @@ void KdbxXmlWriter::writeEntry(const Entry* entry) for (const QString& key : attributesKeyList) { m_xml.writeStartElement("String"); - bool protect = ( ((key == "Title") && m_meta->protectTitle()) || - ((key == "UserName") && m_meta->protectUsername()) || - ((key == "Password") && m_meta->protectPassword()) || - ((key == "URL") && m_meta->protectUrl()) || - ((key == "Notes") && m_meta->protectNotes()) || - entry->attributes()->isProtected(key) ); + bool protect = + (((key == "Title") && m_meta->protectTitle()) || ((key == "UserName") && m_meta->protectUsername()) + || ((key == "Password") && m_meta->protectPassword()) + || ((key == "URL") && m_meta->protectUrl()) + || ((key == "Notes") && m_meta->protectNotes()) + || entry->attributes()->isProtected(key)); writeString("Key", key); @@ -375,13 +377,11 @@ void KdbxXmlWriter::writeEntry(const Entry* entry) raiseError(m_randomStream->errorString()); } value = QString::fromLatin1(rawData.toBase64()); - } - else { + } else { m_xml.writeAttribute("ProtectInMemory", "True"); value = entry->attributes()->value(key); } - } - else { + } else { value = entry->attributes()->value(key); } @@ -462,8 +462,7 @@ void KdbxXmlWriter::writeString(const QString& qualifiedName, const QString& str { if (string.isEmpty()) { m_xml.writeEmptyElement(qualifiedName); - } - else { + } else { m_xml.writeTextElement(qualifiedName, stripInvalidXml10Chars(string)); } } @@ -477,8 +476,7 @@ void KdbxXmlWriter::writeBool(const QString& qualifiedName, bool b) { if (b) { writeString(qualifiedName, "True"); - } - else { + } else { writeString(qualifiedName, "False"); } } @@ -513,8 +511,7 @@ void KdbxXmlWriter::writeUuid(const QString& qualifiedName, const Group* group) { if (group) { writeUuid(qualifiedName, group->uuid()); - } - else { + } else { writeUuid(qualifiedName, Uuid()); } } @@ -523,8 +520,7 @@ void KdbxXmlWriter::writeUuid(const QString& qualifiedName, const Entry* entry) { if (entry) { writeUuid(qualifiedName, entry->uuid()); - } - else { + } else { writeUuid(qualifiedName, Uuid()); } } @@ -539,9 +535,8 @@ void KdbxXmlWriter::writeColor(const QString& qualifiedName, const QColor& color QString colorStr; if (color.isValid()) { - colorStr = QString("#%1%2%3").arg(colorPartToString(color.red()), - colorPartToString(color.green()), - colorPartToString(color.blue())); + colorStr = QString("#%1%2%3").arg( + colorPartToString(color.red()), colorPartToString(color.green()), colorPartToString(color.blue())); } writeString(qualifiedName, colorStr); @@ -553,11 +548,9 @@ void KdbxXmlWriter::writeTriState(const QString& qualifiedName, Group::TriState if (triState == Group::Inherit) { value = "null"; - } - else if (triState == Group::Enable) { + } else if (triState == Group::Enable) { value = "true"; - } - else { + } else { value = "false"; } @@ -583,13 +576,12 @@ QString KdbxXmlWriter::stripInvalidXml10Chars(QString str) if (ch.isLowSurrogate() && i != 0 && str.at(i - 1).isHighSurrogate()) { // keep valid surrogate pair i--; - } - else if ((uc < 0x20 && uc != 0x09 && uc != 0x0A && uc != 0x0D) // control characters - || (uc >= 0x7F && uc <= 0x84) // control characters, valid but discouraged by XML - || (uc >= 0x86 && uc <= 0x9F) // control characters, valid but discouraged by XML - || (uc > 0xFFFD) // noncharacter - || ch.isLowSurrogate() // single low surrogate - || ch.isHighSurrogate()) // single high surrogate + } else if ((uc < 0x20 && uc != 0x09 && uc != 0x0A && uc != 0x0D) // control characters + || (uc >= 0x7F && uc <= 0x84) // control characters, valid but discouraged by XML + || (uc >= 0x86 && uc <= 0x9F) // control characters, valid but discouraged by XML + || (uc > 0xFFFD) // noncharacter + || ch.isLowSurrogate() // single low surrogate + || ch.isHighSurrogate()) // single high surrogate { qWarning("Stripping invalid XML 1.0 codepoint %x", uc); str.remove(i, 1); diff --git a/src/format/KdbxXmlWriter.h b/src/format/KdbxXmlWriter.h index e2c5b73c..a8ed79b8 100644 --- a/src/format/KdbxXmlWriter.h +++ b/src/format/KdbxXmlWriter.h @@ -37,7 +37,9 @@ class KdbxXmlWriter public: explicit KdbxXmlWriter(quint32 version); - void writeDatabase(QIODevice* device, Database* db, KeePass2RandomStream* randomStream = nullptr, + void writeDatabase(QIODevice* device, + Database* db, + KeePass2RandomStream* randomStream = nullptr, const QByteArray& headerHash = QByteArray()); void writeDatabase(const QString& filename, Database* db); bool hasError(); diff --git a/src/format/KeePass1Reader.cpp b/src/format/KeePass1Reader.cpp index 02810b98..5789c590 100644 --- a/src/format/KeePass1Reader.cpp +++ b/src/format/KeePass1Reader.cpp @@ -21,7 +21,6 @@ #include #include -#include "crypto/kdf/AesKdf.h" #include "core/Database.h" #include "core/Endian.h" #include "core/Entry.h" @@ -29,6 +28,7 @@ #include "core/Metadata.h" #include "core/Tools.h" #include "crypto/CryptoHash.h" +#include "crypto/kdf/AesKdf.h" #include "format/KeePass1.h" #include "keys/FileKey.h" #include "keys/PasswordKey.h" @@ -47,7 +47,6 @@ private: QByteArray m_keyfileData; }; - KeePass1Reader::KeePass1Reader() : m_db(nullptr) , m_tmpParent(nullptr) @@ -58,8 +57,7 @@ KeePass1Reader::KeePass1Reader() { } -Database* KeePass1Reader::readDatabase(QIODevice* device, const QString& password, - QIODevice* keyfileDevice) +Database* KeePass1Reader::readDatabase(QIODevice* device, const QString& password, QIODevice* keyfileDevice) { m_error = false; m_errorStr.clear(); @@ -112,8 +110,9 @@ Database* KeePass1Reader::readDatabase(QIODevice* device, const QString& passwor } auto version = Endian::readSizedInt(m_device, KeePass1::BYTEORDER, &ok); - if (!ok || (version & KeePass1::FILE_VERSION_CRITICAL_MASK) - != (KeePass1::FILE_VERSION & KeePass1::FILE_VERSION_CRITICAL_MASK)) { + if (!ok + || (version & KeePass1::FILE_VERSION_CRITICAL_MASK) + != (KeePass1::FILE_VERSION & KeePass1::FILE_VERSION_CRITICAL_MASK)) { raiseError(tr("Unsupported KeePass database version.")); return nullptr; } @@ -200,8 +199,7 @@ Database* KeePass1Reader::readDatabase(QIODevice* device, const QString& passwor parseMetaStream(entry); delete entry; - } - else { + } else { quint32 groupId = m_entryGroupIds.value(entry); if (!m_groupIds.contains(groupId)) { qWarning("Orphaned entry found, assigning to root group."); @@ -251,8 +249,7 @@ Database* KeePass1Reader::readDatabase(QIODevice* device, const QString& passwor return db.take(); } -Database* KeePass1Reader::readDatabase(QIODevice* device, const QString& password, - const QString& keyfileName) +Database* KeePass1Reader::readDatabase(QIODevice* device, const QString& password, const QString& keyfileName) { QScopedPointer keyFile; if (!keyfileName.isEmpty()) { @@ -268,8 +265,7 @@ Database* KeePass1Reader::readDatabase(QIODevice* device, const QString& passwor return db.take(); } -Database* KeePass1Reader::readDatabase(const QString& filename, const QString& password, - const QString& keyfileName) +Database* KeePass1Reader::readDatabase(const QString& filename, const QString& password, const QString& keyfileName) { QFile dbFile(filename); if (!dbFile.open(QFile::ReadOnly)) { @@ -297,10 +293,10 @@ QString KeePass1Reader::errorString() return m_errorStr; } -SymmetricCipherStream* KeePass1Reader::testKeys(const QString& password, const QByteArray& keyfileData, - qint64 contentPos) +SymmetricCipherStream* +KeePass1Reader::testKeys(const QString& password, const QByteArray& keyfileData, qint64 contentPos) { - const QList encodings = { Windows1252, Latin1, UTF8 }; + const QList encodings = {Windows1252, Latin1, UTF8}; QScopedPointer cipherStream; QByteArray passwordData; @@ -310,28 +306,24 @@ SymmetricCipherStream* KeePass1Reader::testKeys(const QString& password, const Q for (PasswordEncoding encoding : encodings) { if (encoding == Windows1252) { passwordData = passwordDataCorrect; - } - else if (encoding == Latin1) { + } else if (encoding == Latin1) { // KeePassX used Latin-1 encoding for passwords until version 0.3.1 // but KeePass/Win32 uses Windows Codepage 1252. passwordData = password.toLatin1(); if (passwordData == passwordDataCorrect) { continue; - } - else { + } else { qWarning("Testing password encoded as Latin-1."); } - } - else if (encoding == UTF8) { + } else if (encoding == UTF8) { // KeePassX used UTF-8 encoding for passwords until version 0.2.2 // but KeePass/Win32 uses Windows Codepage 1252. passwordData = password.toUtf8(); if (passwordData == passwordDataCorrect) { continue; - } - else { + } else { qWarning("Testing password encoded as UTF-8."); } } @@ -341,12 +333,11 @@ SymmetricCipherStream* KeePass1Reader::testKeys(const QString& password, const Q return nullptr; } if (m_encryptionFlags & KeePass1::Rijndael) { - cipherStream.reset(new SymmetricCipherStream(m_device, SymmetricCipher::Aes256, - SymmetricCipher::Cbc, SymmetricCipher::Decrypt)); - } - else { - cipherStream.reset(new SymmetricCipherStream(m_device, SymmetricCipher::Twofish, - SymmetricCipher::Cbc, SymmetricCipher::Decrypt)); + cipherStream.reset(new SymmetricCipherStream( + m_device, SymmetricCipher::Aes256, SymmetricCipher::Cbc, SymmetricCipher::Decrypt)); + } else { + cipherStream.reset(new SymmetricCipherStream( + m_device, SymmetricCipher::Twofish, SymmetricCipher::Cbc, SymmetricCipher::Decrypt)); } if (!cipherStream->init(finalKey, m_encryptionIV)) { @@ -375,8 +366,7 @@ SymmetricCipherStream* KeePass1Reader::testKeys(const QString& password, const Q if (success) { break; - } - else { + } else { cipherStream.reset(); } } @@ -476,8 +466,7 @@ Group* KeePass1Reader::readGroup(QIODevice* cipherStream) case 0x0002: group->setName(QString::fromUtf8(fieldData.constData())); break; - case 0x0003: - { + case 0x0003: { if (fieldSize != 5) { raiseError(tr("Incorrect group creation time field size")); return nullptr; @@ -488,8 +477,7 @@ Group* KeePass1Reader::readGroup(QIODevice* cipherStream) } break; } - case 0x0004: - { + case 0x0004: { if (fieldSize != 5) { raiseError(tr("Incorrect group modification time field size")); return nullptr; @@ -500,8 +488,7 @@ Group* KeePass1Reader::readGroup(QIODevice* cipherStream) } break; } - case 0x0005: - { + case 0x0005: { if (fieldSize != 5) { raiseError(tr("Incorrect group access time field size")); } @@ -511,8 +498,7 @@ Group* KeePass1Reader::readGroup(QIODevice* cipherStream) } break; } - case 0x0006: - { + case 0x0006: { if (fieldSize != 5) { raiseError(tr("Incorrect group expiry time field size")); } @@ -523,8 +509,7 @@ Group* KeePass1Reader::readGroup(QIODevice* cipherStream) } break; } - case 0x0007: - { + case 0x0007: { if (fieldSize != 4) { raiseError(tr("Incorrect group icon field size")); return nullptr; @@ -533,8 +518,7 @@ Group* KeePass1Reader::readGroup(QIODevice* cipherStream) group->setIcon(iconNumber); break; } - case 0x0008: - { + case 0x0008: { if (fieldSize != 2) { raiseError(tr("Incorrect group level field size")); return nullptr; @@ -610,8 +594,7 @@ Entry* KeePass1Reader::readEntry(QIODevice* cipherStream) } m_entryUuids.insert(fieldData, entry.data()); break; - case 0x0002: - { + case 0x0002: { if (fieldSize != 4) { raiseError(tr("Invalid entry group id field size")); return nullptr; @@ -620,8 +603,7 @@ Entry* KeePass1Reader::readEntry(QIODevice* cipherStream) m_entryGroupIds.insert(entry.data(), groupId); break; } - case 0x0003: - { + case 0x0003: { if (fieldSize != 4) { raiseError(tr("Invalid entry icon field size")); return nullptr; @@ -645,8 +627,7 @@ Entry* KeePass1Reader::readEntry(QIODevice* cipherStream) case 0x0008: parseNotes(QString::fromUtf8(fieldData.constData()), entry.data()); break; - case 0x0009: - { + case 0x0009: { if (fieldSize != 5) { raiseError(tr("Invalid entry creation time field size")); return nullptr; @@ -657,8 +638,7 @@ Entry* KeePass1Reader::readEntry(QIODevice* cipherStream) } break; } - case 0x000A: - { + case 0x000A: { if (fieldSize != 5) { raiseError(tr("Invalid entry modification time field size")); return nullptr; @@ -669,8 +649,7 @@ Entry* KeePass1Reader::readEntry(QIODevice* cipherStream) } break; } - case 0x000B: - { + case 0x000B: { if (fieldSize != 5) { raiseError(tr("Invalid entry creation time field size")); return nullptr; @@ -681,8 +660,7 @@ Entry* KeePass1Reader::readEntry(QIODevice* cipherStream) } break; } - case 0x000C: - { + case 0x000C: { if (fieldSize != 5) { raiseError(tr("Invalid entry expiry time field size")); return nullptr; @@ -734,27 +712,23 @@ void KeePass1Reader::parseNotes(const QString& rawNotes, Entry* entry) if (sequenceRegexp.exactMatch(line)) { if (sequenceRegexp.cap(1).isEmpty()) { entry->setDefaultAutoTypeSequence(sequenceRegexp.cap(2)); - } - else { + } else { sequences[sequenceRegexp.cap(1).toInt()] = sequenceRegexp.cap(2); } lastLineAutoType = true; - } - else if (windowRegexp.exactMatch(line)) { + } else if (windowRegexp.exactMatch(line)) { int nr; if (windowRegexp.cap(1).isEmpty()) { nr = -1; // special number that matches no other sequence - } - else { + } else { nr = windowRegexp.cap(1).toInt(); } windows[nr].append(windowRegexp.cap(2)); lastLineAutoType = true; - } - else { + } else { // don't add empty lines following a removed auto-type line if (!lastLineAutoType || !line.isEmpty()) { notes.append(line); @@ -788,8 +762,7 @@ bool KeePass1Reader::constructGroupTree(const QList& groups) if (level == 0) { groups[i]->setParent(m_db->rootGroup()); - } - else { + } else { for (int j = (i - 1); j >= 0; j--) { if (m_groupLevels.value(groups[j]) < level) { if ((level - m_groupLevels.value(groups[j])) != 1) { @@ -818,13 +791,11 @@ void KeePass1Reader::parseMetaStream(const Entry* entry) if (!parseGroupTreeState(data)) { qWarning("Unable to parse group tree state metastream."); } - } - else if (entry->notes() == "KPX_CUSTOM_ICONS_4") { + } else if (entry->notes() == "KPX_CUSTOM_ICONS_4") { if (!parseCustomIcons4(data)) { qWarning("Unable to parse custom icons metastream."); } - } - else { + } else { qWarning("Ignoring unknown metastream \"%s\".", entry->notes().toLocal8Bit().constData()); } } @@ -962,20 +933,16 @@ QDateTime KeePass1Reader::dateFromPackedStruct(const QByteArray& data) // check for the special "never" datetime if (dateTime == QDateTime(QDate(2999, 12, 28), QTime(23, 59, 59), Qt::UTC)) { return QDateTime(); - } - else { + } else { return dateTime; } } bool KeePass1Reader::isMetaStream(const Entry* entry) { - return entry->attachments()->keys().contains("bin-stream") - && !entry->notes().isEmpty() - && entry->title() == "Meta-Info" - && entry->username() == "SYSTEM" - && entry->url() == "$" - && entry->iconNumber() == 0; + return entry->attachments()->keys().contains("bin-stream") && !entry->notes().isEmpty() + && entry->title() == "Meta-Info" && entry->username() == "SYSTEM" && entry->url() == "$" + && entry->iconNumber() == 0; } QByteArray KeePass1Reader::readKeyfile(QIODevice* device) @@ -1002,8 +969,7 @@ QByteArray KeePass1Reader::readKeyfile(QIODevice* device) if (Tools::isHex(data)) { return QByteArray::fromHex(data); - } - else { + } else { device->seek(0); } } @@ -1021,16 +987,13 @@ QByteArray KeePass1Reader::readKeyfile(QIODevice* device) return cryptoHash.result(); } - QByteArray KeePass1Key::rawKey() const { if (m_keyfileData.isEmpty()) { return CryptoHash::hash(m_password, CryptoHash::Sha256); - } - else if (m_password.isEmpty()) { + } else if (m_password.isEmpty()) { return m_keyfileData; - } - else { + } else { CryptoHash keyHash(CryptoHash::Sha256); keyHash.addData(CryptoHash::hash(m_password, CryptoHash::Sha256)); keyHash.addData(m_keyfileData); diff --git a/src/format/KeePass1Reader.h b/src/format/KeePass1Reader.h index e98dd7d1..8302746c 100644 --- a/src/format/KeePass1Reader.h +++ b/src/format/KeePass1Reader.h @@ -34,12 +34,9 @@ class KeePass1Reader public: KeePass1Reader(); - Database* readDatabase(QIODevice* device, const QString& password, - QIODevice* keyfileDevice); - Database* readDatabase(QIODevice* device, const QString& password, - const QString& keyfileName); - Database* readDatabase(const QString& filename, const QString& password, - const QString& keyfileName); + Database* readDatabase(QIODevice* device, const QString& password, QIODevice* keyfileDevice); + Database* readDatabase(QIODevice* device, const QString& password, const QString& keyfileName); + Database* readDatabase(const QString& filename, const QString& password, const QString& keyfileName); bool hasError(); QString errorString(); @@ -51,8 +48,7 @@ private: UTF8 }; - SymmetricCipherStream* testKeys(const QString& password, const QByteArray& keyfileData, - qint64 contentPos); + SymmetricCipherStream* testKeys(const QString& password, const QByteArray& keyfileData, qint64 contentPos); QByteArray key(const QByteArray& password, const QByteArray& keyfileData); bool verifyKey(SymmetricCipherStream* cipherStream); Group* readGroup(QIODevice* cipherStream); diff --git a/src/format/KeePass2.cpp b/src/format/KeePass2.cpp index 9c0355cd..b53ff092 100644 --- a/src/format/KeePass2.cpp +++ b/src/format/KeePass2.cpp @@ -16,10 +16,10 @@ */ #include "KeePass2.h" -#include +#include "crypto/CryptoHash.h" #include "crypto/kdf/AesKdf.h" #include "crypto/kdf/Argon2Kdf.h" -#include "crypto/CryptoHash.h" +#include const Uuid KeePass2::CIPHER_AES = Uuid(QByteArray::fromHex("31c1f2e6bf714350be5805216afc5aff")); const Uuid KeePass2::CIPHER_TWOFISH = Uuid(QByteArray::fromHex("ad68f29f576f4bb9a36ad47af965346c")); @@ -47,16 +47,15 @@ const QString KeePass2::KDFPARAM_ARGON2_ASSOCDATA("A"); const QList> KeePass2::CIPHERS{ qMakePair(KeePass2::CIPHER_AES, QString(QT_TRANSLATE_NOOP("KeePass2", "AES: 256-bit"))), qMakePair(KeePass2::CIPHER_TWOFISH, QString(QT_TRANSLATE_NOOP("KeePass2", "Twofish: 256-bit"))), - qMakePair(KeePass2::CIPHER_CHACHA20, QString(QT_TRANSLATE_NOOP("KeePass2", "ChaCha20: 256-bit"))) -}; + qMakePair(KeePass2::CIPHER_CHACHA20, QString(QT_TRANSLATE_NOOP("KeePass2", "ChaCha20: 256-bit")))}; const QList> KeePass2::KDFS{ qMakePair(KeePass2::KDF_ARGON2, QString(QT_TRANSLATE_NOOP("KeePass2", "Argon2 (KDBX 4 – recommended)"))), qMakePair(KeePass2::KDF_AES_KDBX4, QString(QT_TRANSLATE_NOOP("KeePass2", "AES-KDF (KDBX 4)"))), - qMakePair(KeePass2::KDF_AES_KDBX3, QString(QT_TRANSLATE_NOOP("KeePass2", "AES-KDF (KDBX 3.1)"))) -}; + qMakePair(KeePass2::KDF_AES_KDBX3, QString(QT_TRANSLATE_NOOP("KeePass2", "AES-KDF (KDBX 3.1)")))}; -QByteArray KeePass2::hmacKey(QByteArray masterSeed, QByteArray transformedMasterKey) { +QByteArray KeePass2::hmacKey(QByteArray masterSeed, QByteArray transformedMasterKey) +{ CryptoHash hmacKeyHash(CryptoHash::Sha512); hmacKeyHash.addData(masterSeed); hmacKeyHash.addData(transformedMasterKey); diff --git a/src/format/KeePass2.h b/src/format/KeePass2.h index a46df7fa..bcfef238 100644 --- a/src/format/KeePass2.h +++ b/src/format/KeePass2.h @@ -1,137 +1,137 @@ - /* - * Copyright (C) 2010 Felix Geyer - * - * 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 (C) 2010 Felix Geyer + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ #ifndef KEEPASSX_KEEPASS2_H #define KEEPASSX_KEEPASS2_H -#include -#include -#include #include +#include #include +#include +#include +#include "core/Uuid.h" #include "crypto/SymmetricCipher.h" #include "crypto/kdf/Kdf.h" -#include "core/Uuid.h" namespace KeePass2 { -constexpr quint32 SIGNATURE_1 = 0x9AA2D903; -constexpr quint32 SIGNATURE_2 = 0xB54BFB67; + constexpr quint32 SIGNATURE_1 = 0x9AA2D903; + constexpr quint32 SIGNATURE_2 = 0xB54BFB67; -constexpr quint32 FILE_VERSION_CRITICAL_MASK = 0xFFFF0000; -constexpr quint32 FILE_VERSION_4 = 0x00040000; -constexpr quint32 FILE_VERSION_3_1 = 0x00030001; -constexpr quint32 FILE_VERSION_3 = 0x00030000; -constexpr quint32 FILE_VERSION_2 = 0x00020000; -constexpr quint32 FILE_VERSION_MIN = FILE_VERSION_2; + constexpr quint32 FILE_VERSION_CRITICAL_MASK = 0xFFFF0000; + constexpr quint32 FILE_VERSION_4 = 0x00040000; + constexpr quint32 FILE_VERSION_3_1 = 0x00030001; + constexpr quint32 FILE_VERSION_3 = 0x00030000; + constexpr quint32 FILE_VERSION_2 = 0x00020000; + constexpr quint32 FILE_VERSION_MIN = FILE_VERSION_2; -constexpr quint16 VARIANTMAP_VERSION = 0x0100; -constexpr quint16 VARIANTMAP_CRITICAL_MASK = 0xFF00; + constexpr quint16 VARIANTMAP_VERSION = 0x0100; + constexpr quint16 VARIANTMAP_CRITICAL_MASK = 0xFF00; -const QSysInfo::Endian BYTEORDER = QSysInfo::LittleEndian; + const QSysInfo::Endian BYTEORDER = QSysInfo::LittleEndian; -extern const Uuid CIPHER_AES; -extern const Uuid CIPHER_TWOFISH; -extern const Uuid CIPHER_CHACHA20; + extern const Uuid CIPHER_AES; + extern const Uuid CIPHER_TWOFISH; + extern const Uuid CIPHER_CHACHA20; -extern const Uuid KDF_AES_KDBX3; -extern const Uuid KDF_AES_KDBX4; -extern const Uuid KDF_ARGON2; + extern const Uuid KDF_AES_KDBX3; + extern const Uuid KDF_AES_KDBX4; + extern const Uuid KDF_ARGON2; -extern const QByteArray INNER_STREAM_SALSA20_IV; + extern const QByteArray INNER_STREAM_SALSA20_IV; -extern const QString KDFPARAM_UUID; -extern const QString KDFPARAM_AES_ROUNDS; -extern const QString KDFPARAM_AES_SEED; -extern const QString KDFPARAM_ARGON2_SALT; -extern const QString KDFPARAM_ARGON2_PARALLELISM; -extern const QString KDFPARAM_ARGON2_MEMORY; -extern const QString KDFPARAM_ARGON2_ITERATIONS; -extern const QString KDFPARAM_ARGON2_VERSION; -extern const QString KDFPARAM_ARGON2_SECRET; -extern const QString KDFPARAM_ARGON2_ASSOCDATA; + extern const QString KDFPARAM_UUID; + extern const QString KDFPARAM_AES_ROUNDS; + extern const QString KDFPARAM_AES_SEED; + extern const QString KDFPARAM_ARGON2_SALT; + extern const QString KDFPARAM_ARGON2_PARALLELISM; + extern const QString KDFPARAM_ARGON2_MEMORY; + extern const QString KDFPARAM_ARGON2_ITERATIONS; + extern const QString KDFPARAM_ARGON2_VERSION; + extern const QString KDFPARAM_ARGON2_SECRET; + extern const QString KDFPARAM_ARGON2_ASSOCDATA; -extern const QList> CIPHERS; -extern const QList> KDFS; + extern const QList> CIPHERS; + extern const QList> KDFS; -enum class HeaderFieldID -{ - EndOfHeader = 0, - Comment = 1, - CipherID = 2, - CompressionFlags = 3, - MasterSeed = 4, - TransformSeed = 5, - TransformRounds = 6, - EncryptionIV = 7, - ProtectedStreamKey = 8, - StreamStartBytes = 9, - InnerRandomStreamID = 10, - KdfParameters = 11, - PublicCustomData = 12 -}; + enum class HeaderFieldID + { + EndOfHeader = 0, + Comment = 1, + CipherID = 2, + CompressionFlags = 3, + MasterSeed = 4, + TransformSeed = 5, + TransformRounds = 6, + EncryptionIV = 7, + ProtectedStreamKey = 8, + StreamStartBytes = 9, + InnerRandomStreamID = 10, + KdfParameters = 11, + PublicCustomData = 12 + }; -enum class InnerHeaderFieldID : quint8 -{ - End = 0, - InnerRandomStreamID = 1, - InnerRandomStreamKey = 2, - Binary = 3 -}; + enum class InnerHeaderFieldID : quint8 + { + End = 0, + InnerRandomStreamID = 1, + InnerRandomStreamKey = 2, + Binary = 3 + }; -enum class ProtectedStreamAlgo -{ - ArcFourVariant = 1, - Salsa20 = 2, - ChaCha20 = 3, - InvalidProtectedStreamAlgo = -1 -}; + enum class ProtectedStreamAlgo + { + ArcFourVariant = 1, + Salsa20 = 2, + ChaCha20 = 3, + InvalidProtectedStreamAlgo = -1 + }; -enum class VariantMapFieldType : quint8 -{ - End = 0, - // Byte = 0x02, - // UInt16 = 0x03, - UInt32 = 0x04, - UInt64 = 0x05, - // Signed mask: 0x08 - Bool = 0x08, - // SByte = 0x0A, - // Int16 = 0x0B, - Int32 = 0x0C, - Int64 = 0x0D, - // Float = 0x10, - // Double = 0x11, - // Decimal = 0x12, - // Char = 0x17, // 16-bit Unicode character - String = 0x18, - // Array mask: 0x40 - ByteArray = 0x42 -}; + enum class VariantMapFieldType : quint8 + { + End = 0, + // Byte = 0x02, + // UInt16 = 0x03, + UInt32 = 0x04, + UInt64 = 0x05, + // Signed mask: 0x08 + Bool = 0x08, + // SByte = 0x0A, + // Int16 = 0x0B, + Int32 = 0x0C, + Int64 = 0x0D, + // Float = 0x10, + // Double = 0x11, + // Decimal = 0x12, + // Char = 0x17, // 16-bit Unicode character + String = 0x18, + // Array mask: 0x40 + ByteArray = 0x42 + }; -QByteArray hmacKey(QByteArray masterSeed, QByteArray transformedMasterKey); -QSharedPointer kdfFromParameters(const QVariantMap& p); -QVariantMap kdfToParameters(QSharedPointer kdf); -QSharedPointer uuidToKdf(const Uuid& uuid); -Uuid kdfToUuid(QSharedPointer kdf); -ProtectedStreamAlgo idToProtectedStreamAlgo(quint32 id); + QByteArray hmacKey(QByteArray masterSeed, QByteArray transformedMasterKey); + QSharedPointer kdfFromParameters(const QVariantMap& p); + QVariantMap kdfToParameters(QSharedPointer kdf); + QSharedPointer uuidToKdf(const Uuid& uuid); + Uuid kdfToUuid(QSharedPointer kdf); + ProtectedStreamAlgo idToProtectedStreamAlgo(quint32 id); -} // namespace KeePass2 +} // namespace KeePass2 #endif // KEEPASSX_KEEPASS2_H diff --git a/src/format/KeePass2RandomStream.cpp b/src/format/KeePass2RandomStream.cpp index 26824b7e..2f8c8340 100644 --- a/src/format/KeePass2RandomStream.cpp +++ b/src/format/KeePass2RandomStream.cpp @@ -30,8 +30,7 @@ bool KeePass2RandomStream::init(const QByteArray& key) { switch (m_cipher.algorithm()) { case SymmetricCipher::Salsa20: - return m_cipher.init(CryptoHash::hash(key, CryptoHash::Sha256), - KeePass2::INNER_STREAM_SALSA20_IV); + return m_cipher.init(CryptoHash::hash(key, CryptoHash::Sha256), KeePass2::INNER_STREAM_SALSA20_IV); case SymmetricCipher::ChaCha20: { QByteArray keyIv = CryptoHash::hash(key, CryptoHash::Sha512); return m_cipher.init(keyIv.left(32), keyIv.mid(32, 12)); @@ -121,7 +120,8 @@ bool KeePass2RandomStream::loadBlock() return true; } -SymmetricCipher::Algorithm KeePass2RandomStream::mapAlgo(KeePass2::ProtectedStreamAlgo algo) { +SymmetricCipher::Algorithm KeePass2RandomStream::mapAlgo(KeePass2::ProtectedStreamAlgo algo) +{ switch (algo) { case KeePass2::ProtectedStreamAlgo::ChaCha20: return SymmetricCipher::ChaCha20; diff --git a/src/format/KeePass2RandomStream.h b/src/format/KeePass2RandomStream.h index 1e341bac..e41f5a5d 100644 --- a/src/format/KeePass2RandomStream.h +++ b/src/format/KeePass2RandomStream.h @@ -20,8 +20,8 @@ #include -#include "crypto/SymmetricCipher.h" #include "KeePass2.h" +#include "crypto/SymmetricCipher.h" class KeePass2RandomStream { diff --git a/src/format/KeePass2Reader.cpp b/src/format/KeePass2Reader.cpp index abc7f54e..1c16e76d 100644 --- a/src/format/KeePass2Reader.cpp +++ b/src/format/KeePass2Reader.cpp @@ -16,9 +16,9 @@ */ #include "format/KeePass2Reader.h" -#include "format/KeePass1.h" #include "format/Kdbx3Reader.h" #include "format/Kdbx4Reader.h" +#include "format/KeePass1.h" #include diff --git a/src/format/KeePass2Reader.h b/src/format/KeePass2Reader.h index 1b91223e..c4947c73 100644 --- a/src/format/KeePass2Reader.h +++ b/src/format/KeePass2Reader.h @@ -18,21 +18,21 @@ #ifndef KEEPASSX_KEEPASS2READER_H #define KEEPASSX_KEEPASS2READER_H -#include "format/KeePass2.h" -#include "core/Database.h" -#include "keys/CompositeKey.h" #include "KdbxReader.h" +#include "core/Database.h" +#include "format/KeePass2.h" +#include "keys/CompositeKey.h" -#include #include -#include #include -#include #include +#include +#include +#include class KeePass2Reader { -Q_DECLARE_TR_FUNCTIONS(KdbxReader) + Q_DECLARE_TR_FUNCTIONS(KdbxReader) public: Database* readDatabase(const QString& filename, const CompositeKey& key); @@ -46,6 +46,7 @@ public: QSharedPointer reader() const; quint32 version() const; + private: void raiseError(const QString& errorMessage); diff --git a/src/format/KeePass2Repair.cpp b/src/format/KeePass2Repair.cpp index 47ed59dc..508a9517 100644 --- a/src/format/KeePass2Repair.cpp +++ b/src/format/KeePass2Repair.cpp @@ -21,11 +21,11 @@ #include #include "core/Group.h" +#include "format/Kdbx4Reader.h" +#include "format/KdbxXmlReader.h" #include "format/KeePass2.h" #include "format/KeePass2RandomStream.h" #include "format/KeePass2Reader.h" -#include "format/Kdbx4Reader.h" -#include "format/KdbxXmlReader.h" KeePass2Repair::RepairOutcome KeePass2Repair::repairDatabase(QIODevice* device, const CompositeKey& key) { @@ -51,8 +51,7 @@ KeePass2Repair::RepairOutcome KeePass2Repair::repairDatabase(QIODevice* device, QRegExp encodingRegExp("encoding=\"([^\"]+)\"", Qt::CaseInsensitive, QRegExp::RegExp2); if (encodingRegExp.indexIn(xmlStart) != -1) { if (encodingRegExp.cap(1).compare("utf-8", Qt::CaseInsensitive) != 0 - && encodingRegExp.cap(1).compare("utf8", Qt::CaseInsensitive) != 0) - { + && encodingRegExp.cap(1).compare("utf8", Qt::CaseInsensitive) != 0) { // database is not utf-8 encoded, we don't support repairing that return qMakePair(RepairFailed, nullptr); } @@ -92,8 +91,7 @@ KeePass2Repair::RepairOutcome KeePass2Repair::repairDatabase(QIODevice* device, if (hasError) { return qMakePair(RepairFailed, nullptr); - } - else { + } else { return qMakePair(RepairSuccess, db.take()); } } diff --git a/src/format/KeePass2Writer.cpp b/src/format/KeePass2Writer.cpp index 325986a3..262bebc2 100644 --- a/src/format/KeePass2Writer.cpp +++ b/src/format/KeePass2Writer.cpp @@ -15,16 +15,16 @@ * along with this program. If not, see . */ -#include #include +#include #include "core/Database.h" #include "core/Group.h" #include "core/Metadata.h" #include "crypto/kdf/AesKdf.h" -#include "format/KeePass2Writer.h" #include "format/Kdbx3Writer.h" #include "format/Kdbx4Writer.h" +#include "format/KeePass2Writer.h" /** * Write a database to a KDBX file. @@ -52,17 +52,17 @@ bool KeePass2Writer::implicitUpgradeNeeded(Database const* db) const return true; } - for (const auto& group: db->rootGroup()->groupsRecursive(true)) { + for (const auto& group : db->rootGroup()->groupsRecursive(true)) { if (group->customData() && !group->customData()->isEmpty()) { return true; } - for (const auto& entry: group->entries()) { + for (const auto& entry : group->entries()) { if (entry->customData() && !entry->customData()->isEmpty()) { return true; } - for (const auto& historyItem: entry->historyItems()) { + for (const auto& historyItem : entry->historyItems()) { if (historyItem->customData() && !historyItem->customData()->isEmpty()) { return true; } @@ -81,7 +81,8 @@ bool KeePass2Writer::implicitUpgradeNeeded(Database const* db) const * @return true on success */ -bool KeePass2Writer::writeDatabase(QIODevice* device, Database* db) { +bool KeePass2Writer::writeDatabase(QIODevice* device, Database* db) +{ m_error = false; m_errorStr.clear(); diff --git a/src/format/KeePass2Writer.h b/src/format/KeePass2Writer.h index f024d4a8..e5b26eae 100644 --- a/src/format/KeePass2Writer.h +++ b/src/format/KeePass2Writer.h @@ -28,7 +28,7 @@ class Database; class KeePass2Writer { -Q_DECLARE_TR_FUNCTIONS(KeePass2Writer) + Q_DECLARE_TR_FUNCTIONS(KeePass2Writer) public: bool writeDatabase(const QString& filename, Database* db); diff --git a/src/gui/AboutDialog.cpp b/src/gui/AboutDialog.cpp index 73d8ec55..5a082851 100644 --- a/src/gui/AboutDialog.cpp +++ b/src/gui/AboutDialog.cpp @@ -20,16 +20,16 @@ #include "ui_AboutDialog.h" #include "config-keepassx.h" -#include "version.h" #include "core/FilePath.h" #include "crypto/Crypto.h" +#include "version.h" #include #include AboutDialog::AboutDialog(QWidget* parent) - : QDialog(parent), - m_ui(new Ui::AboutDialog()) + : QDialog(parent) + , m_ui(new Ui::AboutDialog()) { m_ui->setupUi(this); @@ -47,8 +47,7 @@ AboutDialog::AboutDialog(QWidget* parent) QString commitHash; if (!QString(GIT_HEAD).isEmpty()) { commitHash = GIT_HEAD; - } - else if (!QString(DIST_HASH).contains("Format")) { + } else if (!QString(DIST_HASH).contains("Format")) { commitHash = DIST_HASH; } @@ -66,16 +65,16 @@ AboutDialog::AboutDialog(QWidget* parent) #endif debugInfo.append("\n").append(QString("%1\n- Qt %2\n- %3\n\n") - .arg(tr("Libraries:")) - .arg(QString::fromLocal8Bit(qVersion())) - .arg(Crypto::backendVersion())); + .arg(tr("Libraries:")) + .arg(QString::fromLocal8Bit(qVersion())) + .arg(Crypto::backendVersion())); #if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0) debugInfo.append(tr("Operating system: %1\nCPU architecture: %2\nKernel: %3 %4") - .arg(QSysInfo::prettyProductName(), - QSysInfo::currentCpuArchitecture(), - QSysInfo::kernelType(), - QSysInfo::kernelVersion())); + .arg(QSysInfo::prettyProductName(), + QSysInfo::currentCpuArchitecture(), + QSysInfo::kernelType(), + QSysInfo::kernelVersion())); debugInfo.append("\n\n"); #endif diff --git a/src/gui/AboutDialog.h b/src/gui/AboutDialog.h index 9d0c1c35..bd6b2edb 100644 --- a/src/gui/AboutDialog.h +++ b/src/gui/AboutDialog.h @@ -22,7 +22,8 @@ #include #include -namespace Ui { +namespace Ui +{ class AboutDialog; } diff --git a/src/gui/Application.cpp b/src/gui/Application.cpp index 48cd0d8d..02209b14 100644 --- a/src/gui/Application.cpp +++ b/src/gui/Application.cpp @@ -34,13 +34,14 @@ #if defined(Q_OS_UNIX) #include -#include #include +#include #endif -namespace { -constexpr int WaitTimeoutMSec = 150; -const char BlockSizeProperty[] = "blockSize"; +namespace +{ + constexpr int WaitTimeoutMSec = 150; + const char BlockSizeProperty[] = "blockSize"; } #if defined(Q_OS_UNIX) && !defined(Q_OS_OSX) @@ -70,7 +71,7 @@ public: Q_UNUSED(result); if (eventType == QByteArrayLiteral("windows_generic_MSG") - || eventType == QByteArrayLiteral("windows_dispatcher_MSG")) { + || eventType == QByteArrayLiteral("windows_dispatcher_MSG")) { int retCode = autoType()->callEventFilter(message); if (retCode == 1) { return true; @@ -109,8 +110,8 @@ Application::Application(int& argc, char** argv) identifier += "-" + userName; } #ifdef QT_DEBUG - // In DEBUG mode don't interfere with Release instances - identifier += "-DEBUG"; + // In DEBUG mode don't interfere with Release instances + identifier += "-DEBUG"; #endif QString lockName = identifier + ".lock"; m_socketName = identifier + ".socket"; @@ -146,9 +147,10 @@ Application::Application(int& argc, char** argv) if (!m_alreadyRunning) { // If we get here then the original instance is likely dead - qWarning() << QCoreApplication::translate("Main", - "Existing single-instance lock file is invalid. Launching new instance.") - .toUtf8().constData(); + qWarning() << QCoreApplication::translate( + "Main", "Existing single-instance lock file is invalid. Launching new instance.") + .toUtf8() + .constData(); // forceably reset the lock file m_lockFile->removeStaleLockFile(); @@ -161,8 +163,9 @@ Application::Application(int& argc, char** argv) } default: qWarning() << QCoreApplication::translate("Main", - "The lock file could not be created. Single-instance mode disabled.") - .toUtf8().constData(); + "The lock file could not be created. Single-instance mode disabled.") + .toUtf8() + .constData(); } } @@ -214,17 +217,17 @@ void Application::registerUnixSignals() // application will be unresponsive to signals such as SIGINT or SIGTERM return; } - - QVector const handledSignals = { SIGQUIT, SIGINT, SIGTERM, SIGHUP }; - for (auto s: handledSignals) { + + QVector const handledSignals = {SIGQUIT, SIGINT, SIGTERM, SIGHUP}; + for (auto s : handledSignals) { struct sigaction sigAction; - + sigAction.sa_handler = handleUnixSignal; sigemptyset(&sigAction.sa_mask); sigAction.sa_flags = 0 | SA_RESTART; sigaction(s, &sigAction, nullptr); } - + m_unixSignalNotifier = new QSocketNotifier(unixSignalSocket[1], QSocketNotifier::Read, this); connect(m_unixSignalNotifier, SIGNAL(activated(int)), this, SLOT(quitBySignal())); } @@ -232,16 +235,15 @@ void Application::registerUnixSignals() void Application::handleUnixSignal(int sig) { switch (sig) { - case SIGQUIT: - case SIGINT: - case SIGTERM: - { - char buf = 0; - Q_UNUSED(::write(unixSignalSocket[0], &buf, sizeof(buf))); - return; - } - case SIGHUP: - return; + case SIGQUIT: + case SIGINT: + case SIGTERM: { + char buf = 0; + Q_UNUSED(::write(unixSignalSocket[0], &buf, sizeof(buf))); + return; + } + case SIGHUP: + return; } } @@ -289,7 +291,7 @@ void Application::socketReadyRead() QStringList fileNames; in >> fileNames; - for (const QString& fileName: asConst(fileNames)) { + for (const QString& fileName : asConst(fileNames)) { const QFileInfo fInfo(fileName); if (fInfo.isFile() && fInfo.suffix().toLower() == "kdbx") { emit openFile(fileName); @@ -319,8 +321,7 @@ bool Application::sendFileNamesToRunningInstance(const QStringList& fileNames) QByteArray data; QDataStream out(&data, QIODevice::WriteOnly); out.setVersion(QDataStream::Qt_5_0); - out << quint32(0) - << fileNames; + out << quint32(0) << fileNames; out.device()->seek(0); out << quint32(data.size() - sizeof(quint32)); @@ -329,4 +330,3 @@ bool Application::sendFileNamesToRunningInstance(const QStringList& fileNames) const bool disconnected = client.waitForDisconnected(WaitTimeoutMSec); return writeOk && disconnected; } - diff --git a/src/gui/Application.h b/src/gui/Application.h index 1f575936..a6c6fdf9 100644 --- a/src/gui/Application.h +++ b/src/gui/Application.h @@ -56,7 +56,7 @@ private slots: private: QWidget* m_mainWindow; - + #if defined(Q_OS_UNIX) /** * Register Unix signals such as SIGINT and SIGTERM for clean shutdown. diff --git a/src/gui/CategoryListWidget.cpp b/src/gui/CategoryListWidget.cpp index f091cc24..14429083 100644 --- a/src/gui/CategoryListWidget.cpp +++ b/src/gui/CategoryListWidget.cpp @@ -19,15 +19,15 @@ #include "ui_CategoryListWidget.h" #include +#include #include #include #include -#include CategoryListWidget::CategoryListWidget(QWidget* parent) - : QWidget(parent), - m_itemDelegate(nullptr), - m_ui(new Ui::CategoryListWidget()) + : QWidget(parent) + , m_itemDelegate(nullptr) + , m_ui(new Ui::CategoryListWidget()) { m_ui->setupUi(this); m_itemDelegate = new CategoryListWidgetDelegate(m_ui->categoryList); @@ -38,7 +38,8 @@ CategoryListWidget::CategoryListWidget(QWidget* parent) connect(m_ui->scrollUp, SIGNAL(clicked()), SLOT(scrollCategoriesUp())); connect(m_ui->scrollDown, SIGNAL(clicked()), SLOT(scrollCategoriesDown())); connect(m_ui->categoryList->verticalScrollBar(), SIGNAL(valueChanged(int)), SLOT(updateCategoryScrollButtons())); - connect(m_ui->categoryList->verticalScrollBar(), SIGNAL(rangeChanged(int, int)), SLOT(updateCategoryScrollButtons())); + connect( + m_ui->categoryList->verticalScrollBar(), SIGNAL(rangeChanged(int, int)), SLOT(updateCategoryScrollButtons())); } CategoryListWidget::~CategoryListWidget() @@ -128,16 +129,14 @@ void CategoryListWidget::updateCategoryScrollButtons() void CategoryListWidget::scrollCategoriesUp() { - m_ui->categoryList->verticalScrollBar()->setValue( - m_ui->categoryList->verticalScrollBar()->value() - m_ui->categoryList->verticalScrollBar()->pageStep() - ); + m_ui->categoryList->verticalScrollBar()->setValue(m_ui->categoryList->verticalScrollBar()->value() + - m_ui->categoryList->verticalScrollBar()->pageStep()); } void CategoryListWidget::scrollCategoriesDown() { - m_ui->categoryList->verticalScrollBar()->setValue( - m_ui->categoryList->verticalScrollBar()->value() + m_ui->categoryList->verticalScrollBar()->pageStep() - ); + m_ui->categoryList->verticalScrollBar()->setValue(m_ui->categoryList->verticalScrollBar()->value() + + m_ui->categoryList->verticalScrollBar()->pageStep()); } void CategoryListWidget::emitCategoryChanged(int index) @@ -145,14 +144,12 @@ void CategoryListWidget::emitCategoryChanged(int index) emit categoryChanged(index); } - /* =============================================================================================== */ - CategoryListWidgetDelegate::CategoryListWidgetDelegate(QListWidget* parent) - : QStyledItemDelegate(parent), - m_listWidget(parent), - m_size(96, 96) + : QStyledItemDelegate(parent) + , m_listWidget(parent) + , m_size(96, 96) { m_size.setWidth(minWidth()); if (m_listWidget && m_listWidget->width() > m_size.width()) { @@ -165,7 +162,10 @@ CategoryListWidgetDelegate::CategoryListWidgetDelegate(QListWidget* parent) class WindowsCorrectedStyle : public QProxyStyle { public: - void drawPrimitive(PrimitiveElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget) const override + void drawPrimitive(PrimitiveElement element, + const QStyleOption* option, + QPainter* painter, + const QWidget* widget) const override { painter->save(); @@ -187,7 +187,9 @@ public: }; #endif -void CategoryListWidgetDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const +void CategoryListWidgetDelegate::paint(QPainter* painter, + const QStyleOptionViewItem& option, + const QModelIndex& index) const { QStyleOptionViewItem opt = option; initStyleOption(&opt, index); @@ -225,8 +227,8 @@ int CategoryListWidgetDelegate::minWidth() const for (int i = 0; i < c; ++i) { QFontMetrics fm(m_listWidget->font()); - QRect fontRect = fm.boundingRect( - QRect(0, 0, 0, 0), Qt::TextWordWrap | Qt::ElideNone, m_listWidget->item(i)->text()); + QRect fontRect = + fm.boundingRect(QRect(0, 0, 0, 0), Qt::TextWordWrap | Qt::ElideNone, m_listWidget->item(i)->text()); if (fontRect.width() > maxWidth) { maxWidth = fontRect.width(); @@ -239,7 +241,7 @@ int CategoryListWidgetDelegate::minWidth() const return maxWidth < m_size.height() ? m_size.height() : maxWidth; } -QSize CategoryListWidgetDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const +QSize CategoryListWidgetDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const { Q_UNUSED(option); Q_UNUSED(index); diff --git a/src/gui/CategoryListWidget.h b/src/gui/CategoryListWidget.h index 3cf82fd1..911b5cc9 100644 --- a/src/gui/CategoryListWidget.h +++ b/src/gui/CategoryListWidget.h @@ -15,14 +15,15 @@ * along with this program. If not, see . */ -#include -#include #include +#include +#include class CategoryListWidgetDelegate; class QListWidget; -namespace Ui { +namespace Ui +{ class CategoryListWidget; } @@ -46,7 +47,7 @@ signals: protected: void showEvent(QShowEvent* event) override; - void resizeEvent(QResizeEvent * event) override; + void resizeEvent(QResizeEvent* event) override; QSize sizeHint() const override; QSize minimumSizeHint() const override; @@ -63,10 +64,8 @@ private: Q_DISABLE_COPY(CategoryListWidget) }; - /* =============================================================================================== */ - class CategoryListWidgetDelegate : public QStyledItemDelegate { Q_OBJECT @@ -77,10 +76,9 @@ public: protected: void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override; - QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override; + QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const override; private: - const int ICON_SIZE = 32; QPointer m_listWidget; diff --git a/src/gui/ChangeMasterKeyWidget.cpp b/src/gui/ChangeMasterKeyWidget.cpp index 79fd2712..b91495f7 100644 --- a/src/gui/ChangeMasterKeyWidget.cpp +++ b/src/gui/ChangeMasterKeyWidget.cpp @@ -19,19 +19,19 @@ #include "ChangeMasterKeyWidget.h" #include "ui_ChangeMasterKeyWidget.h" +#include "MainWindow.h" #include "core/FilePath.h" +#include "crypto/Random.h" +#include "gui/FileDialog.h" +#include "gui/MessageBox.h" #include "keys/FileKey.h" #include "keys/PasswordKey.h" #include "keys/YkChallengeResponseKey.h" -#include "gui/FileDialog.h" -#include "gui/MessageBox.h" -#include "crypto/Random.h" -#include "MainWindow.h" #include "config-keepassx.h" -#include #include +#include ChangeMasterKeyWidget::ChangeMasterKeyWidget(QWidget* parent) : DialogyWidget(parent) @@ -65,7 +65,7 @@ ChangeMasterKeyWidget::ChangeMasterKeyWidget(QWidget* parent) connect(m_ui->challengeResponseGroup, SIGNAL(clicked(bool)), SLOT(setOkEnabled())); connect(m_ui->buttonRedetectYubikey, SIGNAL(clicked()), SLOT(pollYubikey())); - connect(YubiKey::instance(), SIGNAL(detected(int,bool)), SLOT(yubikeyDetected(int,bool)), Qt::QueuedConnection); + connect(YubiKey::instance(), SIGNAL(detected(int, bool)), SLOT(yubikeyDetected(int, bool)), Qt::QueuedConnection); connect(YubiKey::instance(), SIGNAL(notFound()), SLOT(noYubikeyFound()), Qt::QueuedConnection); #else m_ui->challengeResponseGroup->setVisible(false); @@ -86,8 +86,7 @@ void ChangeMasterKeyWidget::createKeyFile() bool created = FileKey::create(fileName, &errorMsg); if (!created) { m_ui->messageWidget->showMessage(tr("Unable to create key file: %1").arg(errorMsg), MessageWidget::Error); - } - else { + } else { m_ui->keyFileCombo->setEditText(fileName); } } @@ -138,15 +137,16 @@ void ChangeMasterKeyWidget::generateKey() if (m_ui->passwordGroup->isChecked()) { if (m_ui->enterPasswordEdit->text() == m_ui->repeatPasswordEdit->text()) { if (m_ui->enterPasswordEdit->text().isEmpty()) { - if (MessageBox::warning(this, tr("Empty password"), + if (MessageBox::warning(this, + tr("Empty password"), tr("Do you really want to use an empty string as password?"), - QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes) { + QMessageBox::Yes | QMessageBox::No) + != QMessageBox::Yes) { return; } } m_key.addKey(PasswordKey(m_ui->enterPasswordEdit->text())); - } - else { + } else { m_ui->messageWidget->showMessage(tr("Different passwords supplied."), MessageWidget::Error); m_ui->enterPasswordEdit->setText(""); m_ui->repeatPasswordEdit->setText(""); @@ -158,16 +158,16 @@ void ChangeMasterKeyWidget::generateKey() QString errorMsg; QString fileKeyName = m_ui->keyFileCombo->currentText(); if (!fileKey.load(fileKeyName, &errorMsg)) { - m_ui->messageWidget->showMessage( - tr("Failed to set %1 as the key file:\n%2").arg(fileKeyName, errorMsg), MessageWidget::Error); + m_ui->messageWidget->showMessage(tr("Failed to set %1 as the key file:\n%2").arg(fileKeyName, errorMsg), + MessageWidget::Error); return; } if (fileKey.type() != FileKey::Hashed) { QMessageBox::warning(this, tr("Legacy key file format"), tr("You are using a legacy key file format which may become\n" - "unsupported in the future.\n\n" - "Please consider generating a new key file."), + "unsupported in the future.\n\n" + "Please consider generating a new key file."), QMessageBox::Ok); } m_key.addKey(fileKey); @@ -186,8 +186,8 @@ void ChangeMasterKeyWidget::generateKey() // read blocking mode from LSB and slot index number from second LSB bool blocking = comboPayload & 1; - int slot = comboPayload >> 1; - auto key = QSharedPointer(new YkChallengeResponseKey(slot, blocking)); + int slot = comboPayload >> 1; + auto key = QSharedPointer(new YkChallengeResponseKey(slot, blocking)); m_key.addChallengeResponseKey(key); } #endif @@ -196,7 +196,6 @@ void ChangeMasterKeyWidget::generateKey() emit editFinished(true); } - void ChangeMasterKeyWidget::reject() { emit editFinished(false); @@ -240,9 +239,9 @@ void ChangeMasterKeyWidget::noYubikeyFound() void ChangeMasterKeyWidget::setOkEnabled() { - bool ok = m_ui->passwordGroup->isChecked() || - (m_ui->challengeResponseGroup->isChecked() && !m_ui->comboChallengeResponse->currentText().isEmpty()) || - (m_ui->keyFileGroup->isChecked() && !m_ui->keyFileCombo->currentText().isEmpty()); + bool ok = m_ui->passwordGroup->isChecked() + || (m_ui->challengeResponseGroup->isChecked() && !m_ui->comboChallengeResponse->currentText().isEmpty()) + || (m_ui->keyFileGroup->isChecked() && !m_ui->keyFileCombo->currentText().isEmpty()); m_ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(ok); } diff --git a/src/gui/ChangeMasterKeyWidget.h b/src/gui/ChangeMasterKeyWidget.h index 2825d8d5..2a4e0cc4 100644 --- a/src/gui/ChangeMasterKeyWidget.h +++ b/src/gui/ChangeMasterKeyWidget.h @@ -25,7 +25,8 @@ #include "keys/CompositeKey.h" class QLabel; -namespace Ui { +namespace Ui +{ class ChangeMasterKeyWidget; } diff --git a/src/gui/Clipboard.cpp b/src/gui/Clipboard.cpp index 2c0d3d6e..b30fd64b 100644 --- a/src/gui/Clipboard.cpp +++ b/src/gui/Clipboard.cpp @@ -88,8 +88,7 @@ void Clipboard::clearClipboard() clipboard->clear(QClipboard::Clipboard); } - if (clipboard->supportsSelection() - && (clipboard->text(QClipboard::Selection) == m_lastCopied)) { + if (clipboard->supportsSelection() && (clipboard->text(QClipboard::Selection) == m_lastCopied)) { clipboard->clear(QClipboard::Selection); } diff --git a/src/gui/Clipboard.h b/src/gui/Clipboard.h index 279ae7f0..60c66c88 100644 --- a/src/gui/Clipboard.h +++ b/src/gui/Clipboard.h @@ -55,7 +55,8 @@ private: QString m_lastCopied; }; -inline Clipboard* clipboard() { +inline Clipboard* clipboard() +{ return Clipboard::instance(); } diff --git a/src/gui/CloneDialog.cpp b/src/gui/CloneDialog.cpp index 7af50439..990a590e 100644 --- a/src/gui/CloneDialog.cpp +++ b/src/gui/CloneDialog.cpp @@ -19,12 +19,12 @@ #include "ui_CloneDialog.h" #include "config-keepassx.h" -#include "version.h" #include "core/Database.h" #include "core/Entry.h" #include "core/FilePath.h" #include "crypto/Crypto.h" #include "gui/DatabaseWidget.h" +#include "version.h" CloneDialog::CloneDialog(DatabaseWidget* parent, Database* db, Entry* entry) : QDialog(parent) diff --git a/src/gui/CloneDialog.h b/src/gui/CloneDialog.h index a925bb47..56993846 100644 --- a/src/gui/CloneDialog.h +++ b/src/gui/CloneDialog.h @@ -18,13 +18,14 @@ #ifndef KEEPASSX_CLONEDIALOG_H #define KEEPASSX_CLONEDIALOG_H +#include "core/Database.h" +#include "core/Entry.h" +#include "gui/DatabaseWidget.h" #include #include -#include "core/Entry.h" -#include "core/Database.h" -#include "gui/DatabaseWidget.h" -namespace Ui { +namespace Ui +{ class CloneDialog; } diff --git a/src/gui/DatabaseOpenWidget.cpp b/src/gui/DatabaseOpenWidget.cpp index 16792e78..78fa0858 100644 --- a/src/gui/DatabaseOpenWidget.cpp +++ b/src/gui/DatabaseOpenWidget.cpp @@ -22,20 +22,19 @@ #include "core/Config.h" #include "core/Database.h" #include "core/FilePath.h" -#include "gui/MainWindow.h" -#include "gui/FileDialog.h" -#include "gui/MessageBox.h" +#include "crypto/Random.h" #include "format/KeePass2Reader.h" +#include "gui/FileDialog.h" +#include "gui/MainWindow.h" +#include "gui/MessageBox.h" #include "keys/FileKey.h" #include "keys/PasswordKey.h" -#include "crypto/Random.h" #include "keys/YkChallengeResponseKey.h" #include "config-keepassx.h" -#include #include - +#include DatabaseOpenWidget::DatabaseOpenWidget(QWidget* parent) : DialogyWidget(parent) @@ -52,8 +51,7 @@ DatabaseOpenWidget::DatabaseOpenWidget(QWidget* parent) m_ui->labelHeadline->setFont(font); m_ui->buttonTogglePassword->setIcon(filePath()->onOffIcon("actions", "password-show")); - connect(m_ui->buttonTogglePassword, SIGNAL(toggled(bool)), - m_ui->editPassword, SLOT(setShowPassword(bool))); + connect(m_ui->buttonTogglePassword, SIGNAL(toggled(bool)), m_ui->editPassword, SLOT(setShowPassword(bool))); connect(m_ui->buttonBrowseFile, SIGNAL(clicked()), SLOT(browseKeyFile())); connect(m_ui->editPassword, SIGNAL(textChanged(QString)), SLOT(activatePassword())); @@ -97,8 +95,8 @@ void DatabaseOpenWidget::showEvent(QShowEvent* event) #ifdef WITH_XC_YUBIKEY // showEvent() may be called twice, so make sure we are only polling once if (!m_yubiKeyBeingPolled) { - connect(YubiKey::instance(), SIGNAL(detected(int, bool)), SLOT(yubikeyDetected(int, bool)), - Qt::QueuedConnection); + connect( + YubiKey::instance(), SIGNAL(detected(int, bool)), SLOT(yubikeyDetected(int, bool)), Qt::QueuedConnection); connect(YubiKey::instance(), SIGNAL(detectComplete()), SLOT(yubikeyDetectComplete()), Qt::QueuedConnection); connect(YubiKey::instance(), SIGNAL(notFound()), SLOT(noYubikeyFound()), Qt::QueuedConnection); @@ -147,7 +145,6 @@ void DatabaseOpenWidget::clearForms() m_db = nullptr; } - Database* DatabaseOpenWidget::database() { return m_db; @@ -178,8 +175,8 @@ void DatabaseOpenWidget::openDatabase() QFile file(m_filename); if (!file.open(QIODevice::ReadOnly)) { - m_ui->messageWidget->showMessage( - tr("Unable to open the database.").append("\n").append(file.errorString()), MessageWidget::Error); + m_ui->messageWidget->showMessage(tr("Unable to open the database.").append("\n").append(file.errorString()), + MessageWidget::Error); return; } if (m_db) { @@ -217,22 +214,21 @@ QSharedPointer DatabaseOpenWidget::databaseKey() QString keyFilename = m_ui->comboKeyFile->currentText(); QString errorMsg; if (!key.load(keyFilename, &errorMsg)) { - m_ui->messageWidget->showMessage(tr("Can't open key file:\n%1").arg(errorMsg), - MessageWidget::Error); + m_ui->messageWidget->showMessage(tr("Can't open key file:\n%1").arg(errorMsg), MessageWidget::Error); return QSharedPointer(); } if (key.type() != FileKey::Hashed && !config()->get("Messages/NoLegacyKeyFileWarning").toBool()) { QMessageBox legacyWarning; legacyWarning.setWindowTitle(tr("Legacy key file format")); legacyWarning.setText(tr("You are using a legacy key file format which may become\n" - "unsupported in the future.\n\n" - "Please consider generating a new key file.")); + "unsupported in the future.\n\n" + "Please consider generating a new key file.")); legacyWarning.setIcon(QMessageBox::Icon::Warning); legacyWarning.addButton(QMessageBox::Ok); legacyWarning.setDefaultButton(QMessageBox::Ok); legacyWarning.setCheckBox(new QCheckBox(tr("Don't show this warning again"))); - connect(legacyWarning.checkBox(), &QCheckBox::stateChanged, [](int state){ + connect(legacyWarning.checkBox(), &QCheckBox::stateChanged, [](int state) { config()->set("Messages/NoLegacyKeyFileWarning", state == Qt::CheckState::Checked); }); diff --git a/src/gui/DatabaseOpenWidget.h b/src/gui/DatabaseOpenWidget.h index aade111c..0c4c938b 100644 --- a/src/gui/DatabaseOpenWidget.h +++ b/src/gui/DatabaseOpenWidget.h @@ -27,7 +27,8 @@ class Database; class QFile; -namespace Ui { +namespace Ui +{ class DatabaseOpenWidget; } diff --git a/src/gui/DatabaseRepairWidget.cpp b/src/gui/DatabaseRepairWidget.cpp index aa9613a2..b4be7124 100644 --- a/src/gui/DatabaseRepairWidget.cpp +++ b/src/gui/DatabaseRepairWidget.cpp @@ -21,13 +21,13 @@ #include #include -#include "ui_DatabaseOpenWidget.h" #include "core/Database.h" #include "core/Metadata.h" #include "format/KeePass2Repair.h" #include "gui/MessageBox.h" #include "keys/FileKey.h" #include "keys/PasswordKey.h" +#include "ui_DatabaseOpenWidget.h" DatabaseRepairWidget::DatabaseRepairWidget(QWidget* parent) : DatabaseOpenWidget(parent) @@ -61,8 +61,8 @@ void DatabaseRepairWidget::openDatabase() QFile file(m_filename); if (!file.open(QIODevice::ReadOnly)) { - MessageBox::warning(this, tr("Error"), tr("Unable to open the database.").append("\n") - .append(file.errorString())); + MessageBox::warning( + this, tr("Error"), tr("Unable to open the database.").append("\n").append(file.errorString())); emit editFinished(false); return; } @@ -80,13 +80,14 @@ void DatabaseRepairWidget::openDatabase() emit editFinished(false); return; case KeePass2Repair::UnableToOpen: - MessageBox::warning(this, tr("Error"), tr("Unable to open the database.").append("\n") - .append(repair.errorString())); + MessageBox::warning( + this, tr("Error"), tr("Unable to open the database.").append("\n").append(repair.errorString())); emit editFinished(false); return; case KeePass2Repair::RepairSuccess: m_db = repairOutcome.second; - MessageBox::warning(this, tr("Success"), tr("The database has been successfully repaired\nYou can now save it.")); + MessageBox::warning( + this, tr("Success"), tr("The database has been successfully repaired\nYou can now save it.")); emit editFinished(true); return; case KeePass2Repair::RepairFailed: @@ -100,8 +101,7 @@ void DatabaseRepairWidget::processEditFinished(bool result) { if (result) { emit success(); - } - else { + } else { emit error(); } } diff --git a/src/gui/DatabaseSettingsWidget.cpp b/src/gui/DatabaseSettingsWidget.cpp index 79b84f88..1fa95c10 100644 --- a/src/gui/DatabaseSettingsWidget.cpp +++ b/src/gui/DatabaseSettingsWidget.cpp @@ -18,22 +18,22 @@ #include "DatabaseSettingsWidget.h" #include "ui_DatabaseSettingsWidget.h" -#include "ui_DatabaseSettingsWidgetGeneral.h" #include "ui_DatabaseSettingsWidgetEncryption.h" +#include "ui_DatabaseSettingsWidgetGeneral.h" #include #include #include -#include "core/Global.h" -#include "core/FilePath.h" +#include "MessageBox.h" #include "core/AsyncTask.h" #include "core/Database.h" +#include "core/FilePath.h" +#include "core/Global.h" #include "core/Group.h" #include "core/Metadata.h" #include "crypto/SymmetricCipher.h" #include "crypto/kdf/Argon2Kdf.h" -#include "MessageBox.h" DatabaseSettingsWidget::DatabaseSettingsWidget(QWidget* parent) : DialogyWidget(parent) @@ -50,10 +50,14 @@ DatabaseSettingsWidget::DatabaseSettingsWidget(QWidget* parent) connect(m_ui->buttonBox, SIGNAL(accepted()), SLOT(save())); connect(m_ui->buttonBox, SIGNAL(rejected()), SLOT(reject())); - connect(m_uiGeneral->historyMaxItemsCheckBox, SIGNAL(toggled(bool)), - m_uiGeneral->historyMaxItemsSpinBox, SLOT(setEnabled(bool))); - connect(m_uiGeneral->historyMaxSizeCheckBox, SIGNAL(toggled(bool)), - m_uiGeneral->historyMaxSizeSpinBox, SLOT(setEnabled(bool))); + connect(m_uiGeneral->historyMaxItemsCheckBox, + SIGNAL(toggled(bool)), + m_uiGeneral->historyMaxItemsSpinBox, + SLOT(setEnabled(bool))); + connect(m_uiGeneral->historyMaxSizeCheckBox, + SIGNAL(toggled(bool)), + m_uiGeneral->historyMaxSizeSpinBox, + SLOT(setEnabled(bool))); connect(m_uiEncryption->transformBenchmarkButton, SIGNAL(clicked()), SLOT(transformRoundsBenchmark())); connect(m_uiEncryption->kdfComboBox, SIGNAL(currentIndexChanged(int)), SLOT(kdfChanged(int))); @@ -101,8 +105,9 @@ void DatabaseSettingsWidget::load(Database* db) } m_uiEncryption->algorithmComboBox->clear(); - for (auto& cipher: asConst(KeePass2::CIPHERS)) { - m_uiEncryption->algorithmComboBox->addItem(QCoreApplication::translate("KeePass2", cipher.second.toUtf8()), cipher.first.toByteArray()); + for (auto& cipher : asConst(KeePass2::CIPHERS)) { + m_uiEncryption->algorithmComboBox->addItem(QCoreApplication::translate("KeePass2", cipher.second.toUtf8()), + cipher.first.toByteArray()); } int cipherIndex = m_uiEncryption->algorithmComboBox->findData(m_db->cipher().toByteArray()); if (cipherIndex > -1) { @@ -112,8 +117,9 @@ void DatabaseSettingsWidget::load(Database* db) // Setup kdf combo box m_uiEncryption->kdfComboBox->blockSignals(true); m_uiEncryption->kdfComboBox->clear(); - for (auto& kdf: asConst(KeePass2::KDFS)) { - m_uiEncryption->kdfComboBox->addItem(QCoreApplication::translate("KeePass2", kdf.second.toUtf8()), kdf.first.toByteArray()); + for (auto& kdf : asConst(KeePass2::KDFS)) { + m_uiEncryption->kdfComboBox->addItem(QCoreApplication::translate("KeePass2", kdf.second.toUtf8()), + kdf.first.toByteArray()); } m_uiEncryption->kdfComboBox->blockSignals(false); @@ -158,7 +164,7 @@ void DatabaseSettingsWidget::save() return; } } else if ((kdf->uuid() == KeePass2::KDF_AES_KDBX3 || kdf->uuid() == KeePass2::KDF_AES_KDBX4) - && m_uiEncryption->transformRoundsSpinBox->value() < 100000) { + && m_uiEncryption->transformRoundsSpinBox->value() < 100000) { QMessageBox warning; warning.setIcon(QMessageBox::Warning); warning.setWindowTitle(tr("Number of rounds too low", "Key transformation rounds")); @@ -173,7 +179,8 @@ void DatabaseSettingsWidget::save() } } - m_db->setCompressionAlgo(m_uiGeneral->compressionCheckbox->isChecked() ? Database::CompressionGZip : Database::CompressionNone); + m_db->setCompressionAlgo(m_uiGeneral->compressionCheckbox->isChecked() ? Database::CompressionGZip + : Database::CompressionNone); Metadata* meta = m_db->metadata(); @@ -228,7 +235,8 @@ void DatabaseSettingsWidget::save() QApplication::restoreOverrideCursor(); if (!ok) { - MessageBox::warning(this, tr("KDF unchanged"), + MessageBox::warning(this, + tr("KDF unchanged"), tr("Failed to transform key with new KDF parameters; KDF unchanged."), QMessageBox::Ok); } @@ -261,9 +269,7 @@ void DatabaseSettingsWidget::transformRoundsBenchmark() } // Determine the number of rounds required to meet 1 second delay - int rounds = AsyncTask::runAndWaitForFuture([&kdf]() { - return kdf->benchmark(1000); - }); + int rounds = AsyncTask::runAndWaitForFuture([&kdf]() { return kdf->benchmark(1000); }); m_uiEncryption->transformRoundsSpinBox->setValue(rounds); m_uiEncryption->transformBenchmarkButton->setEnabled(true); @@ -298,8 +304,7 @@ void DatabaseSettingsWidget::kdfChanged(int index) */ void DatabaseSettingsWidget::memoryChanged(int value) { - m_uiEncryption->memorySpinBox->setSuffix( - tr(" MiB", "Abbreviation for Mebibytes (KDF settings)", value)); + m_uiEncryption->memorySpinBox->setSuffix(tr(" MiB", "Abbreviation for Mebibytes (KDF settings)", value)); } /** diff --git a/src/gui/DatabaseSettingsWidget.h b/src/gui/DatabaseSettingsWidget.h index b0cae5db..5abad8e0 100644 --- a/src/gui/DatabaseSettingsWidget.h +++ b/src/gui/DatabaseSettingsWidget.h @@ -18,26 +18,26 @@ #ifndef KEEPASSX_DATABASESETTINGSWIDGET_H #define KEEPASSX_DATABASESETTINGSWIDGET_H -#include -#include -#include #include +#include +#include +#include -#include "gui/DialogyWidget.h" #include "crypto/kdf/Kdf.h" +#include "gui/DialogyWidget.h" class Database; namespace Ui { -class DatabaseSettingsWidget; -class DatabaseSettingsWidgetGeneral; -class DatabaseSettingsWidgetEncryption; + class DatabaseSettingsWidget; + class DatabaseSettingsWidgetGeneral; + class DatabaseSettingsWidgetEncryption; } -class DatabaseSettingsWidget: public DialogyWidget +class DatabaseSettingsWidget : public DialogyWidget { -Q_OBJECT + Q_OBJECT public: explicit DatabaseSettingsWidget(QWidget* parent = nullptr); diff --git a/src/gui/DatabaseTabWidget.cpp b/src/gui/DatabaseTabWidget.cpp index 832512e9..ff7a4228 100644 --- a/src/gui/DatabaseTabWidget.cpp +++ b/src/gui/DatabaseTabWidget.cpp @@ -19,16 +19,16 @@ #include "DatabaseTabWidget.h" #include -#include #include +#include #include "autotype/AutoType.h" +#include "core/AsyncTask.h" #include "core/Config.h" -#include "core/Global.h" #include "core/Database.h" +#include "core/Global.h" #include "core/Group.h" #include "core/Metadata.h" -#include "core/AsyncTask.h" #include "format/CsvExporter.h" #include "gui/Clipboard.h" #include "gui/DatabaseWidget.h" @@ -36,9 +36,9 @@ #include "gui/DragTabBar.h" #include "gui/FileDialog.h" #include "gui/MessageBox.h" +#include "gui/UnlockDatabaseDialog.h" #include "gui/entry/EntryView.h" #include "gui/group/GroupView.h" -#include "gui/UnlockDatabaseDialog.h" DatabaseManagerStruct::DatabaseManagerStruct() : dbWidget(nullptr) @@ -48,7 +48,6 @@ DatabaseManagerStruct::DatabaseManagerStruct() { } - const int DatabaseTabWidget::LastDatabasesCount = 5; DatabaseTabWidget::DatabaseTabWidget(QWidget* parent) @@ -62,7 +61,8 @@ DatabaseTabWidget::DatabaseTabWidget(QWidget* parent) connect(this, SIGNAL(tabCloseRequested(int)), SLOT(closeDatabase(int))); connect(this, SIGNAL(currentChanged(int)), SLOT(emitActivateDatabaseChanged())); - connect(this, SIGNAL(activateDatabaseChanged(DatabaseWidget*)), m_dbWidgetStateSync, SLOT(setActive(DatabaseWidget*))); + connect( + this, SIGNAL(activateDatabaseChanged(DatabaseWidget*)), m_dbWidgetStateSync, SLOT(setActive(DatabaseWidget*))); connect(autoType(), SIGNAL(globalShortcutTriggered()), SLOT(performGlobalAutoType())); connect(autoType(), SIGNAL(autotypePerformed()), SLOT(relockPendingDatabase())); } @@ -108,15 +108,13 @@ void DatabaseTabWidget::newDatabase() void DatabaseTabWidget::openDatabase() { QString filter = QString("%1 (*.kdbx);;%2 (*)").arg(tr("KeePass 2 Database"), tr("All files")); - QString fileName = fileDialog()->getOpenFileName(this, tr("Open database"), QDir::homePath(), - filter); + QString fileName = fileDialog()->getOpenFileName(this, tr("Open database"), QDir::homePath(), filter); if (!fileName.isEmpty()) { openDatabase(fileName); } } -void DatabaseTabWidget::openDatabase(const QString& fileName, const QString& pw, - const QString& keyFile) +void DatabaseTabWidget::openDatabase(const QString& fileName, const QString& pw, const QString& keyFile) { QFileInfo fileInfo(fileName); QString canonicalFilePath = fileInfo.canonicalFilePath(); @@ -125,7 +123,6 @@ void DatabaseTabWidget::openDatabase(const QString& fileName, const QString& pw, return; } - QHashIterator i(m_dbList); while (i.hasNext()) { i.next(); @@ -147,11 +144,10 @@ void DatabaseTabWidget::openDatabase(const QString& fileName, const QString& pw, if (!file.open(QIODevice::ReadWrite)) { if (!file.open(QIODevice::ReadOnly)) { // can't open - emit messageGlobal( - tr("Unable to open the database.").append("\n").append(file.errorString()), MessageWidget::Error); + emit messageGlobal(tr("Unable to open the database.").append("\n").append(file.errorString()), + MessageWidget::Error); return; - } - else { + } else { // can only open read-only dbStruct.readOnly = true; } @@ -175,15 +171,14 @@ void DatabaseTabWidget::openDatabase(const QString& fileName, const QString& pw, } else { dbStruct.dbWidget->switchToOpenDatabase(dbStruct.fileInfo.absoluteFilePath()); } - + emit messageDismissTab(); } void DatabaseTabWidget::importCsv() { QString filter = QString("%1 (*.csv);;%2 (*)").arg(tr("CSV file"), tr("All files")); - QString fileName = fileDialog()->getOpenFileName(this, tr("Open CSV file"), QString(), - filter); + QString fileName = fileDialog()->getOpenFileName(this, tr("Open CSV file"), QString(), filter); if (fileName.isEmpty()) { return; @@ -200,8 +195,7 @@ void DatabaseTabWidget::importCsv() void DatabaseTabWidget::mergeDatabase() { QString filter = QString("%1 (*.kdbx);;%2 (*)").arg(tr("KeePass 2 Database"), tr("All files")); - const QString fileName = fileDialog()->getOpenFileName(this, tr("Merge database"), QString(), - filter); + const QString fileName = fileDialog()->getOpenFileName(this, tr("Merge database"), QString(), filter); if (!fileName.isEmpty()) { mergeDatabase(fileName); } @@ -215,8 +209,7 @@ void DatabaseTabWidget::mergeDatabase(const QString& fileName) void DatabaseTabWidget::importKeePass1Database() { QString filter = QString("%1 (*.kdb);;%2 (*)").arg(tr("KeePass 1 database"), tr("All files")); - QString fileName = fileDialog()->getOpenFileName(this, tr("Open KeePass 1 database"), QString(), - filter); + QString fileName = fileDialog()->getOpenFileName(this, tr("Open KeePass 1 database"), QString(), filter); if (fileName.isEmpty()) { return; @@ -247,11 +240,12 @@ bool DatabaseTabWidget::closeDatabase(Database* db) dbName.chop(1); } if (dbStruct.dbWidget->isInEditMode() && db->hasKey() && dbStruct.dbWidget->isEditWidgetModified()) { - QMessageBox::StandardButton result = - MessageBox::question( - this, tr("Close?"), + QMessageBox::StandardButton result = MessageBox::question( + this, + tr("Close?"), tr("\"%1\" is in edit mode.\nDiscard changes and close anyway?").arg(dbName.toHtmlEscaped()), - QMessageBox::Discard | QMessageBox::Cancel, QMessageBox::Cancel); + QMessageBox::Discard | QMessageBox::Cancel, + QMessageBox::Cancel); if (result == QMessageBox::Cancel) { return false; } @@ -263,10 +257,11 @@ bool DatabaseTabWidget::closeDatabase(Database* db) } } else if (dbStruct.dbWidget->currentMode() != DatabaseWidget::LockedMode) { QMessageBox::StandardButton result = - MessageBox::question( - this, tr("Save changes?"), - tr("\"%1\" was modified.\nSave changes?").arg(dbName.toHtmlEscaped()), - QMessageBox::Yes | QMessageBox::Discard | QMessageBox::Cancel, QMessageBox::Yes); + MessageBox::question(this, + tr("Save changes?"), + tr("\"%1\" was modified.\nSave changes?").arg(dbName.toHtmlEscaped()), + QMessageBox::Yes | QMessageBox::Discard | QMessageBox::Cancel, + QMessageBox::Yes); if (result == QMessageBox::Yes) { if (!saveDatabase(db)) { return false; @@ -349,11 +344,13 @@ bool DatabaseTabWidget::saveDatabase(Database* db, QString filePath) if (++dbStruct.saveAttempts > 2 && useAtomicSaves) { // Saving failed 3 times, issue a warning and attempt to resolve - auto choice = MessageBox::question(this, tr("Disable safe saves?"), + auto choice = MessageBox::question(this, + tr("Disable safe saves?"), tr("KeePassXC has failed to save the database multiple times. " - "This is likely caused by file sync services holding a lock on " - "the save file.\nDisable safe saves and try again?"), - QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes); + "This is likely caused by file sync services holding a lock on " + "the save file.\nDisable safe saves and try again?"), + QMessageBox::Yes | QMessageBox::No, + QMessageBox::Yes); if (choice == QMessageBox::Yes) { config()->set("UseAtomicSaves", false); return saveDatabase(db, filePath); @@ -362,8 +359,7 @@ bool DatabaseTabWidget::saveDatabase(Database* db, QString filePath) dbStruct.saveAttempts = 0; } - emit messageTab(tr("Writing the database failed.").append("\n").append(errorMessage), - MessageWidget::Error); + emit messageTab(tr("Writing the database failed.").append("\n").append(errorMessage), MessageWidget::Error); return false; } } else { @@ -381,9 +377,13 @@ bool DatabaseTabWidget::saveDatabaseAs(Database* db) } else { oldFilePath = QDir::toNativeSeparators(QDir::homePath() + "/" + tr("Passwords").append(".kdbx")); } - QString newFilePath = fileDialog()->getSaveFileName(this, tr("Save database as"), oldFilePath, + QString newFilePath = fileDialog()->getSaveFileName(this, + tr("Save database as"), + oldFilePath, tr("KeePass 2 Database").append(" (*.kdbx)"), - nullptr, 0, "kdbx"); + nullptr, + 0, + "kdbx"); if (!newFilePath.isEmpty()) { // Ensure we don't recurse back into this function dbStruct.readOnly = false; @@ -450,18 +450,16 @@ void DatabaseTabWidget::exportToCsv() return; } - QString fileName = fileDialog()->getSaveFileName(this, tr("Export database to CSV file"), - QString(), tr("CSV file").append(" (*.csv)"), - nullptr, 0, "csv"); + QString fileName = fileDialog()->getSaveFileName( + this, tr("Export database to CSV file"), QString(), tr("CSV file").append(" (*.csv)"), nullptr, 0, "csv"); if (fileName.isEmpty()) { return; } CsvExporter csvExporter; if (!csvExporter.exportDatabase(fileName, db)) { - emit messageGlobal( - tr("Writing the CSV file failed.").append("\n") - .append(csvExporter.errorString()), MessageWidget::Error); + emit messageGlobal(tr("Writing the CSV file failed.").append("\n").append(csvExporter.errorString()), + MessageWidget::Error); } } @@ -512,7 +510,6 @@ QString DatabaseTabWidget::databasePath(int index) return indexDatabaseManagerStruct(index).fileInfo.absoluteFilePath(); } - void DatabaseTabWidget::updateTabName(Database* db) { int index = databaseIndex(db); @@ -566,7 +563,7 @@ void DatabaseTabWidget::updateTabNameFromDbWidgetSender() updateTabName(databaseFromDatabaseWidget(dbWidget)); Database* db = dbWidget->database(); - Group *autoload = db->rootGroup()->findChildByName("AutoOpen"); + Group* autoload = db->rootGroup()->findChildByName("AutoOpen"); if (autoload) { const DatabaseManagerStruct& dbStruct = m_dbList.value(db); QDir dbFolder(dbStruct.fileInfo.canonicalPath()); @@ -578,8 +575,7 @@ void DatabaseTabWidget::updateTabNameFromDbWidgetSender() if (entry->url().startsWith("file://")) { QUrl url(entry->url()); filepath.setFile(url.toLocalFile()); - } - else { + } else { filepath.setFile(entry->url()); if (filepath.isRelative()) { filepath.setFile(dbFolder, entry->url()); @@ -665,8 +661,7 @@ DatabaseWidget* DatabaseTabWidget::currentDatabaseWidget() Database* db = indexDatabase(currentIndex()); if (db) { return m_dbList[db].dbWidget; - } - else { + } else { return nullptr; } } @@ -678,8 +673,7 @@ bool DatabaseTabWidget::hasLockableDatabases() const i.next(); DatabaseWidget::Mode mode = i.value().dbWidget->currentMode(); - if ((mode == DatabaseWidget::ViewMode || mode == DatabaseWidget::EditMode) - && i.value().dbWidget->dbHasKey()) { + if ((mode == DatabaseWidget::ViewMode || mode == DatabaseWidget::EditMode) && i.value().dbWidget->dbHasKey()) { return true; } } @@ -704,10 +698,12 @@ void DatabaseTabWidget::lockDatabases() if (dbWidget->currentMode() == DatabaseWidget::EditMode && dbWidget->isEditWidgetModified()) { QMessageBox::StandardButton result = - MessageBox::question( - this, tr("Lock database"), - tr("Can't lock the database as you are currently editing it.\nPlease press cancel to finish your changes or discard them."), - QMessageBox::Discard | QMessageBox::Cancel, QMessageBox::Cancel); + MessageBox::question(this, + tr("Lock database"), + tr("Can't lock the database as you are currently editing it.\nPlease press cancel " + "to finish your changes or discard them."), + QMessageBox::Discard | QMessageBox::Cancel, + QMessageBox::Cancel); if (result == QMessageBox::Cancel) { continue; } @@ -715,20 +711,20 @@ void DatabaseTabWidget::lockDatabases() if (m_dbList[db].modified) { QMessageBox::StandardButton result = - MessageBox::question( - this, tr("Lock database"), - tr("This database has been modified.\nDo you want to save the database before locking it?\nOtherwise your changes are lost."), - QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel, QMessageBox::Cancel); + MessageBox::question(this, + tr("Lock database"), + tr("This database has been modified.\nDo you want to save the database before " + "locking it?\nOtherwise your changes are lost."), + QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel, + QMessageBox::Cancel); if (result == QMessageBox::Save) { if (!saveDatabase(db)) { continue; } - } - else if (result == QMessageBox::Discard) { + } else if (result == QMessageBox::Discard) { m_dbList[db].modified = false; m_dbList[db].dbWidget->databaseSaved(); - } - else if (result == QMessageBox::Cancel) { + } else if (result == QMessageBox::Cancel) { continue; } } @@ -785,8 +781,7 @@ void DatabaseTabWidget::updateLastDatabases(const QString& filename) { if (!config()->get("RememberLastDatabases").toBool()) { config()->set("LastDatabases", QVariant()); - } - else { + } else { QStringList lastDatabases = config()->get("LastDatabases", QVariant()).toStringList(); lastDatabases.prepend(filename); lastDatabases.removeDuplicates(); @@ -851,7 +846,7 @@ void DatabaseTabWidget::performGlobalAutoType() if (unlockedDatabases.size() > 0) { autoType()->performGlobalAutoType(unlockedDatabases); - } else if (m_dbList.size() > 0){ + } else if (m_dbList.size() > 0) { m_dbPendingLock = indexDatabaseManagerStruct(0).dbWidget; m_dbPendingLock->showUnlockDialog(); } diff --git a/src/gui/DatabaseTabWidget.h b/src/gui/DatabaseTabWidget.h index 38f9b847..f4cdf295 100644 --- a/src/gui/DatabaseTabWidget.h +++ b/src/gui/DatabaseTabWidget.h @@ -19,9 +19,9 @@ #ifndef KEEPASSX_DATABASETABWIDGET_H #define KEEPASSX_DATABASETABWIDGET_H +#include #include #include -#include #include "gui/DatabaseWidget.h" #include "gui/MessageWidget.h" @@ -52,8 +52,7 @@ class DatabaseTabWidget : public QTabWidget public: explicit DatabaseTabWidget(QWidget* parent = nullptr); ~DatabaseTabWidget() override; - void openDatabase(const QString& fileName, const QString& pw = QString(), - const QString& keyFile = QString()); + void openDatabase(const QString& fileName, const QString& pw = QString(), const QString& keyFile = QString()); void mergeDatabase(const QString& fileName); DatabaseWidget* currentDatabaseWidget(); bool hasLockableDatabases() const; diff --git a/src/gui/DatabaseWidget.cpp b/src/gui/DatabaseWidget.cpp index bc8fc3f7..7ee317ad 100644 --- a/src/gui/DatabaseWidget.cpp +++ b/src/gui/DatabaseWidget.cpp @@ -19,18 +19,18 @@ #include "DatabaseWidget.h" #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include "autotype/AutoType.h" #include "core/Config.h" @@ -43,15 +43,15 @@ #include "gui/ChangeMasterKeyWidget.h" #include "gui/Clipboard.h" #include "gui/CloneDialog.h" -#include "gui/SetupTotpDialog.h" -#include "gui/TotpDialog.h" #include "gui/DatabaseOpenWidget.h" #include "gui/DatabaseSettingsWidget.h" #include "gui/DetailsWidget.h" #include "gui/KeePass1OpenWidget.h" #include "gui/MessageBox.h" -#include "gui/UnlockDatabaseWidget.h" +#include "gui/SetupTotpDialog.h" +#include "gui/TotpDialog.h" #include "gui/UnlockDatabaseDialog.h" +#include "gui/UnlockDatabaseWidget.h" #include "gui/entry/EditEntryWidget.h" #include "gui/entry/EntryView.h" #include "gui/group/EditGroupWidget.h" @@ -91,15 +91,13 @@ DatabaseWidget::DatabaseWidget(Database* db, QWidget* parent) m_groupView = new GroupView(db, m_mainSplitter); m_groupView->setObjectName("groupView"); m_groupView->setContextMenuPolicy(Qt::CustomContextMenu); - connect(m_groupView, SIGNAL(customContextMenuRequested(QPoint)), - SLOT(emitGroupContextMenuRequested(QPoint))); + connect(m_groupView, SIGNAL(customContextMenuRequested(QPoint)), SLOT(emitGroupContextMenuRequested(QPoint))); m_entryView = new EntryView(rightHandSideWidget); m_entryView->setObjectName("entryView"); m_entryView->setContextMenuPolicy(Qt::CustomContextMenu); m_entryView->setGroup(db->rootGroup()); - connect(m_entryView, SIGNAL(customContextMenuRequested(QPoint)), - SLOT(emitEntryContextMenuRequested(QPoint))); + connect(m_entryView, SIGNAL(customContextMenuRequested(QPoint)), SLOT(emitEntryContextMenuRequested(QPoint))); // Add a notification for when we are searching m_searchingLabel = new QLabel(); @@ -114,11 +112,12 @@ DatabaseWidget::DatabaseWidget(Database* db, QWidget* parent) m_detailsView->hide(); connect(this, SIGNAL(pressedEntry(Entry*)), m_detailsView, SLOT(setEntry(Entry*))); connect(this, SIGNAL(pressedGroup(Group*)), m_detailsView, SLOT(setGroup(Group*))); - connect(this, SIGNAL(currentModeChanged(DatabaseWidget::Mode)), - m_detailsView, SLOT(setDatabaseMode(DatabaseWidget::Mode))); + connect(this, + SIGNAL(currentModeChanged(DatabaseWidget::Mode)), + m_detailsView, + SLOT(setDatabaseMode(DatabaseWidget::Mode))); connect(m_detailsView, SIGNAL(errorOccurred(QString)), this, SLOT(showErrorMessage(QString))); - auto* vLayout = new QVBoxLayout(rightHandSideWidget); vLayout->setMargin(0); vLayout->addWidget(m_searchingLabel); @@ -184,12 +183,13 @@ DatabaseWidget::DatabaseWidget(Database* db, QWidget* parent) addWidget(m_keepass1OpenWidget); addWidget(m_unlockDatabaseWidget); - connect(m_mainSplitter, SIGNAL(splitterMoved(int,int)), SIGNAL(mainSplitterSizesChanged())); - connect(m_detailSplitter, SIGNAL(splitterMoved(int,int)), SIGNAL(detailSplitterSizesChanged())); + connect(m_mainSplitter, SIGNAL(splitterMoved(int, int)), SIGNAL(mainSplitterSizesChanged())); + connect(m_detailSplitter, SIGNAL(splitterMoved(int, int)), SIGNAL(detailSplitterSizesChanged())); connect(m_entryView, SIGNAL(viewStateChanged()), SIGNAL(entryViewStateChanged())); connect(m_groupView, SIGNAL(groupChanged(Group*)), this, SLOT(onGroupChanged(Group*))); connect(m_groupView, SIGNAL(groupChanged(Group*)), SIGNAL(groupChanged())); - connect(m_entryView, SIGNAL(entryActivated(Entry*, EntryModel::ModelColumn)), + connect(m_entryView, + SIGNAL(entryActivated(Entry*, EntryModel::ModelColumn)), SLOT(entryActivationSignalReceived(Entry*, EntryModel::ModelColumn))); connect(m_entryView, SIGNAL(entrySelectionChanged()), SIGNAL(entrySelectionChanged())); connect(m_editEntryWidget, SIGNAL(editFinished(bool)), SLOT(switchToView(bool))); @@ -203,7 +203,7 @@ DatabaseWidget::DatabaseWidget(Database* db, QWidget* parent) connect(m_keepass1OpenWidget, SIGNAL(editFinished(bool)), SLOT(openDatabase(bool))); connect(m_csvImportWizard, SIGNAL(importFinished(bool)), SLOT(csvImportFinished(bool))); connect(m_unlockDatabaseWidget, SIGNAL(editFinished(bool)), SLOT(unlockDatabase(bool))); - connect(m_unlockDatabaseDialog, SIGNAL(unlockDone(bool)), SLOT(unlockDatabase(bool))); + connect(m_unlockDatabaseDialog, SIGNAL(unlockDone(bool)), SLOT(unlockDatabase(bool))); connect(&m_fileWatcher, SIGNAL(fileChanged(QString)), this, SLOT(onWatchedFileChanged())); connect(&m_fileWatchTimer, SIGNAL(timeout()), this, SLOT(reloadDatabaseFile())); connect(&m_fileWatchUnblockTimer, SIGNAL(timeout()), this, SLOT(unblockAutoReload())); @@ -226,7 +226,10 @@ DatabaseWidget::DatabaseWidget(Database* db, QWidget* parent) #ifdef WITH_XC_SSHAGENT if (config()->get("SSHAgent", false).toBool()) { - connect(this, SIGNAL(currentModeChanged(DatabaseWidget::Mode)), SSHAgent::instance(), SLOT(databaseModeChanged(DatabaseWidget::Mode))); + connect(this, + SIGNAL(currentModeChanged(DatabaseWidget::Mode)), + SSHAgent::instance(), + SLOT(databaseModeChanged(DatabaseWidget::Mode))); connect(this, SIGNAL(closeRequest()), SSHAgent::instance(), SLOT(databaseModeChanged())); } #endif @@ -242,18 +245,13 @@ DatabaseWidget::Mode DatabaseWidget::currentMode() const { if (currentWidget() == nullptr) { return DatabaseWidget::None; - } - else if (currentWidget() == m_csvImportWizard) { + } else if (currentWidget() == m_csvImportWizard) { return DatabaseWidget::ImportMode; - } - else if (currentWidget() == m_mainWidget) { + } else if (currentWidget() == m_mainWidget) { return DatabaseWidget::ViewMode; - } - else if (currentWidget() == m_unlockDatabaseWidget || - currentWidget() == m_databaseOpenWidget) { + } else if (currentWidget() == m_unlockDatabaseWidget || currentWidget() == m_databaseOpenWidget) { return DatabaseWidget::LockedMode; - } - else { + } else { return DatabaseWidget::EditMode; } } @@ -267,8 +265,7 @@ bool DatabaseWidget::isEditWidgetModified() const { if (currentWidget() == m_editEntryWidget) { return m_editEntryWidget->hasBeenModified(); - } - else { + } else { // other edit widget don't have a hasBeenModified() method yet // assume that they already have been modified return true; @@ -290,7 +287,7 @@ QList DatabaseWidget::detailSplitterSizes() const return m_detailSplitter->sizes(); } -void DatabaseWidget::setDetailSplitterSizes(const QList &sizes) +void DatabaseWidget::setDetailSplitterSizes(const QList& sizes) { m_detailSplitter->setSizes(sizes); } @@ -392,8 +389,7 @@ void DatabaseWidget::setIconFromParent() if (m_newParent->iconUuid().isNull()) { m_newEntry->setIcon(m_newParent->iconNumber()); - } - else { + } else { m_newEntry->setIcon(m_newParent->iconUuid()); } } @@ -461,7 +457,6 @@ void DatabaseWidget::setupTotp() setupTotpDialog->open(); } - void DatabaseWidget::deleteEntries() { const QModelIndexList selected = m_entryView->selectionModel()->selectedRows(); @@ -482,17 +477,13 @@ void DatabaseWidget::deleteEntries() QString prompt; if (selected.size() == 1) { prompt = tr("Do you really want to delete the entry \"%1\" for good?") - .arg(selectedEntries.first()->title().toHtmlEscaped()); - } - else { + .arg(selectedEntries.first()->title().toHtmlEscaped()); + } else { prompt = tr("Do you really want to delete %n entry(s) for good?", "", selected.size()); } QMessageBox::StandardButton result = MessageBox::question( - this, - tr("Delete entry(s)?", "", selected.size()), - prompt, - QMessageBox::Yes | QMessageBox::No); + this, tr("Delete entry(s)?", "", selected.size()), prompt, QMessageBox::Yes | QMessageBox::No); if (result == QMessageBox::Yes) { for (Entry* entry : asConst(selectedEntries)) { @@ -500,21 +491,17 @@ void DatabaseWidget::deleteEntries() } refreshSearch(); } - } - else { + } else { QString prompt; if (selected.size() == 1) { prompt = tr("Do you really want to move entry \"%1\" to the recycle bin?") - .arg(selectedEntries.first()->title().toHtmlEscaped()); + .arg(selectedEntries.first()->title().toHtmlEscaped()); } else { prompt = tr("Do you really want to move %n entry(s) to the recycle bin?", "", selected.size()); } QMessageBox::StandardButton result = MessageBox::question( - this, - tr("Move entry(s) to recycle bin?", "", selected.size()), - prompt, - QMessageBox::Yes | QMessageBox::No); + this, tr("Move entry(s) to recycle bin?", "", selected.size()), prompt, QMessageBox::Yes | QMessageBox::No); if (result == QMessageBox::No) { return; @@ -528,7 +515,7 @@ void DatabaseWidget::deleteEntries() void DatabaseWidget::setFocus() { - m_entryView->setFocus(); + m_entryView->setFocus(); } void DatabaseWidget::copyTitle() @@ -594,7 +581,8 @@ void DatabaseWidget::copyAttribute(QAction* action) return; } - setClipboardTextAndMinimize(currentEntry->resolveMultiplePlaceholders(currentEntry->attributes()->value(action->data().toString()))); + setClipboardTextAndMinimize( + currentEntry->resolveMultiplePlaceholders(currentEntry->attributes()->value(action->data().toString()))); } void DatabaseWidget::setClipboardTextAndMinimize(const QString& text) @@ -653,8 +641,7 @@ void DatabaseWidget::openUrlForEntry(Entry* entry) tr("Do you really want to execute the following command?

%1
") .arg(cmdTruncated.toHtmlEscaped()), QMessageBox::Yes | QMessageBox::No, - this - ); + this); msgbox.setDefaultButton(QMessageBox::No); QCheckBox* checkbox = new QCheckBox(tr("Remember my choice"), &msgbox); @@ -662,8 +649,8 @@ void DatabaseWidget::openUrlForEntry(Entry* entry) bool remember = false; QObject::connect(checkbox, &QCheckBox::stateChanged, [&](int state) { if (static_cast(state) == Qt::CheckState::Checked) { - remember = true; - } + remember = true; + } }); int result = msgbox.exec(); @@ -672,12 +659,10 @@ void DatabaseWidget::openUrlForEntry(Entry* entry) } if (remember) { - entry->attributes()->set(EntryAttributes::RememberCmdExecAttr, - result == QMessageBox::Yes ? "1" : "0"); + entry->attributes()->set(EntryAttributes::RememberCmdExecAttr, result == QMessageBox::Yes ? "1" : "0"); } } - } - else { + } else { QUrl url = QUrl::fromUserInput(urlString); QDesktopServices::openUrl(url); } @@ -709,15 +694,14 @@ void DatabaseWidget::deleteGroup() bool isRecycleBinSubgroup = Tools::hasChild(currentGroup, m_db->metadata()->recycleBin()); if (inRecycleBin || isRecycleBin || isRecycleBinSubgroup || !m_db->metadata()->recycleBinEnabled()) { QMessageBox::StandardButton result = MessageBox::question( - this, tr("Delete group?"), - tr("Do you really want to delete the group \"%1\" for good?") - .arg(currentGroup->name().toHtmlEscaped()), + this, + tr("Delete group?"), + tr("Do you really want to delete the group \"%1\" for good?").arg(currentGroup->name().toHtmlEscaped()), QMessageBox::Yes | QMessageBox::No); if (result == QMessageBox::Yes) { delete currentGroup; } - } - else { + } else { m_db->recycleGroup(currentGroup); } } @@ -760,8 +744,7 @@ void DatabaseWidget::csvImportFinished(bool accepted) { if (!accepted) { emit closeRequest(); - } - else { + } else { setCurrentWidget(m_mainWidget); } } @@ -852,8 +835,7 @@ void DatabaseWidget::updateMasterKey(bool accepted) m_messageWidget->showMessage(tr("Unable to calculate master key"), MessageWidget::Error); return; } - } - else if (!m_db->hasKey()) { + } else if (!m_db->hasKey()) { emit closeRequest(); return; } @@ -875,8 +857,7 @@ void DatabaseWidget::openDatabase(bool accepted) delete m_keepass1OpenWidget; m_keepass1OpenWidget = nullptr; m_fileWatcher.addPath(m_filePath); - } - else { + } else { m_fileWatcher.removePath(m_filePath); if (m_databaseOpenWidget->database()) { delete m_databaseOpenWidget->database(); @@ -960,10 +941,10 @@ void DatabaseWidget::entryActivationSignalReceived(Entry* entry, EntryModel::Mod } break; // TODO: switch to 'Notes' tab in details view/pane - //case EntryModel::Notes: + // case EntryModel::Notes: // break; // TODO: switch to 'Attachments' tab in details view/pane - //case EntryModel::Attachments: + // case EntryModel::Attachments: // break; default: switchToEntryEdit(entry); @@ -1018,8 +999,7 @@ void DatabaseWidget::switchToOpenDatabase(const QString& filePath) } } -void DatabaseWidget::switchToOpenDatabase(const QString& filePath, const QString& password, - const QString& keyFile) +void DatabaseWidget::switchToOpenDatabase(const QString& filePath, const QString& password, const QString& keyFile) { updateFilePath(filePath); switchToOpenDatabase(filePath); @@ -1047,9 +1027,7 @@ void DatabaseWidget::switchToOpenMergeDatabase(const QString& filePath) setCurrentWidget(m_databaseOpenMergeWidget); } - -void DatabaseWidget::switchToOpenMergeDatabase(const QString& filePath, const QString& password, - const QString& keyFile) +void DatabaseWidget::switchToOpenMergeDatabase(const QString& filePath, const QString& password, const QString& keyFile) { switchToOpenMergeDatabase(filePath); m_databaseOpenMergeWidget->enterKey(password, keyFile); @@ -1072,7 +1050,8 @@ void DatabaseWidget::databaseSaved() m_databaseModified = false; } -void DatabaseWidget::refreshSearch() { +void DatabaseWidget::refreshSearch() +{ if (isInSearchMode()) { search(m_lastSearchText); } @@ -1080,8 +1059,7 @@ void DatabaseWidget::refreshSearch() { void DatabaseWidget::search(const QString& searchtext) { - if (searchtext.isEmpty()) - { + if (searchtext.isEmpty()) { endSearch(); return; } @@ -1100,8 +1078,7 @@ void DatabaseWidget::search(const QString& searchtext) // Display a label detailing our search results if (searchResult.size() > 0) { m_searchingLabel->setText(tr("Search Results (%1)").arg(searchResult.size())); - } - else { + } else { m_searchingLabel->setText(tr("No Results")); } @@ -1138,8 +1115,7 @@ QString DatabaseWidget::getCurrentSearch() void DatabaseWidget::endSearch() { - if (isInSearchMode()) - { + if (isInSearchMode()) { emit listModeAboutToActivate(); // Show the normal entry view of the current group @@ -1217,8 +1193,7 @@ void DatabaseWidget::lock() if (m_groupView->currentGroup()) { m_groupBeforeLock = m_groupView->currentGroup()->uuid(); - } - else { + } else { m_groupBeforeLock = m_db->rootGroup()->uuid(); } @@ -1235,7 +1210,7 @@ void DatabaseWidget::lock() replaceDatabase(newDb); } -void DatabaseWidget::updateFilePath(const QString &filePath) +void DatabaseWidget::updateFilePath(const QString& filePath) { if (!m_filePath.isEmpty()) { m_fileWatcher.removePath(m_filePath); @@ -1282,11 +1257,13 @@ void DatabaseWidget::reloadDatabaseFile() return; } - if (! config()->get("AutoReloadOnChange").toBool()) { + if (!config()->get("AutoReloadOnChange").toBool()) { // Ask if we want to reload the db - QMessageBox::StandardButton mb = MessageBox::question(this, tr("File has changed"), - tr("The database file has changed. Do you want to load the changes?"), - QMessageBox::Yes | QMessageBox::No); + QMessageBox::StandardButton mb = + MessageBox::question(this, + tr("File has changed"), + tr("The database file has changed. Do you want to load the changes?"), + QMessageBox::Yes | QMessageBox::No); if (mb == QMessageBox::No) { // Notify everyone the database does not match the file @@ -1305,10 +1282,12 @@ void DatabaseWidget::reloadDatabaseFile() if (db != nullptr) { if (m_databaseModified) { // Ask if we want to merge changes into new database - QMessageBox::StandardButton mb = MessageBox::question(this, tr("Merge Request"), - tr("The database file has changed and you have unsaved changes.\n" - "Do you want to merge your changes?"), - QMessageBox::Yes | QMessageBox::No); + QMessageBox::StandardButton mb = + MessageBox::question(this, + tr("Merge Request"), + tr("The database file has changed and you have unsaved changes.\n" + "Do you want to merge your changes?"), + QMessageBox::Yes | QMessageBox::No); if (mb == QMessageBox::Yes) { // Merge the old database into the new one @@ -1324,8 +1303,7 @@ void DatabaseWidget::reloadDatabaseFile() Uuid groupBeforeReload; if (m_groupView && m_groupView->currentGroup()) { groupBeforeReload = m_groupView->currentGroup()->uuid(); - } - else { + } else { groupBeforeReload = m_db->rootGroup()->uuid(); } @@ -1336,12 +1314,12 @@ void DatabaseWidget::reloadDatabaseFile() replaceDatabase(db); restoreGroupEntryFocus(groupBeforeReload, entryBeforeReload); - } } else { m_messageWidget->showMessage( tr("Could not open the new database file while attempting to autoreload this database.") - .append("\n").append(file.errorString()), + .append("\n") + .append(file.errorString()), MessageWidget::Error); // HACK: Directly calling the database's signal // Mark db as modified since existing data may differ from file or file was deleted @@ -1383,17 +1361,16 @@ void DatabaseWidget::restoreGroupEntryFocus(Uuid groupUuid, Uuid entryUuid) } if (restoredGroup != nullptr) { - m_groupView->setCurrentGroup(restoredGroup); + m_groupView->setCurrentGroup(restoredGroup); - const QList entries = restoredGroup->entries(); - for (Entry* entry : entries) { - if (entry->uuid() == entryUuid) { - m_entryView->setCurrentEntry(entry); - break; - } - } + const QList entries = restoredGroup->entries(); + for (Entry* entry : entries) { + if (entry->uuid() == entryUuid) { + m_entryView->setCurrentEntry(entry); + break; + } + } } - } bool DatabaseWidget::isGroupSelected() const @@ -1441,7 +1418,6 @@ bool DatabaseWidget::currentEntryHasUrl() return !currentEntry->resolveMultiplePlaceholders(currentEntry->url()).isEmpty(); } - bool DatabaseWidget::currentEntryHasTotp() { Entry* currentEntry = m_entryView->currentEntry(); @@ -1462,11 +1438,13 @@ bool DatabaseWidget::currentEntryHasNotes() return !currentEntry->resolveMultiplePlaceholders(currentEntry->notes()).isEmpty(); } -GroupView* DatabaseWidget::groupView() { +GroupView* DatabaseWidget::groupView() +{ return m_groupView; } -EntryView* DatabaseWidget::entryView() { +EntryView* DatabaseWidget::entryView() +{ return m_entryView; } @@ -1489,7 +1467,10 @@ void DatabaseWidget::closeUnlockDialog() m_unlockDatabaseDialog->close(); } -void DatabaseWidget::showMessage(const QString& text, MessageWidget::MessageType type, bool showClosebutton, int autoHideTimeout) +void DatabaseWidget::showMessage(const QString& text, + MessageWidget::MessageType type, + bool showClosebutton, + int autoHideTimeout) { m_messageWidget->setCloseButtonVisible(showClosebutton); m_messageWidget->showMessage(text, type, autoHideTimeout); @@ -1514,14 +1495,15 @@ bool DatabaseWidget::isRecycleBinSelected() const void DatabaseWidget::emptyRecycleBin() { - if(!isRecycleBinSelected()) { + if (!isRecycleBinSelected()) { return; } - QMessageBox::StandardButton result = MessageBox::question( - this, tr("Empty recycle bin?"), - tr("Are you sure you want to permanently delete everything from your recycle bin?"), - QMessageBox::Yes | QMessageBox::No); + QMessageBox::StandardButton result = + MessageBox::question(this, + tr("Empty recycle bin?"), + tr("Are you sure you want to permanently delete everything from your recycle bin?"), + QMessageBox::Yes | QMessageBox::No); if (result == QMessageBox::Yes) { m_db->emptyRecycleBin(); diff --git a/src/gui/DatabaseWidget.h b/src/gui/DatabaseWidget.h index 464a543a..ca1bfc14 100644 --- a/src/gui/DatabaseWidget.h +++ b/src/gui/DatabaseWidget.h @@ -19,16 +19,16 @@ #ifndef KEEPASSX_DATABASEWIDGET_H #define KEEPASSX_DATABASEWIDGET_H +#include #include #include -#include #include #include "core/Uuid.h" -#include "gui/entry/EntryModel.h" #include "gui/MessageWidget.h" #include "gui/csvImport/CsvImportWizard.h" +#include "gui/entry/EntryModel.h" class ChangeMasterKeyWidget; class DatabaseOpenWidget; @@ -51,7 +51,8 @@ class DetailsWidget; class UnlockDatabaseDialog; class QFileSystemWatcher; -namespace Ui { +namespace Ui +{ class SearchWidget; } @@ -82,7 +83,7 @@ public: void setCurrentWidget(QWidget* widget); DatabaseWidget::Mode currentMode() const; void lock(); - void updateFilePath(const QString &filePath); + void updateFilePath(const QString& filePath); int numberOfSelectedEntries() const; QStringList customEntryAttributes() const; bool isGroupSelected() const; @@ -176,7 +177,9 @@ public slots: void setSearchLimitGroup(bool state); void endSearch(); - void showMessage(const QString& text, MessageWidget::MessageType type, bool showClosebutton = true, + void showMessage(const QString& text, + MessageWidget::MessageType type, + bool showClosebutton = true, int autoHideTimeout = MessageWidget::DefaultAutoHideTimeout); void showErrorMessage(const QString& errorMessage); void hideMessage(); diff --git a/src/gui/DatabaseWidgetStateSync.cpp b/src/gui/DatabaseWidgetStateSync.cpp index 9b89412e..1a1fae7a 100644 --- a/src/gui/DatabaseWidgetStateSync.cpp +++ b/src/gui/DatabaseWidgetStateSync.cpp @@ -82,20 +82,13 @@ void DatabaseWidgetStateSync::setActive(DatabaseWidget* dbWidget) m_blockUpdates = false; - connect(m_activeDbWidget, SIGNAL(mainSplitterSizesChanged()), - SLOT(updateSplitterSizes())); - connect(m_activeDbWidget, SIGNAL(detailSplitterSizesChanged()), - SLOT(updateSplitterSizes())); - connect(m_activeDbWidget, SIGNAL(entryViewStateChanged()), - SLOT(updateViewState())); - connect(m_activeDbWidget, SIGNAL(listModeActivated()), - SLOT(restoreListView())); - connect(m_activeDbWidget, SIGNAL(searchModeActivated()), - SLOT(restoreSearchView())); - connect(m_activeDbWidget, SIGNAL(listModeAboutToActivate()), - SLOT(blockUpdates())); - connect(m_activeDbWidget, SIGNAL(searchModeAboutToActivate()), - SLOT(blockUpdates())); + connect(m_activeDbWidget, SIGNAL(mainSplitterSizesChanged()), SLOT(updateSplitterSizes())); + connect(m_activeDbWidget, SIGNAL(detailSplitterSizesChanged()), SLOT(updateSplitterSizes())); + connect(m_activeDbWidget, SIGNAL(entryViewStateChanged()), SLOT(updateViewState())); + connect(m_activeDbWidget, SIGNAL(listModeActivated()), SLOT(restoreListView())); + connect(m_activeDbWidget, SIGNAL(searchModeActivated()), SLOT(restoreSearchView())); + connect(m_activeDbWidget, SIGNAL(listModeAboutToActivate()), SLOT(blockUpdates())); + connect(m_activeDbWidget, SIGNAL(searchModeAboutToActivate()), SLOT(blockUpdates())); } } diff --git a/src/gui/DetailsWidget.cpp b/src/gui/DetailsWidget.cpp index fcf8ecb5..234d7e61 100644 --- a/src/gui/DetailsWidget.cpp +++ b/src/gui/DetailsWidget.cpp @@ -20,16 +20,17 @@ #include "ui_DetailsWidget.h" #include -#include #include +#include #include "core/Config.h" #include "core/FilePath.h" -#include "gui/Clipboard.h" #include "entry/EntryAttachmentsModel.h" +#include "gui/Clipboard.h" -namespace { -constexpr int GeneralTabIndex = 0; +namespace +{ + constexpr int GeneralTabIndex = 0; } DetailsWidget::DetailsWidget(QWidget* parent) @@ -87,8 +88,7 @@ void DetailsWidget::setEntry(Entry* selectedEntry) setVisible(!config()->get("GUI/HideDetailsView").toBool()); m_ui->stackedWidget->setCurrentWidget(m_ui->pageEntry); - const int tabIndex = m_ui->entryTabWidget->isTabEnabled(m_selectedTabEntry) ? m_selectedTabEntry - : GeneralTabIndex; + const int tabIndex = m_ui->entryTabWidget->isTabEnabled(m_selectedTabEntry) ? m_selectedTabEntry : GeneralTabIndex; Q_ASSERT(m_ui->entryTabWidget->isTabEnabled(GeneralTabIndex)); m_ui->entryTabWidget->setCurrentIndex(tabIndex); } @@ -108,8 +108,7 @@ void DetailsWidget::setGroup(Group* selectedGroup) setVisible(!config()->get("GUI/HideDetailsView").toBool()); m_ui->stackedWidget->setCurrentWidget(m_ui->pageGroup); - const int tabIndex = m_ui->groupTabWidget->isTabEnabled(m_selectedTabGroup) ? m_selectedTabGroup - : GeneralTabIndex; + const int tabIndex = m_ui->groupTabWidget->isTabEnabled(m_selectedTabGroup) ? m_selectedTabGroup : GeneralTabIndex; Q_ASSERT(m_ui->groupTabWidget->isTabEnabled(GeneralTabIndex)); m_ui->groupTabWidget->setCurrentIndex(tabIndex); } @@ -188,8 +187,8 @@ void DetailsWidget::updateEntryGeneralTab() } const TimeInfo entryTime = m_currentEntry->timeInfo(); - const QString expires = entryTime.expires() ? entryTime.expiryTime().toString(Qt::DefaultLocaleShortDate) - : tr("Never"); + const QString expires = + entryTime.expires() ? entryTime.expiryTime().toString(Qt::DefaultLocaleShortDate) : tr("Never"); m_ui->entryExpirationLabel->setText(expires); } @@ -238,8 +237,8 @@ void DetailsWidget::updateEntryAutotypeTab() const AutoTypeAssociations* autotypeAssociations = m_currentEntry->autoTypeAssociations(); const auto associations = autotypeAssociations->getAll(); for (const auto& assoc : associations) { - const QString sequence = assoc.sequence.isEmpty() ? m_currentEntry->effectiveAutoTypeSequence() - : assoc.sequence; + const QString sequence = + assoc.sequence.isEmpty() ? m_currentEntry->effectiveAutoTypeSequence() : assoc.sequence; items.append(new QTreeWidgetItem(m_ui->entryAutotypeTree, {assoc.window, sequence})); } @@ -264,8 +263,8 @@ void DetailsWidget::updateGroupGeneralTab() m_ui->groupAutotypeLabel->setText(autotypeText); const TimeInfo groupTime = m_currentGroup->timeInfo(); - const QString expiresText = groupTime.expires() ? groupTime.expiryTime().toString(Qt::DefaultLocaleShortDate) - : tr("Never"); + const QString expiresText = + groupTime.expires() ? groupTime.expiryTime().toString(Qt::DefaultLocaleShortDate) : tr("Never"); m_ui->groupExpirationLabel->setText(expiresText); } diff --git a/src/gui/DetailsWidget.h b/src/gui/DetailsWidget.h index abec3340..3a4c277d 100644 --- a/src/gui/DetailsWidget.h +++ b/src/gui/DetailsWidget.h @@ -22,7 +22,8 @@ #include -namespace Ui { +namespace Ui +{ class DetailsWidget; } diff --git a/src/gui/DialogyWidget.cpp b/src/gui/DialogyWidget.cpp index d8e05a91..2c0bf35e 100644 --- a/src/gui/DialogyWidget.cpp +++ b/src/gui/DialogyWidget.cpp @@ -33,29 +33,27 @@ void DialogyWidget::keyPressEvent(QKeyEvent* e) if (!clickButton(QDialogButtonBox::Cancel)) { e->ignore(); } - } - else + } else #endif - if (!e->modifiers() || (e->modifiers() & Qt::KeypadModifier && e->key() == Qt::Key_Enter)) { + if (!e->modifiers() || (e->modifiers() & Qt::KeypadModifier && e->key() == Qt::Key_Enter)) { switch (e->key()) { - case Qt::Key_Enter: - case Qt::Key_Return: - if (!clickButton(QDialogButtonBox::Ok)) { + case Qt::Key_Enter: + case Qt::Key_Return: + if (!clickButton(QDialogButtonBox::Ok)) { + e->ignore(); + } + break; + case Qt::Key_Escape: + if (!clickButton(QDialogButtonBox::Cancel)) { + if (!clickButton(QDialogButtonBox::Close)) { e->ignore(); } - break; - case Qt::Key_Escape: - if (!clickButton(QDialogButtonBox::Cancel)) { - if (!clickButton(QDialogButtonBox::Close)) { - e->ignore(); - } - } - break; - default: - e->ignore(); + } + break; + default: + e->ignore(); } - } - else { + } else { e->ignore(); } } diff --git a/src/gui/DragTabBar.cpp b/src/gui/DragTabBar.cpp index a19031a8..c40cceb7 100644 --- a/src/gui/DragTabBar.cpp +++ b/src/gui/DragTabBar.cpp @@ -42,8 +42,7 @@ void DragTabBar::dragEnterEvent(QDragEnterEvent* event) m_tabSwitchTimer->start(QApplication::doubleClickInterval() * 2); } event->setAccepted(true); - } - else { + } else { QTabBar::dragEnterEvent(event); } } @@ -55,14 +54,12 @@ void DragTabBar::dragMoveEvent(QDragMoveEvent* event) if (tab != -1) { if (tab == currentIndex()) { m_tabSwitchTimer->stop(); - } - else if (tab != m_tabSwitchIndex) { + } else if (tab != m_tabSwitchIndex) { m_tabSwitchIndex = tab; m_tabSwitchTimer->start(QApplication::doubleClickInterval() * 2); } event->setAccepted(true); - } - else { + } else { m_tabSwitchIndex = -1; m_tabSwitchTimer->stop(); QTabBar::dragMoveEvent(event); diff --git a/src/gui/EditWidget.cpp b/src/gui/EditWidget.cpp index 5f05a428..ce80c03b 100644 --- a/src/gui/EditWidget.cpp +++ b/src/gui/EditWidget.cpp @@ -18,8 +18,8 @@ #include "EditWidget.h" #include "ui_EditWidget.h" -#include #include +#include #include "core/FilePath.h" @@ -38,8 +38,7 @@ EditWidget::EditWidget(QWidget* parent) headlineLabel()->setFont(headerLabelFont); headlineLabel()->setTextFormat(Qt::PlainText); - connect(m_ui->categoryList, SIGNAL(categoryChanged(int)), - m_ui->stackedWidget, SLOT(setCurrentIndex(int))); + connect(m_ui->categoryList, SIGNAL(categoryChanged(int)), m_ui->stackedWidget, SLOT(setCurrentIndex(int))); connect(m_ui->buttonBox, SIGNAL(accepted()), SIGNAL(accepted())); connect(m_ui->buttonBox, SIGNAL(rejected()), SIGNAL(rejected())); @@ -103,8 +102,7 @@ void EditWidget::setReadOnly(bool readOnly) if (readOnly) { m_ui->buttonBox->setStandardButtons(QDialogButtonBox::Close); - } - else { + } else { m_ui->buttonBox->setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel | QDialogButtonBox::Apply); // Find and connect the apply button QPushButton* applyButton = m_ui->buttonBox->button(QDialogButtonBox::Apply); diff --git a/src/gui/EditWidget.h b/src/gui/EditWidget.h index 38179a77..f0d157c4 100644 --- a/src/gui/EditWidget.h +++ b/src/gui/EditWidget.h @@ -20,15 +20,16 @@ #define KEEPASSX_EDITWIDGET_H #include -#include #include +#include #include "gui/DialogyWidget.h" #include "gui/MessageWidget.h" class QLabel; -namespace Ui { +namespace Ui +{ class EditWidget; } diff --git a/src/gui/EditWidgetIcons.cpp b/src/gui/EditWidgetIcons.cpp index e02ad952..0d2c63a6 100644 --- a/src/gui/EditWidgetIcons.cpp +++ b/src/gui/EditWidgetIcons.cpp @@ -20,8 +20,8 @@ #include "ui_EditWidgetIcons.h" #include -#include #include +#include #include "core/Config.h" #include "core/Group.h" @@ -31,8 +31,8 @@ #include "gui/MessageBox.h" #ifdef WITH_XC_NETWORKING -#include #include "core/AsyncTask.h" +#include #undef MessageBox #endif @@ -54,24 +54,24 @@ EditWidgetIcons::EditWidgetIcons(QWidget* parent) m_ui->defaultIconsView->setModel(m_defaultIconModel); m_ui->customIconsView->setModel(m_customIconModel); - connect(m_ui->defaultIconsView, SIGNAL(clicked(QModelIndex)), - this, SLOT(updateRadioButtonDefaultIcons())); - connect(m_ui->customIconsView, SIGNAL(clicked(QModelIndex)), - this, SLOT(updateRadioButtonCustomIcons())); - connect(m_ui->defaultIconsRadio, SIGNAL(toggled(bool)), - this, SLOT(updateWidgetsDefaultIcons(bool))); - connect(m_ui->customIconsRadio, SIGNAL(toggled(bool)), - this, SLOT(updateWidgetsCustomIcons(bool))); + connect(m_ui->defaultIconsView, SIGNAL(clicked(QModelIndex)), this, SLOT(updateRadioButtonDefaultIcons())); + connect(m_ui->customIconsView, SIGNAL(clicked(QModelIndex)), this, SLOT(updateRadioButtonCustomIcons())); + connect(m_ui->defaultIconsRadio, SIGNAL(toggled(bool)), this, SLOT(updateWidgetsDefaultIcons(bool))); + connect(m_ui->customIconsRadio, SIGNAL(toggled(bool)), this, SLOT(updateWidgetsCustomIcons(bool))); connect(m_ui->addButton, SIGNAL(clicked()), SLOT(addCustomIconFromFile())); connect(m_ui->deleteButton, SIGNAL(clicked()), SLOT(removeCustomIcon())); connect(m_ui->faviconButton, SIGNAL(clicked()), SLOT(downloadFavicon())); connect(m_ui->defaultIconsRadio, SIGNAL(toggled(bool)), this, SIGNAL(widgetUpdated())); connect(m_ui->defaultIconsRadio, SIGNAL(toggled(bool)), this, SIGNAL(widgetUpdated())); - connect(m_ui->defaultIconsView->selectionModel(), SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)), - this, SIGNAL(widgetUpdated())); - connect(m_ui->customIconsView->selectionModel(), SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)), - this, SIGNAL(widgetUpdated())); + connect(m_ui->defaultIconsView->selectionModel(), + SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)), + this, + SIGNAL(widgetUpdated())); + connect(m_ui->customIconsView->selectionModel(), + SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)), + this, + SIGNAL(widgetUpdated())); m_ui->faviconButton->setVisible(false); } @@ -111,7 +111,10 @@ void EditWidgetIcons::reset() m_currentUuid = Uuid(); } -void EditWidgetIcons::load(const Uuid& currentUuid, Database* database, const IconStruct& iconStruct, const QString& url) +void EditWidgetIcons::load(const Uuid& currentUuid, + Database* database, + const IconStruct& iconStruct, + const QString& url) { Q_ASSERT(database); Q_ASSERT(!currentUuid.isNull()); @@ -173,8 +176,8 @@ void EditWidgetIcons::downloadFavicon() emit messageEditEntry(tr("Unable to fetch favicon."), MessageWidget::Error); } } else { - emit messageEditEntry(tr("Unable to fetch favicon.") + "\n" + - tr("Hint: You can enable Google as a fallback under Tools>Settings>Security"), + emit messageEditEntry(tr("Unable to fetch favicon.") + "\n" + + tr("Hint: You can enable Google as a fallback under Tools>Settings>Security"), MessageWidget::Error); } @@ -183,14 +186,15 @@ void EditWidgetIcons::downloadFavicon() } #ifdef WITH_XC_NETWORKING -namespace { -std::size_t writeCurlResponse(char* ptr, std::size_t size, std::size_t nmemb, void* data) +namespace { - QByteArray* response = static_cast(data); - std::size_t realsize = size * nmemb; - response->append(ptr, realsize); - return realsize; -} + std::size_t writeCurlResponse(char* ptr, std::size_t size, std::size_t nmemb, void* data) + { + QByteArray* response = static_cast(data); + std::size_t realsize = size * nmemb; + response->append(ptr, realsize); + return realsize; + } } QImage EditWidgetIcons::fetchFavicon(const QUrl& url) @@ -213,14 +217,13 @@ QImage EditWidgetIcons::fetchFavicon(const QUrl& url) #ifdef Q_OS_WIN const QDir appDir = QFileInfo(QCoreApplication::applicationFilePath()).absoluteDir(); if (appDir.exists("ssl\\certs")) { - curl_easy_setopt(curl, CURLOPT_CAINFO, (appDir.absolutePath() + "\\ssl\\certs\\ca-bundle.crt").toLatin1().data()); + curl_easy_setopt( + curl, CURLOPT_CAINFO, (appDir.absolutePath() + "\\ssl\\certs\\ca-bundle.crt").toLatin1().data()); } #endif // Perform the request in another thread - CURLcode result = AsyncTask::runAndWaitForFuture([curl]() { - return curl_easy_perform(curl); - }); + CURLcode result = AsyncTask::runAndWaitForFuture([curl]() { return curl_easy_perform(curl); }); if (result == CURLE_OK) { image.loadFromData(imagedata); @@ -236,11 +239,9 @@ QImage EditWidgetIcons::fetchFavicon(const QUrl& url) void EditWidgetIcons::addCustomIconFromFile() { if (m_database) { - QString filter = QString("%1 (%2);;%3 (*)").arg(tr("Images"), - Tools::imageReaderFilter(), tr("All files")); + QString filter = QString("%1 (%2);;%3 (*)").arg(tr("Images"), Tools::imageReaderFilter(), tr("All files")); - QString filename = QFileDialog::getOpenFileName( - this, tr("Select Image"), "", filter); + QString filename = QFileDialog::getOpenFileName(this, tr("Select Image"), "", filter); if (!filename.isEmpty()) { auto icon = QImage(filename); if (!icon.isNull()) { @@ -313,11 +314,14 @@ void EditWidgetIcons::removeCustomIcon() int iconUseCount = entriesWithSameIcon.size() + groupsWithSameIcon.size(); if (iconUseCount > 0) { - QMessageBox::StandardButton ans = MessageBox::question(this, tr("Confirm Delete"), - tr("This icon is used by %n entry(s), and will be replaced " - "by the default icon. Are you sure you want to delete it?", - "", iconUseCount), - QMessageBox::Yes | QMessageBox::No); + QMessageBox::StandardButton ans = + MessageBox::question(this, + tr("Confirm Delete"), + tr("This icon is used by %n entry(s), and will be replaced " + "by the default icon. Are you sure you want to delete it?", + "", + iconUseCount), + QMessageBox::Yes | QMessageBox::No); if (ans == QMessageBox::No) { // Early out, nothing is changed @@ -335,7 +339,6 @@ void EditWidgetIcons::removeCustomIcon() } } - // Remove the icon from history entries for (Entry* entry : asConst(historyEntriesWithSameIcon)) { entry->setUpdateTimeinfo(false); diff --git a/src/gui/EditWidgetIcons.h b/src/gui/EditWidgetIcons.h index 0f875a8a..858537ab 100644 --- a/src/gui/EditWidgetIcons.h +++ b/src/gui/EditWidgetIcons.h @@ -19,9 +19,9 @@ #ifndef KEEPASSX_EDITWIDGETICONS_H #define KEEPASSX_EDITWIDGETICONS_H -#include #include #include +#include #include "config-keepassx.h" #include "core/Global.h" @@ -32,7 +32,8 @@ class Database; class DefaultIconModel; class CustomIconModel; -namespace Ui { +namespace Ui +{ class EditWidgetIcons; } diff --git a/src/gui/EditWidgetProperties.cpp b/src/gui/EditWidgetProperties.cpp index a06928c4..fa5da054 100644 --- a/src/gui/EditWidgetProperties.cpp +++ b/src/gui/EditWidgetProperties.cpp @@ -16,8 +16,8 @@ */ #include "EditWidgetProperties.h" -#include "ui_EditWidgetProperties.h" #include "MessageBox.h" +#include "ui_EditWidgetProperties.h" EditWidgetProperties::EditWidgetProperties(QWidget* parent) : QWidget(parent) @@ -29,7 +29,8 @@ EditWidgetProperties::EditWidgetProperties(QWidget* parent) m_ui->removeCustomDataButton->setEnabled(false); m_ui->customDataTable->setModel(m_customDataModel); - connect(m_ui->customDataTable->selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)), + connect(m_ui->customDataTable->selectionModel(), + SIGNAL(selectionChanged(QItemSelection, QItemSelection)), SLOT(toggleRemoveButton(QItemSelection))); connect(m_ui->removeCustomDataButton, SIGNAL(clicked()), SLOT(removeSelectedPluginData())); } @@ -41,12 +42,9 @@ EditWidgetProperties::~EditWidgetProperties() void EditWidgetProperties::setFields(const TimeInfo& timeInfo, const Uuid& uuid) { static const QString timeFormat("d MMM yyyy HH:mm:ss"); - m_ui->modifiedEdit->setText( - timeInfo.lastModificationTime().toLocalTime().toString(timeFormat)); - m_ui->createdEdit->setText( - timeInfo.creationTime().toLocalTime().toString(timeFormat)); - m_ui->accessedEdit->setText( - timeInfo.lastAccessTime().toLocalTime().toString(timeFormat)); + m_ui->modifiedEdit->setText(timeInfo.lastModificationTime().toLocalTime().toString(timeFormat)); + m_ui->createdEdit->setText(timeInfo.creationTime().toLocalTime().toString(timeFormat)); + m_ui->accessedEdit->setText(timeInfo.lastAccessTime().toLocalTime().toString(timeFormat)); m_ui->uuidEdit->setText(uuid.toHex()); } @@ -66,10 +64,11 @@ const CustomData* EditWidgetProperties::customData() const void EditWidgetProperties::removeSelectedPluginData() { if (QMessageBox::Yes != MessageBox::question(this, - tr("Delete plugin data?"), - tr("Do you really want to delete the selected plugin data?\n" - "This may cause the affected plugins to malfunction."), - QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Cancel)) { + tr("Delete plugin data?"), + tr("Do you really want to delete the selected plugin data?\n" + "This may cause the affected plugins to malfunction."), + QMessageBox::Yes | QMessageBox::Cancel, + QMessageBox::Cancel)) { return; } @@ -95,9 +94,8 @@ void EditWidgetProperties::updateModel() m_customDataModel->setHorizontalHeaderLabels({tr("Key"), tr("Value")}); for (const QString& key : m_customData->keys()) { - m_customDataModel->appendRow(QList() - << new QStandardItem(key) - << new QStandardItem(m_customData->value(key))); + m_customDataModel->appendRow(QList() << new QStandardItem(key) + << new QStandardItem(m_customData->value(key))); } m_ui->removeCustomDataButton->setEnabled(false); diff --git a/src/gui/EditWidgetProperties.h b/src/gui/EditWidgetProperties.h index a1fd198d..e6bb2ed7 100644 --- a/src/gui/EditWidgetProperties.h +++ b/src/gui/EditWidgetProperties.h @@ -18,16 +18,17 @@ #ifndef KEEPASSX_EDITWIDGETPROPERTIES_H #define KEEPASSX_EDITWIDGETPROPERTIES_H -#include #include #include +#include #include #include "core/CustomData.h" #include "core/TimeInfo.h" #include "core/Uuid.h" -namespace Ui { +namespace Ui +{ class EditWidgetProperties; } diff --git a/src/gui/FileDialog.cpp b/src/gui/FileDialog.cpp index 9f3caf6d..d58f5292 100644 --- a/src/gui/FileDialog.cpp +++ b/src/gui/FileDialog.cpp @@ -21,22 +21,23 @@ FileDialog* FileDialog::m_instance(nullptr); -QString FileDialog::getOpenFileName(QWidget* parent, const QString& caption, QString dir, - const QString& filter, QString* selectedFilter, +QString FileDialog::getOpenFileName(QWidget* parent, + const QString& caption, + QString dir, + const QString& filter, + QString* selectedFilter, QFileDialog::Options options) { if (!m_nextFileName.isEmpty()) { QString result = m_nextFileName; m_nextFileName.clear(); return result; - } - else { + } else { if (dir.isEmpty()) { dir = config()->get("LastDir").toString(); } - QString result = QFileDialog::getOpenFileName(parent, caption, dir, filter, - selectedFilter, options); + QString result = QFileDialog::getOpenFileName(parent, caption, dir, filter, selectedFilter, options); // on Mac OS X the focus is lost after closing the native dialog if (parent) { @@ -48,22 +49,23 @@ QString FileDialog::getOpenFileName(QWidget* parent, const QString& caption, QSt } } -QStringList FileDialog::getOpenFileNames(QWidget *parent, const QString &caption, QString dir, - const QString &filter, QString *selectedFilter, - QFileDialog::Options options) +QStringList FileDialog::getOpenFileNames(QWidget* parent, + const QString& caption, + QString dir, + const QString& filter, + QString* selectedFilter, + QFileDialog::Options options) { if (!m_nextFileNames.isEmpty()) { QStringList results = m_nextFileNames; m_nextFileNames.clear(); return results; - } - else { + } else { if (dir.isEmpty()) { dir = config()->get("LastDir").toString(); } - QStringList results = QFileDialog::getOpenFileNames(parent, caption, dir, filter, - selectedFilter, options); + QStringList results = QFileDialog::getOpenFileNames(parent, caption, dir, filter, selectedFilter, options); // on Mac OS X the focus is lost after closing the native dialog if (parent) { @@ -77,16 +79,19 @@ QStringList FileDialog::getOpenFileNames(QWidget *parent, const QString &caption } } -QString FileDialog::getSaveFileName(QWidget* parent, const QString& caption, QString dir, - const QString& filter, QString* selectedFilter, - QFileDialog::Options options, const QString& defaultExtension) +QString FileDialog::getSaveFileName(QWidget* parent, + const QString& caption, + QString dir, + const QString& filter, + QString* selectedFilter, + QFileDialog::Options options, + const QString& defaultExtension) { if (!m_nextFileName.isEmpty()) { QString result = m_nextFileName; m_nextFileName.clear(); return result; - } - else { + } else { if (dir.isEmpty()) { dir = config()->get("LastDir").toString(); } @@ -95,8 +100,7 @@ QString FileDialog::getSaveFileName(QWidget* parent, const QString& caption, QSt #if defined(Q_OS_MAC) || defined(Q_OS_WIN) Q_UNUSED(defaultExtension); // the native dialogs on these platforms already append the file extension - result = QFileDialog::getSaveFileName(parent, caption, dir, filter, - selectedFilter, options); + result = QFileDialog::getSaveFileName(parent, caption, dir, filter, selectedFilter, options); #else QFileDialog dialog(parent, caption, dir, filter); dialog.setAcceptMode(QFileDialog::AcceptSave); @@ -126,15 +130,14 @@ QString FileDialog::getSaveFileName(QWidget* parent, const QString& caption, QSt } } -QString FileDialog::getExistingDirectory(QWidget *parent, const QString &caption, QString dir, - QFileDialog::Options options) +QString +FileDialog::getExistingDirectory(QWidget* parent, const QString& caption, QString dir, QFileDialog::Options options) { if (!m_nextDirName.isEmpty()) { QString result = m_nextDirName; m_nextDirName.clear(); return result; - } - else { + } else { if (dir.isEmpty()) { dir = config()->get("LastDir").toString(); } @@ -156,12 +159,12 @@ void FileDialog::setNextFileName(const QString& fileName) m_nextFileName = fileName; } -void FileDialog::setNextFileNames(const QStringList &fileNames) +void FileDialog::setNextFileNames(const QStringList& fileNames) { m_nextFileNames = fileNames; } -void FileDialog::setNextDirName(const QString &dirName) +void FileDialog::setNextDirName(const QString& dirName) { m_nextDirName = dirName; } @@ -175,7 +178,8 @@ FileDialog::FileDialog() { } -void FileDialog::saveLastDir(QString dir) { +void FileDialog::saveLastDir(QString dir) +{ if (!dir.isEmpty() && !m_forgetLastDir) { config()->set("LastDir", QFileInfo(dir).absolutePath()); } diff --git a/src/gui/FileDialog.h b/src/gui/FileDialog.h index 9a57a921..4862dcfd 100644 --- a/src/gui/FileDialog.h +++ b/src/gui/FileDialog.h @@ -23,18 +23,29 @@ class FileDialog { public: - QString getOpenFileName(QWidget* parent = nullptr, const QString& caption = QString(), - QString dir = QString(), const QString& filter = QString(), - QString* selectedFilter = nullptr, QFileDialog::Options options = 0); - QStringList getOpenFileNames(QWidget* parent = nullptr, const QString& caption = QString(), - QString dir = QString(), const QString& filter = QString(), - QString* selectedFilter = nullptr, QFileDialog::Options options = 0); - QString getSaveFileName(QWidget* parent = nullptr, const QString& caption = QString(), - QString dir = QString(), const QString& filter = QString(), - QString* selectedFilter = nullptr, QFileDialog::Options options = 0, + QString getOpenFileName(QWidget* parent = nullptr, + const QString& caption = QString(), + QString dir = QString(), + const QString& filter = QString(), + QString* selectedFilter = nullptr, + QFileDialog::Options options = 0); + QStringList getOpenFileNames(QWidget* parent = nullptr, + const QString& caption = QString(), + QString dir = QString(), + const QString& filter = QString(), + QString* selectedFilter = nullptr, + QFileDialog::Options options = 0); + QString getSaveFileName(QWidget* parent = nullptr, + const QString& caption = QString(), + QString dir = QString(), + const QString& filter = QString(), + QString* selectedFilter = nullptr, + QFileDialog::Options options = 0, const QString& defaultExtension = QString()); - QString getExistingDirectory(QWidget* parent = nullptr, const QString& caption = QString(), - QString dir = QString(), QFileDialog::Options options = QFileDialog::ShowDirsOnly); + QString getExistingDirectory(QWidget* parent = nullptr, + const QString& caption = QString(), + QString dir = QString(), + QFileDialog::Options options = QFileDialog::ShowDirsOnly); void setNextForgetDialog(); /** @@ -61,7 +72,8 @@ private: Q_DISABLE_COPY(FileDialog) }; -inline FileDialog* fileDialog() { +inline FileDialog* fileDialog() +{ return FileDialog::instance(); } diff --git a/src/gui/Font.h b/src/gui/Font.h index bfc3d7d3..076c4277 100644 --- a/src/gui/Font.h +++ b/src/gui/Font.h @@ -24,8 +24,11 @@ class Font { public: static QFont fixedFont(); + private: - Font() {} + Font() + { + } }; #endif // KEEPASSX_FONT_H diff --git a/src/gui/IconModels.cpp b/src/gui/IconModels.cpp index 1c181eae..48868284 100644 --- a/src/gui/IconModels.cpp +++ b/src/gui/IconModels.cpp @@ -28,8 +28,7 @@ int DefaultIconModel::rowCount(const QModelIndex& parent) const { if (!parent.isValid()) { return DatabaseIcons::IconCount; - } - else { + } else { return 0; } } @@ -69,8 +68,7 @@ int CustomIconModel::rowCount(const QModelIndex& parent) const { if (!parent.isValid()) { return m_icons.size(); - } - else { + } else { return 0; } } @@ -101,8 +99,7 @@ QModelIndex CustomIconModel::indexFromUuid(const Uuid& uuid) const int idx = m_iconsOrder.indexOf(uuid); if (idx > -1) { return index(idx, 0); - } - else { + } else { return QModelIndex(); } } diff --git a/src/gui/KeePass1OpenWidget.cpp b/src/gui/KeePass1OpenWidget.cpp index 91586424..4a54aaf3 100644 --- a/src/gui/KeePass1OpenWidget.cpp +++ b/src/gui/KeePass1OpenWidget.cpp @@ -20,11 +20,11 @@ #include #include -#include "ui_DatabaseOpenWidget.h" #include "core/Database.h" #include "core/Metadata.h" #include "format/KeePass1Reader.h" #include "gui/MessageBox.h" +#include "ui_DatabaseOpenWidget.h" KeePass1OpenWidget::KeePass1OpenWidget(QWidget* parent) : DatabaseOpenWidget(parent) @@ -49,8 +49,8 @@ void KeePass1OpenWidget::openDatabase() QFile file(m_filename); if (!file.open(QIODevice::ReadOnly)) { - m_ui->messageWidget->showMessage( tr("Unable to open the database.").append("\n") - .append(file.errorString()), MessageWidget::Error); + m_ui->messageWidget->showMessage(tr("Unable to open the database.").append("\n").append(file.errorString()), + MessageWidget::Error); return; } if (m_db) { @@ -63,10 +63,9 @@ void KeePass1OpenWidget::openDatabase() if (m_db) { m_db->metadata()->setName(QFileInfo(m_filename).completeBaseName()); emit editFinished(true); - } - else { - m_ui->messageWidget->showMessage(tr("Unable to open the database.").append("\n") - .append(reader.errorString()), MessageWidget::Error); + } else { + m_ui->messageWidget->showMessage(tr("Unable to open the database.").append("\n").append(reader.errorString()), + MessageWidget::Error); m_ui->editPassword->clear(); } diff --git a/src/gui/LineEdit.cpp b/src/gui/LineEdit.cpp index 148dc3d1..3e757447 100644 --- a/src/gui/LineEdit.cpp +++ b/src/gui/LineEdit.cpp @@ -31,8 +31,8 @@ LineEdit::LineEdit(QWidget* parent) m_clearButton->setObjectName("clearButton"); QIcon icon; - QString iconNameDirected = QString("edit-clear-locationbar-").append( - (layoutDirection() == Qt::LeftToRight) ? "rtl" : "ltr"); + QString iconNameDirected = + QString("edit-clear-locationbar-").append((layoutDirection() == Qt::LeftToRight) ? "rtl" : "ltr"); icon = QIcon::fromTheme(iconNameDirected); if (icon.isNull()) { icon = QIcon::fromTheme("edit-clear"); @@ -48,8 +48,8 @@ LineEdit::LineEdit(QWidget* parent) connect(m_clearButton, SIGNAL(clicked()), this, SLOT(clear())); connect(this, SIGNAL(textChanged(QString)), this, SLOT(updateCloseButton(QString))); int frameWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth); - setStyleSheet(QString("QLineEdit { padding-right: %1px; } ") - .arg(m_clearButton->sizeHint().width() + frameWidth + 1)); + setStyleSheet( + QString("QLineEdit { padding-right: %1px; } ").arg(m_clearButton->sizeHint().width() + frameWidth + 1)); QSize msz = minimumSizeHint(); setMinimumSize(qMax(msz.width(), m_clearButton->sizeHint().height() + frameWidth * 2 + 2), qMax(msz.height(), m_clearButton->sizeHint().height() + frameWidth * 2 + 2)); @@ -63,8 +63,7 @@ void LineEdit::resizeEvent(QResizeEvent* event) if (layoutDirection() == Qt::LeftToRight) { m_clearButton->move(rect().right() - frameWidth - sz.width(), y); - } - else { + } else { m_clearButton->move(rect().left() + frameWidth, y); } diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp index 8549d8f8..95bdd3fa 100644 --- a/src/gui/MainWindow.cpp +++ b/src/gui/MainWindow.cpp @@ -33,8 +33,8 @@ #include "core/Metadata.h" #include "format/KeePass2Writer.h" #include "gui/AboutDialog.h" -#include "gui/DatabaseWidget.h" #include "gui/DatabaseRepairWidget.h" +#include "gui/DatabaseWidget.h" #include "gui/FileDialog.h" #include "gui/MessageBox.h" #include "gui/SearchWidget.h" @@ -45,65 +45,72 @@ #endif #ifdef WITH_XC_BROWSER -#include "browser/NativeMessagingHost.h" -#include "browser/BrowserSettings.h" #include "browser/BrowserOptionDialog.h" +#include "browser/BrowserSettings.h" +#include "browser/NativeMessagingHost.h" #endif #if defined(Q_OS_UNIX) && !defined(Q_OS_MAC) && !defined(QT_NO_DBUS) +#include "gui/MainWindowAdaptor.h" #include #include -#include "gui/MainWindowAdaptor.h" #endif -#include "gui/SettingsWidget.h" #include "gui/PasswordGeneratorWidget.h" +#include "gui/SettingsWidget.h" #ifdef WITH_XC_BROWSER -class BrowserPlugin: public ISettingsPage +class BrowserPlugin : public ISettingsPage { - public: - BrowserPlugin(DatabaseTabWidget* tabWidget) { - m_nativeMessagingHost = QSharedPointer(new NativeMessagingHost(tabWidget)); - } +public: + BrowserPlugin(DatabaseTabWidget* tabWidget) + { + m_nativeMessagingHost = QSharedPointer(new NativeMessagingHost(tabWidget)); + } - ~BrowserPlugin() { + ~BrowserPlugin() + { + } - } + QString name() override + { + return QObject::tr("Browser Integration"); + } - QString name() override - { - return QObject::tr("Browser Integration"); - } + QIcon icon() override + { + return FilePath::instance()->icon("apps", "internet-web-browser"); + } - QIcon icon() override - { - return FilePath::instance()->icon("apps", "internet-web-browser"); - } + QWidget* createWidget() override + { + BrowserOptionDialog* dlg = new BrowserOptionDialog(); + QObject::connect(dlg, + SIGNAL(removeSharedEncryptionKeys()), + m_nativeMessagingHost.data(), + SLOT(removeSharedEncryptionKeys())); + QObject::connect( + dlg, SIGNAL(removeStoredPermissions()), m_nativeMessagingHost.data(), SLOT(removeStoredPermissions())); + return dlg; + } - QWidget* createWidget() override { - BrowserOptionDialog* dlg = new BrowserOptionDialog(); - QObject::connect(dlg, SIGNAL(removeSharedEncryptionKeys()), m_nativeMessagingHost.data(), SLOT(removeSharedEncryptionKeys())); - QObject::connect(dlg, SIGNAL(removeStoredPermissions()), m_nativeMessagingHost.data(), SLOT(removeStoredPermissions())); - return dlg; - } + void loadSettings(QWidget* widget) override + { + qobject_cast(widget)->loadSettings(); + } - void loadSettings(QWidget* widget) override - { - qobject_cast(widget)->loadSettings(); + void saveSettings(QWidget* widget) override + { + qobject_cast(widget)->saveSettings(); + if (BrowserSettings::isEnabled()) { + m_nativeMessagingHost->run(); + } else { + m_nativeMessagingHost->stop(); } + } - void saveSettings(QWidget* widget) override - { - qobject_cast(widget)->saveSettings(); - if (BrowserSettings::isEnabled()) { - m_nativeMessagingHost->run(); - } else { - m_nativeMessagingHost->stop(); - } - } - private: - QSharedPointer m_nativeMessagingHost; +private: + QSharedPointer m_nativeMessagingHost; }; #endif @@ -116,7 +123,7 @@ MainWindow::MainWindow() , m_appExiting(false) { m_ui->setupUi(this); - + #if defined(Q_OS_UNIX) && !defined(Q_OS_MAC) && !defined(QT_NO_DBUS) new MainWindowAdaptor(this); QDBusConnection dbus = QDBusConnection::sessionBus(); @@ -129,7 +136,7 @@ MainWindow::MainWindow() m_ui->toolBar->setContextMenuPolicy(Qt::PreventContextMenu); // Setup the search widget in the toolbar - SearchWidget *search = new SearchWidget(); + SearchWidget* search = new SearchWidget(); search->connectSignals(m_actionMultiplexer); m_searchWidgetAction = m_ui->toolBar->addWidget(search); m_searchWidgetAction->setEnabled(false); @@ -149,8 +156,10 @@ MainWindow::MainWindow() setWindowIcon(filePath()->applicationIcon()); m_ui->globalMessageWidget->setHidden(true); connect(m_ui->globalMessageWidget, &MessageWidget::linkActivated, &MessageWidget::openHttpUrl); - connect(m_ui->globalMessageWidget, SIGNAL(showAnimationStarted()), m_ui->globalMessageWidgetContainer, SLOT(show())); - connect(m_ui->globalMessageWidget, SIGNAL(hideAnimationFinished()), m_ui->globalMessageWidgetContainer, SLOT(hide())); + connect( + m_ui->globalMessageWidget, SIGNAL(showAnimationStarted()), m_ui->globalMessageWidgetContainer, SLOT(show())); + connect( + m_ui->globalMessageWidget, SIGNAL(hideAnimationFinished()), m_ui->globalMessageWidgetContainer, SLOT(hide())); m_clearHistoryAction = new QAction(tr("Clear history"), m_ui->menuFile); m_lastDatabasesActions = new QActionGroup(m_ui->menuRecentDatabases); @@ -159,14 +168,13 @@ MainWindow::MainWindow() connect(m_ui->menuRecentDatabases, SIGNAL(aboutToShow()), this, SLOT(updateLastDatabasesMenu())); m_copyAdditionalAttributeActions = new QActionGroup(m_ui->menuEntryCopyAttribute); - m_actionMultiplexer.connect(m_copyAdditionalAttributeActions, SIGNAL(triggered(QAction*)), - SLOT(copyAttribute(QAction*))); - connect(m_ui->menuEntryCopyAttribute, SIGNAL(aboutToShow()), - this, SLOT(updateCopyAttributesMenu())); + m_actionMultiplexer.connect( + m_copyAdditionalAttributeActions, SIGNAL(triggered(QAction*)), SLOT(copyAttribute(QAction*))); + connect(m_ui->menuEntryCopyAttribute, SIGNAL(aboutToShow()), this, SLOT(updateCopyAttributesMenu())); Qt::Key globalAutoTypeKey = static_cast(config()->get("GlobalAutoTypeKey").toInt()); - Qt::KeyboardModifiers globalAutoTypeModifiers = static_cast( - config()->get("GlobalAutoTypeModifiers").toInt()); + Qt::KeyboardModifiers globalAutoTypeModifiers = + static_cast(config()->get("GlobalAutoTypeModifiers").toInt()); if (globalAutoTypeKey > 0 && globalAutoTypeModifiers > 0) { autoType()->registerGlobalShortcut(globalAutoTypeKey, globalAutoTypeModifiers); } @@ -174,8 +182,7 @@ MainWindow::MainWindow() m_ui->actionEntryAutoType->setVisible(autoType()->isAvailable()); m_inactivityTimer = new InactivityTimer(this); - connect(m_inactivityTimer, SIGNAL(inactivityDetected()), - this, SLOT(lockDatabasesAfterInactivity())); + connect(m_inactivityTimer, SIGNAL(inactivityDetected()), this, SLOT(lockDatabasesAfterInactivity())); applySettingsChanges(); m_ui->actionDatabaseNew->setShortcut(Qt::CTRL + Qt::SHIFT + Qt::Key_N); @@ -229,35 +236,26 @@ MainWindow::MainWindow() m_ui->actionAbout->setIcon(filePath()->icon("actions", "help-about")); - m_actionMultiplexer.connect(SIGNAL(currentModeChanged(DatabaseWidget::Mode)), - this, SLOT(setMenuActionState(DatabaseWidget::Mode))); - m_actionMultiplexer.connect(SIGNAL(groupChanged()), - this, SLOT(setMenuActionState())); - m_actionMultiplexer.connect(SIGNAL(entrySelectionChanged()), - this, SLOT(setMenuActionState())); - m_actionMultiplexer.connect(SIGNAL(groupContextMenuRequested(QPoint)), - this, SLOT(showGroupContextMenu(QPoint))); - m_actionMultiplexer.connect(SIGNAL(entryContextMenuRequested(QPoint)), - this, SLOT(showEntryContextMenu(QPoint))); + m_actionMultiplexer.connect( + SIGNAL(currentModeChanged(DatabaseWidget::Mode)), this, SLOT(setMenuActionState(DatabaseWidget::Mode))); + m_actionMultiplexer.connect(SIGNAL(groupChanged()), this, SLOT(setMenuActionState())); + m_actionMultiplexer.connect(SIGNAL(entrySelectionChanged()), this, SLOT(setMenuActionState())); + m_actionMultiplexer.connect(SIGNAL(groupContextMenuRequested(QPoint)), this, SLOT(showGroupContextMenu(QPoint))); + m_actionMultiplexer.connect(SIGNAL(entryContextMenuRequested(QPoint)), this, SLOT(showEntryContextMenu(QPoint))); // Notify search when the active database changes or gets locked - connect(m_ui->tabWidget, SIGNAL(activateDatabaseChanged(DatabaseWidget*)), - search, SLOT(databaseChanged(DatabaseWidget*))); - connect(m_ui->tabWidget, SIGNAL(databaseLocked(DatabaseWidget*)), - search, SLOT(databaseChanged())); + connect(m_ui->tabWidget, + SIGNAL(activateDatabaseChanged(DatabaseWidget*)), + search, + SLOT(databaseChanged(DatabaseWidget*))); + connect(m_ui->tabWidget, SIGNAL(databaseLocked(DatabaseWidget*)), search, SLOT(databaseChanged())); - connect(m_ui->tabWidget, SIGNAL(tabNameChanged()), - SLOT(updateWindowTitle())); - connect(m_ui->tabWidget, SIGNAL(currentChanged(int)), - SLOT(updateWindowTitle())); - connect(m_ui->tabWidget, SIGNAL(currentChanged(int)), - SLOT(databaseTabChanged(int))); - connect(m_ui->tabWidget, SIGNAL(currentChanged(int)), - SLOT(setMenuActionState())); - connect(m_ui->tabWidget, SIGNAL(databaseLocked(DatabaseWidget*)), - SLOT(databaseStatusChanged(DatabaseWidget*))); - connect(m_ui->tabWidget, SIGNAL(databaseUnlocked(DatabaseWidget*)), - SLOT(databaseStatusChanged(DatabaseWidget*))); + connect(m_ui->tabWidget, SIGNAL(tabNameChanged()), SLOT(updateWindowTitle())); + connect(m_ui->tabWidget, SIGNAL(currentChanged(int)), SLOT(updateWindowTitle())); + connect(m_ui->tabWidget, SIGNAL(currentChanged(int)), SLOT(databaseTabChanged(int))); + connect(m_ui->tabWidget, SIGNAL(currentChanged(int)), SLOT(setMenuActionState())); + connect(m_ui->tabWidget, SIGNAL(databaseLocked(DatabaseWidget*)), SLOT(databaseStatusChanged(DatabaseWidget*))); + connect(m_ui->tabWidget, SIGNAL(databaseUnlocked(DatabaseWidget*)), SLOT(databaseStatusChanged(DatabaseWidget*))); connect(m_ui->stackedWidget, SIGNAL(currentChanged(int)), SLOT(setMenuActionState())); connect(m_ui->stackedWidget, SIGNAL(currentChanged(int)), SLOT(updateWindowTitle())); connect(m_ui->settingsWidget, SIGNAL(accepted()), SLOT(applySettingsChanges())); @@ -265,73 +263,42 @@ MainWindow::MainWindow() connect(m_ui->settingsWidget, SIGNAL(accepted()), SLOT(switchToDatabases())); connect(m_ui->settingsWidget, SIGNAL(rejected()), SLOT(switchToDatabases())); - connect(m_ui->actionDatabaseNew, SIGNAL(triggered()), m_ui->tabWidget, - SLOT(newDatabase())); - connect(m_ui->actionDatabaseOpen, SIGNAL(triggered()), m_ui->tabWidget, - SLOT(openDatabase())); - connect(m_ui->actionDatabaseSave, SIGNAL(triggered()), m_ui->tabWidget, - SLOT(saveDatabase())); - connect(m_ui->actionDatabaseSaveAs, SIGNAL(triggered()), m_ui->tabWidget, - SLOT(saveDatabaseAs())); - connect(m_ui->actionDatabaseClose, SIGNAL(triggered()), m_ui->tabWidget, - SLOT(closeDatabase())); - connect(m_ui->actionDatabaseMerge, SIGNAL(triggered()), m_ui->tabWidget, - SLOT(mergeDatabase())); - connect(m_ui->actionChangeMasterKey, SIGNAL(triggered()), m_ui->tabWidget, - SLOT(changeMasterKey())); - connect(m_ui->actionChangeDatabaseSettings, SIGNAL(triggered()), m_ui->tabWidget, - SLOT(changeDatabaseSettings())); - connect(m_ui->actionImportCsv, SIGNAL(triggered()), m_ui->tabWidget, - SLOT(importCsv())); - connect(m_ui->actionImportKeePass1, SIGNAL(triggered()), m_ui->tabWidget, - SLOT(importKeePass1Database())); - connect(m_ui->actionRepairDatabase, SIGNAL(triggered()), this, - SLOT(repairDatabase())); - connect(m_ui->actionExportCsv, SIGNAL(triggered()), m_ui->tabWidget, - SLOT(exportToCsv())); - connect(m_ui->actionLockDatabases, SIGNAL(triggered()), m_ui->tabWidget, - SLOT(lockDatabases())); + connect(m_ui->actionDatabaseNew, SIGNAL(triggered()), m_ui->tabWidget, SLOT(newDatabase())); + connect(m_ui->actionDatabaseOpen, SIGNAL(triggered()), m_ui->tabWidget, SLOT(openDatabase())); + connect(m_ui->actionDatabaseSave, SIGNAL(triggered()), m_ui->tabWidget, SLOT(saveDatabase())); + connect(m_ui->actionDatabaseSaveAs, SIGNAL(triggered()), m_ui->tabWidget, SLOT(saveDatabaseAs())); + connect(m_ui->actionDatabaseClose, SIGNAL(triggered()), m_ui->tabWidget, SLOT(closeDatabase())); + connect(m_ui->actionDatabaseMerge, SIGNAL(triggered()), m_ui->tabWidget, SLOT(mergeDatabase())); + connect(m_ui->actionChangeMasterKey, SIGNAL(triggered()), m_ui->tabWidget, SLOT(changeMasterKey())); + connect(m_ui->actionChangeDatabaseSettings, SIGNAL(triggered()), m_ui->tabWidget, SLOT(changeDatabaseSettings())); + connect(m_ui->actionImportCsv, SIGNAL(triggered()), m_ui->tabWidget, SLOT(importCsv())); + connect(m_ui->actionImportKeePass1, SIGNAL(triggered()), m_ui->tabWidget, SLOT(importKeePass1Database())); + connect(m_ui->actionRepairDatabase, SIGNAL(triggered()), this, SLOT(repairDatabase())); + connect(m_ui->actionExportCsv, SIGNAL(triggered()), m_ui->tabWidget, SLOT(exportToCsv())); + connect(m_ui->actionLockDatabases, SIGNAL(triggered()), m_ui->tabWidget, SLOT(lockDatabases())); connect(m_ui->actionQuit, SIGNAL(triggered()), SLOT(appExit())); - m_actionMultiplexer.connect(m_ui->actionEntryNew, SIGNAL(triggered()), - SLOT(createEntry())); - m_actionMultiplexer.connect(m_ui->actionEntryClone, SIGNAL(triggered()), - SLOT(cloneEntry())); - m_actionMultiplexer.connect(m_ui->actionEntryEdit, SIGNAL(triggered()), - SLOT(switchToEntryEdit())); - m_actionMultiplexer.connect(m_ui->actionEntryDelete, SIGNAL(triggered()), - SLOT(deleteEntries())); + m_actionMultiplexer.connect(m_ui->actionEntryNew, SIGNAL(triggered()), SLOT(createEntry())); + m_actionMultiplexer.connect(m_ui->actionEntryClone, SIGNAL(triggered()), SLOT(cloneEntry())); + m_actionMultiplexer.connect(m_ui->actionEntryEdit, SIGNAL(triggered()), SLOT(switchToEntryEdit())); + m_actionMultiplexer.connect(m_ui->actionEntryDelete, SIGNAL(triggered()), SLOT(deleteEntries())); - m_actionMultiplexer.connect(m_ui->actionEntryTotp, SIGNAL(triggered()), - SLOT(showTotp())); - m_actionMultiplexer.connect(m_ui->actionEntrySetupTotp, SIGNAL(triggered()), - SLOT(setupTotp())); + m_actionMultiplexer.connect(m_ui->actionEntryTotp, SIGNAL(triggered()), SLOT(showTotp())); + m_actionMultiplexer.connect(m_ui->actionEntrySetupTotp, SIGNAL(triggered()), SLOT(setupTotp())); - m_actionMultiplexer.connect(m_ui->actionEntryCopyTotp, SIGNAL(triggered()), - SLOT(copyTotp())); - m_actionMultiplexer.connect(m_ui->actionEntryCopyTitle, SIGNAL(triggered()), - SLOT(copyTitle())); - m_actionMultiplexer.connect(m_ui->actionEntryCopyUsername, SIGNAL(triggered()), - SLOT(copyUsername())); - m_actionMultiplexer.connect(m_ui->actionEntryCopyPassword, SIGNAL(triggered()), - SLOT(copyPassword())); - 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->actionEntryOpenUrl, SIGNAL(triggered()), - SLOT(openUrl())); + m_actionMultiplexer.connect(m_ui->actionEntryCopyTotp, SIGNAL(triggered()), SLOT(copyTotp())); + m_actionMultiplexer.connect(m_ui->actionEntryCopyTitle, SIGNAL(triggered()), SLOT(copyTitle())); + m_actionMultiplexer.connect(m_ui->actionEntryCopyUsername, SIGNAL(triggered()), SLOT(copyUsername())); + m_actionMultiplexer.connect(m_ui->actionEntryCopyPassword, SIGNAL(triggered()), SLOT(copyPassword())); + 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->actionEntryOpenUrl, SIGNAL(triggered()), SLOT(openUrl())); - m_actionMultiplexer.connect(m_ui->actionGroupNew, SIGNAL(triggered()), - SLOT(createGroup())); - m_actionMultiplexer.connect(m_ui->actionGroupEdit, SIGNAL(triggered()), - SLOT(switchToGroupEdit())); - m_actionMultiplexer.connect(m_ui->actionGroupDelete, SIGNAL(triggered()), - SLOT(deleteGroup())); - m_actionMultiplexer.connect(m_ui->actionGroupEmptyRecycleBin, SIGNAL(triggered()), - SLOT(emptyRecycleBin())); + m_actionMultiplexer.connect(m_ui->actionGroupNew, SIGNAL(triggered()), SLOT(createGroup())); + m_actionMultiplexer.connect(m_ui->actionGroupEdit, SIGNAL(triggered()), SLOT(switchToGroupEdit())); + m_actionMultiplexer.connect(m_ui->actionGroupDelete, SIGNAL(triggered()), SLOT(deleteGroup())); + m_actionMultiplexer.connect(m_ui->actionGroupEmptyRecycleBin, SIGNAL(triggered()), SLOT(emptyRecycleBin())); connect(m_ui->actionSettings, SIGNAL(triggered()), SLOT(switchToSettings())); connect(m_ui->actionPasswordGenerator, SIGNAL(toggled(bool)), SLOT(switchToPasswordGen(bool))); @@ -349,9 +316,15 @@ MainWindow::MainWindow() setUnifiedTitleAndToolBarOnMac(true); #endif - connect(m_ui->tabWidget, SIGNAL(messageGlobal(QString,MessageWidget::MessageType)), this, SLOT(displayGlobalMessage(QString, MessageWidget::MessageType))); + connect(m_ui->tabWidget, + SIGNAL(messageGlobal(QString, MessageWidget::MessageType)), + this, + SLOT(displayGlobalMessage(QString, MessageWidget::MessageType))); connect(m_ui->tabWidget, SIGNAL(messageDismissGlobal()), this, SLOT(hideGlobalMessage())); - connect(m_ui->tabWidget, SIGNAL(messageTab(QString,MessageWidget::MessageType)), this, SLOT(displayTabMessage(QString, MessageWidget::MessageType))); + connect(m_ui->tabWidget, + SIGNAL(messageTab(QString, MessageWidget::MessageType)), + this, + SLOT(displayTabMessage(QString, MessageWidget::MessageType))); connect(m_ui->tabWidget, SIGNAL(messageDismissTab()), this, SLOT(hideTabMessage())); m_screenLockListener = new ScreenLockListener(this); @@ -360,15 +333,17 @@ MainWindow::MainWindow() updateTrayIcon(); if (config()->hasAccessError()) { - m_ui->globalMessageWidget->showMessage( - tr("Access error for config file %1").arg(config()->getFileName()), MessageWidget::Error); + m_ui->globalMessageWidget->showMessage(tr("Access error for config file %1").arg(config()->getFileName()), + MessageWidget::Error); } #ifndef KEEPASSXC_BUILD_TYPE_RELEASE - m_ui->globalMessageWidget->showMessage(tr("WARNING: You are using an unstable build of KeePassXC!\n" - "There is a high risk of corruption, maintain a backup of your databases.\n" - "This version is not meant for production use."), - MessageWidget::Warning, -1); + m_ui->globalMessageWidget->showMessage( + tr("WARNING: You are using an unstable build of KeePassXC!\n" + "There is a high risk of corruption, maintain a backup of your databases.\n" + "This version is not meant for production use."), + MessageWidget::Warning, + -1); #endif } @@ -461,7 +436,7 @@ void MainWindow::setMenuActionState(DatabaseWidget::Mode mode) switch (mode) { case DatabaseWidget::ViewMode: { - //bool inSearch = dbWidget->isInSearchMode(); + // bool inSearch = dbWidget->isInSearchMode(); bool singleEntrySelected = dbWidget->numberOfSelectedEntries() == 1; bool entriesSelected = dbWidget->numberOfSelectedEntries() > 0; bool groupSelected = dbWidget->isGroupSelected(); @@ -533,8 +508,7 @@ void MainWindow::setMenuActionState(DatabaseWidget::Mode mode) Q_ASSERT(false); } m_ui->actionDatabaseClose->setEnabled(true); - } - else { + } else { const QList entryActions = m_ui->menuEntries->actions(); for (QAction* action : entryActions) { action->setEnabled(false); @@ -629,8 +603,7 @@ void MainWindow::switchToDatabases() { if (m_ui->tabWidget->currentIndex() == -1) { m_ui->stackedWidget->setCurrentIndex(WelcomeScreen); - } - else { + } else { m_ui->stackedWidget->setCurrentIndex(DatabaseTabScreen); } } @@ -644,13 +617,13 @@ void MainWindow::switchToSettings() void MainWindow::switchToPasswordGen(bool enabled) { if (enabled == true) { - m_ui->passwordGeneratorWidget->loadSettings(); - m_ui->passwordGeneratorWidget->regeneratePassword(); - m_ui->passwordGeneratorWidget->setStandaloneMode(true); - m_ui->stackedWidget->setCurrentIndex(PasswordGeneratorScreen); + m_ui->passwordGeneratorWidget->loadSettings(); + m_ui->passwordGeneratorWidget->regeneratePassword(); + m_ui->passwordGeneratorWidget->setStandaloneMode(true); + m_ui->stackedWidget->setCurrentIndex(PasswordGeneratorScreen); } else { - m_ui->passwordGeneratorWidget->saveSettings(); - switchToDatabases(); + m_ui->passwordGeneratorWidget->saveSettings(); + switchToDatabases(); } } @@ -689,7 +662,7 @@ void MainWindow::switchToImportCsv() switchToDatabases(); } -void MainWindow::databaseStatusChanged(DatabaseWidget *) +void MainWindow::databaseStatusChanged(DatabaseWidget*) { updateTrayIcon(); } @@ -698,8 +671,7 @@ void MainWindow::databaseTabChanged(int tabIndex) { if (tabIndex != -1 && m_ui->stackedWidget->currentIndex() == WelcomeScreen) { m_ui->stackedWidget->setCurrentIndex(DatabaseTabScreen); - } - else if (tabIndex == -1 && m_ui->stackedWidget->currentIndex() == DatabaseTabScreen) { + } else if (tabIndex == -1 && m_ui->stackedWidget->currentIndex() == DatabaseTabScreen) { m_ui->stackedWidget->setCurrentIndex(WelcomeScreen); } @@ -714,10 +686,8 @@ void MainWindow::closeEvent(QCloseEvent* event) return; } - bool minimizeOnClose = isTrayIconEnabled() && - config()->get("GUI/MinimizeOnClose").toBool(); - if (minimizeOnClose && !m_appExitCalled) - { + bool minimizeOnClose = isTrayIconEnabled() && config()->get("GUI/MinimizeOnClose").toBool(); + if (minimizeOnClose && !m_appExitCalled) { event->ignore(); hideWindow(); @@ -736,8 +706,7 @@ void MainWindow::closeEvent(QCloseEvent* event) event->accept(); QApplication::quit(); - } - else { + } else { event->ignore(); } } @@ -746,8 +715,7 @@ void MainWindow::changeEvent(QEvent* event) { if ((event->type() == QEvent::WindowStateChange) && isMinimized()) { if (isTrayIconEnabled() && m_trayIcon && m_trayIcon->isVisible() - && config()->get("GUI/MinimizeToTray").toBool()) - { + && config()->get("GUI/MinimizeToTray").toBool()) { event->ignore(); QTimer::singleShot(0, this, SLOT(hide())); } @@ -755,8 +723,7 @@ void MainWindow::changeEvent(QEvent* event) if (config()->get("security/lockdatabaseminimize").toBool()) { m_ui->tabWidget->lockDatabases(); } - } - else { + } else { QMainWindow::changeEvent(event); } } @@ -775,20 +742,18 @@ bool MainWindow::saveLastDatabases() bool openPreviousDatabasesOnStartup = config()->get("OpenPreviousDatabasesOnStartup").toBool(); if (openPreviousDatabasesOnStartup) { - connect(m_ui->tabWidget, SIGNAL(databaseWithFileClosed(QString)), - this, SLOT(rememberOpenDatabases(QString))); + connect(m_ui->tabWidget, SIGNAL(databaseWithFileClosed(QString)), this, SLOT(rememberOpenDatabases(QString))); } if (!m_ui->tabWidget->closeAllDatabases()) { accept = false; - } - else { + } else { accept = true; } if (openPreviousDatabasesOnStartup) { - disconnect(m_ui->tabWidget, SIGNAL(databaseWithFileClosed(QString)), - this, SLOT(rememberOpenDatabases(QString))); + disconnect( + m_ui->tabWidget, SIGNAL(databaseWithFileClosed(QString)), this, SLOT(rememberOpenDatabases(QString))); config()->set("LastOpenedDatabases", m_openDatabases); } @@ -813,24 +778,23 @@ void MainWindow::updateTrayIcon() #else menu->addAction(m_ui->actionQuit); - connect(m_trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), + connect(m_trayIcon, + SIGNAL(activated(QSystemTrayIcon::ActivationReason)), SLOT(trayIconTriggered(QSystemTrayIcon::ActivationReason))); #endif connect(actionToggle, SIGNAL(triggered()), SLOT(toggleWindow())); m_trayIcon->setContextMenu(menu); - + m_trayIcon->setIcon(filePath()->trayIcon()); m_trayIcon->show(); } if (m_ui->tabWidget->hasLockableDatabases()) { m_trayIcon->setIcon(filePath()->trayIconUnlocked()); - } - else { + } else { m_trayIcon->setIcon(filePath()->trayIconLocked()); } - } - else { + } else { if (m_trayIcon) { m_trayIcon->hide(); delete m_trayIcon; @@ -853,8 +817,7 @@ void MainWindow::setShortcut(QAction* action, QKeySequence::StandardKey standard { if (!QKeySequence::keyBindings(standard).isEmpty()) { action->setShortcuts(standard); - } - else if (fallback != 0) { + } else if (fallback != 0) { action->setShortcut(QKeySequence(fallback)); } } @@ -874,8 +837,7 @@ void MainWindow::applySettingsChanges() m_inactivityTimer->setInactivityTimeout(timeout); if (config()->get("security/lockdatabaseidle").toBool()) { m_inactivityTimer->activate(); - } - else { + } else { m_inactivityTimer->deactivate(); } @@ -919,11 +881,10 @@ void MainWindow::toggleWindow() // and https://bugreports.qt.io/browse/QTBUG-58723 // check for !isVisible(), because isNativeMenuBar() does not work with appmenu-qt5 if (!m_ui->menubar->isVisible()) { - QDBusMessage msg = QDBusMessage::createMethodCall( - "com.canonical.AppMenu.Registrar", - "/com/canonical/AppMenu/Registrar", - "com.canonical.AppMenu.Registrar", - "RegisterWindow"); + QDBusMessage msg = QDBusMessage::createMethodCall("com.canonical.AppMenu.Registrar", + "/com/canonical/AppMenu/Registrar", + "com.canonical.AppMenu.Registrar", + "RegisterWindow"); QList args; args << QVariant::fromValue(static_cast(winId())) << QVariant::fromValue(QDBusObjectPath("/MenuBar/1")); @@ -947,8 +908,7 @@ void MainWindow::lockDatabasesAfterInactivity() void MainWindow::repairDatabase() { QString filter = QString("%1 (*.kdbx);;%2 (*)").arg(tr("KeePass 2 Database"), tr("All files")); - QString fileName = fileDialog()->getOpenFileName(this, tr("Open database"), QString(), - filter); + QString fileName = fileDialog()->getOpenFileName(this, tr("Open database"), QString(), filter); if (fileName.isEmpty()) { return; } @@ -959,17 +919,20 @@ void MainWindow::repairDatabase() connect(dbRepairWidget, SIGNAL(error()), dialog.data(), SLOT(reject())); dbRepairWidget->load(fileName); if (dialog->exec() == QDialog::Accepted && dbRepairWidget->database()) { - QString saveFileName = fileDialog()->getSaveFileName(this, tr("Save repaired database"), QString(), + QString saveFileName = fileDialog()->getSaveFileName(this, + tr("Save repaired database"), + QString(), tr("KeePass 2 Database").append(" (*.kdbx)"), - nullptr, 0, "kdbx"); + nullptr, + 0, + "kdbx"); if (!saveFileName.isEmpty()) { KeePass2Writer writer; writer.writeDatabase(saveFileName, dbRepairWidget->database()); if (writer.hasError()) { - displayGlobalMessage( - tr("Writing the database failed.").append("\n").append(writer.errorString()), - MessageWidget::Error); + displayGlobalMessage(tr("Writing the database failed.").append("\n").append(writer.errorString()), + MessageWidget::Error); } } } @@ -977,18 +940,21 @@ void MainWindow::repairDatabase() bool MainWindow::isTrayIconEnabled() const { - return config()->get("GUI/ShowTrayIcon").toBool() - && QSystemTrayIcon::isSystemTrayAvailable(); + return config()->get("GUI/ShowTrayIcon").toBool() && QSystemTrayIcon::isSystemTrayAvailable(); } -void MainWindow::displayGlobalMessage(const QString& text, MessageWidget::MessageType type, bool showClosebutton, +void MainWindow::displayGlobalMessage(const QString& text, + MessageWidget::MessageType type, + bool showClosebutton, int autoHideTimeout) { m_ui->globalMessageWidget->setCloseButtonVisible(showClosebutton); m_ui->globalMessageWidget->showMessage(text, type, autoHideTimeout); } -void MainWindow::displayTabMessage(const QString& text, MessageWidget::MessageType type, bool showClosebutton, +void MainWindow::displayTabMessage(const QString& text, + MessageWidget::MessageType type, + bool showClosebutton, int autoHideTimeout) { m_ui->tabWidget->currentDatabaseWidget()->showMessage(text, type, showClosebutton, autoHideTimeout); @@ -1008,8 +974,10 @@ void MainWindow::hideTabMessage() void MainWindow::showYubiKeyPopup() { - displayGlobalMessage(tr("Please touch the button on your YubiKey!"), MessageWidget::Information, - false, MessageWidget::DisableAutoHide); + displayGlobalMessage(tr("Please touch the button on your YubiKey!"), + MessageWidget::Information, + false, + MessageWidget::DisableAutoHide); setEnabled(false); } @@ -1030,7 +998,7 @@ void MainWindow::bringToFront() void MainWindow::handleScreenLock() { - if (config()->get("security/lockdatabasescreenlock").toBool()){ + if (config()->get("security/lockdatabasescreenlock").toBool()) { lockDatabasesAfterInactivity(); } } @@ -1038,7 +1006,7 @@ void MainWindow::handleScreenLock() QStringList MainWindow::kdbxFilesFromUrls(const QList& urls) { QStringList kdbxFiles; - for (const QUrl& url: urls) { + for (const QUrl& url : urls) { const QFileInfo fInfo(url.toLocalFile()); const bool isKdbxFile = fInfo.isFile() && fInfo.suffix().toLower() == "kdbx"; if (isKdbxFile) { @@ -1068,7 +1036,7 @@ void MainWindow::dropEvent(QDropEvent* event) if (!kdbxFiles.isEmpty()) { event->acceptProposedAction(); } - for (const QString& kdbxFile: kdbxFiles) { + for (const QString& kdbxFile : kdbxFiles) { openDatabase(kdbxFile); } } diff --git a/src/gui/MainWindow.h b/src/gui/MainWindow.h index 5ce69523..08e264e7 100644 --- a/src/gui/MainWindow.h +++ b/src/gui/MainWindow.h @@ -23,12 +23,13 @@ #include #include -#include "core/SignalMultiplexer.h" #include "core/ScreenLockListener.h" -#include "gui/DatabaseWidget.h" +#include "core/SignalMultiplexer.h" #include "gui/Application.h" +#include "gui/DatabaseWidget.h" -namespace Ui { +namespace Ui +{ class MainWindow; } @@ -37,7 +38,7 @@ class InactivityTimer; class MainWindow : public QMainWindow { Q_OBJECT - + #if defined(Q_OS_UNIX) && !defined(Q_OS_MAC) && !defined(QT_NO_DBUS) Q_CLASSINFO("D-Bus Interface", "org.keepassxc.KeePassXC.MainWindow") #endif @@ -55,12 +56,15 @@ public: }; public slots: - void openDatabase(const QString& fileName, const QString& pw = QString(), - const QString& keyFile = QString()); + void openDatabase(const QString& fileName, const QString& pw = QString(), const QString& keyFile = QString()); void appExit(); - void displayGlobalMessage(const QString& text, MessageWidget::MessageType type, bool showClosebutton = true, + void displayGlobalMessage(const QString& text, + MessageWidget::MessageType type, + bool showClosebutton = true, int autoHideTimeout = MessageWidget::DefaultAutoHideTimeout); - void displayTabMessage(const QString& text, MessageWidget::MessageType type, bool showClosebutton = true, + void displayTabMessage(const QString& text, + MessageWidget::MessageType type, + bool showClosebutton = true, int autoHideTimeout = MessageWidget::DefaultAutoHideTimeout); void hideGlobalMessage(); void showYubiKeyPopup(); @@ -86,7 +90,7 @@ private slots: void switchToKeePass1Database(); void switchToImportCsv(); void closePasswordGen(); - void databaseStatusChanged(DatabaseWidget *dbWidget); + void databaseStatusChanged(DatabaseWidget* dbWidget); void databaseTabChanged(int tabIndex); void openRecentDatabase(QAction* action); void clearLastDatabases(); @@ -137,7 +141,8 @@ private: bool m_appExiting; }; -#define KEEPASSXC_MAIN_WINDOW (qobject_cast(qApp) ? \ - qobject_cast(qobject_cast(qApp)->mainWindow()) : nullptr) +#define KEEPASSXC_MAIN_WINDOW \ + (qobject_cast(qApp) ? qobject_cast(qobject_cast(qApp)->mainWindow()) \ + : nullptr) #endif // KEEPASSX_MAINWINDOW_H diff --git a/src/gui/MessageBox.cpp b/src/gui/MessageBox.cpp index 40912b7e..7aba6a2a 100644 --- a/src/gui/MessageBox.cpp +++ b/src/gui/MessageBox.cpp @@ -20,14 +20,14 @@ QMessageBox::StandardButton MessageBox::m_nextAnswer(QMessageBox::NoButton); QMessageBox::StandardButton MessageBox::critical(QWidget* parent, - const QString& title, const QString& text, + const QString& title, + const QString& text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton) { if (m_nextAnswer == QMessageBox::NoButton) { return QMessageBox::critical(parent, title, text, buttons, defaultButton); - } - else { + } else { QMessageBox::StandardButton returnButton = m_nextAnswer; m_nextAnswer = QMessageBox::NoButton; return returnButton; @@ -35,14 +35,14 @@ QMessageBox::StandardButton MessageBox::critical(QWidget* parent, } QMessageBox::StandardButton MessageBox::information(QWidget* parent, - const QString& title, const QString& text, + const QString& title, + const QString& text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton) { if (m_nextAnswer == QMessageBox::NoButton) { return QMessageBox::information(parent, title, text, buttons, defaultButton); - } - else { + } else { QMessageBox::StandardButton returnButton = m_nextAnswer; m_nextAnswer = QMessageBox::NoButton; return returnButton; @@ -50,14 +50,14 @@ QMessageBox::StandardButton MessageBox::information(QWidget* parent, } QMessageBox::StandardButton MessageBox::question(QWidget* parent, - const QString& title, const QString& text, + const QString& title, + const QString& text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton) { if (m_nextAnswer == QMessageBox::NoButton) { return QMessageBox::question(parent, title, text, buttons, defaultButton); - } - else { + } else { QMessageBox::StandardButton returnButton = m_nextAnswer; m_nextAnswer = QMessageBox::NoButton; return returnButton; @@ -65,14 +65,14 @@ QMessageBox::StandardButton MessageBox::question(QWidget* parent, } QMessageBox::StandardButton MessageBox::warning(QWidget* parent, - const QString& title, const QString& text, + const QString& title, + const QString& text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton) { if (m_nextAnswer == QMessageBox::NoButton) { return QMessageBox::warning(parent, title, text, buttons, defaultButton); - } - else { + } else { QMessageBox::StandardButton returnButton = m_nextAnswer; m_nextAnswer = QMessageBox::NoButton; return returnButton; diff --git a/src/gui/MessageBox.h b/src/gui/MessageBox.h index 1ea4022c..c6cdaa28 100644 --- a/src/gui/MessageBox.h +++ b/src/gui/MessageBox.h @@ -24,19 +24,23 @@ class MessageBox { public: static QMessageBox::StandardButton critical(QWidget* parent, - const QString& title, const QString& text, + const QString& title, + const QString& text, QMessageBox::StandardButtons buttons = QMessageBox::Ok, QMessageBox::StandardButton defaultButton = QMessageBox::NoButton); static QMessageBox::StandardButton information(QWidget* parent, - const QString& title, const QString& text, + const QString& title, + const QString& text, QMessageBox::StandardButtons buttons = QMessageBox::Ok, QMessageBox::StandardButton defaultButton = QMessageBox::NoButton); static QMessageBox::StandardButton question(QWidget* parent, - const QString& title, const QString& text, + const QString& title, + const QString& text, QMessageBox::StandardButtons buttons = QMessageBox::Ok, QMessageBox::StandardButton defaultButton = QMessageBox::NoButton); static QMessageBox::StandardButton warning(QWidget* parent, - const QString& title, const QString& text, + const QString& title, + const QString& text, QMessageBox::StandardButtons buttons = QMessageBox::Ok, QMessageBox::StandardButton defaultButton = QMessageBox::NoButton); diff --git a/src/gui/MessageWidget.cpp b/src/gui/MessageWidget.cpp index f40e5aad..5b18a583 100644 --- a/src/gui/MessageWidget.cpp +++ b/src/gui/MessageWidget.cpp @@ -18,8 +18,8 @@ #include "MessageWidget.h" -#include #include +#include #include const int MessageWidget::DefaultAutoHideTimeout = 6000; @@ -45,7 +45,7 @@ void MessageWidget::showMessage(const QString& text, MessageWidget::MessageType showMessage(text, type, m_autoHideTimeout); } -void MessageWidget::showMessage(const QString &text, KMessageWidget::MessageType type, int autoHideTimeout) +void MessageWidget::showMessage(const QString& text, KMessageWidget::MessageType type, int autoHideTimeout) { setMessageType(type); setText(text); diff --git a/src/gui/PasswordEdit.cpp b/src/gui/PasswordEdit.cpp index b084f9cf..94125acf 100644 --- a/src/gui/PasswordEdit.cpp +++ b/src/gui/PasswordEdit.cpp @@ -42,7 +42,7 @@ void PasswordEdit::enableVerifyMode(PasswordEdit* basePasswordEdit) m_basePasswordEdit = basePasswordEdit; updateStylesheet(); - + connect(m_basePasswordEdit, SIGNAL(textChanged(QString)), SLOT(autocompletePassword(QString))); connect(m_basePasswordEdit, SIGNAL(textChanged(QString)), SLOT(updateStylesheet())); connect(this, SIGNAL(textChanged(QString)), SLOT(updateStylesheet())); @@ -54,13 +54,12 @@ void PasswordEdit::setShowPassword(bool show) { setEchoMode(show ? QLineEdit::Normal : QLineEdit::Password); // if I have a parent, I'm the child - if (m_basePasswordEdit){ + if (m_basePasswordEdit) { if (config()->get("security/passwordsrepeat").toBool()) { setEnabled(!show); setReadOnly(show); setText(m_basePasswordEdit->text()); - } - else { + } else { // This fix a bug when the QLineEdit is disabled while switching config if (isEnabled() == false) { setEnabled(true); @@ -86,8 +85,7 @@ void PasswordEdit::updateStylesheet() if (m_basePasswordEdit->text().startsWith(text())) { stylesheet = stylesheet.arg(CorrectSoFarColor.name()); - } - else { + } else { stylesheet = stylesheet.arg(ErrorColor.name()); } } diff --git a/src/gui/PasswordGeneratorWidget.cpp b/src/gui/PasswordGeneratorWidget.cpp index 7a93f86b..3d8ebf7b 100644 --- a/src/gui/PasswordGeneratorWidget.cpp +++ b/src/gui/PasswordGeneratorWidget.cpp @@ -19,13 +19,13 @@ #include "PasswordGeneratorWidget.h" #include "ui_PasswordGeneratorWidget.h" -#include #include #include +#include #include "core/Config.h" -#include "core/PasswordGenerator.h" #include "core/FilePath.h" +#include "core/PasswordGenerator.h" #include "gui/Clipboard.h" PasswordGeneratorWidget::PasswordGeneratorWidget(QWidget* parent) @@ -96,16 +96,22 @@ void PasswordGeneratorWidget::loadSettings() m_ui->checkBoxLower->setChecked(config()->get("generator/LowerCase", PasswordGenerator::DefaultLower).toBool()); m_ui->checkBoxUpper->setChecked(config()->get("generator/UpperCase", PasswordGenerator::DefaultUpper).toBool()); m_ui->checkBoxNumbers->setChecked(config()->get("generator/Numbers", PasswordGenerator::DefaultNumbers).toBool()); - m_ui->checkBoxSpecialChars->setChecked(config()->get("generator/SpecialChars", PasswordGenerator::DefaultSpecial).toBool()); + m_ui->checkBoxSpecialChars->setChecked( + config()->get("generator/SpecialChars", PasswordGenerator::DefaultSpecial).toBool()); m_ui->checkBoxExtASCII->setChecked(config()->get("generator/EASCII", PasswordGenerator::DefaultEASCII).toBool()); - m_ui->checkBoxExcludeAlike->setChecked(config()->get("generator/ExcludeAlike", PasswordGenerator::DefaultLookAlike).toBool()); - m_ui->checkBoxEnsureEvery->setChecked(config()->get("generator/EnsureEvery", PasswordGenerator::DefaultFromEveryGroup).toBool()); + m_ui->checkBoxExcludeAlike->setChecked( + config()->get("generator/ExcludeAlike", PasswordGenerator::DefaultLookAlike).toBool()); + m_ui->checkBoxEnsureEvery->setChecked( + config()->get("generator/EnsureEvery", PasswordGenerator::DefaultFromEveryGroup).toBool()); m_ui->spinBoxLength->setValue(config()->get("generator/Length", PasswordGenerator::DefaultLength).toInt()); // Diceware config - m_ui->spinBoxWordCount->setValue(config()->get("generator/WordCount", PassphraseGenerator::DefaultWordCount).toInt()); - m_ui->editWordSeparator->setText(config()->get("generator/WordSeparator", PassphraseGenerator::DefaultSeparator).toString()); - m_ui->comboBoxWordList->setCurrentText(config()->get("generator/WordList", PassphraseGenerator::DefaultWordList).toString()); + m_ui->spinBoxWordCount->setValue( + config()->get("generator/WordCount", PassphraseGenerator::DefaultWordCount).toInt()); + m_ui->editWordSeparator->setText( + config()->get("generator/WordSeparator", PassphraseGenerator::DefaultSeparator).toString()); + m_ui->comboBoxWordList->setCurrentText( + config()->get("generator/WordList", PassphraseGenerator::DefaultWordList).toString()); // Password or diceware? m_ui->tabWidget->setCurrentIndex(config()->get("generator/Type", 0).toInt()); @@ -275,8 +281,7 @@ void PasswordGeneratorWidget::colorStrengthIndicator(double entropy) // Take the existing stylesheet and convert the text and background color to arguments QString style = m_ui->entropyProgressBar->styleSheet(); QRegularExpression re("(QProgressBar::chunk\\s*\\{.*?background-color:)[^;]+;", - QRegularExpression::CaseInsensitiveOption | - QRegularExpression::DotMatchesEverythingOption); + QRegularExpression::CaseInsensitiveOption | QRegularExpression::DotMatchesEverythingOption); style.replace(re, "\\1 %1;"); // Set the color and background based on entropy diff --git a/src/gui/PasswordGeneratorWidget.h b/src/gui/PasswordGeneratorWidget.h index ed441437..84d5484b 100644 --- a/src/gui/PasswordGeneratorWidget.h +++ b/src/gui/PasswordGeneratorWidget.h @@ -19,14 +19,15 @@ #ifndef KEEPASSX_PASSWORDGENERATORWIDGET_H #define KEEPASSX_PASSWORDGENERATORWIDGET_H -#include #include #include +#include -#include "core/PasswordGenerator.h" #include "core/PassphraseGenerator.h" +#include "core/PasswordGenerator.h" -namespace Ui { +namespace Ui +{ class PasswordGeneratorWidget; } @@ -55,7 +56,7 @@ public slots: void regeneratePassword(); void applyPassword(); void copyPassword(); - + signals: void appliedPassword(const QString& password); void dialogTerminated(); diff --git a/src/gui/SearchWidget.cpp b/src/gui/SearchWidget.cpp index bf961ecb..c84ba858 100644 --- a/src/gui/SearchWidget.cpp +++ b/src/gui/SearchWidget.cpp @@ -172,7 +172,6 @@ void SearchWidget::setLimitGroup(bool state) updateLimitGroup(); } - void SearchWidget::searchFocus() { m_ui->searchEdit->setFocus(); diff --git a/src/gui/SearchWidget.h b/src/gui/SearchWidget.h index 2441ef60..1d95c664 100644 --- a/src/gui/SearchWidget.h +++ b/src/gui/SearchWidget.h @@ -25,7 +25,8 @@ #include "core/SignalMultiplexer.h" #include "gui/DatabaseWidget.h" -namespace Ui { +namespace Ui +{ class SearchWidget; } diff --git a/src/gui/SettingsWidget.cpp b/src/gui/SettingsWidget.cpp index 56b1b2a3..be2f4cd4 100644 --- a/src/gui/SettingsWidget.cpp +++ b/src/gui/SettingsWidget.cpp @@ -20,32 +20,35 @@ #include "ui_SettingsWidgetGeneral.h" #include "ui_SettingsWidgetSecurity.h" -#include "config-keepassx.h" #include "autotype/AutoType.h" +#include "config-keepassx.h" #include "core/Config.h" -#include "core/Translator.h" #include "core/FilePath.h" #include "core/Global.h" +#include "core/Translator.h" class SettingsWidget::ExtraPage { - public: - ExtraPage(ISettingsPage* page, QWidget* widget): settingsPage(page), widget(widget) - {} +public: + ExtraPage(ISettingsPage* page, QWidget* widget) + : settingsPage(page) + , widget(widget) + { + } - void loadSettings() const - { - settingsPage->loadSettings(widget); - } + void loadSettings() const + { + settingsPage->loadSettings(widget); + } - void saveSettings() const - { - settingsPage->saveSettings(widget); - } + void saveSettings() const + { + settingsPage->saveSettings(widget); + } - private: - QSharedPointer settingsPage; - QWidget* widget; +private: + QSharedPointer settingsPage; + QWidget* widget; }; SettingsWidget::SettingsWidget(QWidget* parent) @@ -72,15 +75,16 @@ SettingsWidget::SettingsWidget(QWidget* parent) connect(this, SIGNAL(apply()), SLOT(saveSettings())); connect(this, SIGNAL(rejected()), SLOT(reject())); - connect(m_generalUi->autoSaveAfterEveryChangeCheckBox, SIGNAL(toggled(bool)), - this, SLOT(enableAutoSaveOnExit(bool))); - connect(m_generalUi->systrayShowCheckBox, SIGNAL(toggled(bool)), - this, SLOT(enableSystray(bool))); + connect( + m_generalUi->autoSaveAfterEveryChangeCheckBox, SIGNAL(toggled(bool)), this, SLOT(enableAutoSaveOnExit(bool))); + connect(m_generalUi->systrayShowCheckBox, SIGNAL(toggled(bool)), this, SLOT(enableSystray(bool))); - connect(m_secUi->clearClipboardCheckBox, SIGNAL(toggled(bool)), - m_secUi->clearClipboardSpinBox, SLOT(setEnabled(bool))); - connect(m_secUi->lockDatabaseIdleCheckBox, SIGNAL(toggled(bool)), - m_secUi->lockDatabaseIdleSpinBox, SLOT(setEnabled(bool))); + connect( + m_secUi->clearClipboardCheckBox, SIGNAL(toggled(bool)), m_secUi->clearClipboardSpinBox, SLOT(setEnabled(bool))); + connect(m_secUi->lockDatabaseIdleCheckBox, + SIGNAL(toggled(bool)), + m_secUi->lockDatabaseIdleSpinBox, + SLOT(setEnabled(bool))); #ifndef WITH_XC_NETWORKING m_secUi->privacy->setVisible(false); @@ -103,8 +107,7 @@ void SettingsWidget::loadSettings() { if (config()->hasAccessError()) { - showMessage( - tr("Access error for config file %1").arg(config()->getFileName()), MessageWidget::Error); + showMessage(tr("Access error for config file %1").arg(config()->getFileName()), MessageWidget::Error); } #ifdef QT_DEBUG @@ -127,7 +130,7 @@ void SettingsWidget::loadSettings() m_generalUi->ignoreGroupExpansionCheckBox->setChecked(config()->get("IgnoreGroupExpansion").toBool()); m_generalUi->languageComboBox->clear(); - QList > languages = Translator::availableLanguages(); + QList> languages = Translator::availableLanguages(); for (int i = 0; i < languages.size(); i++) { m_generalUi->languageComboBox->addItem(languages[i].second, languages[i].first); } @@ -146,7 +149,8 @@ void SettingsWidget::loadSettings() if (autoType()->isAvailable()) { m_globalAutoTypeKey = static_cast(config()->get("GlobalAutoTypeKey").toInt()); - m_globalAutoTypeModifiers = static_cast(config()->get("GlobalAutoTypeModifiers").toInt()); + m_globalAutoTypeModifiers = + static_cast(config()->get("GlobalAutoTypeModifiers").toInt()); if (m_globalAutoTypeKey > 0 && m_globalAutoTypeModifiers > 0) { m_generalUi->autoTypeShortcutWidget->setShortcut(m_globalAutoTypeKey, m_globalAutoTypeModifiers); } @@ -154,7 +158,6 @@ void SettingsWidget::loadSettings() m_generalUi->autoTypeDelaySpinBox->setValue(config()->get("AutoTypeDelay").toInt()); } - m_secUi->clearClipboardCheckBox->setChecked(config()->get("security/clearclipboard").toBool()); m_secUi->clearClipboardSpinBox->setValue(config()->get("security/clearclipboardtimeout").toInt()); @@ -170,8 +173,7 @@ void SettingsWidget::loadSettings() m_secUi->passwordRepeatCheckBox->setChecked(config()->get("security/passwordsrepeat").toBool()); m_secUi->hideNotesCheckBox->setChecked(config()->get("security/hidenotes").toBool()); - - for (const ExtraPage& page: asConst(m_extraPages)) { + for (const ExtraPage& page : asConst(m_extraPages)) { page.loadSettings(); } @@ -182,8 +184,7 @@ void SettingsWidget::saveSettings() { if (config()->hasAccessError()) { - showMessage( - tr("Access error for config file %1").arg(config()->getFileName()), MessageWidget::Error); + showMessage(tr("Access error for config file %1").arg(config()->getFileName()), MessageWidget::Error); // We prevent closing the settings page if we could not write to // the config file. return; @@ -192,23 +193,17 @@ void SettingsWidget::saveSettings() config()->set("SingleInstance", m_generalUi->singleInstanceCheckBox->isChecked()); config()->set("RememberLastDatabases", m_generalUi->rememberLastDatabasesCheckBox->isChecked()); config()->set("RememberLastKeyFiles", m_generalUi->rememberLastKeyFilesCheckBox->isChecked()); - config()->set("OpenPreviousDatabasesOnStartup", - m_generalUi->openPreviousDatabasesOnStartupCheckBox->isChecked()); - config()->set("AutoSaveAfterEveryChange", - m_generalUi->autoSaveAfterEveryChangeCheckBox->isChecked()); + config()->set("OpenPreviousDatabasesOnStartup", m_generalUi->openPreviousDatabasesOnStartupCheckBox->isChecked()); + config()->set("AutoSaveAfterEveryChange", m_generalUi->autoSaveAfterEveryChangeCheckBox->isChecked()); config()->set("AutoSaveOnExit", m_generalUi->autoSaveOnExitCheckBox->isChecked()); config()->set("BackupBeforeSave", m_generalUi->backupBeforeSaveCheckBox->isChecked()); config()->set("UseAtomicSaves", m_generalUi->useAtomicSavesCheckBox->isChecked()); config()->set("AutoReloadOnChange", m_generalUi->autoReloadOnChangeCheckBox->isChecked()); config()->set("MinimizeOnCopy", m_generalUi->minimizeOnCopyCheckBox->isChecked()); - config()->set("UseGroupIconOnEntryCreation", - m_generalUi->useGroupIconOnEntryCreationCheckBox->isChecked()); - config()->set("IgnoreGroupExpansion", - m_generalUi->ignoreGroupExpansionCheckBox->isChecked()); - config()->set("AutoTypeEntryTitleMatch", - m_generalUi->autoTypeEntryTitleMatchCheckBox->isChecked()); - config()->set("AutoTypeEntryURLMatch", - m_generalUi->autoTypeEntryURLMatchCheckBox->isChecked()); + config()->set("UseGroupIconOnEntryCreation", m_generalUi->useGroupIconOnEntryCreationCheckBox->isChecked()); + config()->set("IgnoreGroupExpansion", m_generalUi->ignoreGroupExpansionCheckBox->isChecked()); + config()->set("AutoTypeEntryTitleMatch", m_generalUi->autoTypeEntryTitleMatchCheckBox->isChecked()); + config()->set("AutoTypeEntryURLMatch", m_generalUi->autoTypeEntryURLMatchCheckBox->isChecked()); int currentLangIndex = m_generalUi->languageComboBox->currentIndex(); config()->set("GUI/Language", m_generalUi->languageComboBox->itemData(currentLangIndex).toString()); @@ -224,8 +219,7 @@ void SettingsWidget::saveSettings() if (autoType()->isAvailable()) { config()->set("GlobalAutoTypeKey", m_generalUi->autoTypeShortcutWidget->key()); - config()->set("GlobalAutoTypeModifiers", - static_cast(m_generalUi->autoTypeShortcutWidget->modifiers())); + config()->set("GlobalAutoTypeModifiers", static_cast(m_generalUi->autoTypeShortcutWidget->modifiers())); config()->set("AutoTypeDelay", m_generalUi->autoTypeDelaySpinBox->value()); } config()->set("security/clearclipboard", m_secUi->clearClipboardCheckBox->isChecked()); @@ -253,7 +247,7 @@ void SettingsWidget::saveSettings() config()->set("LastDir", ""); } - for (const ExtraPage& page: asConst(m_extraPages)) { + for (const ExtraPage& page : asConst(m_extraPages)) { page.saveSettings(); } } @@ -264,7 +258,6 @@ void SettingsWidget::reject() if (m_globalAutoTypeKey > 0 && m_globalAutoTypeModifiers > 0) { autoType()->registerGlobalShortcut(m_globalAutoTypeKey, m_globalAutoTypeModifiers); } - } void SettingsWidget::enableAutoSaveOnExit(bool checked) diff --git a/src/gui/SettingsWidget.h b/src/gui/SettingsWidget.h index 27566037..d6a1a7e6 100644 --- a/src/gui/SettingsWidget.h +++ b/src/gui/SettingsWidget.h @@ -21,19 +21,23 @@ #include "gui/EditWidget.h" -namespace Ui { +namespace Ui +{ class SettingsWidgetGeneral; class SettingsWidgetSecurity; } -class ISettingsPage { +class ISettingsPage +{ public: - virtual ~ISettingsPage() {} + virtual ~ISettingsPage() + { + } virtual QString name() = 0; virtual QIcon icon() = 0; - virtual QWidget * createWidget() = 0; - virtual void loadSettings(QWidget * widget) = 0; - virtual void saveSettings(QWidget * widget) = 0; + virtual QWidget* createWidget() = 0; + virtual void loadSettings(QWidget* widget) = 0; + virtual void saveSettings(QWidget* widget) = 0; }; class SettingsWidget : public EditWidget @@ -43,7 +47,7 @@ class SettingsWidget : public EditWidget public: explicit SettingsWidget(QWidget* parent = nullptr); ~SettingsWidget(); - void addSettingsPage(ISettingsPage * page); + void addSettingsPage(ISettingsPage* page); void loadSettings(); private slots: diff --git a/src/gui/SetupTotpDialog.cpp b/src/gui/SetupTotpDialog.cpp index 52d63f0e..ef7ee9e7 100644 --- a/src/gui/SetupTotpDialog.cpp +++ b/src/gui/SetupTotpDialog.cpp @@ -17,9 +17,8 @@ */ #include "SetupTotpDialog.h" -#include "ui_SetupTotpDialog.h" #include "totp/totp.h" - +#include "ui_SetupTotpDialog.h" SetupTotpDialog::SetupTotpDialog(DatabaseWidget* parent, Entry* entry) : QDialog(parent) @@ -40,7 +39,6 @@ SetupTotpDialog::SetupTotpDialog(DatabaseWidget* parent, Entry* entry) connect(m_ui->radioCustom, SIGNAL(toggled(bool)), SLOT(toggleCustom(bool))); } - void SetupTotpDialog::setupTotp() { quint8 digits; @@ -86,17 +84,16 @@ void SetupTotpDialog::toggleCustom(bool status) m_ui->stepSpinBox->setEnabled(status); } - void SetupTotpDialog::setSeed(QString value) { m_ui->seedEdit->setText(value); } -void SetupTotpDialog::setSettings(quint8 digits) { +void SetupTotpDialog::setSettings(quint8 digits) +{ quint8 step = m_ui->stepSpinBox->value(); - bool isDefault = ((step == Totp::defaultStep) && - (digits == Totp::defaultDigits)); + bool isDefault = ((step == Totp::defaultStep) && (digits == Totp::defaultDigits)); bool isSteam = (digits == Totp::ENCODER_STEAM); if (isSteam) { diff --git a/src/gui/SetupTotpDialog.h b/src/gui/SetupTotpDialog.h index 9e90e968..7c34bb5f 100644 --- a/src/gui/SetupTotpDialog.h +++ b/src/gui/SetupTotpDialog.h @@ -19,13 +19,14 @@ #ifndef KEEPASSX_SETUPTOTPDIALOG_H #define KEEPASSX_SETUPTOTPDIALOG_H +#include "core/Database.h" +#include "core/Entry.h" +#include "gui/DatabaseWidget.h" #include #include -#include "core/Entry.h" -#include "core/Database.h" -#include "gui/DatabaseWidget.h" -namespace Ui { +namespace Ui +{ class SetupTotpDialog; } diff --git a/src/gui/TotpDialog.cpp b/src/gui/TotpDialog.cpp index 1529db0d..75cf6a48 100644 --- a/src/gui/TotpDialog.cpp +++ b/src/gui/TotpDialog.cpp @@ -22,7 +22,6 @@ #include "core/Config.h" #include "gui/Clipboard.h" - TotpDialog::TotpDialog(DatabaseWidget* parent, Entry* entry) : QDialog(parent) , m_ui(new Ui::TotpDialog()) @@ -68,7 +67,6 @@ void TotpDialog::updateProgressBar() } } - void TotpDialog::updateSeconds() { uint epoch = QDateTime::currentDateTime().toTime_t() - 1; diff --git a/src/gui/TotpDialog.h b/src/gui/TotpDialog.h index ce21a66f..e002cb82 100644 --- a/src/gui/TotpDialog.h +++ b/src/gui/TotpDialog.h @@ -19,15 +19,16 @@ #ifndef KEEPASSX_TOTPDIALOG_H #define KEEPASSX_TOTPDIALOG_H +#include "core/Database.h" +#include "core/Entry.h" +#include "gui/DatabaseWidget.h" #include #include #include #include -#include "core/Entry.h" -#include "core/Database.h" -#include "gui/DatabaseWidget.h" -namespace Ui { +namespace Ui +{ class TotpDialog; } diff --git a/src/gui/UnlockDatabaseDialog.cpp b/src/gui/UnlockDatabaseDialog.cpp index cea5918a..3d900f52 100644 --- a/src/gui/UnlockDatabaseDialog.cpp +++ b/src/gui/UnlockDatabaseDialog.cpp @@ -30,7 +30,7 @@ UnlockDatabaseDialog::UnlockDatabaseDialog(QWidget* parent) connect(m_view, SIGNAL(editFinished(bool)), this, SLOT(complete(bool))); } -void UnlockDatabaseDialog::setFilePath(const QString &filePath) +void UnlockDatabaseDialog::setFilePath(const QString& filePath) { m_view->load(filePath); } diff --git a/src/gui/UnlockDatabaseDialog.h b/src/gui/UnlockDatabaseDialog.h index 7dec0676..95d6ce23 100644 --- a/src/gui/UnlockDatabaseDialog.h +++ b/src/gui/UnlockDatabaseDialog.h @@ -32,7 +32,7 @@ class UnlockDatabaseDialog : public QDialog Q_OBJECT public: explicit UnlockDatabaseDialog(QWidget* parent = nullptr); - void setFilePath(const QString &filePath); + void setFilePath(const QString& filePath); void clearForms(); Database* database(); diff --git a/src/gui/UnlockDatabaseWidget.cpp b/src/gui/UnlockDatabaseWidget.cpp index a777d493..ffd2bf22 100644 --- a/src/gui/UnlockDatabaseWidget.cpp +++ b/src/gui/UnlockDatabaseWidget.cpp @@ -17,9 +17,9 @@ #include "UnlockDatabaseWidget.h" -#include "ui_DatabaseOpenWidget.h" #include "core/Database.h" #include "gui/MessageBox.h" +#include "ui_DatabaseOpenWidget.h" UnlockDatabaseWidget::UnlockDatabaseWidget(QWidget* parent) : DatabaseOpenWidget(parent) diff --git a/src/gui/WelcomeWidget.cpp b/src/gui/WelcomeWidget.cpp index ed9d025a..7bb4484c 100644 --- a/src/gui/WelcomeWidget.cpp +++ b/src/gui/WelcomeWidget.cpp @@ -20,8 +20,8 @@ #include "ui_WelcomeWidget.h" #include "config-keepassx.h" -#include "core/FilePath.h" #include "core/Config.h" +#include "core/FilePath.h" WelcomeWidget::WelcomeWidget(QWidget* parent) : QWidget(parent) @@ -48,8 +48,10 @@ WelcomeWidget::WelcomeWidget(QWidget* parent) connect(m_ui->buttonOpenDatabase, SIGNAL(clicked()), SIGNAL(openDatabase())); connect(m_ui->buttonImportKeePass1, SIGNAL(clicked()), SIGNAL(importKeePass1Database())); connect(m_ui->buttonImportCSV, SIGNAL(clicked()), SIGNAL(importCsv())); - connect(m_ui->recentListWidget, SIGNAL(itemActivated(QListWidgetItem*)), this, - SLOT(openDatabaseFromFile(QListWidgetItem*))); + connect(m_ui->recentListWidget, + SIGNAL(itemActivated(QListWidgetItem*)), + this, + SLOT(openDatabaseFromFile(QListWidgetItem*))); } WelcomeWidget::~WelcomeWidget() @@ -58,10 +60,10 @@ WelcomeWidget::~WelcomeWidget() void WelcomeWidget::openDatabaseFromFile(QListWidgetItem* item) { - if (item->text().isEmpty()) { - return; - } - emit openDatabaseFile(item->text()); + if (item->text().isEmpty()) { + return; + } + emit openDatabaseFile(item->text()); } void WelcomeWidget::refreshLastDatabases() @@ -69,7 +71,7 @@ void WelcomeWidget::refreshLastDatabases() m_ui->recentListWidget->clear(); const QStringList lastDatabases = config()->get("LastDatabases", QVariant()).toStringList(); for (const QString& database : lastDatabases) { - QListWidgetItem *itm = new QListWidgetItem; + QListWidgetItem* itm = new QListWidgetItem; itm->setText(database); m_ui->recentListWidget->addItem(itm); } diff --git a/src/gui/WelcomeWidget.h b/src/gui/WelcomeWidget.h index 71ceda35..1b248343 100644 --- a/src/gui/WelcomeWidget.h +++ b/src/gui/WelcomeWidget.h @@ -19,10 +19,11 @@ #ifndef KEEPASSX_WELCOMEWIDGET_H #define KEEPASSX_WELCOMEWIDGET_H -#include #include +#include -namespace Ui { +namespace Ui +{ class WelcomeWidget; } diff --git a/src/gui/csvImport/CsvImportWidget.cpp b/src/gui/csvImport/CsvImportWidget.cpp index c2c2aa03..f90f4636 100644 --- a/src/gui/csvImport/CsvImportWidget.cpp +++ b/src/gui/csvImport/CsvImportWidget.cpp @@ -27,24 +27,19 @@ #include "gui/MessageBox.h" #include "gui/MessageWidget.h" -//I wanted to make the CSV import GUI future-proof, so if one day you need entries -//to have a new field, all you have to do is uncomment a row or two here, and the GUI will follow: -//dynamic generation of comboBoxes, labels, placement and so on. Try it for immense fun! -const QStringList CsvImportWidget::m_columnHeader = QStringList() - << QObject::tr("Group") - << QObject::tr("Title") - << QObject::tr("Username") - << QObject::tr("Password") - << QObject::tr("URL") - << QObject::tr("Notes") - << QObject::tr("Last Modified") - << QObject::tr("Created") -// << QObject::tr("Future field1") -// << QObject::tr("Future field2") -// << QObject::tr("Future field3") +// I wanted to make the CSV import GUI future-proof, so if one day you need entries +// to have a new field, all you have to do is uncomment a row or two here, and the GUI will follow: +// dynamic generation of comboBoxes, labels, placement and so on. Try it for immense fun! +const QStringList CsvImportWidget::m_columnHeader = + QStringList() << QObject::tr("Group") << QObject::tr("Title") << QObject::tr("Username") << QObject::tr("Password") + << QObject::tr("URL") << QObject::tr("Notes") << QObject::tr("Last Modified") + << QObject::tr("Created") + // << QObject::tr("Future field1") + // << QObject::tr("Future field2") + // << QObject::tr("Future field3") ; -CsvImportWidget::CsvImportWidget(QWidget *parent) +CsvImportWidget::CsvImportWidget(QWidget* parent) : QWidget(parent) , m_ui(new Ui::CsvImportWidget()) , m_parserModel(new CsvParserModel(this)) @@ -53,10 +48,24 @@ CsvImportWidget::CsvImportWidget(QWidget *parent) { m_ui->setupUi(this); - m_ui->comboBoxCodec->addItems(QStringList() <<"UTF-8" <<"Windows-1252" <<"UTF-16" <<"UTF-16LE"); - m_ui->comboBoxFieldSeparator->addItems(QStringList() <<"," <<";" <<"-" <<":" <<"."); - m_ui->comboBoxTextQualifier->addItems(QStringList() <<"\"" <<"'" <<":" <<"." <<"|"); - m_ui->comboBoxComment->addItems(QStringList() <<"#" <<";" <<":" <<"@"); + m_ui->comboBoxCodec->addItems(QStringList() << "UTF-8" + << "Windows-1252" + << "UTF-16" + << "UTF-16LE"); + m_ui->comboBoxFieldSeparator->addItems(QStringList() << "," + << ";" + << "-" + << ":" + << "."); + m_ui->comboBoxTextQualifier->addItems(QStringList() << "\"" + << "'" + << ":" + << "." + << "|"); + m_ui->comboBoxComment->addItems(QStringList() << "#" + << ";" + << ":" + << "@"); m_ui->tableViewFields->setSelectionMode(QAbstractItemView::NoSelection); m_ui->tableViewFields->setFocusPolicy(Qt::NoFocus); m_ui->messageWidget->setHidden(true); @@ -77,14 +86,14 @@ CsvImportWidget::CsvImportWidget(QWidget *parent) m_comboMapper->setMapping(combo, i); connect(combo, SIGNAL(currentIndexChanged(int)), m_comboMapper, SLOT(map())); - //layout labels and combo fields in column-first order + // layout labels and combo fields in column-first order int combo_rows = 1 + (m_columnHeader.count() - 1) / 2; int x = i % combo_rows; int y = 2 * (i / combo_rows); m_ui->gridLayout_combos->addWidget(label, x, y); - m_ui->gridLayout_combos->addWidget(combo, x, y+1); - QSpacerItem *item = new QSpacerItem(1,1, QSizePolicy::Expanding, QSizePolicy::Fixed); - m_ui->gridLayout_combos->addItem(item, x, y+2); + m_ui->gridLayout_combos->addWidget(combo, x, y + 1); + QSpacerItem* item = new QSpacerItem(1, 1, QSizePolicy::Expanding, QSizePolicy::Fixed); + m_ui->gridLayout_combos->addItem(item, x, y + 2); } m_parserModel->setHeaderLabels(m_columnHeader); @@ -103,22 +112,27 @@ CsvImportWidget::CsvImportWidget(QWidget *parent) connect(m_ui->buttonBox, SIGNAL(rejected()), this, SLOT(reject())); } -void CsvImportWidget::comboChanged(int comboId) { +void CsvImportWidget::comboChanged(int comboId) +{ QComboBox* currentSender = qobject_cast(m_comboMapper->mapping(comboId)); if (currentSender->currentIndex() != -1) - //this line is the one that actually updates GUI table + // this line is the one that actually updates GUI table m_parserModel->mapColumns(currentSender->currentIndex(), comboId); updateTableview(); } -void CsvImportWidget::skippedChanged(int rows) { +void CsvImportWidget::skippedChanged(int rows) +{ m_parserModel->setSkippedRows(rows); updateTableview(); } -CsvImportWidget::~CsvImportWidget() {} +CsvImportWidget::~CsvImportWidget() +{ +} -void CsvImportWidget::configParser() { +void CsvImportWidget::configParser() +{ m_parserModel->setBackslashSyntax(m_ui->checkBoxBackslash->isChecked()); m_parserModel->setComment(m_ui->comboBoxComment->currentText().at(0)); m_parserModel->setTextQualifier(m_ui->comboBoxTextQualifier->currentText().at(0)); @@ -126,7 +140,8 @@ void CsvImportWidget::configParser() { m_parserModel->setFieldSeparator(m_ui->comboBoxFieldSeparator->currentText().at(0)); } -void CsvImportWidget::updateTableview() { +void CsvImportWidget::updateTableview() +{ m_ui->tableViewFields->resizeRowsToContents(); m_ui->tableViewFields->resizeColumnsToContents(); @@ -134,7 +149,8 @@ void CsvImportWidget::updateTableview() { m_ui->tableViewFields->horizontalHeader()->setSectionResizeMode(c, QHeaderView::Stretch); } -void CsvImportWidget::updatePreview() { +void CsvImportWidget::updatePreview() +{ int minSkip = 0; if (m_ui->checkBoxFieldNames->isChecked()) @@ -159,7 +175,7 @@ void CsvImportWidget::updatePreview() { } m_comboModel->setStringList(list); - int j=1; + int j = 1; for (QComboBox* b : m_combos) { if (j < m_parserModel->getCsvCols()) b->setCurrentIndex(j); @@ -169,8 +185,9 @@ void CsvImportWidget::updatePreview() { } } -void CsvImportWidget::load(const QString& filename, Database* const db) { - //QApplication::processEvents(); +void CsvImportWidget::load(const QString& filename, Database* const db) +{ + // QApplication::processEvents(); m_db = db; m_parserModel->setFilename(filename); m_ui->labelFilename->setText(filename); @@ -180,29 +197,28 @@ void CsvImportWidget::load(const QString& filename, Database* const db) { parse(); } -void CsvImportWidget::parse() { +void CsvImportWidget::parse() +{ configParser(); QApplication::setOverrideCursor(Qt::WaitCursor); - //QApplication::processEvents(); + // QApplication::processEvents(); bool good = m_parserModel->parse(); updatePreview(); QApplication::restoreOverrideCursor(); if (!good) - m_ui->messageWidget->showMessage(tr("Error(s) detected in CSV file!").append("\n") - .append(formatStatusText()), MessageWidget::Warning); + m_ui->messageWidget->showMessage(tr("Error(s) detected in CSV file!").append("\n").append(formatStatusText()), + MessageWidget::Warning); else m_ui->messageWidget->setHidden(true); QWidget::adjustSize(); } - -QString CsvImportWidget::formatStatusText() const { +QString CsvImportWidget::formatStatusText() const +{ QString text = m_parserModel->getStatus(); int items = text.count('\n'); if (items > 2) { - return text.section('\n', 0, 1) - .append("\n") - .append(tr("[%n more message(s) skipped]", "", items - 2)); + return text.section('\n', 0, 1).append("\n").append(tr("[%n more message(s) skipped]", "", items - 2)); } if (items == 1) { text.append(QString("\n")); @@ -210,11 +226,12 @@ QString CsvImportWidget::formatStatusText() const { return text; } -void CsvImportWidget::writeDatabase() { +void CsvImportWidget::writeDatabase() +{ setRootGroup(); for (int r = 0; r < m_parserModel->rowCount(); ++r) { - //use validity of second column as a GO/NOGO for all others fields + // use validity of second column as a GO/NOGO for all others fields if (not m_parserModel->data(m_parserModel->index(r, 1)).isValid()) continue; Entry* entry = new Entry(); @@ -230,7 +247,8 @@ void CsvImportWidget::writeDatabase() { if (m_parserModel->data(m_parserModel->index(r, 6)).isValid()) { qint64 lastModified = m_parserModel->data(m_parserModel->index(r, 6)).toString().toLongLong(); if (lastModified) { - timeInfo.setLastModificationTime(QDateTime::fromMSecsSinceEpoch(lastModified * 1000).toTimeSpec(Qt::UTC)); + timeInfo.setLastModificationTime( + QDateTime::fromMSecsSinceEpoch(lastModified * 1000).toTimeSpec(Qt::UTC)); } } if (m_parserModel->data(m_parserModel->index(r, 7)).isValid()) { @@ -247,35 +265,37 @@ void CsvImportWidget::writeDatabase() { KeePass2Writer writer; writer.writeDatabase(&buffer, m_db); if (writer.hasError()) - MessageBox::warning(this, tr("Error"), tr("CSV import: writer has errors:\n%1") - .arg(writer.errorString()), QMessageBox::Ok, QMessageBox::Ok); + MessageBox::warning(this, + tr("Error"), + tr("CSV import: writer has errors:\n%1").arg(writer.errorString()), + QMessageBox::Ok, + QMessageBox::Ok); emit editFinished(true); } - -void CsvImportWidget::setRootGroup() { +void CsvImportWidget::setRootGroup() +{ QString groupLabel; QStringList groupList; - bool is_root = false; + bool is_root = false; bool is_empty = false; bool is_label = false; for (int r = 0; r < m_parserModel->rowCount(); ++r) { - //use validity of second column as a GO/NOGO for all others fields + // use validity of second column as a GO/NOGO for all others fields if (not m_parserModel->data(m_parserModel->index(r, 1)).isValid()) continue; groupLabel = m_parserModel->data(m_parserModel->index(r, 0)).toString(); - //check if group name is either "root", "" (empty) or some other label + // check if group name is either "root", "" (empty) or some other label groupList = groupLabel.split("/", QString::SkipEmptyParts); if (groupList.isEmpty()) is_empty = true; + else if (not groupList.first().compare("Root", Qt::CaseSensitive)) + is_root = true; + else if (not groupLabel.compare("")) + is_empty = true; else - if (not groupList.first().compare("Root", Qt::CaseSensitive)) - is_root = true; - else if (not groupLabel.compare("")) - is_empty = true; - else - is_label = true; + is_label = true; groupList.clear(); } @@ -286,21 +306,22 @@ void CsvImportWidget::setRootGroup() { m_db->rootGroup()->setName("Root"); } -Group *CsvImportWidget::splitGroups(QString label) { - //extract group names from nested path provided in "label" - Group *current = m_db->rootGroup(); +Group* CsvImportWidget::splitGroups(QString label) +{ + // extract group names from nested path provided in "label" + Group* current = m_db->rootGroup(); if (label.isEmpty()) return current; QStringList groupList = label.split("/", QString::SkipEmptyParts); - //avoid the creation of a subgroup with the same name as Root + // avoid the creation of a subgroup with the same name as Root if (m_db->rootGroup()->name() == "Root" && groupList.first() == "Root") groupList.removeFirst(); for (const QString& groupName : groupList) { - Group *children = hasChildren(current, groupName); + Group* children = hasChildren(current, groupName); if (children == nullptr) { - Group *brandNew = new Group(); + Group* brandNew = new Group(); brandNew->setParent(current); brandNew->setName(groupName); brandNew->setUuid(Uuid::random()); @@ -313,15 +334,17 @@ Group *CsvImportWidget::splitGroups(QString label) { return current; } -Group* CsvImportWidget::hasChildren(Group* current, QString groupName) { - //returns the group whose name is "groupName" and is child of "current" group - for (Group * group : current->children()) { +Group* CsvImportWidget::hasChildren(Group* current, QString groupName) +{ + // returns the group whose name is "groupName" and is child of "current" group + for (Group* group : current->children()) { if (group->name() == groupName) return group; } return nullptr; } -void CsvImportWidget::reject() { +void CsvImportWidget::reject() +{ emit editFinished(false); } diff --git a/src/gui/csvImport/CsvImportWidget.h b/src/gui/csvImport/CsvImportWidget.h index 463a92c5..3823fcb2 100644 --- a/src/gui/csvImport/CsvImportWidget.h +++ b/src/gui/csvImport/CsvImportWidget.h @@ -19,20 +19,20 @@ #ifndef KEEPASSX_CSVIMPORTWIDGET_H #define KEEPASSX_CSVIMPORTWIDGET_H -#include -#include -#include -#include -#include #include +#include +#include +#include +#include #include +#include #include "core/Metadata.h" #include "gui/csvImport/CsvParserModel.h" #include "keys/PasswordKey.h" - -namespace Ui { +namespace Ui +{ class CsvImportWidget; } diff --git a/src/gui/csvImport/CsvImportWizard.cpp b/src/gui/csvImport/CsvImportWizard.cpp index e9a8f498..d1d15215 100644 --- a/src/gui/csvImport/CsvImportWizard.cpp +++ b/src/gui/csvImport/CsvImportWizard.cpp @@ -23,8 +23,7 @@ #include "gui/MessageBox.h" - -CsvImportWizard::CsvImportWizard(QWidget *parent) +CsvImportWizard::CsvImportWizard(QWidget* parent) : DialogyWidget(parent) { m_layout = new QGridLayout(this); @@ -34,7 +33,8 @@ CsvImportWizard::CsvImportWizard(QWidget *parent) } CsvImportWizard::~CsvImportWizard() -{} +{ +} void CsvImportWizard::load(const QString& filename, Database* database) { diff --git a/src/gui/csvImport/CsvImportWizard.h b/src/gui/csvImport/CsvImportWizard.h index b6414c0c..9c11e9d1 100644 --- a/src/gui/csvImport/CsvImportWizard.h +++ b/src/gui/csvImport/CsvImportWizard.h @@ -21,8 +21,8 @@ #include "CsvImportWidget.h" -#include #include +#include #include "core/Database.h" #include "gui/ChangeMasterKeyWidget.h" @@ -35,9 +35,9 @@ class CsvImportWizard : public DialogyWidget Q_OBJECT public: - explicit CsvImportWizard(QWidget *parent = nullptr); + explicit CsvImportWizard(QWidget* parent = nullptr); ~CsvImportWizard(); - void load(const QString& filename, Database *database); + void load(const QString& filename, Database* database); void keyFinished(bool accepted, CompositeKey key); signals: @@ -49,7 +49,7 @@ private slots: private: Database* m_db; CsvImportWidget* m_parse; - QGridLayout *m_layout; + QGridLayout* m_layout; }; -#endif //KEEPASSX_CSVIMPORTWIZARD_H +#endif // KEEPASSX_CSVIMPORTWIZARD_H diff --git a/src/gui/csvImport/CsvParserModel.cpp b/src/gui/csvImport/CsvParserModel.cpp index eb2793f8..e69ea185 100644 --- a/src/gui/csvImport/CsvParserModel.cpp +++ b/src/gui/csvImport/CsvParserModel.cpp @@ -18,27 +18,32 @@ #include "CsvParserModel.h" -CsvParserModel::CsvParserModel(QObject *parent) +CsvParserModel::CsvParserModel(QObject* parent) : QAbstractTableModel(parent) , m_skipped(0) -{} +{ +} CsvParserModel::~CsvParserModel() -{} +{ +} -void CsvParserModel::setFilename(const QString& filename) { +void CsvParserModel::setFilename(const QString& filename) +{ m_filename = filename; } -QString CsvParserModel::getFileInfo(){ +QString CsvParserModel::getFileInfo() +{ QString a(tr("%1, %2, %3", "file info: bytes, rows, columns") - .arg(tr("%n byte(s)", nullptr, getFileSize())) - .arg(tr("%n row(s)", nullptr, getCsvRows())) - .arg(tr("%n column(s)", nullptr, qMax(0, getCsvCols() - 1)))); + .arg(tr("%n byte(s)", nullptr, getFileSize())) + .arg(tr("%n row(s)", nullptr, getCsvRows())) + .arg(tr("%n column(s)", nullptr, qMax(0, getCsvCols() - 1)))); return a; } -bool CsvParserModel::parse() { +bool CsvParserModel::parse() +{ bool r; beginResetModel(); m_columnMap.clear(); @@ -49,13 +54,14 @@ bool CsvParserModel::parse() { r = CsvParser::parse(&csv); } for (int i = 0; i < columnCount(); ++i) - m_columnMap.insert(i,0); + m_columnMap.insert(i, 0); addEmptyColumn(); endResetModel(); return r; } -void CsvParserModel::addEmptyColumn() { +void CsvParserModel::addEmptyColumn() +{ for (int i = 0; i < m_table.size(); ++i) { CsvRow r = m_table.at(i); r.prepend(QString("")); @@ -63,65 +69,68 @@ void CsvParserModel::addEmptyColumn() { } } -void CsvParserModel::mapColumns(int csvColumn, int dbColumn) { +void CsvParserModel::mapColumns(int csvColumn, int dbColumn) +{ if ((csvColumn < 0) || (dbColumn < 0)) return; beginResetModel(); if (csvColumn >= getCsvCols()) - m_columnMap[dbColumn] = 0; //map to the empty column + m_columnMap[dbColumn] = 0; // map to the empty column else m_columnMap[dbColumn] = csvColumn; endResetModel(); } -void CsvParserModel::setSkippedRows(int skipped) { +void CsvParserModel::setSkippedRows(int skipped) +{ m_skipped = skipped; - QModelIndex topLeft = createIndex(skipped,0); - QModelIndex bottomRight = createIndex(m_skipped+rowCount(), columnCount()); + QModelIndex topLeft = createIndex(skipped, 0); + QModelIndex bottomRight = createIndex(m_skipped + rowCount(), columnCount()); emit dataChanged(topLeft, bottomRight); emit layoutChanged(); } -void CsvParserModel::setHeaderLabels(QStringList l) { +void CsvParserModel::setHeaderLabels(QStringList l) +{ m_columnHeader = l; } -int CsvParserModel::rowCount(const QModelIndex &parent) const { +int CsvParserModel::rowCount(const QModelIndex& parent) const +{ if (parent.isValid()) return 0; return getCsvRows(); } -int CsvParserModel::columnCount(const QModelIndex &parent) const { +int CsvParserModel::columnCount(const QModelIndex& parent) const +{ if (parent.isValid()) return 0; return m_columnHeader.size(); } -QVariant CsvParserModel::data(const QModelIndex &index, int role) const { - if ((index.column() >= m_columnHeader.size()) - || (index.row()+m_skipped >= rowCount()) - || !index.isValid()) { +QVariant CsvParserModel::data(const QModelIndex& index, int role) const +{ + if ((index.column() >= m_columnHeader.size()) || (index.row() + m_skipped >= rowCount()) || !index.isValid()) { return QVariant(); } if (role == Qt::DisplayRole) - return m_table.at(index.row()+m_skipped).at(m_columnMap[index.column()]); + return m_table.at(index.row() + m_skipped).at(m_columnMap[index.column()]); return QVariant(); } -QVariant CsvParserModel::headerData(int section, Qt::Orientation orientation, int role) const { +QVariant CsvParserModel::headerData(int section, Qt::Orientation orientation, int role) const +{ if (role == Qt::DisplayRole) { if (orientation == Qt::Horizontal) { if ((section < 0) || (section >= m_columnHeader.size())) return QVariant(); return m_columnHeader.at(section); } else if (orientation == Qt::Vertical) { - if (section+m_skipped >= rowCount()) + if (section + m_skipped >= rowCount()) return QVariant(); - return QString::number(section+1); + return QString::number(section + 1); } } return QVariant(); } - - diff --git a/src/gui/csvImport/CsvParserModel.h b/src/gui/csvImport/CsvParserModel.h index b092092b..7a13b0d1 100644 --- a/src/gui/csvImport/CsvParserModel.h +++ b/src/gui/csvImport/CsvParserModel.h @@ -30,7 +30,7 @@ class CsvParserModel : public QAbstractTableModel, public CsvParser Q_OBJECT public: - explicit CsvParserModel(QObject *parent = nullptr); + explicit CsvParserModel(QObject* parent = nullptr); ~CsvParserModel(); void setFilename(const QString& filename); QString getFileInfo(); @@ -39,9 +39,9 @@ public: void setHeaderLabels(QStringList l); void mapColumns(int csvColumn, int dbColumn); - int rowCount(const QModelIndex &parent = QModelIndex()) const override; - int columnCount(const QModelIndex &parent = QModelIndex()) const override; - QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + int rowCount(const QModelIndex& parent = QModelIndex()) const override; + int columnCount(const QModelIndex& parent = QModelIndex()) const override; + QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; QVariant headerData(int section, Qt::Orientation orientation, int role) const override; public slots: @@ -51,11 +51,10 @@ private: int m_skipped; QString m_filename; QStringList m_columnHeader; - //first column of model must be empty (aka combobox row "Not present in CSV file") + // first column of model must be empty (aka combobox row "Not present in CSV file") void addEmptyColumn(); - //mapping CSV columns to keepassx columns + // mapping CSV columns to keepassx columns QMap m_columnMap; }; -#endif //KEEPASSX_CSVPARSERMODEL_H - +#endif // KEEPASSX_CSVPARSERMODEL_H diff --git a/src/gui/entry/AutoTypeAssociationsModel.cpp b/src/gui/entry/AutoTypeAssociationsModel.cpp index 442453de..59d2c84f 100644 --- a/src/gui/entry/AutoTypeAssociationsModel.cpp +++ b/src/gui/entry/AutoTypeAssociationsModel.cpp @@ -49,7 +49,7 @@ void AutoTypeAssociationsModel::setAutoTypeAssociations(AutoTypeAssociations* au endResetModel(); } -void AutoTypeAssociationsModel::setEntry(const Entry *entry) +void AutoTypeAssociationsModel::setEntry(const Entry* entry) { m_entry = entry; } @@ -58,8 +58,7 @@ int AutoTypeAssociationsModel::rowCount(const QModelIndex& parent) const { if (!m_autoTypeAssociations || parent.isValid()) { return 0; - } - else { + } else { return m_autoTypeAssociations->size(); } } @@ -76,12 +75,10 @@ QVariant AutoTypeAssociationsModel::headerData(int section, Qt::Orientation orie if ((orientation == Qt::Horizontal) && (role == Qt::DisplayRole)) { if (section == 0) { return tr("Window"); - } - else { + } else { return tr("Sequence"); } - } - else { + } else { return QVariant(); } } @@ -100,16 +97,14 @@ QVariant AutoTypeAssociationsModel::data(const QModelIndex& index, int role) con window = m_entry->resolveMultiplePlaceholders(window); } return window; - } - else { + } else { QString sequence = m_autoTypeAssociations->get(index.row()).sequence; if (sequence.isEmpty()) { sequence = tr("Default sequence"); } return sequence; } - } - else { + } else { return QVariant(); } } diff --git a/src/gui/entry/AutoTypeMatchModel.cpp b/src/gui/entry/AutoTypeMatchModel.cpp index 6a370dea..1a6a6ba3 100644 --- a/src/gui/entry/AutoTypeMatchModel.cpp +++ b/src/gui/entry/AutoTypeMatchModel.cpp @@ -163,12 +163,11 @@ void AutoTypeMatchModel::entryDataChanged(Entry* entry) for (int row = 0; row < m_matches.size(); ++row) { AutoTypeMatch match = m_matches[row]; if (match.entry == entry) { - emit dataChanged(index(row, 0), index(row, columnCount()-1)); + emit dataChanged(index(row, 0), index(row, columnCount() - 1)); } } } - void AutoTypeMatchModel::entryAboutToRemove(Entry* entry) { for (int row = 0; row < m_matches.size(); ++row) { diff --git a/src/gui/entry/AutoTypeMatchView.cpp b/src/gui/entry/AutoTypeMatchView.cpp index 67f38c79..a0667b31 100644 --- a/src/gui/entry/AutoTypeMatchView.cpp +++ b/src/gui/entry/AutoTypeMatchView.cpp @@ -43,7 +43,8 @@ AutoTypeMatchView::AutoTypeMatchView(QWidget* parent) header()->setDefaultSectionSize(150); connect(this, SIGNAL(doubleClicked(QModelIndex)), SLOT(emitMatchActivated(QModelIndex))); - connect(selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), SIGNAL(matchSelectionChanged())); + connect( + selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)), SIGNAL(matchSelectionChanged())); } void AutoTypeMatchView::keyPressEvent(QKeyEvent* event) diff --git a/src/gui/entry/EditEntryWidget.cpp b/src/gui/entry/EditEntryWidget.cpp index 8163a648..eee4ec2a 100644 --- a/src/gui/entry/EditEntryWidget.cpp +++ b/src/gui/entry/EditEntryWidget.cpp @@ -19,19 +19,19 @@ #include "EditEntryWidget.h" #include "ui_EditEntryWidgetAdvanced.h" #include "ui_EditEntryWidgetAutoType.h" -#include "ui_EditEntryWidgetSSHAgent.h" #include "ui_EditEntryWidgetHistory.h" #include "ui_EditEntryWidgetMain.h" +#include "ui_EditEntryWidgetSSHAgent.h" +#include #include +#include +#include +#include +#include #include #include -#include -#include #include -#include -#include -#include #include "autotype/AutoType.h" #include "core/Config.h" @@ -46,12 +46,12 @@ #include "sshagent/OpenSSHKey.h" #include "sshagent/SSHAgent.h" #endif +#include "gui/Clipboard.h" #include "gui/EditWidgetIcons.h" #include "gui/EditWidgetProperties.h" #include "gui/FileDialog.h" -#include "gui/MessageBox.h" -#include "gui/Clipboard.h" #include "gui/Font.h" +#include "gui/MessageBox.h" #include "gui/entry/AutoTypeAssociationsModel.h" #include "gui/entry/EntryAttachmentsModel.h" #include "gui/entry/EntryAttributesModel.h" @@ -100,9 +100,11 @@ EditEntryWidget::EditEntryWidget(QWidget* parent) connect(this, SIGNAL(accepted()), SLOT(acceptEntry())); connect(this, SIGNAL(rejected()), SLOT(cancel())); connect(this, SIGNAL(apply()), SLOT(commitEntry())); - connect(m_iconsWidget, SIGNAL(messageEditEntry(QString, MessageWidget::MessageType)), SLOT(showMessage(QString, MessageWidget::MessageType))); + connect(m_iconsWidget, + SIGNAL(messageEditEntry(QString, MessageWidget::MessageType)), + SLOT(showMessage(QString, MessageWidget::MessageType))); connect(m_iconsWidget, SIGNAL(messageEditEntryDismiss()), SLOT(hideMessage())); - + m_mainUi->passwordGenerator->layout()->setContentsMargins(0, 0, 0, 0); } @@ -127,7 +129,7 @@ void EditEntryWidget::setupMain() m_mainUi->expirePresets->setMenu(createPresetsMenu()); connect(m_mainUi->expirePresets->menu(), SIGNAL(triggered(QAction*)), this, SLOT(useExpiryPreset(QAction*))); - QAction *action = new QAction(this); + QAction* action = new QAction(this); action->setShortcut(Qt::CTRL | Qt::Key_Return); connect(action, SIGNAL(triggered()), this, SLOT(commitEntry())); this->addAction(action); @@ -144,9 +146,10 @@ void EditEntryWidget::setupAdvanced() m_advancedUi->attachmentsWidget->setReadOnly(false); m_advancedUi->attachmentsWidget->setButtonsVisible(true); - connect(m_advancedUi->attachmentsWidget, &EntryAttachmentsWidget::errorOccurred, this, [this](const QString &error) { - showMessage(error, MessageWidget::Error); - }); + connect(m_advancedUi->attachmentsWidget, + &EntryAttachmentsWidget::errorOccurred, + this, + [this](const QString& error) { showMessage(error, MessageWidget::Error); }); m_attributesModel->setEntryAttributes(m_entryAttributes); m_advancedUi->attributesView->setModel(m_attributesModel); @@ -156,7 +159,7 @@ void EditEntryWidget::setupAdvanced() connect(m_advancedUi->protectAttributeButton, SIGNAL(toggled(bool)), SLOT(protectCurrentAttribute(bool))); connect(m_advancedUi->revealAttributeButton, SIGNAL(clicked(bool)), SLOT(revealCurrentAttribute())); connect(m_advancedUi->attributesView->selectionModel(), - SIGNAL(currentChanged(QModelIndex,QModelIndex)), + SIGNAL(currentChanged(QModelIndex, QModelIndex)), SLOT(updateCurrentAttribute())); connect(m_advancedUi->fgColorButton, SIGNAL(clicked()), SLOT(pickColor())); connect(m_advancedUi->bgColorButton, SIGNAL(clicked()), SLOT(pickColor())); @@ -178,24 +181,25 @@ void EditEntryWidget::setupAutoType() m_autoTypeUi->assocView->setModel(m_autoTypeAssocModel); m_autoTypeUi->assocView->setColumnHidden(1, true); connect(m_autoTypeUi->enableButton, SIGNAL(toggled(bool)), SLOT(updateAutoTypeEnabled())); - connect(m_autoTypeUi->customSequenceButton, SIGNAL(toggled(bool)), - m_autoTypeUi->sequenceEdit, SLOT(setEnabled(bool))); - connect(m_autoTypeUi->customWindowSequenceButton, SIGNAL(toggled(bool)), - m_autoTypeUi->windowSequenceEdit, SLOT(setEnabled(bool))); + connect( + m_autoTypeUi->customSequenceButton, SIGNAL(toggled(bool)), m_autoTypeUi->sequenceEdit, SLOT(setEnabled(bool))); + connect(m_autoTypeUi->customWindowSequenceButton, + SIGNAL(toggled(bool)), + m_autoTypeUi->windowSequenceEdit, + SLOT(setEnabled(bool))); connect(m_autoTypeUi->assocAddButton, SIGNAL(clicked()), SLOT(insertAutoTypeAssoc())); connect(m_autoTypeUi->assocRemoveButton, SIGNAL(clicked()), SLOT(removeAutoTypeAssoc())); - connect(m_autoTypeUi->assocView->selectionModel(), SIGNAL(currentRowChanged(QModelIndex,QModelIndex)), + connect(m_autoTypeUi->assocView->selectionModel(), + SIGNAL(currentRowChanged(QModelIndex, QModelIndex)), SLOT(updateAutoTypeEnabled())); connect(m_autoTypeAssocModel, SIGNAL(modelReset()), SLOT(updateAutoTypeEnabled())); - connect(m_autoTypeUi->assocView->selectionModel(), SIGNAL(currentRowChanged(QModelIndex,QModelIndex)), + connect(m_autoTypeUi->assocView->selectionModel(), + SIGNAL(currentRowChanged(QModelIndex, QModelIndex)), SLOT(loadCurrentAssoc(QModelIndex))); connect(m_autoTypeAssocModel, SIGNAL(modelReset()), SLOT(clearCurrentAssoc())); - connect(m_autoTypeUi->windowTitleCombo, SIGNAL(editTextChanged(QString)), - SLOT(applyCurrentAssoc())); - connect(m_autoTypeUi->customWindowSequenceButton, SIGNAL(toggled(bool)), - SLOT(applyCurrentAssoc())); - connect(m_autoTypeUi->windowSequenceEdit, SIGNAL(textChanged(QString)), - SLOT(applyCurrentAssoc())); + connect(m_autoTypeUi->windowTitleCombo, SIGNAL(editTextChanged(QString)), SLOT(applyCurrentAssoc())); + connect(m_autoTypeUi->customWindowSequenceButton, SIGNAL(toggled(bool)), SLOT(applyCurrentAssoc())); + connect(m_autoTypeUi->windowSequenceEdit, SIGNAL(textChanged(QString)), SLOT(applyCurrentAssoc())); } void EditEntryWidget::setupProperties() @@ -217,11 +221,10 @@ void EditEntryWidget::setupHistory() m_historyUi->historyView->setModel(m_sortModel); m_historyUi->historyView->setRootIsDecorated(false); - connect(m_historyUi->historyView, SIGNAL(activated(QModelIndex)), - SLOT(histEntryActivated(QModelIndex))); + connect(m_historyUi->historyView, SIGNAL(activated(QModelIndex)), SLOT(histEntryActivated(QModelIndex))); connect(m_historyUi->historyView->selectionModel(), - SIGNAL(currentChanged(QModelIndex,QModelIndex)), - SLOT(updateHistoryButtons(QModelIndex,QModelIndex))); + SIGNAL(currentChanged(QModelIndex, QModelIndex)), + SLOT(updateHistoryButtons(QModelIndex, QModelIndex))); connect(m_historyUi->showButton, SIGNAL(clicked()), SLOT(showHistoryEntry())); connect(m_historyUi->restoreButton, SIGNAL(clicked()), SLOT(restoreHistoryEntry())); connect(m_historyUi->deleteButton, SIGNAL(clicked()), SLOT(deleteHistoryEntry())); @@ -261,7 +264,7 @@ void EditEntryWidget::setupEntryUpdate() connect(m_autoTypeUi->windowTitleCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(setUnsavedChanges())); connect(m_autoTypeUi->windowTitleCombo, SIGNAL(editTextChanged(const QString&)), this, SLOT(setUnsavedChanges())); - // Properties and History tabs don't need extra connections +// Properties and History tabs don't need extra connections #ifdef WITH_XC_SSHAGENT // SSH Agent tab @@ -269,12 +272,14 @@ void EditEntryWidget::setupEntryUpdate() connect(m_sshAgentUi->attachmentRadioButton, SIGNAL(toggled(bool)), this, SLOT(setUnsavedChanges())); connect(m_sshAgentUi->externalFileRadioButton, SIGNAL(toggled(bool)), this, SLOT(setUnsavedChanges())); connect(m_sshAgentUi->attachmentComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(setUnsavedChanges())); - connect(m_sshAgentUi->attachmentComboBox, SIGNAL(editTextChanged(const QString&)), this, SLOT(setUnsavedChanges())); + connect( + m_sshAgentUi->attachmentComboBox, SIGNAL(editTextChanged(const QString&)), this, SLOT(setUnsavedChanges())); connect(m_sshAgentUi->externalFileEdit, SIGNAL(textChanged(const QString&)), this, SLOT(setUnsavedChanges())); connect(m_sshAgentUi->publicKeyEdit, SIGNAL(textChanged()), this, SLOT(setUnsavedChanges())); connect(m_sshAgentUi->addKeyToAgentCheckBox, SIGNAL(stateChanged(int)), this, SLOT(setUnsavedChanges())); connect(m_sshAgentUi->removeKeyFromAgentCheckBox, SIGNAL(stateChanged(int)), this, SLOT(setUnsavedChanges())); - connect(m_sshAgentUi->requireUserConfirmationCheckBox, SIGNAL(stateChanged(int)), this, SLOT(setUnsavedChanges())); + connect( + m_sshAgentUi->requireUserConfirmationCheckBox, SIGNAL(stateChanged(int)), this, SLOT(setUnsavedChanges())); connect(m_sshAgentUi->lifetimeCheckBox, SIGNAL(stateChanged(int)), this, SLOT(setUnsavedChanges())); connect(m_sshAgentUi->lifetimeSpinBox, SIGNAL(valueChanged(int)), this, SLOT(setUnsavedChanges())); } @@ -307,8 +312,7 @@ void EditEntryWidget::updateHistoryButtons(const QModelIndex& current, const QMo m_historyUi->showButton->setEnabled(true); m_historyUi->restoreButton->setEnabled(true); m_historyUi->deleteButton->setEnabled(true); - } - else { + } else { m_historyUi->showButton->setEnabled(false); m_historyUi->restoreButton->setEnabled(false); m_historyUi->deleteButton->setEnabled(false); @@ -622,14 +626,12 @@ QString EditEntryWidget::entryTitle() const { if (m_entry) { return m_entry->title(); - } - else { + } else { return QString(); } } -void EditEntryWidget::loadEntry(Entry* entry, bool create, bool history, const QString& parentName, - Database* database) +void EditEntryWidget::loadEntry(Entry* entry, bool create, bool history, const QString& parentName, Database* database) { m_entry = entry; m_database = database; @@ -638,14 +640,11 @@ void EditEntryWidget::loadEntry(Entry* entry, bool create, bool history, const Q if (history) { setHeadline(QString("%1 > %2").arg(parentName, tr("Entry history"))); - } - else { + } else { if (create) { setHeadline(QString("%1 > %2").arg(parentName, tr("Add entry"))); - } - else { - setHeadline(QString("%1 > %2 > %3").arg(parentName, - entry->title(), tr("Edit entry"))); + } else { + setHeadline(QString("%1 > %2 > %3").arg(parentName, entry->title(), tr("Edit entry"))); } } @@ -684,8 +683,7 @@ void EditEntryWidget::setForms(const Entry* entry, bool restore) QAbstractItemView::EditTriggers editTriggers; if (m_history) { editTriggers = QAbstractItemView::NoEditTriggers; - } - else { + } else { editTriggers = QAbstractItemView::DoubleClicked; } m_advancedUi->attributesView->setEditTriggers(editTriggers); @@ -714,8 +712,7 @@ void EditEntryWidget::setForms(const Entry* entry, bool restore) if (m_attributesModel->rowCount() != 0) { m_advancedUi->attributesView->setCurrentIndex(m_attributesModel->index(0, 0)); - } - else { + } else { m_advancedUi->attributesEdit->setPlainText(""); m_advancedUi->attributesEdit->setEnabled(false); } @@ -734,8 +731,7 @@ void EditEntryWidget::setForms(const Entry* entry, bool restore) m_autoTypeUi->enableButton->setChecked(entry->autoTypeEnabled()); if (entry->defaultAutoTypeSequence().isEmpty()) { m_autoTypeUi->inheritSequenceButton->setChecked(true); - } - else { + } else { m_autoTypeUi->customSequenceButton->setChecked(true); } m_autoTypeUi->sequenceEdit->setText(entry->effectiveAutoTypeSequence()); @@ -767,8 +763,7 @@ void EditEntryWidget::setForms(const Entry* entry, bool restore) } if (m_historyModel->rowCount() > 0) { m_historyUi->deleteAllButton->setEnabled(true); - } - else { + } else { m_historyUi->deleteAllButton->setEnabled(false); } @@ -797,11 +792,13 @@ bool EditEntryWidget::commitEntry() } // Ask the user to apply the generator password, if open - if (m_mainUi->togglePasswordGeneratorButton->isChecked() && - m_mainUi->passwordGenerator->getGeneratedPassword() != m_mainUi->passwordEdit->text()) { - auto answer = MessageBox::question(this, tr("Apply generated password?"), - tr("Do you want to apply the generated password to this entry?"), - QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes); + if (m_mainUi->togglePasswordGeneratorButton->isChecked() + && m_mainUi->passwordGenerator->getGeneratedPassword() != m_mainUi->passwordEdit->text()) { + auto answer = MessageBox::question(this, + tr("Apply generated password?"), + tr("Do you want to apply the generated password to this entry?"), + QMessageBox::Yes | QMessageBox::No, + QMessageBox::Yes); if (answer == QMessageBox::Yes) { m_mainUi->passwordGenerator->applyPassword(); } @@ -812,8 +809,7 @@ bool EditEntryWidget::commitEntry() if (m_advancedUi->attributesView->currentIndex().isValid() && m_advancedUi->attributesEdit->isEnabled()) { QString key = m_attributesModel->keyByIndex(m_advancedUi->attributesView->currentIndex()); - m_entryAttributes->set(key, m_advancedUi->attributesEdit->toPlainText(), - m_entryAttributes->isProtected(key)); + m_entryAttributes->set(key, m_advancedUi->attributesEdit->toPlainText(), m_entryAttributes->isProtected(key)); } m_currentAttribute = QPersistentModelIndex(); @@ -879,15 +875,13 @@ void EditEntryWidget::updateEntryData(Entry* entry) const entry->setNotes(m_mainUi->notesEdit->toPlainText()); - if (m_advancedUi->fgColorCheckBox->isChecked() && - m_advancedUi->fgColorButton->property("color").isValid()) { + if (m_advancedUi->fgColorCheckBox->isChecked() && m_advancedUi->fgColorButton->property("color").isValid()) { entry->setForegroundColor(QColor(m_advancedUi->fgColorButton->property("color").toString())); } else { entry->setForegroundColor(QColor()); } - if (m_advancedUi->bgColorCheckBox->isChecked() && - m_advancedUi->bgColorButton->property("color").isValid()) { + if (m_advancedUi->bgColorCheckBox->isChecked() && m_advancedUi->bgColorButton->property("color").isValid()) { entry->setBackgroundColor(QColor(m_advancedUi->bgColorButton->property("color").toString())); } else { entry->setBackgroundColor(QColor()); @@ -922,13 +916,14 @@ void EditEntryWidget::cancel() return; } - if (!m_entry->iconUuid().isNull() && - !m_database->metadata()->containsCustomIcon(m_entry->iconUuid())) { + if (!m_entry->iconUuid().isNull() && !m_database->metadata()->containsCustomIcon(m_entry->iconUuid())) { m_entry->setIcon(Entry::DefaultIconNumber); } if (!m_saved) { - auto result = MessageBox::question(this, QString(), tr("Entry has unsaved changes"), + auto result = MessageBox::question(this, + QString(), + tr("Entry has unsaved changes"), QMessageBox::Cancel | QMessageBox::Save | QMessageBox::Discard, QMessageBox::Cancel); if (result == QMessageBox::Cancel) { @@ -1032,8 +1027,11 @@ void EditEntryWidget::removeCurrentAttribute() QModelIndex index = m_advancedUi->attributesView->currentIndex(); if (index.isValid()) { - if (MessageBox::question(this, tr("Confirm Remove"), tr("Are you sure you want to remove this attribute?"), - QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) { + if (MessageBox::question(this, + tr("Confirm Remove"), + tr("Are you sure you want to remove this attribute?"), + QMessageBox::Yes | QMessageBox::No) + == QMessageBox::Yes) { m_entryAttributes->remove(m_attributesModel->keyByIndex(index)); setUnsavedChanges(true); } @@ -1049,9 +1047,9 @@ void EditEntryWidget::updateCurrentAttribute() // Save changes to the currently selected attribute if editing is enabled if (m_currentAttribute.isValid() && m_advancedUi->attributesEdit->isEnabled()) { QString currKey = m_attributesModel->keyByIndex(m_currentAttribute); - m_entryAttributes->set(currKey, m_advancedUi->attributesEdit->toPlainText(), - m_entryAttributes->isProtected(currKey)); - } + m_entryAttributes->set( + currKey, m_advancedUi->attributesEdit->toPlainText(), m_entryAttributes->isProtected(currKey)); + } } displayAttribute(newIndex, m_entryAttributes->isProtected(newKey)); @@ -1071,8 +1069,7 @@ void EditEntryWidget::displayAttribute(QModelIndex index, bool showProtected) m_advancedUi->attributesEdit->setEnabled(false); m_advancedUi->revealAttributeButton->setEnabled(true); m_advancedUi->protectAttributeButton->setChecked(true); - } - else { + } else { m_advancedUi->attributesEdit->setPlainText(m_entryAttributes->value(key)); m_advancedUi->attributesEdit->setEnabled(true); m_advancedUi->revealAttributeButton->setEnabled(false); @@ -1083,8 +1080,7 @@ void EditEntryWidget::displayAttribute(QModelIndex index, bool showProtected) m_advancedUi->protectAttributeButton->setEnabled(!m_history); m_advancedUi->editAttributeButton->setEnabled(!m_history); m_advancedUi->removeAttributeButton->setEnabled(!m_history); - } - else { + } else { m_advancedUi->attributesEdit->setPlainText(""); m_advancedUi->attributesEdit->setEnabled(false); m_advancedUi->revealAttributeButton->setEnabled(false); @@ -1117,7 +1113,7 @@ void EditEntryWidget::protectCurrentAttribute(bool state) void EditEntryWidget::revealCurrentAttribute() { - if (! m_advancedUi->attributesEdit->isEnabled()) { + if (!m_advancedUi->attributesEdit->isEnabled()) { QModelIndex index = m_advancedUi->attributesView->currentIndex(); if (index.isValid()) { bool oldBlockSignals = m_advancedUi->attributesEdit->blockSignals(true); @@ -1253,8 +1249,7 @@ void EditEntryWidget::deleteAllHistoryEntries() m_historyModel->deleteAll(); if (m_historyModel->rowCount() > 0) { m_historyUi->deleteAllButton->setEnabled(true); - } - else { + } else { m_historyUi->deleteAllButton->setEnabled(false); } setUnsavedChanges(true); diff --git a/src/gui/entry/EditEntryWidget.h b/src/gui/entry/EditEntryWidget.h index 863d6505..814d2cc7 100644 --- a/src/gui/entry/EditEntryWidget.h +++ b/src/gui/entry/EditEntryWidget.h @@ -22,8 +22,8 @@ #include #include -#include "gui/EditWidget.h" #include "config-keepassx.h" +#include "gui/EditWidget.h" class AutoTypeAssociations; class AutoTypeAssociationsModel; @@ -43,7 +43,8 @@ class QStackedLayout; class OpenSSHKey; #endif -namespace Ui { +namespace Ui +{ class EditEntryWidgetAdvanced; class EditEntryWidgetAutoType; class EditEntryWidgetSSHAgent; @@ -60,8 +61,7 @@ public: explicit EditEntryWidget(QWidget* parent = nullptr); ~EditEntryWidget(); - void loadEntry(Entry* entry, bool create, bool history, const QString& parentName, - Database* database); + void loadEntry(Entry* entry, bool create, bool history, const QString& parentName, Database* database); void createPresetsMenu(QMenu* expirePresetsMenu); QString entryTitle() const; diff --git a/src/gui/entry/EditEntryWidget_p.h b/src/gui/entry/EditEntryWidget_p.h index 0e37c1fe..0ba01cd5 100644 --- a/src/gui/entry/EditEntryWidget_p.h +++ b/src/gui/entry/EditEntryWidget_p.h @@ -24,7 +24,8 @@ class AttributesListView : public QListView { public: - explicit AttributesListView(QWidget* parent = 0) : QListView(parent) + explicit AttributesListView(QWidget* parent = 0) + : QListView(parent) { setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding); } diff --git a/src/gui/entry/EntryAttachmentsModel.cpp b/src/gui/entry/EntryAttachmentsModel.cpp index 60874484..8f04a262 100644 --- a/src/gui/entry/EntryAttachmentsModel.cpp +++ b/src/gui/entry/EntryAttachmentsModel.cpp @@ -26,8 +26,7 @@ EntryAttachmentsModel::EntryAttachmentsModel(QObject* parent) : QAbstractListModel(parent) , m_entryAttachments(nullptr) { - m_headers << tr("Name") - << tr("Size"); + m_headers << tr("Name") << tr("Size"); } void EntryAttachmentsModel::setEntryAttachments(EntryAttachments* entryAttachments) @@ -57,8 +56,7 @@ int EntryAttachmentsModel::rowCount(const QModelIndex& parent) const { if (!m_entryAttachments || parent.isValid()) { return 0; - } - else { + } else { return m_entryAttachments->keys().size(); } } @@ -115,7 +113,7 @@ QString EntryAttachmentsModel::keyByIndex(const QModelIndex& index) const void EntryAttachmentsModel::attachmentChange(const QString& key) { int row = m_entryAttachments->keys().indexOf(key); - emit dataChanged(index(row, 0), index(row, columnCount()-1)); + emit dataChanged(index(row, 0), index(row, columnCount() - 1)); } void EntryAttachmentsModel::attachmentAboutToAdd(const QString& key) diff --git a/src/gui/entry/EntryAttachmentsModel.h b/src/gui/entry/EntryAttachmentsModel.h index fa8d3554..18a02c7c 100644 --- a/src/gui/entry/EntryAttachmentsModel.h +++ b/src/gui/entry/EntryAttachmentsModel.h @@ -27,7 +27,8 @@ class EntryAttachmentsModel : public QAbstractListModel Q_OBJECT public: - enum Columns { + enum Columns + { NameColumn, SizeColumn, ColumnsCount diff --git a/src/gui/entry/EntryAttachmentsWidget.cpp b/src/gui/entry/EntryAttachmentsWidget.cpp index d420d9d6..c1897d89 100644 --- a/src/gui/entry/EntryAttachmentsWidget.cpp +++ b/src/gui/entry/EntryAttachmentsWidget.cpp @@ -16,9 +16,8 @@ #include "gui/FileDialog.h" #include "gui/MessageBox.h" - -EntryAttachmentsWidget::EntryAttachmentsWidget(QWidget* parent) : - QWidget(parent) +EntryAttachmentsWidget::EntryAttachmentsWidget(QWidget* parent) + : QWidget(parent) , m_ui(new Ui::EntryAttachmentsWidget) , m_entryAttachments(new EntryAttachments(this)) , m_attachmentsModel(new EntryAttachmentsModel(this)) @@ -44,7 +43,8 @@ EntryAttachmentsWidget::EntryAttachmentsWidget(QWidget* parent) : connect(this, SIGNAL(readOnlyChanged(bool)), SLOT(updateButtonsEnabled())); connect(m_attachmentsModel, SIGNAL(modelReset()), SLOT(updateButtonsEnabled())); - connect(m_ui->attachmentsView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), + connect(m_ui->attachmentsView->selectionModel(), + SIGNAL(selectionChanged(QItemSelection, QItemSelection)), SLOT(updateButtonsEnabled())); connect(m_ui->attachmentsView, SIGNAL(doubleClicked(QModelIndex)), SLOT(openAttachment(QModelIndex))); @@ -163,11 +163,11 @@ void EntryAttachmentsWidget::removeSelectedAttachments() } const QString question = tr("Are you sure you want to remove %n attachment(s)?", "", indexes.count()); - QMessageBox::StandardButton answer = MessageBox::question(this, tr("Confirm remove"), - question, QMessageBox::Yes | QMessageBox::No); + QMessageBox::StandardButton answer = + MessageBox::question(this, tr("Confirm remove"), question, QMessageBox::Yes | QMessageBox::No); if (answer == QMessageBox::Yes) { QStringList keys; - for (const QModelIndex& index: indexes) { + for (const QModelIndex& index : indexes) { keys.append(m_attachmentsModel->keyByIndex(index)); } m_entryAttachments->remove(keys); @@ -183,7 +183,7 @@ void EntryAttachmentsWidget::saveSelectedAttachments() } QString defaultDirPath = config()->get("LastAttachmentDir").toString(); - const bool dirExists = !defaultDirPath.isEmpty() && QDir(defaultDirPath).exists(); + const bool dirExists = !defaultDirPath.isEmpty() && QDir(defaultDirPath).exists(); if (!dirExists) { defaultDirPath = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation); } @@ -203,13 +203,16 @@ void EntryAttachmentsWidget::saveSelectedAttachments() config()->set("LastAttachmentDir", QFileInfo(saveDir.absolutePath()).absolutePath()); QStringList errors; - for (const QModelIndex& index: indexes) { + for (const QModelIndex& index : indexes) { const QString filename = m_attachmentsModel->keyByIndex(index); const QString attachmentPath = saveDir.absoluteFilePath(filename); if (QFileInfo::exists(attachmentPath)) { - const QString question(tr("Are you sure you want to overwrite the existing file \"%1\" with the attachment?")); - auto answer = MessageBox::question(this, tr("Confirm overwrite"), question.arg(filename), + const QString question( + tr("Are you sure you want to overwrite the existing file \"%1\" with the attachment?")); + auto answer = MessageBox::question(this, + tr("Confirm overwrite"), + question.arg(filename), QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel); if (answer == QMessageBox::No) { continue; @@ -252,7 +255,7 @@ void EntryAttachmentsWidget::openSelectedAttachments() } QStringList errors; - for (const QModelIndex& index: indexes) { + for (const QModelIndex& index : indexes) { QString errorMessage; if (!openAttachment(index, errorMessage)) { const QString filename = m_attachmentsModel->keyByIndex(index); @@ -284,7 +287,7 @@ bool EntryAttachmentsWidget::insertAttachments(const QStringList& filenames, QSt } QStringList errors; - for (const QString &filename: filenames) { + for (const QString& filename : filenames) { QByteArray data; QFile file(filename); const QFileInfo fInfo(filename); @@ -313,9 +316,7 @@ bool EntryAttachmentsWidget::openAttachment(const QModelIndex& index, QString& e QScopedPointer tmpFile(new QTemporaryFile(tmpFileTemplate, this)); - const bool saveOk = tmpFile->open() - && tmpFile->write(attachmentData) == attachmentData.size() - && tmpFile->flush(); + const bool saveOk = tmpFile->open() && tmpFile->write(attachmentData) == attachmentData.size() && tmpFile->flush(); if (!saveOk) { errorMessage = QString("%1 - %2").arg(filename, tmpFile->errorString()); return false; @@ -351,7 +352,7 @@ bool EntryAttachmentsWidget::eventFilter(QObject* watched, QEvent* e) dropEv->acceptProposedAction(); QStringList filenames; const QList urls = mimeData->urls(); - for (const QUrl& url: urls) { + for (const QUrl& url : urls) { const QFileInfo fInfo(url.toLocalFile()); if (fInfo.isFile()) { filenames.append(fInfo.absoluteFilePath()); diff --git a/src/gui/entry/EntryAttachmentsWidget.h b/src/gui/entry/EntryAttachmentsWidget.h index 590060ae..8859536d 100644 --- a/src/gui/entry/EntryAttachmentsWidget.h +++ b/src/gui/entry/EntryAttachmentsWidget.h @@ -4,8 +4,9 @@ #include #include -namespace Ui { -class EntryAttachmentsWidget; +namespace Ui +{ + class EntryAttachmentsWidget; } class QByteArray; diff --git a/src/gui/entry/EntryAttributesModel.cpp b/src/gui/entry/EntryAttributesModel.cpp index 1b1eab22..ddb31d62 100644 --- a/src/gui/entry/EntryAttributesModel.cpp +++ b/src/gui/entry/EntryAttributesModel.cpp @@ -46,9 +46,9 @@ void EntryAttributesModel::setEntryAttributes(EntryAttributes* entryAttributes) connect(m_entryAttributes, SIGNAL(added(QString)), SLOT(attributeAdd())); connect(m_entryAttributes, SIGNAL(aboutToBeRemoved(QString)), SLOT(attributeAboutToRemove(QString))); connect(m_entryAttributes, SIGNAL(removed(QString)), SLOT(attributeRemove())); - connect(m_entryAttributes, SIGNAL(aboutToRename(QString,QString)), - SLOT(attributeAboutToRename(QString,QString))); - connect(m_entryAttributes, SIGNAL(renamed(QString,QString)), SLOT(attributeRename(QString,QString))); + connect( + m_entryAttributes, SIGNAL(aboutToRename(QString, QString)), SLOT(attributeAboutToRename(QString, QString))); + connect(m_entryAttributes, SIGNAL(renamed(QString, QString)), SLOT(attributeRename(QString, QString))); connect(m_entryAttributes, SIGNAL(aboutToBeReset()), SLOT(aboutToReset())); connect(m_entryAttributes, SIGNAL(reset()), SLOT(reset())); } @@ -60,8 +60,7 @@ int EntryAttributesModel::rowCount(const QModelIndex& parent) const { if (!m_entryAttributes || parent.isValid()) { return 0; - } - else { + } else { return m_attributes.size(); } } @@ -77,8 +76,7 @@ QVariant EntryAttributesModel::headerData(int section, Qt::Orientation orientati { if ((orientation == Qt::Horizontal) && (role == Qt::DisplayRole) && (section == 0)) { return tr("Name"); - } - else { + } else { return QVariant(); } } @@ -94,16 +92,14 @@ QVariant EntryAttributesModel::data(const QModelIndex& index, int role) const bool EntryAttributesModel::setData(const QModelIndex& index, const QVariant& value, int role) { - if (!index.isValid() || role != Qt::EditRole || value.type() != QVariant::String - || value.toString().isEmpty()) { + if (!index.isValid() || role != Qt::EditRole || value.type() != QVariant::String || value.toString().isEmpty()) { return false; } QString oldKey = m_attributes.at(index.row()); QString newKey = value.toString(); - if (EntryAttributes::isDefaultAttribute(newKey) - || m_entryAttributes->keys().contains(newKey)) { + if (EntryAttributes::isDefaultAttribute(newKey) || m_entryAttributes->keys().contains(newKey)) { return false; } m_entryAttributes->rename(oldKey, newKey); @@ -115,8 +111,7 @@ Qt::ItemFlags EntryAttributesModel::flags(const QModelIndex& index) const { if (!index.isValid()) { return Qt::NoItemFlags; - } - else { + } else { return QAbstractItemModel::flags(index) | Qt::ItemIsEditable; } } @@ -127,8 +122,7 @@ QModelIndex EntryAttributesModel::indexByKey(const QString& key) const if (row == -1) { return QModelIndex(); - } - else { + } else { return index(row, 0); } } @@ -137,8 +131,7 @@ QString EntryAttributesModel::keyByIndex(const QModelIndex& index) const { if (!index.isValid()) { return QString(); - } - else { + } else { return m_attributes.at(index.row()); } } @@ -147,7 +140,7 @@ void EntryAttributesModel::attributeChange(const QString& key) { int row = m_attributes.indexOf(key); Q_ASSERT(row != -1); - emit dataChanged(index(row, 0), index(row, columnCount()-1)); + emit dataChanged(index(row, 0), index(row, columnCount() - 1)); } void EntryAttributesModel::attributeAboutToAdd(const QString& key) @@ -194,8 +187,7 @@ void EntryAttributesModel::attributeAboutToRename(const QString& oldKey, const Q bool result = beginMoveRows(QModelIndex(), oldRow, oldRow, QModelIndex(), newRow); Q_UNUSED(result); Q_ASSERT(result); - } - else { + } else { m_nextRenameDataChange = true; } } @@ -208,8 +200,7 @@ void EntryAttributesModel::attributeRename(const QString& oldKey, const QString& if (!m_nextRenameDataChange) { endMoveRows(); - } - else { + } else { m_nextRenameDataChange = false; QModelIndex keyIndex = index(m_attributes.indexOf(newKey), 0); diff --git a/src/gui/entry/EntryHistoryModel.cpp b/src/gui/entry/EntryHistoryModel.cpp index 21f0aec4..aaec3de6 100644 --- a/src/gui/entry/EntryHistoryModel.cpp +++ b/src/gui/entry/EntryHistoryModel.cpp @@ -41,8 +41,7 @@ int EntryHistoryModel::rowCount(const QModelIndex& parent) const { if (!parent.isValid()) { return m_historyEntries.count(); - } - else { + } else { return 0; } } @@ -61,8 +60,7 @@ QVariant EntryHistoryModel::data(const QModelIndex& index, int role) const case 0: if (role == Qt::DisplayRole) { return lastModificationLocalTime.toString(Qt::SystemLocaleShortDate); - } - else { + } else { return lastModificationLocalTime; } case 1: diff --git a/src/gui/entry/EntryModel.cpp b/src/gui/entry/EntryModel.cpp index 6f7ebf6a..92709590 100644 --- a/src/gui/entry/EntryModel.cpp +++ b/src/gui/entry/EntryModel.cpp @@ -17,12 +17,12 @@ #include "EntryModel.h" +#include #include #include #include -#include -#include #include +#include #include "core/DatabaseIcons.h" #include "core/Entry.h" @@ -192,7 +192,9 @@ QVariant EntryModel::data(const QModelIndex& index, int role) const return result; case Expires: // Display either date of expiry or 'Never' - result = entry->timeInfo().expires() ? entry->timeInfo().expiryTime().toLocalTime().toString(EntryModel::DateFormat) : tr("Never"); + result = entry->timeInfo().expires() + ? entry->timeInfo().expiryTime().toLocalTime().toString(EntryModel::DateFormat) + : tr("Never"); return result; case Created: result = entry->timeInfo().creationTime().toLocalTime().toString(EntryModel::DateFormat); @@ -426,7 +428,7 @@ void EntryModel::entryRemoved() void EntryModel::entryDataChanged(Entry* entry) { int row = m_entries.indexOf(entry); - emit dataChanged(index(row, 0), index(row, columnCount()-1)); + emit dataChanged(index(row, 0), index(row, columnCount() - 1)); } void EntryModel::severConnections() diff --git a/src/gui/entry/EntryView.cpp b/src/gui/entry/EntryView.cpp index 19978a80..8c573e9e 100644 --- a/src/gui/entry/EntryView.cpp +++ b/src/gui/entry/EntryView.cpp @@ -50,7 +50,8 @@ EntryView::EntryView(QWidget* parent) setDefaultDropAction(Qt::MoveAction); connect(this, SIGNAL(doubleClicked(QModelIndex)), SLOT(emitEntryActivated(QModelIndex))); - connect(selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), SIGNAL(entrySelectionChanged())); + connect( + selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)), SIGNAL(entrySelectionChanged())); connect(m_model, SIGNAL(switchedToListMode()), SLOT(switchToListMode())); connect(m_model, SIGNAL(switchedToSearchMode()), SLOT(switchToSearchMode())); connect(m_model, SIGNAL(usernamesHiddenChanged()), SIGNAL(viewStateChanged())); @@ -330,7 +331,7 @@ void EntryView::showHeaderMenu(const QPoint& position) /** * Toggle visibility of column referenced by triggering action */ -void EntryView::toggleColumnVisibility(QAction *action) +void EntryView::toggleColumnVisibility(QAction* action) { // Verify action carries a column index as data. Since QVariant.toInt() // below will accept anything that's interpretable as int, perform a type @@ -443,7 +444,8 @@ void EntryView::fillRemainingWidth(bool lastColumnOnly) } // Add remaining width to last column - header()->resizeSection(header()->logicalIndex(lastColumnIndex), header()->sectionSize(lastColumnIndex) + (header()->width() - width)); + header()->resizeSection(header()->logicalIndex(lastColumnIndex), + header()->sectionSize(lastColumnIndex) + (header()->width() - width)); } void EntryView::resetFixedColumns() @@ -451,4 +453,3 @@ void EntryView::resetFixedColumns() header()->setSectionResizeMode(EntryModel::Paperclip, QHeaderView::Fixed); header()->resizeSection(EntryModel::Paperclip, header()->minimumSectionSize()); } - diff --git a/src/gui/entry/EntryView.h b/src/gui/entry/EntryView.h index a8422c56..3d166c48 100644 --- a/src/gui/entry/EntryView.h +++ b/src/gui/entry/EntryView.h @@ -68,7 +68,7 @@ private slots: void switchToListMode(); void switchToSearchMode(); void showHeaderMenu(const QPoint& position); - void toggleColumnVisibility(QAction *action); + void toggleColumnVisibility(QAction* action); void fitColumnsToWindow(); void fitColumnsToContents(); void resetViewToDefaults(); @@ -76,7 +76,7 @@ private slots: private: void fillRemainingWidth(bool lastColumnOnly); void resetFixedColumns(); - + EntryModel* const m_model; SortFilterHideProxyModel* const m_sortModel; bool m_inSearchMode; diff --git a/src/gui/group/EditGroupWidget.cpp b/src/gui/group/EditGroupWidget.cpp index 9ffd31a5..2abfa554 100644 --- a/src/gui/group/EditGroupWidget.cpp +++ b/src/gui/group/EditGroupWidget.cpp @@ -18,8 +18,8 @@ #include "EditGroupWidget.h" #include "ui_EditGroupWidgetMain.h" -#include "core/Metadata.h" #include "core/FilePath.h" +#include "core/Metadata.h" #include "gui/EditWidgetIcons.h" #include "gui/EditWidgetProperties.h" @@ -39,14 +39,18 @@ EditGroupWidget::EditGroupWidget(QWidget* parent) addPage(tr("Properties"), FilePath::instance()->icon("actions", "document-properties"), m_editWidgetProperties); connect(m_mainUi->expireCheck, SIGNAL(toggled(bool)), m_mainUi->expireDatePicker, SLOT(setEnabled(bool))); - connect(m_mainUi->autoTypeSequenceCustomRadio, SIGNAL(toggled(bool)), - m_mainUi->autoTypeSequenceCustomEdit, SLOT(setEnabled(bool))); + connect(m_mainUi->autoTypeSequenceCustomRadio, + SIGNAL(toggled(bool)), + m_mainUi->autoTypeSequenceCustomEdit, + SLOT(setEnabled(bool))); connect(this, SIGNAL(apply()), SLOT(apply())); connect(this, SIGNAL(accepted()), SLOT(save())); connect(this, SIGNAL(rejected()), SLOT(cancel())); - connect(m_editGroupWidgetIcons, SIGNAL(messageEditEntry(QString, MessageWidget::MessageType)), SLOT(showMessage(QString, MessageWidget::MessageType))); + connect(m_editGroupWidgetIcons, + SIGNAL(messageEditEntry(QString, MessageWidget::MessageType)), + SLOT(showMessage(QString, MessageWidget::MessageType))); connect(m_editGroupWidgetIcons, SIGNAL(messageEditEntryDismiss()), SLOT(hideMessage())); } @@ -61,16 +65,14 @@ void EditGroupWidget::loadGroup(Group* group, bool create, Database* database) if (create) { setHeadline(tr("Add group")); - } - else { + } else { setHeadline(tr("Edit group")); } if (m_group->parentGroup()) { addTriStateItems(m_mainUi->searchComboBox, m_group->parentGroup()->resolveSearchingEnabled()); addTriStateItems(m_mainUi->autotypeComboBox, m_group->parentGroup()->resolveAutoTypeEnabled()); - } - else { + } else { addTriStateItems(m_mainUi->searchComboBox, true); addTriStateItems(m_mainUi->autotypeComboBox, true); } @@ -83,8 +85,7 @@ void EditGroupWidget::loadGroup(Group* group, bool create, Database* database) m_mainUi->autotypeComboBox->setCurrentIndex(indexFromTriState(group->autoTypeEnabled())); if (group->defaultAutoTypeSequence().isEmpty()) { m_mainUi->autoTypeSequenceInherit->setChecked(true); - } - else { + } else { m_mainUi->autoTypeSequenceCustomRadio->setChecked(true); } m_mainUi->autoTypeSequenceCustomEdit->setText(group->effectiveAutoTypeSequence()); @@ -123,8 +124,7 @@ void EditGroupWidget::apply() if (m_mainUi->autoTypeSequenceInherit->isChecked()) { m_group->setDefaultAutoTypeSequence(QString()); - } - else { + } else { m_group->setDefaultAutoTypeSequence(m_mainUi->autoTypeSequenceCustomEdit->text()); } @@ -132,19 +132,16 @@ void EditGroupWidget::apply() if (iconStruct.number < 0) { m_group->setIcon(Group::DefaultIconNumber); - } - else if (iconStruct.uuid.isNull()) { + } else if (iconStruct.uuid.isNull()) { m_group->setIcon(iconStruct.number); - } - else { + } else { m_group->setIcon(iconStruct.uuid); } } void EditGroupWidget::cancel() { - if (!m_group->iconUuid().isNull() && - !m_database->metadata()->containsCustomIcon(m_group->iconUuid())) { + if (!m_group->iconUuid().isNull() && !m_database->metadata()->containsCustomIcon(m_group->iconUuid())) { m_group->setIcon(Entry::DefaultIconNumber); } @@ -164,8 +161,7 @@ void EditGroupWidget::addTriStateItems(QComboBox* comboBox, bool inheritDefault) QString inheritDefaultString; if (inheritDefault) { inheritDefaultString = tr("Enable"); - } - else { + } else { inheritDefaultString = tr("Disable"); } diff --git a/src/gui/group/EditGroupWidget.h b/src/gui/group/EditGroupWidget.h index 2d184493..8f13ef33 100644 --- a/src/gui/group/EditGroupWidget.h +++ b/src/gui/group/EditGroupWidget.h @@ -27,7 +27,8 @@ class EditWidgetIcons; class EditWidgetProperties; -namespace Ui { +namespace Ui +{ class EditGroupWidgetMain; class EditWidget; } diff --git a/src/gui/group/GroupModel.cpp b/src/gui/group/GroupModel.cpp index 87eacf27..ad268c46 100644 --- a/src/gui/group/GroupModel.cpp +++ b/src/gui/group/GroupModel.cpp @@ -44,11 +44,11 @@ void GroupModel::changeDatabase(Database* newDb) m_db = newDb; connect(m_db, SIGNAL(groupDataChanged(Group*)), SLOT(groupDataChanged(Group*))); - connect(m_db, SIGNAL(groupAboutToAdd(Group*,int)), SLOT(groupAboutToAdd(Group*,int))); + connect(m_db, SIGNAL(groupAboutToAdd(Group*, int)), SLOT(groupAboutToAdd(Group*, int))); connect(m_db, SIGNAL(groupAdded()), SLOT(groupAdded())); connect(m_db, SIGNAL(groupAboutToRemove(Group*)), SLOT(groupAboutToRemove(Group*))); connect(m_db, SIGNAL(groupRemoved()), SLOT(groupRemoved())); - connect(m_db, SIGNAL(groupAboutToMove(Group*,Group*,int)), SLOT(groupAboutToMove(Group*,Group*,int))); + connect(m_db, SIGNAL(groupAboutToMove(Group*, Group*, int)), SLOT(groupAboutToMove(Group*, Group*, int))); connect(m_db, SIGNAL(groupMoved()), SLOT(groupMoved())); endResetModel(); @@ -59,8 +59,7 @@ int GroupModel::rowCount(const QModelIndex& parent) const if (!parent.isValid()) { // we have exactly 1 root item return 1; - } - else { + } else { const Group* group = groupFromIndex(parent); return group->children().size(); } @@ -83,8 +82,7 @@ QModelIndex GroupModel::index(int row, int column, const QModelIndex& parent) co if (!parent.isValid()) { group = m_db->rootGroup(); - } - else { + } else { group = groupFromIndex(parent)->children().at(row); } @@ -107,14 +105,12 @@ QModelIndex GroupModel::parent(Group* group) const if (!parentGroup) { // index is already the root group return QModelIndex(); - } - else { + } else { const Group* grandParentGroup = parentGroup->parentGroup(); if (!grandParentGroup) { // parent is the root group return createIndex(0, 0, parentGroup); - } - else { + } else { return createIndex(grandParentGroup->children().indexOf(parentGroup), 0, parentGroup); } } @@ -130,23 +126,19 @@ QVariant GroupModel::data(const QModelIndex& index, int role) const if (role == Qt::DisplayRole) { return group->name(); - } - else if (role == Qt::DecorationRole) { + } else if (role == Qt::DecorationRole) { if (group->isExpired()) { return databaseIcons()->iconPixmap(DatabaseIcons::ExpiredIconIndex); - } - else { + } else { return group->iconScaledPixmap(); } - } - else if (role == Qt::FontRole) { + } else if (role == Qt::FontRole) { QFont font; if (group->isExpired()) { font.setStrikeOut(true); } return font; - } - else { + } else { return QVariant(); } } @@ -166,8 +158,7 @@ QModelIndex GroupModel::index(Group* group) const if (!group->parentGroup()) { row = 0; - } - else { + } else { row = group->parentGroup()->children().indexOf(group); } @@ -190,17 +181,18 @@ Qt::ItemFlags GroupModel::flags(const QModelIndex& modelIndex) const { if (!modelIndex.isValid()) { return Qt::NoItemFlags; - } - else if (modelIndex == index(0, 0)) { + } else if (modelIndex == index(0, 0)) { return QAbstractItemModel::flags(modelIndex) | Qt::ItemIsDropEnabled; - } - else { + } else { return QAbstractItemModel::flags(modelIndex) | Qt::ItemIsDropEnabled | Qt::ItemIsDragEnabled; } } -bool GroupModel::dropMimeData(const QMimeData* data, Qt::DropAction action, - int row, int column, const QModelIndex& parent) +bool GroupModel::dropMimeData(const QMimeData* data, + Qt::DropAction action, + int row, + int column, + const QModelIndex& parent) { Q_UNUSED(column); @@ -229,7 +221,6 @@ bool GroupModel::dropMimeData(const QMimeData* data, Qt::DropAction action, QByteArray encoded = data->data(isGroup ? types.at(0) : types.at(1)); QDataStream stream(&encoded, QIODevice::ReadOnly); - Group* parentGroup = groupFromIndex(parent); if (isGroup) { @@ -258,8 +249,7 @@ bool GroupModel::dropMimeData(const QMimeData* data, Qt::DropAction action, Group* group; if (action == Qt::MoveAction) { group = dragGroup; - } - else { + } else { group = dragGroup->clone(); } @@ -272,8 +262,7 @@ bool GroupModel::dropMimeData(const QMimeData* data, Qt::DropAction action, } group->setParent(parentGroup, row); - } - else { + } else { if (row != -1) { return false; } @@ -296,8 +285,7 @@ bool GroupModel::dropMimeData(const QMimeData* data, Qt::DropAction action, Entry* entry; if (action == Qt::MoveAction) { entry = dragEntry; - } - else { + } else { entry = dragEntry->clone(Entry::CloneNewUuid | Entry::CloneResetTimeInfo); } @@ -305,10 +293,8 @@ bool GroupModel::dropMimeData(const QMimeData* data, Qt::DropAction action, Database* targetDb = parentGroup->database(); Uuid customIcon = entry->iconUuid(); - if (sourceDb != targetDb && !customIcon.isNull() - && !targetDb->metadata()->containsCustomIcon(customIcon)) { - targetDb->metadata()->addCustomIcon(customIcon, - sourceDb->metadata()->customIcon(customIcon)); + if (sourceDb != targetDb && !customIcon.isNull() && !targetDb->metadata()->containsCustomIcon(customIcon)) { + targetDb->metadata()->addCustomIcon(customIcon, sourceDb->metadata()->customIcon(customIcon)); } entry->setGroup(parentGroup); @@ -355,8 +341,7 @@ QMimeData* GroupModel::mimeData(const QModelIndexList& indexes) const if (seenGroups.isEmpty()) { delete data; return nullptr; - } - else { + } else { data->setData(mimeTypes().at(0), encoded); return data; } diff --git a/src/gui/group/GroupModel.h b/src/gui/group/GroupModel.h index 899aa3fd..ca5370d7 100644 --- a/src/gui/group/GroupModel.h +++ b/src/gui/group/GroupModel.h @@ -41,8 +41,8 @@ public: QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; Qt::DropActions supportedDropActions() const override; Qt::ItemFlags flags(const QModelIndex& modelIndex) const override; - bool dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, - const QModelIndex& parent) override; + bool + dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent) override; QStringList mimeTypes() const override; QMimeData* mimeData(const QModelIndexList& indexes) const override; diff --git a/src/gui/group/GroupView.cpp b/src/gui/group/GroupView.cpp index 82d01e31..fd674800 100644 --- a/src/gui/group/GroupView.cpp +++ b/src/gui/group/GroupView.cpp @@ -36,10 +36,10 @@ GroupView::GroupView(Database* db, QWidget* parent) connect(this, SIGNAL(expanded(QModelIndex)), this, SLOT(expandedChanged(QModelIndex))); connect(this, SIGNAL(collapsed(QModelIndex)), this, SLOT(expandedChanged(QModelIndex))); - connect(m_model, SIGNAL(rowsInserted(QModelIndex,int,int)), SLOT(syncExpandedState(QModelIndex,int,int))); + connect(m_model, SIGNAL(rowsInserted(QModelIndex, int, int)), SLOT(syncExpandedState(QModelIndex, int, int))); connect(m_model, SIGNAL(modelReset()), SLOT(modelReset())); - connect(selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)), SLOT(emitGroupChanged())); + connect(selectionModel(), SIGNAL(currentChanged(QModelIndex, QModelIndex)), SLOT(emitGroupChanged())); connect(this, SIGNAL(clicked(QModelIndex)), SLOT(emitGroupPressed(QModelIndex))); @@ -60,8 +60,7 @@ void GroupView::dragMoveEvent(QDragMoveEvent* event) { if (event->keyboardModifiers() & Qt::ControlModifier) { event->setDropAction(Qt::CopyAction); - } - else { + } else { event->setDropAction(Qt::MoveAction); } @@ -69,7 +68,7 @@ void GroupView::dragMoveEvent(QDragMoveEvent* event) // entries may only be dropped on groups if (event->isAccepted() && event->mimeData()->hasFormat("application/x-keepassx-entry") - && (dropIndicatorPosition() == AboveItem || dropIndicatorPosition() == BelowItem)) { + && (dropIndicatorPosition() == AboveItem || dropIndicatorPosition() == BelowItem)) { event->ignore(); } } @@ -78,8 +77,7 @@ Group* GroupView::currentGroup() { if (currentIndex() == QModelIndex()) { return nullptr; - } - else { + } else { return m_model->groupFromIndex(currentIndex()); } } diff --git a/src/gui/widgets/ElidedLabel.cpp b/src/gui/widgets/ElidedLabel.cpp index 1642bdec..03d2b556 100644 --- a/src/gui/widgets/ElidedLabel.cpp +++ b/src/gui/widgets/ElidedLabel.cpp @@ -17,11 +17,12 @@ #include "ElidedLabel.h" -#include #include +#include -namespace { -const QString htmlLinkTemplate("%2"); +namespace +{ + const QString htmlLinkTemplate("%2"); } ElidedLabel::ElidedLabel(QWidget* parent, Qt::WindowFlags f) diff --git a/src/gui/widgets/ElidedLabel.h b/src/gui/widgets/ElidedLabel.h index c7694b5a..5dd14891 100644 --- a/src/gui/widgets/ElidedLabel.h +++ b/src/gui/widgets/ElidedLabel.h @@ -29,8 +29,8 @@ class ElidedLabel : public QLabel Q_PROPERTY(QString rawText READ rawText WRITE setRawText NOTIFY rawTextChanged) Q_PROPERTY(QString url READ url WRITE setUrl NOTIFY urlChanged) public: - explicit ElidedLabel(QWidget *parent=nullptr, Qt::WindowFlags f=Qt::WindowFlags()); - explicit ElidedLabel(const QString &text, QWidget *parent=nullptr, Qt::WindowFlags f=Qt::WindowFlags()); + explicit ElidedLabel(QWidget* parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags()); + explicit ElidedLabel(const QString& text, QWidget* parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags()); Qt::TextElideMode elideMode() const; QString rawText() const; diff --git a/src/keys/ChallengeResponseKey.h b/src/keys/ChallengeResponseKey.h index 698846a0..702ee251 100644 --- a/src/keys/ChallengeResponseKey.h +++ b/src/keys/ChallengeResponseKey.h @@ -24,7 +24,9 @@ class ChallengeResponseKey { public: - virtual ~ChallengeResponseKey() {} + virtual ~ChallengeResponseKey() + { + } virtual QByteArray rawKey() const = 0; virtual bool challenge(const QByteArray& challenge) = 0; }; diff --git a/src/keys/CompositeKey.cpp b/src/keys/CompositeKey.cpp index 6391819b..3bce1559 100644 --- a/src/keys/CompositeKey.cpp +++ b/src/keys/CompositeKey.cpp @@ -22,8 +22,8 @@ #include #include "core/Global.h" -#include "crypto/kdf/AesKdf.h" #include "crypto/CryptoHash.h" +#include "crypto/kdf/AesKdf.h" CompositeKey::CompositeKey() { diff --git a/src/keys/CompositeKey.h b/src/keys/CompositeKey.h index fe93a38b..50d9dbd3 100644 --- a/src/keys/CompositeKey.h +++ b/src/keys/CompositeKey.h @@ -20,12 +20,12 @@ #define KEEPASSX_COMPOSITEKEY_H #include -#include #include +#include #include "crypto/kdf/Kdf.h" -#include "keys/Key.h" #include "keys/ChallengeResponseKey.h" +#include "keys/Key.h" class CompositeKey : public Key { @@ -41,7 +41,7 @@ public: QByteArray rawKey() const override; QByteArray rawKey(const QByteArray* transformSeed, bool* ok = nullptr) const; bool transform(const Kdf& kdf, QByteArray& result) const Q_REQUIRED_RESULT; - bool challenge(const QByteArray& seed, QByteArray &result) const; + bool challenge(const QByteArray& seed, QByteArray& result) const; void addKey(const Key& key); void addChallengeResponseKey(QSharedPointer key); diff --git a/src/keys/FileKey.cpp b/src/keys/FileKey.cpp index 26db40d8..b491fc51 100644 --- a/src/keys/FileKey.cpp +++ b/src/keys/FileKey.cpp @@ -347,8 +347,7 @@ bool FileKey::loadHashed(QIODevice* device) return false; } cryptoHash.addData(buffer); - } - while (!buffer.isEmpty()); + } while (!buffer.isEmpty()); m_key = cryptoHash.result(); diff --git a/src/keys/FileKey.h b/src/keys/FileKey.h index 2aa48909..3f04eded 100644 --- a/src/keys/FileKey.h +++ b/src/keys/FileKey.h @@ -25,10 +25,11 @@ class QIODevice; -class FileKey: public Key +class FileKey : public Key { public: - enum Type { + enum Type + { None, Hashed, KeePass2XML, diff --git a/src/keys/Key.h b/src/keys/Key.h index 2172f570..4014e390 100644 --- a/src/keys/Key.h +++ b/src/keys/Key.h @@ -23,7 +23,9 @@ class Key { public: - virtual ~Key() {} + virtual ~Key() + { + } virtual QByteArray rawKey() const = 0; virtual Key* clone() const = 0; }; diff --git a/src/keys/YkChallengeResponseKey.cpp b/src/keys/YkChallengeResponseKey.cpp index ac50a5bb..913e2d32 100644 --- a/src/keys/YkChallengeResponseKey.cpp +++ b/src/keys/YkChallengeResponseKey.cpp @@ -23,16 +23,16 @@ #include "crypto/Random.h" #include "gui/MainWindow.h" -#include -#include -#include #include #include +#include #include +#include +#include YkChallengeResponseKey::YkChallengeResponseKey(int slot, bool blocking) - : m_slot(slot), - m_blocking(blocking) + : m_slot(slot) + , m_blocking(blocking) { if (KEEPASSXC_MAIN_WINDOW) { connect(this, SIGNAL(userInteractionRequired()), KEEPASSXC_MAIN_WINDOW, SLOT(showYubiKeyPopup())); @@ -64,9 +64,8 @@ bool YkChallengeResponseKey::challenge(const QByteArray& challenge, unsigned ret emit userInteractionRequired(); } - QFuture future = QtConcurrent::run([this, challenge]() { - return YubiKey::instance()->challenge(m_slot, true, challenge, m_key); - }); + QFuture future = QtConcurrent::run( + [this, challenge]() { return YubiKey::instance()->challenge(m_slot, true, challenge, m_key); }); QEventLoop loop; QFutureWatcher watcher; @@ -99,9 +98,8 @@ QString YkChallengeResponseKey::getName() const YubiKey::instance()->getSerial(serial); - return fmt.arg(QString::number(serial), - QString::number(m_slot), - (m_blocking) ? QObject::tr("Press") : QObject::tr("Passive")); + return fmt.arg( + QString::number(serial), QString::number(m_slot), (m_blocking) ? QObject::tr("Press") : QObject::tr("Passive")); } bool YkChallengeResponseKey::isBlocking() const diff --git a/src/keys/YkChallengeResponseKey.h b/src/keys/YkChallengeResponseKey.h index 2816602a..912896e9 100644 --- a/src/keys/YkChallengeResponseKey.h +++ b/src/keys/YkChallengeResponseKey.h @@ -29,7 +29,6 @@ class YkChallengeResponseKey : public QObject, public ChallengeResponseKey Q_OBJECT public: - YkChallengeResponseKey(int slot = -1, bool blocking = false); QByteArray rawKey() const; diff --git a/src/keys/drivers/YubiKey.cpp b/src/keys/drivers/YubiKey.cpp index 4b98a6e4..b9491619 100644 --- a/src/keys/drivers/YubiKey.cpp +++ b/src/keys/drivers/YubiKey.cpp @@ -21,12 +21,12 @@ #include #include -#include #include #include +#include -#include "core/Tools.h" #include "core/Global.h" +#include "core/Tools.h" #include "crypto/Random.h" #include "YubiKey.h" @@ -36,7 +36,10 @@ #define m_yk (static_cast(m_yk_void)) #define m_ykds (static_cast(m_ykds_void)) -YubiKey::YubiKey() : m_yk_void(NULL), m_ykds_void(NULL), m_mutex(QMutex::Recursive) +YubiKey::YubiKey() + : m_yk_void(NULL) + , m_ykds_void(NULL) + , m_mutex(QMutex::Recursive) { } @@ -188,8 +191,8 @@ YubiKey::ChallengeResult YubiKey::challenge(int slot, bool mayBlock, const QByte paddedChallenge.append(QByteArray(padLen, padLen)); } - const unsigned char *c; - unsigned char *r; + const unsigned char* c; + unsigned char* r; c = reinterpret_cast(paddedChallenge.constData()); r = reinterpret_cast(response.data()); diff --git a/src/keys/drivers/YubiKey.h b/src/keys/drivers/YubiKey.h index 328688f0..39085546 100644 --- a/src/keys/drivers/YubiKey.h +++ b/src/keys/drivers/YubiKey.h @@ -19,8 +19,8 @@ #ifndef KEEPASSX_YUBIKEY_H #define KEEPASSX_YUBIKEY_H -#include #include +#include /** * Singleton class to manage the interface to the hardware @@ -30,7 +30,13 @@ class YubiKey : public QObject Q_OBJECT public: - enum ChallengeResult { ERROR = -1, SUCCESS = 0, WOULDBLOCK, ALREADY_RUNNING }; + enum ChallengeResult + { + ERROR = -1, + SUCCESS = 0, + WOULDBLOCK, + ALREADY_RUNNING + }; /** * @brief YubiKey::instance - get instance of singleton diff --git a/src/keys/drivers/YubiKeyStub.cpp b/src/keys/drivers/YubiKeyStub.cpp index 9f6314f0..3cff0496 100644 --- a/src/keys/drivers/YubiKeyStub.cpp +++ b/src/keys/drivers/YubiKeyStub.cpp @@ -23,7 +23,9 @@ #include "YubiKey.h" -YubiKey::YubiKey() : m_yk_void(NULL), m_ykds_void(NULL) +YubiKey::YubiKey() + : m_yk_void(NULL) + , m_ykds_void(NULL) { } diff --git a/src/main.cpp b/src/main.cpp index b3b607f2..13c22858 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -59,22 +59,24 @@ int main(int argc, char** argv) // QStandardPaths::writableLocation(QDesktopServices::DataLocation) QCommandLineParser parser; - parser.setApplicationDescription(QCoreApplication::translate("main", "KeePassXC - cross-platform password manager")); - parser.addPositionalArgument("filename", QCoreApplication::translate("main", "filenames of the password databases to open (*.kdbx)"), "[filename(s)]"); + parser.setApplicationDescription( + QCoreApplication::translate("main", "KeePassXC - cross-platform password manager")); + parser.addPositionalArgument( + "filename", + QCoreApplication::translate("main", "filenames of the password databases to open (*.kdbx)"), + "[filename(s)]"); - QCommandLineOption configOption("config", - QCoreApplication::translate("main", "path to a custom config file"), - "config"); - QCommandLineOption keyfileOption("keyfile", - QCoreApplication::translate("main", "key file of the database"), - "keyfile"); + QCommandLineOption configOption( + "config", QCoreApplication::translate("main", "path to a custom config file"), "config"); + QCommandLineOption keyfileOption( + "keyfile", QCoreApplication::translate("main", "key file of the database"), "keyfile"); QCommandLineOption pwstdinOption("pw-stdin", QCoreApplication::translate("main", "read password of the database from stdin")); // This is needed under Windows where clients send --parent-window parameter with Native Messaging connect method QCommandLineOption parentWindowOption(QStringList() << "pw" << "parent-window", - QCoreApplication::translate("main", "Parent window handle"), - "handle"); + QCoreApplication::translate("main", "Parent window handle"), + "handle"); parser.addHelpOption(); parser.addVersionOption(); @@ -90,15 +92,16 @@ int main(int argc, char** argv) if (!fileNames.isEmpty()) { app.sendFileNamesToRunningInstance(fileNames); } - qWarning() << QCoreApplication::translate("Main", "Another instance of KeePassXC is already running.").toUtf8().constData(); + qWarning() << QCoreApplication::translate("Main", "Another instance of KeePassXC is already running.") + .toUtf8() + .constData(); return 0; } QApplication::setQuitOnLastWindowClosed(false); if (!Crypto::init()) { - QString error = QCoreApplication::translate("Main", - "Fatal error while testing the cryptographic functions."); + QString error = QCoreApplication::translate("Main", "Fatal error while testing the cryptographic functions."); error.append("\n"); error.append(Crypto::errorString()); MessageBox::critical(nullptr, QCoreApplication::translate("Main", "KeePassXC - Error"), error); @@ -126,7 +129,7 @@ int main(int argc, char** argv) // start minimized if configured bool minimizeOnStartup = config()->get("GUI/MinimizeOnStartup").toBool(); - bool minimizeToTray = config()->get("GUI/MinimizeToTray").toBool(); + bool minimizeToTray = config()->get("GUI/MinimizeToTray").toBool(); #ifndef Q_OS_LINUX if (minimizeOnStartup) { #else @@ -143,7 +146,7 @@ int main(int argc, char** argv) if (config()->get("OpenPreviousDatabasesOnStartup").toBool()) { const QStringList fileNames = config()->get("LastOpenedDatabases").toStringList(); - for (const QString& filename: fileNames) { + for (const QString& filename : fileNames) { if (!filename.isEmpty() && QFile::exists(filename)) { mainWindow.openDatabase(filename); } @@ -151,7 +154,7 @@ int main(int argc, char** argv) } const bool pwstdin = parser.isSet(pwstdinOption); - for (const QString& filename: fileNames) { + for (const QString& filename : fileNames) { QString password; if (pwstdin) { // we always need consume a line of STDIN if --pw-stdin is set to clear out the diff --git a/src/proxy/NativeMessagingHost.cpp b/src/proxy/NativeMessagingHost.cpp old mode 100755 new mode 100644 index c5ce60ea..61b1687f --- a/src/proxy/NativeMessagingHost.cpp +++ b/src/proxy/NativeMessagingHost.cpp @@ -15,20 +15,25 @@ * along with this program. If not, see . */ -#include #include "NativeMessagingHost.h" +#include -NativeMessagingHost::NativeMessagingHost() : NativeMessagingBase() +NativeMessagingHost::NativeMessagingHost() + : NativeMessagingBase() { m_localSocket = new QLocalSocket(); m_localSocket->connectToServer(getLocalServerPath()); #ifdef Q_OS_WIN m_running.store(true); - m_future = QtConcurrent::run(this, static_cast(&NativeMessagingHost::readNativeMessages)); + m_future = + QtConcurrent::run(this, static_cast(&NativeMessagingHost::readNativeMessages)); #endif connect(m_localSocket, SIGNAL(readyRead()), this, SLOT(newLocalMessage())); connect(m_localSocket, SIGNAL(disconnected()), this, SLOT(deleteSocket())); - connect(m_localSocket, SIGNAL(stateChanged(QLocalSocket::LocalSocketState)), this, SLOT(socketStateChanged(QLocalSocket::LocalSocketState))); + connect(m_localSocket, + SIGNAL(stateChanged(QLocalSocket::LocalSocketState)), + this, + SLOT(socketStateChanged(QLocalSocket::LocalSocketState))); } NativeMessagingHost::~NativeMessagingHost() @@ -45,7 +50,7 @@ void NativeMessagingHost::readLength() if (!std::cin.eof() && length > 0) { readStdIn(length); } else { - QCoreApplication::quit(); + QCoreApplication::quit(); } } @@ -81,7 +86,7 @@ void NativeMessagingHost::newLocalMessage() QByteArray arr = m_localSocket->readAll(); if (!arr.isEmpty()) { - sendReply(arr); + sendReply(arr); } } diff --git a/src/proxy/NativeMessagingHost.h b/src/proxy/NativeMessagingHost.h old mode 100755 new mode 100644 index 41f3ed75..faf9d908 --- a/src/proxy/NativeMessagingHost.h +++ b/src/proxy/NativeMessagingHost.h @@ -37,7 +37,7 @@ private: void readStdIn(const quint32 length); private: - QLocalSocket* m_localSocket; + QLocalSocket* m_localSocket; }; #endif // NATIVEMESSAGINGHOST_H diff --git a/src/proxy/keepassxc-proxy.cpp b/src/proxy/keepassxc-proxy.cpp index 9509c1ea..d75f841c 100644 --- a/src/proxy/keepassxc-proxy.cpp +++ b/src/proxy/keepassxc-proxy.cpp @@ -16,9 +16,9 @@ * along with this program. If not, see . */ +#include "NativeMessagingHost.h" #include #include -#include "NativeMessagingHost.h" #ifndef Q_OS_WIN #include @@ -26,13 +26,15 @@ #include // (C) Gist: https://gist.github.com/azadkuh/a2ac6869661ebd3f8588 -void ignoreUnixSignals(std::initializer_list ignoreSignals) { +void ignoreUnixSignals(std::initializer_list ignoreSignals) +{ for (int sig : ignoreSignals) { signal(sig, SIG_IGN); } } -void catchUnixSignals(std::initializer_list quitSignals) { +void catchUnixSignals(std::initializer_list quitSignals) +{ auto handler = [](int sig) -> void { std::cerr << sig; QCoreApplication::quit(); @@ -46,8 +48,8 @@ void catchUnixSignals(std::initializer_list quitSignals) { struct sigaction sa; sa.sa_handler = handler; - sa.sa_mask = blocking_mask; - sa.sa_flags = 0; + sa.sa_mask = blocking_mask; + sa.sa_flags = 0; for (auto sig : quitSignals) { sigaction(sig, &sa, nullptr); @@ -55,7 +57,7 @@ void catchUnixSignals(std::initializer_list quitSignals) { } #endif -int main(int argc, char *argv[]) +int main(int argc, char* argv[]) { QCoreApplication a(argc, argv); #if defined(Q_OS_UNIX) || defined(Q_OS_LINUX) diff --git a/src/sshagent/ASN1Key.cpp b/src/sshagent/ASN1Key.cpp index c46b8fa0..9197cade 100644 --- a/src/sshagent/ASN1Key.cpp +++ b/src/sshagent/ASN1Key.cpp @@ -19,10 +19,11 @@ #include "ASN1Key.h" #include -namespace { - constexpr quint8 TAG_INT = 0x02; - constexpr quint8 TAG_SEQUENCE = 0x30; - constexpr quint8 KEY_ZERO = 0x0; +namespace +{ + constexpr quint8 TAG_INT = 0x02; + constexpr quint8 TAG_SEQUENCE = 0x30; + constexpr quint8 KEY_ZERO = 0x0; bool nextTag(BinaryStream& stream, quint8& tag, quint32& len) { @@ -103,7 +104,8 @@ namespace { mpi_invm(u, q, p); iqmp_hex.resize((bap.length() + 1) * 2); - gcry_mpi_print(GCRYMPI_FMT_HEX, reinterpret_cast(iqmp_hex.data()), iqmp_hex.length(), nullptr, u); + gcry_mpi_print( + GCRYMPI_FMT_HEX, reinterpret_cast(iqmp_hex.data()), iqmp_hex.length(), nullptr, u); gcry_mpi_release(u); gcry_mpi_release(p); @@ -121,7 +123,7 @@ bool ASN1Key::parseDSA(QByteArray& ba, OpenSSHKey& key) return false; } - QByteArray p,q,g,y,x; + QByteArray p, q, g, y, x; readInt(stream, p); readInt(stream, q); readInt(stream, g); @@ -156,7 +158,7 @@ bool ASN1Key::parseRSA(QByteArray& ba, OpenSSHKey& key) return false; } - QByteArray n,e,d,p,q,dp,dq,qinv; + QByteArray n, e, d, p, q, dp, dq, qinv; readInt(stream, n); readInt(stream, e); readInt(stream, d); diff --git a/src/sshagent/AgentSettingsPage.cpp b/src/sshagent/AgentSettingsPage.cpp index 70fa04bd..1f04d61b 100644 --- a/src/sshagent/AgentSettingsPage.cpp +++ b/src/sshagent/AgentSettingsPage.cpp @@ -27,7 +27,6 @@ AgentSettingsPage::AgentSettingsPage(DatabaseTabWidget* tabWidget) AgentSettingsPage::~AgentSettingsPage() { - } QString AgentSettingsPage::name() diff --git a/src/sshagent/AgentSettingsPage.h b/src/sshagent/AgentSettingsPage.h index f9d1be3f..1cd4d9a5 100644 --- a/src/sshagent/AgentSettingsPage.h +++ b/src/sshagent/AgentSettingsPage.h @@ -19,8 +19,8 @@ #ifndef AGENTSETTINGSPAGE_H #define AGENTSETTINGSPAGE_H -#include "gui/SettingsWidget.h" #include "gui/DatabaseTabWidget.h" +#include "gui/SettingsWidget.h" class AgentSettingsPage : public ISettingsPage { diff --git a/src/sshagent/AgentSettingsWidget.cpp b/src/sshagent/AgentSettingsWidget.cpp index 81b6808f..10a09f9d 100644 --- a/src/sshagent/AgentSettingsWidget.cpp +++ b/src/sshagent/AgentSettingsWidget.cpp @@ -17,8 +17,8 @@ */ #include "AgentSettingsWidget.h" -#include "ui_AgentSettingsWidget.h" #include "core/Config.h" +#include "ui_AgentSettingsWidget.h" AgentSettingsWidget::AgentSettingsWidget(QWidget* parent) : QWidget(parent) diff --git a/src/sshagent/AgentSettingsWidget.h b/src/sshagent/AgentSettingsWidget.h index 90d1b197..8667be65 100644 --- a/src/sshagent/AgentSettingsWidget.h +++ b/src/sshagent/AgentSettingsWidget.h @@ -19,10 +19,11 @@ #ifndef AGENTSETTINGSWIDGET_H #define AGENTSETTINGSWIDGET_H -#include #include +#include -namespace Ui { +namespace Ui +{ class AgentSettingsWidget; } diff --git a/src/sshagent/BinaryStream.cpp b/src/sshagent/BinaryStream.cpp index b9ed236f..2aa8ac1c 100644 --- a/src/sshagent/BinaryStream.cpp +++ b/src/sshagent/BinaryStream.cpp @@ -23,7 +23,6 @@ BinaryStream::BinaryStream(QObject* parent) : QObject(parent) , m_timeout(-1) { - } BinaryStream::BinaryStream(QIODevice* device) @@ -31,7 +30,6 @@ BinaryStream::BinaryStream(QIODevice* device) , m_timeout(-1) , m_device(device) { - } BinaryStream::BinaryStream(QByteArray* ba, QObject* parent) @@ -105,7 +103,7 @@ bool BinaryStream::read(QByteArray& ba) bool BinaryStream::read(quint32& i) { - if (read(reinterpret_cast(&i), sizeof(i))) { + if (read(reinterpret_cast(&i), sizeof(i))) { i = qFromBigEndian(i); return true; } @@ -115,7 +113,7 @@ bool BinaryStream::read(quint32& i) bool BinaryStream::read(quint16& i) { - if (read(reinterpret_cast(&i), sizeof(i))) { + if (read(reinterpret_cast(&i), sizeof(i))) { i = qFromBigEndian(i); return true; } @@ -125,24 +123,24 @@ bool BinaryStream::read(quint16& i) bool BinaryStream::read(quint8& i) { - return read(reinterpret_cast(&i), sizeof(i)); + return read(reinterpret_cast(&i), sizeof(i)); } bool BinaryStream::readString(QByteArray& ba) { - quint32 length; + quint32 length; - if (!read(length)) { - return false; - } + if (!read(length)) { + return false; + } - ba.resize(length); + ba.resize(length); - if (!read(ba.data(), ba.length())) { - return false; - } + if (!read(ba.data(), ba.length())) { + return false; + } - return true; + return true; } bool BinaryStream::readString(QString& str) @@ -157,7 +155,6 @@ bool BinaryStream::readString(QString& str) return true; } - bool BinaryStream::write(const char* ptr, qint64 size) { if (m_device->write(ptr, size) < 0) { @@ -186,18 +183,18 @@ bool BinaryStream::write(const QByteArray& ba) bool BinaryStream::write(quint32 i) { i = qToBigEndian(i); - return write(reinterpret_cast(&i), sizeof(i)); + return write(reinterpret_cast(&i), sizeof(i)); } bool BinaryStream::write(quint16 i) { i = qToBigEndian(i); - return write(reinterpret_cast(&i), sizeof(i)); + return write(reinterpret_cast(&i), sizeof(i)); } bool BinaryStream::write(quint8 i) { - return write(reinterpret_cast(&i), sizeof(i)); + return write(reinterpret_cast(&i), sizeof(i)); } bool BinaryStream::writeString(const QByteArray& ba) diff --git a/src/sshagent/BinaryStream.h b/src/sshagent/BinaryStream.h index c6101018..fa9ded81 100644 --- a/src/sshagent/BinaryStream.h +++ b/src/sshagent/BinaryStream.h @@ -19,9 +19,9 @@ #ifndef BINARYSTREAM_H #define BINARYSTREAM_H -#include -#include #include +#include +#include class BinaryStream : QObject { diff --git a/src/sshagent/KeeAgentSettings.cpp b/src/sshagent/KeeAgentSettings.cpp index 218e98ac..ac6a381b 100644 --- a/src/sshagent/KeeAgentSettings.cpp +++ b/src/sshagent/KeeAgentSettings.cpp @@ -30,13 +30,11 @@ KeeAgentSettings::KeeAgentSettings() , m_saveAttachmentToTempFile(false) , m_fileName(QString()) { - } bool KeeAgentSettings::operator==(KeeAgentSettings& other) { - return (m_allowUseOfSshKey == other.m_allowUseOfSshKey - && m_addAtDatabaseOpen == other.m_addAtDatabaseOpen + return (m_allowUseOfSshKey == other.m_allowUseOfSshKey && m_addAtDatabaseOpen == other.m_addAtDatabaseOpen && m_removeAtDatabaseClose == other.m_removeAtDatabaseClose && m_useConfirmConstraintWhenAdding == other.m_useConfirmConstraintWhenAdding && m_useLifetimeConstraintWhenAdding == other.m_useLifetimeConstraintWhenAdding diff --git a/src/sshagent/KeeAgentSettings.h b/src/sshagent/KeeAgentSettings.h index 4022750d..484dee88 100644 --- a/src/sshagent/KeeAgentSettings.h +++ b/src/sshagent/KeeAgentSettings.h @@ -19,8 +19,8 @@ #ifndef KEEAGENTSETTINGS_H #define KEEAGENTSETTINGS_H -#include #include +#include class KeeAgentSettings { @@ -31,7 +31,7 @@ public: bool operator!=(KeeAgentSettings& other); bool isDefault(); - bool fromXml(const QByteArray &ba); + bool fromXml(const QByteArray& ba); QByteArray toXml(); bool allowUseOfSshKey() const; diff --git a/src/sshagent/OpenSSHKey.cpp b/src/sshagent/OpenSSHKey.cpp index ccc7606f..c80708c0 100644 --- a/src/sshagent/OpenSSHKey.cpp +++ b/src/sshagent/OpenSSHKey.cpp @@ -18,10 +18,10 @@ #include "OpenSSHKey.h" #include "ASN1Key.h" +#include "crypto/SymmetricCipher.h" +#include #include #include -#include -#include "crypto/SymmetricCipher.h" const QString OpenSSHKey::TYPE_DSA = "DSA PRIVATE KEY"; const QString OpenSSHKey::TYPE_RSA = "RSA PRIVATE KEY"; @@ -30,7 +30,7 @@ const QString OpenSSHKey::TYPE_OPENSSH = "OPENSSH PRIVATE KEY"; // bcrypt_pbkdf.cpp int bcrypt_pbkdf(const QByteArray& pass, const QByteArray& salt, QByteArray& key, quint32 rounds); -OpenSSHKey::OpenSSHKey(QObject *parent) +OpenSSHKey::OpenSSHKey(QObject* parent) : QObject(parent) , m_type(QString()) , m_cipherName(QString("none")) @@ -43,7 +43,6 @@ OpenSSHKey::OpenSSHKey(QObject *parent) , m_comment(QString()) , m_error(QString()) { - } OpenSSHKey::OpenSSHKey(const OpenSSHKey& other) @@ -58,7 +57,6 @@ OpenSSHKey::OpenSSHKey(const OpenSSHKey& other) , m_comment(other.m_comment) , m_error(other.m_error) { - } bool OpenSSHKey::operator==(const OpenSSHKey& other) const diff --git a/src/sshagent/OpenSSHKey.h b/src/sshagent/OpenSSHKey.h index e06af220..cd162796 100644 --- a/src/sshagent/OpenSSHKey.h +++ b/src/sshagent/OpenSSHKey.h @@ -19,8 +19,8 @@ #ifndef OPENSSHKEY_H #define OPENSSHKEY_H -#include #include "BinaryStream.h" +#include class OpenSSHKey : QObject { diff --git a/src/sshagent/SSHAgent.cpp b/src/sshagent/SSHAgent.cpp index 973e0305..e8639f5d 100644 --- a/src/sshagent/SSHAgent.cpp +++ b/src/sshagent/SSHAgent.cpp @@ -28,7 +28,8 @@ SSHAgent* SSHAgent::m_instance; -SSHAgent::SSHAgent(QObject* parent) : QObject(parent) +SSHAgent::SSHAgent(QObject* parent) + : QObject(parent) { #ifndef Q_OS_WIN m_socketPath = QProcessEnvironment::systemEnvironment().value("SSH_AUTH_SOCK"); @@ -108,7 +109,8 @@ bool SSHAgent::sendMessage(const QByteArray& in, QByteArray& out) return false; } - QByteArray mapName = (QString("SSHAgentRequest") + reinterpret_cast(QThread::currentThreadId())).toLatin1(); + QByteArray mapName = + (QString("SSHAgentRequest") + reinterpret_cast(QThread::currentThreadId())).toLatin1(); HANDLE handle = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, AGENT_MAX_MSGLEN, mapName.data()); @@ -125,8 +127,8 @@ bool SSHAgent::sendMessage(const QByteArray& in, QByteArray& out) return false; } - quint32 *requestLength = reinterpret_cast(ptr); - void *requestData = reinterpret_cast(reinterpret_cast(ptr) + 4); + quint32* requestLength = reinterpret_cast(ptr); + void* requestData = reinterpret_cast(reinterpret_cast(ptr) + 4); *requestLength = qToBigEndian(in.length()); memcpy(requestData, in.data(), in.length()); @@ -157,7 +159,6 @@ bool SSHAgent::sendMessage(const QByteArray& in, QByteArray& out) #endif } - bool SSHAgent::addIdentity(OpenSSHKey& key, quint32 lifetime, bool confirm) { if (!isAgentRunning()) { @@ -186,8 +187,8 @@ bool SSHAgent::addIdentity(OpenSSHKey& key, quint32 lifetime, bool confirm) } if (responseData.length() < 1 || static_cast(responseData[0]) != SSH_AGENT_SUCCESS) { - m_error = tr("Agent refused this identity. Possible reasons include:") - + "\n" + tr("The key has already been added."); + m_error = + tr("Agent refused this identity. Possible reasons include:") + "\n" + tr("The key has already been added."); if (lifetime > 0) { m_error += "\n" + tr("Restricted lifetime is not supported by the agent (check options)."); diff --git a/src/sshagent/SSHAgent.h b/src/sshagent/SSHAgent.h index adb08cad..b12f32b2 100644 --- a/src/sshagent/SSHAgent.h +++ b/src/sshagent/SSHAgent.h @@ -19,9 +19,9 @@ #ifndef AGENTCLIENT_H #define AGENTCLIENT_H -#include -#include #include "OpenSSHKey.h" +#include +#include #include "gui/DatabaseWidget.h" @@ -46,16 +46,16 @@ public slots: void databaseModeChanged(DatabaseWidget::Mode mode = DatabaseWidget::LockedMode); private: - const quint8 SSH_AGENT_FAILURE = 5; - const quint8 SSH_AGENT_SUCCESS = 6; - const quint8 SSH_AGENTC_REQUEST_IDENTITIES = 11; - const quint8 SSH_AGENT_IDENTITIES_ANSWER = 12; - const quint8 SSH_AGENTC_ADD_IDENTITY = 17; - const quint8 SSH_AGENTC_REMOVE_IDENTITY = 18; - const quint8 SSH_AGENTC_ADD_ID_CONSTRAINED = 25; + const quint8 SSH_AGENT_FAILURE = 5; + const quint8 SSH_AGENT_SUCCESS = 6; + const quint8 SSH_AGENTC_REQUEST_IDENTITIES = 11; + const quint8 SSH_AGENT_IDENTITIES_ANSWER = 12; + const quint8 SSH_AGENTC_ADD_IDENTITY = 17; + const quint8 SSH_AGENTC_REMOVE_IDENTITY = 18; + const quint8 SSH_AGENTC_ADD_ID_CONSTRAINED = 25; - const quint8 SSH_AGENT_CONSTRAIN_LIFETIME = 1; - const quint8 SSH_AGENT_CONSTRAIN_CONFIRM = 2; + const quint8 SSH_AGENT_CONSTRAIN_LIFETIME = 1; + const quint8 SSH_AGENT_CONSTRAIN_CONFIRM = 2; explicit SSHAgent(QObject* parent = nullptr); ~SSHAgent(); diff --git a/src/sshagent/includes.h b/src/sshagent/includes.h index c6bb4d32..23b4aeeb 100644 --- a/src/sshagent/includes.h +++ b/src/sshagent/includes.h @@ -8,7 +8,6 @@ #endif #include - #ifdef _WIN32 #include @@ -16,5 +15,5 @@ typedef uint32_t u_int32_t; typedef uint16_t u_int16_t; typedef uint8_t u_int8_t; -#define bzero(p,s) memset(p, 0, s) +#define bzero(p, s) memset(p, 0, s) #endif diff --git a/src/streams/HashedBlockStream.cpp b/src/streams/HashedBlockStream.cpp index dd323a6d..753bdecc 100644 --- a/src/streams/HashedBlockStream.cpp +++ b/src/streams/HashedBlockStream.cpp @@ -26,7 +26,7 @@ const QSysInfo::Endian HashedBlockStream::ByteOrder = QSysInfo::LittleEndian; HashedBlockStream::HashedBlockStream(QIODevice* baseDevice) : LayeredStream(baseDevice) - , m_blockSize(1024*1024) + , m_blockSize(1024 * 1024) { init(); } @@ -94,8 +94,7 @@ qint64 HashedBlockStream::readData(char* data, qint64 maxSize) { if (m_error) { return -1; - } - else if (m_eof) { + } else if (m_eof) { return 0; } @@ -107,8 +106,7 @@ qint64 HashedBlockStream::readData(char* data, qint64 maxSize) if (!readHashedBlock()) { if (m_error) { return -1; - } - else { + } else { return maxSize - bytesRemaining; } } @@ -204,8 +202,7 @@ qint64 HashedBlockStream::writeData(const char* data, qint64 maxSize) if (!writeHashedBlock()) { if (m_error) { return -1; - } - else { + } else { return maxSize - bytesRemaining; } } @@ -227,8 +224,7 @@ bool HashedBlockStream::writeHashedBlock() QByteArray hash; if (!m_buffer.isEmpty()) { hash = CryptoHash::hash(m_buffer, CryptoHash::Sha256); - } - else { + } else { hash.fill(0, 32); } @@ -257,6 +253,7 @@ bool HashedBlockStream::writeHashedBlock() return true; } -bool HashedBlockStream::atEnd() const { +bool HashedBlockStream::atEnd() const +{ return m_eof; } diff --git a/src/streams/HmacBlockStream.h b/src/streams/HmacBlockStream.h index 592cf844..c10c9674 100644 --- a/src/streams/HmacBlockStream.h +++ b/src/streams/HmacBlockStream.h @@ -22,9 +22,9 @@ #include "streams/LayeredStream.h" -class HmacBlockStream: public LayeredStream +class HmacBlockStream : public LayeredStream { -Q_OBJECT + Q_OBJECT public: explicit HmacBlockStream(QIODevice* baseDevice, QByteArray key); diff --git a/src/streams/LayeredStream.cpp b/src/streams/LayeredStream.cpp index 9f7783bd..9b154585 100644 --- a/src/streams/LayeredStream.cpp +++ b/src/streams/LayeredStream.cpp @@ -47,17 +47,13 @@ bool LayeredStream::open(QIODevice::OpenMode mode) if (readMode && writeMode) { qWarning("LayeredStream::open: Reading and writing at the same time is not supported."); return false; - } - else if (!readMode && !writeMode) { + } else if (!readMode && !writeMode) { qWarning("LayeredStream::open: Must be opened in read or write mode."); return false; - } - else if ((readMode && !m_baseDevice->isReadable()) || - (writeMode && !m_baseDevice->isWritable())) { + } else if ((readMode && !m_baseDevice->isReadable()) || (writeMode && !m_baseDevice->isWritable())) { qWarning("LayeredStream::open: Base device is not opened correctly."); return false; - } - else { + } else { if (mode & QIODevice::Append) { qWarning("LayeredStream::open: QIODevice::Append is not supported."); mode = mode & ~QIODevice::Append; diff --git a/src/streams/SymmetricCipherStream.cpp b/src/streams/SymmetricCipherStream.cpp index 78476c61..f6957622 100644 --- a/src/streams/SymmetricCipherStream.cpp +++ b/src/streams/SymmetricCipherStream.cpp @@ -17,8 +17,10 @@ #include "SymmetricCipherStream.h" -SymmetricCipherStream::SymmetricCipherStream(QIODevice* baseDevice, SymmetricCipher::Algorithm algo, - SymmetricCipher::Mode mode, SymmetricCipher::Direction direction) +SymmetricCipherStream::SymmetricCipherStream(QIODevice* baseDevice, + SymmetricCipher::Algorithm algo, + SymmetricCipher::Mode mode, + SymmetricCipher::Direction direction) : LayeredStream(baseDevice) , m_cipher(new SymmetricCipher(algo, mode, direction)) , m_bufferPos(0) @@ -57,7 +59,6 @@ void SymmetricCipherStream::resetInternalState() bool SymmetricCipherStream::open(QIODevice::OpenMode mode) { return m_isInitialized && LayeredStream::open(mode); - } bool SymmetricCipherStream::reset() @@ -100,8 +101,7 @@ qint64 SymmetricCipherStream::readData(char* data, qint64 maxSize) if (!readBlock()) { if (m_error) { return -1; - } - else { + } else { return maxSize - bytesRemaining; } } @@ -125,8 +125,7 @@ bool SymmetricCipherStream::readBlock() if (m_bufferFilling) { newData.resize(blockSize() - m_buffer.size()); - } - else { + } else { m_buffer.clear(); newData.resize(blockSize()); } @@ -144,8 +143,7 @@ bool SymmetricCipherStream::readBlock() if (!m_streamCipher && m_buffer.size() != blockSize()) { m_bufferFilling = true; return false; - } - else { + } else { if (!m_cipher->processInPlace(m_buffer)) { m_error = true; setErrorString(m_cipher->errorString()); @@ -178,8 +176,7 @@ bool SymmetricCipherStream::readBlock() } else { return m_buffer.size() > 0; } - } - else { + } else { return true; } } @@ -209,8 +206,7 @@ qint64 SymmetricCipherStream::writeData(const char* data, qint64 maxSize) if (!writeBlock(false)) { if (m_error) { return -1; - } - else { + } else { return maxSize - bytesRemaining; } } @@ -242,14 +238,14 @@ bool SymmetricCipherStream::writeBlock(bool lastBlock) m_error = true; setErrorString(m_baseDevice->errorString()); return false; - } - else { + } else { m_buffer.clear(); return true; } } -int SymmetricCipherStream::blockSize() const { +int SymmetricCipherStream::blockSize() const +{ if (m_streamCipher) { return 1024; } diff --git a/src/streams/SymmetricCipherStream.h b/src/streams/SymmetricCipherStream.h index b68dba01..4f8feaa3 100644 --- a/src/streams/SymmetricCipherStream.h +++ b/src/streams/SymmetricCipherStream.h @@ -29,8 +29,10 @@ class SymmetricCipherStream : public LayeredStream Q_OBJECT public: - SymmetricCipherStream(QIODevice* baseDevice, SymmetricCipher::Algorithm algo, - SymmetricCipher::Mode mode, SymmetricCipher::Direction direction); + SymmetricCipherStream(QIODevice* baseDevice, + SymmetricCipher::Algorithm algo, + SymmetricCipher::Mode mode, + SymmetricCipher::Direction direction); ~SymmetricCipherStream(); bool init(const QByteArray& key, const QByteArray& iv); bool open(QIODevice::OpenMode mode) override; diff --git a/src/totp/totp.cpp b/src/totp/totp.cpp index f102335a..d187bd0f 100644 --- a/src/totp/totp.cpp +++ b/src/totp/totp.cpp @@ -40,9 +40,9 @@ const quint8 Totp::defaultDigits = 6; */ const quint8 Totp::ENCODER_STEAM = 254; -const Totp::Encoder Totp::defaultEncoder = { "", "", "0123456789", 0, 0, false }; +const Totp::Encoder Totp::defaultEncoder = {"", "", "0123456789", 0, 0, false}; const QMap Totp::encoders{ - { Totp::ENCODER_STEAM, { "steam", "S", "23456789BCDFGHJKMNPQRTVWXY", 5, 30, true } }, + {Totp::ENCODER_STEAM, {"steam", "S", "23456789BCDFGHJKMNPQRTVWXY", 5, 30, true}}, }; /** @@ -53,7 +53,7 @@ const QMap Totp::encoders{ * in Entry::totpSeed() */ const QMap Totp::shortNameToEncoder{ - { "S", Totp::ENCODER_STEAM }, + {"S", Totp::ENCODER_STEAM}, }; /** * These map the "encoder=" URL parameter of the "otp" field to our internal encoder number @@ -61,7 +61,7 @@ const QMap Totp::shortNameToEncoder{ * in the corresponding Encoder */ const QMap Totp::nameToEncoder{ - { "steam", Totp::ENCODER_STEAM }, + {"steam", Totp::ENCODER_STEAM}, }; Totp::Totp() @@ -129,9 +129,9 @@ QString Totp::parseOtpString(QString key, quint8& digits, quint8& step) } QString Totp::generateTotp(const QByteArray key, - quint64 time, - const quint8 numDigits = defaultDigits, - const quint8 step = defaultStep) + quint64 time, + const quint8 numDigits = defaultDigits, + const quint8 step = defaultStep) { quint64 current = qToBigEndian(time / step); @@ -177,12 +177,12 @@ QString Totp::generateTotp(const QByteArray key, // See: https://github.com/google/google-authenticator/wiki/Key-Uri-Format QUrl Totp::generateOtpString(const QString& secret, - const QString& type, - const QString& issuer, - const QString& username, - const QString& algorithm, - quint8 digits, - quint8 step) + const QString& type, + const QString& issuer, + const QString& username, + const QString& algorithm, + quint8 digits, + quint8 step) { QUrl keyUri; keyUri.setScheme("otpauth"); diff --git a/src/totp/totp.h b/src/totp/totp.h index 7d4c78c1..1c159e29 100644 --- a/src/totp/totp.h +++ b/src/totp/totp.h @@ -19,9 +19,9 @@ #ifndef QTOTP_H #define QTOTP_H -#include -#include #include +#include +#include class QUrl; diff --git a/tests/FailDevice.cpp b/tests/FailDevice.cpp index 5a25db28..33e000cf 100644 --- a/tests/FailDevice.cpp +++ b/tests/FailDevice.cpp @@ -35,8 +35,7 @@ qint64 FailDevice::readData(char* data, qint64 len) if (m_readCount >= m_failAfter) { setErrorString("FAILDEVICE"); return -1; - } - else { + } else { qint64 result = QBuffer::readData(data, len); if (result != -1) { m_readCount += result; @@ -51,8 +50,7 @@ qint64 FailDevice::writeData(const char* data, qint64 len) if (m_writeCount >= m_failAfter) { setErrorString("FAILDEVICE"); return -1; - } - else { + } else { qint64 result = QBuffer::writeData(data, len); if (result != -1) { m_writeCount += result; diff --git a/tests/TestAutoType.cpp b/tests/TestAutoType.cpp index 5eaed66a..f59625d8 100644 --- a/tests/TestAutoType.cpp +++ b/tests/TestAutoType.cpp @@ -21,12 +21,12 @@ #include -#include "core/Config.h" -#include "core/FilePath.h" -#include "crypto/Crypto.h" #include "autotype/AutoType.h" #include "autotype/AutoTypePlatformPlugin.h" #include "autotype/test/AutoTypeTestInterface.h" +#include "core/Config.h" +#include "core/FilePath.h" +#include "crypto/Crypto.h" #include "gui/MessageBox.h" QTEST_GUILESS_MAIN(TestAutoType) @@ -94,10 +94,10 @@ void TestAutoType::init() m_entry4 = new Entry(); m_entry4->setGroup(m_group); m_entry4->setPassword("custom_attr"); - m_entry4->attributes()->set("CUSTOM","Attribute",false); - m_entry4->attributes()->set("CustomAttrFirst","AttrValueFirst",false); - m_entry4->attributes()->set("CustomAttrSecond","AttrValueSecond",false); - m_entry4->attributes()->set("CustomAttrThird","AttrValueThird",false); + m_entry4->attributes()->set("CUSTOM", "Attribute", false); + m_entry4->attributes()->set("CustomAttrFirst", "AttrValueFirst", false); + m_entry4->attributes()->set("CustomAttrSecond", "AttrValueSecond", false); + m_entry4->attributes()->set("CustomAttrThird", "AttrValueThird", false); association.window = "//^CustomAttr1$//"; association.sequence = "{PASSWORD}:{S:CUSTOM}"; m_entry4->autoTypeAssociations()->add(association); @@ -143,9 +143,7 @@ void TestAutoType::testSingleAutoType() QCOMPARE(m_test->actionCount(), 14); QCOMPARE(m_test->actionChars(), - QString("myuser%1mypass%2") - .arg(m_test->keyToString(Qt::Key_Tab)) - .arg(m_test->keyToString(Qt::Key_Enter))); + QString("myuser%1mypass%2").arg(m_test->keyToString(Qt::Key_Tab)).arg(m_test->keyToString(Qt::Key_Enter))); } void TestAutoType::testGlobalAutoTypeWithNoMatch() @@ -162,10 +160,7 @@ void TestAutoType::testGlobalAutoTypeWithOneMatch() m_test->setActiveWindowTitle("custom window"); m_autoType->performGlobalAutoType(m_dbList); - QCOMPARE(m_test->actionChars(), - QString("%1association%2") - .arg(m_entry1->username()) - .arg(m_entry1->password())); + QCOMPARE(m_test->actionChars(), QString("%1association%2").arg(m_entry1->username()).arg(m_entry1->password())); } void TestAutoType::testGlobalAutoTypeTitleMatch() @@ -175,8 +170,7 @@ void TestAutoType::testGlobalAutoTypeTitleMatch() m_test->setActiveWindowTitle("An Entry Title!"); m_autoType->performGlobalAutoType(m_dbList); - QCOMPARE(m_test->actionChars(), - QString("%1%2").arg(m_entry2->password(), m_test->keyToString(Qt::Key_Enter))); + QCOMPARE(m_test->actionChars(), QString("%1%2").arg(m_entry2->password(), m_test->keyToString(Qt::Key_Enter))); } void TestAutoType::testGlobalAutoTypeUrlMatch() @@ -186,8 +180,7 @@ void TestAutoType::testGlobalAutoTypeUrlMatch() m_test->setActiveWindowTitle("Dummy - http://example.org/ - "); m_autoType->performGlobalAutoType(m_dbList); - QCOMPARE(m_test->actionChars(), - QString("%1%2").arg(m_entry5->password(), m_test->keyToString(Qt::Key_Enter))); + QCOMPARE(m_test->actionChars(), QString("%1%2").arg(m_entry5->password(), m_test->keyToString(Qt::Key_Enter))); } void TestAutoType::testGlobalAutoTypeUrlSubdomainMatch() @@ -197,8 +190,7 @@ void TestAutoType::testGlobalAutoTypeUrlSubdomainMatch() m_test->setActiveWindowTitle("Dummy - http://sub.example.org/ - "); m_autoType->performGlobalAutoType(m_dbList); - QCOMPARE(m_test->actionChars(), - QString("%1%2").arg(m_entry5->password(), m_test->keyToString(Qt::Key_Enter))); + QCOMPARE(m_test->actionChars(), QString("%1%2").arg(m_entry5->password(), m_test->keyToString(Qt::Key_Enter))); } void TestAutoType::testGlobalAutoTypeTitleMatchDisabled() @@ -274,7 +266,8 @@ void TestAutoType::testGlobalAutoTypeRegExp() void TestAutoType::testAutoTypeSyntaxChecks() { // Huge sequence - QVERIFY(AutoType::checkSyntax("{word 23}{F1 23}{~ 23}{% 23}{^}{F12}{(}{) 23}{[}{[}{]}{Delay=23}{+}{SUBTRACT}~+%@fixedstring")); + QVERIFY(AutoType::checkSyntax( + "{word 23}{F1 23}{~ 23}{% 23}{^}{F12}{(}{) 23}{[}{[}{]}{Delay=23}{+}{SUBTRACT}~+%@fixedstring")); QVERIFY(AutoType::checkSyntax("{NUMPAD1 3}")); @@ -327,7 +320,7 @@ void TestAutoType::testAutoTypeEffectiveSequences() QPointer group1 = new Group(); group1->setParent(rootGroup); group1->setDefaultAutoTypeSequence(sequenceG1); - + // Child group with inherit QPointer group2 = new Group(); group2->setParent(group1); diff --git a/tests/TestCryptoHash.cpp b/tests/TestCryptoHash.cpp index 914bcf19..ac6cd7c7 100644 --- a/tests/TestCryptoHash.cpp +++ b/tests/TestCryptoHash.cpp @@ -46,14 +46,17 @@ void TestCryptoHash::test() CryptoHash cryptoHash2(CryptoHash::Sha512); QCOMPARE(cryptoHash2.result(), - QByteArray::fromHex("cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e")); + QByteArray::fromHex("cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff831" + "8d2877eec2f63b931bd47417a81a538327af927da3e")); QByteArray result3 = CryptoHash::hash(source2, CryptoHash::Sha512); - QCOMPARE(result3, QByteArray::fromHex("0d41b612584ed39ff72944c29494573e40f4bb95283455fae2e0be1e3565aa9f48057d59e6ffd777970e282871c25a549a2763e5b724794f312c97021c42f91d")); + QCOMPARE(result3, QByteArray::fromHex("0d41b612584ed39ff72944c29494573e40f4bb95283455fae2e0be1e3565aa9f48057d59e6ff" + "d777970e282871c25a549a2763e5b724794f312c97021c42f91d")); CryptoHash cryptoHash4(CryptoHash::Sha512); cryptoHash4.addData(QString("KeePa").toLatin1()); cryptoHash4.addData(QString("ssX").toLatin1()); QCOMPARE(cryptoHash4.result(), - QByteArray::fromHex("0d41b612584ed39ff72944c29494573e40f4bb95283455fae2e0be1e3565aa9f48057d59e6ffd777970e282871c25a549a2763e5b724794f312c97021c42f91d")); + QByteArray::fromHex("0d41b612584ed39ff72944c29494573e40f4bb95283455fae2e0be1e3565aa9f48057d59e6ffd777970e2" + "82871c25a549a2763e5b724794f312c97021c42f91d")); } diff --git a/tests/TestCsvExporter.cpp b/tests/TestCsvExporter.cpp index b85dbf26..732e2636 100644 --- a/tests/TestCsvExporter.cpp +++ b/tests/TestCsvExporter.cpp @@ -26,7 +26,8 @@ QTEST_GUILESS_MAIN(TestCsvExporter) -const QString TestCsvExporter::ExpectedHeaderLine = QString("\"Group\",\"Title\",\"Username\",\"Password\",\"URL\",\"Notes\"\n"); +const QString TestCsvExporter::ExpectedHeaderLine = + QString("\"Group\",\"Title\",\"Username\",\"Password\",\"URL\",\"Notes\"\n"); void TestCsvExporter::init() { @@ -63,7 +64,9 @@ void TestCsvExporter::testExport() QVERIFY(buffer.open(QIODevice::ReadWrite)); m_csvExporter->exportDatabase(&buffer, m_db); - QString expectedResult = QString().append(ExpectedHeaderLine).append("\"Test Group Name\",\"Test Entry Title\",\"Test Username\",\"Test Password\",\"http://test.url\",\"Test Notes\"\n"); + QString expectedResult = + QString().append(ExpectedHeaderLine).append("\"Test Group Name\",\"Test Entry Title\",\"Test Username\",\"Test " + "Password\",\"http://test.url\",\"Test Notes\"\n"); QCOMPARE(QString::fromUtf8(buffer.buffer().constData()), expectedResult); } @@ -94,5 +97,8 @@ void TestCsvExporter::testNestedGroups() QVERIFY(buffer.open(QIODevice::ReadWrite)); m_csvExporter->exportDatabase(&buffer, m_db); - QCOMPARE(QString::fromUtf8(buffer.buffer().constData()), QString().append(ExpectedHeaderLine).append("\"Test Group Name/Test Sub Group Name\",\"Test Entry Title\",\"\",\"\",\"\",\"\"\n")); + QCOMPARE(QString::fromUtf8(buffer.buffer().constData()), + QString() + .append(ExpectedHeaderLine) + .append("\"Test Group Name/Test Sub Group Name\",\"Test Entry Title\",\"\",\"\",\"\",\"\"\n")); } diff --git a/tests/TestCsvParser.cpp b/tests/TestCsvParser.cpp index 705ef48c..46d25409 100644 --- a/tests/TestCsvParser.cpp +++ b/tests/TestCsvParser.cpp @@ -44,7 +44,8 @@ void TestCsvParser::cleanup() } /****************** TEST CASES ******************/ -void TestCsvParser::testMissingQuote() { +void TestCsvParser::testMissingQuote() +{ parser->setTextQualifier(':'); QTextStream out(file.data()); out << "A,B\n:BM,1"; @@ -54,7 +55,8 @@ void TestCsvParser::testMissingQuote() { QWARN(parser->getStatus().toLatin1()); } -void TestCsvParser::testMalformed() { +void TestCsvParser::testMalformed() +{ parser->setTextQualifier(':'); QTextStream out(file.data()); out << "A,B,C\n:BM::,1,:2:"; @@ -64,11 +66,12 @@ void TestCsvParser::testMalformed() { QWARN(parser->getStatus().toLatin1()); } -void TestCsvParser::testBackslashSyntax() { +void TestCsvParser::testBackslashSyntax() +{ parser->setBackslashSyntax(true); parser->setTextQualifier(QChar('X')); QTextStream out(file.data()); - //attended result: one"\t\"wo + // attended result: one"\t\"wo out << "Xone\\\"\\\\t\\\\\\\"w\noX\n" << "X13X,X2\\X,X,\"\"3\"X\r" << "3,X\"4\"X,,\n" @@ -88,7 +91,8 @@ void TestCsvParser::testBackslashSyntax() { QVERIFY(t.size() == 4); } -void TestCsvParser::testQuoted() { +void TestCsvParser::testQuoted() +{ QTextStream out(file.data()); out << "ro,w,\"end, of \"\"\"\"\"\"row\"\"\"\"\"\n" << "2\n"; @@ -101,25 +105,28 @@ void TestCsvParser::testQuoted() { QVERIFY(t.size() == 2); } -void TestCsvParser::testEmptySimple() { +void TestCsvParser::testEmptySimple() +{ QTextStream out(file.data()); - out <<""; + out << ""; QVERIFY(parser->parse(file.data())); t = parser->getCsvTable(); QVERIFY(t.size() == 0); } -void TestCsvParser::testEmptyQuoted() { +void TestCsvParser::testEmptyQuoted() +{ QTextStream out(file.data()); - out <<"\"\""; + out << "\"\""; QVERIFY(parser->parse(file.data())); t = parser->getCsvTable(); QVERIFY(t.size() == 0); } -void TestCsvParser::testEmptyNewline() { +void TestCsvParser::testEmptyNewline() +{ QTextStream out(file.data()); - out <<"\"\n\""; + out << "\"\n\""; QVERIFY(parser->parse(file.data())); t = parser->getCsvTable(); QVERIFY(t.size() == 0); @@ -197,7 +204,8 @@ void TestCsvParser::testComments() QVERIFY(t.at(0).at(1) == "text #1!"); } -void TestCsvParser::testColumns() { +void TestCsvParser::testColumns() +{ QTextStream out(file.data()); out << "1,2\n" << ",,,,,,,,,a\n" @@ -207,7 +215,8 @@ void TestCsvParser::testColumns() { QVERIFY(parser->getCsvCols() == 10); } -void TestCsvParser::testSimple() { +void TestCsvParser::testSimple() +{ QTextStream out(file.data()); out << ",,2\r,2,3\n" << "A,,B\"\n" @@ -229,7 +238,8 @@ void TestCsvParser::testSimple() { QVERIFY(t.at(3).at(2) == ""); } -void TestCsvParser::testSeparator() { +void TestCsvParser::testSeparator() +{ parser->setFieldSeparator('\t'); QTextStream out(file.data()); out << "\t\t2\r\t2\t3\n" @@ -296,7 +306,8 @@ void TestCsvParser::testReparsing() QVERIFY(t.size() == 2); } -void TestCsvParser::testQualifier() { +void TestCsvParser::testQualifier() +{ parser->setTextQualifier(QChar('X')); QTextStream out(file.data()); out << "X1X,X2XX,X,\"\"3\"\"\"X\r" @@ -313,11 +324,12 @@ void TestCsvParser::testQualifier() { QVERIFY(t.at(1).at(3) == ""); } -void TestCsvParser::testUnicode() { - //QString m("Texte en fran\u00e7ais"); - //CORRECT QString g("\u20AC"); - //CORRECT QChar g(0x20AC); - //ERROR QChar g("\u20AC"); +void TestCsvParser::testUnicode() +{ + // QString m("Texte en fran\u00e7ais"); + // CORRECT QString g("\u20AC"); + // CORRECT QChar g(0x20AC); + // ERROR QChar g("\u20AC"); parser->setFieldSeparator(QChar('A')); QTextStream out(file.data()); out.setCodec("UTF-8"); diff --git a/tests/TestCsvParser.h b/tests/TestCsvParser.h index f8c327d6..9db09166 100644 --- a/tests/TestCsvParser.h +++ b/tests/TestCsvParser.h @@ -19,10 +19,10 @@ #ifndef KEEPASSX_TESTCSVPARSER_H #define KEEPASSX_TESTCSVPARSER_H -#include #include -#include +#include #include +#include #include "core/CsvParser.h" @@ -33,7 +33,6 @@ class TestCsvParser : public QObject Q_OBJECT public: - private slots: void init(); void cleanup(); diff --git a/tests/TestDatabase.cpp b/tests/TestDatabase.cpp index 4aae91dc..51304b1f 100644 --- a/tests/TestDatabase.cpp +++ b/tests/TestDatabase.cpp @@ -23,10 +23,10 @@ #include #include "config-keepassx-tests.h" -#include "crypto/Crypto.h" -#include "keys/PasswordKey.h" #include "core/Metadata.h" +#include "crypto/Crypto.h" #include "format/KeePass2Writer.h" +#include "keys/PasswordKey.h" QTEST_GUILESS_MAIN(TestDatabase) @@ -46,7 +46,7 @@ void TestDatabase::testEmptyRecycleBinOnDisabled() QSignalSpy spyModified(db, SIGNAL(modifiedImmediate())); db->emptyRecycleBin(); - //The database must be unmodified in this test after emptying the recycle bin. + // The database must be unmodified in this test after emptying the recycle bin. QCOMPARE(spyModified.count(), 0); delete db; @@ -63,7 +63,7 @@ void TestDatabase::testEmptyRecycleBinOnNotCreated() QSignalSpy spyModified(db, SIGNAL(modifiedImmediate())); db->emptyRecycleBin(); - //The database must be unmodified in this test after emptying the recycle bin. + // The database must be unmodified in this test after emptying the recycle bin. QCOMPARE(spyModified.count(), 0); delete db; @@ -80,7 +80,7 @@ void TestDatabase::testEmptyRecycleBinOnEmpty() QSignalSpy spyModified(db, SIGNAL(modifiedImmediate())); db->emptyRecycleBin(); - //The database must be unmodified in this test after emptying the recycle bin. + // The database must be unmodified in this test after emptying the recycle bin. QCOMPARE(spyModified.count(), 0); delete db; diff --git a/tests/TestDeletedObjects.cpp b/tests/TestDeletedObjects.cpp index ee9d8de2..50ff1845 100644 --- a/tests/TestDeletedObjects.cpp +++ b/tests/TestDeletedObjects.cpp @@ -18,10 +18,10 @@ #include "TestDeletedObjects.h" #include "TestGlobal.h" -#include "crypto/Crypto.h" -#include "format/KeePass2.h" -#include "format/KdbxXmlReader.h" #include "config-keepassx-tests.h" +#include "crypto/Crypto.h" +#include "format/KdbxXmlReader.h" +#include "format/KeePass2.h" QTEST_GUILESS_MAIN(TestDeletedObjects) @@ -42,7 +42,7 @@ void TestDeletedObjects::createAndDelete(Database* db, int delObjectsSize) g->setUuid(gUuid); delete g; QCOMPARE(db->deletedObjects().size(), ++delObjectsSize); - QCOMPARE(db->deletedObjects().at(delObjectsSize-1).uuid, gUuid); + QCOMPARE(db->deletedObjects().at(delObjectsSize - 1).uuid, gUuid); QCOMPARE(rootChildrenCount, root->children().size()); Group* g1 = new Group(); @@ -66,10 +66,10 @@ void TestDeletedObjects::createAndDelete(Database* db, int delObjectsSize) delObjectsSize += 4; QCOMPARE(db->deletedObjects().size(), delObjectsSize); - QCOMPARE(db->deletedObjects().at(delObjectsSize-4).uuid, e1Uuid); - QCOMPARE(db->deletedObjects().at(delObjectsSize-3).uuid, e2Uuid); - QCOMPARE(db->deletedObjects().at(delObjectsSize-2).uuid, g2Uuid); - QCOMPARE(db->deletedObjects().at(delObjectsSize-1).uuid, g1Uuid); + QCOMPARE(db->deletedObjects().at(delObjectsSize - 4).uuid, e1Uuid); + QCOMPARE(db->deletedObjects().at(delObjectsSize - 3).uuid, e2Uuid); + QCOMPARE(db->deletedObjects().at(delObjectsSize - 2).uuid, g2Uuid); + QCOMPARE(db->deletedObjects().at(delObjectsSize - 1).uuid, g1Uuid); QCOMPARE(rootChildrenCount, root->children().size()); Entry* e3 = new Entry(); @@ -80,7 +80,7 @@ void TestDeletedObjects::createAndDelete(Database* db, int delObjectsSize) delete e3; QCOMPARE(db->deletedObjects().size(), ++delObjectsSize); - QCOMPARE(db->deletedObjects().at(delObjectsSize-1).uuid, e3Uuid); + QCOMPARE(db->deletedObjects().at(delObjectsSize - 1).uuid, e3Uuid); QCOMPARE(rootChildrenCount, root->children().size()); } @@ -143,8 +143,8 @@ void TestDeletedObjects::testDatabaseChange() delObjectsSize += 2; QCOMPARE(db->deletedObjects().size(), delObjectsSize); QCOMPARE(db2->deletedObjects().size(), delObjectsSize2); - QCOMPARE(db->deletedObjects().at(delObjectsSize-2).uuid, e1Uuid); - QCOMPARE(db->deletedObjects().at(delObjectsSize-1).uuid, g1Uuid); + QCOMPARE(db->deletedObjects().at(delObjectsSize - 2).uuid, e1Uuid); + QCOMPARE(db->deletedObjects().at(delObjectsSize - 1).uuid, g1Uuid); Group* group = new Group(); Entry* entry = new Entry(); diff --git a/tests/TestEntry.cpp b/tests/TestEntry.cpp index c088fc01..6ece366b 100644 --- a/tests/TestEntry.cpp +++ b/tests/TestEntry.cpp @@ -337,52 +337,78 @@ void TestEntry::testResolveReferencePlaceholders() tstEntry->setGroup(root); tstEntry->setUuid(Uuid::random()); - QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:T@I:%1}").arg(entry1->uuid().toHex())), entry1->title()); + QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:T@I:%1}").arg(entry1->uuid().toHex())), + entry1->title()); QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:T@T:%1}").arg(entry1->title())), entry1->title()); QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:T@U:%1}").arg(entry1->username())), entry1->title()); QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:T@P:%1}").arg(entry1->password())), entry1->title()); QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:T@A:%1}").arg(entry1->url())), entry1->title()); QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:T@N:%1}").arg(entry1->notes())), entry1->title()); - QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:T@O:%1}").arg(entry1->attributes()->value("CustomAttribute1"))), entry1->title()); + QCOMPARE(tstEntry->resolveMultiplePlaceholders( + QString("{REF:T@O:%1}").arg(entry1->attributes()->value("CustomAttribute1"))), + entry1->title()); - QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:T@I:%1}").arg(entry1->uuid().toHex())), entry1->title()); + QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:T@I:%1}").arg(entry1->uuid().toHex())), + entry1->title()); QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:T@T:%1}").arg(entry1->title())), entry1->title()); - QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:U@U:%1}").arg(entry1->username())), entry1->username()); - QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:P@P:%1}").arg(entry1->password())), entry1->password()); + QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:U@U:%1}").arg(entry1->username())), + entry1->username()); + QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:P@P:%1}").arg(entry1->password())), + entry1->password()); QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:A@A:%1}").arg(entry1->url())), entry1->url()); QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:N@N:%1}").arg(entry1->notes())), entry1->notes()); - QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:T@I:%1}").arg(entry2->uuid().toHex())), entry2->title()); + QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:T@I:%1}").arg(entry2->uuid().toHex())), + entry2->title()); QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:T@T:%1}").arg(entry2->title())), entry2->title()); QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:T@U:%1}").arg(entry2->username())), entry2->title()); QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:T@P:%1}").arg(entry2->password())), entry2->title()); QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:T@A:%1}").arg(entry2->url())), entry2->title()); QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:T@N:%1}").arg(entry2->notes())), entry2->title()); - QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:T@O:%1}").arg(entry2->attributes()->value("CustomAttribute2"))), entry2->title()); + QCOMPARE(tstEntry->resolveMultiplePlaceholders( + QString("{REF:T@O:%1}").arg(entry2->attributes()->value("CustomAttribute2"))), + entry2->title()); QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:T@T:%1}").arg(entry2->title())), entry2->title()); - QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:U@U:%1}").arg(entry2->username())), entry2->username()); - QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:P@P:%1}").arg(entry2->password())), entry2->password()); + QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:U@U:%1}").arg(entry2->username())), + entry2->username()); + QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:P@P:%1}").arg(entry2->password())), + entry2->password()); QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:A@A:%1}").arg(entry2->url())), entry2->url()); QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:N@N:%1}").arg(entry2->notes())), entry2->notes()); - QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:T@I:%1}").arg(entry3->uuid().toHex())), entry3->attributes()->value("AttributeTitle")); - QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:U@I:%1}").arg(entry3->uuid().toHex())), entry3->attributes()->value("AttributeUsername")); - QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:P@I:%1}").arg(entry3->uuid().toHex())), entry3->attributes()->value("AttributePassword")); - QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:A@I:%1}").arg(entry3->uuid().toHex())), entry3->attributes()->value("AttributeUrl")); - QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:N@I:%1}").arg(entry3->uuid().toHex())), entry3->attributes()->value("AttributeNotes")); + QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:T@I:%1}").arg(entry3->uuid().toHex())), + entry3->attributes()->value("AttributeTitle")); + QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:U@I:%1}").arg(entry3->uuid().toHex())), + entry3->attributes()->value("AttributeUsername")); + QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:P@I:%1}").arg(entry3->uuid().toHex())), + entry3->attributes()->value("AttributePassword")); + QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:A@I:%1}").arg(entry3->uuid().toHex())), + entry3->attributes()->value("AttributeUrl")); + QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:N@I:%1}").arg(entry3->uuid().toHex())), + entry3->attributes()->value("AttributeNotes")); - QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:T@I:%1}").arg(entry3->uuid().toHex().toUpper())), entry3->attributes()->value("AttributeTitle")); - QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:U@I:%1}").arg(entry3->uuid().toHex().toUpper())), entry3->attributes()->value("AttributeUsername")); - QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:P@I:%1}").arg(entry3->uuid().toHex().toUpper())), entry3->attributes()->value("AttributePassword")); - QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:A@I:%1}").arg(entry3->uuid().toHex().toUpper())), entry3->attributes()->value("AttributeUrl")); - QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:N@I:%1}").arg(entry3->uuid().toHex().toUpper())), entry3->attributes()->value("AttributeNotes")); + QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:T@I:%1}").arg(entry3->uuid().toHex().toUpper())), + entry3->attributes()->value("AttributeTitle")); + QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:U@I:%1}").arg(entry3->uuid().toHex().toUpper())), + entry3->attributes()->value("AttributeUsername")); + QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:P@I:%1}").arg(entry3->uuid().toHex().toUpper())), + entry3->attributes()->value("AttributePassword")); + QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:A@I:%1}").arg(entry3->uuid().toHex().toUpper())), + entry3->attributes()->value("AttributeUrl")); + QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:N@I:%1}").arg(entry3->uuid().toHex().toUpper())), + entry3->attributes()->value("AttributeNotes")); - QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:t@i:%1}").arg(entry3->uuid().toHex().toLower())), entry3->attributes()->value("AttributeTitle")); - QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:u@i:%1}").arg(entry3->uuid().toHex().toLower())), entry3->attributes()->value("AttributeUsername")); - QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:p@i:%1}").arg(entry3->uuid().toHex().toLower())), entry3->attributes()->value("AttributePassword")); - QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:a@i:%1}").arg(entry3->uuid().toHex().toLower())), entry3->attributes()->value("AttributeUrl")); - QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:n@i:%1}").arg(entry3->uuid().toHex().toLower())), entry3->attributes()->value("AttributeNotes")); + QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:t@i:%1}").arg(entry3->uuid().toHex().toLower())), + entry3->attributes()->value("AttributeTitle")); + QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:u@i:%1}").arg(entry3->uuid().toHex().toLower())), + entry3->attributes()->value("AttributeUsername")); + QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:p@i:%1}").arg(entry3->uuid().toHex().toLower())), + entry3->attributes()->value("AttributePassword")); + QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:a@i:%1}").arg(entry3->uuid().toHex().toLower())), + entry3->attributes()->value("AttributeUrl")); + QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:n@i:%1}").arg(entry3->uuid().toHex().toLower())), + entry3->attributes()->value("AttributeNotes")); } void TestEntry::testResolveNonIdPlaceholdersToUuid() @@ -420,37 +446,36 @@ void TestEntry::testResolveNonIdPlaceholdersToUuid() const Entry* referencedEntry = nullptr; QString newEntryNotesRaw("{REF:I@%1:%2}"); - switch(searchIn.toLatin1()) { - case 'T': - referencedEntry = referencedEntryTitle; - newEntryNotesRaw = newEntryNotesRaw.arg(searchIn, referencedEntry->title()); - break; - case 'U': - referencedEntry = referencedEntryUsername; - newEntryNotesRaw = newEntryNotesRaw.arg(searchIn, referencedEntry->username()); - break; - case 'P': - referencedEntry = referencedEntryPassword; - newEntryNotesRaw = newEntryNotesRaw.arg(searchIn, referencedEntry->password()); - break; - case 'A': - referencedEntry = referencedEntryUrl; - newEntryNotesRaw = newEntryNotesRaw.arg(searchIn, referencedEntry->url()); - break; - case 'N': - referencedEntry = referencedEntryNotes; - newEntryNotesRaw = newEntryNotesRaw.arg(searchIn, referencedEntry->notes()); - break; - default: - break; + switch (searchIn.toLatin1()) { + case 'T': + referencedEntry = referencedEntryTitle; + newEntryNotesRaw = newEntryNotesRaw.arg(searchIn, referencedEntry->title()); + break; + case 'U': + referencedEntry = referencedEntryUsername; + newEntryNotesRaw = newEntryNotesRaw.arg(searchIn, referencedEntry->username()); + break; + case 'P': + referencedEntry = referencedEntryPassword; + newEntryNotesRaw = newEntryNotesRaw.arg(searchIn, referencedEntry->password()); + break; + case 'A': + referencedEntry = referencedEntryUrl; + newEntryNotesRaw = newEntryNotesRaw.arg(searchIn, referencedEntry->url()); + break; + case 'N': + referencedEntry = referencedEntryNotes; + newEntryNotesRaw = newEntryNotesRaw.arg(searchIn, referencedEntry->notes()); + break; + default: + break; } auto* newEntry = new Entry(); newEntry->setGroup(root); newEntry->setNotes(newEntryNotesRaw); - const QString newEntryNotesResolved = - newEntry->resolveMultiplePlaceholders(newEntry->notes()); + const QString newEntryNotesResolved = newEntry->resolveMultiplePlaceholders(newEntry->notes()); QCOMPARE(newEntryNotesResolved, QString(referencedEntry->uuid().toHex())); } } diff --git a/tests/TestEntryModel.cpp b/tests/TestEntryModel.cpp index d290507f..6bc65db4 100644 --- a/tests/TestEntryModel.cpp +++ b/tests/TestEntryModel.cpp @@ -20,7 +20,6 @@ #include -#include "modeltest.h" #include "core/DatabaseIcons.h" #include "core/Entry.h" #include "core/Group.h" @@ -28,9 +27,10 @@ #include "gui/IconModels.h" #include "gui/SortFilterHideProxyModel.h" #include "gui/entry/AutoTypeAssociationsModel.h" -#include "gui/entry/EntryModel.h" #include "gui/entry/EntryAttachmentsModel.h" #include "gui/entry/EntryAttributesModel.h" +#include "gui/entry/EntryModel.h" +#include "modeltest.h" QTEST_GUILESS_MAIN(TestEntryModel) @@ -61,7 +61,7 @@ void TestEntryModel::test() QCOMPARE(model->rowCount(), 2); - QSignalSpy spyDataChanged(model, SIGNAL(dataChanged(QModelIndex,QModelIndex))); + QSignalSpy spyDataChanged(model, SIGNAL(dataChanged(QModelIndex, QModelIndex))); entry1->setTitle("changed"); QCOMPARE(spyDataChanged.count(), 1); @@ -71,10 +71,10 @@ void TestEntryModel::test() QCOMPARE(model->data(index1).toString(), entry1->title()); QCOMPARE(model->data(index2).toString(), entry2->title()); - QSignalSpy spyAboutToAdd(model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int))); - QSignalSpy spyAdded(model, SIGNAL(rowsInserted(QModelIndex,int,int))); - QSignalSpy spyAboutToRemove(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int))); - QSignalSpy spyRemoved(model, SIGNAL(rowsRemoved(QModelIndex,int,int))); + QSignalSpy spyAboutToAdd(model, SIGNAL(rowsAboutToBeInserted(QModelIndex, int, int))); + QSignalSpy spyAdded(model, SIGNAL(rowsInserted(QModelIndex, int, int))); + QSignalSpy spyAboutToRemove(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex, int, int))); + QSignalSpy spyRemoved(model, SIGNAL(rowsRemoved(QModelIndex, int, int))); Entry* entry3 = new Entry(); entry3->setGroup(group1); @@ -113,11 +113,11 @@ void TestEntryModel::testAttachmentsModel() model->setEntryAttachments(entryAttachments); QCOMPARE(model->rowCount(), 0); - QSignalSpy spyDataChanged(model, SIGNAL(dataChanged(QModelIndex,QModelIndex))); - QSignalSpy spyAboutToAdd(model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int))); - QSignalSpy spyAdded(model, SIGNAL(rowsInserted(QModelIndex,int,int))); - QSignalSpy spyAboutToRemove(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int))); - QSignalSpy spyRemoved(model, SIGNAL(rowsRemoved(QModelIndex,int,int))); + QSignalSpy spyDataChanged(model, SIGNAL(dataChanged(QModelIndex, QModelIndex))); + QSignalSpy spyAboutToAdd(model, SIGNAL(rowsAboutToBeInserted(QModelIndex, int, int))); + QSignalSpy spyAdded(model, SIGNAL(rowsInserted(QModelIndex, int, int))); + QSignalSpy spyAboutToRemove(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex, int, int))); + QSignalSpy spyRemoved(model, SIGNAL(rowsRemoved(QModelIndex, int, int))); entryAttachments->set("first", QByteArray("123")); @@ -158,11 +158,11 @@ void TestEntryModel::testAttributesModel() model->setEntryAttributes(entryAttributes); QCOMPARE(model->rowCount(), 0); - QSignalSpy spyDataChanged(model, SIGNAL(dataChanged(QModelIndex,QModelIndex))); - QSignalSpy spyAboutToAdd(model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int))); - QSignalSpy spyAdded(model, SIGNAL(rowsInserted(QModelIndex,int,int))); - QSignalSpy spyAboutToRemove(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int))); - QSignalSpy spyRemoved(model, SIGNAL(rowsRemoved(QModelIndex,int,int))); + QSignalSpy spyDataChanged(model, SIGNAL(dataChanged(QModelIndex, QModelIndex))); + QSignalSpy spyAboutToAdd(model, SIGNAL(rowsAboutToBeInserted(QModelIndex, int, int))); + QSignalSpy spyAdded(model, SIGNAL(rowsInserted(QModelIndex, int, int))); + QSignalSpy spyAboutToRemove(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex, int, int))); + QSignalSpy spyRemoved(model, SIGNAL(rowsRemoved(QModelIndex, int, int))); entryAttributes->set("first", "123"); @@ -294,7 +294,7 @@ void TestEntryModel::testProxyModel() * additional columns 'Password', 'Notes', 'Expires', 'Created', 'Modified', * 'Accessed', 'Paperclip' and 'Attachments' */ - QSignalSpy spyColumnRemove(modelProxy, SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int))); + QSignalSpy spyColumnRemove(modelProxy, SIGNAL(columnsAboutToBeRemoved(QModelIndex, int, int))); modelProxy->hideColumn(0, true); QCOMPARE(modelProxy->columnCount(), 11); QVERIFY(spyColumnRemove.size() >= 1); @@ -316,7 +316,7 @@ void TestEntryModel::testProxyModel() * additional columns 'Password', 'Notes', 'Expires', 'Created', 'Modified', * 'Accessed', 'Paperclip' and 'Attachments' */ - QSignalSpy spyColumnInsert(modelProxy, SIGNAL(columnsAboutToBeInserted(QModelIndex,int,int))); + QSignalSpy spyColumnInsert(modelProxy, SIGNAL(columnsAboutToBeInserted(QModelIndex, int, int))); modelProxy->hideColumn(0, false); QCOMPARE(modelProxy->columnCount(), 12); QVERIFY(spyColumnInsert.size() >= 1); diff --git a/tests/TestEntrySearcher.cpp b/tests/TestEntrySearcher.cpp index 25d83e4d..659f7a48 100644 --- a/tests/TestEntrySearcher.cpp +++ b/tests/TestEntrySearcher.cpp @@ -136,6 +136,7 @@ void TestEntrySearcher::testAllAttributesAreSearched() entry->setUrl("testUrl"); entry->setNotes("testNote"); - m_searchResult = m_entrySearcher.search("testTitle testUsername testUrl testNote", m_groupRoot, Qt::CaseInsensitive); + m_searchResult = + m_entrySearcher.search("testTitle testUsername testUrl testNote", m_groupRoot, Qt::CaseInsensitive); QCOMPARE(m_searchResult.count(), 1); } diff --git a/tests/TestEntrySearcher.h b/tests/TestEntrySearcher.h index 3965c22e..17d486c2 100644 --- a/tests/TestEntrySearcher.h +++ b/tests/TestEntrySearcher.h @@ -15,7 +15,6 @@ * along with this program. If not, see . */ - #ifndef KEEPASSX_TESTENTRYSEARCHER_H #define KEEPASSX_TESTENTRYSEARCHER_H diff --git a/tests/TestGlobal.h b/tests/TestGlobal.h index 017fbd5f..788bd8a1 100644 --- a/tests/TestGlobal.h +++ b/tests/TestGlobal.h @@ -18,52 +18,48 @@ #ifndef KEEPASSXC_TESTGLOBAL_H #define KEEPASSXC_TESTGLOBAL_H -#include "core/Uuid.h" #include "core/Group.h" +#include "core/Uuid.h" -#include #include +#include -namespace QTest { - -template<> -inline char* toString(const Uuid& uuid) +namespace QTest { - QByteArray ba = "Uuid("; - ba += uuid.toHex().toLatin1().constData(); - ba += ")"; - return qstrdup(ba.constData()); -} -template<> -inline char* toString(const Group::TriState& triState) -{ - QString value; - - if (triState == Group::Inherit) { - value = "null"; - } else if (triState == Group::Enable) { - value = "true"; - } else { - value = "false"; + template <> inline char* toString(const Uuid& uuid) + { + QByteArray ba = "Uuid("; + ba += uuid.toHex().toLatin1().constData(); + ba += ")"; + return qstrdup(ba.constData()); } - return qstrdup(value.toLocal8Bit().constData()); -} + template <> inline char* toString(const Group::TriState& triState) + { + QString value; -} // namespace QTest + if (triState == Group::Inherit) { + value = "null"; + } else if (triState == Group::Enable) { + value = "true"; + } else { + value = "false"; + } + return qstrdup(value.toLocal8Bit().constData()); + } -namespace Test { +} // namespace QTest -inline QDateTime datetime(int year, int month, int day, int hour, int min, int second) +namespace Test { - return QDateTime( - QDate(year, month, day), - QTime(hour, min, second), - Qt::UTC); -} -} // namespace Test + inline QDateTime datetime(int year, int month, int day, int hour, int min, int second) + { + return QDateTime(QDate(year, month, day), QTime(hour, min, second), Qt::UTC); + } -#endif //KEEPASSXC_TESTGLOBAL_H +} // namespace Test + +#endif // KEEPASSXC_TESTGLOBAL_H diff --git a/tests/TestGroup.cpp b/tests/TestGroup.cpp index d9eb2c76..0058c711 100644 --- a/tests/TestGroup.cpp +++ b/tests/TestGroup.cpp @@ -391,11 +391,12 @@ void TestGroup::testClone() // Making sure the new modification date is not the same. QTest::qSleep(1); - QScopedPointer clonedGroupResetTimeInfo(originalGroup->clone(Entry::CloneNoFlags, - Group::CloneNewUuid | Group::CloneResetTimeInfo)); + QScopedPointer clonedGroupResetTimeInfo( + originalGroup->clone(Entry::CloneNoFlags, Group::CloneNewUuid | Group::CloneResetTimeInfo)); QCOMPARE(clonedGroupResetTimeInfo->entries().size(), 0); QVERIFY(clonedGroupResetTimeInfo->uuid() != originalGroup->uuid()); - QVERIFY(clonedGroupResetTimeInfo->timeInfo().lastModificationTime() != originalGroup->timeInfo().lastModificationTime()); + QVERIFY(clonedGroupResetTimeInfo->timeInfo().lastModificationTime() + != originalGroup->timeInfo().lastModificationTime()); } void TestGroup::testCopyCustomIcons() diff --git a/tests/TestGroup.h b/tests/TestGroup.h index 11abfe12..f11cbf6f 100644 --- a/tests/TestGroup.h +++ b/tests/TestGroup.h @@ -19,8 +19,8 @@ #ifndef KEEPASSX_TESTGROUP_H #define KEEPASSX_TESTGROUP_H -#include #include "core/Database.h" +#include class TestGroup : public QObject { diff --git a/tests/TestGroupModel.cpp b/tests/TestGroupModel.cpp index f9f55e24..ecdc2405 100644 --- a/tests/TestGroupModel.cpp +++ b/tests/TestGroupModel.cpp @@ -20,9 +20,9 @@ #include -#include "modeltest.h" #include "crypto/Crypto.h" #include "gui/group/GroupModel.h" +#include "modeltest.h" QTEST_GUILESS_MAIN(TestGroupModel) @@ -76,18 +76,18 @@ void TestGroupModel::test() QCOMPARE(model->data(index12).toString(), QString("group12")); QCOMPARE(model->data(index121).toString(), QString("group121")); - QSignalSpy spy1(model, SIGNAL(dataChanged(QModelIndex,QModelIndex))); + QSignalSpy spy1(model, SIGNAL(dataChanged(QModelIndex, QModelIndex))); group11->setName("test"); group121->setIcon(4); QCOMPARE(spy1.count(), 2); QCOMPARE(model->data(index11).toString(), QString("test")); - QSignalSpy spyAboutToAdd(model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int))); - QSignalSpy spyAdded(model, SIGNAL(rowsInserted(QModelIndex,int,int))); - QSignalSpy spyAboutToRemove(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int))); - QSignalSpy spyRemoved(model, SIGNAL(rowsRemoved(QModelIndex,int,int))); - QSignalSpy spyAboutToMove(model, SIGNAL(rowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int))); - QSignalSpy spyMoved(model, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int))); + QSignalSpy spyAboutToAdd(model, SIGNAL(rowsAboutToBeInserted(QModelIndex, int, int))); + QSignalSpy spyAdded(model, SIGNAL(rowsInserted(QModelIndex, int, int))); + QSignalSpy spyAboutToRemove(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex, int, int))); + QSignalSpy spyRemoved(model, SIGNAL(rowsRemoved(QModelIndex, int, int))); + QSignalSpy spyAboutToMove(model, SIGNAL(rowsAboutToBeMoved(QModelIndex, int, int, QModelIndex, int))); + QSignalSpy spyMoved(model, SIGNAL(rowsMoved(QModelIndex, int, int, QModelIndex, int))); Group* group2 = new Group(); group2->setObjectName("group2"); diff --git a/tests/TestKdbx2.cpp b/tests/TestKdbx2.cpp index c0a0b307..76d5d81b 100644 --- a/tests/TestKdbx2.cpp +++ b/tests/TestKdbx2.cpp @@ -18,12 +18,12 @@ #include "TestKdbx2.h" #include "TestGlobal.h" +#include "config-keepassx-tests.h" +#include "core/Metadata.h" #include "crypto/Crypto.h" -#include "keys/PasswordKey.h" #include "format/KeePass2Reader.h" #include "format/KeePass2Writer.h" -#include "core/Metadata.h" -#include "config-keepassx-tests.h" +#include "keys/PasswordKey.h" #include diff --git a/tests/TestKdbx2.h b/tests/TestKdbx2.h index 9b5f5c5f..9eb0e415 100644 --- a/tests/TestKdbx2.h +++ b/tests/TestKdbx2.h @@ -24,7 +24,7 @@ class Database; class TestKdbx2 : public QObject { -Q_OBJECT + Q_OBJECT private slots: void initTestCase(); diff --git a/tests/TestKdbx3.cpp b/tests/TestKdbx3.cpp index 5312bcf0..6df13d38 100644 --- a/tests/TestKdbx3.cpp +++ b/tests/TestKdbx3.cpp @@ -18,16 +18,15 @@ #include "TestKdbx3.h" #include "TestGlobal.h" +#include "config-keepassx-tests.h" #include "core/Metadata.h" -#include "keys/PasswordKey.h" -#include "format/KeePass2.h" -#include "format/KeePass2Reader.h" -#include "format/KeePass2Writer.h" #include "format/KdbxXmlReader.h" #include "format/KdbxXmlWriter.h" +#include "format/KeePass2.h" +#include "format/KeePass2Reader.h" #include "format/KeePass2Repair.h" -#include "config-keepassx-tests.h" - +#include "format/KeePass2Writer.h" +#include "keys/PasswordKey.h" QTEST_GUILESS_MAIN(TestKdbx3) @@ -63,8 +62,11 @@ void TestKdbx3::writeXml(QBuffer* buf, Database* db, bool& hasError, QString& er errorString = writer.errorString(); } -void TestKdbx3::readKdbx(QIODevice* device, CompositeKey const& key, QScopedPointer& db, - bool& hasError, QString& errorString) +void TestKdbx3::readKdbx(QIODevice* device, + CompositeKey const& key, + QScopedPointer& db, + bool& hasError, + QString& errorString) { KeePass2Reader reader; db.reset(reader.readDatabase(device, key)); @@ -75,8 +77,11 @@ void TestKdbx3::readKdbx(QIODevice* device, CompositeKey const& key, QScopedPoin QCOMPARE(reader.version(), KeePass2::FILE_VERSION_3_1 & KeePass2::FILE_VERSION_CRITICAL_MASK); } -void TestKdbx3::readKdbx(const QString& path, CompositeKey const& key, QScopedPointer& db, - bool& hasError, QString& errorString) +void TestKdbx3::readKdbx(const QString& path, + CompositeKey const& key, + QScopedPointer& db, + bool& hasError, + QString& errorString) { KeePass2Reader reader; db.reset(reader.readDatabase(path, key)); diff --git a/tests/TestKdbx3.h b/tests/TestKdbx3.h index 07c1c550..298cefc6 100644 --- a/tests/TestKdbx3.h +++ b/tests/TestKdbx3.h @@ -22,7 +22,7 @@ class TestKdbx3 : public TestKeePass2Format { -Q_OBJECT + Q_OBJECT private slots: void testNonAscii(); @@ -39,12 +39,17 @@ protected: Database* readXml(const QString& path, bool strictMode, bool& hasError, QString& errorString) override; void writeXml(QBuffer* buf, Database* db, bool& hasError, QString& errorString) override; - void readKdbx(QIODevice* device, CompositeKey const& key, QScopedPointer& db, - bool& hasError, QString& errorString) override; - void readKdbx(const QString& path, CompositeKey const& key, QScopedPointer& db, - bool& hasError, QString& errorString) override; + void readKdbx(QIODevice* device, + CompositeKey const& key, + QScopedPointer& db, + bool& hasError, + QString& errorString) override; + void readKdbx(const QString& path, + CompositeKey const& key, + QScopedPointer& db, + bool& hasError, + QString& errorString) override; void writeKdbx(QIODevice* device, Database* db, bool& hasError, QString& errorString) override; - }; #endif // KEEPASSXC_TEST_KDBX3_H diff --git a/tests/TestKdbx4.cpp b/tests/TestKdbx4.cpp index 1d50b8e7..53207a04 100644 --- a/tests/TestKdbx4.cpp +++ b/tests/TestKdbx4.cpp @@ -18,17 +18,16 @@ #include "TestKdbx4.h" #include "TestGlobal.h" +#include "config-keepassx-tests.h" #include "core/Metadata.h" -#include "keys/PasswordKey.h" -#include "keys/FileKey.h" -#include "mock/MockChallengeResponseKey.h" +#include "format/KdbxXmlReader.h" +#include "format/KdbxXmlWriter.h" #include "format/KeePass2.h" #include "format/KeePass2Reader.h" #include "format/KeePass2Writer.h" -#include "format/KdbxXmlReader.h" -#include "format/KdbxXmlWriter.h" -#include "config-keepassx-tests.h" - +#include "keys/FileKey.h" +#include "keys/PasswordKey.h" +#include "mock/MockChallengeResponseKey.h" QTEST_GUILESS_MAIN(TestKdbx4) @@ -66,8 +65,11 @@ void TestKdbx4::writeXml(QBuffer* buf, Database* db, bool& hasError, QString& er errorString = writer.errorString(); } -void TestKdbx4::readKdbx(QIODevice* device, CompositeKey const& key, QScopedPointer& db, - bool& hasError, QString& errorString) +void TestKdbx4::readKdbx(QIODevice* device, + CompositeKey const& key, + QScopedPointer& db, + bool& hasError, + QString& errorString) { KeePass2Reader reader; db.reset(reader.readDatabase(device, key)); @@ -78,8 +80,11 @@ void TestKdbx4::readKdbx(QIODevice* device, CompositeKey const& key, QScopedPoin QCOMPARE(reader.version(), KeePass2::FILE_VERSION_4); } -void TestKdbx4::readKdbx(const QString& path, CompositeKey const& key, QScopedPointer& db, - bool& hasError, QString& errorString) +void TestKdbx4::readKdbx(const QString& path, + CompositeKey const& key, + QScopedPointer& db, + bool& hasError, + QString& errorString) { KeePass2Reader reader; db.reset(reader.readDatabase(path, key)); @@ -139,7 +144,7 @@ void TestKdbx4::testFormat400Upgrade() QScopedPointer sourceDb(new Database()); sourceDb->changeKdf(fastKdf(sourceDb->kdf())); sourceDb->metadata()->setName("Wubba lubba dub dub"); - QCOMPARE(sourceDb->kdf()->uuid(), KeePass2::KDF_AES_KDBX3); // default is legacy AES-KDF + QCOMPARE(sourceDb->kdf()->uuid(), KeePass2::KDF_AES_KDBX3); // default is legacy AES-KDF CompositeKey key; key.addKey(PasswordKey("I am in great pain, please help me!")); @@ -156,7 +161,8 @@ void TestKdbx4::testFormat400Upgrade() sourceDb->metadata()->customData()->set("CustomPublicData", "Hey look, I turned myself into a pickle!"); if (addCustomData) { // this, however, should - sourceDb->rootGroup()->customData()->set("CustomGroupData", "I just killed my family! I don't care who they were!"); + sourceDb->rootGroup()->customData()->set("CustomGroupData", + "I just killed my family! I don't care who they were!"); } KeePass2Writer writer; @@ -305,16 +311,18 @@ void TestKdbx4::testUpgradeMasterKeyIntegrity_data() QTest::addColumn("upgradeAction"); QTest::addColumn("expectedVersion"); - QTest::newRow("Upgrade: none") << QString("none") << KeePass2::FILE_VERSION_3; - QTest::newRow("Upgrade: none (meta-customdata)") << QString("meta-customdata") << KeePass2::FILE_VERSION_3; - QTest::newRow("Upgrade: none (explicit kdf-aes-kdbx3)") << QString("kdf-aes-kdbx3") << KeePass2::FILE_VERSION_3; - QTest::newRow("Upgrade (explicit): kdf-argon2") << QString("kdf-argon2") << KeePass2::FILE_VERSION_4; - QTest::newRow("Upgrade (explicit): kdf-aes-kdbx4") << QString("kdf-aes-kdbx4") << KeePass2::FILE_VERSION_4; - QTest::newRow("Upgrade (implicit): public-customdata") << QString("public-customdata") << KeePass2::FILE_VERSION_4; - QTest::newRow("Upgrade (implicit): rootgroup-customdata") << QString("rootgroup-customdata") << KeePass2::FILE_VERSION_4; - QTest::newRow("Upgrade (implicit): group-customdata") << QString("group-customdata") << KeePass2::FILE_VERSION_4; - QTest::newRow("Upgrade (implicit): rootentry-customdata") << QString("rootentry-customdata") << KeePass2::FILE_VERSION_4; - QTest::newRow("Upgrade (implicit): entry-customdata") << QString("entry-customdata") << KeePass2::FILE_VERSION_4; + QTest::newRow("Upgrade: none") << QString("none") << KeePass2::FILE_VERSION_3; + QTest::newRow("Upgrade: none (meta-customdata)") << QString("meta-customdata") << KeePass2::FILE_VERSION_3; + QTest::newRow("Upgrade: none (explicit kdf-aes-kdbx3)") << QString("kdf-aes-kdbx3") << KeePass2::FILE_VERSION_3; + QTest::newRow("Upgrade (explicit): kdf-argon2") << QString("kdf-argon2") << KeePass2::FILE_VERSION_4; + QTest::newRow("Upgrade (explicit): kdf-aes-kdbx4") << QString("kdf-aes-kdbx4") << KeePass2::FILE_VERSION_4; + QTest::newRow("Upgrade (implicit): public-customdata") << QString("public-customdata") << KeePass2::FILE_VERSION_4; + QTest::newRow("Upgrade (implicit): rootgroup-customdata") << QString("rootgroup-customdata") + << KeePass2::FILE_VERSION_4; + QTest::newRow("Upgrade (implicit): group-customdata") << QString("group-customdata") << KeePass2::FILE_VERSION_4; + QTest::newRow("Upgrade (implicit): rootentry-customdata") << QString("rootentry-customdata") + << KeePass2::FILE_VERSION_4; + QTest::newRow("Upgrade (implicit): entry-customdata") << QString("entry-customdata") << KeePass2::FILE_VERSION_4; } void TestKdbx4::testCustomData() @@ -335,8 +343,8 @@ void TestKdbx4::testCustomData() const QString customDataKey2 = "CD2"; const QString customData1 = "abcäöü"; const QString customData2 = "Hello World"; - const int dataSize = customDataKey1.toUtf8().size() + customDataKey1.toUtf8().size() + - customData1.toUtf8().size() + customData2.toUtf8().size(); + const int dataSize = customDataKey1.toUtf8().size() + customDataKey1.toUtf8().size() + customData1.toUtf8().size() + + customData2.toUtf8().size(); // test custom database data db.metadata()->customData()->set(customDataKey1, customData1); @@ -413,10 +421,7 @@ QSharedPointer TestKdbx4::fastKdf(QSharedPointer kdf) kdf->setRounds(1); if (kdf->uuid() == KeePass2::KDF_ARGON2) { - kdf->processParameters({ - {KeePass2::KDFPARAM_ARGON2_MEMORY, 1024}, - {KeePass2::KDFPARAM_ARGON2_PARALLELISM, 1} - }); + kdf->processParameters({{KeePass2::KDFPARAM_ARGON2_MEMORY, 1024}, {KeePass2::KDFPARAM_ARGON2_PARALLELISM, 1}}); } return kdf; diff --git a/tests/TestKdbx4.h b/tests/TestKdbx4.h index e278ebb0..1b677b4a 100644 --- a/tests/TestKdbx4.h +++ b/tests/TestKdbx4.h @@ -22,7 +22,7 @@ class TestKdbx4 : public TestKeePass2Format { -Q_OBJECT + Q_OBJECT private slots: void testFormat400(); @@ -39,10 +39,16 @@ protected: Database* readXml(const QString& path, bool strictMode, bool& hasError, QString& errorString) override; void writeXml(QBuffer* buf, Database* db, bool& hasError, QString& errorString) override; - void readKdbx(const QString& path, CompositeKey const& key, QScopedPointer& db, - bool& hasError, QString& errorString) override; - void readKdbx(QIODevice* device, CompositeKey const& key, QScopedPointer& db, - bool& hasError, QString& errorString) override; + void readKdbx(const QString& path, + CompositeKey const& key, + QScopedPointer& db, + bool& hasError, + QString& errorString) override; + void readKdbx(QIODevice* device, + CompositeKey const& key, + QScopedPointer& db, + bool& hasError, + QString& errorString) override; void writeKdbx(QIODevice* device, Database* db, bool& hasError, QString& errorString) override; QSharedPointer fastKdf(QSharedPointer kdf); diff --git a/tests/TestKeePass1Reader.cpp b/tests/TestKeePass1Reader.cpp index 892f746e..3cf95286 100644 --- a/tests/TestKeePass1Reader.cpp +++ b/tests/TestKeePass1Reader.cpp @@ -133,8 +133,7 @@ void TestKeePass1Reader::testGroupExpanded() { QCOMPARE(m_db->rootGroup()->children().at(0)->isExpanded(), true); QCOMPARE(m_db->rootGroup()->children().at(0)->children().at(0)->isExpanded(), true); - QCOMPARE(m_db->rootGroup()->children().at(0)->children().at(0)->children().at(0)->isExpanded(), - false); + QCOMPARE(m_db->rootGroup()->children().at(0)->children().at(0)->children().at(0)->isExpanded(), false); } void TestKeePass1Reader::testAutoType() diff --git a/tests/TestKeePass2Format.cpp b/tests/TestKeePass2Format.cpp index 266047be..9dac0769 100644 --- a/tests/TestKeePass2Format.cpp +++ b/tests/TestKeePass2Format.cpp @@ -20,8 +20,8 @@ #include "core/Metadata.h" #include "crypto/Crypto.h" -#include "keys/PasswordKey.h" #include "format/KdbxXmlReader.h" +#include "keys/PasswordKey.h" #include "FailDevice.h" #include "config-keepassx-tests.h" @@ -402,11 +402,15 @@ void TestKeePass2Format::testXmlInvalidXmlChars() { QScopedPointer dbWrite(new Database()); - QString strPlainInvalid = QString().append(QChar(0x02)).append(QChar(0x19)) - .append(QChar(0xFFFE)).append(QChar(0xFFFF)); - QString strPlainValid = QString().append(QChar(0x09)).append(QChar(0x0A)) - .append(QChar(0x20)).append(QChar(0xD7FF)) - .append(QChar(0xE000)).append(QChar(0xFFFD)); + QString strPlainInvalid = + QString().append(QChar(0x02)).append(QChar(0x19)).append(QChar(0xFFFE)).append(QChar(0xFFFF)); + QString strPlainValid = QString() + .append(QChar(0x09)) + .append(QChar(0x0A)) + .append(QChar(0x20)) + .append(QChar(0xD7FF)) + .append(QChar(0xE000)) + .append(QChar(0xFFFD)); // U+10437 in UTF-16: D801 DC37 // high low surrogate QString strSingleHighSurrogate1 = QString().append(QChar(0xD801)); @@ -416,8 +420,8 @@ void TestKeePass2Format::testXmlInvalidXmlChars() QString strSingleLowSurrogate2 = QString().append(QChar((0x31))).append(QChar(0xDC37)).append(QChar(0x32)); QString strLowLowSurrogate = QString().append(QChar(0xDC37)).append(QChar(0xDC37)); QString strSurrogateValid1 = QString().append(QChar(0xD801)).append(QChar(0xDC37)); - QString strSurrogateValid2 = QString().append(QChar(0x31)).append(QChar(0xD801)).append(QChar(0xDC37)) - .append(QChar(0x32)); + QString strSurrogateValid2 = + QString().append(QChar(0x31)).append(QChar(0xD801)).append(QChar(0xDC37)).append(QChar(0x32)); auto entry = new Entry(); entry->setUuid(Uuid::random()); @@ -532,7 +536,8 @@ void TestKeePass2Format::testKdbxAttachments() void TestKeePass2Format::testKdbxNonAsciiPasswords() { - QCOMPARE(m_kdbxTargetDb->rootGroup()->entries()[0]->password(), m_kdbxSourceDb->rootGroup()->entries()[0]->password()); + QCOMPARE(m_kdbxTargetDb->rootGroup()->entries()[0]->password(), + m_kdbxSourceDb->rootGroup()->entries()[0]->password()); } void TestKeePass2Format::testKdbxDeviceFailure() diff --git a/tests/TestKeePass2Format.h b/tests/TestKeePass2Format.h index 13426cb9..d29fa2c1 100644 --- a/tests/TestKeePass2Format.h +++ b/tests/TestKeePass2Format.h @@ -18,9 +18,9 @@ #ifndef KEEPASSXC_TESTKEEPASS2FORMAT_H #define KEEPASSXC_TESTKEEPASS2FORMAT_H +#include #include #include -#include #include #include "core/Database.h" @@ -30,7 +30,7 @@ */ class TestKeePass2Format : public QObject { -Q_OBJECT + Q_OBJECT private slots: void initTestCase(); @@ -71,10 +71,16 @@ protected: virtual Database* readXml(const QString& path, bool strictMode, bool& hasError, QString& errorString) = 0; virtual void writeXml(QBuffer* buf, Database* db, bool& hasError, QString& errorString) = 0; - virtual void readKdbx(QIODevice* device, CompositeKey const& key, QScopedPointer& db, - bool& hasError, QString& errorString) = 0; - virtual void readKdbx(const QString& path, CompositeKey const& key, QScopedPointer& db, - bool& hasError, QString& errorString) = 0; + virtual void readKdbx(QIODevice* device, + CompositeKey const& key, + QScopedPointer& db, + bool& hasError, + QString& errorString) = 0; + virtual void readKdbx(const QString& path, + CompositeKey const& key, + QScopedPointer& db, + bool& hasError, + QString& errorString) = 0; virtual void writeKdbx(QIODevice* device, Database* db, bool& hasError, QString& errorString) = 0; QScopedPointer m_xmlDb; diff --git a/tests/TestKeePass2RandomStream.cpp b/tests/TestKeePass2RandomStream.cpp index edb95b6c..3f544353 100644 --- a/tests/TestKeePass2RandomStream.cpp +++ b/tests/TestKeePass2RandomStream.cpp @@ -35,7 +35,6 @@ void TestKeePass2RandomStream::test() const QByteArray key("\x11\x22\x33\x44\x55\x66\x77\x88"); const int Size = 128; - SymmetricCipher cipher(SymmetricCipher::Salsa20, SymmetricCipher::Stream, SymmetricCipher::Encrypt); QVERIFY(cipher.init(CryptoHash::hash(key, CryptoHash::Sha256), KeePass2::INNER_STREAM_SALSA20_IV)); @@ -55,7 +54,6 @@ void TestKeePass2RandomStream::test() cipherData[i] = data[i] ^ cipherPad[i]; } - KeePass2RandomStream randomStream(KeePass2::ProtectedStreamAlgo::Salsa20); bool ok; QVERIFY(randomStream.init(key)); @@ -72,13 +70,11 @@ void TestKeePass2RandomStream::test() randomStreamData.append(randomStream.process(data.mid(64, 64), &ok)); QVERIFY(ok); - SymmetricCipher cipherEncrypt(SymmetricCipher::Salsa20, SymmetricCipher::Stream, SymmetricCipher::Encrypt); QVERIFY(cipherEncrypt.init(CryptoHash::hash(key, CryptoHash::Sha256), KeePass2::INNER_STREAM_SALSA20_IV)); QByteArray cipherDataEncrypt = cipherEncrypt.process(data, &ok); QVERIFY(ok); - QCOMPARE(randomStreamData.size(), Size); QCOMPARE(cipherData, cipherDataEncrypt); QCOMPARE(randomStreamData, cipherData); diff --git a/tests/TestKeys.cpp b/tests/TestKeys.cpp index e2b7010b..e5cc75c2 100644 --- a/tests/TestKeys.cpp +++ b/tests/TestKeys.cpp @@ -26,8 +26,8 @@ #include "core/Metadata.h" #include "core/Tools.h" #include "crypto/Crypto.h" -#include "crypto/kdf/AesKdf.h" #include "crypto/CryptoHash.h" +#include "crypto/kdf/AesKdf.h" #include "format/KeePass2Reader.h" #include "format/KeePass2Writer.h" #include "keys/FileKey.h" @@ -231,7 +231,8 @@ void TestKeys::benchmarkTransformKey() kdf.setSeed(seed); kdf.setRounds(1e6); - QBENCHMARK { + QBENCHMARK + { Q_UNUSED(compositeKey.transform(kdf, result)); }; } diff --git a/tests/TestMerge.cpp b/tests/TestMerge.cpp index 8f38a2f8..e490da8d 100644 --- a/tests/TestMerge.cpp +++ b/tests/TestMerge.cpp @@ -560,7 +560,6 @@ void TestMerge::testResolveGroupConflictOlder() delete dbSource; } - Database* TestMerge::createTestDatabase() { Database* db = new Database(); diff --git a/tests/TestModified.cpp b/tests/TestModified.cpp index 0bf2c5b3..0a9f0cfa 100644 --- a/tests/TestModified.cpp +++ b/tests/TestModified.cpp @@ -141,7 +141,6 @@ void TestModified::testGroupSets() root->setIcon(root->iconUuid()); QCOMPARE(spyModified.count(), spyCount); - group->setUuid(Uuid::random()); QCOMPARE(spyModified.count(), ++spyCount); group->setUuid(group->uuid()); @@ -306,7 +305,7 @@ void TestModified::testHistoryItems() entry->setTitle("b"); entry->endUpdate(); QCOMPARE(entry->historyItems().size(), ++historyItemsSize); - auto *historyEntry = entry->historyItems().at(historyItemsSize - 1); + auto* historyEntry = entry->historyItems().at(historyItemsSize - 1); QCOMPARE(historyEntry->title(), QString("a")); QCOMPARE(historyEntry->uuid(), entry->uuid()); QCOMPARE(historyEntry->tags(), entry->tags()); @@ -475,7 +474,6 @@ void TestModified::testHistoryMaxSize() QCOMPARE(entry1->attachments()->attachmentsSize(), 6000 + key.size()); QCOMPARE(entry1->historyItems().size(), 4); - auto entry2 = new Entry(); entry2->setGroup(db->rootGroup()); QCOMPARE(entry2->historyItems().size(), 0); diff --git a/tests/TestOpenSSHKey.cpp b/tests/TestOpenSSHKey.cpp index 8ac12986..cad591bd 100644 --- a/tests/TestOpenSSHKey.cpp +++ b/tests/TestOpenSSHKey.cpp @@ -17,8 +17,8 @@ #include "TestOpenSSHKey.h" #include "TestGlobal.h" -#include "sshagent/OpenSSHKey.h" #include "crypto/Crypto.h" +#include "sshagent/OpenSSHKey.h" QTEST_GUILESS_MAIN(TestOpenSSHKey) @@ -30,17 +30,15 @@ void TestOpenSSHKey::initTestCase() void TestOpenSSHKey::testParse() { // mixed line endings and missing ones are intentional, we only require 3 lines total - const QString keyString = QString( - "\r\n\r" - "-----BEGIN OPENSSH PRIVATE KEY-----\n" - "b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW" - "QyNTUxOQAAACDdlO5F2kF2WzedrBAHBi9wBHeISzXZ0IuIqrp0EzeazAAAAKjgCfj94An4" - "/QAAAAtzc2gtZWQyNTUxOQAAACDdlO5F2kF2WzedrBAHBi9wBHeISzXZ0IuIqrp0EzeazA" - "AAAEBe1iilZFho8ZGAliiSj5URvFtGrgvmnEKdiLZow5hOR92U7kXaQXZbN52sEAcGL3AE" - "d4hLNdnQi4iqunQTN5rMAAAAH29wZW5zc2hrZXktdGVzdC1wYXJzZUBrZWVwYXNzeGMBAg" - "MEBQY=\r" - "-----END OPENSSH PRIVATE KEY-----\r\n\r" - ); + const QString keyString = QString("\r\n\r" + "-----BEGIN OPENSSH PRIVATE KEY-----\n" + "b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW" + "QyNTUxOQAAACDdlO5F2kF2WzedrBAHBi9wBHeISzXZ0IuIqrp0EzeazAAAAKjgCfj94An4" + "/QAAAAtzc2gtZWQyNTUxOQAAACDdlO5F2kF2WzedrBAHBi9wBHeISzXZ0IuIqrp0EzeazA" + "AAAEBe1iilZFho8ZGAliiSj5URvFtGrgvmnEKdiLZow5hOR92U7kXaQXZbN52sEAcGL3AE" + "d4hLNdnQi4iqunQTN5rMAAAAH29wZW5zc2hrZXktdGVzdC1wYXJzZUBrZWVwYXNzeGMBAg" + "MEBQY=\r" + "-----END OPENSSH PRIVATE KEY-----\r\n\r"); const QByteArray keyData = keyString.toLatin1(); @@ -64,20 +62,18 @@ void TestOpenSSHKey::testParse() void TestOpenSSHKey::testParseDSA() { - const QString keyString = QString( - "-----BEGIN DSA PRIVATE KEY-----\n" - "MIIBuwIBAAKBgQCudjbvSh8JxQOr2laCqZM1t4kNWBETVOXz5vgk9iw6Z5opB9/k\n" - "g4nFc1PVq7fdAIc8W/5WCAjugKcxPb9PIHfcwY2fimmiPWFK68/eHKLoCuIn2wxB\n" - "63ig2hAhx5U5aYG9QHkNCaT6VX7rc19nToSeZXlpja4x54/DaQaqOEWYsQIVAOer\n" - "UQWfccz7KXUu6+x7heGob6I3AoGAVDRFJIlL0DI/4nePIcgwgwbfgs2ojSu21g4w\n" - "dQoXvqU34XydPgPQ985XIIuiDkaomRw4yYd/Sh4ZapFcrP++iJ1V+WS6kLcWPHMq\n" - "poYwk8mq6GLbPFLEjr+n6HgX5ln15n3i4WAopNH7mEl0glY9L0rxmcN0XOpqw6Ux\n" - "ETGEfAwCgYAiOeYwblMkkTIGtVx5NvNsOlfrBYL4GqUP9oQMO5I+xLZLWQIf+7Jp\n" - "8t6mwxSBz0RHjNVQ11vZowNjq3587aLy57bVwf2lIm9KSvS6z9HoNbHgQimcBorR\n" - "J9l9RUrj7TnsZgiVw66j2r34nHRHRtggiO+qrMtw7MJc0Q7jiuTmzgIVAMXbk0T9\n" - "nBfSLWQz/L8RexU2GR4e\n" - "-----END DSA PRIVATE KEY-----\n" - ); + const QString keyString = QString("-----BEGIN DSA PRIVATE KEY-----\n" + "MIIBuwIBAAKBgQCudjbvSh8JxQOr2laCqZM1t4kNWBETVOXz5vgk9iw6Z5opB9/k\n" + "g4nFc1PVq7fdAIc8W/5WCAjugKcxPb9PIHfcwY2fimmiPWFK68/eHKLoCuIn2wxB\n" + "63ig2hAhx5U5aYG9QHkNCaT6VX7rc19nToSeZXlpja4x54/DaQaqOEWYsQIVAOer\n" + "UQWfccz7KXUu6+x7heGob6I3AoGAVDRFJIlL0DI/4nePIcgwgwbfgs2ojSu21g4w\n" + "dQoXvqU34XydPgPQ985XIIuiDkaomRw4yYd/Sh4ZapFcrP++iJ1V+WS6kLcWPHMq\n" + "poYwk8mq6GLbPFLEjr+n6HgX5ln15n3i4WAopNH7mEl0glY9L0rxmcN0XOpqw6Ux\n" + "ETGEfAwCgYAiOeYwblMkkTIGtVx5NvNsOlfrBYL4GqUP9oQMO5I+xLZLWQIf+7Jp\n" + "8t6mwxSBz0RHjNVQ11vZowNjq3587aLy57bVwf2lIm9KSvS6z9HoNbHgQimcBorR\n" + "J9l9RUrj7TnsZgiVw66j2r34nHRHRtggiO+qrMtw7MJc0Q7jiuTmzgIVAMXbk0T9\n" + "nBfSLWQz/L8RexU2GR4e\n" + "-----END DSA PRIVATE KEY-----\n"); const QByteArray keyData = keyString.toLatin1(); @@ -92,38 +88,36 @@ void TestOpenSSHKey::testParseDSA() void TestOpenSSHKey::testDecryptAES128CBC() { - const QString keyString = QString( - "-----BEGIN RSA PRIVATE KEY-----\n" - "Proc-Type: 4,ENCRYPTED\n" - "DEK-Info: AES-128-CBC,804E4D214D1263FF94E3743FE799DBB4\n" - "\n" - "lM9TDfOTbiRhaGGDh7Hn+rqw8CCWcYBZYu7smyYLdnWKXKPmbne8CQFZBAS1FJwZ\n" - "6Mj6n075yFGyzN9/OfeqKiUA4adlbwLbGwB+yyKsC2FlsvRIEr4hup02WWM47vHj\n" - "DS4TRmNkE7MKFLhpNCyt5OGGM45s+/lwVTw51K0Hm99TBd72IrX4jfY9ZxAVbL3l\n" - "aTohL8x6oOTe7q318QgJoFi+DjJhDWLGLLJ7fBqD2imz2fmrY4j8Jpw2sDe1rj82\n" - "gMqqNG3FrfN0S4uYlWYH5pAh+BUcB1UdmTU/rV5wJMK1oUytmZv/J2+X/0k3Y93F\n" - "aw6JWOy28OizW+TQXvv8gREWsp5PEclqUZhhGQbVbCQCiDOxg+xiXNySdRH1IqjR\n" - "zQiKgD4SPzkxQekExPaIQT/KutWZdMNYybEqooCx8YyeDoN31z7Wa2rv6OulOn/j\n" - "wJFvyd2PT/6brHKI4ky8RYroDf4FbVYKfyEW5CSAg2OyL/tY/kSPgy/k0WT7fDwq\n" - "dPSuYM9yeWNL6kAhDqDOv8+s3xvOVEljktBvQvItQwVLmHszC3E2AcnaxzdblKPu\n" - "e3+mBT80NXHjERK2ht+/9JYseK1ujNbNAaG8SbKfU3FF0VlyJ0QW6TuIEdpNnymT\n" - "0fm0cDfKNaoeJIFnBRZhgIOJAic9DM0cTe/vSG69DaUYsaQPp36al7Fbux3GpFHS\n" - "OtJEySYGro/6zvJ9dDIEfIGZjA3RaMt6+DuyJZXQdT2RNXa9j60xW7dXh0En4n82\n" - "JUKTxYhDPLS5c8BzpJqoopxpKwElmrJ7Y3xpd6z2vIlD8ftuZrkk6siTMNQ2s7MI\n" - "Xl332O+0H4k7uSfczHPOOw36TFhNjGQAP0b7O+0/RVG0ttOIoAn7ZkX3nfdbtG5B\n" - "DWKvDaopvrcC2/scQ5uLUnqnBiGw1XiYpdg5ang7knHNzHZAIekVaYYZigpCAKp+\n" - "OtoaDeUEzqFhYVmF8ad1fgvC9ZUsuxS4XUHCKl0H6CJcvW9MJPVbveqYoK+j9qKd\n" - "iMIkQBP1kE2rzGZVGUkZTpM9LVD9nP0nsbr6E8BatFcNgRirsg2BTJglNpXlCmY6\n" - "ldzJ/ELBbzoXIn+0wTGai0o4eBPx55baef69JfPuZqEB9pLNE+mHstrqIwcfqYu4\n" - "M+Vzun1QshRMj9a1PVkIHfs1fLeebI4QCHO0vJlc9K4iYPM4rsDNO3YaAgGRuARS\n" - "f3McGiGFxkv5zxe8i05ZBnn+exE77jpRKxd223jAMe2wu4WiFB7ZVo4Db6b5Oo2T\n" - "TPh3VuY7TNMEKkcUi+mGLKjroocQ5j8WQYlfnyOaTalUVQDzOTNb67QIIoiszR0U\n" - "+AXGyxHj0QtotZFoPME+AbS9Zqy3SgSOuIzPBPU5zS4uoKNdD5NPE5YAuafCjsDy\n" - "MT4DVy+cPOQYUK022S7T2nsA1btmvUvD5LL2Mc8VuKsWOn/7FKZua6OCfipt6oX0\n" - "1tzYrw0/ALK+CIdVdYIiPPfxGZkr+JSLOOg7u50tpmen9GzxgNTv63miygwUAIDF\n" - "u0GbQwOueoA453/N75FcXOgrbqTdivyadUbRP+l7YJk/SfIytyJMOigejp+Z1lzF\n" - "-----END RSA PRIVATE KEY-----\n" - ); + const QString keyString = QString("-----BEGIN RSA PRIVATE KEY-----\n" + "Proc-Type: 4,ENCRYPTED\n" + "DEK-Info: AES-128-CBC,804E4D214D1263FF94E3743FE799DBB4\n" + "\n" + "lM9TDfOTbiRhaGGDh7Hn+rqw8CCWcYBZYu7smyYLdnWKXKPmbne8CQFZBAS1FJwZ\n" + "6Mj6n075yFGyzN9/OfeqKiUA4adlbwLbGwB+yyKsC2FlsvRIEr4hup02WWM47vHj\n" + "DS4TRmNkE7MKFLhpNCyt5OGGM45s+/lwVTw51K0Hm99TBd72IrX4jfY9ZxAVbL3l\n" + "aTohL8x6oOTe7q318QgJoFi+DjJhDWLGLLJ7fBqD2imz2fmrY4j8Jpw2sDe1rj82\n" + "gMqqNG3FrfN0S4uYlWYH5pAh+BUcB1UdmTU/rV5wJMK1oUytmZv/J2+X/0k3Y93F\n" + "aw6JWOy28OizW+TQXvv8gREWsp5PEclqUZhhGQbVbCQCiDOxg+xiXNySdRH1IqjR\n" + "zQiKgD4SPzkxQekExPaIQT/KutWZdMNYybEqooCx8YyeDoN31z7Wa2rv6OulOn/j\n" + "wJFvyd2PT/6brHKI4ky8RYroDf4FbVYKfyEW5CSAg2OyL/tY/kSPgy/k0WT7fDwq\n" + "dPSuYM9yeWNL6kAhDqDOv8+s3xvOVEljktBvQvItQwVLmHszC3E2AcnaxzdblKPu\n" + "e3+mBT80NXHjERK2ht+/9JYseK1ujNbNAaG8SbKfU3FF0VlyJ0QW6TuIEdpNnymT\n" + "0fm0cDfKNaoeJIFnBRZhgIOJAic9DM0cTe/vSG69DaUYsaQPp36al7Fbux3GpFHS\n" + "OtJEySYGro/6zvJ9dDIEfIGZjA3RaMt6+DuyJZXQdT2RNXa9j60xW7dXh0En4n82\n" + "JUKTxYhDPLS5c8BzpJqoopxpKwElmrJ7Y3xpd6z2vIlD8ftuZrkk6siTMNQ2s7MI\n" + "Xl332O+0H4k7uSfczHPOOw36TFhNjGQAP0b7O+0/RVG0ttOIoAn7ZkX3nfdbtG5B\n" + "DWKvDaopvrcC2/scQ5uLUnqnBiGw1XiYpdg5ang7knHNzHZAIekVaYYZigpCAKp+\n" + "OtoaDeUEzqFhYVmF8ad1fgvC9ZUsuxS4XUHCKl0H6CJcvW9MJPVbveqYoK+j9qKd\n" + "iMIkQBP1kE2rzGZVGUkZTpM9LVD9nP0nsbr6E8BatFcNgRirsg2BTJglNpXlCmY6\n" + "ldzJ/ELBbzoXIn+0wTGai0o4eBPx55baef69JfPuZqEB9pLNE+mHstrqIwcfqYu4\n" + "M+Vzun1QshRMj9a1PVkIHfs1fLeebI4QCHO0vJlc9K4iYPM4rsDNO3YaAgGRuARS\n" + "f3McGiGFxkv5zxe8i05ZBnn+exE77jpRKxd223jAMe2wu4WiFB7ZVo4Db6b5Oo2T\n" + "TPh3VuY7TNMEKkcUi+mGLKjroocQ5j8WQYlfnyOaTalUVQDzOTNb67QIIoiszR0U\n" + "+AXGyxHj0QtotZFoPME+AbS9Zqy3SgSOuIzPBPU5zS4uoKNdD5NPE5YAuafCjsDy\n" + "MT4DVy+cPOQYUK022S7T2nsA1btmvUvD5LL2Mc8VuKsWOn/7FKZua6OCfipt6oX0\n" + "1tzYrw0/ALK+CIdVdYIiPPfxGZkr+JSLOOg7u50tpmen9GzxgNTv63miygwUAIDF\n" + "u0GbQwOueoA453/N75FcXOgrbqTdivyadUbRP+l7YJk/SfIytyJMOigejp+Z1lzF\n" + "-----END RSA PRIVATE KEY-----\n"); const QByteArray keyData = keyString.toLatin1(); @@ -140,35 +134,33 @@ void TestOpenSSHKey::testDecryptAES128CBC() void TestOpenSSHKey::testParseRSA() { - const QString keyString = QString( - "-----BEGIN RSA PRIVATE KEY-----\n" - "MIIEpAIBAAKCAQEAsCHtJicDPWnvHSIKbnTZaJkIB9vgE0pmLdK580JUqBuonVbB\n" - "y1QTy0ZQ7/TtqvLPgwPK88TR46OLO/QGCzo2+XxgJ85uy0xfuyUYRmSuw0drsErN\n" - "mH8vU91lSBxsGDp9LtBbgHKoR23vMWZ34IxFRc55XphrIH48ijsMaL6bXBwF/3tD\n" - "9T3lm2MpP1huyVNnIY9+GRRWCy4f9LMj/UGu/n4RtwwfpOZBBRwYkq5QkzA9lPm/\n" - "VzF3MP1rKTMkvAw+Nfb383mkmc6MRnsa6uh6iDa9aVB7naegM13UJQX/PY1Ks6pO\n" - "XDpy/MQ7iCh+HmYNq5dRmARyaNl9xIXJNhz1cQIDAQABAoIBAQCnEUc1LUQxeM5K\n" - "wANNCqE+SgoIClPdeHC7fmrLh1ttqe6ib6ybBUFRS31yXs0hnfefunVEDKlaV8K2\n" - "N52UAMAsngFHQNRvGh6kEWeZPd9Xc+N98TZbNCjcT+DGKc+Om8wqH5DrodZlCq4c\n" - "GaoT4HnE4TjWtZTH2XXrWF9I66PKFWf070R44nvyVcvaZi4pC2YmURRPuGF6K1iK\n" - "dH8zM6HHG1UGu2W6hLNn+K01IulG0Lb8eWNaNYMmtQWaxyp7I2IWkkecUs3nCuiR\n" - "byFOoomCjdh8r9yZFvwxjGUhgtkALN9GCU0Mwve+s11IB2gevruN+q9/Qejbyfdm\n" - "IlgLAeTRAoGBANRcVzW9CYeobCf+U9hKJFEOur8XO+J2mTMaELA0EjWpTJFAeIT7\n" - "KeRpCRG4/vOSklxxRF6vP1EACA4Z+5BlN+FTipHHs+bSEgqkPZiiANDH7Zot5Iqv\n" - "1q0fRyldNRZNZK7DWp08BPNVWGA/EnEuKJiURxnxBaxNXbUyMCdjxvMvAoGBANRT\n" - "utbrqS/bAa/DcHKn3V6DRqBl3TDOfvCNjiKC84a67F2uXgzLIdMktr4d1NyCZVJd\n" - "7/zVgWORLIdg1eAi6rYGoOvNV39wwga7CF+m9sBY0wAaKYCELe6L26r4aQHVCX6n\n" - "rnIgUv+4o4itmU2iP0r3wlmDC9pDRQP82vfvQPlfAoGASwhleANW/quvq2HdViq8\n" - "Mje2HBalfhrRfpDTHK8JUBSFjTzuWG42GxJRtgVbb8x2ElujAKGDCaetMO5VSGu7\n" - "Fs5hw6iAFCpdXY0yhl+XUi2R8kwM2EPQ4lKO3jqkq0ClNmqn9a5jQWcCVt9yMLNS\n" - "fLbHeI8EpiCf34ngIcrLXNkCgYEAzlcEZuKkC46xB+dNew8pMTUwSKZVm53BfPKD\n" - "44QRN6imFbBjU9mAaJnwQbfp6dWKs834cGPolyM4++MeVfB42iZ88ksesgmZdUMD\n" - "szkl6O0pOJs0I+HQZVdjRbadDZvD22MHQ3+oST1dJ3FVXz3Cdo9qPuT8esMO6f4r\n" - "qfDH2s8CgYAXC/lWWHQ//PGP0pH4oiEXisx1K0X1u0xMGgrChxBRGRiKZUwNMIvJ\n" - "TqUu7IKizK19cLHF/NBvxHYHFw+m7puNjn6T1RtRCUjRZT7Dx1VHfVosL9ih5DA8\n" - "tpbZA5KGKcvHtB5DDgT0MHwzBZnb4Q//Rhovzn+HXZPsJTTgHHy3NQ==\n" - "-----END RSA PRIVATE KEY-----\n" - ); + const QString keyString = QString("-----BEGIN RSA PRIVATE KEY-----\n" + "MIIEpAIBAAKCAQEAsCHtJicDPWnvHSIKbnTZaJkIB9vgE0pmLdK580JUqBuonVbB\n" + "y1QTy0ZQ7/TtqvLPgwPK88TR46OLO/QGCzo2+XxgJ85uy0xfuyUYRmSuw0drsErN\n" + "mH8vU91lSBxsGDp9LtBbgHKoR23vMWZ34IxFRc55XphrIH48ijsMaL6bXBwF/3tD\n" + "9T3lm2MpP1huyVNnIY9+GRRWCy4f9LMj/UGu/n4RtwwfpOZBBRwYkq5QkzA9lPm/\n" + "VzF3MP1rKTMkvAw+Nfb383mkmc6MRnsa6uh6iDa9aVB7naegM13UJQX/PY1Ks6pO\n" + "XDpy/MQ7iCh+HmYNq5dRmARyaNl9xIXJNhz1cQIDAQABAoIBAQCnEUc1LUQxeM5K\n" + "wANNCqE+SgoIClPdeHC7fmrLh1ttqe6ib6ybBUFRS31yXs0hnfefunVEDKlaV8K2\n" + "N52UAMAsngFHQNRvGh6kEWeZPd9Xc+N98TZbNCjcT+DGKc+Om8wqH5DrodZlCq4c\n" + "GaoT4HnE4TjWtZTH2XXrWF9I66PKFWf070R44nvyVcvaZi4pC2YmURRPuGF6K1iK\n" + "dH8zM6HHG1UGu2W6hLNn+K01IulG0Lb8eWNaNYMmtQWaxyp7I2IWkkecUs3nCuiR\n" + "byFOoomCjdh8r9yZFvwxjGUhgtkALN9GCU0Mwve+s11IB2gevruN+q9/Qejbyfdm\n" + "IlgLAeTRAoGBANRcVzW9CYeobCf+U9hKJFEOur8XO+J2mTMaELA0EjWpTJFAeIT7\n" + "KeRpCRG4/vOSklxxRF6vP1EACA4Z+5BlN+FTipHHs+bSEgqkPZiiANDH7Zot5Iqv\n" + "1q0fRyldNRZNZK7DWp08BPNVWGA/EnEuKJiURxnxBaxNXbUyMCdjxvMvAoGBANRT\n" + "utbrqS/bAa/DcHKn3V6DRqBl3TDOfvCNjiKC84a67F2uXgzLIdMktr4d1NyCZVJd\n" + "7/zVgWORLIdg1eAi6rYGoOvNV39wwga7CF+m9sBY0wAaKYCELe6L26r4aQHVCX6n\n" + "rnIgUv+4o4itmU2iP0r3wlmDC9pDRQP82vfvQPlfAoGASwhleANW/quvq2HdViq8\n" + "Mje2HBalfhrRfpDTHK8JUBSFjTzuWG42GxJRtgVbb8x2ElujAKGDCaetMO5VSGu7\n" + "Fs5hw6iAFCpdXY0yhl+XUi2R8kwM2EPQ4lKO3jqkq0ClNmqn9a5jQWcCVt9yMLNS\n" + "fLbHeI8EpiCf34ngIcrLXNkCgYEAzlcEZuKkC46xB+dNew8pMTUwSKZVm53BfPKD\n" + "44QRN6imFbBjU9mAaJnwQbfp6dWKs834cGPolyM4++MeVfB42iZ88ksesgmZdUMD\n" + "szkl6O0pOJs0I+HQZVdjRbadDZvD22MHQ3+oST1dJ3FVXz3Cdo9qPuT8esMO6f4r\n" + "qfDH2s8CgYAXC/lWWHQ//PGP0pH4oiEXisx1K0X1u0xMGgrChxBRGRiKZUwNMIvJ\n" + "TqUu7IKizK19cLHF/NBvxHYHFw+m7puNjn6T1RtRCUjRZT7Dx1VHfVosL9ih5DA8\n" + "tpbZA5KGKcvHtB5DDgT0MHwzBZnb4Q//Rhovzn+HXZPsJTTgHHy3NQ==\n" + "-----END RSA PRIVATE KEY-----\n"); const QByteArray keyData = keyString.toLatin1(); @@ -183,16 +175,14 @@ void TestOpenSSHKey::testParseRSA() void TestOpenSSHKey::testDecryptAES256CBC() { - const QString keyString = QString( - "-----BEGIN OPENSSH PRIVATE KEY-----\n" - "b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jYmMAAAAGYmNyeXB0AAAAGAAAABD2A0agtd\n" - "oGtJiI9JvIxYbTAAAAEAAAAAEAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIDPvDXmi0w1rdMoX\n" - "fOeyZ0Q/v+wqq/tPFgJwxnW5ADtfAAAAsC3UPsf035hrF5SgZ48p55iDFPiyGfZC/C3vQx\n" - "+THzpQo8DTUmFokdPn8wvDYGQoIcr9q0RzJuKV87eMQf3zzvZfJthtLYBlt330Deivv9AQ\n" - "MbKdhPZ4SfwRvv0grgT2EVId3GQAPgSVBhXYQTOf2CdmbXV4kieFLTmSsBMy+v6Qn5Rqur\n" - "PDWBwuLQgamcVDZuhrkUEqIVJZU2zAiRU2oAXsw/XOgFV6+Y5UZmLwWJQZ\n" - "-----END OPENSSH PRIVATE KEY-----\n" - ); + const QString keyString = QString("-----BEGIN OPENSSH PRIVATE KEY-----\n" + "b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jYmMAAAAGYmNyeXB0AAAAGAAAABD2A0agtd\n" + "oGtJiI9JvIxYbTAAAAEAAAAAEAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIDPvDXmi0w1rdMoX\n" + "fOeyZ0Q/v+wqq/tPFgJwxnW5ADtfAAAAsC3UPsf035hrF5SgZ48p55iDFPiyGfZC/C3vQx\n" + "+THzpQo8DTUmFokdPn8wvDYGQoIcr9q0RzJuKV87eMQf3zzvZfJthtLYBlt330Deivv9AQ\n" + "MbKdhPZ4SfwRvv0grgT2EVId3GQAPgSVBhXYQTOf2CdmbXV4kieFLTmSsBMy+v6Qn5Rqur\n" + "PDWBwuLQgamcVDZuhrkUEqIVJZU2zAiRU2oAXsw/XOgFV6+Y5UZmLwWJQZ\n" + "-----END OPENSSH PRIVATE KEY-----\n"); const QByteArray keyData = keyString.toLatin1(); @@ -217,16 +207,14 @@ void TestOpenSSHKey::testDecryptAES256CBC() void TestOpenSSHKey::testDecryptAES256CTR() { - const QString keyString = QString( - "-----BEGIN OPENSSH PRIVATE KEY-----\n" - "b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABAMhIAypt\n" - "WP4tZJBmMwq0tTAAAAEAAAAAEAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIErNsS8ROy43XoWC\n" - "nO9Sn2lEFBJYcDVtRPM1t6WB7W7OAAAAsFKXMOlPILoTmMj2JmcqzjaYAhaCezx18HDp76\n" - "VrNxaZTd0T28EGFSkzrReeewpJWy/bWlhLoXR5fRyOSSto+iMg/pibIvIJMrD5sqxlxr/e\n" - "c5lSeSZUzIK8Rv+ou/3EFDcY5jp8hVXqA4qNtoM/3fV52vmwlNje5d1V5Gsr4U8443+i+p\n" - "swqksozfatkynk51uR/9QFoOJKlsL/Z3LkK1S/apYz/K331iU1f5ozFELf\n" - "-----END OPENSSH PRIVATE KEY-----\n" - ); + const QString keyString = QString("-----BEGIN OPENSSH PRIVATE KEY-----\n" + "b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABAMhIAypt\n" + "WP4tZJBmMwq0tTAAAAEAAAAAEAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIErNsS8ROy43XoWC\n" + "nO9Sn2lEFBJYcDVtRPM1t6WB7W7OAAAAsFKXMOlPILoTmMj2JmcqzjaYAhaCezx18HDp76\n" + "VrNxaZTd0T28EGFSkzrReeewpJWy/bWlhLoXR5fRyOSSto+iMg/pibIvIJMrD5sqxlxr/e\n" + "c5lSeSZUzIK8Rv+ou/3EFDcY5jp8hVXqA4qNtoM/3fV52vmwlNje5d1V5Gsr4U8443+i+p\n" + "swqksozfatkynk51uR/9QFoOJKlsL/Z3LkK1S/apYz/K331iU1f5ozFELf\n" + "-----END OPENSSH PRIVATE KEY-----\n"); const QByteArray keyData = keyString.toLatin1(); diff --git a/tests/TestRandom.cpp b/tests/TestRandom.cpp index 7575e3a5..07d1c683 100644 --- a/tests/TestRandom.cpp +++ b/tests/TestRandom.cpp @@ -20,7 +20,6 @@ #include "core/Endian.h" #include "core/Global.h" - QTEST_GUILESS_MAIN(TestRandom) void TestRandom::initTestCase() @@ -70,7 +69,6 @@ void TestRandom::testUIntRange() QCOMPARE(randomGen()->randomUIntRange(100, 200), 142U); } - RandomBackendTest::RandomBackendTest() : m_bytesIndex(0) { diff --git a/tests/TestSymmetricCipher.cpp b/tests/TestSymmetricCipher.cpp index a5159e0d..bec894c0 100644 --- a/tests/TestSymmetricCipher.cpp +++ b/tests/TestSymmetricCipher.cpp @@ -51,8 +51,7 @@ void TestSymmetricCipher::testAes128CbcEncryption() QVERIFY(ok); QBuffer buffer; - SymmetricCipherStream stream(&buffer, SymmetricCipher::Aes128, SymmetricCipher::Cbc, - SymmetricCipher::Encrypt); + SymmetricCipherStream stream(&buffer, SymmetricCipher::Aes128, SymmetricCipher::Cbc, SymmetricCipher::Encrypt); QVERIFY(stream.init(key, iv)); buffer.open(QIODevice::WriteOnly); QVERIFY(stream.open(QIODevice::WriteOnly)); @@ -98,8 +97,7 @@ void TestSymmetricCipher::testAes128CbcDecryption() // padded with 16 0x10 bytes QByteArray cipherTextPadded = cipherText + QByteArray::fromHex("55e21d7100b988ffec32feeafaf23538"); QBuffer buffer(&cipherTextPadded); - SymmetricCipherStream stream(&buffer, SymmetricCipher::Aes128, SymmetricCipher::Cbc, - SymmetricCipher::Decrypt); + SymmetricCipherStream stream(&buffer, SymmetricCipher::Aes128, SymmetricCipher::Cbc, SymmetricCipher::Decrypt); QVERIFY(stream.init(key, iv)); buffer.open(QIODevice::ReadOnly); QVERIFY(stream.open(QIODevice::ReadOnly)); @@ -132,13 +130,11 @@ void TestSymmetricCipher::testAes256CbcEncryption() QVERIFY(cipher.init(key, iv)); QCOMPARE(cipher.blockSize(), 16); - QCOMPARE(cipher.process(plainText, &ok), - cipherText); + QCOMPARE(cipher.process(plainText, &ok), cipherText); QVERIFY(ok); QBuffer buffer; - SymmetricCipherStream stream(&buffer, SymmetricCipher::Aes256, SymmetricCipher::Cbc, - SymmetricCipher::Encrypt); + SymmetricCipherStream stream(&buffer, SymmetricCipher::Aes256, SymmetricCipher::Cbc, SymmetricCipher::Encrypt); QVERIFY(stream.init(key, iv)); buffer.open(QIODevice::WriteOnly); QVERIFY(stream.open(QIODevice::WriteOnly)); @@ -179,33 +175,27 @@ void TestSymmetricCipher::testAes256CbcDecryption() QVERIFY(cipher.init(key, iv)); QCOMPARE(cipher.blockSize(), 16); - QCOMPARE(cipher.process(cipherText, &ok), - plainText); + QCOMPARE(cipher.process(cipherText, &ok), plainText); QVERIFY(ok); // padded with 16 0x16 bytes QByteArray cipherTextPadded = cipherText + QByteArray::fromHex("3a3aa5e0213db1a9901f9036cf5102d2"); QBuffer buffer(&cipherTextPadded); - SymmetricCipherStream stream(&buffer, SymmetricCipher::Aes256, SymmetricCipher::Cbc, - SymmetricCipher::Decrypt); + SymmetricCipherStream stream(&buffer, SymmetricCipher::Aes256, SymmetricCipher::Cbc, SymmetricCipher::Decrypt); QVERIFY(stream.init(key, iv)); buffer.open(QIODevice::ReadOnly); QVERIFY(stream.open(QIODevice::ReadOnly)); - QCOMPARE(stream.read(10), - plainText.left(10)); + QCOMPARE(stream.read(10), plainText.left(10)); buffer.reset(); QVERIFY(stream.reset()); - QCOMPARE(stream.read(20), - plainText.left(20)); + QCOMPARE(stream.read(20), plainText.left(20)); buffer.reset(); QVERIFY(stream.reset()); - QCOMPARE(stream.read(16), - plainText.left(16)); + QCOMPARE(stream.read(16), plainText.left(16)); buffer.reset(); QVERIFY(stream.reset()); - QCOMPARE(stream.read(100), - plainText); + QCOMPARE(stream.read(100), plainText); } void TestSymmetricCipher::testAes256CtrEncryption() @@ -224,8 +214,7 @@ void TestSymmetricCipher::testAes256CtrEncryption() QVERIFY(cipher.init(key, ctr)); QCOMPARE(cipher.blockSize(), 16); - QCOMPARE(cipher.process(plainText, &ok), - cipherText); + QCOMPARE(cipher.process(plainText, &ok), cipherText); QVERIFY(ok); } @@ -243,8 +232,7 @@ void TestSymmetricCipher::testAes256CtrDecryption() QVERIFY(cipher.init(key, ctr)); QCOMPARE(cipher.blockSize(), 16); - QCOMPARE(cipher.process(cipherText, &ok), - plainText); + QCOMPARE(cipher.process(cipherText, &ok), plainText); QVERIFY(ok); } @@ -252,39 +240,31 @@ void TestSymmetricCipher::testTwofish256CbcEncryption() { // NIST MCT Known-Answer Tests (cbc_e_m.txt) // https://www.schneier.com/code/twofish-kat.zip - - QVector keys { - QByteArray::fromHex("0000000000000000000000000000000000000000000000000000000000000000"), - QByteArray::fromHex("D0A260EB41755B19374BABF259A79DB3EA7162E65490B03B1AE4871FB35EF23B"), - QByteArray::fromHex("8D55E4849A4DED08D89881E6708EDD26BEEE942073DFB3790B2798B240ACD74A"), - QByteArray::fromHex("606EFDC2066A837AF0430EBE4CF1F21071CCB236C33B4B9D82404FDB05C74621"), - QByteArray::fromHex("B119AA9485CEEEB4CC778AF21121E54DE4BDBA3498C61C8FD9004AA0C71909C3") - }; - QVector ivs { - QByteArray::fromHex("00000000000000000000000000000000"), - QByteArray::fromHex("EA7162E65490B03B1AE4871FB35EF23B"), - QByteArray::fromHex("549FF6C6274F034211C31FADF3F22571"), - QByteArray::fromHex("CF222616B0E4F8E48967D769456B916B"), - QByteArray::fromHex("957108025BFD57125B40057BC2DE4FE2") - }; - QVector plainTexts { - QByteArray::fromHex("00000000000000000000000000000000"), - QByteArray::fromHex("D0A260EB41755B19374BABF259A79DB3"), - QByteArray::fromHex("5DF7846FDB38B611EFD32A1429294095"), - QByteArray::fromHex("ED3B19469C276E7228DB8F583C7F2F36"), - QByteArray::fromHex("D177575683A46DCE3C34844C5DD0175D") - }; - QVector cipherTexts { - QByteArray::fromHex("EA7162E65490B03B1AE4871FB35EF23B"), - QByteArray::fromHex("549FF6C6274F034211C31FADF3F22571"), - QByteArray::fromHex("CF222616B0E4F8E48967D769456B916B"), - QByteArray::fromHex("957108025BFD57125B40057BC2DE4FE2"), - QByteArray::fromHex("6F725C5950133F82EF021A94CADC8508") - }; - + + QVector keys{QByteArray::fromHex("0000000000000000000000000000000000000000000000000000000000000000"), + QByteArray::fromHex("D0A260EB41755B19374BABF259A79DB3EA7162E65490B03B1AE4871FB35EF23B"), + QByteArray::fromHex("8D55E4849A4DED08D89881E6708EDD26BEEE942073DFB3790B2798B240ACD74A"), + QByteArray::fromHex("606EFDC2066A837AF0430EBE4CF1F21071CCB236C33B4B9D82404FDB05C74621"), + QByteArray::fromHex("B119AA9485CEEEB4CC778AF21121E54DE4BDBA3498C61C8FD9004AA0C71909C3")}; + QVector ivs{QByteArray::fromHex("00000000000000000000000000000000"), + QByteArray::fromHex("EA7162E65490B03B1AE4871FB35EF23B"), + QByteArray::fromHex("549FF6C6274F034211C31FADF3F22571"), + QByteArray::fromHex("CF222616B0E4F8E48967D769456B916B"), + QByteArray::fromHex("957108025BFD57125B40057BC2DE4FE2")}; + QVector plainTexts{QByteArray::fromHex("00000000000000000000000000000000"), + QByteArray::fromHex("D0A260EB41755B19374BABF259A79DB3"), + QByteArray::fromHex("5DF7846FDB38B611EFD32A1429294095"), + QByteArray::fromHex("ED3B19469C276E7228DB8F583C7F2F36"), + QByteArray::fromHex("D177575683A46DCE3C34844C5DD0175D")}; + QVector cipherTexts{QByteArray::fromHex("EA7162E65490B03B1AE4871FB35EF23B"), + QByteArray::fromHex("549FF6C6274F034211C31FADF3F22571"), + QByteArray::fromHex("CF222616B0E4F8E48967D769456B916B"), + QByteArray::fromHex("957108025BFD57125B40057BC2DE4FE2"), + QByteArray::fromHex("6F725C5950133F82EF021A94CADC8508")}; + SymmetricCipher cipher(SymmetricCipher::Twofish, SymmetricCipher::Cbc, SymmetricCipher::Encrypt); bool ok; - + for (int i = 0; i < keys.size(); ++i) { QVERIFY(cipher.init(keys[i], ivs[i])); QByteArray ptNext = plainTexts[i]; @@ -297,14 +277,14 @@ void TestSymmetricCipher::testTwofish256CbcEncryption() break; ptNext = ctPrev; ctPrev = ctCur; - + ctCur = cipher.process(ptNext, &ok); if (!ok) break; ptNext = ctPrev; ctPrev = ctCur; } - + QVERIFY(ok); QCOMPARE(ctCur, cipherTexts[i]); } @@ -314,39 +294,31 @@ void TestSymmetricCipher::testTwofish256CbcDecryption() { // NIST MCT Known-Answer Tests (cbc_d_m.txt) // https://www.schneier.com/code/twofish-kat.zip - - QVector keys { - QByteArray::fromHex("0000000000000000000000000000000000000000000000000000000000000000"), - QByteArray::fromHex("1B1FE8F5A911CD4C0D800EDCE8ED0A942CBA6271A1044F90C30BA8FE91E1C163"), - QByteArray::fromHex("EBA31FF8D2A24FDD769A937353E23257294A33394E4D17A668060AD8230811A1"), - QByteArray::fromHex("1DCF1915C389AB273F80F897BF008F058ED89F58A95C1BE523C4B11295ED2D0F"), - QByteArray::fromHex("491B9A66D3ED4EF19F02180289D5B1A1C2596AE568540A95DC5244198A9B8869") - }; - QVector ivs { - QByteArray::fromHex("00000000000000000000000000000000"), - QByteArray::fromHex("1B1FE8F5A911CD4C0D800EDCE8ED0A94"), - QByteArray::fromHex("F0BCF70D7BB382917B1A9DAFBB0F38C3"), - QByteArray::fromHex("F66C06ED112BE4FA491A6BE4ECE2BD52"), - QByteArray::fromHex("54D483731064E5D6A082E09536D53EA4") - }; - QVector plainTexts { - QByteArray::fromHex("2CBA6271A1044F90C30BA8FE91E1C163"), - QByteArray::fromHex("05F05148EF495836AB0DA226B2E9D0C2"), - QByteArray::fromHex("A792AC61E7110C434BC2BBCAB6E53CAE"), - QByteArray::fromHex("4C81F5BDC1081170FF96F50B1F76A566"), - QByteArray::fromHex("BD959F5B787037631A37051EA5F369F8") - }; - QVector cipherTexts { - QByteArray::fromHex("00000000000000000000000000000000"), - QByteArray::fromHex("2CBA6271A1044F90C30BA8FE91E1C163"), - QByteArray::fromHex("05F05148EF495836AB0DA226B2E9D0C2"), - QByteArray::fromHex("A792AC61E7110C434BC2BBCAB6E53CAE"), - QByteArray::fromHex("4C81F5BDC1081170FF96F50B1F76A566") - }; - + + QVector keys{QByteArray::fromHex("0000000000000000000000000000000000000000000000000000000000000000"), + QByteArray::fromHex("1B1FE8F5A911CD4C0D800EDCE8ED0A942CBA6271A1044F90C30BA8FE91E1C163"), + QByteArray::fromHex("EBA31FF8D2A24FDD769A937353E23257294A33394E4D17A668060AD8230811A1"), + QByteArray::fromHex("1DCF1915C389AB273F80F897BF008F058ED89F58A95C1BE523C4B11295ED2D0F"), + QByteArray::fromHex("491B9A66D3ED4EF19F02180289D5B1A1C2596AE568540A95DC5244198A9B8869")}; + QVector ivs{QByteArray::fromHex("00000000000000000000000000000000"), + QByteArray::fromHex("1B1FE8F5A911CD4C0D800EDCE8ED0A94"), + QByteArray::fromHex("F0BCF70D7BB382917B1A9DAFBB0F38C3"), + QByteArray::fromHex("F66C06ED112BE4FA491A6BE4ECE2BD52"), + QByteArray::fromHex("54D483731064E5D6A082E09536D53EA4")}; + QVector plainTexts{QByteArray::fromHex("2CBA6271A1044F90C30BA8FE91E1C163"), + QByteArray::fromHex("05F05148EF495836AB0DA226B2E9D0C2"), + QByteArray::fromHex("A792AC61E7110C434BC2BBCAB6E53CAE"), + QByteArray::fromHex("4C81F5BDC1081170FF96F50B1F76A566"), + QByteArray::fromHex("BD959F5B787037631A37051EA5F369F8")}; + QVector cipherTexts{QByteArray::fromHex("00000000000000000000000000000000"), + QByteArray::fromHex("2CBA6271A1044F90C30BA8FE91E1C163"), + QByteArray::fromHex("05F05148EF495836AB0DA226B2E9D0C2"), + QByteArray::fromHex("A792AC61E7110C434BC2BBCAB6E53CAE"), + QByteArray::fromHex("4C81F5BDC1081170FF96F50B1F76A566")}; + SymmetricCipher cipher(SymmetricCipher::Twofish, SymmetricCipher::Cbc, SymmetricCipher::Decrypt); bool ok; - + for (int i = 0; i < keys.size(); ++i) { cipher.init(keys[i], ivs[i]); QByteArray ctNext = cipherTexts[i]; @@ -357,13 +329,13 @@ void TestSymmetricCipher::testTwofish256CbcDecryption() if (!ok) break; ctNext = ptCur; - + ptCur = cipher.process(ctNext, &ok); if (!ok) break; ctNext = ptCur; } - + QVERIFY(ok); QCOMPARE(ptCur, plainTexts[i]); } @@ -437,8 +409,8 @@ void TestSymmetricCipher::testChaCha20() SymmetricCipher cipher(SymmetricCipher::ChaCha20, SymmetricCipher::Stream, SymmetricCipher::Encrypt); QVERIFY(cipher.init(key, iv)); QCOMPARE(cipher.process(QByteArray(64, 0), &ok), - QByteArray::fromHex( - "76b8e0ada0f13d90405d6ae55386bd28bdd219b8a08ded1aa836efcc8b770dc7da41597c5157488d7724e03fb8d84a376a43b8f41518a11cc387b669b2ee6586")); + QByteArray::fromHex("76b8e0ada0f13d90405d6ae55386bd28bdd219b8a08ded1aa836efcc8b770dc7da41597c5157488d7" + "724e03fb8d84a376a43b8f41518a11cc387b669b2ee6586")); QVERIFY(ok); } @@ -448,8 +420,8 @@ void TestSymmetricCipher::testChaCha20() SymmetricCipher cipher(SymmetricCipher::ChaCha20, SymmetricCipher::Stream, SymmetricCipher::Encrypt); QVERIFY(cipher.init(key, iv)); QCOMPARE(cipher.process(QByteArray(64, 0), &ok), - QByteArray::fromHex( - "4540f05a9f1fb296d7736e7b208e3c96eb4fe1834688d2604f450952ed432d41bbe2a0b6ea7566d2a5d1e7e20d42af2c53d792b1c43fea817e9ad275ae546963")); + QByteArray::fromHex("4540f05a9f1fb296d7736e7b208e3c96eb4fe1834688d2604f450952ed432d41bbe2a0b6ea7566d2a" + "5d1e7e20d42af2c53d792b1c43fea817e9ad275ae546963")); QVERIFY(ok); } @@ -459,8 +431,8 @@ void TestSymmetricCipher::testChaCha20() SymmetricCipher cipher(SymmetricCipher::ChaCha20, SymmetricCipher::Stream, SymmetricCipher::Encrypt); QVERIFY(cipher.init(key, iv)); QCOMPARE(cipher.process(QByteArray(60, 0), &ok), - QByteArray::fromHex( - "de9cba7bf3d69ef5e786dc63973f653a0b49e015adbff7134fcb7df137821031e85a050278a7084527214f73efc7fa5b5277062eb7a0433e445f41e3")); + QByteArray::fromHex("de9cba7bf3d69ef5e786dc63973f653a0b49e015adbff7134fcb7df137821031e85a050278a708452" + "7214f73efc7fa5b5277062eb7a0433e445f41e3")); QVERIFY(ok); } @@ -470,8 +442,8 @@ void TestSymmetricCipher::testChaCha20() SymmetricCipher cipher(SymmetricCipher::ChaCha20, SymmetricCipher::Stream, SymmetricCipher::Encrypt); QVERIFY(cipher.init(key, iv)); QCOMPARE(cipher.process(QByteArray(64, 0), &ok), - QByteArray::fromHex( - "ef3fdfd6c61578fbf5cf35bd3dd33b8009631634d21e42ac33960bd138e50d32111e4caf237ee53ca8ad6426194a88545ddc497a0b466e7d6bbdb0041b2f586b")); + QByteArray::fromHex("ef3fdfd6c61578fbf5cf35bd3dd33b8009631634d21e42ac33960bd138e50d32111e4caf237ee53ca" + "8ad6426194a88545ddc497a0b466e7d6bbdb0041b2f586b")); QVERIFY(ok); } } @@ -485,8 +457,7 @@ void TestSymmetricCipher::testPadding() QBuffer buffer; buffer.open(QIODevice::ReadWrite); - SymmetricCipherStream streamEnc(&buffer, SymmetricCipher::Aes256, SymmetricCipher::Cbc, - SymmetricCipher::Encrypt); + SymmetricCipherStream streamEnc(&buffer, SymmetricCipher::Aes256, SymmetricCipher::Cbc, SymmetricCipher::Encrypt); QVERIFY(streamEnc.init(key, iv)); streamEnc.open(QIODevice::WriteOnly); streamEnc.write(plainText); @@ -495,8 +466,7 @@ void TestSymmetricCipher::testPadding() // make sure padding is written QCOMPARE(buffer.buffer().size(), 16); - SymmetricCipherStream streamDec(&buffer, SymmetricCipher::Aes256, SymmetricCipher::Cbc, - SymmetricCipher::Decrypt); + SymmetricCipherStream streamDec(&buffer, SymmetricCipher::Aes256, SymmetricCipher::Cbc, SymmetricCipher::Decrypt); QVERIFY(streamDec.init(key, iv)); streamDec.open(QIODevice::ReadOnly); QByteArray decrypted = streamDec.readAll(); @@ -510,8 +480,7 @@ void TestSymmetricCipher::testStreamReset() QBuffer buffer; QVERIFY(buffer.open(QIODevice::WriteOnly)); - SymmetricCipherStream writer(&buffer, SymmetricCipher::Aes256, SymmetricCipher::Cbc, - SymmetricCipher::Encrypt); + SymmetricCipherStream writer(&buffer, SymmetricCipher::Aes256, SymmetricCipher::Cbc, SymmetricCipher::Encrypt); QVERIFY(writer.init(key, iv)); QVERIFY(writer.open(QIODevice::WriteOnly)); QCOMPARE(writer.write(QByteArray(4, 'Z')), qint64(4)); diff --git a/tests/TestTotp.cpp b/tests/TestTotp.cpp index 02af663a..a91ae00b 100644 --- a/tests/TestTotp.cpp +++ b/tests/TestTotp.cpp @@ -81,64 +81,55 @@ void TestTotp::testTotpCode() void TestTotp::testEncoderData() { - for (quint8 key: Totp::encoders.keys()) { + for (quint8 key : Totp::encoders.keys()) { const Totp::Encoder& enc = Totp::encoders.value(key); - QVERIFY2(enc.digits != 0, - qPrintable(QString("Custom encoders cannot have zero-value for digits field: %1(%2)") - .arg(enc.name) - .arg(key))); + QVERIFY2( + enc.digits != 0, + qPrintable( + QString("Custom encoders cannot have zero-value for digits field: %1(%2)").arg(enc.name).arg(key))); QVERIFY2(!enc.name.isEmpty(), - qPrintable(QString("Custom encoders must have a name: %1(%2)") - .arg(enc.name) - .arg(key))); + qPrintable(QString("Custom encoders must have a name: %1(%2)").arg(enc.name).arg(key))); QVERIFY2(!enc.shortName.isEmpty(), - qPrintable(QString("Custom encoders must have a shortName: %1(%2)") - .arg(enc.name) - .arg(key))); + qPrintable(QString("Custom encoders must have a shortName: %1(%2)").arg(enc.name).arg(key))); QVERIFY2(Totp::shortNameToEncoder.contains(enc.shortName), - qPrintable(QString("No shortNameToEncoder entry found for custom encoder: %1(%2) %3") - .arg(enc.name) - .arg(key) - .arg(enc.shortName))); + qPrintable(QString("No shortNameToEncoder entry found for custom encoder: %1(%2) %3") + .arg(enc.name) + .arg(key) + .arg(enc.shortName))); QVERIFY2(Totp::shortNameToEncoder[enc.shortName] == key, - qPrintable(QString("shortNameToEncoder doesn't reference this custome encoder: %1(%2) %3") - .arg(enc.name) - .arg(key) - .arg(enc.shortName))); + qPrintable(QString("shortNameToEncoder doesn't reference this custome encoder: %1(%2) %3") + .arg(enc.name) + .arg(key) + .arg(enc.shortName))); QVERIFY2(Totp::nameToEncoder.contains(enc.name), - qPrintable(QString("No nameToEncoder entry found for custom encoder: %1(%2) %3") - .arg(enc.name) - .arg(key) - .arg(enc.shortName))); + qPrintable(QString("No nameToEncoder entry found for custom encoder: %1(%2) %3") + .arg(enc.name) + .arg(key) + .arg(enc.shortName))); QVERIFY2(Totp::nameToEncoder[enc.name] == key, - qPrintable(QString("nameToEncoder doesn't reference this custome encoder: %1(%2) %3") - .arg(enc.name) - .arg(key) - .arg(enc.shortName))); + qPrintable(QString("nameToEncoder doesn't reference this custome encoder: %1(%2) %3") + .arg(enc.name) + .arg(key) + .arg(enc.shortName))); } - for (const QString & key: Totp::nameToEncoder.keys()) { + for (const QString& key : Totp::nameToEncoder.keys()) { quint8 value = Totp::nameToEncoder.value(key); QVERIFY2(Totp::encoders.contains(value), - qPrintable(QString("No custom encoder found for encoder named %1(%2)") - .arg(value) - .arg(key))); + qPrintable(QString("No custom encoder found for encoder named %1(%2)").arg(value).arg(key))); QVERIFY2(Totp::encoders[value].name == key, - qPrintable(QString("nameToEncoder doesn't reference the right custom encoder: %1(%2)") - .arg(value) - .arg(key))); + qPrintable( + QString("nameToEncoder doesn't reference the right custom encoder: %1(%2)").arg(value).arg(key))); } - for (const QString & key: Totp::shortNameToEncoder.keys()) { + for (const QString& key : Totp::shortNameToEncoder.keys()) { quint8 value = Totp::shortNameToEncoder.value(key); QVERIFY2(Totp::encoders.contains(value), - qPrintable(QString("No custom encoder found for short-name encoder %1(%2)") - .arg(value) - .arg(key))); - QVERIFY2(Totp::encoders[value].shortName == key, - qPrintable(QString("shortNameToEncoder doesn't reference the right custom encoder: %1(%2)") - .arg(value) - .arg(key))); + qPrintable(QString("No custom encoder found for short-name encoder %1(%2)").arg(value).arg(key))); + QVERIFY2( + Totp::encoders[value].shortName == key, + qPrintable( + QString("shortNameToEncoder doesn't reference the right custom encoder: %1(%2)").arg(value).arg(key))); } } @@ -153,7 +144,6 @@ void TestTotp::testSteamTotp() QCOMPARE(digits, quint8(Totp::ENCODER_STEAM)); QCOMPARE(step, quint8(30)); - QByteArray seed = QString("63BEDWCQZKTQWPESARIERL5DTTQFCJTK").toLatin1(); // These time/value pairs were created by running the Steam Guard function of the diff --git a/tests/TestWildcardMatcher.cpp b/tests/TestWildcardMatcher.cpp index e5d1d117..b7b92fdd 100644 --- a/tests/TestWildcardMatcher.cpp +++ b/tests/TestWildcardMatcher.cpp @@ -70,8 +70,7 @@ void TestWildcardMatcher::verifyMatchResult(QString pattern, bool expected) { if (expected) { verifyMatch(pattern); - } - else { + } else { verifyNoMatch(pattern); } } diff --git a/tests/TestYkChallengeResponseKey.cpp b/tests/TestYkChallengeResponseKey.cpp index 276ba732..126d0031 100644 --- a/tests/TestYkChallengeResponseKey.cpp +++ b/tests/TestYkChallengeResponseKey.cpp @@ -40,9 +40,7 @@ void TestYubiKeyChalResp::init() void TestYubiKeyChalResp::detectDevices() { - connect(YubiKey::instance(), SIGNAL(detected(int,bool)), - SLOT(ykDetected(int,bool)), - Qt::QueuedConnection); + connect(YubiKey::instance(), SIGNAL(detected(int, bool)), SLOT(ykDetected(int, bool)), Qt::QueuedConnection); QtConcurrent::run(YubiKey::instance(), &YubiKey::detect); // need to wait for the hardware (that's hopefully plugged in)... diff --git a/tests/TestYkChallengeResponseKey.h b/tests/TestYkChallengeResponseKey.h index 82223ec3..81253cc9 100644 --- a/tests/TestYkChallengeResponseKey.h +++ b/tests/TestYkChallengeResponseKey.h @@ -24,7 +24,7 @@ #include "keys/YkChallengeResponseKey.h" -class TestYubiKeyChalResp: public QObject +class TestYubiKeyChalResp : public QObject { Q_OBJECT diff --git a/tests/gui/TemporaryFile.cpp b/tests/gui/TemporaryFile.cpp index 7c7a1c5d..b6d20848 100644 --- a/tests/gui/TemporaryFile.cpp +++ b/tests/gui/TemporaryFile.cpp @@ -56,7 +56,7 @@ void TemporaryFile::close() #endif } -qint64 TemporaryFile::write(const char *data, qint64 maxSize) +qint64 TemporaryFile::write(const char* data, qint64 maxSize) { #ifdef Q_OS_WIN return m_file.write(data, maxSize); @@ -65,7 +65,7 @@ qint64 TemporaryFile::write(const char *data, qint64 maxSize) #endif } -qint64 TemporaryFile::write(const QByteArray &byteArray) +qint64 TemporaryFile::write(const QByteArray& byteArray) { #ifdef Q_OS_WIN return m_file.write(byteArray); diff --git a/tests/gui/TemporaryFile.h b/tests/gui/TemporaryFile.h index f1cff3ef..8a98d923 100644 --- a/tests/gui/TemporaryFile.h +++ b/tests/gui/TemporaryFile.h @@ -19,8 +19,8 @@ #ifndef KEEPASSX_TEMPORARYFILE_H #define KEEPASSX_TEMPORARYFILE_H -#include #include +#include #include /** @@ -48,8 +48,8 @@ public: bool open(); void close(); - qint64 write(const char *data, qint64 maxSize); - qint64 write(const QByteArray &byteArray); + qint64 write(const char* data, qint64 maxSize); + qint64 write(const QByteArray& byteArray); QString fileName() const; QString filePath() const; diff --git a/tests/gui/TestGui.cpp b/tests/gui/TestGui.cpp index c736ea48..0fe49eb9 100644 --- a/tests/gui/TestGui.cpp +++ b/tests/gui/TestGui.cpp @@ -21,22 +21,22 @@ #include #include -#include -#include -#include -#include -#include #include -#include -#include +#include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include +#include #include #include -#include -#include -#include -#include #include "config-keepassx-tests.h" #include "core/Config.h" @@ -48,21 +48,21 @@ #include "crypto/Crypto.h" #include "crypto/kdf/AesKdf.h" #include "format/KeePass2Reader.h" +#include "gui/CloneDialog.h" #include "gui/DatabaseTabWidget.h" #include "gui/DatabaseWidget.h" -#include "gui/CloneDialog.h" -#include "gui/PasswordEdit.h" -#include "gui/TotpDialog.h" -#include "gui/SetupTotpDialog.h" #include "gui/FileDialog.h" #include "gui/MainWindow.h" #include "gui/MessageBox.h" +#include "gui/PasswordEdit.h" #include "gui/SearchWidget.h" +#include "gui/SetupTotpDialog.h" +#include "gui/TotpDialog.h" #include "gui/entry/EditEntryWidget.h" #include "gui/entry/EntryView.h" +#include "gui/group/EditGroupWidget.h" #include "gui/group/GroupModel.h" #include "gui/group/GroupView.h" -#include "gui/group/EditGroupWidget.h" #include "keys/PasswordKey.h" void TestGui::initTestCase() @@ -228,7 +228,7 @@ void TestGui::testAutoreloadDatabase() // the General group contains one entry from the new db data QCOMPARE(m_db->rootGroup()->findChildByName("General")->entries().size(), 1); - QVERIFY(! m_tabWidget->tabText(m_tabWidget->currentIndex()).endsWith("*")); + QVERIFY(!m_tabWidget->tabText(m_tabWidget->currentIndex()).endsWith("*")); // Reset the state cleanup(); @@ -252,7 +252,7 @@ void TestGui::testAutoreloadDatabase() cleanup(); init(); - // Test accepting a merge of edits into autoreload + // Test accepting a merge of edits into autoreload // Turn on autoload so we only get one messagebox (for the merge) config()->set("AutoReloadOnChange", true); @@ -559,17 +559,17 @@ void TestGui::testPasswordEntryEntropy() editNewPassword->setText(""); QTest::keyClicks(editNewPassword, "correcthorsebatterystaple"); - QCOMPARE(entropyLabel->text(), QString("Entropy: 47.98 bit")); + QCOMPARE(entropyLabel->text(), QString("Entropy: 47.98 bit")); QCOMPARE(strengthLabel->text(), QString("Password Quality: Weak")); editNewPassword->setText(""); QTest::keyClicks(editNewPassword, "YQC3kbXbjC652dTDH"); - QCOMPARE(entropyLabel->text(), QString("Entropy: 95.83 bit")); + QCOMPARE(entropyLabel->text(), QString("Entropy: 95.83 bit")); QCOMPARE(strengthLabel->text(), QString("Password Quality: Good")); editNewPassword->setText(""); QTest::keyClicks(editNewPassword, "Bs5ZFfthWzR8DGFEjaCM6bGqhmCT4km"); - QCOMPARE(entropyLabel->text(), QString("Entropy: 174.59 bit")); + QCOMPARE(entropyLabel->text(), QString("Entropy: 174.59 bit")); QCOMPARE(strengthLabel->text(), QString("Password Quality: Excellent")); } @@ -613,7 +613,7 @@ void TestGui::testDicewareEntryEntropy() QLabel* entropyLabel = editEntryWidget->findChild("entropyLabel"); QLabel* strengthLabel = editEntryWidget->findChild("strengthLabel"); - QCOMPARE(entropyLabel->text(), QString("Entropy: 77.55 bit")); + QCOMPARE(entropyLabel->text(), QString("Entropy: 77.55 bit")); QCOMPARE(strengthLabel->text(), QString("Password Quality: Good")); } @@ -726,7 +726,7 @@ void TestGui::testSearch() QTest::mouseClick(searchTextEdit, Qt::LeftButton); QTRY_VERIFY(searchTextEdit->hasFocus()); // Test password copy - QClipboard *clipboard = QApplication::clipboard(); + QClipboard* clipboard = QApplication::clipboard(); QTest::keyClick(searchTextEdit, Qt::Key_C, Qt::ControlModifier); QModelIndex searchedItem = entryView->model()->index(0, 1); Entry* searchedEntry = entryView->entryFromIndex(searchedItem); @@ -744,7 +744,7 @@ void TestGui::testSearch() QModelIndex rootGroupIndex = groupView->model()->index(0, 0); clickIndex(groupView->model()->index(0, 0, rootGroupIndex), groupView, Qt::LeftButton); QCOMPARE(groupView->currentGroup()->name(), QString("General")); - + searchWidget->setLimitGroup(false); QTRY_COMPARE(entryView->model()->rowCount(), 2); searchWidget->setLimitGroup(true); @@ -822,7 +822,8 @@ void TestGui::testDeleteEntry() QCOMPARE(groupView->currentGroup(), m_db->rootGroup()); QModelIndex rootGroupIndex = groupView->model()->index(0, 0); clickIndex(groupView->model()->index(groupView->model()->rowCount(rootGroupIndex) - 1, 0, rootGroupIndex), - groupView, Qt::LeftButton); + groupView, + Qt::LeftButton); QCOMPARE(groupView->currentGroup()->name(), m_db->metadata()->recycleBin()->name()); clickIndex(entryView->model()->index(0, 1), entryView, Qt::LeftButton); @@ -843,8 +844,7 @@ void TestGui::testDeleteEntry() QCOMPARE(entryView->model()->rowCount(), 0); QCOMPARE(m_db->metadata()->recycleBin()->entries().size(), 0); - clickIndex(groupView->model()->index(0, 0), - groupView, Qt::LeftButton); + clickIndex(groupView->model()->index(0, 0), groupView, Qt::LeftButton); QCOMPARE(groupView->currentGroup(), m_db->rootGroup()); } @@ -860,9 +860,9 @@ void TestGui::testCloneEntry() triggerAction("actionEntryClone"); - CloneDialog* cloneDialog = m_dbWidget->findChild("CloneDialog"); - QDialogButtonBox* cloneButtonBox = cloneDialog->findChild("buttonBox"); - QTest::mouseClick(cloneButtonBox->button(QDialogButtonBox::Ok), Qt::LeftButton); + CloneDialog* cloneDialog = m_dbWidget->findChild("CloneDialog"); + QDialogButtonBox* cloneButtonBox = cloneDialog->findChild("buttonBox"); + QTest::mouseClick(cloneButtonBox->button(QDialogButtonBox::Ok), Qt::LeftButton); QCOMPARE(entryView->model()->rowCount(), 2); Entry* entryClone = entryView->entryFromIndex(entryView->model()->index(1, 1)); @@ -909,7 +909,7 @@ void TestGui::testEntryPlaceholders() QCOMPARE(entry->url(), QString("{TITLE}.{USERNAME}")); // Test password copy - QClipboard *clipboard = QApplication::clipboard(); + QClipboard* clipboard = QApplication::clipboard(); m_dbWidget->copyURL(); QTRY_COMPARE(clipboard->text(), QString("test.john")); } @@ -941,22 +941,19 @@ void TestGui::testDragAndDropGroup() QAbstractItemModel* groupModel = m_dbWidget->findChild("groupView")->model(); QModelIndex rootIndex = groupModel->index(0, 0); - dragAndDropGroup(groupModel->index(0, 0, rootIndex), - groupModel->index(1, 0, rootIndex), - -1, true, "Windows", 0); + dragAndDropGroup(groupModel->index(0, 0, rootIndex), groupModel->index(1, 0, rootIndex), -1, true, "Windows", 0); // dropping parent on child is supposed to fail dragAndDropGroup(groupModel->index(0, 0, rootIndex), groupModel->index(0, 0, groupModel->index(0, 0, rootIndex)), - -1, false, "NewDatabase", 0); + -1, + false, + "NewDatabase", + 0); - dragAndDropGroup(groupModel->index(1, 0, rootIndex), - rootIndex, - 0, true, "NewDatabase", 0); + dragAndDropGroup(groupModel->index(1, 0, rootIndex), rootIndex, 0, true, "NewDatabase", 0); - dragAndDropGroup(groupModel->index(0, 0, rootIndex), - rootIndex, - -1, true, "NewDatabase", 4); + dragAndDropGroup(groupModel->index(0, 0, rootIndex), rootIndex, -1, true, "NewDatabase", 4); } void TestGui::testSaveAs() @@ -1034,7 +1031,6 @@ void TestGui::testKeePass1Import() MessageBox::setNextAnswer(QMessageBox::No); triggerAction("actionDatabaseClose"); Tools::wait(100); - } void TestGui::testDatabaseLocking() @@ -1059,7 +1055,7 @@ void TestGui::testDatabaseLocking() void TestGui::testDragAndDropKdbxFiles() { - const int openedDatabasesCount = m_tabWidget->count(); + const int openedDatabasesCount = m_tabWidget->count(); const QString badDatabaseFilePath(QString(KEEPASSX_TEST_DATA_DIR).append("/NotDatabase.notkdbx")); QMimeData badMimeData; @@ -1183,8 +1179,12 @@ void TestGui::triggerAction(const QString& name) action->trigger(); } -void TestGui::dragAndDropGroup(const QModelIndex& sourceIndex, const QModelIndex& targetIndex, int row, - bool expectedResult, const QString& expectedParentName, int expectedPos) +void TestGui::dragAndDropGroup(const QModelIndex& sourceIndex, + const QModelIndex& targetIndex, + int row, + bool expectedResult, + const QString& expectedParentName, + int expectedPos) { QVERIFY(sourceIndex.isValid()); QVERIFY(targetIndex.isValid()); @@ -1203,7 +1203,9 @@ void TestGui::dragAndDropGroup(const QModelIndex& sourceIndex, const QModelIndex QCOMPARE(group->parentGroup()->children().indexOf(group), expectedPos); } -void TestGui::clickIndex(const QModelIndex& index, QAbstractItemView* view, Qt::MouseButton button, +void TestGui::clickIndex(const QModelIndex& index, + QAbstractItemView* view, + Qt::MouseButton button, Qt::KeyboardModifiers stateKey) { QTest::mouseClick(view->viewport(), button, stateKey, view->visualRect(index).center()); diff --git a/tests/gui/TestGui.h b/tests/gui/TestGui.h index e7232cca..2a3708c4 100644 --- a/tests/gui/TestGui.h +++ b/tests/gui/TestGui.h @@ -69,9 +69,15 @@ private: int addCannedEntries(); void checkDatabase(QString dbFileName = ""); void triggerAction(const QString& name); - void dragAndDropGroup(const QModelIndex& sourceIndex, const QModelIndex& targetIndex, int row, - bool expectedResult, const QString& expectedParentName, int expectedPos); - void clickIndex(const QModelIndex& index, QAbstractItemView* view, Qt::MouseButton button, + void dragAndDropGroup(const QModelIndex& sourceIndex, + const QModelIndex& targetIndex, + int row, + bool expectedResult, + const QString& expectedParentName, + int expectedPos); + void clickIndex(const QModelIndex& index, + QAbstractItemView* view, + Qt::MouseButton button, Qt::KeyboardModifiers stateKey = 0); QPointer m_mainWindow; diff --git a/tests/mock/MockChallengeResponseKey.h b/tests/mock/MockChallengeResponseKey.h index af795d93..011b06e5 100644 --- a/tests/mock/MockChallengeResponseKey.h +++ b/tests/mock/MockChallengeResponseKey.h @@ -37,4 +37,4 @@ private: QByteArray m_secret; }; -#endif //KEEPASSXC_MOCKCHALLENGERESPONSEKEY_H +#endif // KEEPASSXC_MOCKCHALLENGERESPONSEKEY_H From 72bbf127476ed44ad3b617c22203ddd4bc3e1f84 Mon Sep 17 00:00:00 2001 From: Jonathan Hult Date: Mon, 2 Apr 2018 22:11:50 -0400 Subject: [PATCH 019/267] Update link to note about HTTP in README [ci skip] (#1637) From c773d85876d7c5ae1ca5fa02adda6fa4da88376a Mon Sep 17 00:00:00 2001 From: varjolintu Date: Tue, 3 Apr 2018 10:37:28 +0300 Subject: [PATCH 020/267] Change socket location in macOS to temporary dir --- src/browser/NativeMessagingBase.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/browser/NativeMessagingBase.cpp b/src/browser/NativeMessagingBase.cpp index 64a6df48..4152c1d7 100644 --- a/src/browser/NativeMessagingBase.cpp +++ b/src/browser/NativeMessagingBase.cpp @@ -131,13 +131,11 @@ void NativeMessagingBase::sendReply(const QString& reply) QString NativeMessagingBase::getLocalServerPath() const { -#if defined(Q_OS_WIN) - return QStandardPaths::writableLocation(QStandardPaths::TempLocation) + "/kpxc_server"; -#elif defined(Q_OS_UNIX) && !defined(Q_OS_MAC) +#if defined(Q_OS_UNIX) && !defined(Q_OS_MAC) // Use XDG_RUNTIME_DIR instead of /tmp/ if it's available QString path = QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation) + "/kpxc_server"; return path.isEmpty() ? "/tmp/kpxc_server" : path; -#else // Q_OS_MAC and others - return "/tmp/kpxc_server"; +#else // Q_OS_MAC, Q_OS_WIN and others + return QStandardPaths::writableLocation(QStandardPaths::TempLocation) + "/kpxc_server"; #endif } From 9b6c589b9ce5127be70d031905f9cbd73b6c74e6 Mon Sep 17 00:00:00 2001 From: Weslly Date: Wed, 4 Apr 2018 23:01:52 -0300 Subject: [PATCH 021/267] Fix build error on mac introduced on 8324d03f0a015e62b6182843b4478226a5197090 --- src/core/Tools.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/Tools.cpp b/src/core/Tools.cpp index 47a0df03..6877e5c8 100644 --- a/src/core/Tools.cpp +++ b/src/core/Tools.cpp @@ -47,8 +47,8 @@ #endif #ifdef HAVE_PT_DENY_ATTACH -#include #include +#include #endif namespace Tools From 586961013dcc3bfcd54ce86041cb6406a221743f Mon Sep 17 00:00:00 2001 From: Weslly Date: Thu, 5 Apr 2018 08:59:42 -0300 Subject: [PATCH 022/267] Disable clang-format on Tools.cpp include order --- src/core/Tools.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/core/Tools.cpp b/src/core/Tools.cpp index 6877e5c8..5f51fa47 100644 --- a/src/core/Tools.cpp +++ b/src/core/Tools.cpp @@ -47,8 +47,10 @@ #endif #ifdef HAVE_PT_DENY_ATTACH +// clang-format off #include #include +// clang-format on #endif namespace Tools From ddc4b9b7d548c6b753a7f161085990bdac7e88c6 Mon Sep 17 00:00:00 2001 From: Vladimir Svyatski Date: Fri, 6 Apr 2018 23:23:52 +0300 Subject: [PATCH 023/267] Remove empty context menu from the main menu --- src/gui/MainWindow.ui | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/gui/MainWindow.ui b/src/gui/MainWindow.ui index 648a0e61..49c0a6f3 100644 --- a/src/gui/MainWindow.ui +++ b/src/gui/MainWindow.ui @@ -175,6 +175,9 @@ + + Qt::PreventContextMenu + &Database From 677b8caa63964e9891585d5594a3a33b276de610 Mon Sep 17 00:00:00 2001 From: Vladimir Svyatski Date: Mon, 9 Apr 2018 21:09:31 +0300 Subject: [PATCH 024/267] Add UI setting "Hide toolbar (icons)" --- src/gui/SettingsWidget.cpp | 2 ++ src/gui/SettingsWidgetGeneral.ui | 9 ++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/gui/SettingsWidget.cpp b/src/gui/SettingsWidget.cpp index be2f4cd4..b16356d8 100644 --- a/src/gui/SettingsWidget.cpp +++ b/src/gui/SettingsWidget.cpp @@ -140,6 +140,7 @@ void SettingsWidget::loadSettings() } m_generalUi->detailsHideCheckBox->setChecked(config()->get("GUI/HideDetailsView").toBool()); + m_generalUi->toolbarHideCheckBox->setChecked(config()->get("GUI/HideToolbar").toBool()); m_generalUi->systrayShowCheckBox->setChecked(config()->get("GUI/ShowTrayIcon").toBool()); m_generalUi->systrayDarkIconCheckBox->setChecked(config()->get("GUI/DarkTrayIcon").toBool()); m_generalUi->systrayMinimizeToTrayCheckBox->setChecked(config()->get("GUI/MinimizeToTray").toBool()); @@ -209,6 +210,7 @@ void SettingsWidget::saveSettings() config()->set("GUI/Language", m_generalUi->languageComboBox->itemData(currentLangIndex).toString()); config()->set("GUI/HideDetailsView", m_generalUi->detailsHideCheckBox->isChecked()); + config()->set("GUI/HideToolbar", m_generalUi->toolbarHideCheckBox->isChecked()); config()->set("GUI/ShowTrayIcon", m_generalUi->systrayShowCheckBox->isChecked()); config()->set("GUI/DarkTrayIcon", m_generalUi->systrayDarkIconCheckBox->isChecked()); config()->set("GUI/MinimizeToTray", m_generalUi->systrayMinimizeToTrayCheckBox->isChecked()); diff --git a/src/gui/SettingsWidgetGeneral.ui b/src/gui/SettingsWidgetGeneral.ui index 5ed952f1..d7535f6e 100644 --- a/src/gui/SettingsWidgetGeneral.ui +++ b/src/gui/SettingsWidgetGeneral.ui @@ -7,7 +7,7 @@ 0 0 684 - 732 + 794 @@ -179,6 +179,13 @@ General + + + + Hide toolbar (icons) + + + From d843ad414a6a0ab26c27c5d37f883d7efdcccbae Mon Sep 17 00:00:00 2001 From: Vladimir Svyatski Date: Mon, 9 Apr 2018 22:06:48 +0300 Subject: [PATCH 025/267] Use the "Hide toolbar" setting --- src/gui/MainWindow.cpp | 2 +- src/gui/MainWindow.ui | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp index 95bdd3fa..8f7caa7c 100644 --- a/src/gui/MainWindow.cpp +++ b/src/gui/MainWindow.cpp @@ -133,7 +133,7 @@ MainWindow::MainWindow() setAcceptDrops(true); - m_ui->toolBar->setContextMenuPolicy(Qt::PreventContextMenu); + m_ui->toolBar->setHidden(config()->get("GUI/HideToolbar").toBool()); // Setup the search widget in the toolbar SearchWidget* search = new SearchWidget(); diff --git a/src/gui/MainWindow.ui b/src/gui/MainWindow.ui index 49c0a6f3..b67e6ffd 100644 --- a/src/gui/MainWindow.ui +++ b/src/gui/MainWindow.ui @@ -175,6 +175,14 @@ + + + 0 + 0 + 800 + 30 + + Qt::PreventContextMenu @@ -280,6 +288,9 @@ + + Qt::PreventContextMenu + false From 57860fc33cc911f2dced683dfa25effe30aa1a37 Mon Sep 17 00:00:00 2001 From: Vladimir Svyatski Date: Mon, 9 Apr 2018 22:33:08 +0300 Subject: [PATCH 026/267] Fix to apply "Hide toolbar" without restart --- src/gui/MainWindow.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp index 8f7caa7c..8cdff237 100644 --- a/src/gui/MainWindow.cpp +++ b/src/gui/MainWindow.cpp @@ -133,8 +133,6 @@ MainWindow::MainWindow() setAcceptDrops(true); - m_ui->toolBar->setHidden(config()->get("GUI/HideToolbar").toBool()); - // Setup the search widget in the toolbar SearchWidget* search = new SearchWidget(); search->connectSignals(m_actionMultiplexer); @@ -841,6 +839,8 @@ void MainWindow::applySettingsChanges() m_inactivityTimer->deactivate(); } + m_ui->toolBar->setHidden(config()->get("GUI/HideToolbar").toBool()); + updateTrayIcon(); } From bbfac926729cd1abb68eb1f5046788be0a16c073 Mon Sep 17 00:00:00 2001 From: Vladimir Svyatski Date: Tue, 10 Apr 2018 08:27:23 +0300 Subject: [PATCH 027/267] Add requested changes to PR #1819. --- src/core/Config.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/core/Config.cpp b/src/core/Config.cpp index ccdc24fd..6719e37d 100644 --- a/src/core/Config.cpp +++ b/src/core/Config.cpp @@ -149,6 +149,7 @@ void Config::init(const QString& fileName) m_defaults.insert("security/autotypeask", true); m_defaults.insert("security/IconDownloadFallbackToGoogle", false); m_defaults.insert("GUI/Language", "system"); + m_defaults.insert("GUI/HideToolbar", false); m_defaults.insert("GUI/ShowTrayIcon", false); m_defaults.insert("GUI/DarkTrayIcon", false); m_defaults.insert("GUI/MinimizeToTray", false); From 2110ae4d3322229d137c5187e6f5e4aaecc8de4a Mon Sep 17 00:00:00 2001 From: varjolintu Date: Mon, 16 Apr 2018 11:41:45 +0300 Subject: [PATCH 028/267] Create KPH attribute for browser integration --- src/browser/BrowserService.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/browser/BrowserService.cpp b/src/browser/BrowserService.cpp index 331bc6b7..77c89ef0 100644 --- a/src/browser/BrowserService.cpp +++ b/src/browser/BrowserService.cpp @@ -607,6 +607,10 @@ QJsonObject BrowserService::prepareEntry(const Entry* entry) res["name"] = entry->resolveMultiplePlaceholders(entry->title()); res["uuid"] = entry->resolveMultiplePlaceholders(entry->uuid().toHex()); + if (entry->hasTotp()) { + res["totp"] = entry->totp(); + } + if (BrowserSettings::supportKphFields()) { const EntryAttributes* attr = entry->attributes(); QJsonArray stringFields; From 64917bd9fbb065bbd46b1dae9221d5a30647d76c Mon Sep 17 00:00:00 2001 From: louib Date: Fri, 27 Apr 2018 21:29:00 -0400 Subject: [PATCH 029/267] Disable merge button when db is locked. --- src/gui/MainWindow.cpp | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp index 95bdd3fa..af127171 100644 --- a/src/gui/MainWindow.cpp +++ b/src/gui/MainWindow.cpp @@ -423,8 +423,20 @@ void MainWindow::openDatabase(const QString& fileName, const QString& pw, const void MainWindow::setMenuActionState(DatabaseWidget::Mode mode) { int currentIndex = m_ui->stackedWidget->currentIndex(); + bool inDatabaseTabWidget = (currentIndex == DatabaseTabScreen); bool inWelcomeWidget = (currentIndex == WelcomeScreen); + bool inDatabaseTabWidgetOrWelcomeWidget = inDatabaseTabWidget || inWelcomeWidget; + + m_ui->actionDatabaseMerge->setEnabled(inDatabaseTabWidget); + + m_ui->actionDatabaseNew->setEnabled(inDatabaseTabWidgetOrWelcomeWidget); + m_ui->actionDatabaseOpen->setEnabled(inDatabaseTabWidgetOrWelcomeWidget); + m_ui->menuRecentDatabases->setEnabled(inDatabaseTabWidgetOrWelcomeWidget); + m_ui->menuImport->setEnabled(inDatabaseTabWidgetOrWelcomeWidget); + m_ui->actionRepairDatabase->setEnabled(inDatabaseTabWidgetOrWelcomeWidget); + + m_ui->actionLockDatabases->setEnabled(m_ui->tabWidget->hasLockableDatabases()); if (inDatabaseTabWidget && m_ui->tabWidget->currentIndex() != -1) { DatabaseWidget* dbWidget = m_ui->tabWidget->currentDatabaseWidget(); @@ -537,16 +549,6 @@ void MainWindow::setMenuActionState(DatabaseWidget::Mode mode) m_searchWidgetAction->setEnabled(false); } - bool inDatabaseTabWidgetOrWelcomeWidget = inDatabaseTabWidget || inWelcomeWidget; - m_ui->actionDatabaseNew->setEnabled(inDatabaseTabWidgetOrWelcomeWidget); - m_ui->actionDatabaseOpen->setEnabled(inDatabaseTabWidgetOrWelcomeWidget); - m_ui->menuRecentDatabases->setEnabled(inDatabaseTabWidgetOrWelcomeWidget); - m_ui->menuImport->setEnabled(inDatabaseTabWidgetOrWelcomeWidget); - m_ui->actionDatabaseMerge->setEnabled(inDatabaseTabWidget); - m_ui->actionRepairDatabase->setEnabled(inDatabaseTabWidgetOrWelcomeWidget); - - m_ui->actionLockDatabases->setEnabled(m_ui->tabWidget->hasLockableDatabases()); - if ((currentIndex == PasswordGeneratorScreen) != m_ui->actionPasswordGenerator->isChecked()) { bool blocked = m_ui->actionPasswordGenerator->blockSignals(true); m_ui->actionPasswordGenerator->toggle(); From f25c8d3d2a41a6014e1aff4ffe61e63d488bc513 Mon Sep 17 00:00:00 2001 From: louib Date: Mon, 30 Apr 2018 17:07:07 -0400 Subject: [PATCH 030/267] Adding a GUI test. --- tests/gui/TestGui.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/gui/TestGui.cpp b/tests/gui/TestGui.cpp index 0fe49eb9..90f23a2e 100644 --- a/tests/gui/TestGui.cpp +++ b/tests/gui/TestGui.cpp @@ -1042,6 +1042,11 @@ void TestGui::testDatabaseLocking() QCOMPARE(m_tabWidget->tabText(0).remove('&'), origDbName + " [locked]"); + QAction* actionDatabaseMerge = m_mainWindow->findChild("actionDatabaseMerge", Qt::FindChildrenRecursively); + QCOMPARE(actionDatabaseMerge->isEnabled(), false); + QAction* actionDatabaseSave = m_mainWindow->findChild("actionDatabaseSave", Qt::FindChildrenRecursively); + QCOMPARE(actionDatabaseSave->isEnabled(), false); + QWidget* dbWidget = m_tabWidget->currentDatabaseWidget(); QWidget* unlockDatabaseWidget = dbWidget->findChild("unlockDatabaseWidget"); QWidget* editPassword = unlockDatabaseWidget->findChild("editPassword"); @@ -1051,6 +1056,9 @@ void TestGui::testDatabaseLocking() QTest::keyClick(editPassword, Qt::Key_Enter); QCOMPARE(m_tabWidget->tabText(0).remove('&'), origDbName); + + actionDatabaseMerge = m_mainWindow->findChild("actionDatabaseMerge", Qt::FindChildrenRecursively); + QCOMPARE(actionDatabaseMerge->isEnabled(), true); } void TestGui::testDragAndDropKdbxFiles() From f524d51624f22980742996f7601471d32b46202a Mon Sep 17 00:00:00 2001 From: Jonathan White Date: Wed, 9 May 2018 06:56:38 -0400 Subject: [PATCH 031/267] Update snapcraft to use ppa packages --- snapcraft.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/snapcraft.yaml b/snapcraft.yaml index 5a3597c3..61315bc7 100644 --- a/snapcraft.yaml +++ b/snapcraft.yaml @@ -33,7 +33,7 @@ parts: - -DWITH_XC_ALL=ON build-packages: - g++ - - libgcrypt20-dev + - libgcrypt20-18-dev - libqt5x11extras5-dev - qtbase5-dev - qttools5-dev @@ -45,9 +45,11 @@ parts: - libykpers-1-dev - libcurl4-openssl-dev - libsodium-dev + - libargon2-0-dev stage-packages: - dbus - qttranslations5-l10n # common translations + - libgcrypt20-18 install: | sed -i 's|Icon=keepassxc|Icon=${SNAP}/usr/share/icons/hicolor/256x256/apps/keepassxc.png|g' $SNAPCRAFT_PART_INSTALL/usr/share/applications/org.keepassxc.KeePassXC.desktop organize: From 1d499d2f29155a11da1df5138210d144a85dabb6 Mon Sep 17 00:00:00 2001 From: Chih-Hsuan Yen Date: Sat, 12 May 2018 23:01:01 +0800 Subject: [PATCH 032/267] SSH Agent: Don't mark the entry dirty when the public key is changed That occurs when the key is decrypted and/or added to the agent, and neither of them indicates changes in entry data. Fixes #1909 --- src/gui/entry/EditEntryWidget.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/gui/entry/EditEntryWidget.cpp b/src/gui/entry/EditEntryWidget.cpp index 59f2481a..837b2f59 100644 --- a/src/gui/entry/EditEntryWidget.cpp +++ b/src/gui/entry/EditEntryWidget.cpp @@ -275,7 +275,6 @@ void EditEntryWidget::setupEntryUpdate() connect( m_sshAgentUi->attachmentComboBox, SIGNAL(editTextChanged(const QString&)), this, SLOT(setUnsavedChanges())); connect(m_sshAgentUi->externalFileEdit, SIGNAL(textChanged(const QString&)), this, SLOT(setUnsavedChanges())); - connect(m_sshAgentUi->publicKeyEdit, SIGNAL(textChanged()), this, SLOT(setUnsavedChanges())); connect(m_sshAgentUi->addKeyToAgentCheckBox, SIGNAL(stateChanged(int)), this, SLOT(setUnsavedChanges())); connect(m_sshAgentUi->removeKeyFromAgentCheckBox, SIGNAL(stateChanged(int)), this, SLOT(setUnsavedChanges())); connect( From bf5f82ff2761aac5334ba561ab26e242c77d6c3a Mon Sep 17 00:00:00 2001 From: varjolintu Date: Fri, 6 Apr 2018 11:33:17 +0300 Subject: [PATCH 033/267] Change Unix socket location --- src/browser/NativeMessagingBase.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/browser/NativeMessagingBase.cpp b/src/browser/NativeMessagingBase.cpp index f2bf3bb3..ef35705a 100644 --- a/src/browser/NativeMessagingBase.cpp +++ b/src/browser/NativeMessagingBase.cpp @@ -134,11 +134,12 @@ void NativeMessagingBase::sendReply(const QString& reply) QString NativeMessagingBase::getLocalServerPath() const { + const QString serverPath = "/kpxc_server"; #if defined(Q_OS_UNIX) && !defined(Q_OS_MAC) - // Use XDG_RUNTIME_DIR instead of /tmp/ if it's available - QString path = QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation) + "/kpxc_server"; - return path.isEmpty() ? "/tmp/kpxc_server" : path; + // Use XDG_RUNTIME_DIR instead of /tmp if it's available + QString path = QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation); + return path.isEmpty() ? QStandardPaths::writableLocation(QStandardPaths::TempLocation) + serverPath : path + serverPath; #else // Q_OS_MAC, Q_OS_WIN and others - return QStandardPaths::writableLocation(QStandardPaths::TempLocation) + "/kpxc_server"; + return QStandardPaths::writableLocation(QStandardPaths::TempLocation) + serverPath; #endif } From 3bbc6ac0e6298d27bfe0c41999460cafda8edf18 Mon Sep 17 00:00:00 2001 From: Markus Rathgeb Date: Wed, 16 May 2018 09:55:14 +0200 Subject: [PATCH 034/267] fix missing include for Qt 5.11 Qt 5.11 cleanes up the internal headers and so consumers could fail by missing includes. See: https://bugs.gentoo.org/655844 Signed-off-by: Markus Rathgeb --- src/gui/entry/EditEntryWidget.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/gui/entry/EditEntryWidget.cpp b/src/gui/entry/EditEntryWidget.cpp index 837b2f59..db9f5760 100644 --- a/src/gui/entry/EditEntryWidget.cpp +++ b/src/gui/entry/EditEntryWidget.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include "autotype/AutoType.h" #include "core/Config.h" From dbc759332805380abf61dd9d80b054d720988a55 Mon Sep 17 00:00:00 2001 From: Jonathan White Date: Wed, 16 May 2018 22:39:39 -0400 Subject: [PATCH 035/267] Build snaps using custom Docker image * Added --snapcraft option to release-tool build command --- ci/snapcraft/Dockerfile | 51 +++++++++++++++++++++++++++++++++++++++++ release-tool | 51 ++++++++++++++++++++++++++++------------- snapcraft.yaml | 33 ++++++++++++-------------- 3 files changed, 101 insertions(+), 34 deletions(-) create mode 100644 ci/snapcraft/Dockerfile diff --git a/ci/snapcraft/Dockerfile b/ci/snapcraft/Dockerfile new file mode 100644 index 00000000..37b3742d --- /dev/null +++ b/ci/snapcraft/Dockerfile @@ -0,0 +1,51 @@ +# KeePassXC Linux Release Build Dockerfile +# Copyright (C) 2017-2018 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 . + +FROM snapcore/snapcraft + +ENV REBUILD_COUNTER=1 + +ENV QT5_VERSION=510 +ENV QT5_PPA_VERSION=5.10.1 + +RUN set -x \ + && apt update -y \ + && apt -y install software-properties-common + +RUN set -x \ + && add-apt-repository ppa:phoerious/keepassxc + +RUN set -x \ + && apt update -y \ + && apt-get -y --no-install-recommends install \ + build-essential \ + cmake \ + libgcrypt20-18-dev \ + libargon2-0-dev \ + libsodium-dev \ + qtbase5-dev \ + qttools5-dev \ + qttools5-dev-tools \ + zlib1g-dev \ + libyubikey-dev \ + libykpers-1-dev \ + libxi-dev \ + libxtst-dev \ + xvfb + +RUN set -x \ + && apt-get autoremove --purge + diff --git a/release-tool b/release-tool index 74f20590..f2a7b811 100755 --- a/release-tool +++ b/release-tool @@ -41,6 +41,7 @@ BUILD_PLUGINS="all" INSTALL_PREFIX="/usr/local" BUILD_SOURCE_TARBALL=true BUILD_SNAPSHOT=false +BUILD_SNAPCRAFT=false ORIG_BRANCH="" ORIG_CWD="$(pwd)" @@ -106,6 +107,8 @@ Options: This option has no effect if --build is not set. --container-name Docker container name (default: '${DOCKER_CONTAINER_NAME}') The container must not exist already + --snapcraft Create and use docker image to build snapcraft distribution. + This option has no effect if --docker-image is not set. -c, --cmake-options Additional CMake options for compiling the sources --compiler Compiler to use (default: '${COMPILER}') -m, --make-options Make options for compiling sources (default: '${MAKE_OPTIONS}') @@ -542,6 +545,10 @@ build() { --container-name) DOCKER_CONTAINER_NAME="$2" shift ;; + + --snapcraft) + BUILD_SNAPCRAFT=true + shift ;; -c|--cmake-options) CMAKE_OPTIONS="$2" @@ -703,22 +710,34 @@ build() { ${SRC_DIR}/AppImage-Recipe.sh "$APP_NAME" "$RELEASE_NAME" fi else - mkdir -p "${OUTPUT_DIR}/bin-release" - - logInfo "Launching Docker container to compile sources..." - - docker run --name "$DOCKER_CONTAINER_NAME" --rm \ - --cap-add SYS_ADMIN --security-opt apparmor:unconfined --device /dev/fuse \ - -e "CC=${CC}" -e "CXX=${CXX}" \ - -v "$(realpath "$SRC_DIR"):/keepassxc/src:ro" \ - -v "$(realpath "$OUTPUT_DIR"):/keepassxc/out:rw" \ - "$DOCKER_IMAGE" \ - bash -c "cd /keepassxc/out/build-release && \ - cmake -DCMAKE_BUILD_TYPE=Release -DWITH_TESTS=Off $CMAKE_OPTIONS \ - -DCMAKE_INSTALL_PREFIX=\"${INSTALL_PREFIX}\" \ - -DKEEPASSXC_DIST_TYPE=AppImage /keepassxc/src && \ - make $MAKE_OPTIONS && make DESTDIR=/keepassxc/out/bin-release install/strip && \ - /keepassxc/src/AppImage-Recipe.sh "$APP_NAME" "$RELEASE_NAME"" + if [ BUILD_SNAPCRAFT ]; then + logInfo "Building snapcraft docker image..." + + sudo docker image build -t "$DOCKER_IMAGE" "$(realpath "$SRC_DIR")/ci/snapcraft" + + logInfo "Launching Docker contain to compile snapcraft..." + + sudo docker run --name "$DOCKER_CONTAINER_NAME" --rm \ + -v "$(realpath "$SRC_DIR"):/keepassxc" -w "/keepassxc" \ + "$DOCKER_IMAGE" snapcraft + else + mkdir -p "${OUTPUT_DIR}/bin-release" + + logInfo "Launching Docker container to compile sources..." + + docker run --name "$DOCKER_CONTAINER_NAME" --rm \ + --cap-add SYS_ADMIN --security-opt apparmor:unconfined --device /dev/fuse \ + -e "CC=${CC}" -e "CXX=${CXX}" \ + -v "$(realpath "$SRC_DIR"):/keepassxc/src:ro" \ + -v "$(realpath "$OUTPUT_DIR"):/keepassxc/out:rw" \ + "$DOCKER_IMAGE" \ + bash -c "cd /keepassxc/out/build-release && \ + cmake -DCMAKE_BUILD_TYPE=Release -DWITH_TESTS=Off $CMAKE_OPTIONS \ + -DCMAKE_INSTALL_PREFIX=\"${INSTALL_PREFIX}\" \ + -DKEEPASSXC_DIST_TYPE=AppImage /keepassxc/src && \ + make $MAKE_OPTIONS && make DESTDIR=/keepassxc/out/bin-release install/strip && \ + /keepassxc/src/AppImage-Recipe.sh "$APP_NAME" "$RELEASE_NAME"" + fi if [ 0 -ne $? ]; then exitError "Docker build failed!" diff --git a/snapcraft.yaml b/snapcraft.yaml index 61315bc7..a7d137f8 100644 --- a/snapcraft.yaml +++ b/snapcraft.yaml @@ -27,6 +27,8 @@ parts: configflags: - -DCMAKE_BUILD_TYPE=Release - -DCMAKE_INSTALL_PREFIX=/usr + - -DCMAKE_LIBRARY_PATH=/opt/keepassxc-libs/lib/x86_64-linux-gnu + - -DCMAKE_INCLUDE_PATH=/opt/keepassxc-libs/include - -DKEEPASSXC_DIST_TYPE=Snap - -DKEEPASSXC_BUILD_TYPE=Release - -DWITH_TESTS=OFF @@ -43,31 +45,26 @@ parts: - libxtst-dev - libyubikey-dev - libykpers-1-dev - - libcurl4-openssl-dev - libsodium-dev - libargon2-0-dev stage-packages: - dbus - qttranslations5-l10n # common translations - libgcrypt20-18 - install: | + - libykpers-1-1 + - libargon2-0 + - libsodium23 + - libxtst6 + - libqt5x11extras5 + - libusb-1.0-0 + override-build: | + snapcraftctl build sed -i 's|Icon=keepassxc|Icon=${SNAP}/usr/share/icons/hicolor/256x256/apps/keepassxc.png|g' $SNAPCRAFT_PART_INSTALL/usr/share/applications/org.keepassxc.KeePassXC.desktop organize: usr/share/qt5/translations/*.qm: usr/share/keepassxc/translations/ + opt/keepassxc-libs/lib/x86_64-linux-gnu/*: usr/lib/x86_64-linux-gnu/ + opt/keepassxc-libs/share/locale/*: usr/share/locale/ + stage: + - -opt after: [desktop-qt5] - - # Redefine desktop-qt5 stage packages to work with Ubuntu 17.04 - desktop-qt5: - stage-packages: - - libxkbcommon0 - - ttf-ubuntu-font-family - - dmz-cursor-theme - - light-themes - - adwaita-icon-theme - - gnome-themes-standard - - shared-mime-info - - libqt5gui5 - - libgdk-pixbuf2.0-0 - - libqt5svg5 # for loading icon themes which are svg - - locales-all - - xdg-user-dirs + From 486b99b39d21a7b2f30b8c786171ed6477b79f41 Mon Sep 17 00:00:00 2001 From: Michal Kaptur Date: Mon, 14 May 2018 21:26:26 +0200 Subject: [PATCH 036/267] Add some unit tests to Tools Clean up and test 3 methods from Tools: - humanReadableFileSize - isHex - isBase64 --- src/core/Tools.cpp | 35 ++++++++++++----------- src/core/Tools.h | 2 +- tests/CMakeLists.txt | 3 ++ tests/TestKeys.cpp | 1 - tests/TestModified.cpp | 1 - tests/TestTools.cpp | 65 ++++++++++++++++++++++++++++++++++++++++++ tests/TestTools.h | 32 +++++++++++++++++++++ 7 files changed, 120 insertions(+), 19 deletions(-) create mode 100644 tests/TestTools.cpp create mode 100644 tests/TestTools.h diff --git a/src/core/Tools.cpp b/src/core/Tools.cpp index 5f51fa47..458d4298 100644 --- a/src/core/Tools.cpp +++ b/src/core/Tools.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include @@ -56,8 +57,9 @@ namespace Tools { - QString humanReadableFileSize(qint64 bytes) + QString humanReadableFileSize(qint64 bytes, quint32 precision) { + constexpr auto kibibyte = 1024; double size = bytes; QStringList units = QStringList() << "B" @@ -67,12 +69,12 @@ namespace Tools int i = 0; int maxI = units.size() - 1; - while ((size >= 1024) && (i < maxI)) { - size /= 1024; + while ((size >= kibibyte) && (i < maxI)) { + size /= kibibyte; i++; } - return QString("%1 %2").arg(QLocale().toString(size, 'f', 2), units.at(i)); + return QString("%1 %2").arg(QLocale().toString(size, 'f', precision), units.at(i)); } bool hasChild(const QObject* parent, const QObject* child) @@ -147,8 +149,8 @@ namespace Tools bool isHex(const QByteArray& ba) { - for (char c : ba) { - if (!((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'))) { + for (const unsigned char c : ba) { + if (!std::isxdigit(c)) { return false; } } @@ -158,8 +160,8 @@ namespace Tools bool isBase64(const QByteArray& ba) { - QRegExp regexp( - "^(?:[a-z0-9+/]{4})*(?:[a-z0-9+/]{3}=|[a-z0-9+/]{2}==)?$", Qt::CaseInsensitive, QRegExp::RegExp2); + constexpr auto pattern = R"(^(?:[a-z0-9+]{4})*(?:[a-z0-9+]{3}=|[a-z0-9+]{2}==)?$)"; + QRegExp regexp(pattern, Qt::CaseInsensitive, QRegExp::RegExp2); QString base64 = QString::fromLatin1(ba.constData(), ba.size()); @@ -318,14 +320,15 @@ namespace Tools } // Set discretionary access control list - bSuccess = ERROR_SUCCESS == SetSecurityInfo(GetCurrentProcess(), // object handle - SE_KERNEL_OBJECT, // type of object - DACL_SECURITY_INFORMATION, // change only the objects DACL - nullptr, - nullptr, // do not change owner or group - pACL, // DACL specified - nullptr // do not change SACL - ); + bSuccess = ERROR_SUCCESS + == SetSecurityInfo(GetCurrentProcess(), // object handle + SE_KERNEL_OBJECT, // type of object + DACL_SECURITY_INFORMATION, // change only the objects DACL + nullptr, + nullptr, // do not change owner or group + pACL, // DACL specified + nullptr // do not change SACL + ); Cleanup: diff --git a/src/core/Tools.h b/src/core/Tools.h index b1176007..9fd49799 100644 --- a/src/core/Tools.h +++ b/src/core/Tools.h @@ -32,7 +32,7 @@ class QIODevice; namespace Tools { - QString humanReadableFileSize(qint64 bytes); + QString humanReadableFileSize(qint64 bytes, quint32 precision = 2); bool hasChild(const QObject* parent, const QObject* child); bool readFromDevice(QIODevice* device, QByteArray& data, int size = 16384); bool readAllFromDevice(QIODevice* device, QByteArray& data); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index df5c37f8..261c9627 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -190,6 +190,9 @@ add_unit_test(NAME testykchallengeresponsekey add_unit_test(NAME testdatabase SOURCES TestDatabase.cpp LIBS ${TEST_LIBRARIES}) +add_unit_test(NAME testtools SOURCES TestTools.cpp + LIBS ${TEST_LIBRARIES}) + if(WITH_GUI_TESTS) add_subdirectory(gui) endif(WITH_GUI_TESTS) diff --git a/tests/TestKeys.cpp b/tests/TestKeys.cpp index e5cc75c2..f04aabcb 100644 --- a/tests/TestKeys.cpp +++ b/tests/TestKeys.cpp @@ -24,7 +24,6 @@ #include "config-keepassx-tests.h" #include "core/Metadata.h" -#include "core/Tools.h" #include "crypto/Crypto.h" #include "crypto/CryptoHash.h" #include "crypto/kdf/AesKdf.h" diff --git a/tests/TestModified.cpp b/tests/TestModified.cpp index 0a9f0cfa..60ea68e5 100644 --- a/tests/TestModified.cpp +++ b/tests/TestModified.cpp @@ -23,7 +23,6 @@ #include "core/Database.h" #include "core/Group.h" #include "core/Metadata.h" -#include "core/Tools.h" #include "crypto/Crypto.h" QTEST_GUILESS_MAIN(TestModified) diff --git a/tests/TestTools.cpp b/tests/TestTools.cpp new file mode 100644 index 00000000..c3acd3c6 --- /dev/null +++ b/tests/TestTools.cpp @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2017 KeePassXC Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "TestTools.h" + +#include +#include + +QTEST_GUILESS_MAIN(TestTools) + +namespace +{ + QString createDecimal(QString wholes, QString fractions, QString unit) + { + return wholes + QLocale().decimalPoint() + fractions + " " + unit; + } +} + +void TestTools::testHumanReadableFileSize() +{ + constexpr auto kibibyte = 1024u; + using namespace Tools; + + QCOMPARE(createDecimal("1", "00", "B"), humanReadableFileSize(1)); + QCOMPARE(createDecimal("1", "00", "KiB"), humanReadableFileSize(kibibyte)); + QCOMPARE(createDecimal("1", "00", "MiB"), humanReadableFileSize(kibibyte * kibibyte)); + QCOMPARE(createDecimal("1", "00", "GiB"), humanReadableFileSize(kibibyte * kibibyte * kibibyte)); + + QCOMPARE(QString("100 B"), humanReadableFileSize(100, 0)); + QCOMPARE(createDecimal("1", "10", "KiB"), humanReadableFileSize(kibibyte + 100)); + QCOMPARE(createDecimal("1", "001", "KiB"), humanReadableFileSize(kibibyte + 1, 3)); + QCOMPARE(createDecimal("15", "00", "KiB"), humanReadableFileSize(kibibyte * 15)); +} + +void TestTools::testIsHex() +{ + QVERIFY(Tools::isHex("0123456789abcdefABCDEF")); + QVERIFY(not Tools::isHex(QByteArray("0xnothex"))); +} + +void TestTools::testIsBase64() +{ + QVERIFY(Tools::isBase64(QByteArray("1234"))); + QVERIFY(Tools::isBase64(QByteArray("123="))); + QVERIFY(Tools::isBase64(QByteArray("12=="))); + QVERIFY(Tools::isBase64(QByteArray("abcd9876MN=="))); + QVERIFY(Tools::isBase64(QByteArray("abcd9876DEFGhijkMNO="))); + QVERIFY(not Tools::isBase64(QByteArray("abcd123=="))); + QVERIFY(not Tools::isBase64(QByteArray("abc_"))); + QVERIFY(not Tools::isBase64(QByteArray("123"))); +} diff --git a/tests/TestTools.h b/tests/TestTools.h new file mode 100644 index 00000000..56d354ec --- /dev/null +++ b/tests/TestTools.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2017 KeePassXC Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef KEEPASSX_TESTTOOLS_H +#define KEEPASSX_TESTTOOLS_H + +#include "core/Tools.h" + +class TestTools : public QObject +{ + Q_OBJECT +private slots: + void testHumanReadableFileSize(); + void testIsHex(); + void testIsBase64(); +}; + +#endif // KEEPASSX_TESTTOOLS_H From 959acb798896dd69561b271bc281ba99aa518008 Mon Sep 17 00:00:00 2001 From: Corentin Dancette Date: Sun, 3 Jun 2018 17:08:24 +0200 Subject: [PATCH 037/267] update link in readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b09a5d20..e6866d1f 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ so please check out your distribution's package list to see if KeePassXC is avai - Browser integration with KeePassHTTP-Connector for [Mozilla Firefox](https://addons.mozilla.org/en-US/firefox/addon/keepasshttp-connector/) and [Google Chrome or Chromium](https://chrome.google.com/webstore/detail/keepasshttp-connector/dafgdjggglmmknipkhngniifhplpcldb), and -[passafari](https://github.com/mmichaa/passafari.safariextension/) in Safari. [[See note about KeePassHTTP]](#Note_about_KeePassHTTP) +[passafari](https://github.com/mmichaa/passafari.safariextension/) in Safari. [[See note about KeePassHTTP]](#note-about-keepasshttp) - Browser integration with KeePassXC-Browser using [native messaging](https://developer.chrome.com/extensions/nativeMessaging) for [Mozilla Firefox](https://addons.mozilla.org/en-US/firefox/addon/keepassxc-browser/) and [Google Chrome or Chromium](https://chrome.google.com/webstore/detail/keepassxc-browser/oboonakemofpalcgghocfoadofidjkkk) - Many bug fixes From b07d4efe5fefe0d03e409ad948eaad653d862fff Mon Sep 17 00:00:00 2001 From: Jonathan White Date: Wed, 30 May 2018 22:23:39 -0400 Subject: [PATCH 038/267] Allow multiple image selections when adding favicons --- src/gui/EditWidgetIcons.cpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/gui/EditWidgetIcons.cpp b/src/gui/EditWidgetIcons.cpp index 4292234e..73af7bf7 100644 --- a/src/gui/EditWidgetIcons.cpp +++ b/src/gui/EditWidgetIcons.cpp @@ -325,13 +325,15 @@ void EditWidgetIcons::addCustomIconFromFile() if (m_database) { QString filter = QString("%1 (%2);;%3 (*)").arg(tr("Images"), Tools::imageReaderFilter(), tr("All files")); - QString filename = QFileDialog::getOpenFileName(this, tr("Select Image"), "", filter); - if (!filename.isEmpty()) { - auto icon = QImage(filename); - if (!icon.isNull()) { - addCustomIcon(QImage(filename)); - } else { - emit messageEditEntry(tr("Can't read icon"), MessageWidget::Error); + auto filenames = QFileDialog::getOpenFileNames(this, tr("Select Image(s)"), "", filter); + for (const auto& filename : filenames) { + if (!filename.isEmpty()) { + auto icon = QImage(filename); + if (!icon.isNull()) { + addCustomIcon(QImage(filename)); + } else { + emit messageEditEntry(tr("Can't read icon"), MessageWidget::Error); + } } } } From 2e292699b75b79b0221e9cc5b4672a4263c6405f Mon Sep 17 00:00:00 2001 From: Jonathan White Date: Sun, 3 Jun 2018 12:42:33 -0400 Subject: [PATCH 039/267] Add more comprehensive messages when adding custom icons * Error messages now display for 15 seconds and are closable * Add button is always enabled --- src/gui/EditWidget.cpp | 10 ++++- src/gui/EditWidgetIcons.cpp | 75 ++++++++++++++++++++++++++----------- src/gui/EditWidgetIcons.h | 2 +- 3 files changed, 63 insertions(+), 24 deletions(-) diff --git a/src/gui/EditWidget.cpp b/src/gui/EditWidget.cpp index ce80c03b..a58cc6d8 100644 --- a/src/gui/EditWidget.cpp +++ b/src/gui/EditWidget.cpp @@ -125,8 +125,14 @@ void EditWidget::enableApplyButton(bool enabled) void EditWidget::showMessage(const QString& text, MessageWidget::MessageType type) { - m_ui->messageWidget->setCloseButtonVisible(false); - m_ui->messageWidget->showMessage(text, type, 2000); + // Show error messages for a longer time to make sure the user can read them + if (type == MessageWidget::Error) { + m_ui->messageWidget->setCloseButtonVisible(true); + m_ui->messageWidget->showMessage(text, type, 15000); + } else { + m_ui->messageWidget->setCloseButtonVisible(false); + m_ui->messageWidget->showMessage(text, type, 2000); + } } void EditWidget::hideMessage() diff --git a/src/gui/EditWidgetIcons.cpp b/src/gui/EditWidgetIcons.cpp index 73af7bf7..8ec85f92 100644 --- a/src/gui/EditWidgetIcons.cpp +++ b/src/gui/EditWidgetIcons.cpp @@ -93,6 +93,7 @@ EditWidgetIcons::EditWidgetIcons(QWidget* parent) SIGNAL(widgetUpdated())); m_ui->faviconButton->setVisible(false); + m_ui->addButton->setEnabled(true); } EditWidgetIcons::~EditWidgetIcons() @@ -269,7 +270,9 @@ void EditWidgetIcons::fetchFinished() } if (!image.isNull()) { - addCustomIcon(image); + if (!addCustomIcon(image)) { + emit messageEditEntry(tr("Custom icon already exists"), MessageWidget::Information); + } } else if (!m_urlsToTry.empty()) { m_redirects = 0; startFetchFavicon(m_urlsToTry.takeFirst()); @@ -326,36 +329,66 @@ void EditWidgetIcons::addCustomIconFromFile() QString filter = QString("%1 (%2);;%3 (*)").arg(tr("Images"), Tools::imageReaderFilter(), tr("All files")); auto filenames = QFileDialog::getOpenFileNames(this, tr("Select Image(s)"), "", filter); - for (const auto& filename : filenames) { - if (!filename.isEmpty()) { - auto icon = QImage(filename); - if (!icon.isNull()) { - addCustomIcon(QImage(filename)); - } else { - emit messageEditEntry(tr("Can't read icon"), MessageWidget::Error); + if (!filenames.empty()) { + QStringList errornames; + int numexisting = 0; + for (const auto& filename : filenames) { + if (!filename.isEmpty()) { + auto icon = QImage(filename); + if (!icon.isNull()) { + if (!addCustomIcon(QImage(filename))) { + ++numexisting; + } + } else { + errornames << filename; + } } } + + int numloaded = filenames.size() - errornames.size() - numexisting; + QString msg; + + if (numloaded > 0) { + msg = tr("Successfully loaded %1 of %2 icons").arg(numloaded).arg(filenames.size()); + } else { + msg = tr("No icons were loaded"); + } + + if (numexisting > 0) { + msg += ", " + tr("%1 icons already existed").arg(numexisting); + } + + if (!errornames.empty()) { + // Show the first 8 icons that failed to load + errornames = errornames.mid(0, 8); + emit messageEditEntry(msg + "\n" + tr("The following icons failed:") + "\n" + errornames.join("\n"), + MessageWidget::Error); + } else if (numloaded > 0) { + emit messageEditEntry(msg, MessageWidget::Positive); + } else { + emit messageEditEntry(msg, MessageWidget::Information); + } } } } -void EditWidgetIcons::addCustomIcon(const QImage& icon) +bool EditWidgetIcons::addCustomIcon(const QImage& icon) { + bool added = false; if (m_database) { - Uuid uuid = m_database->metadata()->findCustomIcon(icon); + // Don't add an icon larger than 128x128, but retain original size if smaller + auto scaledicon = icon; + if (icon.width() > 128 || icon.height() > 128) { + scaledicon = icon.scaled(128, 128); + } + + Uuid uuid = m_database->metadata()->findCustomIcon(scaledicon); if (uuid.isNull()) { uuid = Uuid::random(); - // Don't add an icon larger than 128x128, but retain original size if smaller - if (icon.width() > 128 || icon.height() > 128) { - m_database->metadata()->addCustomIcon(uuid, icon.scaled(128, 128)); - } else { - m_database->metadata()->addCustomIcon(uuid, icon); - } - + m_database->metadata()->addCustomIcon(uuid, scaledicon); m_customIconModel->setIcons(m_database->metadata()->customIconsScaledPixmaps(), m_database->metadata()->customIconsOrder()); - } else { - emit messageEditEntry(tr("Custom icon already exists"), MessageWidget::Information); + added = true; } // Select the new or existing icon @@ -365,6 +398,8 @@ void EditWidgetIcons::addCustomIcon(const QImage& icon) emit widgetUpdated(); } + + return added; } void EditWidgetIcons::removeCustomIcon() @@ -461,7 +496,6 @@ void EditWidgetIcons::updateWidgetsDefaultIcons(bool check) m_ui->defaultIconsView->setCurrentIndex(index); } m_ui->customIconsView->selectionModel()->clearSelection(); - m_ui->addButton->setEnabled(false); m_ui->deleteButton->setEnabled(false); } } @@ -476,7 +510,6 @@ void EditWidgetIcons::updateWidgetsCustomIcons(bool check) m_ui->customIconsView->setCurrentIndex(index); } m_ui->defaultIconsView->selectionModel()->clearSelection(); - m_ui->addButton->setEnabled(true); m_ui->deleteButton->setEnabled(true); } } diff --git a/src/gui/EditWidgetIcons.h b/src/gui/EditWidgetIcons.h index 94630157..e01ae4b1 100644 --- a/src/gui/EditWidgetIcons.h +++ b/src/gui/EditWidgetIcons.h @@ -88,7 +88,7 @@ private slots: void fetchReadyRead(); void fetchCanceled(); void addCustomIconFromFile(); - void addCustomIcon(const QImage& icon); + bool addCustomIcon(const QImage& icon); void removeCustomIcon(); void updateWidgetsDefaultIcons(bool checked); void updateWidgetsCustomIcons(bool checked); From 76102ee9f0fb02797c334de22870c079f1acf5a6 Mon Sep 17 00:00:00 2001 From: Jonathan White Date: Sat, 9 Jun 2018 16:56:52 -0400 Subject: [PATCH 040/267] Correct plurals and logic gate --- src/gui/EditWidgetIcons.cpp | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/gui/EditWidgetIcons.cpp b/src/gui/EditWidgetIcons.cpp index 8ec85f92..982b02d9 100644 --- a/src/gui/EditWidgetIcons.cpp +++ b/src/gui/EditWidgetIcons.cpp @@ -335,12 +335,11 @@ void EditWidgetIcons::addCustomIconFromFile() for (const auto& filename : filenames) { if (!filename.isEmpty()) { auto icon = QImage(filename); - if (!icon.isNull()) { - if (!addCustomIcon(QImage(filename))) { - ++numexisting; - } - } else { + if (icon.isNull()) { errornames << filename; + } else if (!addCustomIcon(icon)) { + // Icon already exists in database + ++numexisting; } } } @@ -349,20 +348,20 @@ void EditWidgetIcons::addCustomIconFromFile() QString msg; if (numloaded > 0) { - msg = tr("Successfully loaded %1 of %2 icons").arg(numloaded).arg(filenames.size()); + msg = tr("Successfully loaded %1 of %n icon(s)", "", filenames.size()).arg(numloaded); } else { msg = tr("No icons were loaded"); } if (numexisting > 0) { - msg += ", " + tr("%1 icons already existed").arg(numexisting); + msg += "\n" + tr("%n icon(s) already exist in the database", "", numexisting); } if (!errornames.empty()) { // Show the first 8 icons that failed to load errornames = errornames.mid(0, 8); - emit messageEditEntry(msg + "\n" + tr("The following icons failed:") + "\n" + errornames.join("\n"), - MessageWidget::Error); + emit messageEditEntry(msg + "\n" + tr("The following icon(s) failed:", "", errornames.size()) + + "\n" + errornames.join("\n"), MessageWidget::Error); } else if (numloaded > 0) { emit messageEditEntry(msg, MessageWidget::Positive); } else { From 83917299db6a2ba3c99937c6ed6ce60985618f99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adolfo=20E=2E=20Garc=C3=ADa?= Date: Sun, 10 Jun 2018 16:16:30 -0600 Subject: [PATCH 041/267] Add AppVeyor support (#1380) --- CMakeLists.txt | 2 + COPYING | 4 ++ appveyor.yml | 31 ++++++++++++ ci/appveyor/before-build.sh | 21 ++++++++ ci/appveyor/build.sh | 5 ++ ci/appveyor/install.sh | 24 +++++++++ ci/appveyor/test.sh | 6 +++ cmake/DeployQt.cmake | 88 +++++++++++++++++++++++++++++++++ src/CMakeLists.txt | 11 ++--- src/autotype/mac/CMakeLists.txt | 3 +- 10 files changed, 187 insertions(+), 8 deletions(-) create mode 100644 appveyor.yml create mode 100644 ci/appveyor/before-build.sh create mode 100644 ci/appveyor/build.sh create mode 100644 ci/appveyor/install.sh create mode 100644 ci/appveyor/test.sh create mode 100644 cmake/DeployQt.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index a4cb4d1f..dfba1678 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -339,6 +339,8 @@ if(ZLIB_VERSION_STRING VERSION_LESS "1.2.0") message(FATAL_ERROR "zlib 1.2.0 or higher is required to use the gzip format") endif() +include_directories(SYSTEM ${ARGON2_INCLUDE_DIR}) + # Optional if(WITH_XC_YUBIKEY) find_package(YubiKey REQUIRED) diff --git a/COPYING b/COPYING index 8095ef06..5108458d 100644 --- a/COPYING +++ b/COPYING @@ -235,3 +235,7 @@ License: LGPL-2.1 Files: share/macosx/dmg-background.tiff Copyright: 2008-2014, Andrey Tarantsov License: MIT + +Files: cmake/DeployQt.cmake +Copyright: 2018, Nathan Osman +License: MIT diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 00000000..bcb9b9e0 --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,31 @@ +image: + - Visual Studio 2017 + +configuration: + - Debug + +environment: + matrix: + - CC: gcc + CXX: g++ + +clone_depth: 1 + +platform: + - x64 + +matrix: + fast_finish: true + +install: + - C:\msys64\usr\bin\env MSYSTEM=MINGW64 /bin/bash -l -c "pacman --noconfirm -Syu" + - C:\msys64\usr\bin\env MSYSTEM=MINGW64 /bin/bash -l -c "/c/projects/keepassxc/ci/appveyor/install.sh" + +before_build: + - C:\msys64\usr\bin\env MSYSTEM=MINGW64 /bin/bash -l -c "/c/projects/keepassxc/ci/appveyor/before-build.sh" + +build_script: + - C:\msys64\usr\bin\env MSYSTEM=MINGW64 /bin/bash -l -c "/c/projects/keepassxc/ci/appveyor/build.sh" + +test_script: + - C:\msys64\usr\bin\env MSYSTEM=MINGW64 /bin/bash -l -c "/c/projects/keepassxc/ci/appveyor/test.sh" diff --git a/ci/appveyor/before-build.sh b/ci/appveyor/before-build.sh new file mode 100644 index 00000000..ff830598 --- /dev/null +++ b/ci/appveyor/before-build.sh @@ -0,0 +1,21 @@ +#!/usr/bin/bash + +cd /c/projects/keepassxc +mkdir build && cd build + +if [ "${configuration}" = "Debug" ]; then + cmake -G "MSYS Makefiles" \ + -DCMAKE_BUILD_TYPE=${configuration} \ + -DWITH_XC_ALL=ON \ + -DWITH_TESTS=ON \ + -DWITH_GUI_TESTS=ON \ + -DWITH_ASAN=ON \ + .. +else + cmake -G "MSYS Makefiles" \ + -DCMAKE_BUILD_TYPE=${configuration} \ + -DWITH_XC_ALL=ON \ + -DWITH_TESTS=ON \ + -DWITH_GUI_TESTS=ON \ + .. +fi diff --git a/ci/appveyor/build.sh b/ci/appveyor/build.sh new file mode 100644 index 00000000..b89ebd3a --- /dev/null +++ b/ci/appveyor/build.sh @@ -0,0 +1,5 @@ +#!/usr/bin/bash + +cd /c/projects/keepassxc/build + +make -j2 diff --git a/ci/appveyor/install.sh b/ci/appveyor/install.sh new file mode 100644 index 00000000..c5c34c32 --- /dev/null +++ b/ci/appveyor/install.sh @@ -0,0 +1,24 @@ +#!/usr/bin/bash + +# Pacman derived dependencies +pacman --needed --noconfirm -S \ + mingw-w64-$(uname -m)-cmake \ + mingw-w64-$(uname -m)-libgcrypt \ + mingw-w64-$(uname -m)-zlib \ + mingw-w64-$(uname -m)-libsodium \ + mingw-w64-$(uname -m)-argon2 \ + mingw-w64-$(uname -m)-qt5 + +# Yubikey library +curl -O -J -L https://developers.yubico.com/yubikey-personalization/Releases/ykpers-1.18.1-win64.zip +7z x ykpers-1.18.1-win64.zip -o"/mingw64/" -aoa + +# qrencode library +curl -O -J -L https://fukuchi.org/works/qrencode/qrencode-4.0.0.tar.gz +tar -xf qrencode-4.0.0.tar.gz + +cd qrencode-4.0.0 +mkdir build && cd build +cmake -G "MSYS Makefiles" -DBUILD_SHARED_LIBS=YES -DWITH_TOOLS=NO -DCMAKE_BUILD_TYPE=${configuration} .. +make -j2 +make install PREFIX="/mingw64" \ No newline at end of file diff --git a/ci/appveyor/test.sh b/ci/appveyor/test.sh new file mode 100644 index 00000000..b7a8a212 --- /dev/null +++ b/ci/appveyor/test.sh @@ -0,0 +1,6 @@ +#!/usr/bin/bash + +cd /c/projects/keepassxc/build + +make test ARGS+="-E testgui --output-on-failure --verbose" +make test ARGS+="-R testgui --output-on-failure --verbose" diff --git a/cmake/DeployQt.cmake b/cmake/DeployQt.cmake new file mode 100644 index 00000000..a9d239be --- /dev/null +++ b/cmake/DeployQt.cmake @@ -0,0 +1,88 @@ +# The MIT License (MIT) +# +# Copyright (c) 2018 Nathan Osman +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +find_package(Qt5Core REQUIRED) + +# Retrieve the absolute path to qmake and then use that path to find +# the windeployqt and macdeployqt binaries +get_target_property(_qmake_executable Qt5::qmake IMPORTED_LOCATION) +get_filename_component(_qt_bin_dir "${_qmake_executable}" DIRECTORY) + +find_program(WINDEPLOYQT_EXECUTABLE windeployqt HINTS "${_qt_bin_dir}") +if(WIN32 AND NOT WINDEPLOYQT_EXECUTABLE) + message(FATAL_ERROR "windeployqt not found") +endif() + +find_program(MACDEPLOYQT_EXECUTABLE macdeployqt HINTS "${_qt_bin_dir}") +if(APPLE AND NOT MACDEPLOYQT_EXECUTABLE) + message(FATAL_ERROR "macdeployqt not found") +endif() + +# Add commands that copy the required Qt files to the same directory as the +# target after being built as well as including them in final installation +function(windeployqt target) + + # Run windeployqt immediately after build + add_custom_command(TARGET ${target} POST_BUILD + COMMAND "${CMAKE_COMMAND}" -E + env PATH="${_qt_bin_dir}" "${WINDEPLOYQT_EXECUTABLE}" + --verbose 0 + --no-compiler-runtime + --no-angle + --no-opengl-sw + \"$\" + COMMENT "Deploying Qt..." + ) + + # windeployqt doesn't work correctly with the system runtime libraries, + # so we fall back to one of CMake's own modules for copying them over + + # Doing this with MSVC 2015 requires CMake 3.6+ + if((MSVC_VERSION VERSION_EQUAL 1900 OR MSVC_VERSION VERSION_GREATER 1900) + AND CMAKE_VERSION VERSION_LESS "3.6") + message(WARNING "Deploying with MSVC 2015+ requires CMake 3.6+") + endif() + + set(CMAKE_INSTALL_UCRT_LIBRARIES TRUE) + include(InstallRequiredSystemLibraries) + foreach(lib ${CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS}) + get_filename_component(filename "${lib}" NAME) + add_custom_command(TARGET ${target} POST_BUILD + COMMAND "${CMAKE_COMMAND}" -E + copy_if_different "${lib}" \"$\" + COMMENT "Copying ${filename}..." + ) + endforeach() +endfunction() + +# Add commands that copy the required Qt files to the application bundle +# represented by the target. +function(macdeployqt target) + add_custom_command(TARGET ${target} POST_BUILD + COMMAND "${MACDEPLOYQT_EXECUTABLE}" + \"$/../..\" + -always-overwrite + COMMENT "Deploying Qt..." + ) +endfunction() + +mark_as_advanced(WINDEPLOYQT_EXECUTABLE MACDEPLOYQT_EXECUTABLE) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 432d10ee..012fc29d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -313,11 +313,8 @@ if(APPLE AND WITH_APP_BUNDLE) set(CPACK_PACKAGE_FILE_NAME "${PROGNAME}-${KEEPASSXC_VERSION}") include(CPack) - add_custom_command(TARGET ${PROGNAME} - POST_BUILD - COMMAND ${MACDEPLOYQT_EXE} ${PROGNAME}.app - WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/src - COMMENT "Deploying app bundle") + include(DeployQt) + macdeployqt(${PROGNAME}) endif() install(TARGETS ${PROGNAME} @@ -378,8 +375,8 @@ if(MINGW) set(gp_tool \"objdump\") " COMPONENT Runtime) - include(DeployQt4) - install_qt4_executable(${PROGNAME}.exe) + include(DeployQt) + windeployqt(${PROGNAME}) # install Qt5 plugins set(PLUGINS_DIR ${Qt5_PREFIX}/share/qt5/plugins) diff --git a/src/autotype/mac/CMakeLists.txt b/src/autotype/mac/CMakeLists.txt index 08c53278..9ec8b71a 100644 --- a/src/autotype/mac/CMakeLists.txt +++ b/src/autotype/mac/CMakeLists.txt @@ -11,10 +11,11 @@ set_target_properties(keepassx-autotype-cocoa PROPERTIES LINK_FLAGS "-framework target_link_libraries(keepassx-autotype-cocoa ${PROGNAME} Qt5::Core Qt5::Widgets) if(WITH_APP_BUNDLE) + include(DeployQt) add_custom_command(TARGET keepassx-autotype-cocoa POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/libkeepassx-autotype-cocoa.so ${PLUGIN_INSTALL_DIR} - COMMAND ${MACDEPLOYQT_EXE} ${PROGNAME}.app -executable=${PLUGIN_INSTALL_DIR}/libkeepassx-autotype-cocoa.so -no-plugins + COMMAND ${MACDEPLOYQT_EXECUTABLE} ${PROGNAME}.app -executable=${PLUGIN_INSTALL_DIR}/libkeepassx-autotype-cocoa.so -no-plugins WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/src COMMENT "Deploying autotype plugin") else() From e124f17c64eb4af2d3c0bb836d75202e2703a58c Mon Sep 17 00:00:00 2001 From: seregaxvm Date: Mon, 11 Jun 2018 05:37:09 +0300 Subject: [PATCH 042/267] Add advanced password generator features (#1841) * Split between simple and advanced features * Finetune password character groups * Support for hex passwords --- src/autotype/AutoType.cpp | 7 +- src/browser/BrowserSettings.cpp | 98 ++++ src/browser/BrowserSettings.h | 16 + src/cli/Generate.cpp | 46 +- src/core/PasswordGenerator.cpp | 139 ++++- src/core/PasswordGenerator.h | 31 +- src/gui/DatabaseWidget.cpp | 1 - src/gui/EditWidgetIcons.cpp | 1 - src/gui/PasswordGeneratorWidget.cpp | 190 ++++++- src/gui/PasswordGeneratorWidget.h | 3 + src/gui/PasswordGeneratorWidget.ui | 785 ++++++++++++++++++++++------ 11 files changed, 1100 insertions(+), 217 deletions(-) diff --git a/src/autotype/AutoType.cpp b/src/autotype/AutoType.cpp index 89c24e55..aaa742a0 100644 --- a/src/autotype/AutoType.cpp +++ b/src/autotype/AutoType.cpp @@ -756,9 +756,10 @@ bool AutoType::verifyAutoTypeSyntax(const QString& sequence) } } else if (AutoType::checkHighRepetition(sequence)) { QMessageBox::StandardButton reply; - reply = - QMessageBox::question(nullptr, tr("Auto-Type"), tr("This Auto-Type command contains arguments which are " - "repeated very often. Do you really want to proceed?")); + reply = QMessageBox::question(nullptr, + tr("Auto-Type"), + tr("This Auto-Type command contains arguments which are " + "repeated very often. Do you really want to proceed?")); if (reply == QMessageBox::No) { return false; diff --git a/src/browser/BrowserSettings.cpp b/src/browser/BrowserSettings.cpp index 4a75797f..76163b9d 100644 --- a/src/browser/BrowserSettings.cpp +++ b/src/browser/BrowserSettings.cpp @@ -261,6 +261,66 @@ void BrowserSettings::setPasswordUseSpecial(bool useSpecial) config()->set("generator/SpecialChars", useSpecial); } +bool BrowserSettings::passwordUseBraces() +{ + return config()->get("generator/Braces", PasswordGenerator::DefaultBraces).toBool(); +} + +void BrowserSettings::setPasswordUseBraces(bool useBraces) +{ + config()->set("generator/Braces", useBraces); +} + +bool BrowserSettings::passwordUsePunctuation() +{ + return config()->get("generator/Punctuation", PasswordGenerator::DefaultQuotes).toBool(); +} + +void BrowserSettings::setPasswordUsePunctuation(bool usePunctuation) +{ + config()->set("generator/Punctuation", usePunctuation); +} + +bool BrowserSettings::passwordUseQuotes() +{ + return config()->get("generator/Quotes", PasswordGenerator::DefaultQuotes).toBool(); +} + +void BrowserSettings::setPasswordUseQuotes(bool useQuotes) +{ + config()->set("generator/Quotes", useQuotes); +} + +bool BrowserSettings::passwordUseDashes() +{ + return config()->get("generator/Dashes", PasswordGenerator::DefaultDashes).toBool(); +} + +void BrowserSettings::setPasswordUseDashes(bool useDashes) +{ + config()->set("generator/Dashes", useDashes); +} + +bool BrowserSettings::passwordUseMath() +{ + return config()->get("generator/Math", PasswordGenerator::DefaultMath).toBool(); +} + +void BrowserSettings::setPasswordUseMath(bool useMath) +{ + config()->set("generator/Math", useMath); +} + +bool BrowserSettings::passwordUseLogograms() +{ + return config()->get("generator/Logograms", PasswordGenerator::DefaultLogograms).toBool(); +} + +void BrowserSettings::setPasswordUseLogograms(bool useLogograms) +{ + config()->set("generator/Logograms", useLogograms); +} + bool BrowserSettings::passwordUseEASCII() { return config()->get("generator/EASCII", PasswordGenerator::DefaultEASCII).toBool(); @@ -271,6 +331,26 @@ void BrowserSettings::setPasswordUseEASCII(bool useEASCII) config()->set("generator/EASCII", useEASCII); } +bool BrowserSettings::advancedMode() +{ + return config()->get("generator/AdvancedMode", PasswordGenerator::DefaultAdvancedMode).toBool(); +} + +void BrowserSettings::setAdvancedMode(bool advancedMode) +{ + config()->set("generator/AdvancedMode", advancedMode); +} + +QString BrowserSettings::passwordExcludedChars() +{ + return config()->get("generator/ExcludedChars", PasswordGenerator::DefaultExcludedChars).toString(); +} + +void BrowserSettings::setPasswordExcludedChars(QString chars) +{ + config()->set("generator/ExcludedChars", chars); +} + int BrowserSettings::passPhraseWordCount() { return config()->get("generator/WordCount", PassphraseGenerator::DefaultWordCount).toInt(); @@ -347,6 +427,24 @@ PasswordGenerator::CharClasses BrowserSettings::passwordCharClasses() if (passwordUseSpecial()) { classes |= PasswordGenerator::SpecialCharacters; } + if (passwordUseBraces()) { + classes |= PasswordGenerator::Braces; + } + if (passwordUsePunctuation()) { + classes |= PasswordGenerator::Punctuation; + } + if (passwordUseQuotes()) { + classes |= PasswordGenerator::Quotes; + } + if (passwordUseDashes()) { + classes |= PasswordGenerator::Dashes; + } + if (passwordUseMath()) { + classes |= PasswordGenerator::Math; + } + if (passwordUseLogograms()) { + classes |= PasswordGenerator::Logograms; + } if (passwordUseEASCII()) { classes |= PasswordGenerator::EASCII; } diff --git a/src/browser/BrowserSettings.h b/src/browser/BrowserSettings.h index b02fd475..3c79dbed 100644 --- a/src/browser/BrowserSettings.h +++ b/src/browser/BrowserSettings.h @@ -76,8 +76,24 @@ public: static void setPasswordUseUppercase(bool useUppercase); static bool passwordUseSpecial(); static void setPasswordUseSpecial(bool useSpecial); + static bool passwordUseBraces(); + static void setPasswordUseBraces(bool useBraces); + static bool passwordUsePunctuation(); + static void setPasswordUsePunctuation(bool usePunctuation); + static bool passwordUseQuotes(); + static void setPasswordUseQuotes(bool useQuotes); + static bool passwordUseDashes(); + static void setPasswordUseDashes(bool useDashes); + static bool passwordUseMath(); + static void setPasswordUseMath(bool useMath); + static bool passwordUseLogograms(); + static void setPasswordUseLogograms(bool useLogograms); static bool passwordUseEASCII(); static void setPasswordUseEASCII(bool useEASCII); + static bool advancedMode(); + static void setAdvancedMode(bool advancedMode); + static QString passwordExcludedChars(); + static void setPasswordExcludedChars(QString chars); static int passPhraseWordCount(); static void setPassPhraseWordCount(int wordCount); static QString passPhraseWordSeparator(); diff --git a/src/cli/Generate.cpp b/src/cli/Generate.cpp index 45b67259..6a5be3f0 100644 --- a/src/cli/Generate.cpp +++ b/src/cli/Generate.cpp @@ -44,19 +44,41 @@ int Generate::execute(const QStringList& arguments) parser.setApplicationDescription(this->description); QCommandLineOption len(QStringList() << "L" << "length", - QObject::tr("Length of the generated password."), + QObject::tr("Length of the generated password"), QObject::tr("length")); parser.addOption(len); - QCommandLineOption lower(QStringList() << "l", QObject::tr("Use lowercase characters in the generated password.")); + QCommandLineOption lower(QStringList() << "l" + << "lower", + QObject::tr("Use lowercase characters")); parser.addOption(lower); - QCommandLineOption upper(QStringList() << "u", QObject::tr("Use uppercase characters in the generated password.")); + QCommandLineOption upper(QStringList() << "u" + << "upper", + QObject::tr("Use uppercase characters")); parser.addOption(upper); - QCommandLineOption numeric(QStringList() << "n", QObject::tr("Use numbers in the generated password.")); + QCommandLineOption numeric(QStringList() << "n" + << "numeric", + QObject::tr("Use numbers.")); parser.addOption(numeric); - QCommandLineOption special(QStringList() << "s", QObject::tr("Use special characters in the generated password.")); + QCommandLineOption special(QStringList() << "s" + << "special", + QObject::tr("Use special characters")); parser.addOption(special); - QCommandLineOption extended(QStringList() << "e", QObject::tr("Use extended ASCII in the generated password.")); + QCommandLineOption extended(QStringList() << "e" + << "extended", + QObject::tr("Use extended ASCII")); parser.addOption(extended); + QCommandLineOption exclude(QStringList() << "x" + << "exclude", + QObject::tr("Exclude character set"), + QObject::tr("chars")); + parser.addOption(exclude); + QCommandLineOption exclude_similar(QStringList() << "exclude-similar", + QObject::tr("Exclude similar looking characters")); + parser.addOption(exclude_similar); + QCommandLineOption every_group(QStringList() << "every-group", + QObject::tr("Include characters from every selected group")); + parser.addOption(every_group); + parser.process(arguments); const QStringList args = parser.positionalArguments(); @@ -92,8 +114,18 @@ int Generate::execute(const QStringList& arguments) classes |= PasswordGenerator::EASCII; } + PasswordGenerator::GeneratorFlags flags = 0x0; + + if (parser.isSet(exclude_similar)) { + flags |= PasswordGenerator::ExcludeLookAlike; + } + if (parser.isSet(every_group)) { + flags |= PasswordGenerator::CharFromEveryGroup; + } + passwordGenerator.setCharClasses(classes); - passwordGenerator.setFlags(PasswordGenerator::DefaultFlags); + passwordGenerator.setFlags(flags); + passwordGenerator.setExcludedChars(parser.value(exclude)); if (!passwordGenerator.isValid()) { outputTextStream << parser.helpText().replace("keepassxc-cli", "keepassxc-cli generate"); diff --git a/src/core/PasswordGenerator.cpp b/src/core/PasswordGenerator.cpp index 00984d31..01b71507 100644 --- a/src/core/PasswordGenerator.cpp +++ b/src/core/PasswordGenerator.cpp @@ -21,10 +21,13 @@ #include "crypto/Random.h" #include +const char* PasswordGenerator::DefaultExcludedChars = ""; + PasswordGenerator::PasswordGenerator() : m_length(0) , m_classes(0) , m_flags(0) + , m_excluded(PasswordGenerator::DefaultExcludedChars) { } @@ -56,6 +59,11 @@ void PasswordGenerator::setFlags(const GeneratorFlags& flags) m_flags = flags; } +void PasswordGenerator::setExcludedChars(const QString& chars) +{ + m_excluded = chars; +} + QString PasswordGenerator::generatePassword() const { Q_ASSERT(isValid()); @@ -130,6 +138,10 @@ bool PasswordGenerator::isValid() const return false; } + if (passwordGroups().size() == 0) { + return false; + } + return true; } @@ -140,7 +152,8 @@ QVector PasswordGenerator::passwordGroups() const if (m_classes & LowerLetters) { PasswordGroup group; - for (int i = 97; i < (97 + 26); i++) { + for (int i = 97; i <= (97 + 25); i++) { + if ((m_flags & ExcludeLookAlike) && (i == 108)) { // "l" continue; } @@ -153,7 +166,8 @@ QVector PasswordGenerator::passwordGroups() const if (m_classes & UpperLetters) { PasswordGroup group; - for (int i = 65; i < (65 + 26); i++) { + for (int i = 65; i <= (65 + 25); i++) { + if ((m_flags & ExcludeLookAlike) && (i == 73 || i == 79)) { // "I" and "O" continue; } @@ -176,28 +190,79 @@ QVector PasswordGenerator::passwordGroups() const passwordGroups.append(group); } - if (m_classes & SpecialCharacters) { + if (m_classes & Braces) { PasswordGroup group; - for (int i = 33; i <= 47; i++) { - group.append(i); + // ()[]{} + group.append(40); + group.append(41); + group.append(91); + group.append(93); + group.append(123); + group.append(125); + + passwordGroups.append(group); + } + if (m_classes & Punctuation) { + PasswordGroup group; + + // .,:; + group.append(44); + group.append(46); + group.append(58); + group.append(59); + + passwordGroups.append(group); + } + if (m_classes & Quotes) { + PasswordGroup group; + + // "' + group.append(34); + group.append(39); + + passwordGroups.append(group); + } + if (m_classes & Dashes) { + PasswordGroup group; + + // -/\_| + group.append(45); + group.append(47); + group.append(92); + group.append(95); + if (!(m_flags & ExcludeLookAlike)) { + group.append(124); // "|" } - for (int i = 58; i <= 64; i++) { - group.append(i); - } - - for (int i = 91; i <= 96; i++) { - group.append(i); - } - - for (int i = 123; i <= 126; i++) { - if ((m_flags & ExcludeLookAlike) && (i == 124)) { // "|" - continue; - } - + passwordGroups.append(group); + } + if (m_classes & Math) { + PasswordGroup group; + + // !*+-<=>? + group.append(33); + group.append(42); + group.append(43); + group.append(60); + group.append(61); + group.append(62); + group.append(63); + + passwordGroups.append(group); + } + if (m_classes & Logograms) { + PasswordGroup group; + + // #$%& + for (int i = 35; i <= 38; i++) { group.append(i); } + // @^`~ + group.append(64); + group.append(94); + group.append(96); + group.append(126); passwordGroups.append(group); } @@ -220,6 +285,27 @@ QVector PasswordGenerator::passwordGroups() const passwordGroups.append(group); } + // Loop over character groups and remove excluded characters from them; + // remove empty groups + int i = 0; + while (i != passwordGroups.size()) { + PasswordGroup group = passwordGroups[i]; + + for (QChar ch : m_excluded) { + int j = group.indexOf(ch); + while (j != -1) { + group.remove(j); + j = group.indexOf(ch); + } + } + if (group.size() > 0) { + passwordGroups.replace(i, group); + i++; + } else { + passwordGroups.remove(i); + } + } + return passwordGroups; } @@ -236,7 +322,22 @@ int PasswordGenerator::numCharClasses() const if (m_classes & Numbers) { numClasses++; } - if (m_classes & SpecialCharacters) { + if (m_classes & Braces) { + numClasses++; + } + if (m_classes & Punctuation) { + numClasses++; + } + if (m_classes & Quotes) { + numClasses++; + } + if (m_classes & Dashes) { + numClasses++; + } + if (m_classes & Math) { + numClasses++; + } + if (m_classes & Logograms) { numClasses++; } if (m_classes & EASCII) { diff --git a/src/core/PasswordGenerator.h b/src/core/PasswordGenerator.h index d6866b5e..1d6ac73f 100644 --- a/src/core/PasswordGenerator.h +++ b/src/core/PasswordGenerator.h @@ -30,19 +30,26 @@ class PasswordGenerator public: enum CharClass { - LowerLetters = 0x1, - UpperLetters = 0x2, - Numbers = 0x4, - SpecialCharacters = 0x8, - EASCII = 0x10, + LowerLetters = (1 << 0), + UpperLetters = (1 << 1), + Numbers = (1 << 2), + Braces = (1 << 3), + Punctuation = (1 << 4), + Quotes = (1 << 5), + Dashes = (1 << 6), + Math = (1 << 7), + Logograms = (1 << 8), + SpecialCharacters = Braces | Punctuation | Quotes | Dashes | Math | Logograms, + EASCII = (1 << 9), DefaultCharset = LowerLetters | UpperLetters | Numbers }; Q_DECLARE_FLAGS(CharClasses, CharClass) enum GeneratorFlag { - ExcludeLookAlike = 0x1, - CharFromEveryGroup = 0x2, + ExcludeLookAlike = (1 << 0), + CharFromEveryGroup = (1 << 1), + AdvancedMode = (1 << 2), DefaultFlags = ExcludeLookAlike | CharFromEveryGroup }; Q_DECLARE_FLAGS(GeneratorFlags, GeneratorFlag) @@ -54,6 +61,7 @@ public: void setLength(int length); void setCharClasses(const CharClasses& classes); void setFlags(const GeneratorFlags& flags); + void setExcludedChars(const QString& chars); bool isValid() const; @@ -61,10 +69,18 @@ public: int getbits() const; static const int DefaultLength = 16; + static const char* DefaultExcludedChars; static constexpr bool DefaultLower = (DefaultCharset & LowerLetters) != 0; static constexpr bool DefaultUpper = (DefaultCharset & UpperLetters) != 0; static constexpr bool DefaultNumbers = (DefaultCharset & Numbers) != 0; static constexpr bool DefaultSpecial = (DefaultCharset & SpecialCharacters) != 0; + static constexpr bool DefaultAdvancedMode = (DefaultFlags & AdvancedMode) != 0; + static constexpr bool DefaultBraces = (DefaultCharset & Braces) != 0; + static constexpr bool DefaultPunctuation = (DefaultCharset & Punctuation) != 0; + static constexpr bool DefaultQuotes = (DefaultCharset & Quotes) != 0; + static constexpr bool DefaultDashes = (DefaultCharset & Dashes) != 0; + static constexpr bool DefaultMath = (DefaultCharset & Math) != 0; + static constexpr bool DefaultLogograms = (DefaultCharset & Logograms) != 0; static constexpr bool DefaultEASCII = (DefaultCharset & EASCII) != 0; static constexpr bool DefaultLookAlike = (DefaultFlags & ExcludeLookAlike) != 0; static constexpr bool DefaultFromEveryGroup = (DefaultFlags & CharFromEveryGroup) != 0; @@ -76,6 +92,7 @@ private: int m_length; CharClasses m_classes; GeneratorFlags m_flags; + QString m_excluded; Q_DISABLE_COPY(PasswordGenerator) }; diff --git a/src/gui/DatabaseWidget.cpp b/src/gui/DatabaseWidget.cpp index 7ee317ad..f1eb1793 100644 --- a/src/gui/DatabaseWidget.cpp +++ b/src/gui/DatabaseWidget.cpp @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include diff --git a/src/gui/EditWidgetIcons.cpp b/src/gui/EditWidgetIcons.cpp index 4292234e..2228501b 100644 --- a/src/gui/EditWidgetIcons.cpp +++ b/src/gui/EditWidgetIcons.cpp @@ -19,7 +19,6 @@ #include "EditWidgetIcons.h" #include "ui_EditWidgetIcons.h" -#include #include #include diff --git a/src/gui/PasswordGeneratorWidget.cpp b/src/gui/PasswordGeneratorWidget.cpp index 3d8ebf7b..fed34754 100644 --- a/src/gui/PasswordGeneratorWidget.cpp +++ b/src/gui/PasswordGeneratorWidget.cpp @@ -42,6 +42,10 @@ PasswordGeneratorWidget::PasswordGeneratorWidget(QWidget* parent) connect(m_ui->editNewPassword, SIGNAL(textChanged(QString)), SLOT(updateButtonsEnabled(QString))); connect(m_ui->editNewPassword, SIGNAL(textChanged(QString)), SLOT(updatePasswordStrength(QString))); connect(m_ui->togglePasswordButton, SIGNAL(toggled(bool)), SLOT(togglePasswordShown(bool))); + connect(m_ui->buttonSimpleMode, SIGNAL(clicked()), SLOT(selectSimpleMode())); + connect(m_ui->buttonAdvancedMode, SIGNAL(clicked()), SLOT(selectAdvancedMode())); + connect(m_ui->buttonAddHex, SIGNAL(clicked()), SLOT(excludeHexChars())); + connect(m_ui->editExcludedChars, SIGNAL(textChanged(QString)), SLOT(updateGenerator())); connect(m_ui->buttonApply, SIGNAL(clicked()), SLOT(applyPassword())); connect(m_ui->buttonCopy, SIGNAL(clicked()), SLOT(copyPassword())); connect(m_ui->buttonGenerate, SIGNAL(clicked()), SLOT(regeneratePassword())); @@ -94,11 +98,34 @@ void PasswordGeneratorWidget::loadSettings() { // Password config m_ui->checkBoxLower->setChecked(config()->get("generator/LowerCase", PasswordGenerator::DefaultLower).toBool()); + m_ui->checkBoxLowerAdv->setChecked(config()->get("generator/LowerCase", PasswordGenerator::DefaultLower).toBool()); m_ui->checkBoxUpper->setChecked(config()->get("generator/UpperCase", PasswordGenerator::DefaultUpper).toBool()); + m_ui->checkBoxUpperAdv->setChecked(config()->get("generator/UpperCase", PasswordGenerator::DefaultUpper).toBool()); m_ui->checkBoxNumbers->setChecked(config()->get("generator/Numbers", PasswordGenerator::DefaultNumbers).toBool()); - m_ui->checkBoxSpecialChars->setChecked( - config()->get("generator/SpecialChars", PasswordGenerator::DefaultSpecial).toBool()); + m_ui->checkBoxNumbersAdv->setChecked( + config()->get("generator/Numbers", PasswordGenerator::DefaultNumbers).toBool()); + m_ui->advancedBar->setVisible( + config()->get("generator/AdvancedMode", PasswordGenerator::DefaultAdvancedMode).toBool()); + m_ui->excludedChars->setVisible( + config()->get("generator/AdvancedMode", PasswordGenerator::DefaultAdvancedMode).toBool()); + m_ui->checkBoxExcludeAlike->setVisible( + config()->get("generator/AdvancedMode", PasswordGenerator::DefaultAdvancedMode).toBool()); + m_ui->checkBoxEnsureEvery->setVisible( + config()->get("generator/AdvancedMode", PasswordGenerator::DefaultAdvancedMode).toBool()); + m_ui->editExcludedChars->setText( + config()->get("generator/ExcludedChars", PasswordGenerator::DefaultExcludedChars).toString()); + m_ui->simpleBar->setVisible( + !(config()->get("generator/AdvancedMode", PasswordGenerator::DefaultAdvancedMode).toBool())); + m_ui->checkBoxBraces->setChecked(config()->get("generator/Braces", PasswordGenerator::DefaultBraces).toBool()); + m_ui->checkBoxQuotes->setChecked(config()->get("generator/Quotes", PasswordGenerator::DefaultQuotes).toBool()); + m_ui->checkBoxPunctuation->setChecked( + config()->get("generator/Punctuation", PasswordGenerator::DefaultPunctuation).toBool()); + m_ui->checkBoxDashes->setChecked(config()->get("generator/Dashes", PasswordGenerator::DefaultDashes).toBool()); + m_ui->checkBoxMath->setChecked(config()->get("generator/Math", PasswordGenerator::DefaultMath).toBool()); + m_ui->checkBoxLogograms->setChecked( + config()->get("generator/Logograms", PasswordGenerator::DefaultLogograms).toBool()); m_ui->checkBoxExtASCII->setChecked(config()->get("generator/EASCII", PasswordGenerator::DefaultEASCII).toBool()); + m_ui->checkBoxExtASCIIAdv->setChecked(config()->get("generator/EASCII", PasswordGenerator::DefaultEASCII).toBool()); m_ui->checkBoxExcludeAlike->setChecked( config()->get("generator/ExcludeAlike", PasswordGenerator::DefaultLookAlike).toBool()); m_ui->checkBoxEnsureEvery->setChecked( @@ -120,11 +147,25 @@ void PasswordGeneratorWidget::loadSettings() void PasswordGeneratorWidget::saveSettings() { // Password config - config()->set("generator/LowerCase", m_ui->checkBoxLower->isChecked()); - config()->set("generator/UpperCase", m_ui->checkBoxUpper->isChecked()); - config()->set("generator/Numbers", m_ui->checkBoxNumbers->isChecked()); + if (m_ui->simpleBar->isVisible()) { + config()->set("generator/LowerCase", m_ui->checkBoxLower->isChecked()); + config()->set("generator/UpperCase", m_ui->checkBoxUpper->isChecked()); + config()->set("generator/Numbers", m_ui->checkBoxNumbers->isChecked()); + config()->set("generator/EASCII", m_ui->checkBoxExtASCII->isChecked()); + } else { + config()->set("generator/LowerCase", m_ui->checkBoxLowerAdv->isChecked()); + config()->set("generator/UpperCase", m_ui->checkBoxUpperAdv->isChecked()); + config()->set("generator/Numbers", m_ui->checkBoxNumbersAdv->isChecked()); + config()->set("generator/EASCII", m_ui->checkBoxExtASCIIAdv->isChecked()); + } config()->set("generator/SpecialChars", m_ui->checkBoxSpecialChars->isChecked()); - config()->set("generator/EASCII", m_ui->checkBoxExtASCII->isChecked()); + config()->set("generator/Braces", m_ui->checkBoxBraces->isChecked()); + config()->set("generator/Punctuation", m_ui->checkBoxPunctuation->isChecked()); + config()->set("generator/Quotes", m_ui->checkBoxQuotes->isChecked()); + config()->set("generator/Dashes", m_ui->checkBoxDashes->isChecked()); + config()->set("generator/Math", m_ui->checkBoxMath->isChecked()); + config()->set("generator/Logograms", m_ui->checkBoxLogograms->isChecked()); + config()->set("generator/ExcludedChars", m_ui->editExcludedChars->text()); config()->set("generator/ExcludeAlike", m_ui->checkBoxExcludeAlike->isChecked()); config()->set("generator/EnsureEvery", m_ui->checkBoxEnsureEvery->isChecked()); config()->set("generator/Length", m_ui->spinBoxLength->value()); @@ -276,6 +317,48 @@ void PasswordGeneratorWidget::togglePasswordShown(bool showing) m_ui->togglePasswordButton->blockSignals(blockSignals); } +void PasswordGeneratorWidget::selectSimpleMode() +{ + m_ui->advancedBar->hide(); + m_ui->excludedChars->hide(); + m_ui->checkBoxExcludeAlike->hide(); + m_ui->checkBoxEnsureEvery->hide(); + m_ui->checkBoxUpper->setChecked(m_ui->checkBoxUpperAdv->isChecked()); + m_ui->checkBoxLower->setChecked(m_ui->checkBoxLowerAdv->isChecked()); + m_ui->checkBoxNumbers->setChecked(m_ui->checkBoxNumbersAdv->isChecked()); + m_ui->checkBoxSpecialChars->setChecked(m_ui->checkBoxBraces->isChecked() | m_ui->checkBoxPunctuation->isChecked() + | m_ui->checkBoxQuotes->isChecked() + | m_ui->checkBoxMath->isChecked() + | m_ui->checkBoxDashes->isChecked() + | m_ui->checkBoxLogograms->isChecked()); + m_ui->checkBoxExtASCII->setChecked(m_ui->checkBoxExtASCIIAdv->isChecked()); + m_ui->simpleBar->show(); +} + +void PasswordGeneratorWidget::selectAdvancedMode() +{ + m_ui->simpleBar->hide(); + m_ui->checkBoxUpperAdv->setChecked(m_ui->checkBoxUpper->isChecked()); + m_ui->checkBoxLowerAdv->setChecked(m_ui->checkBoxLower->isChecked()); + m_ui->checkBoxNumbersAdv->setChecked(m_ui->checkBoxNumbers->isChecked()); + m_ui->checkBoxBraces->setChecked(m_ui->checkBoxSpecialChars->isChecked()); + m_ui->checkBoxPunctuation->setChecked(m_ui->checkBoxSpecialChars->isChecked()); + m_ui->checkBoxQuotes->setChecked(m_ui->checkBoxSpecialChars->isChecked()); + m_ui->checkBoxMath->setChecked(m_ui->checkBoxSpecialChars->isChecked()); + m_ui->checkBoxDashes->setChecked(m_ui->checkBoxSpecialChars->isChecked()); + m_ui->checkBoxLogograms->setChecked(m_ui->checkBoxSpecialChars->isChecked()); + m_ui->checkBoxExtASCIIAdv->setChecked(m_ui->checkBoxExtASCII->isChecked()); + m_ui->advancedBar->show(); + m_ui->excludedChars->show(); + m_ui->checkBoxExcludeAlike->show(); + m_ui->checkBoxEnsureEvery->show(); +} + +void PasswordGeneratorWidget::excludeHexChars() +{ + m_ui->editExcludedChars->setText("GHIJKLMNOPQRSTUVWXYZghijklmnopqrstuvwxyz"); +} + void PasswordGeneratorWidget::colorStrengthIndicator(double entropy) { // Take the existing stylesheet and convert the text and background color to arguments @@ -306,24 +389,69 @@ PasswordGenerator::CharClasses PasswordGeneratorWidget::charClasses() { PasswordGenerator::CharClasses classes; - if (m_ui->checkBoxLower->isChecked()) { - classes |= PasswordGenerator::LowerLetters; - } + if (m_ui->simpleBar->isVisible()) { - if (m_ui->checkBoxUpper->isChecked()) { - classes |= PasswordGenerator::UpperLetters; - } + if (m_ui->checkBoxLower->isChecked()) { + classes |= PasswordGenerator::LowerLetters; + } - if (m_ui->checkBoxNumbers->isChecked()) { - classes |= PasswordGenerator::Numbers; - } + if (m_ui->checkBoxUpper->isChecked()) { + classes |= PasswordGenerator::UpperLetters; + } - if (m_ui->checkBoxSpecialChars->isChecked()) { - classes |= PasswordGenerator::SpecialCharacters; - } + if (m_ui->checkBoxNumbers->isChecked()) { + classes |= PasswordGenerator::Numbers; + } - if (m_ui->checkBoxExtASCII->isChecked()) { - classes |= PasswordGenerator::EASCII; + if (m_ui->checkBoxSpecialChars->isChecked()) { + classes |= PasswordGenerator::SpecialCharacters; + } + + if (m_ui->checkBoxExtASCII->isChecked()) { + classes |= PasswordGenerator::EASCII; + } + + } else { + + if (m_ui->checkBoxLowerAdv->isChecked()) { + classes |= PasswordGenerator::LowerLetters; + } + + if (m_ui->checkBoxUpperAdv->isChecked()) { + classes |= PasswordGenerator::UpperLetters; + } + + if (m_ui->checkBoxNumbersAdv->isChecked()) { + classes |= PasswordGenerator::Numbers; + } + + if (m_ui->checkBoxBraces->isChecked()) { + classes |= PasswordGenerator::Braces; + } + + if (m_ui->checkBoxPunctuation->isChecked()) { + classes |= PasswordGenerator::Punctuation; + } + + if (m_ui->checkBoxQuotes->isChecked()) { + classes |= PasswordGenerator::Quotes; + } + + if (m_ui->checkBoxDashes->isChecked()) { + classes |= PasswordGenerator::Dashes; + } + + if (m_ui->checkBoxMath->isChecked()) { + classes |= PasswordGenerator::Math; + } + + if (m_ui->checkBoxLogograms->isChecked()) { + classes |= PasswordGenerator::Logograms; + } + + if (m_ui->checkBoxExtASCIIAdv->isChecked()) { + classes |= PasswordGenerator::EASCII; + } } return classes; @@ -361,7 +489,22 @@ void PasswordGeneratorWidget::updateGenerator() if (classes.testFlag(PasswordGenerator::Numbers)) { minLength++; } - if (classes.testFlag(PasswordGenerator::SpecialCharacters)) { + if (classes.testFlag(PasswordGenerator::Braces)) { + minLength++; + } + if (classes.testFlag(PasswordGenerator::Punctuation)) { + minLength++; + } + if (classes.testFlag(PasswordGenerator::Quotes)) { + minLength++; + } + if (classes.testFlag(PasswordGenerator::Dashes)) { + minLength++; + } + if (classes.testFlag(PasswordGenerator::Math)) { + minLength++; + } + if (classes.testFlag(PasswordGenerator::Logograms)) { minLength++; } if (classes.testFlag(PasswordGenerator::EASCII)) { @@ -382,6 +525,11 @@ void PasswordGeneratorWidget::updateGenerator() m_passwordGenerator->setLength(m_ui->spinBoxLength->value()); m_passwordGenerator->setCharClasses(classes); + if (m_ui->simpleBar->isVisible()) { + m_passwordGenerator->setExcludedChars(""); + } else { + m_passwordGenerator->setExcludedChars(m_ui->editExcludedChars->text()); + } m_passwordGenerator->setFlags(flags); if (m_passwordGenerator->isValid()) { diff --git a/src/gui/PasswordGeneratorWidget.h b/src/gui/PasswordGeneratorWidget.h index 84d5484b..5b65d7d2 100644 --- a/src/gui/PasswordGeneratorWidget.h +++ b/src/gui/PasswordGeneratorWidget.h @@ -65,6 +65,9 @@ private slots: void updateButtonsEnabled(const QString& password); void updatePasswordStrength(const QString& password); void togglePasswordShown(bool hidden); + void selectSimpleMode(); + void selectAdvancedMode(); + void excludeHexChars(); void passwordSliderMoved(); void passwordSpinBoxChanged(); diff --git a/src/gui/PasswordGeneratorWidget.ui b/src/gui/PasswordGeneratorWidget.ui index 03f70806..e196ff89 100644 --- a/src/gui/PasswordGeneratorWidget.ui +++ b/src/gui/PasswordGeneratorWidget.ui @@ -6,8 +6,8 @@ 0 0 - 547 - 352 + 571 + 394 @@ -19,7 +19,7 @@ - + QLayout::SetMinimumSize @@ -175,12 +175,6 @@ QProgressBar::chunk { - - - 0 - 0 - - QTabWidget::North @@ -204,155 +198,598 @@ QProgressBar::chunk { - - - - - - 0 - 25 - - - - Qt::StrongFocus - - - Upper Case Letters - - - A-Z - - - true - - - optionButtons - - - - - - - - 0 - 25 - - - - Qt::StrongFocus - - - Lower Case Letters - - - a-z - - - true - - - optionButtons - - - - - - - - 0 - 25 - - - - Qt::StrongFocus - - - Numbers - - - 0-9 - - - true - - - optionButtons - - - - - - - - 0 - 25 - - - - Qt::StrongFocus - - - Special Characters - - - /*_& ... - - - true - - - optionButtons - - - - - - - - 0 - 25 - - - - - 16777215 - 16777215 - - - - Qt::StrongFocus - - - Extended ASCII - - - Extended ASCII - - - true - - - optionButtons - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + 0 + 25 + + + + Qt::StrongFocus + + + Upper Case Letters + + + A-Z + + + true + + + optionButtons + + + + + + + + 0 + 25 + + + + Qt::StrongFocus + + + Lower Case Letters + + + a-z + + + true + + + optionButtons + + + + + + + + 0 + 25 + + + + Qt::StrongFocus + + + Numbers + + + 0-9 + + + true + + + optionButtons + + + + + + + true + + + + 0 + 25 + + + + Qt::StrongFocus + + + Special Characters + + + /*_& ... + + + true + + + optionButtons + + + + + + + + 0 + 25 + + + + + 16777215 + 16777215 + + + + Qt::StrongFocus + + + Extended ASCII + + + ExtendedASCII + + + true + + + optionButtons + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 25 + + + + Switch to advanced mode + + + Advanced + + + optionButtons + + + + + + + + + + + + true + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + 40 + 25 + + + + Qt::StrongFocus + + + Upper Case Letters A to F + + + A-Z + + + true + + + optionButtons + + + + + + + + 40 + 25 + + + + Qt::StrongFocus + + + Lower Case Letters A to F + + + a-z + + + true + + + optionButtons + + + + + + + + + + + + 40 + 25 + + + + Qt::StrongFocus + + + Numbers + + + 0-9 + + + true + + + optionButtons + + + + + + + + 40 + 25 + + + + Qt::StrongFocus + + + Braces + + + {[( + + + true + + + optionButtons + + + + + + + + + + + + 35 + 25 + + + + Qt::StrongFocus + + + Punctuation + + + .,:; + + + true + + + optionButtons + + + + + + + + 35 + 25 + + + + Qt::StrongFocus + + + Quotes + + + " ' + + + true + + + optionButtons + + + + + + + + + + + + 60 + 25 + + + + Qt::StrongFocus + + + Math + + + <*+!?= + + + true + + + optionButtons + + + + + + + + 60 + 25 + + + + Qt::StrongFocus + + + Dashes + + + \_|-/ + + + true + + + optionButtons + + + + + + + + + + + + 105 + 25 + + + + Qt::StrongFocus + + + Logograms + + + #$%&&@^`~ + + + true + + + optionButtons + + + + + + + + 105 + 25 + + + + Qt::StrongFocus + + + Extended ASCII + + + ExtendedASCII + + + true + + + optionButtons + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + 0 + 25 + + + + Switch to simple mode + + + Simple + + + optionButtons + + + + + + + + + + + + true + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 25 + + + + Character set to exclude from generated password + + + true + + + + + + + Do not include: + + + + + + + + 0 + 25 + + + + Add non-hex letters to "do not include" list + + + Hex + + + + + + + + + + Qt::Vertical + + + + 20 + 0 + + + + + Excluded characters: "0", "1", "l", "I", "O", "|", "﹒" + Exclude look-alike characters @@ -534,6 +971,19 @@ QProgressBar::chunk { + + + + Qt::Vertical + + + + 20 + 40 + + + + @@ -585,9 +1035,6 @@ QProgressBar::chunk { - - - @@ -607,7 +1054,29 @@ QProgressBar::chunk { checkBoxLower checkBoxNumbers checkBoxSpecialChars + checkBoxExtASCII + buttonAdvancedMode + checkBoxUpperAdv + checkBoxNumbersAdv + checkBoxPunctuation + checkBoxMath + checkBoxLogograms + checkBoxBraces + checkBoxQuotes + checkBoxDashes + checkBoxExtASCIIAdv + editExcludedChars + buttonSimpleMode checkBoxExcludeAlike + checkBoxEnsureEvery + tabWidget + comboBoxWordList + sliderWordCount + spinBoxWordCount + editWordSeparator + buttonGenerate + buttonCopy + buttonApply From f4f8be56ce41ffa92b9107c3f60bce9a0dd3bfdb Mon Sep 17 00:00:00 2001 From: Jonathan White Date: Sun, 10 Jun 2018 23:24:02 -0400 Subject: [PATCH 043/267] Added AppVeyor and CodeCov badges --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index e6866d1f..fc63beda 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,6 @@ # KeePassXC -[![TeamCity Build Status](https://ci.keepassxc.org/app/rest/builds/buildType:\(id:KeepassXC_TeamCityCi\)/statusIcon?guest=1)](https://ci.keepassxc.org/viewType.html?buildTypeId=KeepassXC_TeamCityCi&guest=1) [![Coverage Status](https://coveralls.io/repos/github/keepassxreboot/keepassxc/badge.svg)](https://coveralls.io/github/keepassxreboot/keepassxc) +[![TeamCity Build Status](https://ci.keepassxc.org/app/rest/builds/buildType:\(id:KeepassXC_TeamCityCi\)/statusIcon?guest=1)](https://ci.keepassxc.org/viewType.html?buildTypeId=KeepassXC_TeamCityCi&guest=1) [![Build status](https://ci.appveyor.com/api/projects/status/qmcar8rnqjh4oxof?svg=true)](https://ci.appveyor.com/project/droidmonkey/keepassxc) [![codecov](https://codecov.io/gh/keepassxreboot/keepassxc/branch/develop/graph/badge.svg)](https://codecov.io/gh/keepassxreboot/keepassxc) + ## About KeePassXC [KeePassXC](https://keepassxc.org) is a cross-platform community fork of From 4e7aeca3b7ab4e943f22b6bab5d720ea0471290f Mon Sep 17 00:00:00 2001 From: Jonathan White Date: Mon, 18 Jun 2018 23:34:30 -0400 Subject: [PATCH 044/267] Add support for SonarCloud analysis --- .gitignore | 3 ++- cmake/CodeCoverage.cmake | 4 ++++ sonar-project.properties | 18 ++++++++++++++++++ 3 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 sonar-project.properties diff --git a/.gitignore b/.gitignore index c96688e9..903910a3 100644 --- a/.gitignore +++ b/.gitignore @@ -10,4 +10,5 @@ release*/ *.swp .DS_Store -.version \ No newline at end of file +.version +\.scannerwork/ diff --git a/cmake/CodeCoverage.cmake b/cmake/CodeCoverage.cmake index a0b0ef52..d10f7972 100644 --- a/cmake/CodeCoverage.cmake +++ b/cmake/CodeCoverage.cmake @@ -131,6 +131,10 @@ FUNCTION(SETUP_TARGET_FOR_COVERAGE _targetname _testrunner _outputname) ENDIF() # NOT GENHTML_PATH SET(coverage_info "${CMAKE_BINARY_DIR}/${_outputname}.info") + IF(MINGW) + # Replace C:/ with /C for MINGW + STRING(REGEX REPLACE "^([a-zA-Z]):" "/\\1" coverage_info ${coverage_info}) + ENDIF() SET(coverage_cleaned "${coverage_info}.cleaned") SEPARATE_ARGUMENTS(test_command UNIX_COMMAND "${_testrunner}") diff --git a/sonar-project.properties b/sonar-project.properties new file mode 100644 index 00000000..0ba2bee8 --- /dev/null +++ b/sonar-project.properties @@ -0,0 +1,18 @@ +# https://about.sonarcloud.io/get-started/ +# Run the SonarCloud tools with the follow parameters: +# Run in the cmake build directory after cmake: build-wrapper-[platform]-x86-64 --out-dir bw-output make clean all +# Run in the project root directory: sonar-scanner.bat -Dsonar.cfamily.build-wrapper-output=build/bw-output -Dsonar.cfamily.gcov.reportsPath=build -Dsonar.login=[AUTH_TOKEN] + +# required metadata +sonar.projectKey=keepassxc +sonar.organization=droidmonkey-github +sonar.projectName=keepassxc +sonar.host.url=https://sonarcloud.io + +# path to source directories (required) +sonar.sources=src +sonar.tests=tests + +sonar.cfamily.threads=2 + +sonar.exclusions=**/zxcvbn/* From ad4423d226da6105e0732a15918c6429e2ca8ed4 Mon Sep 17 00:00:00 2001 From: pasdam <> Date: Thu, 22 Mar 2018 22:56:05 +0100 Subject: [PATCH 045/267] Replaced Uuid with QUuid --- src/CMakeLists.txt | 1 - src/core/Database.cpp | 33 +++---- src/core/Database.h | 27 +++--- src/core/Entry.cpp | 35 ++++---- src/core/Entry.h | 16 ++-- src/core/Group.cpp | 29 +++--- src/core/Group.h | 19 ++-- src/core/Metadata.cpp | 32 +++---- src/core/Metadata.h | 36 ++++---- src/core/Uuid.cpp | 124 -------------------------- src/core/Uuid.h | 56 ------------ src/crypto/SymmetricCipher.cpp | 10 ++- src/crypto/SymmetricCipher.h | 6 +- src/crypto/kdf/AesKdf.cpp | 2 +- src/crypto/kdf/Argon2Kdf.cpp | 2 +- src/crypto/kdf/Kdf.cpp | 4 +- src/crypto/kdf/Kdf.h | 10 +-- src/format/Kdbx3Writer.cpp | 10 +-- src/format/Kdbx4Writer.cpp | 10 +-- src/format/KdbxReader.cpp | 12 ++- src/format/KdbxXmlReader.cpp | 41 +++++---- src/format/KdbxXmlReader.h | 12 +-- src/format/KdbxXmlWriter.cpp | 14 +-- src/format/KdbxXmlWriter.h | 5 +- src/format/KeePass1Reader.cpp | 8 +- src/format/KeePass2.cpp | 38 ++++---- src/format/KeePass2.h | 29 +++--- src/gui/DatabaseSettingsWidget.cpp | 17 ++-- src/gui/DatabaseWidget.cpp | 14 +-- src/gui/DatabaseWidget.h | 9 +- src/gui/EditWidgetIcons.cpp | 17 ++-- src/gui/EditWidgetIcons.h | 8 +- src/gui/EditWidgetProperties.cpp | 7 +- src/gui/EditWidgetProperties.h | 3 +- src/gui/IconModels.cpp | 10 ++- src/gui/IconModels.h | 12 ++- src/gui/csvImport/CsvImportWidget.cpp | 8 +- src/gui/group/GroupModel.cpp | 12 +-- src/sshagent/SSHAgent.h | 4 +- tests/TestDeletedObjects.cpp | 16 ++-- tests/TestEntry.cpp | 110 ++++++++++------------- tests/TestEntryModel.cpp | 9 +- tests/TestGlobal.h | 10 +-- tests/TestGroup.cpp | 26 +++--- tests/TestKdbx2.cpp | 4 +- tests/TestKdbx4.cpp | 22 ++--- tests/TestKeePass2Format.cpp | 44 ++++----- tests/TestMerge.cpp | 27 +++--- tests/TestModified.cpp | 15 ++-- 49 files changed, 413 insertions(+), 612 deletions(-) delete mode 100644 src/core/Uuid.cpp delete mode 100644 src/core/Uuid.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 012fc29d..33d3f60b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -66,7 +66,6 @@ set(keepassx_SOURCES core/TimeInfo.cpp core/Tools.cpp core/Translator.cpp - core/Uuid.cpp core/Base32.h core/Base32.cpp cli/Utils.cpp diff --git a/src/core/Database.cpp b/src/core/Database.cpp index 219a97f3..21108f41 100644 --- a/src/core/Database.cpp +++ b/src/core/Database.cpp @@ -18,6 +18,7 @@ #include "Database.h" +#include #include #include #include @@ -35,13 +36,13 @@ #include "keys/FileKey.h" #include "keys/PasswordKey.h" -QHash Database::m_uuidMap; +QHash Database::m_uuidMap; Database::Database() : m_metadata(new Metadata(this)) , m_timer(new QTimer(this)) , m_emitModified(false) - , m_uuid(Uuid::random()) + , m_uuid(QUuid::createUuid()) { m_data.cipher = KeePass2::CIPHER_AES; m_data.compressionAlgo = CompressionGZip; @@ -53,7 +54,7 @@ Database::Database() m_data.hasKey = false; setRootGroup(new Group()); - rootGroup()->setUuid(Uuid::random()); + rootGroup()->setUuid(QUuid::createUuid()); m_timer->setSingleShot(true); m_uuidMap.insert(m_uuid, this); @@ -97,7 +98,7 @@ const Metadata* Database::metadata() const return m_metadata; } -Entry* Database::resolveEntry(const Uuid& uuid) +Entry* Database::resolveEntry(const QUuid& uuid) { return findEntryRecursive(uuid, m_rootGroup); } @@ -107,7 +108,7 @@ Entry* Database::resolveEntry(const QString& text, EntryReferenceType referenceT return findEntryRecursive(text, referenceType, m_rootGroup); } -Entry* Database::findEntryRecursive(const Uuid& uuid, Group* group) +Entry* Database::findEntryRecursive(const QUuid& uuid, Group* group) { const QList entryList = group->entries(); for (Entry* entry : entryList) { @@ -154,8 +155,8 @@ Entry* Database::findEntryRecursive(const QString& text, EntryReferenceType refe case EntryReferenceType::Notes: found = entry->notes() == text; break; - case EntryReferenceType::Uuid: - found = entry->uuid() == Uuid::fromHex(text); + case EntryReferenceType::QUuid: + found = entry->uuid() == QUuid::fromRfc4122(QByteArray::fromHex(text.toLatin1())); break; case EntryReferenceType::CustomAttributes: found = entry->attributes()->containsValue(text); @@ -178,12 +179,12 @@ Entry* Database::findEntryRecursive(const QString& text, EntryReferenceType refe return nullptr; } -Group* Database::resolveGroup(const Uuid& uuid) +Group* Database::resolveGroup(const QUuid& uuid) { return findGroupRecursive(uuid, m_rootGroup); } -Group* Database::findGroupRecursive(const Uuid& uuid, Group* group) +Group* Database::findGroupRecursive(const QUuid& uuid, Group* group) { if (group->uuid() == uuid) { return group; @@ -211,7 +212,7 @@ void Database::addDeletedObject(const DeletedObject& delObj) m_deletedObjects.append(delObj); } -void Database::addDeletedObject(const Uuid& uuid) +void Database::addDeletedObject(const QUuid& uuid) { DeletedObject delObj; delObj.deletionTime = QDateTime::currentDateTimeUtc(); @@ -220,7 +221,7 @@ void Database::addDeletedObject(const Uuid& uuid) addDeletedObject(delObj); } -Uuid Database::cipher() const +const QUuid& Database::cipher() const { return m_data.cipher; } @@ -246,7 +247,7 @@ bool Database::challengeMasterSeed(const QByteArray& masterSeed) return m_data.key.challenge(masterSeed, m_data.challengeResponseKey); } -void Database::setCipher(const Uuid& cipher) +void Database::setCipher(const QUuid& cipher) { Q_ASSERT(!cipher.isNull()); @@ -387,10 +388,10 @@ void Database::merge(const Database* other) { m_rootGroup->merge(other->rootGroup()); - for (Uuid customIconId : other->metadata()->customIcons().keys()) { + for (const QUuid& customIconId : other->metadata()->customIcons().keys()) { QImage customIcon = other->metadata()->customIcon(customIconId); if (!this->metadata()->containsCustomIcon(customIconId)) { - qDebug("Adding custom icon %s to database.", qPrintable(customIconId.toHex())); + qDebug() << QString("Adding custom icon %1 to database.").arg(customIconId.toString()); this->metadata()->addCustomIcon(customIconId, customIcon); } } @@ -407,12 +408,12 @@ void Database::setEmitModified(bool value) m_emitModified = value; } -Uuid Database::uuid() +const QUuid& Database::uuid() { return m_uuid; } -Database* Database::databaseByUuid(const Uuid& uuid) +Database* Database::databaseByUuid(const QUuid& uuid) { return m_uuidMap.value(uuid, 0); } diff --git a/src/core/Database.h b/src/core/Database.h index 26b0ab66..c712faa3 100644 --- a/src/core/Database.h +++ b/src/core/Database.h @@ -23,7 +23,6 @@ #include #include -#include "core/Uuid.h" #include "crypto/kdf/Kdf.h" #include "keys/CompositeKey.h" @@ -36,7 +35,7 @@ class QIODevice; struct DeletedObject { - Uuid uuid; + QUuid uuid; QDateTime deletionTime; }; @@ -56,7 +55,7 @@ public: struct DatabaseData { - Uuid cipher; + QUuid cipher; CompressionAlgorithm compressionAlgo; QByteArray transformedMasterKey; QSharedPointer kdf; @@ -83,14 +82,14 @@ public: Metadata* metadata(); const Metadata* metadata() const; - Entry* resolveEntry(const Uuid& uuid); + Entry* resolveEntry(const QUuid& uuid); Entry* resolveEntry(const QString& text, EntryReferenceType referenceType); - Group* resolveGroup(const Uuid& uuid); + Group* resolveGroup(const QUuid& uuid); QList deletedObjects(); void addDeletedObject(const DeletedObject& delObj); - void addDeletedObject(const Uuid& uuid); + void addDeletedObject(const QUuid& uuid); - Uuid cipher() const; + const QUuid& cipher() const; Database::CompressionAlgorithm compressionAlgo() const; QSharedPointer kdf() const; QByteArray transformedMasterKey() const; @@ -98,7 +97,7 @@ public: QByteArray challengeResponseKey() const; bool challengeMasterSeed(const QByteArray& masterSeed); - void setCipher(const Uuid& cipher); + void setCipher(const QUuid& cipher); void setCompressionAlgo(Database::CompressionAlgorithm algo); void setKdf(QSharedPointer kdf); bool setKey(const CompositeKey& key, bool updateChangedTime = true, bool updateTransformSalt = false); @@ -117,10 +116,10 @@ public: /** * Returns a unique id that is only valid as long as the Database exists. */ - Uuid uuid(); + const QUuid& uuid(); bool changeKdf(QSharedPointer kdf); - static Database* databaseByUuid(const Uuid& uuid); + static Database* databaseByUuid(const QUuid& uuid); static Database* openDatabaseFile(QString fileName, CompositeKey key); static Database* unlockFromStdin(QString databaseFilename, QString keyFilename = QString("")); @@ -140,9 +139,9 @@ private slots: void startModifiedTimer(); private: - Entry* findEntryRecursive(const Uuid& uuid, Group* group); + Entry* findEntryRecursive(const QUuid& uuid, Group* group); Entry* findEntryRecursive(const QString& text, EntryReferenceType referenceType, Group* group); - Group* findGroupRecursive(const Uuid& uuid, Group* group); + Group* findGroupRecursive(const QUuid& uuid, Group* group); void createRecycleBin(); QString writeDatabase(QIODevice* device); @@ -155,8 +154,8 @@ private: DatabaseData m_data; bool m_emitModified; - Uuid m_uuid; - static QHash m_uuidMap; + QUuid m_uuid; + static QHash m_uuidMap; }; #endif // KEEPASSX_DATABASE_H diff --git a/src/core/Entry.cpp b/src/core/Entry.cpp index b63f4c70..a87597a6 100644 --- a/src/core/Entry.cpp +++ b/src/core/Entry.cpp @@ -25,6 +25,7 @@ #include "core/Metadata.h" #include "totp/totp.h" +#include #include const int Entry::DefaultIconNumber = 0; @@ -110,7 +111,7 @@ EntryReferenceType Entry::referenceType(const QString& referenceStr) } else if (referenceLowerStr == QLatin1String("n")) { result = EntryReferenceType::Notes; } else if (referenceLowerStr == QLatin1String("i")) { - result = EntryReferenceType::Uuid; + result = EntryReferenceType::QUuid; } else if (referenceLowerStr == QLatin1String("o")) { result = EntryReferenceType::CustomAttributes; } @@ -118,7 +119,7 @@ EntryReferenceType Entry::referenceType(const QString& referenceStr) return result; } -Uuid Entry::uuid() const +const QUuid& Entry::uuid() const { return m_uuid; } @@ -170,7 +171,7 @@ int Entry::iconNumber() const return m_data.iconNumber; } -Uuid Entry::iconUuid() const +const QUuid& Entry::iconUuid() const { return m_data.customIcon; } @@ -417,7 +418,7 @@ quint8 Entry::totpDigits() const return m_data.totpDigits; } -void Entry::setUuid(const Uuid& uuid) +void Entry::setUuid(const QUuid& uuid) { Q_ASSERT(!uuid.isNull()); set(m_uuid, uuid); @@ -429,14 +430,14 @@ void Entry::setIcon(int iconNumber) if (m_data.iconNumber != iconNumber || !m_data.customIcon.isNull()) { m_data.iconNumber = iconNumber; - m_data.customIcon = Uuid(); + m_data.customIcon = QUuid(); emit modified(); emitDataChanged(); } } -void Entry::setIcon(const Uuid& uuid) +void Entry::setIcon(const QUuid& uuid) { Q_ASSERT(!uuid.isNull()); @@ -632,7 +633,7 @@ Entry* Entry::clone(CloneFlags flags) const Entry* entry = new Entry(); entry->setUpdateTimeinfo(false); if (flags & CloneNewUuid) { - entry->m_uuid = Uuid::random(); + entry->m_uuid = QUuid::createUuid(); } else { entry->m_uuid = m_uuid; } @@ -643,15 +644,13 @@ Entry* Entry::clone(CloneFlags flags) const if (flags & CloneUserAsRef) { // Build the username reference - QString username = "{REF:U@I:" + m_uuid.toHex() + "}"; - entry->m_attributes->set( - EntryAttributes::UserNameKey, username.toUpper(), m_attributes->isProtected(EntryAttributes::UserNameKey)); + QString username = "{REF:U@I:" + m_uuid.toRfc4122().toHex() + "}"; + entry->m_attributes->set(EntryAttributes::UserNameKey, username.toUpper(), m_attributes->isProtected(EntryAttributes::UserNameKey)); } if (flags & ClonePassAsRef) { - QString password = "{REF:P@I:" + m_uuid.toHex() + "}"; - entry->m_attributes->set( - EntryAttributes::PasswordKey, password.toUpper(), m_attributes->isProtected(EntryAttributes::PasswordKey)); + QString password = "{REF:P@I:" + m_uuid.toRfc4122().toHex() + "}"; + entry->m_attributes->set(EntryAttributes::PasswordKey, password.toUpper(), m_attributes->isProtected(EntryAttributes::PasswordKey)); } entry->m_autoTypeAssociations->copyDataFrom(m_autoTypeAssociations); @@ -757,7 +756,7 @@ void Entry::updateTotp() QString Entry::resolveMultiplePlaceholdersRecursive(const QString& str, int maxDepth) const { if (maxDepth <= 0) { - qWarning("Maximum depth of replacement has been reached. Entry uuid: %s", qPrintable(uuid().toHex())); + qWarning() << QString("Maximum depth of replacement has been reached. Entry uuid: %1").arg(uuid().toString()); return str; } @@ -781,7 +780,7 @@ QString Entry::resolveMultiplePlaceholdersRecursive(const QString& str, int maxD QString Entry::resolvePlaceholderRecursive(const QString& placeholder, int maxDepth) const { if (maxDepth <= 0) { - qWarning("Maximum depth of replacement has been reached. Entry uuid: %s", qPrintable(uuid().toHex())); + qWarning() << QString("Maximum depth of replacement has been reached. Entry uuid: %1").arg(uuid().toString()); return placeholder; } @@ -845,7 +844,7 @@ QString Entry::resolvePlaceholderRecursive(const QString& placeholder, int maxDe QString Entry::resolveReferencePlaceholderRecursive(const QString& placeholder, int maxDepth) const { if (maxDepth <= 0) { - qWarning("Maximum depth of replacement has been reached. Entry uuid: %s", qPrintable(uuid().toHex())); + qWarning() << QString("Maximum depth of replacement has been reached. Entry uuid: %1").arg(uuid().toString()); return placeholder; } @@ -893,8 +892,8 @@ QString Entry::referenceFieldValue(EntryReferenceType referenceType) const return url(); case EntryReferenceType::Notes: return notes(); - case EntryReferenceType::Uuid: - return uuid().toHex(); + case EntryReferenceType::QUuid: + return uuid().toRfc4122().toHex(); default: break; } diff --git a/src/core/Entry.h b/src/core/Entry.h index c096a9a2..de6a4b39 100644 --- a/src/core/Entry.h +++ b/src/core/Entry.h @@ -26,13 +26,13 @@ #include #include #include +#include #include "core/AutoTypeAssociations.h" #include "core/CustomData.h" #include "core/EntryAttachments.h" #include "core/EntryAttributes.h" #include "core/TimeInfo.h" -#include "core/Uuid.h" class Database; class Group; @@ -45,14 +45,14 @@ enum class EntryReferenceType Password, Url, Notes, - Uuid, + QUuid, CustomAttributes }; struct EntryData { int iconNumber; - Uuid customIcon; + QUuid customIcon; QColor foregroundColor; QColor backgroundColor; QString overrideUrl; @@ -72,12 +72,12 @@ class Entry : public QObject public: Entry(); ~Entry(); - Uuid uuid() const; + const QUuid& uuid() const; QImage icon() const; QPixmap iconPixmap() const; QPixmap iconScaledPixmap() const; int iconNumber() const; - Uuid iconUuid() const; + const QUuid& iconUuid() const; QColor foregroundColor() const; QColor backgroundColor() const; QString overrideUrl() const; @@ -117,9 +117,9 @@ public: static const QString AutoTypeSequenceUsername; static const QString AutoTypeSequencePassword; - void setUuid(const Uuid& uuid); + void setUuid(const QUuid& uuid); void setIcon(int iconNumber); - void setIcon(const Uuid& uuid); + void setIcon(const QUuid& uuid); void setForegroundColor(const QColor& color); void setBackgroundColor(const QColor& color); void setOverrideUrl(const QString& url); @@ -232,7 +232,7 @@ private: const Database* database() const; template bool set(T& property, const T& value); - Uuid m_uuid; + QUuid m_uuid; EntryData m_data; QPointer m_attributes; QPointer m_attachments; diff --git a/src/core/Group.cpp b/src/core/Group.cpp index b8bca108..a1a1dcd4 100644 --- a/src/core/Group.cpp +++ b/src/core/Group.cpp @@ -73,7 +73,7 @@ Group::~Group() Group* Group::createRecycleBin() { Group* recycleBin = new Group(); - recycleBin->setUuid(Uuid::random()); + recycleBin->setUuid(QUuid::createUuid()); recycleBin->setName(tr("Recycle Bin")); recycleBin->setIcon(RecycleBinIconNumber); recycleBin->setSearchingEnabled(Group::Disable); @@ -105,7 +105,7 @@ void Group::setUpdateTimeinfo(bool value) m_updateTimeinfo = value; } -Uuid Group::uuid() const +const QUuid& Group::uuid() const { return m_uuid; } @@ -171,7 +171,7 @@ int Group::iconNumber() const return m_data.iconNumber; } -Uuid Group::iconUuid() const +const QUuid& Group::iconUuid() const { return m_data.customIcon; } @@ -259,7 +259,7 @@ const CustomData* Group::customData() const return m_customData; } -void Group::setUuid(const Uuid& uuid) +void Group::setUuid(const QUuid& uuid) { set(m_uuid, uuid); } @@ -282,13 +282,13 @@ void Group::setIcon(int iconNumber) if (m_data.iconNumber != iconNumber || !m_data.customIcon.isNull()) { m_data.iconNumber = iconNumber; - m_data.customIcon = Uuid(); + m_data.customIcon = QUuid(); emit modified(); emit dataChanged(this); } } -void Group::setIcon(const Uuid& uuid) +void Group::setIcon(const QUuid& uuid) { Q_ASSERT(!uuid.isNull()); @@ -514,8 +514,9 @@ Entry* Group::findEntry(QString entryId) Q_ASSERT(!entryId.isNull()); Entry* entry; - if (Uuid::isUuid(entryId)) { - entry = findEntryByUuid(Uuid::fromHex(entryId)); + QUuid entryUuid = QUuid::fromRfc4122(QByteArray::fromHex(entryId.toLatin1())); + if (!entryUuid.isNull()) { + entry = findEntryByUuid(entryUuid); if (entry) { return entry; } @@ -535,7 +536,7 @@ Entry* Group::findEntry(QString entryId) return nullptr; } -Entry* Group::findEntryByUuid(const Uuid& uuid) +Entry* Group::findEntryByUuid(const QUuid& uuid) { Q_ASSERT(!uuid.isNull()); for (Entry* entry : entriesRecursive(false)) { @@ -654,9 +655,9 @@ QList Group::groupsRecursive(bool includeSelf) return groupList; } -QSet Group::customIconsRecursive() const +QSet Group::customIconsRecursive() const { - QSet result; + QSet result; if (!iconUuid().isNull()) { result.insert(iconUuid()); @@ -730,7 +731,7 @@ void Group::merge(const Group* other) emit modified(); } -Group* Group::findChildByUuid(const Uuid& uuid) +Group* Group::findChildByUuid(const QUuid& uuid) { Q_ASSERT(!uuid.isNull()); for (Group* group : groupsRecursive(true)) { @@ -760,7 +761,7 @@ Group* Group::clone(Entry::CloneFlags entryFlags, Group::CloneFlags groupFlags) clonedGroup->setUpdateTimeinfo(false); if (groupFlags & Group::CloneNewUuid) { - clonedGroup->setUuid(Uuid::random()); + clonedGroup->setUuid(QUuid::createUuid()); } else { clonedGroup->setUuid(this->uuid()); } @@ -1042,7 +1043,7 @@ Entry* Group::addEntryWithPath(QString entryPath) Entry* entry = new Entry(); entry->setTitle(entryTitle); - entry->setUuid(Uuid::random()); + entry->setUuid(QUuid::createUuid()); entry->setGroup(group); return entry; diff --git a/src/core/Group.h b/src/core/Group.h index 22220e42..57678055 100644 --- a/src/core/Group.h +++ b/src/core/Group.h @@ -28,7 +28,6 @@ #include "core/Database.h" #include "core/Entry.h" #include "core/TimeInfo.h" -#include "core/Uuid.h" class Group : public QObject { @@ -63,7 +62,7 @@ public: QString name; QString notes; int iconNumber; - Uuid customIcon; + QUuid customIcon; TimeInfo timeInfo; bool isExpanded; QString defaultAutoTypeSequence; @@ -77,14 +76,14 @@ public: static Group* createRecycleBin(); - Uuid uuid() const; + const QUuid& uuid() const; QString name() const; QString notes() const; QImage icon() const; QPixmap iconPixmap() const; QPixmap iconScaledPixmap() const; int iconNumber() const; - Uuid iconUuid() const; + const QUuid& iconUuid() const; TimeInfo timeInfo() const; bool isExpanded() const; QString defaultAutoTypeSequence() const; @@ -106,18 +105,18 @@ public: static const QString RootAutoTypeSequence; Group* findChildByName(const QString& name); - Group* findChildByUuid(const Uuid& uuid); + Group* findChildByUuid(const QUuid& uuid); Entry* findEntry(QString entryId); - Entry* findEntryByUuid(const Uuid& uuid); + Entry* findEntryByUuid(const QUuid& uuid); Entry* findEntryByPath(QString entryPath, QString basePath = QString("")); Group* findGroupByPath(QString groupPath, QString basePath = QString("/")); QStringList locate(QString locateTerm, QString currentPath = QString("/")); Entry* addEntryWithPath(QString entryPath); - void setUuid(const Uuid& uuid); + void setUuid(const QUuid& uuid); void setName(const QString& name); void setNotes(const QString& notes); void setIcon(int iconNumber); - void setIcon(const Uuid& uuid); + void setIcon(const QUuid& uuid); void setTimeInfo(const TimeInfo& timeInfo); void setExpanded(bool expanded); void setDefaultAutoTypeSequence(const QString& sequence); @@ -144,7 +143,7 @@ public: QList entriesRecursive(bool includeHistoryItems = false) const; QList groupsRecursive(bool includeSelf) const; QList groupsRecursive(bool includeSelf); - QSet customIconsRecursive() const; + QSet customIconsRecursive() const; /** * Creates a duplicate of this group. * Note that you need to copy the custom icons manually when inserting the @@ -197,7 +196,7 @@ private: void recCreateDelObjects(); QPointer m_db; - Uuid m_uuid; + QUuid m_uuid; GroupData m_data; QPointer m_lastTopVisibleEntry; QList m_children; diff --git a/src/core/Metadata.cpp b/src/core/Metadata.cpp index f8b0fd2f..54f99de2 100644 --- a/src/core/Metadata.cpp +++ b/src/core/Metadata.cpp @@ -160,12 +160,12 @@ bool Metadata::protectNotes() const return m_data.protectNotes; } -QImage Metadata::customIcon(const Uuid& uuid) const +QImage Metadata::customIcon(const QUuid& uuid) const { return m_customIcons.value(uuid); } -QPixmap Metadata::customIconPixmap(const Uuid& uuid) const +QPixmap Metadata::customIconPixmap(const QUuid& uuid) const { QPixmap pixmap; @@ -183,7 +183,7 @@ QPixmap Metadata::customIconPixmap(const Uuid& uuid) const return pixmap; } -QPixmap Metadata::customIconScaledPixmap(const Uuid& uuid) const +QPixmap Metadata::customIconScaledPixmap(const QUuid& uuid) const { QPixmap pixmap; @@ -202,28 +202,28 @@ QPixmap Metadata::customIconScaledPixmap(const Uuid& uuid) const return pixmap; } -bool Metadata::containsCustomIcon(const Uuid& uuid) const +bool Metadata::containsCustomIcon(const QUuid& uuid) const { return m_customIcons.contains(uuid); } -QHash Metadata::customIcons() const +QHash Metadata::customIcons() const { return m_customIcons; } -QHash Metadata::customIconsScaledPixmaps() const +QHash Metadata::customIconsScaledPixmaps() const { - QHash result; + QHash result; - for (const Uuid& uuid : m_customIconsOrder) { + for (const QUuid& uuid : m_customIconsOrder) { result.insert(uuid, customIconScaledPixmap(uuid)); } return result; } -QList Metadata::customIconsOrder() const +QList Metadata::customIconsOrder() const { return m_customIconsOrder; } @@ -378,7 +378,7 @@ void Metadata::setProtectNotes(bool value) set(m_data.protectNotes, value); } -void Metadata::addCustomIcon(const Uuid& uuid, const QImage& icon) +void Metadata::addCustomIcon(const QUuid& uuid, const QImage& icon) { Q_ASSERT(!uuid.isNull()); Q_ASSERT(!m_customIcons.contains(uuid)); @@ -395,7 +395,7 @@ void Metadata::addCustomIcon(const Uuid& uuid, const QImage& icon) emit modified(); } -void Metadata::addCustomIconScaled(const Uuid& uuid, const QImage& icon) +void Metadata::addCustomIconScaled(const QUuid& uuid, const QImage& icon) { QImage iconScaled; @@ -409,7 +409,7 @@ void Metadata::addCustomIconScaled(const Uuid& uuid, const QImage& icon) addCustomIcon(uuid, iconScaled); } -void Metadata::removeCustomIcon(const Uuid& uuid) +void Metadata::removeCustomIcon(const QUuid& uuid) { Q_ASSERT(!uuid.isNull()); Q_ASSERT(m_customIcons.contains(uuid)); @@ -430,15 +430,15 @@ void Metadata::removeCustomIcon(const Uuid& uuid) emit modified(); } -Uuid Metadata::findCustomIcon(const QImage& candidate) +QUuid Metadata::findCustomIcon(const QImage &candidate) { QByteArray hash = hashImage(candidate); - return m_customIconsHashes.value(hash, Uuid()); + return m_customIconsHashes.value(hash, QUuid()); } -void Metadata::copyCustomIcons(const QSet& iconList, const Metadata* otherMetadata) +void Metadata::copyCustomIcons(const QSet& iconList, const Metadata* otherMetadata) { - for (const Uuid& uuid : iconList) { + for (const QUuid& uuid : iconList) { Q_ASSERT(otherMetadata->containsCustomIcon(uuid)); if (!containsCustomIcon(uuid) && otherMetadata->containsCustomIcon(uuid)) { diff --git a/src/core/Metadata.h b/src/core/Metadata.h index a40fb502..f6fdd56e 100644 --- a/src/core/Metadata.h +++ b/src/core/Metadata.h @@ -25,9 +25,9 @@ #include #include #include +#include #include "core/CustomData.h" -#include "core/Uuid.h" class Database; class Group; @@ -78,14 +78,14 @@ public: bool protectPassword() const; bool protectUrl() const; bool protectNotes() const; - QImage customIcon(const Uuid& uuid) const; - QPixmap customIconPixmap(const Uuid& uuid) const; - QPixmap customIconScaledPixmap(const Uuid& uuid) const; - bool containsCustomIcon(const Uuid& uuid) const; - QHash customIcons() const; - QList customIconsOrder() const; + QImage customIcon(const QUuid& uuid) const; + QPixmap customIconPixmap(const QUuid& uuid) const; + QPixmap customIconScaledPixmap(const QUuid& uuid) const; + bool containsCustomIcon(const QUuid& uuid) const; + QHash customIcons() const; + QList customIconsOrder() const; bool recycleBinEnabled() const; - QHash customIconsScaledPixmaps() const; + QHash customIconsScaledPixmaps() const; Group* recycleBin(); const Group* recycleBin() const; QDateTime recycleBinChanged() const; @@ -119,11 +119,11 @@ public: void setProtectPassword(bool value); void setProtectUrl(bool value); void setProtectNotes(bool value); - void addCustomIcon(const Uuid& uuid, const QImage& icon); - void addCustomIconScaled(const Uuid& uuid, const QImage& icon); - void removeCustomIcon(const Uuid& uuid); - void copyCustomIcons(const QSet& iconList, const Metadata* otherMetadata); - Uuid findCustomIcon(const QImage& candidate); + void addCustomIcon(const QUuid& uuid, const QImage& icon); + void addCustomIconScaled(const QUuid& uuid, const QImage& icon); + void removeCustomIcon(const QUuid& uuid); + void copyCustomIcons(const QSet& iconList, const Metadata* otherMetadata); + QUuid findCustomIcon(const QImage& candidate); void setRecycleBinEnabled(bool value); void setRecycleBin(Group* group); void setRecycleBinChanged(const QDateTime& value); @@ -159,11 +159,11 @@ private: MetadataData m_data; - QHash m_customIcons; - mutable QHash m_customIconCacheKeys; - mutable QHash m_customIconScaledCacheKeys; - QList m_customIconsOrder; - QHash m_customIconsHashes; + QHash m_customIcons; + mutable QHash m_customIconCacheKeys; + mutable QHash m_customIconScaledCacheKeys; + QList m_customIconsOrder; + QHash m_customIconsHashes; QPointer m_recycleBin; QDateTime m_recycleBinChanged; diff --git a/src/core/Uuid.cpp b/src/core/Uuid.cpp deleted file mode 100644 index a0a07aa6..00000000 --- a/src/core/Uuid.cpp +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (C) 2010 Felix Geyer - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 or (at your option) - * version 3 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "Uuid.h" - -#include - -#include "crypto/Random.h" - -const int Uuid::Length = 16; -const QRegExp Uuid::HexRegExp = - QRegExp(QString("^[0-9A-F]{%1}$").arg(QString::number(Uuid::Length * 2)), Qt::CaseInsensitive); - -Uuid::Uuid() - : m_data(Length, 0) -{ -} - -Uuid::Uuid(const QByteArray& data) -{ - Q_ASSERT(data.size() == Length); - - m_data = data; -} - -Uuid Uuid::random() -{ - return Uuid(randomGen()->randomArray(Length)); -} - -QString Uuid::toBase64() const -{ - return QString::fromLatin1(m_data.toBase64()); -} - -QString Uuid::toHex() const -{ - return QString::fromLatin1(m_data.toHex()); -} - -QByteArray Uuid::toByteArray() const -{ - return m_data; -} - -bool Uuid::isNull() const -{ - for (int i = 0; i < m_data.size(); ++i) { - if (m_data[i] != 0) { - return false; - } - } - - return true; -} - -Uuid& Uuid::operator=(const Uuid& other) -{ - m_data = other.m_data; - - return *this; -} - -bool Uuid::operator==(const Uuid& other) const -{ - return m_data == other.m_data; -} - -bool Uuid::operator!=(const Uuid& other) const -{ - return !operator==(other); -} - -Uuid Uuid::fromBase64(const QString& str) -{ - QByteArray data = QByteArray::fromBase64(str.toLatin1()); - return Uuid(data); -} - -Uuid Uuid::fromHex(const QString& str) -{ - QByteArray data = QByteArray::fromHex(str.toLatin1()); - return Uuid(data); -} - -uint qHash(const Uuid& key) -{ - return qHash(key.toByteArray()); -} - -QDataStream& operator<<(QDataStream& stream, const Uuid& uuid) -{ - return stream << uuid.toByteArray(); -} - -QDataStream& operator>>(QDataStream& stream, Uuid& uuid) -{ - QByteArray data; - stream >> data; - if (data.size() == Uuid::Length) { - uuid = Uuid(data); - } - - return stream; -} - -bool Uuid::isUuid(const QString& uuid) -{ - return Uuid::HexRegExp.exactMatch(uuid); -} diff --git a/src/core/Uuid.h b/src/core/Uuid.h deleted file mode 100644 index 169d99dc..00000000 --- a/src/core/Uuid.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) 2010 Felix Geyer - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 or (at your option) - * version 3 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef KEEPASSX_UUID_H -#define KEEPASSX_UUID_H - -#include -#include -#include - -class Uuid -{ -public: - Uuid(); - explicit Uuid(const QByteArray& data); - static Uuid random(); - QString toBase64() const; - QString toHex() const; - QByteArray toByteArray() const; - - bool isNull() const; - Uuid& operator=(const Uuid& other); - bool operator==(const Uuid& other) const; - bool operator!=(const Uuid& other) const; - static const int Length; - static const QRegExp HexRegExp; - static Uuid fromBase64(const QString& str); - static Uuid fromHex(const QString& str); - static bool isUuid(const QString& str); - -private: - QByteArray m_data; -}; - -Q_DECLARE_TYPEINFO(Uuid, Q_MOVABLE_TYPE); - -uint qHash(const Uuid& key); - -QDataStream& operator<<(QDataStream& stream, const Uuid& uuid); -QDataStream& operator>>(QDataStream& stream, Uuid& uuid); - -#endif // KEEPASSX_UUID_H diff --git a/src/crypto/SymmetricCipher.cpp b/src/crypto/SymmetricCipher.cpp index 1ba42a53..0467ad7c 100644 --- a/src/crypto/SymmetricCipher.cpp +++ b/src/crypto/SymmetricCipher.cpp @@ -20,6 +20,8 @@ #include "config-keepassx.h" #include "crypto/SymmetricCipherGcrypt.h" +#include + SymmetricCipher::SymmetricCipher(Algorithm algo, Mode mode, Direction direction) : m_backend(createBackend(algo, mode, direction)) , m_initialized(false) @@ -90,7 +92,7 @@ QString SymmetricCipher::errorString() const return m_backend->errorString(); } -SymmetricCipher::Algorithm SymmetricCipher::cipherToAlgorithm(Uuid cipher) +SymmetricCipher::Algorithm SymmetricCipher::cipherToAlgorithm(const QUuid& cipher) { if (cipher == KeePass2::CIPHER_AES) { return Aes256; @@ -100,11 +102,11 @@ SymmetricCipher::Algorithm SymmetricCipher::cipherToAlgorithm(Uuid cipher) return Twofish; } - qWarning("SymmetricCipher::cipherToAlgorithm: invalid Uuid %s", cipher.toByteArray().toHex().data()); + qWarning() << "SymmetricCipher::cipherToAlgorithm: invalid UUID " << cipher; return InvalidAlgorithm; } -Uuid SymmetricCipher::algorithmToCipher(Algorithm algo) +QUuid SymmetricCipher::algorithmToCipher(Algorithm algo) { switch (algo) { case Aes256: @@ -115,7 +117,7 @@ Uuid SymmetricCipher::algorithmToCipher(Algorithm algo) return KeePass2::CIPHER_TWOFISH; default: qWarning("SymmetricCipher::algorithmToCipher: invalid algorithm %d", algo); - return Uuid(); + return QUuid(); } } diff --git a/src/crypto/SymmetricCipher.h b/src/crypto/SymmetricCipher.h index bf5b60a4..ede5ab1a 100644 --- a/src/crypto/SymmetricCipher.h +++ b/src/crypto/SymmetricCipher.h @@ -21,8 +21,8 @@ #include #include #include +#include -#include "core/Uuid.h" #include "crypto/SymmetricCipherBackend.h" #include "format/KeePass2.h" @@ -83,8 +83,8 @@ public: QString errorString() const; Algorithm algorithm() const; - static Algorithm cipherToAlgorithm(Uuid cipher); - static Uuid algorithmToCipher(Algorithm algo); + static Algorithm cipherToAlgorithm(const QUuid& cipher); + static QUuid algorithmToCipher(Algorithm algo); static int algorithmIvSize(Algorithm algo); static Mode algorithmMode(Algorithm algo); diff --git a/src/crypto/kdf/AesKdf.cpp b/src/crypto/kdf/AesKdf.cpp index a6f8f71e..0b2130cf 100644 --- a/src/crypto/kdf/AesKdf.cpp +++ b/src/crypto/kdf/AesKdf.cpp @@ -52,7 +52,7 @@ QVariantMap AesKdf::writeParameters() QVariantMap p; // always write old KDBX3 AES-KDF UUID for compatibility with other applications - p.insert(KeePass2::KDFPARAM_UUID, KeePass2::KDF_AES_KDBX3.toByteArray()); + p.insert(KeePass2::KDFPARAM_UUID, KeePass2::KDF_AES_KDBX3.toRfc4122()); p.insert(KeePass2::KDFPARAM_AES_ROUNDS, static_cast(rounds())); p.insert(KeePass2::KDFPARAM_AES_SEED, seed()); diff --git a/src/crypto/kdf/Argon2Kdf.cpp b/src/crypto/kdf/Argon2Kdf.cpp index 3f329845..2ae81a6b 100644 --- a/src/crypto/kdf/Argon2Kdf.cpp +++ b/src/crypto/kdf/Argon2Kdf.cpp @@ -133,7 +133,7 @@ bool Argon2Kdf::processParameters(const QVariantMap& p) QVariantMap Argon2Kdf::writeParameters() { QVariantMap p; - p.insert(KeePass2::KDFPARAM_UUID, KeePass2::KDF_ARGON2.toByteArray()); + p.insert(KeePass2::KDFPARAM_UUID, KeePass2::KDF_ARGON2.toRfc4122()); p.insert(KeePass2::KDFPARAM_ARGON2_VERSION, version()); p.insert(KeePass2::KDFPARAM_ARGON2_PARALLELISM, parallelism()); p.insert(KeePass2::KDFPARAM_ARGON2_MEMORY, memory() * 1024); diff --git a/src/crypto/kdf/Kdf.cpp b/src/crypto/kdf/Kdf.cpp index e500dbe6..2e1ad2ec 100644 --- a/src/crypto/kdf/Kdf.cpp +++ b/src/crypto/kdf/Kdf.cpp @@ -22,14 +22,14 @@ #include "crypto/Random.h" -Kdf::Kdf(Uuid uuid) +Kdf::Kdf(const QUuid& uuid) : m_rounds(KDF_DEFAULT_ROUNDS) , m_seed(QByteArray(KDF_DEFAULT_SEED_SIZE, 0)) , m_uuid(uuid) { } -Uuid Kdf::uuid() const +const QUuid& Kdf::uuid() const { return m_uuid; } diff --git a/src/crypto/kdf/Kdf.h b/src/crypto/kdf/Kdf.h index ab21bc4d..3d62efe8 100644 --- a/src/crypto/kdf/Kdf.h +++ b/src/crypto/kdf/Kdf.h @@ -19,8 +19,7 @@ #define KEEPASSX_KDF_H #include - -#include "core/Uuid.h" +#include #define KDF_DEFAULT_SEED_SIZE 32 #define KDF_DEFAULT_ROUNDS 1000000ull @@ -28,10 +27,10 @@ class Kdf { public: - explicit Kdf(Uuid uuid); + explicit Kdf(const QUuid& uuid); virtual ~Kdf() = default; - Uuid uuid() const; + const QUuid& uuid() const; int rounds() const; virtual bool setRounds(int rounds); @@ -54,7 +53,6 @@ protected: private: class BenchmarkThread; - const Uuid m_uuid; + const QUuid m_uuid; }; - #endif // KEEPASSX_KDF_H diff --git a/src/format/Kdbx3Writer.cpp b/src/format/Kdbx3Writer.cpp index 866acae0..f17da25a 100644 --- a/src/format/Kdbx3Writer.cpp +++ b/src/format/Kdbx3Writer.cpp @@ -65,12 +65,10 @@ bool Kdbx3Writer::writeDatabase(QIODevice* device, Database* db) writeMagicNumbers(&header, KeePass2::SIGNATURE_1, KeePass2::SIGNATURE_2, KeePass2::FILE_VERSION_3_1); - CHECK_RETURN_FALSE( - writeHeaderField(&header, KeePass2::HeaderFieldID::CipherID, db->cipher().toByteArray())); - CHECK_RETURN_FALSE( - writeHeaderField(&header, - KeePass2::HeaderFieldID::CompressionFlags, - Endian::sizedIntToBytes(db->compressionAlgo(), KeePass2::BYTEORDER))); + CHECK_RETURN_FALSE(writeHeaderField(&header, KeePass2::HeaderFieldID::CipherID, db->cipher().toRfc4122())); + CHECK_RETURN_FALSE(writeHeaderField(&header, KeePass2::HeaderFieldID::CompressionFlags, + Endian::sizedIntToBytes(db->compressionAlgo(), + KeePass2::BYTEORDER))); auto kdf = db->kdf(); CHECK_RETURN_FALSE(writeHeaderField(&header, KeePass2::HeaderFieldID::MasterSeed, masterSeed)); CHECK_RETURN_FALSE(writeHeaderField(&header, KeePass2::HeaderFieldID::TransformSeed, kdf->seed())); diff --git a/src/format/Kdbx4Writer.cpp b/src/format/Kdbx4Writer.cpp index 43234b1e..db90c859 100644 --- a/src/format/Kdbx4Writer.cpp +++ b/src/format/Kdbx4Writer.cpp @@ -73,12 +73,10 @@ bool Kdbx4Writer::writeDatabase(QIODevice* device, Database* db) writeMagicNumbers(&header, KeePass2::SIGNATURE_1, KeePass2::SIGNATURE_2, KeePass2::FILE_VERSION_4); - CHECK_RETURN_FALSE( - writeHeaderField(&header, KeePass2::HeaderFieldID::CipherID, db->cipher().toByteArray())); - CHECK_RETURN_FALSE(writeHeaderField( - &header, - KeePass2::HeaderFieldID::CompressionFlags, - Endian::sizedIntToBytes(static_cast(db->compressionAlgo()), KeePass2::BYTEORDER))); + CHECK_RETURN_FALSE(writeHeaderField(&header, KeePass2::HeaderFieldID::CipherID, db->cipher().toRfc4122())); + CHECK_RETURN_FALSE(writeHeaderField(&header, KeePass2::HeaderFieldID::CompressionFlags, + Endian::sizedIntToBytes(static_cast(db->compressionAlgo()), + KeePass2::BYTEORDER))); CHECK_RETURN_FALSE(writeHeaderField(&header, KeePass2::HeaderFieldID::MasterSeed, masterSeed)); CHECK_RETURN_FALSE(writeHeaderField(&header, KeePass2::HeaderFieldID::EncryptionIV, encryptionIV)); diff --git a/src/format/KdbxReader.cpp b/src/format/KdbxReader.cpp index ade824fb..e33b6e75 100644 --- a/src/format/KdbxReader.cpp +++ b/src/format/KdbxReader.cpp @@ -19,6 +19,8 @@ #include "core/Database.h" #include "core/Endian.h" +#define UUID_LENGHT 16 + /** * Read KDBX magic header numbers from a device. * @@ -133,12 +135,16 @@ KeePass2::ProtectedStreamAlgo KdbxReader::protectedStreamAlgo() const */ void KdbxReader::setCipher(const QByteArray& data) { - if (data.size() != Uuid::Length) { - raiseError(tr("Invalid cipher uuid length")); + if (data.size() != UUID_LENGHT) { + raiseError(tr("Invalid cipher uuid length: %1 (length=%2)").arg(QString(data)).arg(data.size())); return; } - Uuid uuid(data); + QUuid uuid = QUuid::fromRfc4122(data); + if (uuid.isNull()) { + raiseError(tr("Unable to parse UUID: %1").arg(QString(data))); + return; + } if (SymmetricCipher::cipherToAlgorithm(uuid) == SymmetricCipher::InvalidAlgorithm) { raiseError(tr("Unsupported cipher")); diff --git a/src/format/KdbxXmlReader.cpp b/src/format/KdbxXmlReader.cpp index b10df2eb..62b2e683 100644 --- a/src/format/KdbxXmlReader.cpp +++ b/src/format/KdbxXmlReader.cpp @@ -28,6 +28,8 @@ #include #include +#define UUID_LENGHT 16 + /** * @param version KDBX version */ @@ -142,12 +144,12 @@ void KdbxXmlReader::readDatabase(QIODevice* device, Database* db, KeePass2Random m_meta->setUpdateDatetime(true); - QHash::const_iterator iGroup; + QHash::const_iterator iGroup; for (iGroup = m_groups.constBegin(); iGroup != m_groups.constEnd(); ++iGroup) { iGroup.value()->setUpdateTimeinfo(true); } - QHash::const_iterator iEntry; + QHash::const_iterator iEntry; for (iEntry = m_entries.constBegin(); iEntry != m_entries.constEnd(); ++iEntry) { iEntry.value()->setUpdateTimeinfo(true); @@ -346,7 +348,7 @@ void KdbxXmlReader::parseIcon() { Q_ASSERT(m_xml.isStartElement() && m_xml.name() == "Icon"); - Uuid uuid; + QUuid uuid; QImage icon; bool uuidSet = false; bool iconSet = false; @@ -479,12 +481,12 @@ Group* KdbxXmlReader::parseGroup() QList entries; while (!m_xml.hasError() && m_xml.readNextStartElement()) { if (m_xml.name() == "UUID") { - Uuid uuid = readUuid(); + QUuid uuid = readUuid(); if (uuid.isNull()) { if (m_strictMode) { raiseError(tr("Null group uuid")); } else { - group->setUuid(Uuid::random()); + group->setUuid(QUuid::createUuid()); } } else { group->setUuid(uuid); @@ -515,7 +517,7 @@ Group* KdbxXmlReader::parseGroup() continue; } if (m_xml.name() == "CustomIconUUID") { - Uuid uuid = readUuid(); + QUuid uuid = readUuid(); if (!uuid.isNull()) { group->setIcon(uuid); } @@ -588,7 +590,7 @@ Group* KdbxXmlReader::parseGroup() } if (group->uuid().isNull() && !m_strictMode) { - group->setUuid(Uuid::random()); + group->setUuid(QUuid::createUuid()); } if (!group->uuid().isNull()) { @@ -633,10 +635,11 @@ void KdbxXmlReader::parseDeletedObject() while (!m_xml.hasError() && m_xml.readNextStartElement()) { if (m_xml.name() == "UUID") { - Uuid uuid = readUuid(); + QUuid uuid = readUuid(); if (uuid.isNull()) { if (m_strictMode) { raiseError(tr("Null DeleteObject uuid")); + return; } continue; } @@ -671,12 +674,12 @@ Entry* KdbxXmlReader::parseEntry(bool history) while (!m_xml.hasError() && m_xml.readNextStartElement()) { if (m_xml.name() == "UUID") { - Uuid uuid = readUuid(); + QUuid uuid = readUuid(); if (uuid.isNull()) { if (m_strictMode) { raiseError(tr("Null entry uuid")); } else { - entry->setUuid(Uuid::random()); + entry->setUuid(QUuid::createUuid()); } } else { entry->setUuid(uuid); @@ -695,7 +698,7 @@ Entry* KdbxXmlReader::parseEntry(bool history) continue; } if (m_xml.name() == "CustomIconUUID") { - Uuid uuid = readUuid(); + QUuid uuid = readUuid(); if (!uuid.isNull()) { entry->setIcon(uuid); } @@ -752,7 +755,7 @@ Entry* KdbxXmlReader::parseEntry(bool history) } if (entry->uuid().isNull() && !m_strictMode) { - entry->setUuid(Uuid::random()); + entry->setUuid(QUuid::createUuid()); } if (!entry->uuid().isNull()) { @@ -1090,19 +1093,19 @@ int KdbxXmlReader::readNumber() return result; } -Uuid KdbxXmlReader::readUuid() +QUuid KdbxXmlReader::readUuid() { QByteArray uuidBin = readBinary(); if (uuidBin.isEmpty()) { - return {}; + return QUuid(); } - if (uuidBin.length() != Uuid::Length) { + if (uuidBin.length() != UUID_LENGHT) { if (m_strictMode) { raiseError(tr("Invalid uuid value")); } - return {}; + return QUuid(); } - return Uuid(uuidBin); + return QUuid::fromRfc4122(uuidBin); } QByteArray KdbxXmlReader::readBinary() @@ -1146,7 +1149,7 @@ QByteArray KdbxXmlReader::readCompressedBinary() return result; } -Group* KdbxXmlReader::getGroup(const Uuid& uuid) +Group* KdbxXmlReader::getGroup(const QUuid& uuid) { if (uuid.isNull()) { return nullptr; @@ -1164,7 +1167,7 @@ Group* KdbxXmlReader::getGroup(const Uuid& uuid) return group; } -Entry* KdbxXmlReader::getEntry(const Uuid& uuid) +Entry* KdbxXmlReader::getEntry(const QUuid& uuid) { if (uuid.isNull()) { return nullptr; diff --git a/src/format/KdbxXmlReader.h b/src/format/KdbxXmlReader.h index 00c898d1..566fbfc7 100644 --- a/src/format/KdbxXmlReader.h +++ b/src/format/KdbxXmlReader.h @@ -21,7 +21,7 @@ #include "core/Database.h" #include "core/Metadata.h" #include "core/TimeInfo.h" -#include "core/Uuid.h" +#include "core/Database.h" #include #include @@ -86,14 +86,14 @@ protected: virtual QDateTime readDateTime(); virtual QColor readColor(); virtual int readNumber(); - virtual Uuid readUuid(); + virtual QUuid readUuid(); virtual QByteArray readBinary(); virtual QByteArray readCompressedBinary(); virtual void skipCurrentElement(); - virtual Group* getGroup(const Uuid& uuid); - virtual Entry* getEntry(const Uuid& uuid); + virtual Group* getGroup(const QUuid& uuid); + virtual Entry* getEntry(const QUuid& uuid); virtual bool isTrueValue(const QStringRef& value); virtual void raiseError(const QString& errorMessage); @@ -108,8 +108,8 @@ protected: QXmlStreamReader m_xml; QScopedPointer m_tmpParent; - QHash m_groups; - QHash m_entries; + QHash m_groups; + QHash m_entries; QHash m_binaryPool; QHash> m_binaryMap; diff --git a/src/format/KdbxXmlWriter.cpp b/src/format/KdbxXmlWriter.cpp index 748e16d3..5ad1e34a 100644 --- a/src/format/KdbxXmlWriter.cpp +++ b/src/format/KdbxXmlWriter.cpp @@ -154,15 +154,15 @@ void KdbxXmlWriter::writeCustomIcons() { m_xml.writeStartElement("CustomIcons"); - const QList customIconsOrder = m_meta->customIconsOrder(); - for (const Uuid& uuid : customIconsOrder) { + const QList customIconsOrder = m_meta->customIconsOrder(); + for (const QUuid& uuid : customIconsOrder) { writeIcon(uuid, m_meta->customIcon(uuid)); } m_xml.writeEndElement(); } -void KdbxXmlWriter::writeIcon(const Uuid& uuid, const QImage& icon) +void KdbxXmlWriter::writeIcon(const QUuid& uuid, const QImage& icon) { m_xml.writeStartElement("Icon"); @@ -502,9 +502,9 @@ void KdbxXmlWriter::writeDateTime(const QString& qualifiedName, const QDateTime& writeString(qualifiedName, dateTimeStr); } -void KdbxXmlWriter::writeUuid(const QString& qualifiedName, const Uuid& uuid) +void KdbxXmlWriter::writeUuid(const QString& qualifiedName, const QUuid& uuid) { - writeString(qualifiedName, uuid.toBase64()); + writeString(qualifiedName, uuid.toRfc4122().toBase64()); } void KdbxXmlWriter::writeUuid(const QString& qualifiedName, const Group* group) @@ -512,7 +512,7 @@ void KdbxXmlWriter::writeUuid(const QString& qualifiedName, const Group* group) if (group) { writeUuid(qualifiedName, group->uuid()); } else { - writeUuid(qualifiedName, Uuid()); + writeUuid(qualifiedName, QUuid()); } } @@ -521,7 +521,7 @@ void KdbxXmlWriter::writeUuid(const QString& qualifiedName, const Entry* entry) if (entry) { writeUuid(qualifiedName, entry->uuid()); } else { - writeUuid(qualifiedName, Uuid()); + writeUuid(qualifiedName, QUuid()); } } diff --git a/src/format/KdbxXmlWriter.h b/src/format/KdbxXmlWriter.h index a8ed79b8..51a80349 100644 --- a/src/format/KdbxXmlWriter.h +++ b/src/format/KdbxXmlWriter.h @@ -27,7 +27,6 @@ #include "core/Entry.h" #include "core/Group.h" #include "core/TimeInfo.h" -#include "core/Uuid.h" class KeePass2RandomStream; class Metadata; @@ -51,7 +50,7 @@ private: void writeMetadata(); void writeMemoryProtection(); void writeCustomIcons(); - void writeIcon(const Uuid& uuid, const QImage& icon); + void writeIcon(const QUuid& uuid, const QImage& icon); void writeBinaries(); void writeCustomData(const CustomData* customData); void writeCustomDataItem(const QString& key, const QString& value); @@ -69,7 +68,7 @@ private: void writeNumber(const QString& qualifiedName, int number); void writeBool(const QString& qualifiedName, bool b); void writeDateTime(const QString& qualifiedName, const QDateTime& dateTime); - void writeUuid(const QString& qualifiedName, const Uuid& uuid); + void writeUuid(const QString& qualifiedName, const QUuid& uuid); void writeUuid(const QString& qualifiedName, const Group* group); void writeUuid(const QString& qualifiedName, const Entry* entry); void writeBinary(const QString& qualifiedName, const QByteArray& ba); diff --git a/src/format/KeePass1Reader.cpp b/src/format/KeePass1Reader.cpp index 5789c590..1db6e5d1 100644 --- a/src/format/KeePass1Reader.cpp +++ b/src/format/KeePass1Reader.cpp @@ -207,7 +207,7 @@ Database* KeePass1Reader::readDatabase(QIODevice* device, const QString& passwor } else { entry->setGroup(m_groupIds.value(groupId)); } - entry->setUuid(Uuid::random()); + entry->setUuid(QUuid::createUuid()); } } @@ -545,7 +545,7 @@ Group* KeePass1Reader::readGroup(QIODevice* cipherStream) return nullptr; } - group->setUuid(Uuid::random()); + group->setUuid(QUuid::createUuid()); group->setTimeInfo(timeInfo); m_groupIds.insert(groupId, group.data()); m_groupLevels.insert(group.data(), groupLevel); @@ -846,7 +846,7 @@ bool KeePass1Reader::parseCustomIcons4(const QByteArray& data) quint32 numGroups = Endian::bytesToSizedInt(data.mid(pos, 4), KeePass1::BYTEORDER); pos += 4; - QList iconUuids; + QList iconUuids; for (quint32 i = 0; i < numIcons; i++) { if (data.size() < (pos + 4)) { @@ -865,7 +865,7 @@ bool KeePass1Reader::parseCustomIcons4(const QByteArray& data) icon = icon.scaled(16, 16); } - Uuid uuid = Uuid::random(); + QUuid uuid = QUuid::createUuid(); iconUuids.append(uuid); m_db->metadata()->addCustomIcon(uuid, icon); } diff --git a/src/format/KeePass2.cpp b/src/format/KeePass2.cpp index b53ff092..32e56801 100644 --- a/src/format/KeePass2.cpp +++ b/src/format/KeePass2.cpp @@ -21,13 +21,15 @@ #include "crypto/kdf/Argon2Kdf.h" #include -const Uuid KeePass2::CIPHER_AES = Uuid(QByteArray::fromHex("31c1f2e6bf714350be5805216afc5aff")); -const Uuid KeePass2::CIPHER_TWOFISH = Uuid(QByteArray::fromHex("ad68f29f576f4bb9a36ad47af965346c")); -const Uuid KeePass2::CIPHER_CHACHA20 = Uuid(QByteArray::fromHex("D6038A2B8B6F4CB5A524339A31DBB59A")); +#define UUID_LENGHT 16 -const Uuid KeePass2::KDF_AES_KDBX3 = Uuid(QByteArray::fromHex("C9D9F39A628A4460BF740D08C18A4FEA")); -const Uuid KeePass2::KDF_AES_KDBX4 = Uuid(QByteArray::fromHex("7C02BB8279A74AC0927D114A00648238")); -const Uuid KeePass2::KDF_ARGON2 = Uuid(QByteArray::fromHex("EF636DDF8C29444B91F7A9A403E30A0C")); +const QUuid KeePass2::CIPHER_AES = QUuid::fromRfc4122(QByteArray::fromHex("31c1f2e6bf714350be5805216afc5aff")); +const QUuid KeePass2::CIPHER_TWOFISH = QUuid::fromRfc4122(QByteArray::fromHex("ad68f29f576f4bb9a36ad47af965346c")); +const QUuid KeePass2::CIPHER_CHACHA20 = QUuid::fromRfc4122(QByteArray::fromHex("D6038A2B8B6F4CB5A524339A31DBB59A")); + +const QUuid KeePass2::KDF_AES_KDBX3 = QUuid::fromRfc4122(QByteArray::fromHex("C9D9F39A628A4460BF740D08C18A4FEA")); +const QUuid KeePass2::KDF_AES_KDBX4 = QUuid::fromRfc4122(QByteArray::fromHex("7C02BB8279A74AC0927D114A00648238")); +const QUuid KeePass2::KDF_ARGON2 = QUuid::fromRfc4122(QByteArray::fromHex("EF636DDF8C29444B91F7A9A403E30A0C")); const QByteArray KeePass2::INNER_STREAM_SALSA20_IV("\xE8\x30\x09\x4B\x97\x20\x5D\x2A"); @@ -44,15 +46,17 @@ const QString KeePass2::KDFPARAM_ARGON2_VERSION("V"); const QString KeePass2::KDFPARAM_ARGON2_SECRET("K"); const QString KeePass2::KDFPARAM_ARGON2_ASSOCDATA("A"); -const QList> KeePass2::CIPHERS{ - qMakePair(KeePass2::CIPHER_AES, QString(QT_TRANSLATE_NOOP("KeePass2", "AES: 256-bit"))), - qMakePair(KeePass2::CIPHER_TWOFISH, QString(QT_TRANSLATE_NOOP("KeePass2", "Twofish: 256-bit"))), - qMakePair(KeePass2::CIPHER_CHACHA20, QString(QT_TRANSLATE_NOOP("KeePass2", "ChaCha20: 256-bit")))}; +const QList> KeePass2::CIPHERS{ + qMakePair(KeePass2::CIPHER_AES, QObject::tr("AES: 256-bit")), + qMakePair(KeePass2::CIPHER_TWOFISH, QObject::tr("Twofish: 256-bit")), + qMakePair(KeePass2::CIPHER_CHACHA20, QObject::tr("ChaCha20: 256-bit")) +}; -const QList> KeePass2::KDFS{ - qMakePair(KeePass2::KDF_ARGON2, QString(QT_TRANSLATE_NOOP("KeePass2", "Argon2 (KDBX 4 – recommended)"))), - qMakePair(KeePass2::KDF_AES_KDBX4, QString(QT_TRANSLATE_NOOP("KeePass2", "AES-KDF (KDBX 4)"))), - qMakePair(KeePass2::KDF_AES_KDBX3, QString(QT_TRANSLATE_NOOP("KeePass2", "AES-KDF (KDBX 3.1)")))}; +const QList> KeePass2::KDFS{ + qMakePair(KeePass2::KDF_ARGON2, QObject::tr("Argon2 (KDBX 4 – recommended)")), + qMakePair(KeePass2::KDF_AES_KDBX4, QObject::tr("AES-KDF (KDBX 4)")), + qMakePair(KeePass2::KDF_AES_KDBX3, QObject::tr("AES-KDF (KDBX 3.1)")) +}; QByteArray KeePass2::hmacKey(QByteArray masterSeed, QByteArray transformedMasterKey) { @@ -72,11 +76,11 @@ QByteArray KeePass2::hmacKey(QByteArray masterSeed, QByteArray transformedMaster QSharedPointer KeePass2::kdfFromParameters(const QVariantMap& p) { QByteArray uuidBytes = p.value(KDFPARAM_UUID).toByteArray(); - if (uuidBytes.size() != Uuid::Length) { + if (uuidBytes.size() != UUID_LENGHT) { return {}; } - Uuid kdfUuid(uuidBytes); + QUuid kdfUuid = QUuid::fromRfc4122(uuidBytes); if (kdfUuid == KDF_AES_KDBX3) { // upgrade to non-legacy AES-KDF, since KDBX3 doesn't have any KDF parameters kdfUuid = KDF_AES_KDBX4; @@ -98,7 +102,7 @@ QVariantMap KeePass2::kdfToParameters(QSharedPointer kdf) return kdf->writeParameters(); } -QSharedPointer KeePass2::uuidToKdf(const Uuid& uuid) +QSharedPointer KeePass2::uuidToKdf(const QUuid& uuid) { if (uuid == KDF_AES_KDBX3) { return QSharedPointer::create(true); diff --git a/src/format/KeePass2.h b/src/format/KeePass2.h index bcfef238..a8e97c5b 100644 --- a/src/format/KeePass2.h +++ b/src/format/KeePass2.h @@ -23,8 +23,8 @@ #include #include #include +#include -#include "core/Uuid.h" #include "crypto/SymmetricCipher.h" #include "crypto/kdf/Kdf.h" @@ -46,13 +46,13 @@ namespace KeePass2 const QSysInfo::Endian BYTEORDER = QSysInfo::LittleEndian; - extern const Uuid CIPHER_AES; - extern const Uuid CIPHER_TWOFISH; - extern const Uuid CIPHER_CHACHA20; +extern const QUuid CIPHER_AES; +extern const QUuid CIPHER_TWOFISH; +extern const QUuid CIPHER_CHACHA20; - extern const Uuid KDF_AES_KDBX3; - extern const Uuid KDF_AES_KDBX4; - extern const Uuid KDF_ARGON2; +extern const QUuid KDF_AES_KDBX3; +extern const QUuid KDF_AES_KDBX4; +extern const QUuid KDF_ARGON2; extern const QByteArray INNER_STREAM_SALSA20_IV; @@ -67,8 +67,8 @@ namespace KeePass2 extern const QString KDFPARAM_ARGON2_SECRET; extern const QString KDFPARAM_ARGON2_ASSOCDATA; - extern const QList> CIPHERS; - extern const QList> KDFS; +extern const QList> CIPHERS; +extern const QList> KDFS; enum class HeaderFieldID { @@ -125,12 +125,11 @@ namespace KeePass2 ByteArray = 0x42 }; - QByteArray hmacKey(QByteArray masterSeed, QByteArray transformedMasterKey); - QSharedPointer kdfFromParameters(const QVariantMap& p); - QVariantMap kdfToParameters(QSharedPointer kdf); - QSharedPointer uuidToKdf(const Uuid& uuid); - Uuid kdfToUuid(QSharedPointer kdf); - ProtectedStreamAlgo idToProtectedStreamAlgo(quint32 id); +QByteArray hmacKey(QByteArray masterSeed, QByteArray transformedMasterKey); +QSharedPointer kdfFromParameters(const QVariantMap& p); +QVariantMap kdfToParameters(QSharedPointer kdf); +QSharedPointer uuidToKdf(const QUuid& uuid); +ProtectedStreamAlgo idToProtectedStreamAlgo(quint32 id); } // namespace KeePass2 diff --git a/src/gui/DatabaseSettingsWidget.cpp b/src/gui/DatabaseSettingsWidget.cpp index 1fa95c10..27973685 100644 --- a/src/gui/DatabaseSettingsWidget.cpp +++ b/src/gui/DatabaseSettingsWidget.cpp @@ -109,7 +109,7 @@ void DatabaseSettingsWidget::load(Database* db) m_uiEncryption->algorithmComboBox->addItem(QCoreApplication::translate("KeePass2", cipher.second.toUtf8()), cipher.first.toByteArray()); } - int cipherIndex = m_uiEncryption->algorithmComboBox->findData(m_db->cipher().toByteArray()); + int cipherIndex = m_uiEncryption->algorithmComboBox->findData(m_db->cipher().toRfc4122()); if (cipherIndex > -1) { m_uiEncryption->algorithmComboBox->setCurrentIndex(cipherIndex); } @@ -117,14 +117,13 @@ void DatabaseSettingsWidget::load(Database* db) // Setup kdf combo box m_uiEncryption->kdfComboBox->blockSignals(true); m_uiEncryption->kdfComboBox->clear(); - for (auto& kdf : asConst(KeePass2::KDFS)) { - m_uiEncryption->kdfComboBox->addItem(QCoreApplication::translate("KeePass2", kdf.second.toUtf8()), - kdf.first.toByteArray()); + for (auto& kdf: asConst(KeePass2::KDFS)) { + m_uiEncryption->kdfComboBox->addItem(kdf.second, kdf.first.toRfc4122()); } m_uiEncryption->kdfComboBox->blockSignals(false); auto kdfUuid = m_db->kdf()->uuid(); - int kdfIndex = m_uiEncryption->kdfComboBox->findData(kdfUuid.toByteArray()); + int kdfIndex = m_uiEncryption->kdfComboBox->findData(kdfUuid.toRfc4122()); if (kdfIndex > -1) { m_uiEncryption->kdfComboBox->setCurrentIndex(kdfIndex); kdfChanged(kdfIndex); @@ -149,7 +148,7 @@ void DatabaseSettingsWidget::load(Database* db) void DatabaseSettingsWidget::save() { // first perform safety check for KDF rounds - auto kdf = KeePass2::uuidToKdf(Uuid(m_uiEncryption->kdfComboBox->currentData().toByteArray())); + auto kdf = KeePass2::uuidToKdf(m_uiEncryption->kdfComboBox->currentData().value()); if (kdf->uuid() == KeePass2::KDF_ARGON2 && m_uiEncryption->transformRoundsSpinBox->value() > 10000) { QMessageBox warning; warning.setIcon(QMessageBox::Warning); @@ -218,7 +217,7 @@ void DatabaseSettingsWidget::save() truncateHistories(); } - m_db->setCipher(Uuid(m_uiEncryption->algorithmComboBox->currentData().toByteArray())); + m_db->setCipher(m_uiEncryption->algorithmComboBox->currentData().value()); // Save kdf parameters kdf->setRounds(m_uiEncryption->transformRoundsSpinBox->value()); @@ -256,7 +255,7 @@ void DatabaseSettingsWidget::transformRoundsBenchmark() m_uiEncryption->transformRoundsSpinBox->setFocus(); // Create a new kdf with the current parameters - auto kdf = KeePass2::uuidToKdf(Uuid(m_uiEncryption->kdfComboBox->currentData().toByteArray())); + auto kdf = KeePass2::uuidToKdf(m_uiEncryption->kdfComboBox->currentData().value()); kdf->setRounds(m_uiEncryption->transformRoundsSpinBox->value()); if (kdf->uuid() == KeePass2::KDF_ARGON2) { auto argon2Kdf = kdf.staticCast(); @@ -286,7 +285,7 @@ void DatabaseSettingsWidget::truncateHistories() void DatabaseSettingsWidget::kdfChanged(int index) { - Uuid id(m_uiEncryption->kdfComboBox->itemData(index).toByteArray()); + QUuid id(m_uiEncryption->kdfComboBox->itemData(index).value()); bool memoryEnabled = id == KeePass2::KDF_ARGON2; m_uiEncryption->memoryUsageLabel->setEnabled(memoryEnabled); diff --git a/src/gui/DatabaseWidget.cpp b/src/gui/DatabaseWidget.cpp index f1eb1793..8eddd163 100644 --- a/src/gui/DatabaseWidget.cpp +++ b/src/gui/DatabaseWidget.cpp @@ -369,7 +369,7 @@ void DatabaseWidget::createEntry() m_newEntry->setTitle(getCurrentSearch()); endSearch(); } - m_newEntry->setUuid(Uuid::random()); + m_newEntry->setUuid(QUuid::createUuid()); m_newEntry->setUsername(m_db->metadata()->defaultUserName()); m_newParent = m_groupView->currentGroup(); setIconFromParent(); @@ -675,7 +675,7 @@ void DatabaseWidget::createGroup() } m_newGroup = new Group(); - m_newGroup->setUuid(Uuid::random()); + m_newGroup->setUuid(QUuid::createUuid()); m_newParent = m_groupView->currentGroup(); switchToGroupEdit(m_newGroup, true); } @@ -905,8 +905,8 @@ void DatabaseWidget::unlockDatabase(bool accepted) replaceDatabase(db); restoreGroupEntryFocus(m_groupBeforeLock, m_entryBeforeLock); - m_groupBeforeLock = Uuid(); - m_entryBeforeLock = Uuid(); + m_groupBeforeLock = QUuid(); + m_entryBeforeLock = QUuid(); setCurrentWidget(m_mainWidget); m_unlockDatabaseWidget->clearForms(); @@ -1299,14 +1299,14 @@ void DatabaseWidget::reloadDatabaseFile() } } - Uuid groupBeforeReload; + QUuid groupBeforeReload; if (m_groupView && m_groupView->currentGroup()) { groupBeforeReload = m_groupView->currentGroup()->uuid(); } else { groupBeforeReload = m_db->rootGroup()->uuid(); } - Uuid entryBeforeReload; + QUuid entryBeforeReload; if (m_entryView && m_entryView->currentEntry()) { entryBeforeReload = m_entryView->currentEntry()->uuid(); } @@ -1348,7 +1348,7 @@ QStringList DatabaseWidget::customEntryAttributes() const * Restores the focus on the group and entry that was focused * before the database was locked or reloaded. */ -void DatabaseWidget::restoreGroupEntryFocus(Uuid groupUuid, Uuid entryUuid) +void DatabaseWidget::restoreGroupEntryFocus(const QUuid& groupUuid, const QUuid& entryUuid) { Group* restoredGroup = nullptr; const QList groups = m_db->rootGroup()->groupsRecursive(true); diff --git a/src/gui/DatabaseWidget.h b/src/gui/DatabaseWidget.h index ca1bfc14..78b162c3 100644 --- a/src/gui/DatabaseWidget.h +++ b/src/gui/DatabaseWidget.h @@ -24,8 +24,7 @@ #include #include -#include "core/Uuid.h" - +#include "gui/entry/EntryModel.h" #include "gui/MessageWidget.h" #include "gui/csvImport/CsvImportWizard.h" #include "gui/entry/EntryModel.h" @@ -204,7 +203,7 @@ private slots: // Database autoreload slots void onWatchedFileChanged(); void reloadDatabaseFile(); - void restoreGroupEntryFocus(Uuid groupUuid, Uuid EntryUuid); + void restoreGroupEntryFocus(const QUuid& groupUuid, const QUuid& EntryUuid); void unblockAutoReload(); private: @@ -234,8 +233,8 @@ private: Entry* m_newEntry; Group* m_newParent; QString m_filePath; - Uuid m_groupBeforeLock; - Uuid m_entryBeforeLock; + QUuid m_groupBeforeLock; + QUuid m_entryBeforeLock; MessageWidget* m_messageWidget; DetailsWidget* m_detailsView; diff --git a/src/gui/EditWidgetIcons.cpp b/src/gui/EditWidgetIcons.cpp index d5d97dde..981616e9 100644 --- a/src/gui/EditWidgetIcons.cpp +++ b/src/gui/EditWidgetIcons.cpp @@ -34,7 +34,7 @@ #endif IconStruct::IconStruct() - : uuid(Uuid()) + : uuid(QUuid()) , number(0) { } @@ -127,13 +127,10 @@ IconStruct EditWidgetIcons::state() void EditWidgetIcons::reset() { m_database = nullptr; - m_currentUuid = Uuid(); + m_currentUuid = QUuid(); } -void EditWidgetIcons::load(const Uuid& currentUuid, - Database* database, - const IconStruct& iconStruct, - const QString& url) +void EditWidgetIcons::load(const QUuid& currentUuid, Database* database, const IconStruct& iconStruct, const QString& url) { Q_ASSERT(database); Q_ASSERT(!currentUuid.isNull()); @@ -145,7 +142,7 @@ void EditWidgetIcons::load(const Uuid& currentUuid, m_customIconModel->setIcons(database->metadata()->customIconsScaledPixmaps(), database->metadata()->customIconsOrder()); - Uuid iconUuid = iconStruct.uuid; + QUuid iconUuid = iconStruct.uuid; if (iconUuid.isNull()) { int iconNumber = iconStruct.number; m_ui->defaultIconsView->setCurrentIndex(m_defaultIconModel->index(iconNumber, 0)); @@ -380,9 +377,9 @@ bool EditWidgetIcons::addCustomIcon(const QImage& icon) scaledicon = icon.scaled(128, 128); } - Uuid uuid = m_database->metadata()->findCustomIcon(scaledicon); + QUuid uuid = m_database->metadata()->findCustomIcon(scaledicon); if (uuid.isNull()) { - uuid = Uuid::random(); + uuid = QUuid::createUuid(); m_database->metadata()->addCustomIcon(uuid, scaledicon); m_customIconModel->setIcons(m_database->metadata()->customIconsScaledPixmaps(), m_database->metadata()->customIconsOrder()); @@ -405,7 +402,7 @@ void EditWidgetIcons::removeCustomIcon() if (m_database) { QModelIndex index = m_ui->customIconsView->currentIndex(); if (index.isValid()) { - Uuid iconUuid = m_customIconModel->uuidFromIndex(index); + QUuid iconUuid = m_customIconModel->uuidFromIndex(index); const QList allEntries = m_database->rootGroup()->entriesRecursive(true); QList entriesWithSameIcon; diff --git a/src/gui/EditWidgetIcons.h b/src/gui/EditWidgetIcons.h index e01ae4b1..82c4343e 100644 --- a/src/gui/EditWidgetIcons.h +++ b/src/gui/EditWidgetIcons.h @@ -24,10 +24,10 @@ #include #include #include +#include #include "config-keepassx.h" #include "core/Global.h" -#include "core/Uuid.h" #include "gui/MessageWidget.h" class Database; @@ -46,7 +46,7 @@ struct IconStruct { IconStruct(); - Uuid uuid; + QUuid uuid; int number; }; @@ -71,7 +71,7 @@ public: IconStruct state(); void reset(); - void load(const Uuid& currentUuid, Database* database, const IconStruct& iconStruct, const QString& url = ""); + void load(const QUuid& currentUuid, Database* database, const IconStruct& iconStruct, const QString& url = ""); public slots: void setUrl(const QString& url); @@ -98,7 +98,7 @@ private slots: private: const QScopedPointer m_ui; Database* m_database; - Uuid m_currentUuid; + QUuid m_currentUuid; #ifdef WITH_XC_NETWORKING QUrl m_url; QUrl m_fetchUrl; diff --git a/src/gui/EditWidgetProperties.cpp b/src/gui/EditWidgetProperties.cpp index fa5da054..6ec31c89 100644 --- a/src/gui/EditWidgetProperties.cpp +++ b/src/gui/EditWidgetProperties.cpp @@ -16,6 +16,9 @@ */ #include "EditWidgetProperties.h" + +#include + #include "MessageBox.h" #include "ui_EditWidgetProperties.h" @@ -39,13 +42,13 @@ EditWidgetProperties::~EditWidgetProperties() { } -void EditWidgetProperties::setFields(const TimeInfo& timeInfo, const Uuid& uuid) +void EditWidgetProperties::setFields(const TimeInfo& timeInfo, const QUuid& uuid) { static const QString timeFormat("d MMM yyyy HH:mm:ss"); m_ui->modifiedEdit->setText(timeInfo.lastModificationTime().toLocalTime().toString(timeFormat)); m_ui->createdEdit->setText(timeInfo.creationTime().toLocalTime().toString(timeFormat)); m_ui->accessedEdit->setText(timeInfo.lastAccessTime().toLocalTime().toString(timeFormat)); - m_ui->uuidEdit->setText(uuid.toHex()); + m_ui->uuidEdit->setText(uuid.toRfc4122().toHex()); } void EditWidgetProperties::setCustomData(const CustomData* customData) diff --git a/src/gui/EditWidgetProperties.h b/src/gui/EditWidgetProperties.h index e6bb2ed7..6fad1f86 100644 --- a/src/gui/EditWidgetProperties.h +++ b/src/gui/EditWidgetProperties.h @@ -25,7 +25,6 @@ #include "core/CustomData.h" #include "core/TimeInfo.h" -#include "core/Uuid.h" namespace Ui { @@ -40,7 +39,7 @@ public: explicit EditWidgetProperties(QWidget* parent = nullptr); ~EditWidgetProperties(); - void setFields(const TimeInfo& timeInfo, const Uuid& uuid); + void setFields(const TimeInfo& timeInfo, const QUuid& uuid); void setCustomData(const CustomData* customData); const CustomData* customData() const; diff --git a/src/gui/IconModels.cpp b/src/gui/IconModels.cpp index 48868284..495ba9b1 100644 --- a/src/gui/IconModels.cpp +++ b/src/gui/IconModels.cpp @@ -17,6 +17,8 @@ #include "IconModels.h" +#include + #include "core/DatabaseIcons.h" DefaultIconModel::DefaultIconModel(QObject* parent) @@ -53,7 +55,7 @@ CustomIconModel::CustomIconModel(QObject* parent) { } -void CustomIconModel::setIcons(const QHash& icons, const QList& iconsOrder) +void CustomIconModel::setIcons(const QHash& icons, const QList& iconsOrder) { beginResetModel(); @@ -80,21 +82,21 @@ QVariant CustomIconModel::data(const QModelIndex& index, int role) const } if (role == Qt::DecorationRole) { - Uuid uuid = uuidFromIndex(index); + QUuid uuid = uuidFromIndex(index); return m_icons.value(uuid); } return QVariant(); } -Uuid CustomIconModel::uuidFromIndex(const QModelIndex& index) const +QUuid CustomIconModel::uuidFromIndex(const QModelIndex& index) const { Q_ASSERT(index.isValid()); return m_iconsOrder.value(index.row()); } -QModelIndex CustomIconModel::indexFromUuid(const Uuid& uuid) const +QModelIndex CustomIconModel::indexFromUuid(const QUuid& uuid) const { int idx = m_iconsOrder.indexOf(uuid); if (idx > -1) { diff --git a/src/gui/IconModels.h b/src/gui/IconModels.h index 868ce442..1a603bc7 100644 --- a/src/gui/IconModels.h +++ b/src/gui/IconModels.h @@ -21,8 +21,6 @@ #include #include -#include "core/Uuid.h" - class DefaultIconModel : public QAbstractListModel { Q_OBJECT @@ -43,13 +41,13 @@ public: int rowCount(const QModelIndex& parent = QModelIndex()) const override; QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; - void setIcons(const QHash& icons, const QList& iconsOrder); - Uuid uuidFromIndex(const QModelIndex& index) const; - QModelIndex indexFromUuid(const Uuid& uuid) const; + void setIcons(const QHash& icons, const QList& iconsOrder); + QUuid uuidFromIndex(const QModelIndex& index) const; + QModelIndex indexFromUuid(const QUuid& uuid) const; private: - QHash m_icons; - QList m_iconsOrder; + QHash m_icons; + QList m_iconsOrder; }; #endif // KEEPASSX_ICONMODELS_H diff --git a/src/gui/csvImport/CsvImportWidget.cpp b/src/gui/csvImport/CsvImportWidget.cpp index f90f4636..926771fb 100644 --- a/src/gui/csvImport/CsvImportWidget.cpp +++ b/src/gui/csvImport/CsvImportWidget.cpp @@ -192,8 +192,8 @@ void CsvImportWidget::load(const QString& filename, Database* const db) m_parserModel->setFilename(filename); m_ui->labelFilename->setText(filename); Group* group = m_db->rootGroup(); - group->setUuid(Uuid::random()); - group->setNotes(tr("Imported from CSV file\nOriginal data: %1").arg(filename)); + group->setUuid(QUuid::createUuid()); + group->setNotes(tr("Imported from CSV file").append("\n").append(tr("Original data: ")) + filename); parse(); } @@ -235,7 +235,7 @@ void CsvImportWidget::writeDatabase() if (not m_parserModel->data(m_parserModel->index(r, 1)).isValid()) continue; Entry* entry = new Entry(); - entry->setUuid(Uuid::random()); + entry->setUuid(QUuid::createUuid()); entry->setGroup(splitGroups(m_parserModel->data(m_parserModel->index(r, 0)).toString())); entry->setTitle(m_parserModel->data(m_parserModel->index(r, 1)).toString()); entry->setUsername(m_parserModel->data(m_parserModel->index(r, 2)).toString()); @@ -324,7 +324,7 @@ Group* CsvImportWidget::splitGroups(QString label) Group* brandNew = new Group(); brandNew->setParent(current); brandNew->setName(groupName); - brandNew->setUuid(Uuid::random()); + brandNew->setUuid(QUuid::createUuid()); current = brandNew; } else { Q_ASSERT(children != nullptr); diff --git a/src/gui/group/GroupModel.cpp b/src/gui/group/GroupModel.cpp index ad268c46..e8f51909 100644 --- a/src/gui/group/GroupModel.cpp +++ b/src/gui/group/GroupModel.cpp @@ -224,8 +224,8 @@ bool GroupModel::dropMimeData(const QMimeData* data, Group* parentGroup = groupFromIndex(parent); if (isGroup) { - Uuid dbUuid; - Uuid groupUuid; + QUuid dbUuid; + QUuid groupUuid; stream >> dbUuid >> groupUuid; Database* db = Database::databaseByUuid(dbUuid); @@ -257,7 +257,7 @@ bool GroupModel::dropMimeData(const QMimeData* data, Database* targetDb = parentGroup->database(); if (sourceDb != targetDb) { - QSet customIcons = group->customIconsRecursive(); + QSet customIcons = group->customIconsRecursive(); targetDb->metadata()->copyCustomIcons(customIcons, sourceDb->metadata()); } @@ -268,8 +268,8 @@ bool GroupModel::dropMimeData(const QMimeData* data, } while (!stream.atEnd()) { - Uuid dbUuid; - Uuid entryUuid; + QUuid dbUuid; + QUuid entryUuid; stream >> dbUuid >> entryUuid; Database* db = Database::databaseByUuid(dbUuid); @@ -291,7 +291,7 @@ bool GroupModel::dropMimeData(const QMimeData* data, Database* sourceDb = dragEntry->group()->database(); Database* targetDb = parentGroup->database(); - Uuid customIcon = entry->iconUuid(); + QUuid customIcon = entry->iconUuid(); if (sourceDb != targetDb && !customIcon.isNull() && !targetDb->metadata()->containsCustomIcon(customIcon)) { targetDb->metadata()->addCustomIcon(customIcon, sourceDb->metadata()->customIcon(customIcon)); diff --git a/src/sshagent/SSHAgent.h b/src/sshagent/SSHAgent.h index b12f32b2..9bfe5294 100644 --- a/src/sshagent/SSHAgent.h +++ b/src/sshagent/SSHAgent.h @@ -36,8 +36,8 @@ public: const QString errorString() const; bool isAgentRunning() const; bool addIdentity(OpenSSHKey& key, quint32 lifetime = 0, bool confirm = false); - bool removeIdentity(OpenSSHKey& key); - void removeIdentityAtLock(const OpenSSHKey& key, const Uuid& uuid); + bool removeIdentity(OpenSSHKey& key) const; + void removeIdentityAtLock(const OpenSSHKey& key, const QUuid& uuid); signals: void error(const QString& message); diff --git a/tests/TestDeletedObjects.cpp b/tests/TestDeletedObjects.cpp index 50ff1845..00b9cd52 100644 --- a/tests/TestDeletedObjects.cpp +++ b/tests/TestDeletedObjects.cpp @@ -38,7 +38,7 @@ void TestDeletedObjects::createAndDelete(Database* db, int delObjectsSize) Group* g = new Group(); g->setParent(root); - Uuid gUuid = Uuid::random(); + QUuid gUuid = QUuid::createUuid(); g->setUuid(gUuid); delete g; QCOMPARE(db->deletedObjects().size(), ++delObjectsSize); @@ -47,19 +47,19 @@ void TestDeletedObjects::createAndDelete(Database* db, int delObjectsSize) Group* g1 = new Group(); g1->setParent(root); - Uuid g1Uuid = Uuid::random(); + QUuid g1Uuid = QUuid::createUuid(); g1->setUuid(g1Uuid); Entry* e1 = new Entry(); e1->setGroup(g1); - Uuid e1Uuid = Uuid::random(); + QUuid e1Uuid = QUuid::createUuid(); e1->setUuid(e1Uuid); Group* g2 = new Group(); g2->setParent(g1); - Uuid g2Uuid = Uuid::random(); + QUuid g2Uuid = QUuid::createUuid(); g2->setUuid(g2Uuid); Entry* e2 = new Entry(); e2->setGroup(g2); - Uuid e2Uuid = Uuid::random(); + QUuid e2Uuid = QUuid::createUuid(); e2->setUuid(e2Uuid); delete g1; @@ -74,7 +74,7 @@ void TestDeletedObjects::createAndDelete(Database* db, int delObjectsSize) Entry* e3 = new Entry(); e3->setGroup(root); - Uuid e3Uuid = Uuid::random(); + QUuid e3Uuid = QUuid::createUuid(); e3->setUuid(e3Uuid); delete e3; @@ -132,11 +132,11 @@ void TestDeletedObjects::testDatabaseChange() Group* g1 = new Group(); g1->setParent(root); - Uuid g1Uuid = Uuid::random(); + QUuid g1Uuid = QUuid::createUuid(); g1->setUuid(g1Uuid); Entry* e1 = new Entry(); e1->setGroup(g1); - Uuid e1Uuid = Uuid::random(); + QUuid e1Uuid = QUuid::createUuid(); e1->setUuid(e1Uuid); g1->setParent(root2); diff --git a/tests/TestEntry.cpp b/tests/TestEntry.cpp index 6ece366b..aa442621 100644 --- a/tests/TestEntry.cpp +++ b/tests/TestEntry.cpp @@ -82,7 +82,7 @@ void TestEntry::testCopyDataFrom() void TestEntry::testClone() { QScopedPointer entryOrg(new Entry()); - entryOrg->setUuid(Uuid::random()); + entryOrg->setUuid(QUuid::createUuid()); entryOrg->setTitle("Original Title"); entryOrg->beginUpdate(); entryOrg->setTitle("New Title"); @@ -205,7 +205,7 @@ void TestEntry::testResolveRecursivePlaceholders() auto* entry1 = new Entry(); entry1->setGroup(root); - entry1->setUuid(Uuid::random()); + entry1->setUuid(QUuid::createUuid()); entry1->setTitle("{USERNAME}"); entry1->setUsername("{PASSWORD}"); entry1->setPassword("{URL}"); @@ -215,10 +215,10 @@ void TestEntry::testResolveRecursivePlaceholders() auto* entry2 = new Entry(); entry2->setGroup(root); - entry2->setUuid(Uuid::random()); + entry2->setUuid(QUuid::createUuid()); entry2->setTitle("Entry2Title"); entry2->setUsername("{S:CustomUserNameAttribute}"); - entry2->setPassword(QString("{REF:P@I:%1}").arg(entry1->uuid().toHex())); + entry2->setPassword(QString("{REF:P@I:%1}").arg(QString(entry1->uuid().toRfc4122().toHex()))); entry2->setUrl("http://{S:IpAddress}:{S:Port}/{S:Uri}"); entry2->attributes()->set("CustomUserNameAttribute", "CustomUserNameValue"); entry2->attributes()->set("IpAddress", "127.0.0.1"); @@ -227,11 +227,11 @@ void TestEntry::testResolveRecursivePlaceholders() auto* entry3 = new Entry(); entry3->setGroup(root); - entry3->setUuid(Uuid::random()); - entry3->setTitle(QString("{REF:T@I:%1}").arg(entry2->uuid().toHex())); - entry3->setUsername(QString("{REF:U@I:%1}").arg(entry2->uuid().toHex())); - entry3->setPassword(QString("{REF:P@I:%1}").arg(entry2->uuid().toHex())); - entry3->setUrl(QString("{REF:A@I:%1}").arg(entry2->uuid().toHex())); + entry3->setUuid(QUuid::createUuid()); + entry3->setTitle(QString("{REF:T@I:%1}").arg(QString(entry2->uuid().toRfc4122().toHex()))); + entry3->setUsername(QString("{REF:U@I:%1}").arg(QString(entry2->uuid().toRfc4122().toHex()))); + entry3->setPassword(QString("{REF:P@I:%1}").arg(QString(entry2->uuid().toRfc4122().toHex()))); + entry3->setUrl(QString("{REF:A@I:%1}").arg(QString(entry2->uuid().toRfc4122().toHex()))); QCOMPARE(entry3->resolveMultiplePlaceholders(entry3->title()), QString("Entry2Title")); QCOMPARE(entry3->resolveMultiplePlaceholders(entry3->username()), QString("CustomUserNameValue")); @@ -240,11 +240,11 @@ void TestEntry::testResolveRecursivePlaceholders() auto* entry4 = new Entry(); entry4->setGroup(root); - entry4->setUuid(Uuid::random()); - entry4->setTitle(QString("{REF:T@I:%1}").arg(entry3->uuid().toHex())); - entry4->setUsername(QString("{REF:U@I:%1}").arg(entry3->uuid().toHex())); - entry4->setPassword(QString("{REF:P@I:%1}").arg(entry3->uuid().toHex())); - entry4->setUrl(QString("{REF:A@I:%1}").arg(entry3->uuid().toHex())); + entry4->setUuid(QUuid::createUuid()); + entry4->setTitle(QString("{REF:T@I:%1}").arg(QString(entry3->uuid().toRfc4122().toHex()))); + entry4->setUsername(QString("{REF:U@I:%1}").arg(QString(entry3->uuid().toRfc4122().toHex()))); + entry4->setPassword(QString("{REF:P@I:%1}").arg(QString(entry3->uuid().toRfc4122().toHex()))); + entry4->setUrl(QString("{REF:A@I:%1}").arg(QString(entry3->uuid().toRfc4122().toHex()))); QCOMPARE(entry4->resolveMultiplePlaceholders(entry4->title()), QString("Entry2Title")); QCOMPARE(entry4->resolveMultiplePlaceholders(entry4->username()), QString("CustomUserNameValue")); @@ -253,7 +253,7 @@ void TestEntry::testResolveRecursivePlaceholders() auto* entry5 = new Entry(); entry5->setGroup(root); - entry5->setUuid(Uuid::random()); + entry5->setUuid(QUuid::createUuid()); entry5->attributes()->set("Scheme", "http"); entry5->attributes()->set("Host", "host.org"); entry5->attributes()->set("Port", "2017"); @@ -271,8 +271,8 @@ void TestEntry::testResolveRecursivePlaceholders() auto* entry6 = new Entry(); entry6->setGroup(root); - entry6->setUuid(Uuid::random()); - entry6->setTitle(QString("{REF:T@I:%1}").arg(entry3->uuid().toHex())); + entry6->setUuid(QUuid::createUuid()); + entry6->setTitle(QString("{REF:T@I:%1}").arg(QString(entry3->uuid().toRfc4122().toHex()))); entry6->setUsername(QString("{TITLE}")); entry6->setPassword(QString("{PASSWORD}")); @@ -299,7 +299,7 @@ void TestEntry::testResolveReferencePlaceholders() auto* entry1 = new Entry(); entry1->setGroup(root); - entry1->setUuid(Uuid::random()); + entry1->setUuid(QUuid::createUuid()); entry1->setTitle("Title1"); entry1->setUsername("Username1"); entry1->setPassword("Password1"); @@ -311,7 +311,7 @@ void TestEntry::testResolveReferencePlaceholders() group->setParent(root); auto* entry2 = new Entry(); entry2->setGroup(group); - entry2->setUuid(Uuid::random()); + entry2->setUuid(QUuid::createUuid()); entry2->setTitle("Title2"); entry2->setUsername("Username2"); entry2->setPassword("Password2"); @@ -321,7 +321,7 @@ void TestEntry::testResolveReferencePlaceholders() auto* entry3 = new Entry(); entry3->setGroup(group); - entry3->setUuid(Uuid::random()); + entry3->setUuid(QUuid::createUuid()); entry3->setTitle("{S:AttributeTitle}"); entry3->setUsername("{S:AttributeUsername}"); entry3->setPassword("{S:AttributePassword}"); @@ -335,9 +335,9 @@ void TestEntry::testResolveReferencePlaceholders() auto* tstEntry = new Entry(); tstEntry->setGroup(root); - tstEntry->setUuid(Uuid::random()); + tstEntry->setUuid(QUuid::createUuid()); - QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:T@I:%1}").arg(entry1->uuid().toHex())), + QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:T@I:%1}").arg(QString(entry1->uuid().toRfc4122().toHex()))), entry1->title()); QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:T@T:%1}").arg(entry1->title())), entry1->title()); QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:T@U:%1}").arg(entry1->username())), entry1->title()); @@ -348,7 +348,7 @@ void TestEntry::testResolveReferencePlaceholders() QString("{REF:T@O:%1}").arg(entry1->attributes()->value("CustomAttribute1"))), entry1->title()); - QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:T@I:%1}").arg(entry1->uuid().toHex())), + QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:T@I:%1}").arg(QString(entry1->uuid().toRfc4122().toHex()))), entry1->title()); QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:T@T:%1}").arg(entry1->title())), entry1->title()); QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:U@U:%1}").arg(entry1->username())), @@ -358,7 +358,7 @@ void TestEntry::testResolveReferencePlaceholders() QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:A@A:%1}").arg(entry1->url())), entry1->url()); QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:N@N:%1}").arg(entry1->notes())), entry1->notes()); - QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:T@I:%1}").arg(entry2->uuid().toHex())), + QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:T@I:%1}").arg(QString(entry2->uuid().toRfc4122().toHex()))), entry2->title()); QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:T@T:%1}").arg(entry2->title())), entry2->title()); QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:T@U:%1}").arg(entry2->username())), entry2->title()); @@ -377,38 +377,23 @@ void TestEntry::testResolveReferencePlaceholders() QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:A@A:%1}").arg(entry2->url())), entry2->url()); QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:N@N:%1}").arg(entry2->notes())), entry2->notes()); - QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:T@I:%1}").arg(entry3->uuid().toHex())), - entry3->attributes()->value("AttributeTitle")); - QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:U@I:%1}").arg(entry3->uuid().toHex())), - entry3->attributes()->value("AttributeUsername")); - QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:P@I:%1}").arg(entry3->uuid().toHex())), - entry3->attributes()->value("AttributePassword")); - QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:A@I:%1}").arg(entry3->uuid().toHex())), - entry3->attributes()->value("AttributeUrl")); - QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:N@I:%1}").arg(entry3->uuid().toHex())), - entry3->attributes()->value("AttributeNotes")); + QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:T@I:%1}").arg(QString(entry3->uuid().toRfc4122().toHex()))), entry3->attributes()->value("AttributeTitle")); + QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:U@I:%1}").arg(QString(entry3->uuid().toRfc4122().toHex()))), entry3->attributes()->value("AttributeUsername")); + QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:P@I:%1}").arg(QString(entry3->uuid().toRfc4122().toHex()))), entry3->attributes()->value("AttributePassword")); + QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:A@I:%1}").arg(QString(entry3->uuid().toRfc4122().toHex()))), entry3->attributes()->value("AttributeUrl")); + QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:N@I:%1}").arg(QString(entry3->uuid().toRfc4122().toHex()))), entry3->attributes()->value("AttributeNotes")); - QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:T@I:%1}").arg(entry3->uuid().toHex().toUpper())), - entry3->attributes()->value("AttributeTitle")); - QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:U@I:%1}").arg(entry3->uuid().toHex().toUpper())), - entry3->attributes()->value("AttributeUsername")); - QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:P@I:%1}").arg(entry3->uuid().toHex().toUpper())), - entry3->attributes()->value("AttributePassword")); - QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:A@I:%1}").arg(entry3->uuid().toHex().toUpper())), - entry3->attributes()->value("AttributeUrl")); - QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:N@I:%1}").arg(entry3->uuid().toHex().toUpper())), - entry3->attributes()->value("AttributeNotes")); + QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:T@I:%1}").arg(QString(entry3->uuid().toRfc4122().toHex().toUpper()))), entry3->attributes()->value("AttributeTitle")); + QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:U@I:%1}").arg(QString(entry3->uuid().toRfc4122().toHex().toUpper()))), entry3->attributes()->value("AttributeUsername")); + QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:P@I:%1}").arg(QString(entry3->uuid().toRfc4122().toHex().toUpper()))), entry3->attributes()->value("AttributePassword")); + QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:A@I:%1}").arg(QString(entry3->uuid().toRfc4122().toHex().toUpper()))), entry3->attributes()->value("AttributeUrl")); + QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:N@I:%1}").arg(QString(entry3->uuid().toRfc4122().toHex().toUpper()))), entry3->attributes()->value("AttributeNotes")); - QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:t@i:%1}").arg(entry3->uuid().toHex().toLower())), - entry3->attributes()->value("AttributeTitle")); - QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:u@i:%1}").arg(entry3->uuid().toHex().toLower())), - entry3->attributes()->value("AttributeUsername")); - QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:p@i:%1}").arg(entry3->uuid().toHex().toLower())), - entry3->attributes()->value("AttributePassword")); - QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:a@i:%1}").arg(entry3->uuid().toHex().toLower())), - entry3->attributes()->value("AttributeUrl")); - QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:n@i:%1}").arg(entry3->uuid().toHex().toLower())), - entry3->attributes()->value("AttributeNotes")); + QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:t@i:%1}").arg(QString(entry3->uuid().toRfc4122().toHex().toLower()))), entry3->attributes()->value("AttributeTitle")); + QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:u@i:%1}").arg(QString(entry3->uuid().toRfc4122().toHex().toLower()))), entry3->attributes()->value("AttributeUsername")); + QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:p@i:%1}").arg(QString(entry3->uuid().toRfc4122().toHex().toLower()))), entry3->attributes()->value("AttributePassword")); + QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:a@i:%1}").arg(QString(entry3->uuid().toRfc4122().toHex().toLower()))), entry3->attributes()->value("AttributeUrl")); + QCOMPARE(tstEntry->resolveMultiplePlaceholders(QString("{REF:n@i:%1}").arg(QString(entry3->uuid().toRfc4122().toHex().toLower()))), entry3->attributes()->value("AttributeNotes")); } void TestEntry::testResolveNonIdPlaceholdersToUuid() @@ -419,27 +404,27 @@ void TestEntry::testResolveNonIdPlaceholdersToUuid() auto* referencedEntryTitle = new Entry(); referencedEntryTitle->setGroup(root); referencedEntryTitle->setTitle("myTitle"); - referencedEntryTitle->setUuid(Uuid::random()); + referencedEntryTitle->setUuid(QUuid::createUuid()); auto* referencedEntryUsername = new Entry(); referencedEntryUsername->setGroup(root); referencedEntryUsername->setUsername("myUser"); - referencedEntryUsername->setUuid(Uuid::random()); + referencedEntryUsername->setUuid(QUuid::createUuid()); auto* referencedEntryPassword = new Entry(); referencedEntryPassword->setGroup(root); referencedEntryPassword->setPassword("myPassword"); - referencedEntryPassword->setUuid(Uuid::random()); + referencedEntryPassword->setUuid(QUuid::createUuid()); auto* referencedEntryUrl = new Entry(); referencedEntryUrl->setGroup(root); referencedEntryUrl->setUrl("myUrl"); - referencedEntryUrl->setUuid(Uuid::random()); + referencedEntryUrl->setUuid(QUuid::createUuid()); auto* referencedEntryNotes = new Entry(); referencedEntryNotes->setGroup(root); referencedEntryNotes->setNotes("myNotes"); - referencedEntryNotes->setUuid(Uuid::random()); + referencedEntryNotes->setUuid(QUuid::createUuid()); const QList placeholders{'T', 'U', 'P', 'A', 'N'}; for (const QChar& searchIn : placeholders) { @@ -475,8 +460,9 @@ void TestEntry::testResolveNonIdPlaceholdersToUuid() newEntry->setGroup(root); newEntry->setNotes(newEntryNotesRaw); - const QString newEntryNotesResolved = newEntry->resolveMultiplePlaceholders(newEntry->notes()); - QCOMPARE(newEntryNotesResolved, QString(referencedEntry->uuid().toHex())); + const QString newEntryNotesResolved = + newEntry->resolveMultiplePlaceholders(newEntry->notes()); + QCOMPARE(newEntryNotesResolved, QString(referencedEntry->uuid().toRfc4122().toHex())); } } @@ -487,7 +473,7 @@ void TestEntry::testResolveClonedEntry() auto* original = new Entry(); original->setGroup(root); - original->setUuid(Uuid::random()); + original->setUuid(QUuid::createUuid()); original->setTitle("Title"); original->setUsername("SomeUsername"); original->setPassword("SomePassword"); diff --git a/tests/TestEntryModel.cpp b/tests/TestEntryModel.cpp index 6bc65db4..dd3a5372 100644 --- a/tests/TestEntryModel.cpp +++ b/tests/TestEntryModel.cpp @@ -217,15 +217,14 @@ void TestEntryModel::testCustomIconModel() QCOMPARE(model->rowCount(), 0); - QHash icons; - QList iconsOrder; + QHash icons; + QList iconsOrder; - Uuid iconUuid(QByteArray(16, '2')); + QUuid iconUuid(QByteArray(16, '2')); icons.insert(iconUuid, QPixmap()); iconsOrder << iconUuid; - Uuid iconUuid2(QByteArray(16, '1')); - QImage icon2; + QUuid iconUuid2(QByteArray(16, '1')); icons.insert(iconUuid2, QPixmap()); iconsOrder << iconUuid2; diff --git a/tests/TestGlobal.h b/tests/TestGlobal.h index 788bd8a1..ef7472c0 100644 --- a/tests/TestGlobal.h +++ b/tests/TestGlobal.h @@ -26,15 +26,7 @@ namespace QTest { - - template <> inline char* toString(const Uuid& uuid) - { - QByteArray ba = "Uuid("; - ba += uuid.toHex().toLatin1().constData(); - ba += ")"; - return qstrdup(ba.constData()); - } - + template <> inline char* toString(const Group::TriState& triState) { QString value; diff --git a/tests/TestGroup.cpp b/tests/TestGroup.cpp index 0058c711..efdff316 100644 --- a/tests/TestGroup.cpp +++ b/tests/TestGroup.cpp @@ -93,7 +93,7 @@ void TestGroup::testParenting() g4->setName("test"); g3->setName("test"); g1->setName("test"); - g3->setIcon(Uuid::random()); + g3->setIcon(QUuid::createUuid()); g1->setIcon(2); QCOMPARE(spy.count(), 6); delete db; @@ -293,12 +293,12 @@ void TestGroup::testCopyCustomIcon() { QScopedPointer dbSource(new Database()); - Uuid groupIconUuid = Uuid::random(); + QUuid groupIconUuid = QUuid::createUuid(); QImage groupIcon(16, 16, QImage::Format_RGB32); groupIcon.setPixel(0, 0, qRgb(255, 0, 0)); dbSource->metadata()->addCustomIcon(groupIconUuid, groupIcon); - Uuid entryIconUuid = Uuid::random(); + QUuid entryIconUuid = QUuid::createUuid(); QImage entryIcon(16, 16, QImage::Format_RGB32); entryIcon.setPixel(0, 0, qRgb(255, 0, 0)); dbSource->metadata()->addCustomIcon(entryIconUuid, entryIcon); @@ -412,25 +412,25 @@ void TestGroup::testCopyCustomIcons() QScopedPointer group1(new Group()); group1->setParent(dbSource->rootGroup()); - Uuid group1Icon = Uuid::random(); + QUuid group1Icon = QUuid::createUuid(); dbSource->metadata()->addCustomIcon(group1Icon, iconImage1); group1->setIcon(group1Icon); QScopedPointer group2(new Group()); group2->setParent(group1.data()); - Uuid group2Icon = Uuid::random(); + QUuid group2Icon = QUuid::createUuid(); dbSource->metadata()->addCustomIcon(group2Icon, iconImage1); group2->setIcon(group2Icon); QScopedPointer entry1(new Entry()); entry1->setGroup(group2.data()); - Uuid entry1IconOld = Uuid::random(); + QUuid entry1IconOld = QUuid::createUuid(); dbSource->metadata()->addCustomIcon(entry1IconOld, iconImage1); entry1->setIcon(entry1IconOld); // add history item entry1->beginUpdate(); - Uuid entry1IconNew = Uuid::random(); + QUuid entry1IconNew = QUuid::createUuid(); dbSource->metadata()->addCustomIcon(entry1IconNew, iconImage1); entry1->setIcon(entry1IconNew); entry1->endUpdate(); @@ -459,7 +459,7 @@ void TestGroup::testFindEntry() Entry* entry1 = new Entry(); entry1->setTitle(QString("entry1")); entry1->setGroup(db->rootGroup()); - entry1->setUuid(Uuid::random()); + entry1->setUuid(QUuid::createUuid()); Group* group1 = new Group(); group1->setName("group1"); @@ -468,13 +468,13 @@ void TestGroup::testFindEntry() entry2->setTitle(QString("entry2")); entry2->setGroup(group1); - entry2->setUuid(Uuid::random()); + entry2->setUuid(QUuid::createUuid()); group1->setParent(db->rootGroup()); Entry* entry; - entry = db->rootGroup()->findEntry(entry1->uuid().toHex()); + entry = db->rootGroup()->findEntry(entry1->uuid().toRfc4122().toHex()); QVERIFY(entry != nullptr); QCOMPARE(entry->title(), QString("entry1")); @@ -491,7 +491,7 @@ void TestGroup::testFindEntry() entry = db->rootGroup()->findEntry(QString("//entry1")); QVERIFY(entry == nullptr); - entry = db->rootGroup()->findEntry(entry2->uuid().toHex()); + entry = db->rootGroup()->findEntry(entry2->uuid().toRfc4122().toHex()); QVERIFY(entry != nullptr); QCOMPARE(entry->title(), QString("entry2")); @@ -602,7 +602,7 @@ void TestGroup::testPrint() Entry* entry1 = new Entry(); entry1->setTitle(QString("entry1")); entry1->setGroup(db->rootGroup()); - entry1->setUuid(Uuid::random()); + entry1->setUuid(QUuid::createUuid()); output = db->rootGroup()->print(); QCOMPARE(output, QString("entry1\n")); @@ -614,7 +614,7 @@ void TestGroup::testPrint() entry2->setTitle(QString("entry2")); entry2->setGroup(group1); - entry2->setUuid(Uuid::random()); + entry2->setUuid(QUuid::createUuid()); group1->setParent(db->rootGroup()); diff --git a/tests/TestKdbx2.cpp b/tests/TestKdbx2.cpp index 76d5d81b..9fe90ae6 100644 --- a/tests/TestKdbx2.cpp +++ b/tests/TestKdbx2.cpp @@ -71,7 +71,7 @@ void TestKdbx2::testFormat200() QScopedPointer db(reader.readDatabase(filename, key)); QCOMPARE(reader.version(), KeePass2::FILE_VERSION_2 & KeePass2::FILE_VERSION_CRITICAL_MASK); - QVERIFY(!reader.hasError()); + QVERIFY2(!reader.hasError(), reader.errorString().toStdString().c_str()); verifyKdbx2Db(db.data()); } @@ -82,6 +82,8 @@ void TestKdbx2::testFormat200Upgrade() key.addKey(PasswordKey("a")); KeePass2Reader reader; QScopedPointer db(reader.readDatabase(filename, key)); + QVERIFY2(!reader.hasError(), reader.errorString().toStdString().c_str()); + QVERIFY(!db.isNull()); QCOMPARE(reader.version(), KeePass2::FILE_VERSION_2 & KeePass2::FILE_VERSION_CRITICAL_MASK); QCOMPARE(db->kdf()->uuid(), KeePass2::KDF_AES_KDBX3); diff --git a/tests/TestKdbx4.cpp b/tests/TestKdbx4.cpp index 53207a04..9758ac13 100644 --- a/tests/TestKdbx4.cpp +++ b/tests/TestKdbx4.cpp @@ -109,7 +109,7 @@ void TestKdbx4::writeKdbx(QIODevice* device, Database* db, bool& hasError, QStri QCOMPARE(writer.version(), KeePass2::FILE_VERSION_4); } -Q_DECLARE_METATYPE(Uuid); +Q_DECLARE_METATYPE(QUuid) void TestKdbx4::testFormat400() { QString filename = QString(KEEPASSX_TEST_DATA_DIR).append("/Format400.kdbx"); @@ -136,8 +136,8 @@ void TestKdbx4::testFormat400() void TestKdbx4::testFormat400Upgrade() { - QFETCH(Uuid, kdfUuid); - QFETCH(Uuid, cipherUuid); + QFETCH(QUuid, kdfUuid); + QFETCH(QUuid, cipherUuid); QFETCH(bool, addCustomData); QFETCH(quint32, expectedVersion); @@ -191,8 +191,8 @@ void TestKdbx4::testFormat400Upgrade() // clang-format off void TestKdbx4::testFormat400Upgrade_data() { - QTest::addColumn("kdfUuid"); - QTest::addColumn("cipherUuid"); + QTest::addColumn("kdfUuid"); + QTest::addColumn("cipherUuid"); QTest::addColumn("addCustomData"); QTest::addColumn("expectedVersion"); @@ -265,20 +265,20 @@ void TestKdbx4::testUpgradeMasterKeyIntegrity() } else if (upgradeAction == "group-customdata") { auto group = new Group(); group->setParent(db->rootGroup()); - group->setUuid(Uuid::random()); + group->setUuid(QUuid::createUuid()); group->customData()->set("abc", "def"); } else if (upgradeAction == "rootentry-customdata") { auto entry = new Entry(); entry->setGroup(db->rootGroup()); - entry->setUuid(Uuid::random()); + entry->setUuid(QUuid::createUuid()); entry->customData()->set("abc", "def"); } else if (upgradeAction == "entry-customdata") { auto group = new Group(); group->setParent(db->rootGroup()); - group->setUuid(Uuid::random()); + group->setUuid(QUuid::createUuid()); auto entry = new Entry(); entry->setGroup(group); - entry->setUuid(Uuid::random()); + entry->setUuid(QUuid::createUuid()); entry->customData()->set("abc", "def"); } else { QFAIL(qPrintable(QString("Unknown action: %s").arg(upgradeAction))); @@ -362,14 +362,14 @@ void TestKdbx4::testCustomData() // test copied custom group data auto* group = new Group(); group->setParent(root); - group->setUuid(Uuid::random()); + group->setUuid(QUuid::createUuid()); group->customData()->copyDataFrom(root->customData()); QCOMPARE(*group->customData(), *root->customData()); // test copied custom entry data auto* entry = new Entry(); entry->setGroup(group); - entry->setUuid(Uuid::random()); + entry->setUuid(QUuid::createUuid()); entry->customData()->copyDataFrom(group->customData()); QCOMPARE(*entry->customData(), *root->customData()); diff --git a/tests/TestKeePass2Format.cpp b/tests/TestKeePass2Format.cpp index 9dac0769..ce639bde 100644 --- a/tests/TestKeePass2Format.cpp +++ b/tests/TestKeePass2Format.cpp @@ -47,18 +47,18 @@ void TestKeePass2Format::initTestCase() m_kdbxSourceDb->setKey(key); m_kdbxSourceDb->metadata()->setName("TESTDB"); Group* group = m_kdbxSourceDb->rootGroup(); - group->setUuid(Uuid::random()); + group->setUuid(QUuid::createUuid()); group->setNotes("I'm a note!"); auto entry = new Entry(); entry->setPassword(QString::fromUtf8("\xc3\xa4\xa3\xb6\xc3\xbc\xe9\x9b\xbb\xe7\xb4\x85")); - entry->setUuid(Uuid::random()); + entry->setUuid(QUuid::createUuid()); entry->attributes()->set("test", "protectedTest", true); QVERIFY(entry->attributes()->isProtected("test")); entry->attachments()->set("myattach.txt", QByteArray("this is an attachment")); entry->attachments()->set("aaa.txt", QByteArray("also an attachment")); entry->setGroup(group); auto groupNew = new Group(); - groupNew->setUuid(Uuid::random()); + groupNew->setUuid(QUuid::createUuid()); groupNew->setName("TESTGROUP"); groupNew->setNotes("I'm a sub group note!"); groupNew->setParent(group); @@ -108,7 +108,7 @@ void TestKeePass2Format::testXmlMetadata() void TestKeePass2Format::testXmlCustomIcons() { QCOMPARE(m_xmlDb->metadata()->customIcons().size(), 1); - Uuid uuid = Uuid::fromBase64("++vyI+daLk6omox4a6kQGA=="); + QUuid uuid = QUuid::fromRfc4122(QByteArray::fromBase64("++vyI+daLk6omox4a6kQGA==")); QVERIFY(m_xmlDb->metadata()->customIcons().contains(uuid)); QImage icon = m_xmlDb->metadata()->customIcon(uuid); QCOMPARE(icon.width(), 16); @@ -128,11 +128,11 @@ void TestKeePass2Format::testXmlGroupRoot() { const Group* group = m_xmlDb->rootGroup(); QVERIFY(group); - QCOMPARE(group->uuid().toBase64(), QString("lmU+9n0aeESKZvcEze+bRg==")); + QCOMPARE(group->uuid(), QUuid::fromRfc4122(QByteArray::fromBase64("lmU+9n0aeESKZvcEze+bRg=="))); QCOMPARE(group->name(), QString("NewDatabase")); QCOMPARE(group->notes(), QString("")); QCOMPARE(group->iconNumber(), 49); - QCOMPARE(group->iconUuid(), Uuid()); + QCOMPARE(group->iconUuid(), QUuid()); QVERIFY(group->isExpanded()); TimeInfo ti = group->timeInfo(); QCOMPARE(ti.lastModificationTime(), Test::datetime(2010, 8, 8, 17, 24, 27)); @@ -145,7 +145,7 @@ void TestKeePass2Format::testXmlGroupRoot() QCOMPARE(group->defaultAutoTypeSequence(), QString("")); QCOMPARE(group->autoTypeEnabled(), Group::Inherit); QCOMPARE(group->searchingEnabled(), Group::Inherit); - QCOMPARE(group->lastTopVisibleEntry()->uuid().toBase64(), QString("+wSUOv6qf0OzW8/ZHAs2sA==")); + QCOMPARE(group->lastTopVisibleEntry()->uuid(), QUuid::fromRfc4122(QByteArray::fromBase64("+wSUOv6qf0OzW8/ZHAs2sA=="))); QCOMPARE(group->children().size(), 3); QVERIFY(m_xmlDb->metadata()->recycleBin() == m_xmlDb->rootGroup()->children().at(2)); @@ -156,11 +156,11 @@ void TestKeePass2Format::testXmlGroup1() { const Group* group = m_xmlDb->rootGroup()->children().at(0); - QCOMPARE(group->uuid().toBase64(), QString("AaUYVdXsI02h4T1RiAlgtg==")); + QCOMPARE(group->uuid(), QUuid::fromRfc4122(QByteArray::fromBase64("AaUYVdXsI02h4T1RiAlgtg=="))); QCOMPARE(group->name(), QString("General")); QCOMPARE(group->notes(), QString("Group Notez")); QCOMPARE(group->iconNumber(), 48); - QCOMPARE(group->iconUuid(), Uuid()); + QCOMPARE(group->iconUuid(), QUuid()); QCOMPARE(group->isExpanded(), true); QCOMPARE(group->defaultAutoTypeSequence(), QString("{Password}{ENTER}")); QCOMPARE(group->autoTypeEnabled(), Group::Enable); @@ -172,19 +172,19 @@ void TestKeePass2Format::testXmlGroup2() { const Group* group = m_xmlDb->rootGroup()->children().at(1); - QCOMPARE(group->uuid().toBase64(), QString("1h4NtL5DK0yVyvaEnN//4A==")); + QCOMPARE(group->uuid(), QUuid::fromRfc4122(QByteArray::fromBase64("1h4NtL5DK0yVyvaEnN//4A=="))); QCOMPARE(group->name(), QString("Windows")); QCOMPARE(group->isExpanded(), false); QCOMPARE(group->children().size(), 1); const Group* child = group->children().first(); - QCOMPARE(child->uuid().toBase64(), QString("HoYE/BjLfUSW257pCHJ/eA==")); + QCOMPARE(child->uuid(), QUuid::fromRfc4122(QByteArray::fromBase64("HoYE/BjLfUSW257pCHJ/eA=="))); QCOMPARE(child->name(), QString("Subsub")); QCOMPARE(child->entries().size(), 1); const Entry* entry = child->entries().first(); - QCOMPARE(entry->uuid().toBase64(), QString("GZpdQvGXOU2kaKRL/IVAGg==")); + QCOMPARE(entry->uuid(), QUuid::fromRfc4122(QByteArray::fromBase64("GZpdQvGXOU2kaKRL/IVAGg=="))); QCOMPARE(entry->title(), QString("Subsub Entry")); } @@ -192,10 +192,10 @@ void TestKeePass2Format::testXmlEntry1() { const Entry* entry = m_xmlDb->rootGroup()->entries().at(0); - QCOMPARE(entry->uuid().toBase64(), QString("+wSUOv6qf0OzW8/ZHAs2sA==")); + QCOMPARE(entry->uuid(), QUuid::fromRfc4122(QByteArray::fromBase64("+wSUOv6qf0OzW8/ZHAs2sA=="))); QCOMPARE(entry->historyItems().size(), 2); QCOMPARE(entry->iconNumber(), 0); - QCOMPARE(entry->iconUuid(), Uuid()); + QCOMPARE(entry->iconUuid(), QUuid()); QVERIFY(!entry->foregroundColor().isValid()); QVERIFY(!entry->backgroundColor().isValid()); QCOMPARE(entry->overrideUrl(), QString("")); @@ -254,9 +254,9 @@ void TestKeePass2Format::testXmlEntry2() { const Entry* entry = m_xmlDb->rootGroup()->entries().at(1); - QCOMPARE(entry->uuid().toBase64(), QString("4jbADG37hkiLh2O0qUdaOQ==")); + QCOMPARE(entry->uuid(), QUuid::fromRfc4122(QByteArray::fromBase64("4jbADG37hkiLh2O0qUdaOQ=="))); QCOMPARE(entry->iconNumber(), 0); - QCOMPARE(entry->iconUuid().toBase64(), QString("++vyI+daLk6omox4a6kQGA==")); + QCOMPARE(entry->iconUuid(), QUuid::fromRfc4122(QByteArray::fromBase64("++vyI+daLk6omox4a6kQGA=="))); // TODO: test entry->icon() QCOMPARE(entry->foregroundColor(), QColor(255, 0, 0)); QCOMPARE(entry->backgroundColor(), QColor(255, 255, 0)); @@ -330,11 +330,11 @@ void TestKeePass2Format::testXmlDeletedObjects() DeletedObject delObj; delObj = objList.takeFirst(); - QCOMPARE(delObj.uuid.toBase64(), QString("5K/bzWCSmkCv5OZxYl4N/w==")); + QCOMPARE(delObj.uuid, QUuid::fromRfc4122(QByteArray::fromBase64("5K/bzWCSmkCv5OZxYl4N/w=="))); QCOMPARE(delObj.deletionTime, Test::datetime(2010, 8, 25, 16, 14, 12)); delObj = objList.takeFirst(); - QCOMPARE(delObj.uuid.toBase64(), QString("80h8uSNWgkKhKCp1TgXF7g==")); + QCOMPARE(delObj.uuid, QUuid::fromRfc4122(QByteArray::fromBase64("80h8uSNWgkKhKCp1TgXF7g=="))); QCOMPARE(delObj.deletionTime, Test::datetime(2010, 8, 25, 16, 14, 14)); QVERIFY(objList.isEmpty()); @@ -424,7 +424,7 @@ void TestKeePass2Format::testXmlInvalidXmlChars() QString().append(QChar(0x31)).append(QChar(0xD801)).append(QChar(0xDC37)).append(QChar(0x32)); auto entry = new Entry(); - entry->setUuid(Uuid::random()); + entry->setUuid(QUuid::createUuid()); entry->setGroup(dbWrite->rootGroup()); entry->attributes()->set("PlainInvalid", strPlainInvalid); entry->attributes()->set("PlainValid", strPlainValid); @@ -577,12 +577,12 @@ void TestKeePass2Format::testDuplicateAttachments() auto entry1 = new Entry(); entry1->setGroup(db->rootGroup()); - entry1->setUuid(Uuid("aaaaaaaaaaaaaaaa")); + entry1->setUuid(QUuid::fromRfc4122(QByteArray::fromHex("aaaaaaaaaaaaaaaa"))); entry1->attachments()->set("a", attachment1); auto entry2 = new Entry(); entry2->setGroup(db->rootGroup()); - entry2->setUuid(Uuid("bbbbbbbbbbbbbbbb")); + entry2->setUuid(QUuid::fromRfc4122(QByteArray::fromHex("bbbbbbbbbbbbbbbb"))); entry2->attachments()->set("b1", attachment1); entry2->beginUpdate(); entry2->attachments()->set("b2", attachment1); @@ -596,7 +596,7 @@ void TestKeePass2Format::testDuplicateAttachments() auto entry3 = new Entry(); entry3->setGroup(db->rootGroup()); - entry3->setUuid(Uuid("cccccccccccccccc")); + entry3->setUuid(QUuid::fromRfc4122(QByteArray::fromHex("cccccccccccccccc"))); entry3->attachments()->set("c1", attachment2); entry3->attachments()->set("c2", attachment2); entry3->attachments()->set("c3", attachment3); diff --git a/tests/TestMerge.cpp b/tests/TestMerge.cpp index e490da8d..278c3001 100644 --- a/tests/TestMerge.cpp +++ b/tests/TestMerge.cpp @@ -216,8 +216,7 @@ void TestMerge::testResolveConflictKeepBoth() QVERIFY2(olderEntry->attributes()->hasKey("merged"), "older entry is marked with an attribute \"merged\""); QCOMPARE(olderEntry->historyItems().isEmpty(), false); - QVERIFY2(olderEntry->uuid().toHex() != updatedEntry->uuid().toHex(), - "KeepBoth should not reuse the UUIDs when cloning."); + QVERIFY2(olderEntry->uuid() != updatedEntry->uuid(), "KeepBoth should not reuse the UUIDs when cloning."); delete dbSource; delete dbDestination; @@ -308,7 +307,7 @@ void TestMerge::testCreateNewGroups() QTest::qSleep(1); Group* group3 = new Group(); group3->setName("group3"); - group3->setUuid(Uuid::random()); + group3->setUuid(QUuid::createUuid()); group3->setParent(dbSource->rootGroup()); dbDestination->merge(dbSource); @@ -331,7 +330,7 @@ void TestMerge::testMoveEntryIntoNewGroup() QTest::qSleep(1); Group* group3 = new Group(); group3->setName("group3"); - group3->setUuid(Uuid::random()); + group3->setUuid(QUuid::createUuid()); group3->setParent(dbSource->rootGroup()); Entry* entry1 = dbSource->rootGroup()->findEntry("entry1"); @@ -367,13 +366,13 @@ void TestMerge::testUpdateEntryDifferentLocation() Group* group3 = new Group(); group3->setName("group3"); - group3->setUuid(Uuid::random()); + group3->setUuid(QUuid::createUuid()); group3->setParent(dbDestination->rootGroup()); Entry* entry1 = dbDestination->rootGroup()->findEntry("entry1"); QVERIFY(entry1 != nullptr); entry1->setGroup(group3); - Uuid uuidBeforeSyncing = entry1->uuid(); + QUuid uuidBeforeSyncing = entry1->uuid(); // Change the entry in the source db. QTest::qSleep(1); @@ -413,7 +412,7 @@ void TestMerge::testUpdateGroup() Group* group2 = dbSource->rootGroup()->findChildByName("group2"); group2->setName("group2 renamed"); group2->setNotes("updated notes"); - Uuid customIconId = Uuid::random(); + QUuid customIconId = QUuid::createUuid(); QImage customIcon; dbSource->metadata()->addCustomIcon(customIconId, customIcon); group2->setIcon(customIconId); @@ -422,7 +421,7 @@ void TestMerge::testUpdateGroup() QVERIFY(entry1 != nullptr); entry1->setGroup(group2); entry1->setTitle("entry1 renamed"); - Uuid uuidBeforeSyncing = entry1->uuid(); + QUuid uuidBeforeSyncing = entry1->uuid(); dbDestination->merge(dbSource); @@ -446,7 +445,7 @@ void TestMerge::testUpdateGroupLocation() { Database* dbDestination = createTestDatabase(); Group* group3 = new Group(); - Uuid group3Uuid = Uuid::random(); + QUuid group3Uuid = QUuid::createUuid(); group3->setUuid(group3Uuid); group3->setName("group3"); group3->setParent(dbDestination->rootGroup()->findChildByName("group1")); @@ -509,7 +508,7 @@ void TestMerge::testMergeCustomIcons() Database* dbDestination = new Database(); Database* dbSource = createTestDatabase(); - Uuid customIconId = Uuid::random(); + QUuid customIconId = QUuid::createUuid(); QImage customIcon; dbSource->metadata()->addCustomIcon(customIconId, customIcon); @@ -566,11 +565,11 @@ Database* TestMerge::createTestDatabase() Group* group1 = new Group(); group1->setName("group1"); - group1->setUuid(Uuid::random()); + group1->setUuid(QUuid::createUuid()); Group* group2 = new Group(); group2->setName("group2"); - group2->setUuid(Uuid::random()); + group2->setUuid(QUuid::createUuid()); Entry* entry1 = new Entry(); Entry* entry2 = new Entry(); @@ -578,14 +577,14 @@ Database* TestMerge::createTestDatabase() // Give Entry 1 a history entry1->beginUpdate(); entry1->setGroup(group1); - entry1->setUuid(Uuid::random()); + entry1->setUuid(QUuid::createUuid()); entry1->setTitle("entry1"); entry1->endUpdate(); // Give Entry 2 a history entry2->beginUpdate(); entry2->setGroup(group1); - entry2->setUuid(Uuid::random()); + entry2->setUuid(QUuid::createUuid()); entry2->setTitle("entry2"); entry2->endUpdate(); diff --git a/tests/TestModified.cpp b/tests/TestModified.cpp index 60ea68e5..66227e3a 100644 --- a/tests/TestModified.cpp +++ b/tests/TestModified.cpp @@ -115,7 +115,7 @@ void TestModified::testGroupSets() QSignalSpy spyModified(db.data(), SIGNAL(modifiedImmediate())); - root->setUuid(Uuid::random()); + root->setUuid(QUuid::createUuid()); QCOMPARE(spyModified.count(), ++spyCount); root->setUuid(root->uuid()); QCOMPARE(spyModified.count(), spyCount); @@ -135,12 +135,13 @@ void TestModified::testGroupSets() root->setIcon(root->iconNumber()); QCOMPARE(spyModified.count(), spyCount); - root->setIcon(Uuid::random()); + root->setIcon(QUuid::createUuid()); QCOMPARE(spyModified.count(), ++spyCount); root->setIcon(root->iconUuid()); QCOMPARE(spyModified.count(), spyCount); - group->setUuid(Uuid::random()); + + group->setUuid(QUuid::createUuid()); QCOMPARE(spyModified.count(), ++spyCount); group->setUuid(group->uuid()); QCOMPARE(spyModified.count(), spyCount); @@ -160,7 +161,7 @@ void TestModified::testGroupSets() group->setIcon(group->iconNumber()); QCOMPARE(spyModified.count(), spyCount); - group->setIcon(Uuid::random()); + group->setIcon(QUuid::createUuid()); QCOMPARE(spyModified.count(), ++spyCount); group->setIcon(group->iconUuid()); QCOMPARE(spyModified.count(), spyCount); @@ -179,7 +180,7 @@ void TestModified::testEntrySets() QSignalSpy spyModified(db.data(), SIGNAL(modifiedImmediate())); - entry->setUuid(Uuid::random()); + entry->setUuid(QUuid::createUuid()); QCOMPARE(spyModified.count(), ++spyCount); entry->setUuid(entry->uuid()); QCOMPARE(spyModified.count(), spyCount); @@ -214,7 +215,7 @@ void TestModified::testEntrySets() entry->setIcon(entry->iconNumber()); QCOMPARE(spyModified.count(), spyCount); - entry->setIcon(Uuid::random()); + entry->setIcon(QUuid::createUuid()); QCOMPARE(spyModified.count(), ++spyCount); entry->setIcon(entry->iconUuid()); QCOMPARE(spyModified.count(), spyCount); @@ -283,7 +284,7 @@ void TestModified::testHistoryItems() { QScopedPointer entry(new Entry()); QDateTime created = entry->timeInfo().creationTime(); - entry->setUuid(Uuid::random()); + entry->setUuid(QUuid::createUuid()); entry->setTitle("a"); entry->setTags("a"); QScopedPointer attributes(new EntryAttributes()); From b4d806ad412b33b9af63f926c06453b63c06a129 Mon Sep 17 00:00:00 2001 From: pasdam <> Date: Fri, 23 Mar 2018 11:18:06 +0100 Subject: [PATCH 046/267] Fixed issues with initial commit --- src/browser/BrowserService.cpp | 30 +++++++++++++----------------- src/core/TimeInfo.cpp | 2 -- src/crypto/kdf/Kdf.h | 2 +- src/format/KdbxReader.cpp | 4 ++-- src/format/KdbxXmlReader.cpp | 4 ++-- src/format/KeePass2.cpp | 4 ++-- src/gui/DatabaseSettingsWidget.cpp | 9 ++++----- src/gui/EditWidgetIcons.h | 2 +- src/gui/EditWidgetProperties.cpp | 2 +- src/gui/IconModels.cpp | 2 +- src/sshagent/SSHAgent.cpp | 12 ++++++------ src/sshagent/SSHAgent.h | 2 +- tests/TestEntry.cpp | 4 ++-- tests/TestEntryModel.cpp | 4 ++-- tests/TestGlobal.h | 1 - tests/TestKeePass2Format.cpp | 6 +++--- tests/gui/TestGuiPixmaps.cpp | 4 ++-- 17 files changed, 43 insertions(+), 51 deletions(-) diff --git a/src/browser/BrowserService.cpp b/src/browser/BrowserService.cpp index b49804ed..c46f6e70 100644 --- a/src/browser/BrowserService.cpp +++ b/src/browser/BrowserService.cpp @@ -17,6 +17,12 @@ * along with this program. If not, see . */ +#include +#include +#include +#include +#include + #include "BrowserService.h" #include "BrowserAccessControlDialog.h" #include "BrowserEntryConfig.h" @@ -26,19 +32,9 @@ #include "core/Group.h" #include "core/Metadata.h" #include "core/PasswordGenerator.h" -#include "core/Uuid.h" #include "gui/MainWindow.h" -#include -#include -#include -#include -// de887cc3-0363-43b8-974b-5911b8816224 -static const unsigned char KEEPASSXCBROWSER_UUID_DATA[] = - {0xde, 0x88, 0x7c, 0xc3, 0x03, 0x63, 0x43, 0xb8, 0x97, 0x4b, 0x59, 0x11, 0xb8, 0x81, 0x62, 0x24}; -static const Uuid KEEPASSXCBROWSER_UUID = - Uuid(QByteArray::fromRawData(reinterpret_cast(KEEPASSXCBROWSER_UUID_DATA), - sizeof(KEEPASSXCBROWSER_UUID_DATA))); +static const QUuid KEEPASSXCBROWSER_UUID = QUuid::fromRfc4122(QByteArray::fromHex("de887cc3036343b8974b5911b8816224")); static const char KEEPASSXCBROWSER_NAME[] = "KeePassXC-Browser Settings"; static const char ASSOCIATE_KEY_PREFIX[] = "Public Key: "; static const char KEEPASSXCBROWSER_GROUP_NAME[] = "KeePassXC-Browser Passwords"; @@ -118,7 +114,7 @@ QString BrowserService::getDatabaseRootUuid() return QString(); } - return rootGroup->uuid().toHex(); + return QString::fromLatin1(rootGroup->uuid().toRfc4122().toHex()); } QString BrowserService::getDatabaseRecycleBinUuid() @@ -132,7 +128,7 @@ QString BrowserService::getDatabaseRecycleBinUuid() if (!recycleBin) { return QString(); } - return recycleBin->uuid().toHex(); + return QString::fromLatin1(recycleBin->uuid().toRfc4122().toHex()); } Entry* BrowserService::getConfigEntry(bool create) @@ -306,7 +302,7 @@ void BrowserService::addEntry(const QString&, } Entry* entry = new Entry(); - entry->setUuid(Uuid::random()); + entry->setUuid(QUuid::createUuid()); entry->setTitle(QUrl(url).host()); entry->setUrl(url); entry->setIcon(KEEPASSXCBROWSER_DEFAULT_ICON); @@ -350,7 +346,7 @@ void BrowserService::updateEntry(const QString& id, return; } - Entry* entry = db->resolveEntry(Uuid::fromHex(uuid)); + Entry* entry = db->resolveEntry(QUuid::fromRfc4122(QByteArray::fromHex(uuid.toLatin1()))); if (!entry) { return; } @@ -631,7 +627,7 @@ QJsonObject BrowserService::prepareEntry(const Entry* entry) res["login"] = entry->resolveMultiplePlaceholders(entry->username()); res["password"] = entry->resolveMultiplePlaceholders(entry->password()); res["name"] = entry->resolveMultiplePlaceholders(entry->title()); - res["uuid"] = entry->resolveMultiplePlaceholders(entry->uuid().toHex()); + res["uuid"] = entry->resolveMultiplePlaceholders(QString::fromLatin1(entry->uuid().toRfc4122().toHex())); if (entry->hasTotp()) { res["totp"] = entry->totp(); @@ -693,7 +689,7 @@ Group* BrowserService::findCreateAddEntryGroup() } Group* group = new Group(); - group->setUuid(Uuid::random()); + group->setUuid(QUuid::createUuid()); group->setName(groupName); group->setIcon(KEEPASSXCBROWSER_DEFAULT_ICON); group->setParent(rootGroup); diff --git a/src/core/TimeInfo.cpp b/src/core/TimeInfo.cpp index ec6ebdee..85c53a56 100644 --- a/src/core/TimeInfo.cpp +++ b/src/core/TimeInfo.cpp @@ -17,8 +17,6 @@ #include "TimeInfo.h" -#include "core/Tools.h" - TimeInfo::TimeInfo() : m_expires(false) , m_usageCount(0) diff --git a/src/crypto/kdf/Kdf.h b/src/crypto/kdf/Kdf.h index 3d62efe8..1dff1106 100644 --- a/src/crypto/kdf/Kdf.h +++ b/src/crypto/kdf/Kdf.h @@ -19,7 +19,7 @@ #define KEEPASSX_KDF_H #include -#include +#include #define KDF_DEFAULT_SEED_SIZE 32 #define KDF_DEFAULT_ROUNDS 1000000ull diff --git a/src/format/KdbxReader.cpp b/src/format/KdbxReader.cpp index e33b6e75..a8127509 100644 --- a/src/format/KdbxReader.cpp +++ b/src/format/KdbxReader.cpp @@ -19,7 +19,7 @@ #include "core/Database.h" #include "core/Endian.h" -#define UUID_LENGHT 16 +#define UUID_LENGTH 16 /** * Read KDBX magic header numbers from a device. @@ -135,7 +135,7 @@ KeePass2::ProtectedStreamAlgo KdbxReader::protectedStreamAlgo() const */ void KdbxReader::setCipher(const QByteArray& data) { - if (data.size() != UUID_LENGHT) { + if (data.size() != UUID_LENGTH) { raiseError(tr("Invalid cipher uuid length: %1 (length=%2)").arg(QString(data)).arg(data.size())); return; } diff --git a/src/format/KdbxXmlReader.cpp b/src/format/KdbxXmlReader.cpp index 62b2e683..d9b6534b 100644 --- a/src/format/KdbxXmlReader.cpp +++ b/src/format/KdbxXmlReader.cpp @@ -28,7 +28,7 @@ #include #include -#define UUID_LENGHT 16 +#define UUID_LENGTH 16 /** * @param version KDBX version @@ -1099,7 +1099,7 @@ QUuid KdbxXmlReader::readUuid() if (uuidBin.isEmpty()) { return QUuid(); } - if (uuidBin.length() != UUID_LENGHT) { + if (uuidBin.length() != UUID_LENGTH) { if (m_strictMode) { raiseError(tr("Invalid uuid value")); } diff --git a/src/format/KeePass2.cpp b/src/format/KeePass2.cpp index 32e56801..dd9ffc0c 100644 --- a/src/format/KeePass2.cpp +++ b/src/format/KeePass2.cpp @@ -21,7 +21,7 @@ #include "crypto/kdf/Argon2Kdf.h" #include -#define UUID_LENGHT 16 +#define UUID_LENGTH 16 const QUuid KeePass2::CIPHER_AES = QUuid::fromRfc4122(QByteArray::fromHex("31c1f2e6bf714350be5805216afc5aff")); const QUuid KeePass2::CIPHER_TWOFISH = QUuid::fromRfc4122(QByteArray::fromHex("ad68f29f576f4bb9a36ad47af965346c")); @@ -76,7 +76,7 @@ QByteArray KeePass2::hmacKey(QByteArray masterSeed, QByteArray transformedMaster QSharedPointer KeePass2::kdfFromParameters(const QVariantMap& p) { QByteArray uuidBytes = p.value(KDFPARAM_UUID).toByteArray(); - if (uuidBytes.size() != UUID_LENGHT) { + if (uuidBytes.size() != UUID_LENGTH) { return {}; } diff --git a/src/gui/DatabaseSettingsWidget.cpp b/src/gui/DatabaseSettingsWidget.cpp index 27973685..8aea4726 100644 --- a/src/gui/DatabaseSettingsWidget.cpp +++ b/src/gui/DatabaseSettingsWidget.cpp @@ -105,9 +105,8 @@ void DatabaseSettingsWidget::load(Database* db) } m_uiEncryption->algorithmComboBox->clear(); - for (auto& cipher : asConst(KeePass2::CIPHERS)) { - m_uiEncryption->algorithmComboBox->addItem(QCoreApplication::translate("KeePass2", cipher.second.toUtf8()), - cipher.first.toByteArray()); + for (auto& cipher: asConst(KeePass2::CIPHERS)) { + m_uiEncryption->algorithmComboBox->addItem(QCoreApplication::translate("KeePass2", cipher.second.toUtf8()), cipher.first); } int cipherIndex = m_uiEncryption->algorithmComboBox->findData(m_db->cipher().toRfc4122()); if (cipherIndex > -1) { @@ -118,12 +117,12 @@ void DatabaseSettingsWidget::load(Database* db) m_uiEncryption->kdfComboBox->blockSignals(true); m_uiEncryption->kdfComboBox->clear(); for (auto& kdf: asConst(KeePass2::KDFS)) { - m_uiEncryption->kdfComboBox->addItem(kdf.second, kdf.first.toRfc4122()); + m_uiEncryption->kdfComboBox->addItem(QCoreApplication::translate("KeePass2", kdf.second.toUtf8()), kdf.first); } m_uiEncryption->kdfComboBox->blockSignals(false); auto kdfUuid = m_db->kdf()->uuid(); - int kdfIndex = m_uiEncryption->kdfComboBox->findData(kdfUuid.toRfc4122()); + int kdfIndex = m_uiEncryption->kdfComboBox->findData(kdfUuid); if (kdfIndex > -1) { m_uiEncryption->kdfComboBox->setCurrentIndex(kdfIndex); kdfChanged(kdfIndex); diff --git a/src/gui/EditWidgetIcons.h b/src/gui/EditWidgetIcons.h index 82c4343e..7a14123b 100644 --- a/src/gui/EditWidgetIcons.h +++ b/src/gui/EditWidgetIcons.h @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include "config-keepassx.h" #include "core/Global.h" diff --git a/src/gui/EditWidgetProperties.cpp b/src/gui/EditWidgetProperties.cpp index 6ec31c89..93e3b0ae 100644 --- a/src/gui/EditWidgetProperties.cpp +++ b/src/gui/EditWidgetProperties.cpp @@ -17,7 +17,7 @@ #include "EditWidgetProperties.h" -#include +#include #include "MessageBox.h" #include "ui_EditWidgetProperties.h" diff --git a/src/gui/IconModels.cpp b/src/gui/IconModels.cpp index 495ba9b1..39732c50 100644 --- a/src/gui/IconModels.cpp +++ b/src/gui/IconModels.cpp @@ -17,7 +17,7 @@ #include "IconModels.h" -#include +#include #include "core/DatabaseIcons.h" diff --git a/src/sshagent/SSHAgent.cpp b/src/sshagent/SSHAgent.cpp index e8639f5d..758c8685 100644 --- a/src/sshagent/SSHAgent.cpp +++ b/src/sshagent/SSHAgent.cpp @@ -234,11 +234,11 @@ bool SSHAgent::removeIdentity(OpenSSHKey& key) return true; } -void SSHAgent::removeIdentityAtLock(const OpenSSHKey& key, const Uuid& uuid) +void SSHAgent::removeIdentityAtLock(const OpenSSHKey& key, const QUuid& uuid) { OpenSSHKey copy = key; copy.clearPrivate(); - m_keys[uuid.toHex()].insert(copy); + m_keys[uuid].insert(copy); } void SSHAgent::databaseModeChanged(DatabaseWidget::Mode mode) @@ -249,17 +249,17 @@ void SSHAgent::databaseModeChanged(DatabaseWidget::Mode mode) return; } - Uuid uuid = widget->database()->uuid(); + const QUuid& uuid = widget->database()->uuid(); - if (mode == DatabaseWidget::LockedMode && m_keys.contains(uuid.toHex())) { + if (mode == DatabaseWidget::LockedMode && m_keys.contains(uuid)) { - QSet keys = m_keys.take(uuid.toHex()); + QSet keys = m_keys.take(uuid); for (OpenSSHKey key : keys) { if (!removeIdentity(key)) { emit error(m_error); } } - } else if (mode == DatabaseWidget::ViewMode && !m_keys.contains(uuid.toHex())) { + } else if (mode == DatabaseWidget::ViewMode && !m_keys.contains(uuid)) { for (Entry* e : widget->database()->rootGroup()->entriesRecursive()) { if (widget->database()->metadata()->recycleBinEnabled() diff --git a/src/sshagent/SSHAgent.h b/src/sshagent/SSHAgent.h index 9bfe5294..ccbfda0c 100644 --- a/src/sshagent/SSHAgent.h +++ b/src/sshagent/SSHAgent.h @@ -71,7 +71,7 @@ private: const quint32 AGENT_COPYDATA_ID = 0x804e50ba; #endif - QMap> m_keys; + QMap> m_keys; QString m_error; }; diff --git a/tests/TestEntry.cpp b/tests/TestEntry.cpp index aa442621..5e5d7bc3 100644 --- a/tests/TestEntry.cpp +++ b/tests/TestEntry.cpp @@ -282,8 +282,8 @@ void TestEntry::testResolveRecursivePlaceholders() auto* entry7 = new Entry(); entry7->setGroup(root); - entry7->setUuid(Uuid::random()); - entry7->setTitle(QString("{REF:T@I:%1} and something else").arg(entry3->uuid().toHex())); + entry7->setUuid(QUuid::createUuid()); + entry7->setTitle(QString("{REF:T@I:%1} and something else").arg(QString(entry3->uuid().toRfc4122().toHex()))); entry7->setUsername(QString("{TITLE}")); entry7->setPassword(QString("PASSWORD")); diff --git a/tests/TestEntryModel.cpp b/tests/TestEntryModel.cpp index dd3a5372..3378a9f9 100644 --- a/tests/TestEntryModel.cpp +++ b/tests/TestEntryModel.cpp @@ -220,11 +220,11 @@ void TestEntryModel::testCustomIconModel() QHash icons; QList iconsOrder; - QUuid iconUuid(QByteArray(16, '2')); + QUuid iconUuid = QUuid::fromRfc4122(QByteArray(16, '2')); icons.insert(iconUuid, QPixmap()); iconsOrder << iconUuid; - QUuid iconUuid2(QByteArray(16, '1')); + QUuid iconUuid2 = QUuid::fromRfc4122(QByteArray(16, '1')); icons.insert(iconUuid2, QPixmap()); iconsOrder << iconUuid2; diff --git a/tests/TestGlobal.h b/tests/TestGlobal.h index ef7472c0..9889a443 100644 --- a/tests/TestGlobal.h +++ b/tests/TestGlobal.h @@ -19,7 +19,6 @@ #define KEEPASSXC_TESTGLOBAL_H #include "core/Group.h" -#include "core/Uuid.h" #include #include diff --git a/tests/TestKeePass2Format.cpp b/tests/TestKeePass2Format.cpp index ce639bde..c5f22ef6 100644 --- a/tests/TestKeePass2Format.cpp +++ b/tests/TestKeePass2Format.cpp @@ -577,12 +577,12 @@ void TestKeePass2Format::testDuplicateAttachments() auto entry1 = new Entry(); entry1->setGroup(db->rootGroup()); - entry1->setUuid(QUuid::fromRfc4122(QByteArray::fromHex("aaaaaaaaaaaaaaaa"))); + entry1->setUuid(QUuid::fromRfc4122("aaaaaaaaaaaaaaaa")); entry1->attachments()->set("a", attachment1); auto entry2 = new Entry(); entry2->setGroup(db->rootGroup()); - entry2->setUuid(QUuid::fromRfc4122(QByteArray::fromHex("bbbbbbbbbbbbbbbb"))); + entry2->setUuid(QUuid::fromRfc4122("bbbbbbbbbbbbbbbb")); entry2->attachments()->set("b1", attachment1); entry2->beginUpdate(); entry2->attachments()->set("b2", attachment1); @@ -596,7 +596,7 @@ void TestKeePass2Format::testDuplicateAttachments() auto entry3 = new Entry(); entry3->setGroup(db->rootGroup()); - entry3->setUuid(QUuid::fromRfc4122(QByteArray::fromHex("cccccccccccccccc"))); + entry3->setUuid(QUuid::fromRfc4122("cccccccccccccccc")); entry3->attachments()->set("c1", attachment2); entry3->attachments()->set("c2", attachment2); entry3->attachments()->set("c3", attachment3); diff --git a/tests/gui/TestGuiPixmaps.cpp b/tests/gui/TestGuiPixmaps.cpp index c71fe51b..c5754ba8 100644 --- a/tests/gui/TestGuiPixmaps.cpp +++ b/tests/gui/TestGuiPixmaps.cpp @@ -73,7 +73,7 @@ void TestGuiPixmaps::testEntryIcons() QCOMPARE(pixmapCached1.cacheKey(), pixmap.cacheKey()); QCOMPARE(pixmapCached2.cacheKey(), pixmap.cacheKey()); - Uuid iconUuid = Uuid::random(); + QUuid iconUuid = QUuid::createUuid(); icon = QImage(2, 1, QImage::Format_RGB32); icon.setPixel(0, 0, qRgb(0, 0, 0)); icon.setPixel(1, 0, qRgb(0, 0, 50)); @@ -116,7 +116,7 @@ void TestGuiPixmaps::testGroupIcons() QCOMPARE(pixmapCached1.cacheKey(), pixmap.cacheKey()); QCOMPARE(pixmapCached2.cacheKey(), pixmap.cacheKey()); - Uuid iconUuid = Uuid::random(); + QUuid iconUuid = QUuid::createUuid(); icon = QImage(2, 1, QImage::Format_RGB32); icon.setPixel(0, 0, qRgb(0, 0, 0)); icon.setPixel(1, 0, qRgb(0, 0, 50)); From c47882b887c38578243f9a7b11534dd465ae22c7 Mon Sep 17 00:00:00 2001 From: Jonathan White Date: Fri, 6 Jul 2018 22:32:44 -0400 Subject: [PATCH 047/267] Fixed regression --- src/sshagent/SSHAgent.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sshagent/SSHAgent.h b/src/sshagent/SSHAgent.h index ccbfda0c..acef6d62 100644 --- a/src/sshagent/SSHAgent.h +++ b/src/sshagent/SSHAgent.h @@ -36,7 +36,7 @@ public: const QString errorString() const; bool isAgentRunning() const; bool addIdentity(OpenSSHKey& key, quint32 lifetime = 0, bool confirm = false); - bool removeIdentity(OpenSSHKey& key) const; + bool removeIdentity(OpenSSHKey& key); void removeIdentityAtLock(const OpenSSHKey& key, const QUuid& uuid); signals: From c5cd4b67836422d39d164f200722f709e9d77693 Mon Sep 17 00:00:00 2001 From: seatedscribe Date: Thu, 15 Feb 2018 22:08:28 +0100 Subject: [PATCH 048/267] Hotfix for #570. Select password locking if an empty password is entered --- src/gui/DatabaseOpenWidget.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/gui/DatabaseOpenWidget.cpp b/src/gui/DatabaseOpenWidget.cpp index 78fa0858..198e2220 100644 --- a/src/gui/DatabaseOpenWidget.cpp +++ b/src/gui/DatabaseOpenWidget.cpp @@ -44,6 +44,7 @@ DatabaseOpenWidget::DatabaseOpenWidget(QWidget* parent) m_ui->setupUi(this); m_ui->messageWidget->setHidden(true); + m_ui->checkPassword->setChecked(true); QFont font = m_ui->labelHeadline->font(); font.setBold(true); @@ -138,7 +139,7 @@ void DatabaseOpenWidget::clearForms() { m_ui->editPassword->clear(); m_ui->comboKeyFile->clear(); - m_ui->checkPassword->setChecked(false); + m_ui->checkPassword->setChecked(true); m_ui->checkKeyFile->setChecked(false); m_ui->checkChallengeResponse->setChecked(false); m_ui->buttonTogglePassword->setChecked(false); From c19df0130b478fd5135fb46a7dede1c047c8dd25 Mon Sep 17 00:00:00 2001 From: Nick Fox Date: Fri, 29 Jun 2018 20:46:33 -0400 Subject: [PATCH 049/267] Allows printing version with -v when an instance is already running Fixes #1362 by checking if the -v argument was used when deciding whether to print the "keepassxc is already running" error message --- src/main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index a3dd14aa..68798876 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -96,7 +96,7 @@ int main(int argc, char** argv) "handle"); parser.addHelpOption(); - parser.addVersionOption(); + QCommandLineOption versionOption = parser.addVersionOption(); parser.addOption(configOption); parser.addOption(keyfileOption); parser.addOption(pwstdinOption); @@ -105,7 +105,7 @@ int main(int argc, char** argv) parser.process(app); const QStringList fileNames = parser.positionalArguments(); - if (app.isAlreadyRunning()) { + if (app.isAlreadyRunning() && !parser.isSet(versionOption)) { if (!fileNames.isEmpty()) { app.sendFileNamesToRunningInstance(fileNames); } From 0142e070cc753c9f8e2f02778c6144f24f76bcee Mon Sep 17 00:00:00 2001 From: Tarquin Winot Date: Mon, 9 Jul 2018 02:31:12 +0200 Subject: [PATCH 050/267] Add tab delimiter in CSV import. (#1842) * Add tab delimiter in CSV import. Closes #1798 * Corrected several code style issues --- src/gui/csvImport/CsvImportWidget.cpp | 54 +++++++++++++++++---------- src/gui/csvImport/CsvImportWidget.h | 1 + 2 files changed, 36 insertions(+), 19 deletions(-) diff --git a/src/gui/csvImport/CsvImportWidget.cpp b/src/gui/csvImport/CsvImportWidget.cpp index f90f4636..303ec3e4 100644 --- a/src/gui/csvImport/CsvImportWidget.cpp +++ b/src/gui/csvImport/CsvImportWidget.cpp @@ -27,8 +27,8 @@ #include "gui/MessageBox.h" #include "gui/MessageWidget.h" -// I wanted to make the CSV import GUI future-proof, so if one day you need entries -// to have a new field, all you have to do is uncomment a row or two here, and the GUI will follow: +// I wanted to make the CSV import GUI future-proof, so if one day you need a new field, +// all you have to do is uncomment a row or two here, and the GUI will follow: // dynamic generation of comboBoxes, labels, placement and so on. Try it for immense fun! const QStringList CsvImportWidget::m_columnHeader = QStringList() << QObject::tr("Group") << QObject::tr("Title") << QObject::tr("Username") << QObject::tr("Password") @@ -56,7 +56,14 @@ CsvImportWidget::CsvImportWidget(QWidget* parent) << ";" << "-" << ":" - << "."); + << "." + << "TAB (\\t)"); + m_fieldSeparatorList = QStringList() << "," + << ";" + << "-" + << ":" + << "." + << "\t"; m_ui->comboBoxTextQualifier->addItems(QStringList() << "\"" << "'" << ":" @@ -115,9 +122,10 @@ CsvImportWidget::CsvImportWidget(QWidget* parent) void CsvImportWidget::comboChanged(int comboId) { QComboBox* currentSender = qobject_cast(m_comboMapper->mapping(comboId)); - if (currentSender->currentIndex() != -1) + if (currentSender->currentIndex() != -1) { // this line is the one that actually updates GUI table m_parserModel->mapColumns(currentSender->currentIndex(), comboId); + } updateTableview(); } @@ -137,7 +145,7 @@ void CsvImportWidget::configParser() m_parserModel->setComment(m_ui->comboBoxComment->currentText().at(0)); m_parserModel->setTextQualifier(m_ui->comboBoxTextQualifier->currentText().at(0)); m_parserModel->setCodec(m_ui->comboBoxCodec->currentText()); - m_parserModel->setFieldSeparator(m_ui->comboBoxFieldSeparator->currentText().at(0)); + m_parserModel->setFieldSeparator(m_fieldSeparatorList.at(m_ui->comboBoxFieldSeparator->currentIndex()).at(0)); } void CsvImportWidget::updateTableview() @@ -145,16 +153,17 @@ void CsvImportWidget::updateTableview() m_ui->tableViewFields->resizeRowsToContents(); m_ui->tableViewFields->resizeColumnsToContents(); - for (int c = 0; c < m_ui->tableViewFields->horizontalHeader()->count(); ++c) + for (int c = 0; c < m_ui->tableViewFields->horizontalHeader()->count(); ++c) { m_ui->tableViewFields->horizontalHeader()->setSectionResizeMode(c, QHeaderView::Stretch); + } } void CsvImportWidget::updatePreview() { - int minSkip = 0; - if (m_ui->checkBoxFieldNames->isChecked()) + if (m_ui->checkBoxFieldNames->isChecked()) { minSkip = 1; + } m_ui->labelSizeRowsCols->setText(m_parserModel->getFileInfo()); m_ui->spinBoxSkip->setRange(minSkip, qMax(minSkip, m_parserModel->rowCount() - 1)); m_ui->spinBoxSkip->setValue(minSkip); @@ -166,8 +175,9 @@ void CsvImportWidget::updatePreview() for (int i = 1; i < m_parserModel->getCsvCols(); ++i) { if (m_ui->checkBoxFieldNames->isChecked()) { columnName = m_parserModel->getCsvTable().at(0).at(i); - if (columnName.isEmpty()) + if (columnName.isEmpty()) { columnName = "<" + tr("Empty fieldname %1").arg(++emptyId) + ">"; + } list << columnName; } else { list << QString(tr("column %1").arg(i)); @@ -177,10 +187,11 @@ void CsvImportWidget::updatePreview() int j = 1; for (QComboBox* b : m_combos) { - if (j < m_parserModel->getCsvCols()) + if (j < m_parserModel->getCsvCols()) { b->setCurrentIndex(j); - else + } else { b->setCurrentIndex(0); + } ++j; } } @@ -205,11 +216,12 @@ void CsvImportWidget::parse() bool good = m_parserModel->parse(); updatePreview(); QApplication::restoreOverrideCursor(); - if (!good) + if (!good) { m_ui->messageWidget->showMessage(tr("Error(s) detected in CSV file!").append("\n").append(formatStatusText()), MessageWidget::Warning); - else + } else { m_ui->messageWidget->setHidden(true); + } QWidget::adjustSize(); } @@ -228,12 +240,12 @@ QString CsvImportWidget::formatStatusText() const void CsvImportWidget::writeDatabase() { - setRootGroup(); for (int r = 0; r < m_parserModel->rowCount(); ++r) { // use validity of second column as a GO/NOGO for all others fields - if (not m_parserModel->data(m_parserModel->index(r, 1)).isValid()) + if (not m_parserModel->data(m_parserModel->index(r, 1)).isValid()) { continue; + } Entry* entry = new Entry(); entry->setUuid(Uuid::random()); entry->setGroup(splitGroups(m_parserModel->data(m_parserModel->index(r, 0)).toString())); @@ -264,12 +276,13 @@ void CsvImportWidget::writeDatabase() KeePass2Writer writer; writer.writeDatabase(&buffer, m_db); - if (writer.hasError()) + if (writer.hasError()) { MessageBox::warning(this, tr("Error"), tr("CSV import: writer has errors:\n%1").arg(writer.errorString()), QMessageBox::Ok, QMessageBox::Ok); + } emit editFinished(true); } @@ -310,13 +323,15 @@ Group* CsvImportWidget::splitGroups(QString label) { // extract group names from nested path provided in "label" Group* current = m_db->rootGroup(); - if (label.isEmpty()) + if (label.isEmpty()) { return current; + } QStringList groupList = label.split("/", QString::SkipEmptyParts); // avoid the creation of a subgroup with the same name as Root - if (m_db->rootGroup()->name() == "Root" && groupList.first() == "Root") + if (m_db->rootGroup()->name() == "Root" && groupList.first() == "Root") { groupList.removeFirst(); + } for (const QString& groupName : groupList) { Group* children = hasChildren(current, groupName); @@ -338,8 +353,9 @@ Group* CsvImportWidget::hasChildren(Group* current, QString groupName) { // returns the group whose name is "groupName" and is child of "current" group for (Group* group : current->children()) { - if (group->name() == groupName) + if (group->name() == groupName) { return group; + } } return nullptr; } diff --git a/src/gui/csvImport/CsvImportWidget.h b/src/gui/csvImport/CsvImportWidget.h index 3823fcb2..721a8988 100644 --- a/src/gui/csvImport/CsvImportWidget.h +++ b/src/gui/csvImport/CsvImportWidget.h @@ -67,6 +67,7 @@ private: Database* m_db; static const QStringList m_columnHeader; + QStringList m_fieldSeparatorList; void configParser(); void updateTableview(); Group* splitGroups(QString label); From 07efabed0347605de0383857c59e02d471e08447 Mon Sep 17 00:00:00 2001 From: Toni Spets Date: Sat, 14 Jul 2018 15:42:28 +0300 Subject: [PATCH 051/267] SSH Agent: Show MD5 fingerprint of keys Fixes #2050 --- src/gui/entry/EditEntryWidget.cpp | 12 ++++++++++-- src/sshagent/OpenSSHKey.cpp | 17 ++++++++++++++--- src/sshagent/OpenSSHKey.h | 2 +- tests/TestOpenSSHKey.cpp | 2 ++ 4 files changed, 27 insertions(+), 6 deletions(-) diff --git a/src/gui/entry/EditEntryWidget.cpp b/src/gui/entry/EditEntryWidget.cpp index db9f5760..c50d1e0a 100644 --- a/src/gui/entry/EditEntryWidget.cpp +++ b/src/gui/entry/EditEntryWidget.cpp @@ -412,7 +412,11 @@ void EditEntryWidget::updateSSHAgentKeyInfo() } if (!key.fingerprint().isEmpty()) { - m_sshAgentUi->fingerprintTextLabel->setText(key.fingerprint()); + m_sshAgentUi->fingerprintTextLabel->setText( + key.fingerprint(QCryptographicHash::Md5) + + "\n" + + key.fingerprint(QCryptographicHash::Sha256) + ); } else { m_sshAgentUi->fingerprintTextLabel->setText(tr("(encrypted)")); } @@ -596,7 +600,11 @@ void EditEntryWidget::decryptPrivateKey() m_sshAgentUi->commentTextLabel->setText(tr("n/a")); } - m_sshAgentUi->fingerprintTextLabel->setText(key.fingerprint()); + m_sshAgentUi->fingerprintTextLabel->setText( + key.fingerprint(QCryptographicHash::Md5) + + "\n" + + key.fingerprint(QCryptographicHash::Sha256) + ); m_sshAgentUi->publicKeyEdit->document()->setPlainText(key.publicKey()); m_sshAgentUi->copyToClipboardButton->setEnabled(true); } diff --git a/src/sshagent/OpenSSHKey.cpp b/src/sshagent/OpenSSHKey.cpp index c75a41a1..c2f41013 100644 --- a/src/sshagent/OpenSSHKey.cpp +++ b/src/sshagent/OpenSSHKey.cpp @@ -90,7 +90,7 @@ int OpenSSHKey::keyLength() const return 0; } -const QString OpenSSHKey::fingerprint() const +const QString OpenSSHKey::fingerprint(QCryptographicHash::Algorithm algo) const { if (m_publicData.isEmpty()) { return {}; @@ -105,9 +105,20 @@ const QString OpenSSHKey::fingerprint() const stream.writeString(ba); } - QByteArray rawHash = QCryptographicHash::hash(publicKey, QCryptographicHash::Sha256); + QByteArray rawHash = QCryptographicHash::hash(publicKey, algo); - return "SHA256:" + QString::fromLatin1(rawHash.toBase64(QByteArray::OmitTrailingEquals)); + if (algo == QCryptographicHash::Md5) { + QString md5Hash = QString::fromLatin1(rawHash.toHex()); + QStringList md5HashParts; + for (int i = 0; i < md5Hash.length(); i += 2) { + md5HashParts.append(md5Hash.mid(i, 2)); + } + return "MD5:" + md5HashParts.join(':'); + } else if (algo == QCryptographicHash::Sha256) { + return "SHA256:" + QString::fromLatin1(rawHash.toBase64(QByteArray::OmitTrailingEquals)); + } + + return "HASH:" + QString::fromLatin1(rawHash.toHex()); } const QString OpenSSHKey::comment() const diff --git a/src/sshagent/OpenSSHKey.h b/src/sshagent/OpenSSHKey.h index cd162796..406f390e 100644 --- a/src/sshagent/OpenSSHKey.h +++ b/src/sshagent/OpenSSHKey.h @@ -37,7 +37,7 @@ public: const QString cipherName() const; const QString type() const; int keyLength() const; - const QString fingerprint() const; + const QString fingerprint(QCryptographicHash::Algorithm algo = QCryptographicHash::Sha256) const; const QString comment() const; const QString publicKey() const; const QString errorString() const; diff --git a/tests/TestOpenSSHKey.cpp b/tests/TestOpenSSHKey.cpp index a8e0c358..74ea665c 100644 --- a/tests/TestOpenSSHKey.cpp +++ b/tests/TestOpenSSHKey.cpp @@ -49,6 +49,7 @@ void TestOpenSSHKey::testParse() QCOMPARE(key.type(), QString("ssh-ed25519")); QCOMPARE(key.comment(), QString("opensshkey-test-parse@keepassxc")); QCOMPARE(key.fingerprint(), QString("SHA256:D1fVmA15YXzaJ5sdO9dXxo5coHL/pnNaIfCvokHzTA4")); + QCOMPARE(key.fingerprint(QCryptographicHash::Md5), QString("MD5:2d:e8:04:09:13:b4:2b:73:5e:87:43:cf:4e:6f:62:f1")); QByteArray publicKey, privateKey; BinaryStream publicStream(&publicKey), privateStream(&privateKey); @@ -173,6 +174,7 @@ void TestOpenSSHKey::testParseRSA() QCOMPARE(key.type(), QString("ssh-rsa")); QCOMPARE(key.comment(), QString("")); QCOMPARE(key.fingerprint(), QString("SHA256:DYdaZciYNxCejr+/8x+OKYxeTU1D5UsuIFUG4PWRFkk")); + QCOMPARE(key.fingerprint(QCryptographicHash::Md5), QString("MD5:c2:26:5b:3d:62:19:56:b0:c3:67:99:7a:a6:4c:66:06")); } void TestOpenSSHKey::testDecryptOpenSSHAES256CBC() From 1d7105958017fae357e0bf39cfa45a1ed0a2bc51 Mon Sep 17 00:00:00 2001 From: Jacob Sachs Date: Wed, 1 Aug 2018 12:46:07 -0400 Subject: [PATCH 052/267] allow 12 hour timeout for lockDatabaseIdle --- src/gui/SettingsWidgetSecurity.ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/SettingsWidgetSecurity.ui b/src/gui/SettingsWidgetSecurity.ui index da3def86..b130bb54 100644 --- a/src/gui/SettingsWidgetSecurity.ui +++ b/src/gui/SettingsWidgetSecurity.ui @@ -92,7 +92,7 @@ 10 - 9999 + 43200 240 From a19895850c4831b1b7a4ac78c0c65066ef00ea3e Mon Sep 17 00:00:00 2001 From: Janek Bevendorff Date: Thu, 23 Aug 2018 19:14:52 +0200 Subject: [PATCH 053/267] Fix --snapcraft flag --- release-tool | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/release-tool b/release-tool index f2a7b811..147b5b8c 100755 --- a/release-tool +++ b/release-tool @@ -710,7 +710,7 @@ build() { ${SRC_DIR}/AppImage-Recipe.sh "$APP_NAME" "$RELEASE_NAME" fi else - if [ BUILD_SNAPCRAFT ]; then + if ${BUILD_SNAPCRAFT}; then logInfo "Building snapcraft docker image..." sudo docker image build -t "$DOCKER_IMAGE" "$(realpath "$SRC_DIR")/ci/snapcraft" From 08a36b4d40475b29752d6788230289c774d76f4b Mon Sep 17 00:00:00 2001 From: TheZ3ro Date: Wed, 29 Aug 2018 17:13:55 +0200 Subject: [PATCH 054/267] Prevent Klipper from storing secrets in clipboard history (#1969) --- src/gui/Clipboard.cpp | 13 ++++++++++--- src/gui/Clipboard.h | 1 + 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/gui/Clipboard.cpp b/src/gui/Clipboard.cpp index b30fd64b..9f4d7ed6 100644 --- a/src/gui/Clipboard.cpp +++ b/src/gui/Clipboard.cpp @@ -1,4 +1,5 @@ /* + * Copyright (C) 2017 KeePassXC Team * Copyright (C) 2012 Felix Geyer * * This program is free software: you can redistribute it and/or modify @@ -19,6 +20,7 @@ #include #include +#include #include #include "core/Config.h" @@ -46,15 +48,20 @@ void Clipboard::setText(const QString& text) { QClipboard* clipboard = QApplication::clipboard(); -#ifdef Q_OS_MAC QMimeData* mime = new QMimeData; +#ifdef Q_OS_MAC mime->setText(text); mime->setData("application/x-nspasteboard-concealed-type", text.toUtf8()); clipboard->setMimeData(mime, QClipboard::Clipboard); #else - clipboard->setText(text, QClipboard::Clipboard); + const QString secretStr = "secret"; + QByteArray secretBa = secretStr.toUtf8(); + mime->setText(text); + mime->setData("x-kde-passwordManagerHint", secretBa); + clipboard->setMimeData(mime, QClipboard::Clipboard); + if (clipboard->supportsSelection()) { - clipboard->setText(text, QClipboard::Selection); + clipboard->setMimeData(mime, QClipboard::Selection); } #endif diff --git a/src/gui/Clipboard.h b/src/gui/Clipboard.h index 60c66c88..062d360f 100644 --- a/src/gui/Clipboard.h +++ b/src/gui/Clipboard.h @@ -1,4 +1,5 @@ /* + * Copyright (C) 2017 KeePassXC Team * Copyright (C) 2012 Felix Geyer * * This program is free software: you can redistribute it and/or modify From 7592f40de2b6fd6b5674aed2f87f971f21d160d8 Mon Sep 17 00:00:00 2001 From: Michal Date: Mon, 3 Sep 2018 00:31:00 +0200 Subject: [PATCH 055/267] Some Python code improvements (#2264) * Usage of "enumerate()" with start parameter * Use the with keyword when dealing with file objects According to: https://docs.python.org/3.6/tutorial/inputoutput.html * String format using ".format()" * Chained comparisons are faster than using the "and" operator --- src/autotype/xcb/keysymmap.py | 50 +++++++++++++++-------------------- 1 file changed, 22 insertions(+), 28 deletions(-) diff --git a/src/autotype/xcb/keysymmap.py b/src/autotype/xcb/keysymmap.py index a3597101..ed45ee7f 100755 --- a/src/autotype/xcb/keysymmap.py +++ b/src/autotype/xcb/keysymmap.py @@ -39,23 +39,21 @@ else: keysymMap = {} -f = open(keysymdef, "r") -for line in f: - match = re.search(r'0x([0-9a-fA-F]+)\s+/\* U\+([0-9a-fA-F]+)', line) - if match: - keysym = int(match.group(1), 16) - unicodeVal = int(match.group(2), 16) +with open(keysymdef, "r") as fid: + for line in fid: + match = re.search(r'0x([0-9a-fA-F]+)\s+/\* U\+([0-9a-fA-F]+)', line) + if match: + keysym = int(match.group(1), 16) + unicodeVal = int(match.group(2), 16) - # ignore 1:1 mappings - if keysym >= 0x0020 and keysym <= 0x007e: - continue - if keysym >= 0x00a0 and keysym <= 0x00ff: - continue - # ignore unicode | 0x01000000 mappings - if keysym >= 0x1000000: - continue + # ignore 1:1 mappings + if 0x0020 <= keysym <= 0x007e or 0x00a0 <= keysym <= 0x00ff: + continue + # ignore unicode | 0x01000000 mappings + elif keysym >= 0x1000000: + continue - keysymMap[unicodeVal] = keysym + keysymMap[unicodeVal] = keysym keysymMap = collections.OrderedDict(sorted(keysymMap.items(), key=lambda t: t[0])) @@ -64,26 +62,24 @@ print("""/* */ """) -print("const int AutoTypePlatformX11::m_unicodeToKeysymLen = " + str(len(keysymMap)) + ";") +print("const int AutoTypePlatformX11::m_unicodeToKeysymLen = {0};".format(len(keysymMap))) print() print("const uint AutoTypePlatformX11::m_unicodeToKeysymKeys[] = {") keys = keysymMap.keys() keyLen = len(keys) -i = 1 -for val in keys: +for idx, val in enumerate(keys, start=1): hexVal = "{0:#0{1}x}".format(val, 6) - if i == keyLen: + if idx == keyLen: print(hexVal) - elif (i % cols) == 0: + elif (idx % cols) == 0: print(hexVal + ",") - elif ((i - 1) % cols) == 0: + elif ((idx - 1) % cols) == 0: print(" " + hexVal + ", ", end="") else: print(hexVal + ", ", end="") - i += 1 print("};") print() @@ -91,17 +87,15 @@ print() print("const uint AutoTypePlatformX11::m_unicodeToKeysymValues[] = {") values = keysymMap.values() valuesLen = len(values) -i = 1 -for val in values: +for idx, val in enumerate(values, start=1): hexVal = "{0:#0{1}x}".format(val, 6) - if i == valuesLen: + if idx == valuesLen: print(hexVal) - elif (i % cols) == 0: + elif (idx % cols) == 0: print(hexVal + ",") - elif ((i - 1) % cols) == 0: + elif ((idx - 1) % cols) == 0: print(" " + hexVal + ", ", end="") else: print(hexVal + ", ", end="") - i += 1 print("};") From 57e60681f26b6be11a1c5891b1885002b86d504d Mon Sep 17 00:00:00 2001 From: varjolintu Date: Fri, 24 Aug 2018 17:08:15 +0300 Subject: [PATCH 056/267] Fix Match URL scheme setting --- src/browser/BrowserService.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/browser/BrowserService.cpp b/src/browser/BrowserService.cpp index 2e8878a3..e2ee6cac 100644 --- a/src/browser/BrowserService.cpp +++ b/src/browser/BrowserService.cpp @@ -395,7 +395,8 @@ QList BrowserService::searchEntries(Database* db, const QString& hostnam QUrl qUrl(url); // Ignore entry if port or scheme defined in the URL doesn't match - if ((entryQUrl.port() > 0 && entryQUrl.port() != qUrl.port()) || entryScheme.compare(qUrl.scheme()) != 0) { + if ((entryQUrl.port() > 0 && entryQUrl.port() != qUrl.port()) || + (BrowserSettings::matchUrlScheme() && entryScheme.compare(qUrl.scheme()) != 0)) { continue; } From 53a17c235589dede8390ff68c37806081aa1ae08 Mon Sep 17 00:00:00 2001 From: Jonathan White Date: Wed, 5 Sep 2018 16:21:59 -0400 Subject: [PATCH 057/267] Reduce use of static vars in browser plugin * Convert BrowserSettings into instanced class * Moved HostInstaller init into class constructor --- src/browser/BrowserAction.cpp | 4 +- src/browser/BrowserOptionDialog.cpp | 76 ++++++------ src/browser/BrowserService.cpp | 28 ++--- src/browser/BrowserService.h | 1 + src/browser/BrowserSettings.cpp | 21 ++-- src/browser/BrowserSettings.h | 178 +++++++++++++++------------- src/browser/HostInstaller.cpp | 74 +++++------- src/browser/HostInstaller.h | 14 +-- src/browser/NativeMessagingHost.cpp | 10 +- src/browser/NativeMessagingHost.h | 2 +- src/gui/MainWindow.cpp | 4 +- 11 files changed, 209 insertions(+), 203 deletions(-) diff --git a/src/browser/BrowserAction.cpp b/src/browser/BrowserAction.cpp index 2fcf4ee8..60cf8506 100644 --- a/src/browser/BrowserAction.cpp +++ b/src/browser/BrowserAction.cpp @@ -270,8 +270,8 @@ QJsonObject BrowserAction::handleGetLogins(const QJsonObject& json, const QStrin QJsonObject BrowserAction::handleGeneratePassword(const QJsonObject& json, const QString& action) { const QString nonce = json.value("nonce").toString(); - const QString password = BrowserSettings::generatePassword(); - const QString bits = QString::number(BrowserSettings::getbits()); // For some reason this always returns 1140 bits? + const QString password = browserSettings()->generatePassword(); + const QString bits = QString::number(browserSettings()->getbits()); // For some reason this always returns 1140 bits? if (nonce.isEmpty() || password.isEmpty()) { return QJsonObject(); diff --git a/src/browser/BrowserOptionDialog.cpp b/src/browser/BrowserOptionDialog.cpp index c5923c5d..e2ed8420 100644 --- a/src/browser/BrowserOptionDialog.cpp +++ b/src/browser/BrowserOptionDialog.cpp @@ -66,36 +66,36 @@ BrowserOptionDialog::~BrowserOptionDialog() void BrowserOptionDialog::loadSettings() { - BrowserSettings settings; - m_ui->enableBrowserSupport->setChecked(settings.isEnabled()); + auto settings = browserSettings(); + m_ui->enableBrowserSupport->setChecked(settings->isEnabled()); - m_ui->showNotification->setChecked(settings.showNotification()); - m_ui->bestMatchOnly->setChecked(settings.bestMatchOnly()); - m_ui->unlockDatabase->setChecked(settings.unlockDatabase()); - m_ui->matchUrlScheme->setChecked(settings.matchUrlScheme()); + m_ui->showNotification->setChecked(settings->showNotification()); + m_ui->bestMatchOnly->setChecked(settings->bestMatchOnly()); + m_ui->unlockDatabase->setChecked(settings->unlockDatabase()); + m_ui->matchUrlScheme->setChecked(settings->matchUrlScheme()); // hide unimplemented options // TODO: fix this m_ui->showNotification->hide(); - if (settings.sortByUsername()) { + if (settings->sortByUsername()) { m_ui->sortByUsername->setChecked(true); } else { m_ui->sortByTitle->setChecked(true); } - m_ui->alwaysAllowAccess->setChecked(settings.alwaysAllowAccess()); - m_ui->alwaysAllowUpdate->setChecked(settings.alwaysAllowUpdate()); - m_ui->searchInAllDatabases->setChecked(settings.searchInAllDatabases()); - m_ui->supportKphFields->setChecked(settings.supportKphFields()); - m_ui->supportBrowserProxy->setChecked(settings.supportBrowserProxy()); - m_ui->useCustomProxy->setChecked(settings.useCustomProxy()); - m_ui->customProxyLocation->setText(settings.customProxyLocation()); - m_ui->updateBinaryPath->setChecked(settings.updateBinaryPath()); - m_ui->chromeSupport->setChecked(settings.chromeSupport()); - m_ui->chromiumSupport->setChecked(settings.chromiumSupport()); - m_ui->firefoxSupport->setChecked(settings.firefoxSupport()); - m_ui->vivaldiSupport->setChecked(settings.vivaldiSupport()); + m_ui->alwaysAllowAccess->setChecked(settings->alwaysAllowAccess()); + m_ui->alwaysAllowUpdate->setChecked(settings->alwaysAllowUpdate()); + m_ui->searchInAllDatabases->setChecked(settings->searchInAllDatabases()); + m_ui->supportKphFields->setChecked(settings->supportKphFields()); + m_ui->supportBrowserProxy->setChecked(settings->supportBrowserProxy()); + m_ui->useCustomProxy->setChecked(settings->useCustomProxy()); + m_ui->customProxyLocation->setText(settings->customProxyLocation()); + m_ui->updateBinaryPath->setChecked(settings->updateBinaryPath()); + m_ui->chromeSupport->setChecked(settings->chromeSupport()); + m_ui->chromiumSupport->setChecked(settings->chromiumSupport()); + m_ui->firefoxSupport->setChecked(settings->firefoxSupport()); + m_ui->vivaldiSupport->setChecked(settings->vivaldiSupport()); #if defined(KEEPASSXC_DIST_APPIMAGE) m_ui->supportBrowserProxy->setChecked(true); @@ -113,28 +113,28 @@ void BrowserOptionDialog::loadSettings() void BrowserOptionDialog::saveSettings() { - BrowserSettings settings; - settings.setEnabled(m_ui->enableBrowserSupport->isChecked()); - settings.setShowNotification(m_ui->showNotification->isChecked()); - settings.setBestMatchOnly(m_ui->bestMatchOnly->isChecked()); - settings.setUnlockDatabase(m_ui->unlockDatabase->isChecked()); - settings.setMatchUrlScheme(m_ui->matchUrlScheme->isChecked()); - settings.setSortByUsername(m_ui->sortByUsername->isChecked()); + auto settings = browserSettings(); + settings->setEnabled(m_ui->enableBrowserSupport->isChecked()); + settings->setShowNotification(m_ui->showNotification->isChecked()); + settings->setBestMatchOnly(m_ui->bestMatchOnly->isChecked()); + settings->setUnlockDatabase(m_ui->unlockDatabase->isChecked()); + settings->setMatchUrlScheme(m_ui->matchUrlScheme->isChecked()); + settings->setSortByUsername(m_ui->sortByUsername->isChecked()); - settings.setSupportBrowserProxy(m_ui->supportBrowserProxy->isChecked()); - settings.setUseCustomProxy(m_ui->useCustomProxy->isChecked()); - settings.setCustomProxyLocation(m_ui->customProxyLocation->text()); + settings->setSupportBrowserProxy(m_ui->supportBrowserProxy->isChecked()); + settings->setUseCustomProxy(m_ui->useCustomProxy->isChecked()); + settings->setCustomProxyLocation(m_ui->customProxyLocation->text()); - settings.setUpdateBinaryPath(m_ui->updateBinaryPath->isChecked()); - settings.setAlwaysAllowAccess(m_ui->alwaysAllowAccess->isChecked()); - settings.setAlwaysAllowUpdate(m_ui->alwaysAllowUpdate->isChecked()); - settings.setSearchInAllDatabases(m_ui->searchInAllDatabases->isChecked()); - settings.setSupportKphFields(m_ui->supportKphFields->isChecked()); + settings->setUpdateBinaryPath(m_ui->updateBinaryPath->isChecked()); + settings->setAlwaysAllowAccess(m_ui->alwaysAllowAccess->isChecked()); + settings->setAlwaysAllowUpdate(m_ui->alwaysAllowUpdate->isChecked()); + settings->setSearchInAllDatabases(m_ui->searchInAllDatabases->isChecked()); + settings->setSupportKphFields(m_ui->supportKphFields->isChecked()); - settings.setChromeSupport(m_ui->chromeSupport->isChecked()); - settings.setChromiumSupport(m_ui->chromiumSupport->isChecked()); - settings.setFirefoxSupport(m_ui->firefoxSupport->isChecked()); - settings.setVivaldiSupport(m_ui->vivaldiSupport->isChecked()); + settings->setChromeSupport(m_ui->chromeSupport->isChecked()); + settings->setChromiumSupport(m_ui->chromiumSupport->isChecked()); + settings->setFirefoxSupport(m_ui->firefoxSupport->isChecked()); + settings->setVivaldiSupport(m_ui->vivaldiSupport->isChecked()); } void BrowserOptionDialog::showProxyLocationFileDialog() diff --git a/src/browser/BrowserService.cpp b/src/browser/BrowserService.cpp index e2ee6cac..bba651d5 100644 --- a/src/browser/BrowserService.cpp +++ b/src/browser/BrowserService.cpp @@ -34,7 +34,6 @@ #include "core/PasswordGenerator.h" #include "gui/MainWindow.h" -static const QUuid KEEPASSXCBROWSER_UUID = QUuid::fromRfc4122(QByteArray::fromHex("de887cc3036343b8974b5911b8816224")); static const char KEEPASSXCBROWSER_NAME[] = "KeePassXC-Browser Settings"; static const char ASSOCIATE_KEY_PREFIX[] = "Public Key: "; static const char KEEPASSXCBROWSER_GROUP_NAME[] = "KeePassXC-Browser Passwords"; @@ -44,6 +43,7 @@ BrowserService::BrowserService(DatabaseTabWidget* parent) : m_dbTabWidget(parent) , m_dialogActive(false) , m_bringToFrontRequested(false) + , m_keepassBrowserUUID(QUuid::fromRfc4122(QByteArray::fromHex("de887cc3036343b8974b5911b8816224"))) { connect(m_dbTabWidget, SIGNAL(databaseLocked(DatabaseWidget*)), this, SLOT(databaseLocked(DatabaseWidget*))); connect(m_dbTabWidget, SIGNAL(databaseUnlocked(DatabaseWidget*)), this, SLOT(databaseUnlocked(DatabaseWidget*))); @@ -65,7 +65,7 @@ bool BrowserService::isDatabaseOpened() const bool BrowserService::openDatabase(bool triggerUnlock) { - if (!BrowserSettings::unlockDatabase()) { + if (!browserSettings()->unlockDatabase()) { return false; } @@ -139,11 +139,11 @@ Entry* BrowserService::getConfigEntry(bool create) return nullptr; } - entry = db->resolveEntry(KEEPASSXCBROWSER_UUID); + entry = db->resolveEntry(m_keepassBrowserUUID); if (!entry && create) { entry = new Entry(); entry->setTitle(QLatin1String(KEEPASSXCBROWSER_NAME)); - entry->setUuid(KEEPASSXCBROWSER_UUID); + entry->setUuid(m_keepassBrowserUUID); entry->setAutoTypeEnabled(false); entry->setGroup(db->rootGroup()); return entry; @@ -243,7 +243,7 @@ QJsonArray BrowserService::findMatchingEntries(const QString& id, return result; } - const bool alwaysAllowAccess = BrowserSettings::alwaysAllowAccess(); + const bool alwaysAllowAccess = browserSettings()->alwaysAllowAccess(); const QString host = QUrl(url).host(); const QString submitHost = QUrl(submitUrl).host(); @@ -358,7 +358,7 @@ void BrowserService::updateEntry(const QString& id, if (username.compare(login, Qt::CaseSensitive) != 0 || entry->password().compare(password, Qt::CaseSensitive) != 0) { int dialogResult = QMessageBox::No; - if (!BrowserSettings::alwaysAllowUpdate()) { + if (!browserSettings()->alwaysAllowUpdate()) { QMessageBox msgBox; msgBox.setWindowTitle(tr("KeePassXC: Update Entry")); msgBox.setText(tr("Do you want to update the information in %1 - %2?").arg(QUrl(url).host()).arg(username)); @@ -371,7 +371,7 @@ void BrowserService::updateEntry(const QString& id, dialogResult = msgBox.exec(); } - if (BrowserSettings::alwaysAllowUpdate() || dialogResult == QMessageBox::Yes) { + if (browserSettings()->alwaysAllowUpdate() || dialogResult == QMessageBox::Yes) { entry->beginUpdate(); entry->setUsername(login); entry->setPassword(password); @@ -396,7 +396,7 @@ QList BrowserService::searchEntries(Database* db, const QString& hostnam // Ignore entry if port or scheme defined in the URL doesn't match if ((entryQUrl.port() > 0 && entryQUrl.port() != qUrl.port()) || - (BrowserSettings::matchUrlScheme() && entryScheme.compare(qUrl.scheme()) != 0)) { + (browserSettings()->matchUrlScheme() && entryScheme.compare(qUrl.scheme()) != 0)) { continue; } @@ -414,14 +414,14 @@ QList BrowserService::searchEntries(const QString& url, const StringPair { // Get the list of databases to search QList databases; - if (BrowserSettings::searchInAllDatabases()) { + if (browserSettings()->searchInAllDatabases()) { const int count = m_dbTabWidget->count(); for (int i = 0; i < count; ++i) { if (DatabaseWidget* dbWidget = qobject_cast(m_dbTabWidget->widget(i))) { if (Database* db = dbWidget->database()) { // Check if database is connected with KeePassXC-Browser for (const StringPair keyPair : keyList) { - Entry* entry = db->resolveEntry(KEEPASSXCBROWSER_UUID); + Entry* entry = db->resolveEntry(m_keepassBrowserUUID); if (entry) { QString key = entry->attributes()->value(QLatin1String(ASSOCIATE_KEY_PREFIX) + keyPair.first); if (!key.isEmpty() && keyPair.second == key) { @@ -564,18 +564,18 @@ QList BrowserService::sortEntries(QList& pwEntries, const QStrin } QList results; - QString field = BrowserSettings::sortByTitle() ? "Title" : "UserName"; + QString field = browserSettings()->sortByTitle() ? "Title" : "UserName"; for (int i = 100; i >= 0; i -= 5) { if (priorities.count(i) > 0) { // Sort same priority entries by Title or UserName auto entries = priorities.values(i); - std::sort(entries.begin(), entries.end(), [&priorities, &field](Entry* left, Entry* right) { + std::sort(entries.begin(), entries.end(), [&field](Entry* left, Entry* right) { return (QString::localeAwareCompare(left->attributes()->value(field), right->attributes()->value(field)) < 0) || ((QString::localeAwareCompare(left->attributes()->value(field), right->attributes()->value(field)) == 0) && (QString::localeAwareCompare(left->attributes()->value("UserName"), right->attributes()->value("UserName")) < 0)); }); results << entries; - if (BrowserSettings::bestMatchOnly() && !pwEntries.isEmpty()) { + if (browserSettings()->bestMatchOnly() && !pwEntries.isEmpty()) { // Early out once we find the highest batch of matches break; } @@ -642,7 +642,7 @@ QJsonObject BrowserService::prepareEntry(const Entry* entry) res["totp"] = entry->totp(); } - if (BrowserSettings::supportKphFields()) { + if (browserSettings()->supportKphFields()) { const EntryAttributes* attr = entry->attributes(); QJsonArray stringFields; for (const QString& key : attr->keys()) { diff --git a/src/browser/BrowserService.h b/src/browser/BrowserService.h index 4c6797d9..10c3a786 100644 --- a/src/browser/BrowserService.h +++ b/src/browser/BrowserService.h @@ -107,6 +107,7 @@ private: DatabaseTabWidget* const m_dbTabWidget; bool m_dialogActive; bool m_bringToFrontRequested; + QUuid m_keepassBrowserUUID; }; #endif // BROWSERSERVICE_H diff --git a/src/browser/BrowserSettings.cpp b/src/browser/BrowserSettings.cpp index 76163b9d..f7abdece 100644 --- a/src/browser/BrowserSettings.cpp +++ b/src/browser/BrowserSettings.cpp @@ -20,9 +20,16 @@ #include "BrowserSettings.h" #include "core/Config.h" -PasswordGenerator BrowserSettings::m_passwordGenerator; -PassphraseGenerator BrowserSettings::m_passPhraseGenerator; -HostInstaller BrowserSettings::m_hostInstaller; +BrowserSettings* BrowserSettings::m_instance(nullptr); + +BrowserSettings* BrowserSettings::instance() +{ + if (!m_instance) { + m_instance = new BrowserSettings(); + } + + return m_instance; +} bool BrowserSettings::isEnabled() { @@ -185,7 +192,7 @@ bool BrowserSettings::chromeSupport() void BrowserSettings::setChromeSupport(bool enabled) { m_hostInstaller.installBrowser( - HostInstaller::SupportedBrowsers::CHROME, enabled, supportBrowserProxy(), customProxyLocation()); + HostInstaller::SupportedBrowsers::CHROME, enabled, supportBrowserProxy(), customProxyLocation()); } bool BrowserSettings::chromiumSupport() @@ -196,7 +203,7 @@ bool BrowserSettings::chromiumSupport() void BrowserSettings::setChromiumSupport(bool enabled) { m_hostInstaller.installBrowser( - HostInstaller::SupportedBrowsers::CHROMIUM, enabled, supportBrowserProxy(), customProxyLocation()); + HostInstaller::SupportedBrowsers::CHROMIUM, enabled, supportBrowserProxy(), customProxyLocation()); } bool BrowserSettings::firefoxSupport() @@ -207,7 +214,7 @@ bool BrowserSettings::firefoxSupport() void BrowserSettings::setFirefoxSupport(bool enabled) { m_hostInstaller.installBrowser( - HostInstaller::SupportedBrowsers::FIREFOX, enabled, supportBrowserProxy(), customProxyLocation()); + HostInstaller::SupportedBrowsers::FIREFOX, enabled, supportBrowserProxy(), customProxyLocation()); } bool BrowserSettings::vivaldiSupport() @@ -218,7 +225,7 @@ bool BrowserSettings::vivaldiSupport() void BrowserSettings::setVivaldiSupport(bool enabled) { m_hostInstaller.installBrowser( - HostInstaller::SupportedBrowsers::VIVALDI, enabled, supportBrowserProxy(), customProxyLocation()); + HostInstaller::SupportedBrowsers::VIVALDI, enabled, supportBrowserProxy(), customProxyLocation()); } bool BrowserSettings::passwordUseNumbers() diff --git a/src/browser/BrowserSettings.h b/src/browser/BrowserSettings.h index 3c79dbed..3e84ba37 100644 --- a/src/browser/BrowserSettings.h +++ b/src/browser/BrowserSettings.h @@ -27,95 +27,105 @@ class BrowserSettings { public: - static bool isEnabled(); - static void setEnabled(bool enabled); + explicit BrowserSettings() = default; + static BrowserSettings* instance(); - static bool showNotification(); // TODO!! - static void setShowNotification(bool showNotification); - static bool bestMatchOnly(); - static void setBestMatchOnly(bool bestMatchOnly); - static bool unlockDatabase(); - static void setUnlockDatabase(bool unlockDatabase); - static bool matchUrlScheme(); - static void setMatchUrlScheme(bool matchUrlScheme); - static bool sortByUsername(); - static void setSortByUsername(bool sortByUsername = true); - static bool sortByTitle(); - static void setSortByTitle(bool sortByUsertitle = true); - static bool alwaysAllowAccess(); - static void setAlwaysAllowAccess(bool alwaysAllowAccess); - static bool alwaysAllowUpdate(); - static void setAlwaysAllowUpdate(bool alwaysAllowUpdate); - static bool searchInAllDatabases(); - static void setSearchInAllDatabases(bool searchInAllDatabases); - static bool supportKphFields(); - static void setSupportKphFields(bool supportKphFields); + bool isEnabled(); + void setEnabled(bool enabled); - static bool supportBrowserProxy(); - static void setSupportBrowserProxy(bool enabled); - static bool useCustomProxy(); - static void setUseCustomProxy(bool enabled); - static QString customProxyLocation(); - static void setCustomProxyLocation(QString location); - static bool updateBinaryPath(); - static void setUpdateBinaryPath(bool enabled); - static bool chromeSupport(); - static void setChromeSupport(bool enabled); - static bool chromiumSupport(); - static void setChromiumSupport(bool enabled); - static bool firefoxSupport(); - static void setFirefoxSupport(bool enabled); - static bool vivaldiSupport(); - static void setVivaldiSupport(bool enabled); + bool showNotification(); // TODO!! + void setShowNotification(bool showNotification); + bool bestMatchOnly(); + void setBestMatchOnly(bool bestMatchOnly); + bool unlockDatabase(); + void setUnlockDatabase(bool unlockDatabase); + bool matchUrlScheme(); + void setMatchUrlScheme(bool matchUrlScheme); + bool sortByUsername(); + void setSortByUsername(bool sortByUsername = true); + bool sortByTitle(); + void setSortByTitle(bool sortByUsertitle = true); + bool alwaysAllowAccess(); + void setAlwaysAllowAccess(bool alwaysAllowAccess); + bool alwaysAllowUpdate(); + void setAlwaysAllowUpdate(bool alwaysAllowUpdate); + bool searchInAllDatabases(); + void setSearchInAllDatabases(bool searchInAllDatabases); + bool supportKphFields(); + void setSupportKphFields(bool supportKphFields); - static bool passwordUseNumbers(); - static void setPasswordUseNumbers(bool useNumbers); - static bool passwordUseLowercase(); - static void setPasswordUseLowercase(bool useLowercase); - static bool passwordUseUppercase(); - static void setPasswordUseUppercase(bool useUppercase); - static bool passwordUseSpecial(); - static void setPasswordUseSpecial(bool useSpecial); - static bool passwordUseBraces(); - static void setPasswordUseBraces(bool useBraces); - static bool passwordUsePunctuation(); - static void setPasswordUsePunctuation(bool usePunctuation); - static bool passwordUseQuotes(); - static void setPasswordUseQuotes(bool useQuotes); - static bool passwordUseDashes(); - static void setPasswordUseDashes(bool useDashes); - static bool passwordUseMath(); - static void setPasswordUseMath(bool useMath); - static bool passwordUseLogograms(); - static void setPasswordUseLogograms(bool useLogograms); - static bool passwordUseEASCII(); - static void setPasswordUseEASCII(bool useEASCII); - static bool advancedMode(); - static void setAdvancedMode(bool advancedMode); - static QString passwordExcludedChars(); - static void setPasswordExcludedChars(QString chars); - static int passPhraseWordCount(); - static void setPassPhraseWordCount(int wordCount); - static QString passPhraseWordSeparator(); - static void setPassPhraseWordSeparator(QString separator); - static int generatorType(); - static void setGeneratorType(int type); - static bool passwordEveryGroup(); - static void setPasswordEveryGroup(bool everyGroup); - static bool passwordExcludeAlike(); - static void setPasswordExcludeAlike(bool excludeAlike); - static int passwordLength(); - static void setPasswordLength(int length); - static PasswordGenerator::CharClasses passwordCharClasses(); - static PasswordGenerator::GeneratorFlags passwordGeneratorFlags(); - static QString generatePassword(); - static int getbits(); - static void updateBinaryPaths(QString customProxyLocation = QString()); + bool supportBrowserProxy(); + void setSupportBrowserProxy(bool enabled); + bool useCustomProxy(); + void setUseCustomProxy(bool enabled); + QString customProxyLocation(); + void setCustomProxyLocation(QString location); + bool updateBinaryPath(); + void setUpdateBinaryPath(bool enabled); + bool chromeSupport(); + void setChromeSupport(bool enabled); + bool chromiumSupport(); + void setChromiumSupport(bool enabled); + bool firefoxSupport(); + void setFirefoxSupport(bool enabled); + bool vivaldiSupport(); + void setVivaldiSupport(bool enabled); + + bool passwordUseNumbers(); + void setPasswordUseNumbers(bool useNumbers); + bool passwordUseLowercase(); + void setPasswordUseLowercase(bool useLowercase); + bool passwordUseUppercase(); + void setPasswordUseUppercase(bool useUppercase); + bool passwordUseSpecial(); + void setPasswordUseSpecial(bool useSpecial); + bool passwordUseBraces(); + void setPasswordUseBraces(bool useBraces); + bool passwordUsePunctuation(); + void setPasswordUsePunctuation(bool usePunctuation); + bool passwordUseQuotes(); + void setPasswordUseQuotes(bool useQuotes); + bool passwordUseDashes(); + void setPasswordUseDashes(bool useDashes); + bool passwordUseMath(); + void setPasswordUseMath(bool useMath); + bool passwordUseLogograms(); + void setPasswordUseLogograms(bool useLogograms); + bool passwordUseEASCII(); + void setPasswordUseEASCII(bool useEASCII); + bool advancedMode(); + void setAdvancedMode(bool advancedMode); + QString passwordExcludedChars(); + void setPasswordExcludedChars(QString chars); + int passPhraseWordCount(); + void setPassPhraseWordCount(int wordCount); + QString passPhraseWordSeparator(); + void setPassPhraseWordSeparator(QString separator); + int generatorType(); + void setGeneratorType(int type); + bool passwordEveryGroup(); + void setPasswordEveryGroup(bool everyGroup); + bool passwordExcludeAlike(); + void setPasswordExcludeAlike(bool excludeAlike); + int passwordLength(); + void setPasswordLength(int length); + PasswordGenerator::CharClasses passwordCharClasses(); + PasswordGenerator::GeneratorFlags passwordGeneratorFlags(); + QString generatePassword(); + int getbits(); + void updateBinaryPaths(QString customProxyLocation = QString()); private: - static PasswordGenerator m_passwordGenerator; - static PassphraseGenerator m_passPhraseGenerator; - static HostInstaller m_hostInstaller; + static BrowserSettings* m_instance; + + PasswordGenerator m_passwordGenerator; + PassphraseGenerator m_passPhraseGenerator; + HostInstaller m_hostInstaller; }; +inline BrowserSettings* browserSettings() +{ + return BrowserSettings::instance(); +} + #endif // BROWSERSETTINGS_H diff --git a/src/browser/HostInstaller.cpp b/src/browser/HostInstaller.cpp index 95d202a2..99d09f4f 100644 --- a/src/browser/HostInstaller.cpp +++ b/src/browser/HostInstaller.cpp @@ -18,6 +18,7 @@ #include "HostInstaller.h" #include "config-keepassx.h" + #include #include #include @@ -27,35 +28,27 @@ #include #include -const QString HostInstaller::HOST_NAME = "org.keepassxc.keepassxc_browser"; -const QStringList HostInstaller::ALLOWED_ORIGINS = QStringList() - << "chrome-extension://iopaggbpplllidnfmcghoonnokmjoicf/" - << "chrome-extension://oboonakemofpalcgghocfoadofidjkkk/"; - -const QStringList HostInstaller::ALLOWED_EXTENSIONS = QStringList() << "keepassxc-browser@keepassxc.org"; - -#if defined(Q_OS_OSX) -const QString HostInstaller::TARGET_DIR_CHROME = "/Library/Application Support/Google/Chrome/NativeMessagingHosts"; -const QString HostInstaller::TARGET_DIR_CHROMIUM = "/Library/Application Support/Chromium/NativeMessagingHosts"; -const QString HostInstaller::TARGET_DIR_FIREFOX = "/Library/Application Support/Mozilla/NativeMessagingHosts"; -const QString HostInstaller::TARGET_DIR_VIVALDI = "/Library/Application Support/Vivaldi/NativeMessagingHosts"; -#elif defined(Q_OS_LINUX) -const QString HostInstaller::TARGET_DIR_CHROME = "/.config/google-chrome/NativeMessagingHosts"; -const QString HostInstaller::TARGET_DIR_CHROMIUM = "/.config/chromium/NativeMessagingHosts"; -const QString HostInstaller::TARGET_DIR_FIREFOX = "/.mozilla/native-messaging-hosts"; -const QString HostInstaller::TARGET_DIR_VIVALDI = "/.config/vivaldi/NativeMessagingHosts"; -#elif defined(Q_OS_WIN) -const QString HostInstaller::TARGET_DIR_CHROME = - "HKEY_CURRENT_USER\\Software\\Google\\Chrome\\NativeMessagingHosts\\" + HostInstaller::HOST_NAME; -const QString HostInstaller::TARGET_DIR_CHROMIUM = - "HKEY_CURRENT_USER\\Software\\Chromium\\NativeMessagingHosts\\" + HostInstaller::HOST_NAME; -const QString HostInstaller::TARGET_DIR_FIREFOX = - "HKEY_CURRENT_USER\\Software\\Mozilla\\NativeMessagingHosts\\" + HostInstaller::HOST_NAME; -const QString HostInstaller::TARGET_DIR_VIVALDI = - "HKEY_CURRENT_USER\\Software\\Vivaldi\\NativeMessagingHosts\\" + HostInstaller::HOST_NAME; -#endif - HostInstaller::HostInstaller() + : HOST_NAME("org.keepassxc.keepassxc_browser") + , ALLOWED_EXTENSIONS(QStringList() << "keepassxc-browser@keepassxc.org") + , ALLOWED_ORIGINS(QStringList() << "chrome-extension://iopaggbpplllidnfmcghoonnokmjoicf/" + << "chrome-extension://oboonakemofpalcgghocfoadofidjkkk/") +#if defined(Q_OS_OSX) + , TARGET_DIR_CHROME("/Library/Application Support/Google/Chrome/NativeMessagingHosts") + , TARGET_DIR_CHROMIUM("/Library/Application Support/Chromium/NativeMessagingHosts") + , TARGET_DIR_FIREFOX("/Library/Application Support/Mozilla/NativeMessagingHosts") + , TARGET_DIR_VIVALDI("/Library/Application Support/Vivaldi/NativeMessagingHosts") +#elif defined(Q_OS_LINUX) + , TARGET_DIR_CHROME("/.config/google-chrome/NativeMessagingHosts") + , TARGET_DIR_CHROMIUM("/.config/chromium/NativeMessagingHosts") + , TARGET_DIR_FIREFOX("/.mozilla/native-messaging-hosts") + , TARGET_DIR_VIVALDI("/.config/vivaldi/NativeMessagingHosts") +#elif defined(Q_OS_WIN) + , TARGET_DIR_CHROME("HKEY_CURRENT_USER\\Software\\Google\\Chrome\\NativeMessagingHosts\\org.keepassxc.keepassxc_browser") + , TARGET_DIR_CHROMIUM("HKEY_CURRENT_USER\\Software\\Chromium\\NativeMessagingHosts\\org.keepassxc.keepassxc_browser") + , TARGET_DIR_FIREFOX("HKEY_CURRENT_USER\\Software\\Mozilla\\NativeMessagingHosts\\org.keepassxc.keepassxc_browser") + , TARGET_DIR_VIVALDI("HKEY_CURRENT_USER\\Software\\Vivaldi\\NativeMessagingHosts\\org.keepassxc.keepassxc_browser") +#endif { } @@ -118,13 +111,13 @@ QString HostInstaller::getTargetPath(SupportedBrowsers browser) const { switch (browser) { case SupportedBrowsers::CHROME: - return HostInstaller::TARGET_DIR_CHROME; + return TARGET_DIR_CHROME; case SupportedBrowsers::CHROMIUM: - return HostInstaller::TARGET_DIR_CHROMIUM; + return TARGET_DIR_CHROMIUM; case SupportedBrowsers::FIREFOX: - return HostInstaller::TARGET_DIR_FIREFOX; + return TARGET_DIR_FIREFOX; case SupportedBrowsers::VIVALDI: - return HostInstaller::TARGET_DIR_VIVALDI; + return TARGET_DIR_VIVALDI; default: return QString(); } @@ -158,12 +151,12 @@ QString HostInstaller::getPath(SupportedBrowsers browser) const userPath = QDir::fromNativeSeparators(QStandardPaths::writableLocation(QStandardPaths::DataLocation)); } - QString winPath = QString("%1/%2_%3.json").arg(userPath, HostInstaller::HOST_NAME, getBrowserName(browser)); + QString winPath = QString("%1/%2_%3.json").arg(userPath, HOST_NAME, getBrowserName(browser)); winPath.replace("/", "\\"); return winPath; #else QString path = getTargetPath(browser); - return QString("%1%2/%3.json").arg(QDir::homePath(), path, HostInstaller::HOST_NAME); + return QString("%1%2/%3.json").arg(QDir::homePath(), path, HOST_NAME); #endif } @@ -207,19 +200,19 @@ QJsonObject HostInstaller::constructFile(SupportedBrowsers browser, const bool& #endif // #ifdef KEEPASSXC_DIST_APPIMAGE QJsonObject script; - script["name"] = HostInstaller::HOST_NAME; + script["name"] = HOST_NAME; script["description"] = "KeePassXC integration with native messaging support"; script["path"] = path; script["type"] = "stdio"; QJsonArray arr; if (browser == SupportedBrowsers::FIREFOX) { - for (const QString extension : HostInstaller::ALLOWED_EXTENSIONS) { + for (const QString& extension : ALLOWED_EXTENSIONS) { arr.append(extension); } script["allowed_extensions"] = arr; } else { - for (const QString origin : HostInstaller::ALLOWED_ORIGINS) { + for (const QString& origin : ALLOWED_ORIGINS) { arr.append(origin); } script["allowed_origins"] = arr; @@ -248,10 +241,5 @@ bool HostInstaller::saveFile(SupportedBrowsers browser, const QJsonObject& scrip } QJsonDocument doc(script); - qint64 bytesWritten = scriptFile.write(doc.toJson()); - if (bytesWritten < 0) { - return false; - } - - return true; + return scriptFile.write(doc.toJson()) >= 0; } diff --git a/src/browser/HostInstaller.h b/src/browser/HostInstaller.h index 2fac0609..3b985c30 100644 --- a/src/browser/HostInstaller.h +++ b/src/browser/HostInstaller.h @@ -55,13 +55,13 @@ private: bool saveFile(SupportedBrowsers browser, const QJsonObject& script); private: - static const QString HOST_NAME; - static const QStringList ALLOWED_EXTENSIONS; - static const QStringList ALLOWED_ORIGINS; - static const QString TARGET_DIR_CHROME; - static const QString TARGET_DIR_CHROMIUM; - static const QString TARGET_DIR_FIREFOX; - static const QString TARGET_DIR_VIVALDI; + const QString HOST_NAME; + const QStringList ALLOWED_EXTENSIONS; + const QStringList ALLOWED_ORIGINS; + const QString TARGET_DIR_CHROME; + const QString TARGET_DIR_CHROMIUM; + const QString TARGET_DIR_FIREFOX; + const QString TARGET_DIR_VIVALDI; }; #endif // HOSTINSTALLER_H diff --git a/src/browser/NativeMessagingHost.cpp b/src/browser/NativeMessagingHost.cpp index 7483b1ca..fc35bbec 100644 --- a/src/browser/NativeMessagingHost.cpp +++ b/src/browser/NativeMessagingHost.cpp @@ -30,14 +30,14 @@ NativeMessagingHost::NativeMessagingHost(DatabaseTabWidget* parent, const bool enabled) : NativeMessagingBase(enabled) , m_mutex(QMutex::Recursive) - , m_browserClients(m_browserService) , m_browserService(parent) + , m_browserClients(m_browserService) { m_localServer.reset(new QLocalServer(this)); m_localServer->setSocketOptions(QLocalServer::UserAccessOption); m_running.store(false); - if (BrowserSettings::isEnabled() && !m_running) { + if (browserSettings()->isEnabled() && !m_running) { run(); } @@ -64,8 +64,8 @@ void NativeMessagingHost::run() } // Update KeePassXC/keepassxc-proxy binary paths to Native Messaging scripts - if (BrowserSettings::updateBinaryPath()) { - BrowserSettings::updateBinaryPaths(BrowserSettings::useCustomProxy() ? BrowserSettings::customProxyLocation() + if (browserSettings()->updateBinaryPath()) { + browserSettings()->updateBinaryPaths(browserSettings()->useCustomProxy() ? browserSettings()->customProxyLocation() : ""); } @@ -75,7 +75,7 @@ void NativeMessagingHost::run() QtConcurrent::run(this, static_cast(&NativeMessagingHost::readNativeMessages)); #endif - if (BrowserSettings::supportBrowserProxy()) { + if (browserSettings()->supportBrowserProxy()) { QString serverPath = getLocalServerPath(); QFile::remove(serverPath); diff --git a/src/browser/NativeMessagingHost.h b/src/browser/NativeMessagingHost.h index d94284ab..fde8f051 100644 --- a/src/browser/NativeMessagingHost.h +++ b/src/browser/NativeMessagingHost.h @@ -58,8 +58,8 @@ private slots: private: QMutex m_mutex; - BrowserClients m_browserClients; BrowserService m_browserService; + BrowserClients m_browserClients; QSharedPointer m_localServer; SocketList m_socketList; }; diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp index ec5bfa5a..d5342cbc 100644 --- a/src/gui/MainWindow.cpp +++ b/src/gui/MainWindow.cpp @@ -66,7 +66,7 @@ class BrowserPlugin : public ISettingsPage public: BrowserPlugin(DatabaseTabWidget* tabWidget) { - m_nativeMessagingHost = QSharedPointer(new NativeMessagingHost(tabWidget, BrowserSettings::isEnabled())); + m_nativeMessagingHost = QSharedPointer(new NativeMessagingHost(tabWidget, browserSettings()->isEnabled())); } ~BrowserPlugin() @@ -103,7 +103,7 @@ public: void saveSettings(QWidget* widget) override { qobject_cast(widget)->saveSettings(); - if (BrowserSettings::isEnabled()) { + if (browserSettings()->isEnabled()) { m_nativeMessagingHost->run(); } else { m_nativeMessagingHost->stop(); From b74fb3e208f470978d013594c91771bc54e8e4fa Mon Sep 17 00:00:00 2001 From: Jonathan White Date: Sat, 8 Sep 2018 17:05:37 -0400 Subject: [PATCH 058/267] Convert private static vars into member vars * CSV Import and Entry Model --- src/gui/csvImport/CsvImportWidget.cpp | 14 +++++--------- src/gui/csvImport/CsvImportWidget.h | 2 +- src/gui/entry/EntryModel.cpp | 8 ++------ src/gui/entry/EntryModel.h | 4 ++-- 4 files changed, 10 insertions(+), 18 deletions(-) diff --git a/src/gui/csvImport/CsvImportWidget.cpp b/src/gui/csvImport/CsvImportWidget.cpp index 2997b4c9..45e0da24 100644 --- a/src/gui/csvImport/CsvImportWidget.cpp +++ b/src/gui/csvImport/CsvImportWidget.cpp @@ -28,16 +28,8 @@ #include "gui/MessageWidget.h" // I wanted to make the CSV import GUI future-proof, so if one day you need a new field, -// all you have to do is uncomment a row or two here, and the GUI will follow: +// all you have to do is add a field to m_columnHeader, and the GUI will follow: // dynamic generation of comboBoxes, labels, placement and so on. Try it for immense fun! -const QStringList CsvImportWidget::m_columnHeader = - QStringList() << QObject::tr("Group") << QObject::tr("Title") << QObject::tr("Username") << QObject::tr("Password") - << QObject::tr("URL") << QObject::tr("Notes") << QObject::tr("Last Modified") - << QObject::tr("Created") - // << QObject::tr("Future field1") - // << QObject::tr("Future field2") - // << QObject::tr("Future field3") - ; CsvImportWidget::CsvImportWidget(QWidget* parent) : QWidget(parent) @@ -45,6 +37,10 @@ CsvImportWidget::CsvImportWidget(QWidget* parent) , m_parserModel(new CsvParserModel(this)) , m_comboModel(new QStringListModel(this)) , m_comboMapper(new QSignalMapper(this)) + , m_columnHeader(QStringList() << QObject::tr("Group") << QObject::tr("Title") << QObject::tr("Username") + << QObject::tr("Password") << QObject::tr("URL") << QObject::tr("Notes") + << QObject::tr("Last Modified") << QObject::tr("Created") + /* << QObject::tr("Future field1") */ ) { m_ui->setupUi(this); diff --git a/src/gui/csvImport/CsvImportWidget.h b/src/gui/csvImport/CsvImportWidget.h index 721a8988..2a68c95e 100644 --- a/src/gui/csvImport/CsvImportWidget.h +++ b/src/gui/csvImport/CsvImportWidget.h @@ -66,7 +66,7 @@ private: QList m_combos; Database* m_db; - static const QStringList m_columnHeader; + const QStringList m_columnHeader; QStringList m_fieldSeparatorList; void configParser(); void updateTableview(); diff --git a/src/gui/entry/EntryModel.cpp b/src/gui/entry/EntryModel.cpp index aa61a406..d3859e49 100644 --- a/src/gui/entry/EntryModel.cpp +++ b/src/gui/entry/EntryModel.cpp @@ -30,17 +30,13 @@ #include "core/Group.h" #include "core/Metadata.h" -// String being displayed when hiding content -const QString EntryModel::HiddenContentDisplay(QString("\u25cf").repeated(6)); - -// Format used to display dates -const Qt::DateFormat EntryModel::DateFormat = Qt::DefaultLocaleShortDate; - EntryModel::EntryModel(QObject* parent) : QAbstractTableModel(parent) , m_group(nullptr) , m_hideUsernames(false) , m_hidePasswords(true) + , HiddenContentDisplay(QString("\u25cf").repeated(6)) + , DateFormat(Qt::DefaultLocaleShortDate) { } diff --git a/src/gui/entry/EntryModel.h b/src/gui/entry/EntryModel.h index 4fc76504..1965066a 100644 --- a/src/gui/entry/EntryModel.h +++ b/src/gui/entry/EntryModel.h @@ -100,8 +100,8 @@ private: QPixmap m_paperClipPixmap; - static const QString HiddenContentDisplay; - static const Qt::DateFormat DateFormat; + const QString HiddenContentDisplay; + const Qt::DateFormat DateFormat; }; #endif // KEEPASSX_ENTRYMODEL_H From 1dc9f10c7f0b95dbd8eb37865dec89fcc4a52931 Mon Sep 17 00:00:00 2001 From: Jonathan White Date: Wed, 5 Sep 2018 16:20:57 -0400 Subject: [PATCH 059/267] Complete refactor of TOTP integration * Eliminate TOTP logic from GUI elements * Consolidate TOTP functionality under the Totp namespace * Eliminate guessing about state and encoders * Increased test cases * Add entry view column for TOTP [#2132] * General code cleanup, reduction of unnecessary steps, separation of concerns * Rename SetupTotpDialog to TotpSetupDialog for consistency --- src/CMakeLists.txt | 2 +- src/core/Entry.cpp | 92 ++----- src/core/Entry.h | 12 +- src/gui/DatabaseWidget.cpp | 20 +- src/gui/DetailsWidget.cpp | 31 +-- src/gui/DetailsWidget.h | 7 +- src/gui/SetupTotpDialog.cpp | 126 ---------- src/gui/SetupTotpDialog.ui | 167 ------------- src/gui/TotpDialog.cpp | 42 ++-- src/gui/TotpDialog.h | 19 +- src/gui/TotpSetupDialog.cpp | 83 +++++++ .../{SetupTotpDialog.h => TotpSetupDialog.h} | 27 +-- src/gui/TotpSetupDialog.ui | 182 ++++++++++++++ src/gui/entry/EntryModel.cpp | 24 +- src/gui/entry/EntryModel.h | 3 +- src/totp/totp.cpp | 227 +++++++++--------- src/totp/totp.h | 71 +++--- tests/TestEntryModel.cpp | 8 +- tests/TestTotp.cpp | 151 +++++------- tests/TestTotp.h | 3 - tests/gui/TestGui.cpp | 4 +- 21 files changed, 585 insertions(+), 716 deletions(-) delete mode 100644 src/gui/SetupTotpDialog.cpp delete mode 100644 src/gui/SetupTotpDialog.ui create mode 100644 src/gui/TotpSetupDialog.cpp rename src/gui/{SetupTotpDialog.h => TotpSetupDialog.h} (68%) create mode 100644 src/gui/TotpSetupDialog.ui diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f1389c55..ea09d43b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -128,7 +128,7 @@ set(keepassx_SOURCES gui/SettingsWidget.cpp gui/SearchWidget.cpp gui/SortFilterHideProxyModel.cpp - gui/SetupTotpDialog.cpp + gui/TotpSetupDialog.cpp gui/TotpDialog.cpp gui/UnlockDatabaseWidget.cpp gui/UnlockDatabaseDialog.cpp diff --git a/src/core/Entry.cpp b/src/core/Entry.cpp index 598ea849..4233d89e 100644 --- a/src/core/Entry.cpp +++ b/src/core/Entry.cpp @@ -45,8 +45,6 @@ Entry::Entry() m_data.iconNumber = DefaultIconNumber; m_data.autoTypeEnabled = true; m_data.autoTypeObfuscation = 0; - m_data.totpStep = Totp::defaultStep; - m_data.totpDigits = Totp::defaultDigits; connect(m_attributes, SIGNAL(modified()), SLOT(updateTotp())); connect(m_attributes, SIGNAL(modified()), this, SIGNAL(modified())); @@ -347,74 +345,45 @@ const CustomData* Entry::customData() const bool Entry::hasTotp() const { - return m_attributes->hasKey("TOTP Seed") || m_attributes->hasKey("otp"); + return !m_data.totpSettings.isNull(); } QString Entry::totp() const { if (hasTotp()) { - QString seed = totpSeed(); - quint64 time = QDateTime::currentDateTime().toTime_t(); - QString output = Totp::generateTotp(seed.toLatin1(), time, m_data.totpDigits, m_data.totpStep); - - return QString(output); + return Totp::generateTotp(m_data.totpSettings); } return {}; } -void Entry::setTotp(const QString& seed, quint8& step, quint8& digits) +void Entry::setTotp(QSharedPointer settings) { beginUpdate(); - if (step == 0) { - step = Totp::defaultStep; - } + m_data.totpSettings = settings; - if (digits == 0) { - digits = Totp::defaultDigits; - } - QString data; - - const Totp::Encoder& enc = Totp::encoders.value(digits, Totp::defaultEncoder); - - if (m_attributes->hasKey("otp")) { - data = QString("key=%1&step=%2&size=%3").arg(seed).arg(step).arg(enc.digits == 0 ? digits : enc.digits); - if (!enc.name.isEmpty()) { - data.append("&enocder=").append(enc.name); - } - m_attributes->set("otp", data, true); + auto text = Totp::writeSettings(m_data.totpSettings); + if (m_attributes->hasKey(Totp::ATTRIBUTE_OTP)) { + m_attributes->set(Totp::ATTRIBUTE_OTP, text, true); } else { - m_attributes->set("TOTP Seed", seed, true); - if (!enc.shortName.isEmpty()) { - data = QString("%1;%2").arg(step).arg(enc.shortName); - } else { - data = QString("%1;%2").arg(step).arg(digits); - } - m_attributes->set("TOTP Settings", data); + m_attributes->set(Totp::ATTRIBUTE_SEED, m_data.totpSettings->key, true); + m_attributes->set(Totp::ATTRIBUTE_SETTINGS, text); } endUpdate(); } -QString Entry::totpSeed() const +void Entry::updateTotp() { - QString secret = ""; - - if (m_attributes->hasKey("otp")) { - secret = m_attributes->value("otp"); - } else if (m_attributes->hasKey("TOTP Seed")) { - secret = m_attributes->value("TOTP Seed"); + if (m_attributes->contains(Totp::ATTRIBUTE_SETTINGS)) { + m_data.totpSettings = Totp::parseSettings(m_attributes->value(Totp::ATTRIBUTE_SETTINGS), + 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)); } - - return Totp::parseOtpString(secret, m_data.totpDigits, m_data.totpStep); } -quint8 Entry::totpStep() const +QSharedPointer Entry::totpSettings() const { - return m_data.totpStep; -} - -quint8 Entry::totpDigits() const -{ - return m_data.totpDigits; + return m_data.totpSettings; } void Entry::setUuid(const QUuid& uuid) @@ -725,33 +694,6 @@ void Entry::updateModifiedSinceBegin() m_modifiedSinceBegin = true; } -/** - * Update TOTP data whenever entry attributes have changed. - */ -void Entry::updateTotp() -{ - m_data.totpDigits = Totp::defaultDigits; - m_data.totpStep = Totp::defaultStep; - - if (!m_attributes->hasKey("TOTP Settings")) { - return; - } - - // this regex must be kept in sync with the set of allowed short names Totp::shortNameToEncoder - QRegularExpression rx(QString("(\\d+);((?:\\d+)|S)")); - QRegularExpressionMatch m = rx.match(m_attributes->value("TOTP Settings")); - if (!m.hasMatch()) { - return; - } - - m_data.totpStep = static_cast(m.captured(1).toUInt()); - if (Totp::shortNameToEncoder.contains(m.captured(2))) { - m_data.totpDigits = Totp::shortNameToEncoder[m.captured(2)]; - } else { - m_data.totpDigits = static_cast(m.captured(2).toUInt()); - } -} - QString Entry::resolveMultiplePlaceholdersRecursive(const QString& str, int maxDepth) const { if (maxDepth <= 0) { diff --git a/src/core/Entry.h b/src/core/Entry.h index de6a4b39..aa2426c5 100644 --- a/src/core/Entry.h +++ b/src/core/Entry.h @@ -36,6 +36,9 @@ class Database; class Group; +namespace Totp { + struct Settings; +} enum class EntryReferenceType { @@ -61,8 +64,7 @@ struct EntryData int autoTypeObfuscation; QString defaultAutoTypeSequence; TimeInfo timeInfo; - mutable quint8 totpDigits; - mutable quint8 totpStep; + QSharedPointer totpSettings; }; class Entry : public QObject @@ -98,9 +100,7 @@ public: QString password() const; QString notes() const; QString totp() const; - QString totpSeed() const; - quint8 totpDigits() const; - quint8 totpStep() const; + QSharedPointer totpSettings() const; bool hasTotp() const; bool isExpired() const; @@ -135,7 +135,7 @@ public: void setNotes(const QString& notes); void setExpires(const bool& value); void setExpiryTime(const QDateTime& dateTime); - void setTotp(const QString& seed, quint8& step, quint8& digits); + void setTotp(QSharedPointer settings); QList historyItems(); const QList& historyItems() const; diff --git a/src/gui/DatabaseWidget.cpp b/src/gui/DatabaseWidget.cpp index fde356fd..c96c9000 100644 --- a/src/gui/DatabaseWidget.cpp +++ b/src/gui/DatabaseWidget.cpp @@ -47,7 +47,7 @@ #include "gui/DetailsWidget.h" #include "gui/KeePass1OpenWidget.h" #include "gui/MessageBox.h" -#include "gui/SetupTotpDialog.h" +#include "gui/TotpSetupDialog.h" #include "gui/TotpDialog.h" #include "gui/UnlockDatabaseDialog.h" #include "gui/UnlockDatabaseWidget.h" @@ -444,15 +444,8 @@ void DatabaseWidget::setupTotp() return; } - auto setupTotpDialog = new SetupTotpDialog(this, currentEntry); - if (currentEntry->hasTotp()) { - setupTotpDialog->setSeed(currentEntry->totpSeed()); - setupTotpDialog->setStep(currentEntry->totpStep()); - setupTotpDialog->setDigits(currentEntry->totpDigits()); - // now that all settings are set, decide whether it's default, steam or custom - setupTotpDialog->setSettings(currentEntry->totpDigits()); - } - + auto setupTotpDialog = new TotpSetupDialog(this, currentEntry); + connect(setupTotpDialog, SIGNAL(totpUpdated()), SIGNAL(entrySelectionChanged())); setupTotpDialog->open(); } @@ -938,6 +931,13 @@ void DatabaseWidget::entryActivationSignalReceived(Entry* entry, EntryModel::Mod openUrlForEntry(entry); } break; + case EntryModel::Totp: + if (entry->hasTotp()) { + setClipboardTextAndMinimize(entry->totp()); + } else { + setupTotp(); + } + break; // TODO: switch to 'Notes' tab in details view/pane // case EntryModel::Notes: // break; diff --git a/src/gui/DetailsWidget.cpp b/src/gui/DetailsWidget.cpp index 70286b9d..ff886117 100644 --- a/src/gui/DetailsWidget.cpp +++ b/src/gui/DetailsWidget.cpp @@ -39,8 +39,6 @@ DetailsWidget::DetailsWidget(QWidget* parent) , m_locked(false) , m_currentEntry(nullptr) , m_currentGroup(nullptr) - , m_step(0) - , m_totpTimer(nullptr) , m_selectedTabEntry(0) , m_selectedTabGroup(0) { @@ -56,6 +54,7 @@ DetailsWidget::DetailsWidget(QWidget* parent) connect(m_ui->entryTotpButton, SIGNAL(toggled(bool)), m_ui->entryTotpWidget, SLOT(setVisible(bool))); connect(m_ui->entryCloseButton, SIGNAL(toggled(bool)), SLOT(hide())); connect(m_ui->entryTabWidget, SIGNAL(tabBarClicked(int)), SLOT(updateTabIndexes()), Qt::QueuedConnection); + connect(&m_totpTimer, SIGNAL(timeout()), this, SLOT(updateTotpLabel())); // Group m_ui->groupCloseButton->setIcon(filePath()->icon("actions", "dialog-close")); @@ -65,7 +64,6 @@ DetailsWidget::DetailsWidget(QWidget* parent) DetailsWidget::~DetailsWidget() { - deleteTotpTimer(); } void DetailsWidget::setEntry(Entry* selectedEntry) @@ -146,16 +144,11 @@ void DetailsWidget::updateEntryTotp() m_ui->entryTotpButton->setChecked(false); if (hasTotp) { - deleteTotpTimer(); - m_totpTimer = new QTimer(m_currentEntry); - connect(m_totpTimer, SIGNAL(timeout()), this, SLOT(updateTotpLabel())); - m_totpTimer->start(1000); - - m_step = m_currentEntry->totpStep(); + m_totpTimer.start(1000); updateTotpLabel(); } else { m_ui->entryTotpLabel->clear(); - stopTotpTimer(); + m_totpTimer.stop(); } } @@ -274,30 +267,16 @@ void DetailsWidget::updateGroupNotesTab() m_ui->groupNotesEdit->setText(notes); } -void DetailsWidget::stopTotpTimer() -{ - if (m_totpTimer) { - m_totpTimer->stop(); - } -} - -void DetailsWidget::deleteTotpTimer() -{ - if (m_totpTimer) { - delete m_totpTimer; - } -} - void DetailsWidget::updateTotpLabel() { - if (!m_locked && m_currentEntry) { + if (!m_locked && m_currentEntry && m_currentEntry->hasTotp()) { const QString totpCode = m_currentEntry->totp(); const QString firstHalf = totpCode.left(totpCode.size() / 2); const QString secondHalf = totpCode.mid(totpCode.size() / 2); m_ui->entryTotpLabel->setText(firstHalf + " " + secondHalf); } else { m_ui->entryTotpLabel->clear(); - stopTotpTimer(); + m_totpTimer.stop(); } } diff --git a/src/gui/DetailsWidget.h b/src/gui/DetailsWidget.h index 3a4c277d..ba42e527 100644 --- a/src/gui/DetailsWidget.h +++ b/src/gui/DetailsWidget.h @@ -33,7 +33,7 @@ class DetailsWidget : public QWidget public: explicit DetailsWidget(QWidget* parent = nullptr); - ~DetailsWidget(); + ~DetailsWidget() override; public slots: void setEntry(Entry* selectedEntry); @@ -56,8 +56,6 @@ private slots: void updateGroupGeneralTab(); void updateGroupNotesTab(); - void stopTotpTimer(); - void deleteTotpTimer(); void updateTotpLabel(); void updateTabIndexes(); @@ -71,8 +69,7 @@ private: bool m_locked; Entry* m_currentEntry; Group* m_currentGroup; - quint8 m_step; - QPointer m_totpTimer; + QTimer m_totpTimer; quint8 m_selectedTabEntry; quint8 m_selectedTabGroup; }; diff --git a/src/gui/SetupTotpDialog.cpp b/src/gui/SetupTotpDialog.cpp deleted file mode 100644 index ef7ee9e7..00000000 --- a/src/gui/SetupTotpDialog.cpp +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (C) 2017 Weslly Honorato <weslly@protonmail.com> - * Copyright (C) 2017 KeePassXC Team - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 or (at your option) - * version 3 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "SetupTotpDialog.h" -#include "totp/totp.h" -#include "ui_SetupTotpDialog.h" - -SetupTotpDialog::SetupTotpDialog(DatabaseWidget* parent, Entry* entry) - : QDialog(parent) - , m_ui(new Ui::SetupTotpDialog()) -{ - m_entry = entry; - m_parent = parent; - - m_ui->setupUi(this); - setAttribute(Qt::WA_DeleteOnClose); - - this->setFixedSize(this->sizeHint()); - - connect(m_ui->buttonBox, SIGNAL(rejected()), SLOT(close())); - connect(m_ui->buttonBox, SIGNAL(accepted()), SLOT(setupTotp())); - connect(m_ui->radioDefault, SIGNAL(toggled(bool)), SLOT(toggleDefault(bool))); - connect(m_ui->radioSteam, SIGNAL(toggled(bool)), SLOT(toggleSteam(bool))); - connect(m_ui->radioCustom, SIGNAL(toggled(bool)), SLOT(toggleCustom(bool))); -} - -void SetupTotpDialog::setupTotp() -{ - quint8 digits; - - if (m_ui->radioSteam->isChecked()) { - digits = Totp::ENCODER_STEAM; - } else if (m_ui->radio8Digits->isChecked()) { - digits = 8; - } else { - digits = 6; - } - - quint8 step = m_ui->stepSpinBox->value(); - QString seed = Totp::parseOtpString(m_ui->seedEdit->text(), digits, step); - m_entry->setTotp(seed, step, digits); - emit m_parent->entrySelectionChanged(); - close(); -} - -void SetupTotpDialog::toggleDefault(bool status) -{ - if (status) { - setStep(Totp::defaultStep); - setDigits(Totp::defaultDigits); - } -} - -void SetupTotpDialog::toggleSteam(bool status) -{ - if (status) { - setStep(Totp::defaultStep); - setDigits(Totp::ENCODER_STEAM); - } -} - -void SetupTotpDialog::toggleCustom(bool status) -{ - m_ui->digitsLabel->setEnabled(status); - m_ui->radio6Digits->setEnabled(status); - m_ui->radio8Digits->setEnabled(status); - - m_ui->stepLabel->setEnabled(status); - m_ui->stepSpinBox->setEnabled(status); -} - -void SetupTotpDialog::setSeed(QString value) -{ - m_ui->seedEdit->setText(value); -} - -void SetupTotpDialog::setSettings(quint8 digits) -{ - quint8 step = m_ui->stepSpinBox->value(); - - bool isDefault = ((step == Totp::defaultStep) && (digits == Totp::defaultDigits)); - bool isSteam = (digits == Totp::ENCODER_STEAM); - - if (isSteam) { - m_ui->radioSteam->setChecked(true); - } else if (isDefault) { - m_ui->radioDefault->setChecked(true); - } else { - m_ui->radioCustom->setChecked(true); - } -} - -void SetupTotpDialog::setStep(quint8 step) -{ - m_ui->stepSpinBox->setValue(step); -} - -void SetupTotpDialog::setDigits(quint8 digits) -{ - if (digits == 8) { - m_ui->radio8Digits->setChecked(true); - m_ui->radio6Digits->setChecked(false); - } else { - m_ui->radio6Digits->setChecked(true); - m_ui->radio8Digits->setChecked(false); - } -} - -SetupTotpDialog::~SetupTotpDialog() -{ -} diff --git a/src/gui/SetupTotpDialog.ui b/src/gui/SetupTotpDialog.ui deleted file mode 100644 index 327ca6d0..00000000 --- a/src/gui/SetupTotpDialog.ui +++ /dev/null @@ -1,167 +0,0 @@ - - - SetupTotpDialog - - - - 0 - 0 - 282 - 364 - - - - Setup TOTP - - - - - - - - Key: - - - - - - - - - - - - - - Default RFC 6238 token settings - - - settingsButtonGroup - - - - - - - Steam token settings - - - settingsButtonGroup - - - - - - - Use custom settings - - - settingsButtonGroup - - - - - - - - - Note: Change these settings only if you know what you are doing. - - - true - - - - - - - QFormLayout::ExpandingFieldsGrow - - - QFormLayout::DontWrapRows - - - Qt::AlignRight|Qt::AlignTop|Qt::AlignTrailing - - - - - false - - - Time step: - - - - - - - false - - - 8 digits - - - - - - - false - - - 6 digits - - - true - - - - - - - false - - - Code size: - - - - - - - false - - - sec - - - 1 - - - 60 - - - 30 - - - - - - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - - - - diff --git a/src/gui/TotpDialog.cpp b/src/gui/TotpDialog.cpp index 75cf6a48..c2de9adb 100644 --- a/src/gui/TotpDialog.cpp +++ b/src/gui/TotpDialog.cpp @@ -22,21 +22,25 @@ #include "core/Config.h" #include "gui/Clipboard.h" -TotpDialog::TotpDialog(DatabaseWidget* parent, Entry* entry) +TotpDialog::TotpDialog(QWidget* parent, Entry* entry) : QDialog(parent) , m_ui(new Ui::TotpDialog()) - , m_totpUpdateTimer(new QTimer(entry)) , m_entry(entry) { + if (!m_entry->hasTotp()) { + close(); + return; + } + m_ui->setupUi(this); - m_step = m_entry->totpStep(); - uCounter = resetCounter(); + m_step = m_entry->totpSettings()->step; + resetCounter(); updateProgressBar(); - connect(m_totpUpdateTimer, SIGNAL(timeout()), this, SLOT(updateProgressBar())); - connect(m_totpUpdateTimer, SIGNAL(timeout()), this, SLOT(updateSeconds())); - m_totpUpdateTimer->start(m_step * 10); + connect(&m_totpUpdateTimer, SIGNAL(timeout()), this, SLOT(updateProgressBar())); + connect(&m_totpUpdateTimer, SIGNAL(timeout()), this, SLOT(updateSeconds())); + m_totpUpdateTimer.start(m_step * 10); updateTotp(); setAttribute(Qt::WA_DeleteOnClose); @@ -47,6 +51,10 @@ TotpDialog::TotpDialog(DatabaseWidget* parent, Entry* entry) connect(m_ui->buttonBox, SIGNAL(accepted()), SLOT(copyToClipboard())); } +TotpDialog::~TotpDialog() +{ +} + void TotpDialog::copyToClipboard() { clipboard()->setText(m_entry->totp()); @@ -57,13 +65,13 @@ void TotpDialog::copyToClipboard() void TotpDialog::updateProgressBar() { - if (uCounter < 100) { - m_ui->progressBar->setValue(static_cast(100 - uCounter)); + if (m_counter < 100) { + m_ui->progressBar->setValue(100 - m_counter); m_ui->progressBar->update(); - uCounter++; + ++m_counter; } else { updateTotp(); - uCounter = resetCounter(); + resetCounter(); } } @@ -81,16 +89,8 @@ void TotpDialog::updateTotp() m_ui->totpLabel->setText(firstHalf + " " + secondHalf); } -double TotpDialog::resetCounter() +void TotpDialog::resetCounter() { uint epoch = QDateTime::currentDateTime().toTime_t(); - double counter = qRound(static_cast(epoch % m_step) / m_step * 100); - return counter; -} - -TotpDialog::~TotpDialog() -{ - if (m_totpUpdateTimer) { - delete m_totpUpdateTimer; - } + m_counter = static_cast(static_cast(epoch % m_step) / m_step * 100); } diff --git a/src/gui/TotpDialog.h b/src/gui/TotpDialog.h index e002cb82..0ab03518 100644 --- a/src/gui/TotpDialog.h +++ b/src/gui/TotpDialog.h @@ -37,24 +37,23 @@ class TotpDialog : public QDialog Q_OBJECT public: - explicit TotpDialog(DatabaseWidget* parent = nullptr, Entry* entry = nullptr); - ~TotpDialog(); - -private: - double uCounter; - quint8 m_step = Totp::defaultStep; - QScopedPointer m_ui; - QPointer m_totpUpdateTimer; + explicit TotpDialog(QWidget* parent = nullptr, Entry* entry = nullptr); + ~TotpDialog() override; private Q_SLOTS: void updateTotp(); void updateProgressBar(); void updateSeconds(); void copyToClipboard(); - double resetCounter(); -protected: +private: + QScopedPointer m_ui; + + void resetCounter(); Entry* m_entry; + int m_counter; + uint m_step; + QTimer m_totpUpdateTimer; }; #endif // KEEPASSX_TOTPDIALOG_H diff --git a/src/gui/TotpSetupDialog.cpp b/src/gui/TotpSetupDialog.cpp new file mode 100644 index 00000000..69290e7a --- /dev/null +++ b/src/gui/TotpSetupDialog.cpp @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2017 Weslly Honorato <weslly@protonmail.com> + * Copyright (C) 2017 KeePassXC Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "TotpSetupDialog.h" +#include "totp/totp.h" +#include "ui_TotpSetupDialog.h" + +TotpSetupDialog::TotpSetupDialog(QWidget* parent, Entry* entry) + : QDialog(parent) + , m_ui(new Ui::TotpSetupDialog()) + , m_entry(entry) +{ + m_ui->setupUi(this); + setAttribute(Qt::WA_DeleteOnClose); + setFixedSize(sizeHint()); + + connect(m_ui->buttonBox, SIGNAL(rejected()), SLOT(close())); + connect(m_ui->buttonBox, SIGNAL(accepted()), SLOT(saveSettings())); + connect(m_ui->radioCustom, SIGNAL(toggled(bool)), SLOT(toggleCustom(bool))); + + init(); +} + +TotpSetupDialog::~TotpSetupDialog() +{ +} + +void TotpSetupDialog::saveSettings() +{ + QString encShortName; + uint digits = Totp::DEFAULT_DIGITS; + if (m_ui->radio8Digits->isChecked()) { + digits = 8; + } else if (m_ui->radioSteam->isChecked()) { + digits = Totp::STEAM_DIGITS; + encShortName = Totp::STEAM_SHORTNAME; + } + + auto settings = Totp::createSettings(m_ui->seedEdit->text(), digits, m_ui->stepSpinBox->value(), encShortName); + m_entry->setTotp(settings); + emit totpUpdated(); + close(); +} + +void TotpSetupDialog::toggleCustom(bool status) +{ + m_ui->customGroup->setEnabled(status); +} + +void TotpSetupDialog::init() +{ + auto settings = m_entry->totpSettings(); + if (!settings.isNull()) { + m_ui->seedEdit->setText(settings->key); + m_ui->stepSpinBox->setValue(settings->step); + + if (settings->encoder.shortName == Totp::STEAM_SHORTNAME) { + m_ui->radioSteam->setChecked(true); + } else if (settings->custom) { + m_ui->radioCustom->setChecked(true); + if (settings->digits == 8) { + m_ui->radio8Digits->setChecked(true); + } else { + m_ui->radio6Digits->setChecked(true); + } + } + } +} diff --git a/src/gui/SetupTotpDialog.h b/src/gui/TotpSetupDialog.h similarity index 68% rename from src/gui/SetupTotpDialog.h rename to src/gui/TotpSetupDialog.h index 7c34bb5f..905b2a2c 100644 --- a/src/gui/SetupTotpDialog.h +++ b/src/gui/TotpSetupDialog.h @@ -27,33 +27,28 @@ namespace Ui { - class SetupTotpDialog; + class TotpSetupDialog; } -class SetupTotpDialog : public QDialog +class TotpSetupDialog : public QDialog { Q_OBJECT public: - explicit SetupTotpDialog(DatabaseWidget* parent = nullptr, Entry* entry = nullptr); - ~SetupTotpDialog(); - void setSeed(QString value); - void setStep(quint8 step); - void setDigits(quint8 digits); - void setSettings(quint8 digits); + explicit TotpSetupDialog(QWidget* parent = nullptr, Entry* entry = nullptr); + ~TotpSetupDialog() override; + void init(); -private Q_SLOTS: - void toggleDefault(bool status); - void toggleSteam(bool status); +signals: + void totpUpdated(); + +private slots: void toggleCustom(bool status); - void setupTotp(); + void saveSettings(); private: - QScopedPointer m_ui; - -protected: + QScopedPointer m_ui; Entry* m_entry; - DatabaseWidget* m_parent; }; #endif // KEEPASSX_SETUPTOTPDIALOG_H diff --git a/src/gui/TotpSetupDialog.ui b/src/gui/TotpSetupDialog.ui new file mode 100644 index 00000000..7b3e9318 --- /dev/null +++ b/src/gui/TotpSetupDialog.ui @@ -0,0 +1,182 @@ + + + TotpSetupDialog + + + + 0 + 0 + 249 + 248 + + + + Setup TOTP + + + + + + 5 + + + 5 + + + + + Key: + + + + + + + + + + + + border:none + + + + + + false + + + false + + + + + + Default RFC 6238 token settings + + + true + + + settingsButtonGroup + + + + + + + Steam token settings + + + settingsButtonGroup + + + + + + + Use custom settings + + + settingsButtonGroup + + + + + + + + + + false + + + + + + Custom Settings + + + + QFormLayout::ExpandingFieldsGrow + + + QFormLayout::DontWrapRows + + + Qt::AlignRight|Qt::AlignTop|Qt::AlignTrailing + + + 5 + + + 5 + + + + + Time step: + + + + + + + sec + + + 1 + + + 60 + + + 30 + + + + + + + Code size: + + + + + + + 6 digits + + + true + + + + + + + 8 digits + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + + + diff --git a/src/gui/entry/EntryModel.cpp b/src/gui/entry/EntryModel.cpp index d3859e49..fe1f7047 100644 --- a/src/gui/entry/EntryModel.cpp +++ b/src/gui/entry/EntryModel.cpp @@ -127,7 +127,7 @@ int EntryModel::columnCount(const QModelIndex& parent) const return 0; } - return 12; + return 13; } QVariant EntryModel::data(const QModelIndex& index, int role) const @@ -201,16 +201,20 @@ QVariant EntryModel::data(const QModelIndex& index, int role) const case Accessed: result = entry->timeInfo().lastAccessTime().toLocalTime().toString(EntryModel::DateFormat); return result; - case Attachments: - // Display comma-separated list of attachments - QList attachments = entry->attachments()->keys(); - for (int i = 0; i < attachments.size(); ++i) { - if (result.isEmpty()) { - result.append(attachments.at(i)); - continue; + case Attachments: { + // Display comma-separated list of attachments + QList attachments = entry->attachments()->keys(); + for (int i = 0; i < attachments.size(); ++i) { + if (result.isEmpty()) { + result.append(attachments.at(i)); + continue; + } + result.append(QString(", ") + attachments.at(i)); } - result.append(QString(", ") + attachments.at(i)); + return result; } + case Totp: + result = entry->hasTotp() ? tr("Yes") : ""; return result; } } else if (role == Qt::UserRole) { // Qt::UserRole is used as sort role, see EntryView::EntryView() @@ -309,6 +313,8 @@ QVariant EntryModel::headerData(int section, Qt::Orientation orientation, int ro return tr("Accessed"); case Attachments: return tr("Attachments"); + case Totp: + return tr("TOTP"); } } else if (role == Qt::DecorationRole) { if (section == Paperclip) { diff --git a/src/gui/entry/EntryModel.h b/src/gui/entry/EntryModel.h index 1965066a..e8c90f7e 100644 --- a/src/gui/entry/EntryModel.h +++ b/src/gui/entry/EntryModel.h @@ -42,7 +42,8 @@ public: Modified = 8, Accessed = 9, Paperclip = 10, - Attachments = 11 + Attachments = 11, + Totp = 12 }; explicit EntryModel(QObject* parent = nullptr); diff --git a/src/totp/totp.cpp b/src/totp/totp.cpp index d187bd0f..286d383a 100644 --- a/src/totp/totp.cpp +++ b/src/totp/totp.cpp @@ -18,6 +18,7 @@ #include "totp.h" #include "core/Base32.h" + #include #include #include @@ -28,114 +29,107 @@ #include #include -const quint8 Totp::defaultStep = 30; -const quint8 Totp::defaultDigits = 6; - -/** - * Custom encoder types. Each should be unique and >= 128 and < 255 - * Values have no meaning outside of keepassxc - */ -/** - * Encoder for Steam Guard TOTP - */ -const quint8 Totp::ENCODER_STEAM = 254; - -const Totp::Encoder Totp::defaultEncoder = {"", "", "0123456789", 0, 0, false}; -const QMap Totp::encoders{ - {Totp::ENCODER_STEAM, {"steam", "S", "23456789BCDFGHJKMNPQRTVWXY", 5, 30, true}}, +static QList encoders { + {"", "", "0123456789", Totp::DEFAULT_DIGITS, Totp::DEFAULT_STEP, false}, + {"steam", Totp::STEAM_SHORTNAME, "23456789BCDFGHJKMNPQRTVWXY", Totp::STEAM_DIGITS, Totp::DEFAULT_STEP, true}, }; -/** - * These map the second field of the "TOTP Settings" field to our internal encoder number - * that overloads the digits field. Make sure that the key matches the shortName value - * in the corresponding Encoder - * NOTE: when updating this map, a corresponding edit to the settings regex must be made - * in Entry::totpSeed() - */ -const QMap Totp::shortNameToEncoder{ - {"S", Totp::ENCODER_STEAM}, -}; -/** - * These map the "encoder=" URL parameter of the "otp" field to our internal encoder number - * that overloads the digits field. Make sure that the key matches the name value - * in the corresponding Encoder - */ -const QMap Totp::nameToEncoder{ - {"steam", Totp::ENCODER_STEAM}, -}; - -Totp::Totp() +QSharedPointer Totp::parseSettings(const QString& rawSettings, const QString& key) { -} + // Create default settings + auto settings = createSettings(key, DEFAULT_DIGITS, DEFAULT_STEP); -QString Totp::parseOtpString(QString key, quint8& digits, quint8& step) -{ - QUrl url(key); - - QString seed; - uint q_digits, q_step; - - // Default OTP url format + QUrl url(rawSettings); if (url.isValid() && url.scheme() == "otpauth") { + // Default OTP url format QUrlQuery query(url); - - seed = query.queryItemValue("secret"); - - q_digits = query.queryItemValue("digits").toUInt(); - if (q_digits == 6 || q_digits == 8) { - digits = q_digits; - } - - q_step = query.queryItemValue("period").toUInt(); - if (q_step > 0 && q_step <= 60) { - step = q_step; - } - QString encName = query.queryItemValue("encoder"); - if (!encName.isEmpty() && nameToEncoder.contains(encName)) { - digits = nameToEncoder[encName]; + settings->otpUrl = true; + settings->key = query.queryItemValue("secret"); + settings->digits = query.queryItemValue("digits").toUInt(); + settings->step = query.queryItemValue("period").toUInt(); + if (query.hasQueryItem("encoder")) { + settings->encoder = getEncoderByName(query.queryItemValue("encoder")); } } else { - // Compatibility with "KeeOtp" plugin string format - QRegExp rx("key=(.+)", Qt::CaseInsensitive, QRegExp::RegExp); - - if (rx.exactMatch(key)) { - QUrlQuery query(key); - - seed = query.queryItemValue("key"); - q_digits = query.queryItemValue("size").toUInt(); - if (q_digits == 6 || q_digits == 8) { - digits = q_digits; - } - - q_step = query.queryItemValue("step").toUInt(); - if (q_step > 0 && q_step <= 60) { - step = q_step; - } - + QUrlQuery query(rawSettings); + if (query.hasQueryItem("key")) { + // Compatibility with "KeeOtp" plugin + // if settings are changed, will convert to semi-colon format + settings->key = query.queryItemValue("key"); + settings->digits = query.queryItemValue("size").toUInt(); + settings->step = query.queryItemValue("step").toUInt(); } else { - seed = key; + // Parse semi-colon separated values ([step];[digits|S]) + auto vars = rawSettings.split(";"); + if (vars.size() >= 2) { + if (vars[1] == STEAM_SHORTNAME) { + // Explicit steam encoder + settings->encoder = steamEncoder(); + } else { + // Extract step and digits + settings->step = vars[0].toUInt(); + settings->digits = vars[1].toUInt(); + } + } } } - if (digits == 0) { - digits = defaultDigits; + // Bound digits and step + settings->digits = qMax(1u, settings->digits); + settings->step = qBound(1u, settings->step, 60u); + + // Detect custom settings, used by setup GUI + if (settings->encoder.shortName != STEAM_SHORTNAME + && (settings->digits != DEFAULT_DIGITS || settings->step != DEFAULT_STEP)) { + settings->custom = true; } - if (step == 0) { - step = defaultStep; - } - - return seed; + return settings; } -QString Totp::generateTotp(const QByteArray key, - quint64 time, - const quint8 numDigits = defaultDigits, - const quint8 step = defaultStep) +QSharedPointer Totp::createSettings(const QString& key, const uint digits, const uint step, + const QString& encoderShortName) { - quint64 current = qToBigEndian(time / step); + bool isCustom = digits != DEFAULT_DIGITS || step != DEFAULT_STEP; + return QSharedPointer(new Totp::Settings { + getEncoderByShortName(encoderShortName), key, false, isCustom, digits, step + }); +} - QVariant secret = Base32::decode(Base32::sanitizeInput(key)); +QString Totp::writeSettings(const QSharedPointer settings) +{ + // OTP Url output + if (settings->otpUrl) { + auto urlstring = QString("key=%1&step=%2&size=%3").arg(settings->key).arg(settings->step).arg(settings->digits); + if (!settings->encoder.name.isEmpty()) { + urlstring.append("&encoder=").append(settings->encoder.name); + } + return urlstring; + } + + // Semicolon output [step];[encoder] + if (!settings->encoder.shortName.isEmpty()) { + return QString("%1;%2").arg(settings->step).arg(settings->encoder.shortName); + } + + // Semicolon output [step];[digits] + return QString("%1;%2").arg(settings->step).arg(settings->digits); +} + +QString Totp::generateTotp(const QSharedPointer settings, const quint64 time) +{ + const Encoder& encoder = settings->encoder; + uint step = settings->custom ? settings->step : encoder.step; + uint digits = settings->custom ? settings->digits : encoder.digits; + + quint64 current; + if (time == 0) { + current = qToBigEndian(QDateTime::currentDateTime().toTime_t() / step); + } else { + current = qToBigEndian(time / step); + } + + QVariant secret = Base32::decode(Base32::sanitizeInput(settings->key.toLatin1())); if (secret.isNull()) { return "Invalid TOTP secret key"; } @@ -155,9 +149,6 @@ QString Totp::generateTotp(const QByteArray key, | (hmac[offset + 3] & 0xff); // clang-format on - const Encoder& encoder = encoders.value(numDigits, defaultEncoder); - // if encoder.digits is 0, we need to use the passed-in number of digits (default encoder) - quint8 digits = encoder.digits == 0 ? numDigits : encoder.digits; int direction = -1; int startpos = digits - 1; if (encoder.reverse) { @@ -175,26 +166,34 @@ QString Totp::generateTotp(const QByteArray key, return retval; } -// See: https://github.com/google/google-authenticator/wiki/Key-Uri-Format -QUrl Totp::generateOtpString(const QString& secret, - const QString& type, - const QString& issuer, - const QString& username, - const QString& algorithm, - quint8 digits, - quint8 step) +Totp::Encoder& Totp::defaultEncoder() { - QUrl keyUri; - keyUri.setScheme("otpauth"); - keyUri.setHost(type); - keyUri.setPath(QString("/%1:%2").arg(issuer).arg(username)); - QUrlQuery parameters; - parameters.addQueryItem("secret", secret); - parameters.addQueryItem("issuer", issuer); - parameters.addQueryItem("algorithm", algorithm); - parameters.addQueryItem("digits", QString::number(digits)); - parameters.addQueryItem("period", QString::number(step)); - keyUri.setQuery(parameters); - - return keyUri; + // The first encoder is always the default + Q_ASSERT(!encoders.empty()); + return encoders[0]; +} + +Totp::Encoder& Totp::steamEncoder() +{ + return getEncoderByShortName("S"); +} + +Totp::Encoder& Totp::getEncoderByShortName(QString shortName) +{ + for (auto& encoder : encoders) { + if (encoder.shortName == shortName) { + return encoder; + } + } + return defaultEncoder(); +} + +Totp::Encoder& Totp::getEncoderByName(QString name) +{ + for (auto& encoder : encoders) { + if (encoder.name == name) { + return encoder; + } + } + return defaultEncoder(); } diff --git a/src/totp/totp.h b/src/totp/totp.h index 1c159e29..b4a59291 100644 --- a/src/totp/totp.h +++ b/src/totp/totp.h @@ -22,39 +22,52 @@ #include #include #include +#include class QUrl; -class Totp +namespace Totp { + +struct Encoder { -public: - Totp(); - static QString parseOtpString(QString rawSecret, quint8& digits, quint8& step); - static QString generateTotp(const QByteArray key, quint64 time, const quint8 numDigits, const quint8 step); - static QUrl generateOtpString(const QString& secret, - const QString& type, - const QString& issuer, - const QString& username, - const QString& algorithm, - quint8 digits, - quint8 step); - static const quint8 defaultStep; - static const quint8 defaultDigits; - struct Encoder - { - QString name; - QString shortName; - QString alphabet; - quint8 digits; - quint8 step; - bool reverse; - }; - static const Encoder defaultEncoder; - // custom encoder values that overload the digits field - static const quint8 ENCODER_STEAM; - static const QMap encoders; - static const QMap shortNameToEncoder; - static const QMap nameToEncoder; + QString name; + QString shortName; + QString alphabet; + uint digits; + uint step; + bool reverse; }; +struct Settings +{ + Totp::Encoder encoder; + QString key; + bool otpUrl; + bool custom; + uint digits; + uint step; +}; + +constexpr uint DEFAULT_STEP = 30u; +constexpr uint DEFAULT_DIGITS = 6u; +constexpr uint STEAM_DIGITS = 5u; +static const QString STEAM_SHORTNAME = "S"; + +static const QString ATTRIBUTE_OTP = "otp"; +static const QString ATTRIBUTE_SEED = "TOTP Seed"; +static const QString ATTRIBUTE_SETTINGS = "TOTP Settings"; + +QSharedPointer parseSettings(const QString& rawSettings, const QString& key = {}); +QSharedPointer createSettings(const QString& key, const uint digits, const uint step, + const QString& encoderShortName = {}); +QString writeSettings(const QSharedPointer settings); + +QString generateTotp(const QSharedPointer settings, const quint64 time = 0ull); + +Encoder& defaultEncoder(); +Encoder& steamEncoder(); +Encoder& getEncoderByShortName(QString shortName); +Encoder& getEncoderByName(QString name); +} + #endif // QTOTP_H diff --git a/tests/TestEntryModel.cpp b/tests/TestEntryModel.cpp index 3378a9f9..49939e25 100644 --- a/tests/TestEntryModel.cpp +++ b/tests/TestEntryModel.cpp @@ -291,11 +291,11 @@ void TestEntryModel::testProxyModel() * @author Fonic * Update comparison value of modelProxy->columnCount() to account for * additional columns 'Password', 'Notes', 'Expires', 'Created', 'Modified', - * 'Accessed', 'Paperclip' and 'Attachments' + * 'Accessed', 'Paperclip', 'Attachments', and TOTP */ QSignalSpy spyColumnRemove(modelProxy, SIGNAL(columnsAboutToBeRemoved(QModelIndex, int, int))); modelProxy->hideColumn(0, true); - QCOMPARE(modelProxy->columnCount(), 11); + QCOMPARE(modelProxy->columnCount(), 12); QVERIFY(spyColumnRemove.size() >= 1); int oldSpyColumnRemoveSize = spyColumnRemove.size(); @@ -313,11 +313,11 @@ void TestEntryModel::testProxyModel() * @author Fonic * Update comparison value of modelProxy->columnCount() to account for * additional columns 'Password', 'Notes', 'Expires', 'Created', 'Modified', - * 'Accessed', 'Paperclip' and 'Attachments' + * 'Accessed', 'Paperclip', 'Attachments', and TOTP */ QSignalSpy spyColumnInsert(modelProxy, SIGNAL(columnsAboutToBeInserted(QModelIndex, int, int))); modelProxy->hideColumn(0, false); - QCOMPARE(modelProxy->columnCount(), 12); + QCOMPARE(modelProxy->columnCount(), 13); QVERIFY(spyColumnInsert.size() >= 1); int oldSpyColumnInsertSize = spyColumnInsert.size(); diff --git a/tests/TestTotp.cpp b/tests/TestTotp.cpp index a91ae00b..f4de2c6a 100644 --- a/tests/TestTotp.cpp +++ b/tests/TestTotp.cpp @@ -31,138 +31,107 @@ void TestTotp::initTestCase() void TestTotp::testParseSecret() { - quint8 digits = 0; - quint8 step = 0; + // OTP URL Parsing QString secret = "otpauth://totp/" "ACME%20Co:john@example.com?secret=HXDMVJECJJWSRB3HWIZR4IFUGFTMXBOZ&issuer=ACME%20Co&algorithm=" "SHA1&digits=6&period=30"; - QCOMPARE(Totp::parseOtpString(secret, digits, step), QString("HXDMVJECJJWSRB3HWIZR4IFUGFTMXBOZ")); - QCOMPARE(digits, quint8(6)); - QCOMPARE(step, quint8(30)); + auto settings = Totp::parseSettings(secret); + QVERIFY(!settings.isNull()); + QCOMPARE(settings->key, QString("HXDMVJECJJWSRB3HWIZR4IFUGFTMXBOZ")); + QCOMPARE(settings->custom, false); + QCOMPARE(settings->digits, 6u); + QCOMPARE(settings->step, 30u); - digits = Totp::defaultDigits; - step = Totp::defaultStep; + // KeeOTP Parsing secret = "key=HXDMVJECJJWSRBY%3d&step=25&size=8"; - QCOMPARE(Totp::parseOtpString(secret, digits, step), QString("HXDMVJECJJWSRBY=")); - QCOMPARE(digits, quint8(8)); - QCOMPARE(step, quint8(25)); + settings = Totp::parseSettings(secret); + QVERIFY(!settings.isNull()); + QCOMPARE(settings->key, QString("HXDMVJECJJWSRBY=")); + QCOMPARE(settings->custom, true); + QCOMPARE(settings->digits, 8u); + QCOMPARE(settings->step, 25u); - digits = 0; - step = 0; + // Semi-colon delineated "TOTP Settings" secret = "gezdgnbvgy3tqojqgezdgnbvgy3tqojq"; - QCOMPARE(Totp::parseOtpString(secret, digits, step), QString("gezdgnbvgy3tqojqgezdgnbvgy3tqojq")); - QCOMPARE(digits, quint8(6)); - QCOMPARE(step, quint8(30)); + settings = Totp::parseSettings("30;8", secret); + QVERIFY(!settings.isNull()); + QCOMPARE(settings->key, QString("gezdgnbvgy3tqojqgezdgnbvgy3tqojq")); + QCOMPARE(settings->custom, true); + QCOMPARE(settings->digits, 8u); + QCOMPARE(settings->step, 30u); + + // Bare secret (no "TOTP Settings" attribute) + secret = "gezdgnbvgy3tqojqgezdgnbvgy3tqojq"; + settings = Totp::parseSettings("", secret); + QVERIFY(!settings.isNull()); + QCOMPARE(settings->key, QString("gezdgnbvgy3tqojqgezdgnbvgy3tqojq")); + QCOMPARE(settings->custom, false); + QCOMPARE(settings->digits, 6u); + QCOMPARE(settings->step, 30u); } void TestTotp::testTotpCode() { // Test vectors from RFC 6238 // https://tools.ietf.org/html/rfc6238#appendix-B + auto settings = Totp::createSettings("GEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQ", Totp::DEFAULT_DIGITS, Totp::DEFAULT_STEP); - QByteArray seed = QString("GEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQ").toLatin1(); - + // Test 6 digit TOTP (default) quint64 time = 1234567890; - QString output = Totp::generateTotp(seed, time, 6, 30); - QCOMPARE(output, QString("005924")); + QCOMPARE(Totp::generateTotp(settings, time), QString("005924")); time = 1111111109; - output = Totp::generateTotp(seed, time, 6, 30); - QCOMPARE(output, QString("081804")); + QCOMPARE(Totp::generateTotp(settings, time), QString("081804")); + // Test 8 digit TOTP (custom) + settings->digits = 8; + settings->custom = true; time = 1111111111; - output = Totp::generateTotp(seed, time, 8, 30); - QCOMPARE(output, QString("14050471")); + QCOMPARE(Totp::generateTotp(settings, time), QString("14050471")); time = 2000000000; - output = Totp::generateTotp(seed, time, 8, 30); - QCOMPARE(output, QString("69279037")); -} - -void TestTotp::testEncoderData() -{ - for (quint8 key : Totp::encoders.keys()) { - const Totp::Encoder& enc = Totp::encoders.value(key); - QVERIFY2( - enc.digits != 0, - qPrintable( - QString("Custom encoders cannot have zero-value for digits field: %1(%2)").arg(enc.name).arg(key))); - QVERIFY2(!enc.name.isEmpty(), - qPrintable(QString("Custom encoders must have a name: %1(%2)").arg(enc.name).arg(key))); - QVERIFY2(!enc.shortName.isEmpty(), - qPrintable(QString("Custom encoders must have a shortName: %1(%2)").arg(enc.name).arg(key))); - QVERIFY2(Totp::shortNameToEncoder.contains(enc.shortName), - qPrintable(QString("No shortNameToEncoder entry found for custom encoder: %1(%2) %3") - .arg(enc.name) - .arg(key) - .arg(enc.shortName))); - QVERIFY2(Totp::shortNameToEncoder[enc.shortName] == key, - qPrintable(QString("shortNameToEncoder doesn't reference this custome encoder: %1(%2) %3") - .arg(enc.name) - .arg(key) - .arg(enc.shortName))); - QVERIFY2(Totp::nameToEncoder.contains(enc.name), - qPrintable(QString("No nameToEncoder entry found for custom encoder: %1(%2) %3") - .arg(enc.name) - .arg(key) - .arg(enc.shortName))); - QVERIFY2(Totp::nameToEncoder[enc.name] == key, - qPrintable(QString("nameToEncoder doesn't reference this custome encoder: %1(%2) %3") - .arg(enc.name) - .arg(key) - .arg(enc.shortName))); - } - - for (const QString& key : Totp::nameToEncoder.keys()) { - quint8 value = Totp::nameToEncoder.value(key); - QVERIFY2(Totp::encoders.contains(value), - qPrintable(QString("No custom encoder found for encoder named %1(%2)").arg(value).arg(key))); - QVERIFY2(Totp::encoders[value].name == key, - qPrintable( - QString("nameToEncoder doesn't reference the right custom encoder: %1(%2)").arg(value).arg(key))); - } - - for (const QString& key : Totp::shortNameToEncoder.keys()) { - quint8 value = Totp::shortNameToEncoder.value(key); - QVERIFY2(Totp::encoders.contains(value), - qPrintable(QString("No custom encoder found for short-name encoder %1(%2)").arg(value).arg(key))); - QVERIFY2( - Totp::encoders[value].shortName == key, - qPrintable( - QString("shortNameToEncoder doesn't reference the right custom encoder: %1(%2)").arg(value).arg(key))); - } + QCOMPARE(Totp::generateTotp(settings, time), QString("69279037")); } void TestTotp::testSteamTotp() { - quint8 digits = 0; - quint8 step = 0; + // OTP URL Parsing QString secret = "otpauth://totp/" "test:test@example.com?secret=63BEDWCQZKTQWPESARIERL5DTTQFCJTK&issuer=Valve&algorithm=" "SHA1&digits=5&period=30&encoder=steam"; - QCOMPARE(Totp::parseOtpString(secret, digits, step), QString("63BEDWCQZKTQWPESARIERL5DTTQFCJTK")); - QCOMPARE(digits, quint8(Totp::ENCODER_STEAM)); - QCOMPARE(step, quint8(30)); + auto settings = Totp::parseSettings(secret); - QByteArray seed = QString("63BEDWCQZKTQWPESARIERL5DTTQFCJTK").toLatin1(); + QCOMPARE(settings->key, QString("63BEDWCQZKTQWPESARIERL5DTTQFCJTK")); + QCOMPARE(settings->encoder.shortName, Totp::STEAM_SHORTNAME); + QCOMPARE(settings->digits, Totp::STEAM_DIGITS); + QCOMPARE(settings->step, 30u); // These time/value pairs were created by running the Steam Guard function of the // Steam mobile app with a throw-away steam account. The above secret was extracted // from the Steam app's data for use in testing here. quint64 time = 1511200518; - QCOMPARE(Totp::generateTotp(seed, time, Totp::ENCODER_STEAM, 30), QString("FR8RV")); + QCOMPARE(Totp::generateTotp(settings, time), QString("FR8RV")); time = 1511200714; - QCOMPARE(Totp::generateTotp(seed, time, Totp::ENCODER_STEAM, 30), QString("9P3VP")); + QCOMPARE(Totp::generateTotp(settings, time), QString("9P3VP")); } void TestTotp::testEntryHistory() { Entry entry; - quint8 step = 16; - quint8 digits = 6; + uint step = 16; + uint digits = 6; + auto settings = Totp::createSettings("GEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQ", digits, step); + // Test that entry starts without TOTP QCOMPARE(entry.historyItems().size(), 0); - entry.setTotp("GEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQ", step, digits); + QVERIFY(!entry.hasTotp()); + // Add TOTP to entry + entry.setTotp(settings); QCOMPARE(entry.historyItems().size(), 1); - entry.setTotp("foo", step, digits); + QVERIFY(entry.hasTotp()); + QCOMPARE(entry.totpSettings()->key, QString("GEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQ")); + // Change key and verify settings changed + settings->key = "foo"; + entry.setTotp(settings); QCOMPARE(entry.historyItems().size(), 2); + QCOMPARE(entry.totpSettings()->key, QString("foo")); } diff --git a/tests/TestTotp.h b/tests/TestTotp.h index 784eb8f2..92fa7a0e 100644 --- a/tests/TestTotp.h +++ b/tests/TestTotp.h @@ -21,8 +21,6 @@ #include -class Totp; - class TestTotp : public QObject { Q_OBJECT @@ -31,7 +29,6 @@ private slots: void initTestCase(); void testParseSecret(); void testTotpCode(); - void testEncoderData(); void testSteamTotp(); void testEntryHistory(); }; diff --git a/tests/gui/TestGui.cpp b/tests/gui/TestGui.cpp index 5833a241..930dac56 100644 --- a/tests/gui/TestGui.cpp +++ b/tests/gui/TestGui.cpp @@ -56,7 +56,7 @@ #include "gui/MessageBox.h" #include "gui/PasswordEdit.h" #include "gui/SearchWidget.h" -#include "gui/SetupTotpDialog.h" +#include "gui/TotpSetupDialog.h" #include "gui/TotpDialog.h" #include "gui/entry/EditEntryWidget.h" #include "gui/entry/EntryView.h" @@ -636,7 +636,7 @@ void TestGui::testTotp() triggerAction("actionEntrySetupTotp"); - SetupTotpDialog* setupTotpDialog = m_dbWidget->findChild("SetupTotpDialog"); + TotpSetupDialog* setupTotpDialog = m_dbWidget->findChild("TotpSetupDialog"); Tools::wait(100); From 823a91622062102420401e24a3647de091ce86f1 Mon Sep 17 00:00:00 2001 From: Jonathan White Date: Sat, 15 Sep 2018 12:08:33 -0400 Subject: [PATCH 060/267] Fix TOTP epoch time; add null checks for settings --- src/totp/totp.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/totp/totp.cpp b/src/totp/totp.cpp index 286d383a..8d924d57 100644 --- a/src/totp/totp.cpp +++ b/src/totp/totp.cpp @@ -98,6 +98,10 @@ QSharedPointer Totp::createSettings(const QString& key, const ui QString Totp::writeSettings(const QSharedPointer settings) { + if (settings.isNull()) { + return {}; + } + // OTP Url output if (settings->otpUrl) { auto urlstring = QString("key=%1&step=%2&size=%3").arg(settings->key).arg(settings->step).arg(settings->digits); @@ -118,20 +122,26 @@ QString Totp::writeSettings(const QSharedPointer settings) QString Totp::generateTotp(const QSharedPointer settings, const quint64 time) { + Q_ASSERT(!settings.isNull()); + if (settings.isNull()) { + return QObject::tr("Invalid Settings", "TOTP"); + } + const Encoder& encoder = settings->encoder; uint step = settings->custom ? settings->step : encoder.step; uint digits = settings->custom ? settings->digits : encoder.digits; quint64 current; if (time == 0) { - current = qToBigEndian(QDateTime::currentDateTime().toTime_t() / step); + // TODO: Replace toTime_t() with toSecsSinceEpoch() when minimum Qt >= 5.8 + current = qToBigEndian(static_cast(QDateTime::currentDateTime().toTime_t()) / step); } else { current = qToBigEndian(time / step); } QVariant secret = Base32::decode(Base32::sanitizeInput(settings->key.toLatin1())); if (secret.isNull()) { - return "Invalid TOTP secret key"; + return QObject::tr("Invalid Key", "TOTP"); } QMessageAuthenticationCode code(QCryptographicHash::Sha1); From c88390e3be26568d2f5d19b9e18f37bded935c83 Mon Sep 17 00:00:00 2001 From: Jonathan White Date: Tue, 28 Aug 2018 15:11:16 -0400 Subject: [PATCH 061/267] Support building snaps on Ubuntu 18.04 and Launchpad --- snapcraft.yaml | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/snapcraft.yaml b/snapcraft.yaml index 21e33c44..25baf676 100644 --- a/snapcraft.yaml +++ b/snapcraft.yaml @@ -7,11 +7,12 @@ description: | personal data management. It has a light interface, is cross-platform and published under the terms of the GNU General Public License. confinement: strict +base: core18 apps: keepassxc: command: desktop-launch keepassxc - plugs: [unity7, x11, opengl, gsettings, home, network, network-bind, removable-media, raw-usb] + plugs: [unity7, x11, opengl, gsettings, home, network, network-bind, removable-media, raw-usb, wayland, desktop-legacy] desktop: usr/share/applications/org.keepassxc.KeePassXC.desktop cli: command: keepassxc-cli @@ -27,8 +28,6 @@ parts: configflags: - -DCMAKE_BUILD_TYPE=Release - -DCMAKE_INSTALL_PREFIX=/usr - - -DCMAKE_LIBRARY_PATH=/opt/keepassxc-libs/lib/x86_64-linux-gnu - - -DCMAKE_INCLUDE_PATH=/opt/keepassxc-libs/include - -DKEEPASSXC_DIST_TYPE=Snap - -DKEEPASSXC_BUILD_TYPE=Release - -DWITH_TESTS=OFF @@ -50,20 +49,19 @@ parts: stage-packages: - dbus - qttranslations5-l10n # common translations - - libgcrypt20-18 + - libgcrypt20 - libykpers-1-1 - libargon2-0 - libsodium23 - libxtst6 - libqt5x11extras5 - libusb-1.0-0 + - qtwayland5 override-build: | snapcraftctl build sed -i 's|Icon=keepassxc|Icon=${SNAP}/usr/share/icons/hicolor/256x256/apps/keepassxc.png|g' $SNAPCRAFT_PART_INSTALL/usr/share/applications/org.keepassxc.KeePassXC.desktop organize: usr/share/qt5/translations/*.qm: usr/share/keepassxc/translations/ - opt/keepassxc-libs/lib/x86_64-linux-gnu/*: usr/lib/x86_64-linux-gnu/ - opt/keepassxc-libs/share/locale/*: usr/share/locale/ stage: - -opt after: [desktop-qt5] From 4ce42fa6d420bc46ae9c6640971acc325130a1d6 Mon Sep 17 00:00:00 2001 From: Jonathan White Date: Tue, 28 Aug 2018 21:30:56 -0400 Subject: [PATCH 062/267] Bumped version number to 2.4.0-preview --- CHANGELOG | 6 ++++++ CMakeLists.txt | 4 ++-- share/linux/org.keepassxc.KeePassXC.appdata.xml | 7 +++++++ snapcraft.yaml | 4 ++-- 4 files changed, 17 insertions(+), 4 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 20545c44..4c29e968 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,9 @@ +2.4.0-preview (TBD) +========================= + +This is a pre-release build, view merged PR's at +https://github.com/keepassxreboot/keepassxc/pulls?q=is%3Apr+milestone%3Av2.4.0+is%3Aclosed + 2.3.4 (2018-08-21) ========================= diff --git a/CMakeLists.txt b/CMakeLists.txt index 5cac3cc9..7be9e301 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -61,8 +61,8 @@ endif() set(CMAKE_AUTOUIC ON) set(KEEPASSXC_VERSION_MAJOR "2") -set(KEEPASSXC_VERSION_MINOR "3") -set(KEEPASSXC_VERSION_PATCH "4") +set(KEEPASSXC_VERSION_MINOR "4") +set(KEEPASSXC_VERSION_PATCH "0") set(KEEPASSXC_VERSION "${KEEPASSXC_VERSION_MAJOR}.${KEEPASSXC_VERSION_MINOR}.${KEEPASSXC_VERSION_PATCH}") set(KEEPASSXC_BUILD_TYPE "Snapshot" CACHE STRING "Set KeePassXC build type to distinguish between stable releases and snapshots") diff --git a/share/linux/org.keepassxc.KeePassXC.appdata.xml b/share/linux/org.keepassxc.KeePassXC.appdata.xml index 554bcdef..cf9d499b 100644 --- a/share/linux/org.keepassxc.KeePassXC.appdata.xml +++ b/share/linux/org.keepassxc.KeePassXC.appdata.xml @@ -50,6 +50,13 @@ + + +

+ This is a pre-release build, click to view merged PR's +

+
+