diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0246d107..76691de1 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -85,7 +85,6 @@ set(keepassx_SOURCES format/KeePass1Reader.cpp format/KeePass2.cpp format/KeePass2RandomStream.cpp - format/KeePass2Repair.cpp format/KdbxReader.cpp format/KdbxWriter.cpp format/KdbxXmlReader.cpp @@ -102,7 +101,6 @@ set(keepassx_SOURCES gui/Clipboard.cpp gui/CloneDialog.cpp gui/DatabaseOpenWidget.cpp - gui/DatabaseRepairWidget.cpp gui/DatabaseTabWidget.cpp gui/DatabaseWidget.cpp gui/DatabaseWidgetStateSync.cpp @@ -113,7 +111,6 @@ set(keepassx_SOURCES gui/EditWidgetIcons.cpp gui/EditWidgetProperties.cpp gui/FileDialog.cpp - gui/masterkey/KeyComponentWidget.cpp gui/Font.cpp gui/IconModels.cpp gui/KeePass1OpenWidget.cpp @@ -150,16 +147,17 @@ set(keepassx_SOURCES gui/group/EditGroupWidget.cpp gui/group/GroupModel.cpp gui/group/GroupView.cpp + gui/masterkey/KeyComponentWidget.cpp gui/masterkey/PasswordEditWidget.cpp gui/masterkey/YubiKeyEditWidget.cpp gui/masterkey/KeyFileEditWidget.cpp - gui/settings/SettingsWidget.cpp gui/dbsettings/DatabaseSettingsWidget.cpp gui/dbsettings/DatabaseSettingsDialog.cpp gui/dbsettings/DatabaseSettingsWidgetGeneral.cpp - gui/dbsettings/DatabaseSettingsWidgetMetaDataSimple.cpp + gui/dbsettings/DatabaseSettingsWidgetMetaDataSimple.cpp gui/dbsettings/DatabaseSettingsWidgetEncryption.cpp - gui/dbsettings/DatabaseSettingsWidgetMasterKey.cpp + gui/dbsettings/DatabaseSettingsWidgetMasterKey.cpp + gui/settings/SettingsWidget.cpp gui/wizard/NewDatabaseWizard.cpp gui/wizard/NewDatabaseWizardPage.cpp gui/wizard/NewDatabaseWizardPageMetaData.cpp diff --git a/src/format/KdbxReader.cpp b/src/format/KdbxReader.cpp index 72f0f137..5e14b8a9 100644 --- a/src/format/KdbxReader.cpp +++ b/src/format/KdbxReader.cpp @@ -120,11 +120,6 @@ QByteArray KdbxReader::xmlData() const return m_xmlData; } -QByteArray KdbxReader::streamKey() const -{ - return m_protectedStreamKey; -} - KeePass2::ProtectedStreamAlgo KdbxReader::protectedStreamAlgo() const { return m_irsAlgo; diff --git a/src/format/KdbxReader.h b/src/format/KdbxReader.h index d42927c0..a39d6b08 100644 --- a/src/format/KdbxReader.h +++ b/src/format/KdbxReader.h @@ -48,7 +48,6 @@ public: bool saveXml() const; void setSaveXml(bool save); QByteArray xmlData() const; - QByteArray streamKey() const; KeePass2::ProtectedStreamAlgo protectedStreamAlgo() const; protected: diff --git a/src/format/KeePass2Repair.cpp b/src/format/KeePass2Repair.cpp deleted file mode 100644 index 2e0bc53c..00000000 --- a/src/format/KeePass2Repair.cpp +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (C) 2016 Felix Geyer - * 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 "KeePass2Repair.h" - -#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" - -KeePass2Repair::RepairOutcome KeePass2Repair::repairDatabase(QIODevice* device, QSharedPointer key) -{ - m_errorStr.clear(); - - KeePass2Reader reader; - reader.setSaveXml(true); - - QScopedPointer db(reader.readDatabase(device, key, true)); - if (!reader.hasError()) { - return qMakePair(NothingTodo, nullptr); - } - - QByteArray xmlData = reader.reader()->xmlData(); - if (!db || xmlData.isEmpty()) { - m_errorStr = reader.errorString(); - return qMakePair(UnableToOpen, nullptr); - } - - bool repairAction = false; - - QString xmlStart = QString::fromLatin1(xmlData.constData(), qMin(100, xmlData.size())); - 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) { - // database is not utf-8 encoded, we don't support repairing that - return qMakePair(RepairFailed, nullptr); - } - } - - // try to fix broken databases because of bug #392 - for (int i = (xmlData.size() - 1); i >= 0; i--) { - auto ch = static_cast(xmlData.at(i)); - if (ch < 0x20 && ch != 0x09 && ch != 0x0A && ch != 0x0D) { - xmlData.remove(i, 1); - repairAction = true; - } - } - - if (!repairAction) { - // we were unable to find the problem - return qMakePair(RepairFailed, nullptr); - } - - KeePass2RandomStream randomStream(reader.reader()->protectedStreamAlgo()); - randomStream.init(reader.reader()->streamKey()); - bool hasError; - - QBuffer buffer(&xmlData); - buffer.open(QIODevice::ReadOnly); - if ((reader.version() & KeePass2::FILE_VERSION_CRITICAL_MASK) < KeePass2::FILE_VERSION_4) { - KdbxXmlReader xmlReader(KeePass2::FILE_VERSION_3_1); - xmlReader.readDatabase(&buffer, db.data(), &randomStream); - hasError = xmlReader.hasError(); - } else { - auto reader4 = reader.reader().staticCast(); - QHash pool = reader4->binaryPool(); - KdbxXmlReader xmlReader(KeePass2::FILE_VERSION_4, pool); - xmlReader.readDatabase(&buffer, db.data(), &randomStream); - hasError = xmlReader.hasError(); - } - - if (hasError) { - return qMakePair(RepairFailed, nullptr); - } else { - return qMakePair(RepairSuccess, db.take()); - } -} - -QString KeePass2Repair::errorString() const -{ - return m_errorStr; -} diff --git a/src/format/KeePass2Repair.h b/src/format/KeePass2Repair.h deleted file mode 100644 index 2f822dd0..00000000 --- a/src/format/KeePass2Repair.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2016 Felix Geyer - * 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_KEEPASS2REPAIR_H -#define KEEPASSX_KEEPASS2REPAIR_H - -#include -#include -#include - -#include "core/Database.h" -#include "keys/CompositeKey.h" - -class KeePass2Repair -{ - Q_DECLARE_TR_FUNCTIONS(KeePass2Repair) - -public: - enum RepairResult - { - NothingTodo, - UnableToOpen, - RepairSuccess, - RepairFailed - }; - using RepairOutcome = QPair; - - RepairOutcome repairDatabase(QIODevice* device, QSharedPointer key); - QString errorString() const; - -private: - QString m_errorStr; -}; - -#endif // KEEPASSX_KEEPASS2REPAIR_H diff --git a/src/gui/DatabaseRepairWidget.cpp b/src/gui/DatabaseRepairWidget.cpp deleted file mode 100644 index 7a90cf7d..00000000 --- a/src/gui/DatabaseRepairWidget.cpp +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (C) 2016 Felix Geyer - * 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 "DatabaseRepairWidget.h" - -#include -#include - -#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) -{ - m_ui->labelHeadline->setText(tr("Repair database")); - - connect(this, SIGNAL(editFinished(bool)), this, SLOT(processEditFinished(bool))); -} - -void DatabaseRepairWidget::openDatabase() -{ - auto masterKey = QSharedPointer::create(); - - if (m_ui->checkPassword->isChecked()) { - masterKey->addKey(QSharedPointer::create(m_ui->editPassword->text())); - } - - if (m_ui->checkKeyFile->isChecked()) { - auto key = QSharedPointer::create(); - QString keyFilename = m_ui->comboKeyFile->currentText(); - QString errorMsg; - if (!key->load(keyFilename, &errorMsg)) { - MessageBox::warning(this, tr("Error"), tr("Can't open key file:\n%1").arg(errorMsg)); - emit editFinished(false); - return; - } - masterKey->addKey(key); - } - - KeePass2Repair repair; - - 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())); - emit editFinished(false); - return; - } - if (m_db) { - delete m_db; - } - QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); - auto repairOutcome = repair.repairDatabase(&file, masterKey); - KeePass2Repair::RepairResult repairResult = repairOutcome.first; - QApplication::restoreOverrideCursor(); - - switch (repairResult) { - case KeePass2Repair::NothingTodo: - MessageBox::information(this, tr("Error"), tr("Database opened fine. Nothing to do.")); - emit editFinished(false); - return; - case KeePass2Repair::UnableToOpen: - 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.")); - emit editFinished(true); - return; - case KeePass2Repair::RepairFailed: - MessageBox::warning(this, tr("Error"), tr("Unable to repair the database.")); - emit editFinished(false); - return; - } -} - -void DatabaseRepairWidget::processEditFinished(bool result) -{ - if (result) { - emit success(); - } else { - emit error(); - } -} diff --git a/src/gui/DatabaseRepairWidget.h b/src/gui/DatabaseRepairWidget.h deleted file mode 100644 index 67b48ce5..00000000 --- a/src/gui/DatabaseRepairWidget.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2016 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_DATABASEREPAIRWIDGET_H -#define KEEPASSX_DATABASEREPAIRWIDGET_H - -#include "gui/DatabaseOpenWidget.h" - -class DatabaseRepairWidget : public DatabaseOpenWidget -{ - Q_OBJECT - -public: - explicit DatabaseRepairWidget(QWidget* parent = nullptr); - -signals: - void success(); - void error(); - -protected: - void openDatabase() override; - -private slots: - void processEditFinished(bool result); -}; - -#endif // KEEPASSX_DATABASEREPAIRWIDGET_H diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp index f3e97472..733ac016 100644 --- a/src/gui/MainWindow.cpp +++ b/src/gui/MainWindow.cpp @@ -32,12 +32,8 @@ #include "core/FilePath.h" #include "core/InactivityTimer.h" #include "core/Metadata.h" -#include "format/KeePass2Writer.h" #include "gui/AboutDialog.h" -#include "gui/DatabaseRepairWidget.h" #include "gui/DatabaseWidget.h" -#include "gui/FileDialog.h" -#include "gui/MessageBox.h" #include "gui/SearchWidget.h" #ifdef WITH_XC_SSHAGENT @@ -278,7 +274,6 @@ MainWindow::MainWindow() 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())); @@ -448,7 +443,6 @@ void MainWindow::setMenuActionState(DatabaseWidget::Mode mode) 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()); @@ -963,39 +957,6 @@ void MainWindow::forgetTouchIDAfterInactivity() #endif } -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); - if (fileName.isEmpty()) { - return; - } - - QScopedPointer dialog(new QDialog(this)); - DatabaseRepairWidget* dbRepairWidget = new DatabaseRepairWidget(dialog.data()); - connect(dbRepairWidget, SIGNAL(success()), dialog.data(), SLOT(accept())); - 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(), - tr("KeePass 2 Database").append(" (*.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); - } - } - } -} - bool MainWindow::isTrayIconEnabled() const { return config()->get("GUI/ShowTrayIcon").toBool() && QSystemTrayIcon::isSystemTrayAvailable(); diff --git a/src/gui/MainWindow.h b/src/gui/MainWindow.h index c4770072..566034c8 100644 --- a/src/gui/MainWindow.h +++ b/src/gui/MainWindow.h @@ -107,7 +107,6 @@ private slots: void toggleWindow(); void lockDatabasesAfterInactivity(); void forgetTouchIDAfterInactivity(); - void repairDatabase(); void hideTabMessage(); void handleScreenLock(); void showErrorMessage(const QString& message); diff --git a/src/gui/MainWindow.ui b/src/gui/MainWindow.ui index 78d5178b..9f604131 100644 --- a/src/gui/MainWindow.ui +++ b/src/gui/MainWindow.ui @@ -215,7 +215,6 @@ - @@ -576,11 +575,6 @@ Import CSV file... - - - Re&pair database... - - Show TOTP diff --git a/tests/TestKdbx3.cpp b/tests/TestKdbx3.cpp index 1c8526b3..5fdfe024 100644 --- a/tests/TestKdbx3.cpp +++ b/tests/TestKdbx3.cpp @@ -24,7 +24,6 @@ #include "format/KdbxXmlWriter.h" #include "format/KeePass2.h" #include "format/KeePass2Reader.h" -#include "format/KeePass2Repair.h" #include "format/KeePass2Writer.h" #include "keys/PasswordKey.h" @@ -181,34 +180,3 @@ void TestKdbx3::testBrokenHeaderHash() QVERIFY(!db.data()); QVERIFY(reader.hasError()); } - -void TestKdbx3::testKdbxRepair() -{ - QString brokenDbFilename = QString(KEEPASSX_TEST_DATA_DIR).append("/bug392.kdbx"); - // master password = test - // entry username: testuser\x10\x20AC - // entry password: testpw - auto key = QSharedPointer::create(); - key->addKey(QSharedPointer::create("test")); - - // test that we can't open the broken database - bool hasError; - QString errorString; - QScopedPointer dbBroken; - readKdbx(brokenDbFilename, key, dbBroken, hasError, errorString); - QVERIFY(!dbBroken.data()); - QVERIFY(hasError); - - // test if we can repair the database - KeePass2Repair repair; - QFile file(brokenDbFilename); - file.open(QIODevice::ReadOnly); - auto result = repair.repairDatabase(&file, key); - QCOMPARE(result.first, KeePass2Repair::RepairSuccess); - QScopedPointer dbRepaired(result.second); - QVERIFY(dbRepaired); - - QCOMPARE(dbRepaired->rootGroup()->entries().size(), 1); - QCOMPARE(dbRepaired->rootGroup()->entries().at(0)->username(), QString("testuser").append(QChar(0x20AC))); - QCOMPARE(dbRepaired->rootGroup()->entries().at(0)->password(), QString("testpw")); -} diff --git a/tests/TestKdbx3.h b/tests/TestKdbx3.h index f96e1606..aadc50aa 100644 --- a/tests/TestKdbx3.h +++ b/tests/TestKdbx3.h @@ -30,7 +30,6 @@ private slots: void testProtectedStrings(); void testBrokenHeaderHash(); void testFormat300(); - void testKdbxRepair(); protected: void initTestCaseImpl() override; diff --git a/tests/data/bug392.kdbx b/tests/data/bug392.kdbx deleted file mode 100644 index 0953d867..00000000 Binary files a/tests/data/bug392.kdbx and /dev/null differ