mirror of
https://github.com/keepassxreboot/keepassxc.git
synced 2024-12-25 15:29:44 -05:00
Choose database for saving or updating entries from KeePassXC-Browser (#2391)
This commit is contained in:
parent
bb16dc6d01
commit
b8d2d5d877
@ -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()
|
||||
@ -37,7 +37,7 @@ 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()));
|
||||
}
|
||||
@ -45,16 +45,16 @@ void BrowserAccessControlDialog::setUrl(const QString& url)
|
||||
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);
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ public:
|
||||
void setRemember(bool r);
|
||||
|
||||
private:
|
||||
QScopedPointer<Ui::BrowserAccessControlDialog> ui;
|
||||
QScopedPointer<Ui::BrowserAccessControlDialog> m_ui;
|
||||
};
|
||||
|
||||
#endif // BROWSERACCESSCONTROLDIALOG_H
|
||||
|
@ -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);
|
||||
|
79
src/browser/BrowserEntrySaveDialog.cpp
Normal file
79
src/browser/BrowserEntrySaveDialog.cpp
Normal file
@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Francois Ferrand
|
||||
* Copyright (C) 2018 KeePassXC Team <team@keepassxc.org>
|
||||
*
|
||||
* 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
src/browser/BrowserEntrySaveDialog.h
Normal file
49
src/browser/BrowserEntrySaveDialog.h
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Francois Ferrand
|
||||
* Copyright (C) 2018 KeePassXC Team <team@keepassxc.org>
|
||||
*
|
||||
* 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
src/browser/BrowserEntrySaveDialog.ui
Executable file
62
src/browser/BrowserEntrySaveDialog.ui
Executable file
@ -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>
|
@ -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"
|
||||
@ -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;
|
||||
}
|
||||
@ -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,
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
@ -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) {
|
||||
|
@ -51,7 +51,8 @@ public:
|
||||
const QString& password,
|
||||
const QString& url,
|
||||
const QString& submitUrl,
|
||||
const QString& realm);
|
||||
const QString& realm,
|
||||
Database* selectedDb = nullptr);
|
||||
QList<Entry*> searchEntries(Database* db, const QString& hostname, const QString& url);
|
||||
QList<Entry*> searchEntries(const QString& url, const StringPairList& keyList);
|
||||
void removeSharedEncryptionKeys();
|
||||
@ -68,7 +69,8 @@ public slots:
|
||||
const QString& uuid,
|
||||
const QString& login,
|
||||
const QString& password,
|
||||
const QString& url);
|
||||
const QString& url,
|
||||
const QString& submitUrl);
|
||||
void databaseLocked(DatabaseWidget* dbWidget);
|
||||
void databaseUnlocked(DatabaseWidget* dbWidget);
|
||||
void activateDatabaseChanged(DatabaseWidget* dbWidget);
|
||||
@ -96,13 +98,14 @@ private:
|
||||
const QString& realm);
|
||||
QJsonObject prepareEntry(const Entry* entry);
|
||||
Access checkAccess(const Entry* entry, const QString& host, const QString& submitHost, const QString& realm);
|
||||
Group* findCreateAddEntryGroup();
|
||||
Group* findCreateAddEntryGroup(Database* selectedDb = nullptr);
|
||||
int
|
||||
sortPriority(const Entry* entry, const QString& host, const QString& submitUrl, const QString& baseSubmitUrl) const;
|
||||
bool matchUrlScheme(const QString& url);
|
||||
bool removeFirstDomain(QString& hostname);
|
||||
QString baseDomain(const QString& url) const;
|
||||
Database* getDatabase();
|
||||
Database* selectedDatabase();
|
||||
|
||||
private:
|
||||
DatabaseTabWidget* const m_dbTabWidget;
|
||||
|
@ -23,6 +23,7 @@ if(WITH_XC_BROWSER)
|
||||
BrowserAction.cpp
|
||||
BrowserClients.cpp
|
||||
BrowserEntryConfig.cpp
|
||||
BrowserEntrySaveDialog.cpp
|
||||
BrowserOptionDialog.cpp
|
||||
BrowserService.cpp
|
||||
BrowserSettings.cpp
|
||||
|
@ -555,6 +555,7 @@ void DatabaseTabWidget::updateTabName(Database* db)
|
||||
const DatabaseManagerStruct& dbStruct = m_dbList.value(db);
|
||||
|
||||
QString tabName;
|
||||
QString fileName;
|
||||
|
||||
if (dbStruct.fileInfo.exists()) {
|
||||
if (db->metadata()->name().isEmpty()) {
|
||||
@ -563,6 +564,7 @@ void DatabaseTabWidget::updateTabName(Database* db)
|
||||
tabName = db->metadata()->name();
|
||||
}
|
||||
|
||||
fileName = dbStruct.fileInfo.fileName();
|
||||
setTabToolTip(index, dbStruct.fileInfo.absoluteFilePath());
|
||||
} else {
|
||||
if (db->metadata()->name().isEmpty()) {
|
||||
@ -580,6 +582,9 @@ void DatabaseTabWidget::updateTabName(Database* db)
|
||||
tabName.append("*");
|
||||
}
|
||||
|
||||
dbStruct.dbWidget->setDatabaseName(tabName);
|
||||
dbStruct.dbWidget->setDatabaseFileName(fileName);
|
||||
|
||||
setTabText(index, tabName);
|
||||
emit tabNameChanged();
|
||||
}
|
||||
|
@ -56,6 +56,7 @@ public:
|
||||
void mergeDatabase(const QString& fileName);
|
||||
DatabaseWidget* currentDatabaseWidget();
|
||||
bool hasLockableDatabases() const;
|
||||
DatabaseManagerStruct indexDatabaseManagerStruct(int index);
|
||||
|
||||
static const int LastDatabasesCount;
|
||||
|
||||
@ -110,7 +111,6 @@ private:
|
||||
void deleteDatabase(Database* db);
|
||||
int databaseIndex(Database* db);
|
||||
Database* indexDatabase(int index);
|
||||
DatabaseManagerStruct indexDatabaseManagerStruct(int index);
|
||||
Database* databaseFromDatabaseWidget(DatabaseWidget* dbWidget);
|
||||
void insertDatabase(Database* db, const DatabaseManagerStruct& dbStruct);
|
||||
void updateLastDatabases(const QString& filename);
|
||||
|
@ -1487,6 +1487,26 @@ bool DatabaseWidget::isRecycleBinSelected() const
|
||||
return m_groupView->currentGroup() && m_groupView->currentGroup() == m_db->metadata()->recycleBin();
|
||||
}
|
||||
|
||||
QString DatabaseWidget::getDatabaseName() const
|
||||
{
|
||||
return m_databaseName;
|
||||
}
|
||||
|
||||
void DatabaseWidget::setDatabaseName(const QString& databaseName)
|
||||
{
|
||||
m_databaseName = databaseName;
|
||||
}
|
||||
|
||||
QString DatabaseWidget::getDatabaseFileName() const
|
||||
{
|
||||
return m_databaseFileName;
|
||||
}
|
||||
|
||||
void DatabaseWidget::setDatabaseFileName(const QString& databaseFileName)
|
||||
{
|
||||
m_databaseFileName = databaseFileName;
|
||||
}
|
||||
|
||||
void DatabaseWidget::emptyRecycleBin()
|
||||
{
|
||||
if (!isRecycleBinSelected()) {
|
||||
|
@ -112,6 +112,10 @@ public:
|
||||
void blockAutoReload(bool block = true);
|
||||
void refreshSearch();
|
||||
bool isRecycleBinSelected() const;
|
||||
QString getDatabaseName() const;
|
||||
void setDatabaseName(const QString& databaseName);
|
||||
QString getDatabaseFileName() const;
|
||||
void setDatabaseFileName(const QString& databaseFileName);
|
||||
|
||||
signals:
|
||||
void closeRequest();
|
||||
@ -238,6 +242,8 @@ private:
|
||||
QUuid m_entryBeforeLock;
|
||||
MessageWidget* m_messageWidget;
|
||||
EntryPreviewWidget* m_previewView;
|
||||
QString m_databaseName;
|
||||
QString m_databaseFileName;
|
||||
|
||||
// Search state
|
||||
QString m_lastSearchText;
|
||||
|
Loading…
Reference in New Issue
Block a user