From e16672202664d23cd9d2ba3945f684a018053cc9 Mon Sep 17 00:00:00 2001 From: Felix Geyer Date: Fri, 12 Oct 2012 12:12:00 +0200 Subject: [PATCH] Implement database locking. Closes #35 --- .../16x16/actions/document-encrypt.png | Bin 0 -> 452 bytes src/CMakeLists.txt | 2 + src/gui/DatabaseOpenWidget.cpp | 56 +++++++----- src/gui/DatabaseOpenWidget.h | 4 + src/gui/DatabaseTabWidget.cpp | 52 ++++++++++- src/gui/DatabaseTabWidget.h | 5 +- src/gui/DatabaseWidget.cpp | 86 ++++++++++++------ src/gui/DatabaseWidget.h | 12 ++- src/gui/KeePass1OpenWidget.cpp | 2 +- src/gui/MainWindow.cpp | 7 ++ src/gui/MainWindow.ui | 9 ++ src/gui/UnlockDatabaseWidget.cpp | 64 +++++++++++++ src/gui/UnlockDatabaseWidget.h | 33 +++++++ tests/gui/TestGui.cpp | 18 ++++ tests/gui/TestGui.h | 1 + 15 files changed, 297 insertions(+), 54 deletions(-) create mode 100644 share/icons/application/16x16/actions/document-encrypt.png create mode 100644 src/gui/UnlockDatabaseWidget.cpp create mode 100644 src/gui/UnlockDatabaseWidget.h diff --git a/share/icons/application/16x16/actions/document-encrypt.png b/share/icons/application/16x16/actions/document-encrypt.png new file mode 100644 index 0000000000000000000000000000000000000000..ac2fd6f90f473f0e497f9ec65e01b26e8fcbc1e4 GIT binary patch literal 452 zcmV;#0XzPQP){*xqu6zo97u8y1ZJ6plT?@BQ4ok{ z+TdZhC=vE=s3yPtE(pTv`m^2X6qh6^;cz(S^xkLL z&o;NmD#TR4R~VS);WMLje^R3O!hz^@Kh)i9`%foV1%w+4~N55nzQfvtjFUy&15ol zJ!2#oB>{Mz*BamI^ZDd-It@MZtw0pTVxvG11UZ#T84D7^G_I5}oJWRnxZ00xZx^Co z8#WQ`#K^LN3SNTc+x1dZRgv)F~$k_|^fFLKc#)GiFZk*b-n u5N$*!(L?kT14JLuO<0LmqJ?PE_q_mVmxN%}APaE-0000checkPassword->isChecked()) { - masterKey.addKey(PasswordKey(m_ui->editPassword->text())); + CompositeKey masterKey = databaseKey(); + if (masterKey.isEmpty()) { + return; } - QHash lastKeyFiles = config()->get("LastKeyFiles").toHash(); - - if (m_ui->checkKeyFile->isChecked()) { - FileKey key; - QString keyFilename = m_ui->comboKeyFile->currentText(); - QString errorMsg; - if (!key.load(keyFilename, &errorMsg)) { - QMessageBox::warning(this, tr("Error"), tr("Can't open key file:\n%1").arg(errorMsg)); - return; - } - masterKey.addKey(key); - lastKeyFiles[m_filename] = keyFilename; - } - else { - lastKeyFiles.remove(m_filename); - } - - config()->set("LastKeyFiles", lastKeyFiles); - QFile file(m_filename); if (!file.open(QIODevice::ReadOnly)) { // TODO: error message @@ -141,6 +121,36 @@ void DatabaseOpenWidget::openDatabase() } } +CompositeKey DatabaseOpenWidget::databaseKey() +{ + CompositeKey masterKey; + + if (m_ui->checkPassword->isChecked()) { + masterKey.addKey(PasswordKey(m_ui->editPassword->text())); + } + + QHash lastKeyFiles = config()->get("LastKeyFiles").toHash(); + + if (m_ui->checkKeyFile->isChecked()) { + FileKey key; + QString keyFilename = m_ui->comboKeyFile->currentText(); + QString errorMsg; + if (!key.load(keyFilename, &errorMsg)) { + QMessageBox::warning(this, tr("Error"), tr("Can't open key file:\n%1").arg(errorMsg)); + return CompositeKey(); + } + masterKey.addKey(key); + lastKeyFiles[m_filename] = keyFilename; + } + else { + lastKeyFiles.remove(m_filename); + } + + config()->set("LastKeyFiles", lastKeyFiles); + + return masterKey; +} + void DatabaseOpenWidget::reject() { Q_EMIT editFinished(false); diff --git a/src/gui/DatabaseOpenWidget.h b/src/gui/DatabaseOpenWidget.h index 209391fa7..0216de586 100644 --- a/src/gui/DatabaseOpenWidget.h +++ b/src/gui/DatabaseOpenWidget.h @@ -21,6 +21,7 @@ #include #include "gui/DialogyWidget.h" +#include "keys/CompositeKey.h" class Database; class QFile; @@ -43,6 +44,9 @@ public: Q_SIGNALS: void editFinished(bool accepted); +protected: + CompositeKey databaseKey(); + protected Q_SLOTS: virtual void openDatabase(); void reject(); diff --git a/src/gui/DatabaseTabWidget.cpp b/src/gui/DatabaseTabWidget.cpp index 2e041a132..cc87a5745 100644 --- a/src/gui/DatabaseTabWidget.cpp +++ b/src/gui/DatabaseTabWidget.cpp @@ -297,6 +297,7 @@ void DatabaseTabWidget::saveDatabaseAs(Database* db) dbStruct.filePath = fileInfo.absoluteFilePath(); dbStruct.canonicalFilePath = fileInfo.canonicalFilePath(); dbStruct.fileName = fileInfo.fileName(); + dbStruct.dbWidget->updateFilename(dbStruct.filePath); updateTabName(db); updateLastDatabases(dbStruct.filePath); } @@ -391,20 +392,35 @@ void DatabaseTabWidget::updateTabName(Database* db) tabName = QString("%1 [%2]").arg(db->metadata()->name(), tr("New database")); } } + + if (dbStruct.dbWidget->currentMode() == DatabaseWidget::LockedMode) { + tabName.append(QString(" [%1]").arg(tr("locked"))); + } + if (dbStruct.modified) { tabName.append("*"); } + setTabText(index, tabName); Q_EMIT tabNameChanged(); } -void DatabaseTabWidget::updateTabNameFromSender() +void DatabaseTabWidget::updateTabNameFromDbSender() { Q_ASSERT(qobject_cast(sender())); updateTabName(static_cast(sender())); } +void DatabaseTabWidget::updateTabNameFromDbWidgetSender() +{ + Q_ASSERT(qobject_cast(sender())); + Q_ASSERT(databaseFromDatabaseWidget(qobject_cast(sender()))); + + DatabaseWidget* dbWidget = static_cast(sender()); + updateTabName(databaseFromDatabaseWidget(dbWidget)); +} + int DatabaseTabWidget::databaseIndex(Database* db) { QWidget* dbWidget = m_dbList.value(db).dbWidget; @@ -466,6 +482,7 @@ void DatabaseTabWidget::insertDatabase(Database* db, const DatabaseManagerStruct connectDatabase(db); connect(dbStruct.dbWidget, SIGNAL(closeRequest()), SLOT(closeDatabaseFromSender())); connect(dbStruct.dbWidget, SIGNAL(databaseChanged(Database*)), SLOT(changeDatabase(Database*))); + connect(dbStruct.dbWidget, SIGNAL(unlockedDatabase()), SLOT(updateTabNameFromDbWidgetSender())); } DatabaseWidget* DatabaseTabWidget::currentDatabaseWidget() @@ -479,6 +496,37 @@ DatabaseWidget* DatabaseTabWidget::currentDatabaseWidget() } } +bool DatabaseTabWidget::hasLockableDatabases() +{ + QHashIterator i(m_dbList); + while (i.hasNext()) { + i.next(); + DatabaseWidget::Mode mode = i.value().dbWidget->currentMode(); + + if ((mode == DatabaseWidget::ViewMode || mode == DatabaseWidget::EditMode) + && i.value().dbWidget->dbHasKey()) { + return true; + } + } + + return false; +} + +void DatabaseTabWidget::lockDatabases() +{ + QHashIterator i(m_dbList); + while (i.hasNext()) { + i.next(); + DatabaseWidget::Mode mode = i.value().dbWidget->currentMode(); + + if ((mode == DatabaseWidget::ViewMode || mode == DatabaseWidget::EditMode) + && i.value().dbWidget->dbHasKey()) { + i.value().dbWidget->lock(); + updateTabName(i.key()); + } + } +} + void DatabaseTabWidget::modified() { Q_ASSERT(qobject_cast(sender())); @@ -535,7 +583,7 @@ void DatabaseTabWidget::connectDatabase(Database* newDb, Database* oldDb) oldDb->disconnect(this); } - connect(newDb, SIGNAL(nameTextChanged()), SLOT(updateTabNameFromSender())); + connect(newDb, SIGNAL(nameTextChanged()), SLOT(updateTabNameFromDbSender())); connect(newDb, SIGNAL(modified()), SLOT(modified())); newDb->setEmitModified(true); } diff --git a/src/gui/DatabaseTabWidget.h b/src/gui/DatabaseTabWidget.h index 1ec1569c1..51dcc76f9 100644 --- a/src/gui/DatabaseTabWidget.h +++ b/src/gui/DatabaseTabWidget.h @@ -53,6 +53,7 @@ public: void openDatabase(const QString& fileName, const QString& pw = QString(), const QString& keyFile = QString()); DatabaseWidget* currentDatabaseWidget(); + bool hasLockableDatabases(); static const int LastDatabasesCount; @@ -69,13 +70,15 @@ public Q_SLOTS: void changeDatabaseSettings(); bool readOnly(int index = -1); void performGlobalAutoType(); + void lockDatabases(); Q_SIGNALS: void tabNameChanged(); private Q_SLOTS: void updateTabName(Database* db); - void updateTabNameFromSender(); + void updateTabNameFromDbSender(); + void updateTabNameFromDbWidgetSender(); void modified(); void toggleTabbar(); void changeDatabase(Database* newDb); diff --git a/src/gui/DatabaseWidget.cpp b/src/gui/DatabaseWidget.cpp index e6f723139..8a76081fb 100644 --- a/src/gui/DatabaseWidget.cpp +++ b/src/gui/DatabaseWidget.cpp @@ -36,6 +36,7 @@ #include "gui/DatabaseOpenWidget.h" #include "gui/DatabaseSettingsWidget.h" #include "gui/KeePass1OpenWidget.h" +#include "gui/UnlockDatabaseWidget.h" #include "gui/entry/EditEntryWidget.h" #include "gui/entry/EntryView.h" #include "gui/group/EditGroupWidget.h" @@ -121,6 +122,8 @@ DatabaseWidget::DatabaseWidget(Database* db, QWidget* parent) m_databaseOpenWidget->setObjectName("databaseOpenWidget"); m_keepass1OpenWidget = new KeePass1OpenWidget(); m_keepass1OpenWidget->setObjectName("keepass1OpenWidget"); + m_unlockDatabaseWidget = new UnlockDatabaseWidget(); + m_unlockDatabaseWidget->setObjectName("unlockDatabaseWidget"); addWidget(m_mainWidget); addWidget(m_editEntryWidget); addWidget(m_editGroupWidget); @@ -129,6 +132,7 @@ DatabaseWidget::DatabaseWidget(Database* db, QWidget* parent) addWidget(m_historyEditEntryWidget); addWidget(m_databaseOpenWidget); addWidget(m_keepass1OpenWidget); + addWidget(m_unlockDatabaseWidget); connect(m_groupView, SIGNAL(groupChanged(Group*)), this, SLOT(clearLastGroup(Group*))); connect(m_groupView, SIGNAL(groupChanged(Group*)), SIGNAL(groupChanged())); @@ -143,6 +147,7 @@ DatabaseWidget::DatabaseWidget(Database* db, QWidget* parent) connect(m_databaseSettingsWidget, SIGNAL(editFinished(bool)), SLOT(switchToView(bool))); connect(m_databaseOpenWidget, SIGNAL(editFinished(bool)), SLOT(openDatabase(bool))); connect(m_keepass1OpenWidget, SIGNAL(editFinished(bool)), SLOT(openDatabase(bool))); + connect(m_unlockDatabaseWidget, SIGNAL(editFinished(bool)), SLOT(unlockDatabase(bool))); connect(this, SIGNAL(currentChanged(int)), this, SLOT(emitCurrentModeChanged())); connect(m_searchUi->searchEdit, SIGNAL(textChanged(QString)), this, SLOT(startSearchTimer())); connect(m_searchUi->caseSensitiveCheckBox, SIGNAL(toggled(bool)), this, SLOT(startSearch())); @@ -151,7 +156,7 @@ DatabaseWidget::DatabaseWidget(Database* db, QWidget* parent) connect(m_searchTimer, SIGNAL(timeout()), this, SLOT(search())); connect(closeAction, SIGNAL(triggered()), this, SLOT(closeSearch())); - setCurrentIndex(0); + setCurrentWidget(m_mainWidget); } DatabaseWidget::~DatabaseWidget() @@ -160,22 +165,17 @@ DatabaseWidget::~DatabaseWidget() DatabaseWidget::Mode DatabaseWidget::currentMode() { - switch (currentIndex()) { - case -1: + if (currentWidget() == Q_NULLPTR) { return DatabaseWidget::None; - case 0: + } + else if (currentWidget() == m_mainWidget) { return DatabaseWidget::ViewMode; - case 1: // entry edit - case 2: // group edit - case 3: // change master key - case 4: // database settings - case 5: // entry history - case 6: // open database - case 7: // keepass 1 import + } + else if (currentWidget() == m_unlockDatabaseWidget) { + return DatabaseWidget::LockedMode; + } + else { return DatabaseWidget::EditMode; - default: - Q_ASSERT(false); - return DatabaseWidget::None; } } @@ -347,12 +347,20 @@ int DatabaseWidget::addWidget(QWidget* w) } void DatabaseWidget::setCurrentIndex(int index) +{ + // use setCurrentWidget() instead + // index is not reliable + Q_UNUSED(index); + Q_ASSERT(false); +} + +void DatabaseWidget::setCurrentWidget(QWidget* widget) { if (currentWidget()) { currentWidget()->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored); } - QStackedWidget::setCurrentIndex(index); + QStackedWidget::setCurrentWidget(widget); if (currentWidget()) { currentWidget()->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); @@ -390,18 +398,18 @@ void DatabaseWidget::switchToView(bool accepted) m_newParent = Q_NULLPTR; } - setCurrentIndex(0); + setCurrentWidget(m_mainWidget); } void DatabaseWidget::switchToHistoryView(Entry* entry) { m_historyEditEntryWidget->loadEntry(entry, false, true, "", m_db); - setCurrentIndex(5); + setCurrentWidget(m_historyEditEntryWidget); } void DatabaseWidget::switchBackToEntryEdit() { - setCurrentIndex(1); + setCurrentWidget(m_editEntryWidget); } void DatabaseWidget::switchToEntryEdit(Entry* entry) @@ -419,13 +427,13 @@ void DatabaseWidget::switchToEntryEdit(Entry* entry, bool create) Q_ASSERT(group); m_editEntryWidget->loadEntry(entry, create, false, group->name(), m_db); - setCurrentIndex(1); + setCurrentWidget(m_editEntryWidget); } void DatabaseWidget::switchToGroupEdit(Group* group, bool create) { m_editGroupWidget->loadGroup(group, create, m_db); - setCurrentIndex(2); + setCurrentWidget(m_editGroupWidget); } void DatabaseWidget::updateMasterKey(bool accepted) @@ -440,7 +448,7 @@ void DatabaseWidget::updateMasterKey(bool accepted) return; } - setCurrentIndex(0); + setCurrentWidget(m_mainWidget); } void DatabaseWidget::openDatabase(bool accepted) @@ -451,7 +459,7 @@ void DatabaseWidget::openDatabase(bool accepted) m_groupView->changeDatabase(m_db); Q_EMIT databaseChanged(m_db); delete oldDb; - setCurrentIndex(0); + setCurrentWidget(m_mainWidget); // We won't need those anymore and KeePass1OpenWidget closes // the file in its dtor. @@ -468,6 +476,15 @@ void DatabaseWidget::openDatabase(bool accepted) } } +void DatabaseWidget::unlockDatabase(bool accepted) +{ + // cancel button is disabled + Q_ASSERT(accepted); + + setCurrentWidget(widgetBeforeLock); + Q_EMIT unlockedDatabase(); +} + void DatabaseWidget::switchToEntryEdit() { switchToEntryEdit(m_entryView->currentEntry(), false); @@ -481,32 +498,35 @@ void DatabaseWidget::switchToGroupEdit() void DatabaseWidget::switchToMasterKeyChange() { m_changeMasterKeyWidget->clearForms(); - setCurrentIndex(3); + setCurrentWidget(m_changeMasterKeyWidget); } void DatabaseWidget::switchToDatabaseSettings() { m_databaseSettingsWidget->load(m_db); - setCurrentIndex(4); + setCurrentWidget(m_databaseSettingsWidget); } void DatabaseWidget::switchToOpenDatabase(const QString& fileName) { + updateFilename(fileName); m_databaseOpenWidget->load(fileName); - setCurrentIndex(6); + setCurrentWidget(m_databaseOpenWidget); } void DatabaseWidget::switchToOpenDatabase(const QString& fileName, const QString& password, const QString& keyFile) { + updateFilename(fileName); switchToOpenDatabase(fileName); m_databaseOpenWidget->enterKey(password, keyFile); } void DatabaseWidget::switchToImportKeepass1(const QString& fileName) { + updateFilename(fileName); m_keepass1OpenWidget->load(fileName); - setCurrentIndex(7); + setCurrentWidget(m_keepass1OpenWidget); } void DatabaseWidget::toggleSearch() @@ -641,3 +661,17 @@ void DatabaseWidget::clearLastGroup(Group* group) m_searchWidget->hide(); } } + +void DatabaseWidget::lock() +{ + Q_ASSERT(currentMode() != DatabaseWidget::LockedMode); + + widgetBeforeLock = currentWidget(); + m_unlockDatabaseWidget->load(m_filename, m_db); + setCurrentWidget(m_unlockDatabaseWidget); +} + +void DatabaseWidget::updateFilename(const QString& fileName) +{ + m_filename = fileName; +} diff --git a/src/gui/DatabaseWidget.h b/src/gui/DatabaseWidget.h index f31e4d8fe..f680f67ce 100644 --- a/src/gui/DatabaseWidget.h +++ b/src/gui/DatabaseWidget.h @@ -36,6 +36,7 @@ class GroupView; class KeePass1OpenWidget; class QFile; class QMenu; +class UnlockDatabaseWidget; namespace Ui { class SearchWidget; @@ -50,7 +51,8 @@ public: { None, ViewMode, - EditMode + EditMode, + LockedMode }; explicit DatabaseWidget(Database* db, QWidget* parent = Q_NULLPTR); @@ -63,7 +65,10 @@ public: bool isInSearchMode(); int addWidget(QWidget* w); void setCurrentIndex(int index); + void setCurrentWidget(QWidget* widget); DatabaseWidget::Mode currentMode(); + void lock(); + void updateFilename(const QString& filename); Q_SIGNALS: void closeRequest(); @@ -73,6 +78,7 @@ Q_SIGNALS: void databaseChanged(Database* newDb); void groupContextMenuRequested(const QPoint& globalPos); void entryContextMenuRequested(const QPoint& globalPos); + void unlockedDatabase(); public Q_SLOTS: void createEntry(); @@ -104,6 +110,7 @@ private Q_SLOTS: void switchToGroupEdit(Group* entry, bool create); void updateMasterKey(bool accepted); void openDatabase(bool accepted); + void unlockDatabase(bool accepted); void emitCurrentModeChanged(); void clearLastGroup(Group* group); void search(); @@ -124,6 +131,7 @@ private: DatabaseSettingsWidget* m_databaseSettingsWidget; DatabaseOpenWidget* m_databaseOpenWidget; KeePass1OpenWidget* m_keepass1OpenWidget; + UnlockDatabaseWidget* m_unlockDatabaseWidget; GroupView* m_groupView; EntryView* m_entryView; Group* m_newGroup; @@ -131,6 +139,8 @@ private: Group* m_newParent; Group* m_lastGroup; QTimer* m_searchTimer; + QWidget* widgetBeforeLock; + QString m_filename; }; #endif // KEEPASSX_DATABASEWIDGET_H diff --git a/src/gui/KeePass1OpenWidget.cpp b/src/gui/KeePass1OpenWidget.cpp index db6da050a..f167e3bb4 100644 --- a/src/gui/KeePass1OpenWidget.cpp +++ b/src/gui/KeePass1OpenWidget.cpp @@ -29,7 +29,7 @@ KeePass1OpenWidget::KeePass1OpenWidget(QWidget* parent) : DatabaseOpenWidget(parent) { - setWindowTitle(tr("Import KeePass1 database")); + m_ui->labelHeadline->setText(tr("Import KeePass1 database")); } void KeePass1OpenWidget::openDatabase() diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp index 3f8b9241d..90516f68f 100644 --- a/src/gui/MainWindow.cpp +++ b/src/gui/MainWindow.cpp @@ -63,6 +63,7 @@ MainWindow::MainWindow() setShortcut(m_ui->actionDatabaseSave, QKeySequence::Save, Qt::CTRL + Qt::Key_S); setShortcut(m_ui->actionDatabaseSaveAs, QKeySequence::SaveAs); setShortcut(m_ui->actionDatabaseClose, QKeySequence::Close, Qt::CTRL + Qt::Key_W); + m_ui->actionLockDatabases->setShortcut(Qt::CTRL + Qt::Key_L); setShortcut(m_ui->actionQuit, QKeySequence::Quit, Qt::CTRL + Qt::Key_Q); setShortcut(m_ui->actionSearch, QKeySequence::Find, Qt::CTRL + Qt::Key_F); m_ui->actionEntryNew->setShortcut(Qt::CTRL + Qt::Key_N); @@ -85,6 +86,7 @@ MainWindow::MainWindow() m_ui->actionDatabaseClose->setIcon(filePath()->icon("actions", "document-close")); m_ui->actionChangeDatabaseSettings->setIcon(filePath()->icon("actions", "document-edit")); m_ui->actionChangeMasterKey->setIcon(filePath()->icon("actions", "database-change-key", false)); + m_ui->actionLockDatabases->setIcon(filePath()->icon("actions", "document-encrypt", false)); m_ui->actionQuit->setIcon(filePath()->icon("actions", "application-exit")); m_ui->actionEntryNew->setIcon(filePath()->icon("actions", "entry-new", false)); @@ -140,6 +142,8 @@ MainWindow::MainWindow() SLOT(changeDatabaseSettings())); connect(m_ui->actionImportKeePass1, SIGNAL(triggered()), m_ui->tabWidget, SLOT(importKeePass1Database())); + connect(m_ui->actionLockDatabases, SIGNAL(triggered()), m_ui->tabWidget, + SLOT(lockDatabases())); connect(m_ui->actionQuit, SIGNAL(triggered()), SLOT(close())); m_actionMultiplexer.connect(m_ui->actionEntryNew, SIGNAL(triggered()), @@ -246,6 +250,7 @@ void MainWindow::setMenuActionState(DatabaseWidget::Mode mode) break; } case DatabaseWidget::EditMode: + case DatabaseWidget::LockedMode: Q_FOREACH (QAction* action, m_ui->menuEntries->actions()) { action->setEnabled(false); } @@ -290,6 +295,8 @@ void MainWindow::setMenuActionState(DatabaseWidget::Mode mode) m_ui->actionDatabaseOpen->setEnabled(inDatabaseTabWidgetOrWelcomeWidget); m_ui->menuRecentDatabases->setEnabled(inDatabaseTabWidgetOrWelcomeWidget); m_ui->actionImportKeePass1->setEnabled(inDatabaseTabWidgetOrWelcomeWidget); + + m_ui->actionLockDatabases->setEnabled(m_ui->tabWidget->hasLockableDatabases()); } void MainWindow::updateWindowTitle() diff --git a/src/gui/MainWindow.ui b/src/gui/MainWindow.ui index bb2b989f7..fcc862ac7 100644 --- a/src/gui/MainWindow.ui +++ b/src/gui/MainWindow.ui @@ -94,6 +94,7 @@ + @@ -328,6 +329,14 @@ Open URL + + + false + + + Lock databases + + diff --git a/src/gui/UnlockDatabaseWidget.cpp b/src/gui/UnlockDatabaseWidget.cpp new file mode 100644 index 000000000..547b35be0 --- /dev/null +++ b/src/gui/UnlockDatabaseWidget.cpp @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2012 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 "UnlockDatabaseWidget.h" + +#include + +#include "ui_DatabaseOpenWidget.h" +#include "core/Database.h" + +UnlockDatabaseWidget::UnlockDatabaseWidget(QWidget* parent) + : DatabaseOpenWidget(parent) +{ + m_ui->labelHeadline->setText(tr("Unlock database")); + + m_ui->buttonBox->removeButton(m_ui->buttonBox->button(QDialogButtonBox::Cancel)); + connect(this, SIGNAL(editFinished(bool)), SLOT(clearForms())); +} + +void UnlockDatabaseWidget::load(const QString& filename, Database* db) +{ + Q_ASSERT(db); + + DatabaseOpenWidget::load(filename); + m_db = db; +} + +void UnlockDatabaseWidget::openDatabase() +{ + CompositeKey masterKey = databaseKey(); + if (masterKey.isEmpty()) { + return; + } + + if (m_db->verifyKey(masterKey)) { + Q_EMIT editFinished(true); + } + else { + QMessageBox::warning(this, tr("Error"), tr("Wrong key.")); + m_ui->editPassword->clear(); + } +} + +void UnlockDatabaseWidget::clearForms() +{ + m_ui->editPassword->clear(); + m_ui->comboKeyFile->clear(); + m_ui->checkPassword->setChecked(false); + m_ui->checkKeyFile->setChecked(false); +} diff --git a/src/gui/UnlockDatabaseWidget.h b/src/gui/UnlockDatabaseWidget.h new file mode 100644 index 000000000..81da2245d --- /dev/null +++ b/src/gui/UnlockDatabaseWidget.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2012 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 "gui/DatabaseOpenWidget.h" + +class UnlockDatabaseWidget : public DatabaseOpenWidget +{ + Q_OBJECT + +public: + explicit UnlockDatabaseWidget(QWidget* parent = Q_NULLPTR); + void load(const QString& filename, Database* db); + +protected: + void openDatabase() Q_DECL_OVERRIDE; + +private Q_SLOTS: + void clearForms(); +}; diff --git a/tests/gui/TestGui.cpp b/tests/gui/TestGui.cpp index 5ff5f8b0f..1886e594f 100644 --- a/tests/gui/TestGui.cpp +++ b/tests/gui/TestGui.cpp @@ -336,6 +336,24 @@ void TestGui::testKeePass1Import() QCOMPARE(m_tabWidget->tabText(m_tabWidget->currentIndex()), QString("basic [New database]*")); } +void TestGui::testDatabaseLocking() +{ + triggerAction("actionLockDatabases"); + + QCOMPARE(m_tabWidget->tabText(0), QString("Save [locked]")); + QCOMPARE(m_tabWidget->tabText(1), QString("basic [New database] [locked]*")); + + QWidget* dbWidget = m_tabWidget->currentDatabaseWidget(); + QWidget* unlockDatabaseWidget = dbWidget->findChild("unlockDatabaseWidget"); + QWidget* editPassword = unlockDatabaseWidget->findChild("editPassword"); + QVERIFY(editPassword); + + QTest::keyClicks(editPassword, "masterpw"); + QTest::keyClick(editPassword, Qt::Key_Enter); + + QCOMPARE(m_tabWidget->tabText(m_tabWidget->currentIndex()), QString("basic [New database]*")); +} + void TestGui::cleanupTestCase() { delete m_mainWindow; diff --git a/tests/gui/TestGui.h b/tests/gui/TestGui.h index 69fa30d00..dbf733daa 100644 --- a/tests/gui/TestGui.h +++ b/tests/gui/TestGui.h @@ -45,6 +45,7 @@ private Q_SLOTS: void testSave(); void testDatabaseSettings(); void testKeePass1Import(); + void testDatabaseLocking(); void cleanupTestCase(); private: