Skip to content

Commit

Permalink
Choose database for saving or updating entries from KeePassXC-Browser (
Browse files Browse the repository at this point in the history
  • Loading branch information
Sami Vänttinen authored and droidmonkey committed Oct 19, 2018
1 parent bb16dc6 commit b8d2d5d
Show file tree
Hide file tree
Showing 13 changed files with 307 additions and 22 deletions.
16 changes: 8 additions & 8 deletions src/browser/BrowserAccessControlDialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,13 @@

BrowserAccessControlDialog::BrowserAccessControlDialog(QWidget* parent)
: QDialog(parent)
, ui(new Ui::BrowserAccessControlDialog())
, m_ui(new Ui::BrowserAccessControlDialog())
{
this->setWindowFlags(windowFlags() | Qt::WindowStaysOnTopHint);

ui->setupUi(this);
connect(ui->allowButton, SIGNAL(clicked()), this, SLOT(accept()));
connect(ui->denyButton, SIGNAL(clicked()), this, SLOT(reject()));
m_ui->setupUi(this);
connect(m_ui->allowButton, SIGNAL(clicked()), this, SLOT(accept()));
connect(m_ui->denyButton, SIGNAL(clicked()), this, SLOT(reject()));
}

BrowserAccessControlDialog::~BrowserAccessControlDialog()
Expand All @@ -37,24 +37,24 @@ 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"
m_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 BrowserAccessControlDialog::setItems(const QList<Entry*>& items)
{
for (Entry* entry : items) {
ui->itemsList->addItem(entry->title() + " - " + entry->username());
m_ui->itemsList->addItem(entry->title() + " - " + entry->username());
}
}

bool BrowserAccessControlDialog::remember() const
{
return ui->rememberDecisionCheckBox->isChecked();
return m_ui->rememberDecisionCheckBox->isChecked();
}

void BrowserAccessControlDialog::setRemember(bool r)
{
ui->rememberDecisionCheckBox->setChecked(r);
m_ui->rememberDecisionCheckBox->setChecked(r);
}
2 changes: 1 addition & 1 deletion src/browser/BrowserAccessControlDialog.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class BrowserAccessControlDialog : public QDialog
void setRemember(bool r);

private:
QScopedPointer<Ui::BrowserAccessControlDialog> ui;
QScopedPointer<Ui::BrowserAccessControlDialog> m_ui;
};

