diff options
Diffstat (limited to 'src/gui/DatabaseOpenWidget.cpp')
-rw-r--r-- | src/gui/DatabaseOpenWidget.cpp | 146 |
1 files changed, 89 insertions, 57 deletions
diff --git a/src/gui/DatabaseOpenWidget.cpp b/src/gui/DatabaseOpenWidget.cpp index ced72485e..1cadc5e21 100644 --- a/src/gui/DatabaseOpenWidget.cpp +++ b/src/gui/DatabaseOpenWidget.cpp @@ -34,6 +34,8 @@ #include "config-keepassx.h" +#include <QDesktopServices> +#include <QFont> #include <QSharedPointer> #include <QtConcurrentRun> @@ -46,21 +48,30 @@ DatabaseOpenWidget::DatabaseOpenWidget(QWidget* parent) m_ui->messageWidget->setHidden(true); - QFont font = m_ui->labelHeadline->font(); + QFont font; + font.setPointSize(font.pointSize() + 4); font.setBold(true); - font.setPointSize(font.pointSize() + 2); m_ui->labelHeadline->setFont(font); + m_ui->labelHeadline->setText(tr("Unlock KeePassXC Database")); + + m_ui->comboKeyFile->lineEdit()->addAction(m_ui->keyFileClearIcon, QLineEdit::TrailingPosition); 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->buttonBrowseFile, SIGNAL(clicked()), SLOT(browseKeyFile())); - connect(m_ui->editPassword, SIGNAL(textChanged(QString)), SLOT(activatePassword())); - connect(m_ui->comboKeyFile, SIGNAL(editTextChanged(QString)), SLOT(activateKeyFile())); - connect(m_ui->buttonBox, SIGNAL(accepted()), SLOT(openDatabase())); connect(m_ui->buttonBox, SIGNAL(rejected()), SLOT(reject())); + m_ui->hardwareKeyLabelHelp->setIcon(filePath()->icon("actions", "system-help").pixmap(QSize(12, 12))); + connect(m_ui->hardwareKeyLabelHelp, SIGNAL(clicked(bool)), SLOT(openHardwareKeyHelp())); + + connect(m_ui->comboKeyFile->lineEdit(), SIGNAL(textChanged(QString)), SLOT(handleKeyFileComboEdited())); + connect(m_ui->comboKeyFile, SIGNAL(currentIndexChanged(int)), SLOT(handleKeyFileComboChanged())); + m_ui->keyFileClearIcon->setIcon(filePath()->icon("actions", "edit-clear-locationbar-rtl")); + m_ui->keyFileClearIcon->setVisible(false); + connect(m_ui->keyFileClearIcon, SIGNAL(triggered(bool)), SLOT(clearKeyFileEdit())); + #ifdef WITH_XC_YUBIKEY m_ui->yubikeyProgress->setVisible(false); QSizePolicy sp = m_ui->yubikeyProgress->sizePolicy(); @@ -68,9 +79,9 @@ DatabaseOpenWidget::DatabaseOpenWidget(QWidget* parent) m_ui->yubikeyProgress->setSizePolicy(sp); connect(m_ui->buttonRedetectYubikey, SIGNAL(clicked()), SLOT(pollYubikey())); - connect(m_ui->comboChallengeResponse, SIGNAL(activated(int)), SLOT(activateChallengeResponse())); #else - m_ui->checkChallengeResponse->setVisible(false); + m_ui->hardwareKeyLabel->setVisible(false); + m_ui->hardwareKeyLabelHelp->setVisible(false); m_ui->buttonRedetectYubikey->setVisible(false); m_ui->comboChallengeResponse->setVisible(false); m_ui->yubikeyProgress->setVisible(false); @@ -80,11 +91,10 @@ DatabaseOpenWidget::DatabaseOpenWidget(QWidget* parent) // add random padding to layouts to align widgets properly m_ui->dialogButtonsLayout->setContentsMargins(10, 0, 15, 0); m_ui->gridLayout->setContentsMargins(10, 0, 0, 0); - m_ui->labelLayout->setContentsMargins(10, 0, 10, 0); #endif #ifndef WITH_XC_TOUCHID - m_ui->checkTouchID->setVisible(false); + m_ui->touchIDContainer->setVisible(false); #else if (!TouchID::getInstance().isAvailable()) { m_ui->checkTouchID->setVisible(false); @@ -136,14 +146,18 @@ void DatabaseOpenWidget::hideEvent(QHideEvent* event) void DatabaseOpenWidget::load(const QString& filename) { m_filename = filename; + m_ui->fileNameLabel->setRawText(m_filename); - m_ui->labelFilename->setText(filename); + m_ui->comboKeyFile->addItem(tr("Select file..."), -1); + m_ui->comboKeyFile->setCurrentIndex(0); + m_ui->keyFileClearIcon->setVisible(false); + m_keyFileComboEdited = false; if (config()->get("RememberLastKeyFiles").toBool()) { QHash<QString, QVariant> lastKeyFiles = config()->get("LastKeyFiles").toHash(); if (lastKeyFiles.contains(m_filename)) { - m_ui->checkKeyFile->setChecked(true); m_ui->comboKeyFile->addItem(lastKeyFiles[m_filename].toString()); + m_ui->comboKeyFile->setCurrentIndex(1); } } @@ -158,9 +172,6 @@ void DatabaseOpenWidget::clearForms() m_ui->editPassword->setText(""); m_ui->comboKeyFile->clear(); m_ui->comboKeyFile->setEditText(""); - m_ui->checkPassword->setChecked(false); - m_ui->checkKeyFile->setChecked(false); - m_ui->checkChallengeResponse->setChecked(false); m_ui->checkTouchID->setChecked(false); m_ui->buttonTogglePassword->setChecked(false); m_db.reset(); @@ -174,6 +185,7 @@ QSharedPointer<Database> DatabaseOpenWidget::database() void DatabaseOpenWidget::enterKey(const QString& pw, const QString& keyFile) { m_ui->editPassword->setText(pw); + m_ui->comboKeyFile->setCurrentIndex(-1); m_ui->comboKeyFile->setEditText(keyFile); openDatabase(); } @@ -186,6 +198,7 @@ void DatabaseOpenWidget::openDatabase() } m_ui->editPassword->setShowPassword(false); + m_ui->buttonTogglePassword->setChecked(false); QCoreApplication::processEvents(); m_db.reset(new Database()); @@ -194,6 +207,26 @@ void DatabaseOpenWidget::openDatabase() bool ok = m_db->open(m_filename, masterKey, &error, false); QApplication::restoreOverrideCursor(); if (!ok) { + if (m_ui->editPassword->text().isEmpty() && !m_retryUnlockWithEmptyPassword) { + QScopedPointer<QMessageBox> msgBox(new QMessageBox(this)); + msgBox->setIcon(QMessageBox::Critical); + msgBox->setWindowTitle(tr("Unlock failed and no password given")); + msgBox->setText(tr("Unlocking the database failed and you did not enter a password.\n" + "Do you want to retry with an \"empty\" password instead?\n\n" + "To prevent this error from appearing, you must go to " + "\"Database Settings / Security\" and reset your password.")); + auto btn = msgBox->addButton(tr("Retry with empty password"), QMessageBox::ButtonRole::AcceptRole); + msgBox->setDefaultButton(btn); + msgBox->addButton(QMessageBox::Cancel); + msgBox->exec(); + + if (msgBox->clickedButton() == btn) { + m_retryUnlockWithEmptyPassword = true; + openDatabase(); + return; + } + } + m_retryUnlockWithEmptyPassword = false; m_ui->messageWidget->showMessage(error, MessageWidget::MessageType::Error); return; } @@ -236,7 +269,7 @@ QSharedPointer<CompositeKey> DatabaseOpenWidget::databaseKey() { auto masterKey = QSharedPointer<CompositeKey>::create(); - if (m_ui->checkPassword->isChecked()) { + if (!m_ui->editPassword->text().isEmpty() || m_retryUnlockWithEmptyPassword) { masterKey->addKey(QSharedPointer<PasswordKey>::create(m_ui->editPassword->text())); } @@ -260,11 +293,11 @@ QSharedPointer<CompositeKey> DatabaseOpenWidget::databaseKey() #endif QHash<QString, QVariant> lastKeyFiles = config()->get("LastKeyFiles").toHash(); - QHash<QString, QVariant> lastChallengeResponse = config()->get("LastChallengeResponse").toHash(); + lastKeyFiles.remove(m_filename); - if (m_ui->checkKeyFile->isChecked()) { - auto key = QSharedPointer<FileKey>::create(); - QString keyFilename = m_ui->comboKeyFile->currentText(); + auto key = QSharedPointer<FileKey>::create(); + QString keyFilename = m_ui->comboKeyFile->currentText(); + if (!m_ui->comboKeyFile->currentText().isEmpty() && m_keyFileComboEdited) { QString errorMsg; if (!key->load(keyFilename, &errorMsg)) { m_ui->messageWidget->showMessage(tr("Failed to open key file: %1").arg(errorMsg), MessageWidget::Error); @@ -289,14 +322,6 @@ QSharedPointer<CompositeKey> DatabaseOpenWidget::databaseKey() } masterKey->addKey(key); lastKeyFiles[m_filename] = keyFilename; - } else { - lastKeyFiles.remove(m_filename); - } - - if (m_ui->checkChallengeResponse->isChecked()) { - lastChallengeResponse[m_filename] = true; - } else { - lastChallengeResponse.remove(m_filename); } if (config()->get("RememberLastKeyFiles").toBool()) { @@ -304,19 +329,23 @@ QSharedPointer<CompositeKey> DatabaseOpenWidget::databaseKey() } #ifdef WITH_XC_YUBIKEY - if (config()->get("RememberLastKeyFiles").toBool()) { - config()->set("LastChallengeResponse", lastChallengeResponse); - } + QHash<QString, QVariant> lastChallengeResponse = config()->get("LastChallengeResponse").toHash(); + lastChallengeResponse.remove(m_filename); - if (m_ui->checkChallengeResponse->isChecked()) { - int selectionIndex = m_ui->comboChallengeResponse->currentIndex(); + int selectionIndex = m_ui->comboChallengeResponse->currentIndex(); + if (selectionIndex > 0) { int comboPayload = m_ui->comboChallengeResponse->itemData(selectionIndex).toInt(); // read blocking mode from LSB and slot index number from second LSB bool blocking = comboPayload & 1; int slot = comboPayload >> 1; - auto key = QSharedPointer<YkChallengeResponseKey>(new YkChallengeResponseKey(slot, blocking)); - masterKey->addChallengeResponseKey(key); + auto crKey = QSharedPointer<YkChallengeResponseKey>(new YkChallengeResponseKey(slot, blocking)); + masterKey->addChallengeResponseKey(crKey); + lastChallengeResponse[m_filename] = true; + } + + if (config()->get("RememberLastKeyFiles").toBool()) { + config()->set("LastChallengeResponse", lastChallengeResponse); } #endif @@ -328,24 +357,6 @@ void DatabaseOpenWidget::reject() emit dialogFinished(false); } -void DatabaseOpenWidget::activatePassword() -{ - bool hasPassword = !m_ui->editPassword->text().isEmpty(); - m_ui->checkPassword->setChecked(hasPassword); -} - -void DatabaseOpenWidget::activateKeyFile() -{ - bool hasKeyFile = !m_ui->comboKeyFile->lineEdit()->text().isEmpty(); - m_ui->checkKeyFile->setChecked(hasKeyFile); -} - -void DatabaseOpenWidget::activateChallengeResponse() -{ - bool hasCR = m_ui->comboChallengeResponse->currentData().toInt() != -1; - m_ui->checkChallengeResponse->setChecked(hasCR); -} - void DatabaseOpenWidget::browseKeyFile() { QString filters = QString("%1 (*);;%2 (*.key)").arg(tr("All files"), tr("Key files")); @@ -355,15 +366,33 @@ void DatabaseOpenWidget::browseKeyFile() QString filename = fileDialog()->getOpenFileName(this, tr("Select key file"), QString(), filters); if (!filename.isEmpty()) { - m_ui->comboKeyFile->lineEdit()->setText(filename); + m_ui->comboKeyFile->setCurrentIndex(-1); + m_ui->comboKeyFile->setEditText(filename); } } +void DatabaseOpenWidget::clearKeyFileEdit() +{ + m_ui->comboKeyFile->setCurrentIndex(0); + // make sure that handler is called even if 0 was the current index already + handleKeyFileComboChanged(); +} + +void DatabaseOpenWidget::handleKeyFileComboEdited() +{ + m_keyFileComboEdited = true; + m_ui->keyFileClearIcon->setVisible(true); +} + +void DatabaseOpenWidget::handleKeyFileComboChanged() +{ + m_keyFileComboEdited = m_ui->comboKeyFile->currentIndex() != 0; + m_ui->keyFileClearIcon->setVisible(m_keyFileComboEdited); +} + void DatabaseOpenWidget::pollYubikey() { m_ui->buttonRedetectYubikey->setEnabled(false); - m_ui->checkChallengeResponse->setEnabled(false); - m_ui->checkChallengeResponse->setChecked(false); m_ui->comboChallengeResponse->setEnabled(false); m_ui->comboChallengeResponse->clear(); m_ui->comboChallengeResponse->addItem(tr("Select slot..."), -1); @@ -382,7 +411,6 @@ void DatabaseOpenWidget::yubikeyDetected(int slot, bool blocking) if (config()->get("RememberLastKeyFiles").toBool()) { QHash<QString, QVariant> lastChallengeResponse = config()->get("LastChallengeResponse").toHash(); if (lastChallengeResponse.contains(m_filename)) { - m_ui->checkChallengeResponse->setChecked(true); m_ui->comboChallengeResponse->setCurrentIndex(1); } } @@ -391,7 +419,6 @@ void DatabaseOpenWidget::yubikeyDetected(int slot, bool blocking) void DatabaseOpenWidget::yubikeyDetectComplete() { m_ui->comboChallengeResponse->setEnabled(true); - m_ui->checkChallengeResponse->setEnabled(true); m_ui->buttonRedetectYubikey->setEnabled(true); m_ui->yubikeyProgress->setVisible(false); m_yubiKeyBeingPolled = false; @@ -403,3 +430,8 @@ void DatabaseOpenWidget::noYubikeyFound() m_ui->yubikeyProgress->setVisible(false); m_yubiKeyBeingPolled = false; } + +void DatabaseOpenWidget::openHardwareKeyHelp() +{ + QDesktopServices::openUrl(QUrl("https://keepassxc.org/docs#hwtoken")); +}
\ No newline at end of file |