#endif // BROWSERACCESSCONTROLDIALOG_H
2 changes: 1 addition & 1 deletion src/browser/BrowserAction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ QJsonObject BrowserAction::handleSetLogin(const QJsonObject& json, const QString
if (uuid.isEmpty()) {
m_browserService.addEntry(id, login, password, url, submitUrl, realm);
} else {
m_browserService.updateEntry(id, uuid, login, password, url);
m_browserService.updateEntry(id, uuid, login, password, url, submitUrl);
}

const QString newNonce = incrementNonce(nonce);
Expand Down
79 changes: 79 additions & 0 deletions src/browser/BrowserEntrySaveDialog.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*
* Copyright (C) 2013 Francois Ferrand
* Copyright (C) 2018 KeePassXC Team <[email protected]>
*
* 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 3 of the License, or
* (at your option) any later version.
*
* 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 <http://www.gnu.org/licenses/>.
*/

#include "BrowserEntrySaveDialog.h"
#include "ui_BrowserEntrySaveDialog.h"

BrowserEntrySaveDialog::BrowserEntrySaveDialog(QWidget* parent)
: QDialog(parent)
, m_ui(new Ui::BrowserEntrySaveDialog())
{
this->setWindowFlags(windowFlags() | Qt::WindowStaysOnTopHint);

m_ui->setupUi(this);
connect(m_ui->okButton, SIGNAL(clicked()), this, SLOT(accept()));
connect(m_ui->cancelButton, SIGNAL(clicked()), this, SLOT(reject()));

m_ui->itemsList->setSelectionMode(QAbstractItemView::SingleSelection);
m_ui->label->setText(QString(tr("You have multiple databases open.\n"
"Please select the correct database for saving credentials.")));
}

BrowserEntrySaveDialog::~BrowserEntrySaveDialog()
{
}

int BrowserEntrySaveDialog::setItems(QList<DatabaseWidget*>& databaseWidgets, DatabaseWidget* currentWidget) const
{
uint counter = 0;
int activeIndex = -1;
for (const auto dbWidget : databaseWidgets) {
QString databaseName = dbWidget->getDatabaseName();
QString databaseFileName = dbWidget->getDatabaseFileName();

QListWidgetItem* item = new QListWidgetItem();
item->setData(Qt::UserRole, counter);

// Show database name (and filename if the name has been set in metadata)
if (databaseName == databaseFileName) {
item->setText(databaseFileName);
} else {
item->setText(QString("%1 (%2)").arg(databaseName, databaseFileName));
}

if (currentWidget == dbWidget) {
activeIndex = counter;
}

m_ui->itemsList->addItem(item);
++counter;
}

// This must be done after the whole list is filled
if (activeIndex >= 0) {
m_ui->itemsList->item(activeIndex)->setSelected(true);
}

m_ui->itemsList->selectAll();
return databaseWidgets.length();
}

QList<QListWidgetItem*> BrowserEntrySaveDialog::getSelected() const
{
return m_ui->itemsList->selectedItems();
}
49 changes: 49 additions & 0 deletions src/browser/BrowserEntrySaveDialog.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* Copyright (C) 2013 Francois Ferrand
* Copyright (C) 2018 KeePassXC Team <[email protected]>
*
* 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 3 of the License, or
* (at your option) any later version.
*
* 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 <http://www.gnu.org/licenses/>.
*/

#ifndef BROWSERENTRYSAVEDIALOG_H
#define BROWSERENTRYSAVEDIALOG_H

#include <QDialog>
#include <QScopedPointer>
#include <QListWidgetItem>
#include "gui/DatabaseTabWidget.h"

class Entry;

namespace Ui
{
class BrowserEntrySaveDialog;
}

class BrowserEntrySaveDialog : public QDialog
{
Q_OBJECT

public:
explicit BrowserEntrySaveDialog(QWidget* parent = nullptr);
~BrowserEntrySaveDialog() override;

int setItems(QList<DatabaseWidget*>& databaseWidgets, DatabaseWidget* currentWidget) const;
QList<QListWidgetItem *> getSelected() const;

private:
QScopedPointer<Ui::BrowserEntrySaveDialog> m_ui;
};

#endif // BROWSERENTRYSAVEDIALOG_H
62 changes: 62 additions & 0 deletions src/browser/BrowserEntrySaveDialog.ui
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>BrowserEntrySaveDialog</class>
<widget class="QDialog" name="BrowserEntrySaveDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>221</height>
</rect>
</property>
<property name="windowTitle">
<string>KeePassXC-Browser Save Entry</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<widget class="QListWidget" name="itemsList"/>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="okButton">
<property name="text">
<string>Ok</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="cancelButton">
<property name="text">
<string>Cancel</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
76 changes: 68 additions & 8 deletions src/browser/BrowserService.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "BrowserService.h"
#include "BrowserAccessControlDialog.h"
#include "BrowserEntryConfig.h"
#include "BrowserEntrySaveDialog.h"
#include "BrowserSettings.h"
#include "core/Database.h"
#include "core/EntrySearcher.h"
Expand Down Expand Up @@ -289,14 +290,33 @@ QJsonArray BrowserService::findMatchingEntries(const QString& id,
return result;
}

void BrowserService::addEntry(const QString&,
void BrowserService::addEntry(const QString& id,
const QString& login,
const QString& password,
const QString& url,
const QString& submitUrl,
const QString& realm)
const QString& realm,
Database* selectedDb)
{
Group* group = findCreateAddEntryGroup();
if (thread() != QThread::currentThread()) {
QMetaObject::invokeMethod(this,
"addEntry",
Qt::BlockingQueuedConnection,
Q_ARG(const QString&, id),
Q_ARG(const QString&, login),
Q_ARG(const QString&, password),
Q_ARG(const QString&, url),
Q_ARG(const QString&, submitUrl),
Q_ARG(const QString&, realm),
Q_ARG(Database*, selectedDb));
}

Database* db = selectedDb ? selectedDb : selectedDatabase();
if (!db) {
return;
}

Group* group = findCreateAddEntryGroup(db);
if (!group) {
return;
}
Expand Down Expand Up @@ -328,7 +348,8 @@ void BrowserService::updateEntry(const QString& id,
const QString& uuid,
const QString& login,
const QString& password,
const QString& url)
const QString& url,
const QString& submitUrl)
{
if (thread() != QThread::currentThread()) {
QMetaObject::invokeMethod(this,
Expand All @@ -338,16 +359,19 @@ void BrowserService::updateEntry(const QString& id,
Q_ARG(const QString&, uuid),
Q_ARG(const QString&, login),
Q_ARG(const QString&, password),
Q_ARG(const QString&, url));
Q_ARG(const QString&, url),
Q_ARG(const QString&, submitUrl));
}

Database* db = getDatabase();
Database* db = selectedDatabase();
if (!db) {
return;
}

Entry* entry = db->resolveEntry(QUuid::fromRfc4122(QByteArray::fromHex(uuid.toLatin1())));
if (!entry) {
// If entry is not found for update, add a new one to the selected database
addEntry(id, login, password, url, submitUrl, "", db);
return;
}

Expand Down Expand Up @@ -679,9 +703,9 @@ BrowserService::checkAccess(const Entry* entry, const QString& host, const QStri
return Unknown;
}

Group* BrowserService::findCreateAddEntryGroup()
Group* BrowserService::findCreateAddEntryGroup(Database* selectedDb)
{
Database* db = getDatabase();
Database* db = selectedDb ? selectedDb : getDatabase();
if (!db) {
return nullptr;
}
Expand Down Expand Up @@ -813,6 +837,42 @@ Database* BrowserService::getDatabase()
return nullptr;
}

Database* BrowserService::selectedDatabase()
{
QList<DatabaseWidget*> databaseWidgets;
for (int i = 0;; ++i) {
const auto dbStruct = m_dbTabWidget->indexDatabaseManagerStruct(i);
// Add only open databases
if (dbStruct.dbWidget && dbStruct.dbWidget->dbHasKey() &&
(dbStruct.dbWidget->currentMode() == DatabaseWidget::ViewMode ||
dbStruct.dbWidget->currentMode() == DatabaseWidget::EditMode)) {
databaseWidgets.push_back(dbStruct.dbWidget);
continue;
}

// Break out if dbStruct.dbWidget is nullptr
break;
}

BrowserEntrySaveDialog browserEntrySaveDialog;
int openDatabaseCount = browserEntrySaveDialog.setItems(databaseWidgets, m_dbTabWidget->currentDatabaseWidget());
if (openDatabaseCount > 1) {
int res = browserEntrySaveDialog.exec();
if (res == QDialog::Accepted) {
const auto selectedDatabase = browserEntrySaveDialog.getSelected();
if (selectedDatabase.length() > 0) {
int index = selectedDatabase[0]->data(Qt::UserRole).toUInt();
return databaseWidgets[index]->database();
}
} else {
return nullptr;
}
}

// Return current database
return getDatabase();
}

void BrowserService::databaseLocked(DatabaseWidget* dbWidget)
{
if (dbWidget) {
Expand Down
Loading

0 comments on commit b8d2d5d

Please sign in to comment.