mirror of
https://github.com/keepassxreboot/keepassxc.git
synced 2024-10-01 01:26:01 -04:00
Browser connection keys and rules are stored in custom data instead of attributes (#1497)
This commit is contained in:
parent
cfa1eca249
commit
efdb43dc53
@ -222,6 +222,7 @@ add_subdirectory(browser)
|
|||||||
add_subdirectory(proxy)
|
add_subdirectory(proxy)
|
||||||
if(WITH_XC_BROWSER)
|
if(WITH_XC_BROWSER)
|
||||||
set(keepassxcbrowser_LIB keepassxcbrowser)
|
set(keepassxcbrowser_LIB keepassxcbrowser)
|
||||||
|
set(keepassx_SOURCES ${keepassx_SOURCES} gui/dbsettings/DatabaseSettingsWidgetBrowser.cpp)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_subdirectory(autotype)
|
add_subdirectory(autotype)
|
||||||
|
@ -566,15 +566,3 @@ QString BrowserAction::incrementNonce(const QString& nonce)
|
|||||||
sodium_increment(n.data(), n.size());
|
sodium_increment(n.data(), n.size());
|
||||||
return getQByteArray(n.data(), n.size()).toBase64();
|
return getQByteArray(n.data(), n.size()).toBase64();
|
||||||
}
|
}
|
||||||
|
|
||||||
void BrowserAction::removeSharedEncryptionKeys()
|
|
||||||
{
|
|
||||||
QMutexLocker locker(&m_mutex);
|
|
||||||
m_browserService.removeSharedEncryptionKeys();
|
|
||||||
}
|
|
||||||
|
|
||||||
void BrowserAction::removeStoredPermissions()
|
|
||||||
{
|
|
||||||
QMutexLocker locker(&m_mutex);
|
|
||||||
m_browserService.removeStoredPermissions();
|
|
||||||
}
|
|
||||||
|
@ -54,10 +54,6 @@ public:
|
|||||||
|
|
||||||
QJsonObject readResponse(const QJsonObject& json);
|
QJsonObject readResponse(const QJsonObject& json);
|
||||||
|
|
||||||
public slots:
|
|
||||||
void removeSharedEncryptionKeys();
|
|
||||||
void removeStoredPermissions();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QJsonObject handleAction(const QJsonObject& json);
|
QJsonObject handleAction(const QJsonObject& json);
|
||||||
QJsonObject handleChangePublicKeys(const QJsonObject& json, const QString& action);
|
QJsonObject handleChangePublicKeys(const QJsonObject& json, const QString& action);
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
#include "core/EntryAttributes.h"
|
#include "core/EntryAttributes.h"
|
||||||
#include <QtCore>
|
#include <QtCore>
|
||||||
|
|
||||||
static const char KEEPASSBROWSER_NAME[] = "KeePassXC-Browser Settings";
|
static const char KEEPASSXCBROWSER_NAME[] = "KeePassXC-Browser Settings";
|
||||||
|
|
||||||
BrowserEntryConfig::BrowserEntryConfig(QObject* parent)
|
BrowserEntryConfig::BrowserEntryConfig(QObject* parent)
|
||||||
: QObject(parent)
|
: QObject(parent)
|
||||||
@ -82,7 +82,7 @@ void BrowserEntryConfig::setRealm(const QString& realm)
|
|||||||
|
|
||||||
bool BrowserEntryConfig::load(const Entry* entry)
|
bool BrowserEntryConfig::load(const Entry* entry)
|
||||||
{
|
{
|
||||||
QString s = entry->attributes()->value(KEEPASSBROWSER_NAME);
|
QString s = entry->customData()->value(KEEPASSXCBROWSER_NAME);
|
||||||
if (s.isEmpty()) {
|
if (s.isEmpty()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -104,5 +104,5 @@ void BrowserEntryConfig::save(Entry* entry)
|
|||||||
QVariantMap v = qo2qv(this);
|
QVariantMap v = qo2qv(this);
|
||||||
QJsonObject o = QJsonObject::fromVariantMap(v);
|
QJsonObject o = QJsonObject::fromVariantMap(v);
|
||||||
QByteArray json = QJsonDocument(o).toJson(QJsonDocument::Compact);
|
QByteArray json = QJsonDocument(o).toJson(QJsonDocument::Compact);
|
||||||
entry->attributes()->set(KEEPASSBROWSER_NAME, json);
|
entry->customData()->set(KEEPASSXCBROWSER_NAME, json);
|
||||||
}
|
}
|
||||||
|
@ -24,15 +24,12 @@
|
|||||||
#include "ui_BrowserOptionDialog.h"
|
#include "ui_BrowserOptionDialog.h"
|
||||||
|
|
||||||
#include <QFileDialog>
|
#include <QFileDialog>
|
||||||
#include <QMessageBox>
|
|
||||||
|
|
||||||
BrowserOptionDialog::BrowserOptionDialog(QWidget* parent)
|
BrowserOptionDialog::BrowserOptionDialog(QWidget* parent)
|
||||||
: QWidget(parent)
|
: QWidget(parent)
|
||||||
, m_ui(new Ui::BrowserOptionDialog())
|
, m_ui(new Ui::BrowserOptionDialog())
|
||||||
{
|
{
|
||||||
m_ui->setupUi(this);
|
m_ui->setupUi(this);
|
||||||
connect(m_ui->removeSharedEncryptionKeys, SIGNAL(clicked()), this, SIGNAL(removeSharedEncryptionKeys()));
|
|
||||||
connect(m_ui->removeStoredPermissions, SIGNAL(clicked()), this, SIGNAL(removeStoredPermissions()));
|
|
||||||
|
|
||||||
m_ui->extensionLabel->setOpenExternalLinks(true);
|
m_ui->extensionLabel->setOpenExternalLinks(true);
|
||||||
m_ui->extensionLabel->setText(tr("KeePassXC-Browser is needed for the browser integration to work. <br />Download it for %1 and %2.").arg(
|
m_ui->extensionLabel->setText(tr("KeePassXC-Browser is needed for the browser integration to work. <br />Download it for %1 and %2.").arg(
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#define BROWSEROPTIONDIALOG_H
|
#define BROWSEROPTIONDIALOG_H
|
||||||
|
|
||||||
#include <QScopedPointer>
|
#include <QScopedPointer>
|
||||||
|
#include <QPointer>
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
|
||||||
namespace Ui
|
namespace Ui
|
||||||
@ -40,10 +41,6 @@ public slots:
|
|||||||
void loadSettings();
|
void loadSettings();
|
||||||
void saveSettings();
|
void saveSettings();
|
||||||
|
|
||||||
signals:
|
|
||||||
void removeSharedEncryptionKeys();
|
|
||||||
void removeStoredPermissions();
|
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void showProxyLocationFileDialog();
|
void showProxyLocationFileDialog();
|
||||||
|
|
||||||
|
@ -145,7 +145,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<spacer name="verticalSpacer_3">
|
<spacer name="verticalSpacer">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Vertical</enum>
|
<enum>Qt::Vertical</enum>
|
||||||
</property>
|
</property>
|
||||||
@ -215,7 +215,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<spacer name="verticalSpacer">
|
<spacer name="verticalSpacer_2">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Vertical</enum>
|
<enum>Qt::Vertical</enum>
|
||||||
</property>
|
</property>
|
||||||
@ -230,36 +230,6 @@
|
|||||||
</property>
|
</property>
|
||||||
</spacer>
|
</spacer>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="removeSharedEncryptionKeys">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>&Disconnect all browsers</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="removeStoredPermissions">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Forget all remembered &permissions</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item>
|
<item>
|
||||||
<spacer name="verticalSpacer_2">
|
<spacer name="verticalSpacer_2">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
@ -376,7 +346,7 @@
|
|||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<spacer name="verticalSpacer_4">
|
<spacer name="verticalSpacer_5">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Vertical</enum>
|
<enum>Qt::Vertical</enum>
|
||||||
</property>
|
</property>
|
||||||
|
@ -35,10 +35,14 @@
|
|||||||
#include "core/PasswordGenerator.h"
|
#include "core/PasswordGenerator.h"
|
||||||
#include "gui/MainWindow.h"
|
#include "gui/MainWindow.h"
|
||||||
|
|
||||||
static const char KEEPASSXCBROWSER_NAME[] = "KeePassXC-Browser Settings";
|
const char BrowserService::KEEPASSXCBROWSER_NAME[] = "KeePassXC-Browser Settings";
|
||||||
static const char ASSOCIATE_KEY_PREFIX[] = "Public Key: ";
|
const char BrowserService::ASSOCIATE_KEY_PREFIX[] = "KPXC_BROWSER_";
|
||||||
static const char KEEPASSXCBROWSER_GROUP_NAME[] = "KeePassXC-Browser Passwords";
|
static const char KEEPASSXCBROWSER_GROUP_NAME[] = "KeePassXC-Browser Passwords";
|
||||||
static int KEEPASSXCBROWSER_DEFAULT_ICON = 1;
|
static int KEEPASSXCBROWSER_DEFAULT_ICON = 1;
|
||||||
|
// These are for the settings and password conversion
|
||||||
|
const char BrowserService::LEGACY_ASSOCIATE_KEY_PREFIX[] = "Public Key: ";
|
||||||
|
static const char KEEPASSHTTP_NAME[] = "KeePassHttp Settings";
|
||||||
|
static const char KEEPASSHTTP_GROUP_NAME[] = "KeePassHttp Passwords";
|
||||||
|
|
||||||
BrowserService::BrowserService(DatabaseTabWidget* parent)
|
BrowserService::BrowserService(DatabaseTabWidget* parent)
|
||||||
: m_dbTabWidget(parent)
|
: m_dbTabWidget(parent)
|
||||||
@ -46,12 +50,15 @@ BrowserService::BrowserService(DatabaseTabWidget* parent)
|
|||||||
, m_bringToFrontRequested(false)
|
, m_bringToFrontRequested(false)
|
||||||
, m_keepassBrowserUUID(QUuid::fromRfc4122(QByteArray::fromHex("de887cc3036343b8974b5911b8816224")))
|
, m_keepassBrowserUUID(QUuid::fromRfc4122(QByteArray::fromHex("de887cc3036343b8974b5911b8816224")))
|
||||||
{
|
{
|
||||||
connect(m_dbTabWidget, SIGNAL(databaseLocked(DatabaseWidget*)), this, SLOT(databaseLocked(DatabaseWidget*)));
|
// Don't connect the signals when used from DatabaseSettingsWidgetBrowser (parent is nullptr)
|
||||||
connect(m_dbTabWidget, SIGNAL(databaseUnlocked(DatabaseWidget*)), this, SLOT(databaseUnlocked(DatabaseWidget*)));
|
if (m_dbTabWidget) {
|
||||||
connect(m_dbTabWidget,
|
connect(m_dbTabWidget, SIGNAL(databaseLocked(DatabaseWidget*)), this, SLOT(databaseLocked(DatabaseWidget*)));
|
||||||
SIGNAL(activateDatabaseChanged(DatabaseWidget*)),
|
connect(m_dbTabWidget, SIGNAL(databaseUnlocked(DatabaseWidget*)), this, SLOT(databaseUnlocked(DatabaseWidget*)));
|
||||||
this,
|
connect(m_dbTabWidget,
|
||||||
SLOT(activateDatabaseChanged(DatabaseWidget*)));
|
SIGNAL(activateDatabaseChanged(DatabaseWidget*)),
|
||||||
|
this,
|
||||||
|
SLOT(activateDatabaseChanged(DatabaseWidget*)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BrowserService::isDatabaseOpened() const
|
bool BrowserService::isDatabaseOpened() const
|
||||||
@ -107,12 +114,12 @@ QString BrowserService::getDatabaseRootUuid()
|
|||||||
{
|
{
|
||||||
Database* db = getDatabase();
|
Database* db = getDatabase();
|
||||||
if (!db) {
|
if (!db) {
|
||||||
return QString();
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
Group* rootGroup = db->rootGroup();
|
Group* rootGroup = db->rootGroup();
|
||||||
if (!rootGroup) {
|
if (!rootGroup) {
|
||||||
return QString();
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
return rootGroup->uuidToHex();
|
return rootGroup->uuidToHex();
|
||||||
@ -122,46 +129,16 @@ QString BrowserService::getDatabaseRecycleBinUuid()
|
|||||||
{
|
{
|
||||||
Database* db = getDatabase();
|
Database* db = getDatabase();
|
||||||
if (!db) {
|
if (!db) {
|
||||||
return QString();
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
Group* recycleBin = db->metadata()->recycleBin();
|
Group* recycleBin = db->metadata()->recycleBin();
|
||||||
if (!recycleBin) {
|
if (!recycleBin) {
|
||||||
return QString();
|
return {};
|
||||||
}
|
}
|
||||||
return recycleBin->uuidToHex();
|
return recycleBin->uuidToHex();
|
||||||
}
|
}
|
||||||
|
|
||||||
Entry* BrowserService::getConfigEntry(bool create)
|
|
||||||
{
|
|
||||||
Entry* entry = nullptr;
|
|
||||||
Database* db = getDatabase();
|
|
||||||
if (!db) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
entry = db->resolveEntry(m_keepassBrowserUUID);
|
|
||||||
if (!entry && create) {
|
|
||||||
entry = new Entry();
|
|
||||||
entry->setTitle(QLatin1String(KEEPASSXCBROWSER_NAME));
|
|
||||||
entry->setUuid(m_keepassBrowserUUID);
|
|
||||||
entry->setAutoTypeEnabled(false);
|
|
||||||
entry->setGroup(db->rootGroup());
|
|
||||||
return entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (entry && entry->group() == db->metadata()->recycleBin()) {
|
|
||||||
if (!create) {
|
|
||||||
return nullptr;
|
|
||||||
} else {
|
|
||||||
entry->setGroup(db->rootGroup());
|
|
||||||
return entry;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString BrowserService::storeKey(const QString& key)
|
QString BrowserService::storeKey(const QString& key)
|
||||||
{
|
{
|
||||||
QString id;
|
QString id;
|
||||||
@ -172,8 +149,8 @@ QString BrowserService::storeKey(const QString& key)
|
|||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
Entry* config = getConfigEntry(true);
|
Database* db = getDatabase();
|
||||||
if (!config) {
|
if (!db) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -199,7 +176,7 @@ QString BrowserService::storeKey(const QString& key)
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
contains = config->attributes()->contains(QLatin1String(ASSOCIATE_KEY_PREFIX) + id);
|
contains = db->metadata()->customData()->contains(QLatin1String(ASSOCIATE_KEY_PREFIX) + id);
|
||||||
if (contains) {
|
if (contains) {
|
||||||
dialogResult = QMessageBox::warning(nullptr,
|
dialogResult = QMessageBox::warning(nullptr,
|
||||||
tr("KeePassXC: Overwrite existing key?"),
|
tr("KeePassXC: Overwrite existing key?"),
|
||||||
@ -210,18 +187,18 @@ QString BrowserService::storeKey(const QString& key)
|
|||||||
}
|
}
|
||||||
} while (contains && dialogResult == QMessageBox::No);
|
} while (contains && dialogResult == QMessageBox::No);
|
||||||
|
|
||||||
config->attributes()->set(QLatin1String(ASSOCIATE_KEY_PREFIX) + id, key, true);
|
db->metadata()->customData()->set(QLatin1String(ASSOCIATE_KEY_PREFIX) + id, key);
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString BrowserService::getKey(const QString& id)
|
QString BrowserService::getKey(const QString& id)
|
||||||
{
|
{
|
||||||
Entry* config = getConfigEntry();
|
Database* db = getDatabase();
|
||||||
if (!config) {
|
if (!db) {
|
||||||
return QString();
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
return config->attributes()->value(QLatin1String(ASSOCIATE_KEY_PREFIX) + id);
|
return db->metadata()->customData()->value(QLatin1String(ASSOCIATE_KEY_PREFIX) + id);
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonArray BrowserService::findMatchingEntries(const QString& id,
|
QJsonArray BrowserService::findMatchingEntries(const QString& id,
|
||||||
@ -445,12 +422,9 @@ QList<Entry*> BrowserService::searchEntries(const QString& url, const StringPair
|
|||||||
if (Database* db = dbWidget->database()) {
|
if (Database* db = dbWidget->database()) {
|
||||||
// Check if database is connected with KeePassXC-Browser
|
// Check if database is connected with KeePassXC-Browser
|
||||||
for (const StringPair keyPair : keyList) {
|
for (const StringPair keyPair : keyList) {
|
||||||
Entry* entry = db->resolveEntry(m_keepassBrowserUUID);
|
QString key = db->metadata()->customData()->value(QLatin1String(ASSOCIATE_KEY_PREFIX) + keyPair.first);
|
||||||
if (entry) {
|
if (!key.isEmpty() && keyPair.second == key) {
|
||||||
QString key = entry->attributes()->value(QLatin1String(ASSOCIATE_KEY_PREFIX) + keyPair.first);
|
databases << db;
|
||||||
if (!key.isEmpty() && keyPair.second == key) {
|
|
||||||
databases << db;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -472,102 +446,70 @@ QList<Entry*> BrowserService::searchEntries(const QString& url, const StringPair
|
|||||||
return entries;
|
return entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BrowserService::removeSharedEncryptionKeys()
|
void BrowserService::convertAttributesToCustomData(Database *currentDb)
|
||||||
{
|
{
|
||||||
if (!isDatabaseOpened()) {
|
Database* db = currentDb ? currentDb : getDatabase();
|
||||||
QMessageBox::critical(0,
|
|
||||||
tr("KeePassXC: Database locked!"),
|
|
||||||
tr("The active database is locked!\n"
|
|
||||||
"Please unlock the selected database or choose another one which is unlocked."),
|
|
||||||
QMessageBox::Ok);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Entry* entry = getConfigEntry();
|
|
||||||
if (!entry) {
|
|
||||||
QMessageBox::information(0,
|
|
||||||
tr("KeePassXC: Settings not available!"),
|
|
||||||
tr("The active database does not contain a settings entry."),
|
|
||||||
QMessageBox::Ok);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QStringList keysToRemove;
|
|
||||||
for (const QString& key : entry->attributes()->keys()) {
|
|
||||||
if (key.startsWith(ASSOCIATE_KEY_PREFIX)) {
|
|
||||||
keysToRemove << key;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (keysToRemove.isEmpty()) {
|
|
||||||
QMessageBox::information(0,
|
|
||||||
tr("KeePassXC: No keys found"),
|
|
||||||
tr("No shared encryption keys found in KeePassXC settings."),
|
|
||||||
QMessageBox::Ok);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
entry->beginUpdate();
|
|
||||||
for (const QString& key : keysToRemove) {
|
|
||||||
entry->attributes()->remove(key);
|
|
||||||
}
|
|
||||||
entry->endUpdate();
|
|
||||||
|
|
||||||
const int count = keysToRemove.count();
|
|
||||||
QMessageBox::information(0,
|
|
||||||
tr("KeePassXC: Removed keys from database"),
|
|
||||||
tr("Successfully removed %n encryption key(s) from KeePassXC settings.", "", count),
|
|
||||||
QMessageBox::Ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BrowserService::removeStoredPermissions()
|
|
||||||
{
|
|
||||||
if (!isDatabaseOpened()) {
|
|
||||||
QMessageBox::critical(0,
|
|
||||||
tr("KeePassXC: Database locked!"),
|
|
||||||
tr("The active database is locked!\n"
|
|
||||||
"Please unlock the selected database or choose another one which is unlocked."),
|
|
||||||
QMessageBox::Ok);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Database* db = m_dbTabWidget->currentDatabaseWidget()->database();
|
|
||||||
if (!db) {
|
if (!db) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<Entry*> entries = db->rootGroup()->entriesRecursive();
|
QList<Entry*> entries = db->rootGroup()->entriesRecursive();
|
||||||
|
QProgressDialog progress(tr("Converting attributes to custom data…"), tr("Abort"), 0, entries.count());
|
||||||
QProgressDialog progress(tr("Removing stored permissions…"), tr("Abort"), 0, entries.count());
|
|
||||||
progress.setWindowModality(Qt::WindowModal);
|
progress.setWindowModality(Qt::WindowModal);
|
||||||
|
|
||||||
uint counter = 0;
|
int counter = 0;
|
||||||
|
int keyCounter = 0;
|
||||||
for (Entry* entry : entries) {
|
for (Entry* entry : entries) {
|
||||||
if (progress.wasCanceled()) {
|
if (progress.wasCanceled()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (entry->attributes()->contains(KEEPASSXCBROWSER_NAME)) {
|
if (moveSettingsToCustomData(entry, KEEPASSHTTP_NAME)) {
|
||||||
entry->beginUpdate();
|
|
||||||
entry->attributes()->remove(KEEPASSXCBROWSER_NAME);
|
|
||||||
entry->endUpdate();
|
|
||||||
++counter;
|
++counter;
|
||||||
}
|
}
|
||||||
|
if (moveSettingsToCustomData(entry, KEEPASSXCBROWSER_NAME)) {
|
||||||
|
++counter;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry->title() == KEEPASSHTTP_NAME || entry->title() == KEEPASSXCBROWSER_NAME) {
|
||||||
|
keyCounter += moveKeysToCustomData(entry, db);
|
||||||
|
delete entry;
|
||||||
|
}
|
||||||
|
|
||||||
progress.setValue(progress.value() + 1);
|
progress.setValue(progress.value() + 1);
|
||||||
}
|
}
|
||||||
progress.reset();
|
progress.reset();
|
||||||
|
|
||||||
if (counter > 0) {
|
if (counter > 0) {
|
||||||
QMessageBox::information(0,
|
QMessageBox::information(0, tr("KeePassXC: Converted KeePassHTTP attributes"),
|
||||||
tr("KeePassXC: Removed permissions"),
|
tr("Successfully converted attributes from %1 entry(s).\n"
|
||||||
tr("Successfully removed permissions from %n entry(s).", "", counter),
|
"Moved %2 keys to custom data.", "").arg(counter).arg(keyCounter),
|
||||||
|
QMessageBox::Ok);
|
||||||
|
} else if (counter == 0 && keyCounter > 0) {
|
||||||
|
QMessageBox::information(0, tr("KeePassXC: Converted KeePassHTTP attributes"),
|
||||||
|
tr("Successfully moved %n keys to custom data.", "", keyCounter),
|
||||||
QMessageBox::Ok);
|
QMessageBox::Ok);
|
||||||
} else {
|
} else {
|
||||||
QMessageBox::information(0,
|
QMessageBox::information(0, tr("KeePassXC: No entry with KeePassHTTP attributes found!"),
|
||||||
tr("KeePassXC: No entry with permissions found!"),
|
tr("The active database does not contain an entry with KeePassHTTP attributes."),
|
||||||
tr("The active database does not contain an entry with permissions."),
|
|
||||||
QMessageBox::Ok);
|
QMessageBox::Ok);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Rename password groupName
|
||||||
|
Group* rootGroup = db->rootGroup();
|
||||||
|
if (!rootGroup) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString keePassBrowserGroupName = QLatin1String(KEEPASSXCBROWSER_GROUP_NAME);
|
||||||
|
const QString keePassHttpGroupName = QLatin1String(KEEPASSHTTP_GROUP_NAME);
|
||||||
|
|
||||||
|
for (Group* g : rootGroup->groupsRecursive(true)) {
|
||||||
|
if (g->name() == keePassHttpGroupName) {
|
||||||
|
g->setName(keePassBrowserGroupName);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<Entry*> BrowserService::sortEntries(QList<Entry*>& pwEntries, const QString& host, const QString& entryUrl)
|
QList<Entry*> BrowserService::sortEntries(QList<Entry*>& pwEntries, const QString& host, const QString& entryUrl)
|
||||||
@ -873,6 +815,75 @@ Database* BrowserService::selectedDatabase()
|
|||||||
return getDatabase();
|
return getDatabase();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool BrowserService::moveSettingsToCustomData(Entry* entry, const QString& name) const
|
||||||
|
{
|
||||||
|
if (entry->attributes()->contains(name)) {
|
||||||
|
QString attr = entry->attributes()->value(name);
|
||||||
|
entry->beginUpdate();
|
||||||
|
if (!attr.isEmpty()) {
|
||||||
|
entry->customData()->set(KEEPASSXCBROWSER_NAME, attr);
|
||||||
|
}
|
||||||
|
entry->attributes()->remove(name);
|
||||||
|
entry->endUpdate();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int BrowserService::moveKeysToCustomData(Entry* entry, Database* db) const
|
||||||
|
{
|
||||||
|
int keyCounter = 0;
|
||||||
|
for (const auto& key : entry->attributes()->keys()) {
|
||||||
|
if (key.contains(LEGACY_ASSOCIATE_KEY_PREFIX)) {
|
||||||
|
QString publicKey = key;
|
||||||
|
publicKey.remove(LEGACY_ASSOCIATE_KEY_PREFIX);
|
||||||
|
|
||||||
|
// Add key to database custom data
|
||||||
|
if (db && !db->metadata()->customData()->contains(QLatin1String(ASSOCIATE_KEY_PREFIX) + publicKey)) {
|
||||||
|
db->metadata()->customData()->set(QLatin1String(ASSOCIATE_KEY_PREFIX) + publicKey, entry->attributes()->value(key));
|
||||||
|
++keyCounter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return keyCounter;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BrowserService::checkLegacySettings()
|
||||||
|
{
|
||||||
|
Database* db = getDatabase();
|
||||||
|
if (!db) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool legacySettingsFound = false;
|
||||||
|
QList<Entry*> entries = db->rootGroup()->entriesRecursive();
|
||||||
|
for (const auto& e : entries) {
|
||||||
|
if ((e->attributes()->contains(KEEPASSHTTP_NAME) || e->attributes()->contains(KEEPASSXCBROWSER_NAME)) ||
|
||||||
|
(e->title() == KEEPASSHTTP_NAME || e->title() == KEEPASSXCBROWSER_NAME)) {
|
||||||
|
legacySettingsFound = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!legacySettingsFound) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto dialogResult = QMessageBox::warning(nullptr,
|
||||||
|
tr("KeePassXC: Legacy browser integration settings detected"),
|
||||||
|
tr("Legacy browser integration settings have been detected.\n"
|
||||||
|
"Do you want to upgrade the settings to the latest standard?\n"
|
||||||
|
"This is necessary to maintain compatibility with the browser plugin."),
|
||||||
|
QMessageBox::Yes | QMessageBox::No);
|
||||||
|
|
||||||
|
if (dialogResult == QMessageBox::No) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void BrowserService::databaseLocked(DatabaseWidget* dbWidget)
|
void BrowserService::databaseLocked(DatabaseWidget* dbWidget)
|
||||||
{
|
{
|
||||||
if (dbWidget) {
|
if (dbWidget) {
|
||||||
@ -888,6 +899,10 @@ void BrowserService::databaseUnlocked(DatabaseWidget* dbWidget)
|
|||||||
m_bringToFrontRequested = false;
|
m_bringToFrontRequested = false;
|
||||||
}
|
}
|
||||||
emit databaseUnlocked();
|
emit databaseUnlocked();
|
||||||
|
|
||||||
|
if (checkLegacySettings()) {
|
||||||
|
convertAttributesToCustomData();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,8 +55,12 @@ public:
|
|||||||
Database* selectedDb = nullptr);
|
Database* selectedDb = nullptr);
|
||||||
QList<Entry*> searchEntries(Database* db, const QString& hostname, const QString& url);
|
QList<Entry*> searchEntries(Database* db, const QString& hostname, const QString& url);
|
||||||
QList<Entry*> searchEntries(const QString& url, const StringPairList& keyList);
|
QList<Entry*> searchEntries(const QString& url, const StringPairList& keyList);
|
||||||
void removeSharedEncryptionKeys();
|
void convertAttributesToCustomData(Database *currentDb = nullptr);
|
||||||
void removeStoredPermissions();
|
|
||||||
|
public:
|
||||||
|
static const char KEEPASSXCBROWSER_NAME[];
|
||||||
|
static const char ASSOCIATE_KEY_PREFIX[];
|
||||||
|
static const char LEGACY_ASSOCIATE_KEY_PREFIX[];
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
QJsonArray findMatchingEntries(const QString& id,
|
QJsonArray findMatchingEntries(const QString& id,
|
||||||
@ -106,6 +110,9 @@ private:
|
|||||||
QString baseDomain(const QString& url) const;
|
QString baseDomain(const QString& url) const;
|
||||||
Database* getDatabase();
|
Database* getDatabase();
|
||||||
Database* selectedDatabase();
|
Database* selectedDatabase();
|
||||||
|
bool moveSettingsToCustomData(Entry* entry, const QString& name) const;
|
||||||
|
int moveKeysToCustomData(Entry* entry, Database* db) const;
|
||||||
|
bool checkLegacySettings();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DatabaseTabWidget* const m_dbTabWidget;
|
DatabaseTabWidget* const m_dbTabWidget;
|
||||||
|
@ -207,18 +207,6 @@ void NativeMessagingHost::disconnectSocket()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NativeMessagingHost::removeSharedEncryptionKeys()
|
|
||||||
{
|
|
||||||
QMutexLocker locker(&m_mutex);
|
|
||||||
m_browserService.removeSharedEncryptionKeys();
|
|
||||||
}
|
|
||||||
|
|
||||||
void NativeMessagingHost::removeStoredPermissions()
|
|
||||||
{
|
|
||||||
QMutexLocker locker(&m_mutex);
|
|
||||||
m_browserService.removeStoredPermissions();
|
|
||||||
}
|
|
||||||
|
|
||||||
void NativeMessagingHost::databaseLocked()
|
void NativeMessagingHost::databaseLocked()
|
||||||
{
|
{
|
||||||
QJsonObject response;
|
QJsonObject response;
|
||||||
|
@ -37,10 +37,6 @@ public:
|
|||||||
void run();
|
void run();
|
||||||
void stop();
|
void stop();
|
||||||
|
|
||||||
public slots:
|
|
||||||
void removeSharedEncryptionKeys();
|
|
||||||
void removeStoredPermissions();
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void quit();
|
void quit();
|
||||||
|
|
||||||
|
@ -84,12 +84,6 @@ public:
|
|||||||
QWidget* createWidget() override
|
QWidget* createWidget() override
|
||||||
{
|
{
|
||||||
BrowserOptionDialog* dlg = new BrowserOptionDialog();
|
BrowserOptionDialog* dlg = new BrowserOptionDialog();
|
||||||
QObject::connect(dlg,
|
|
||||||
SIGNAL(removeSharedEncryptionKeys()),
|
|
||||||
m_nativeMessagingHost.data(),
|
|
||||||
SLOT(removeSharedEncryptionKeys()));
|
|
||||||
QObject::connect(
|
|
||||||
dlg, SIGNAL(removeStoredPermissions()), m_nativeMessagingHost.data(), SLOT(removeStoredPermissions()));
|
|
||||||
return dlg;
|
return dlg;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,8 +102,8 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QSharedPointer<NativeMessagingHost> m_nativeMessagingHost;
|
QSharedPointer<NativeMessagingHost> m_nativeMessagingHost;
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -21,6 +21,9 @@
|
|||||||
#include "DatabaseSettingsWidgetGeneral.h"
|
#include "DatabaseSettingsWidgetGeneral.h"
|
||||||
#include "DatabaseSettingsWidgetEncryption.h"
|
#include "DatabaseSettingsWidgetEncryption.h"
|
||||||
#include "DatabaseSettingsWidgetMasterKey.h"
|
#include "DatabaseSettingsWidgetMasterKey.h"
|
||||||
|
#ifdef WITH_XC_BROWSER
|
||||||
|
#include "DatabaseSettingsWidgetBrowser.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "core/Config.h"
|
#include "core/Config.h"
|
||||||
#include "core/FilePath.h"
|
#include "core/FilePath.h"
|
||||||
@ -34,6 +37,9 @@ DatabaseSettingsDialog::DatabaseSettingsDialog(QWidget* parent)
|
|||||||
, m_securityTabWidget(new QTabWidget(this))
|
, m_securityTabWidget(new QTabWidget(this))
|
||||||
, m_masterKeyWidget(new DatabaseSettingsWidgetMasterKey(this))
|
, m_masterKeyWidget(new DatabaseSettingsWidgetMasterKey(this))
|
||||||
, m_encryptionWidget(new DatabaseSettingsWidgetEncryption(this))
|
, m_encryptionWidget(new DatabaseSettingsWidgetEncryption(this))
|
||||||
|
#ifdef WITH_XC_BROWSER
|
||||||
|
, m_browserWidget(new DatabaseSettingsWidgetBrowser(this))
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
m_ui->setupUi(this);
|
m_ui->setupUi(this);
|
||||||
|
|
||||||
@ -55,6 +61,11 @@ DatabaseSettingsDialog::DatabaseSettingsDialog(QWidget* parent)
|
|||||||
connect(m_ui->categoryList, SIGNAL(categoryChanged(int)), m_ui->stackedWidget, SLOT(setCurrentIndex(int)));
|
connect(m_ui->categoryList, SIGNAL(categoryChanged(int)), m_ui->stackedWidget, SLOT(setCurrentIndex(int)));
|
||||||
connect(m_ui->advancedSettingsToggle, SIGNAL(toggled(bool)), SLOT(toggleAdvancedMode(bool)));
|
connect(m_ui->advancedSettingsToggle, SIGNAL(toggled(bool)), SLOT(toggleAdvancedMode(bool)));
|
||||||
|
|
||||||
|
#ifdef WITH_XC_BROWSER
|
||||||
|
m_ui->categoryList->addCategory(tr("Browser Integration"), FilePath::instance()->icon("apps", "internet-web-browser"));
|
||||||
|
m_ui->stackedWidget->addWidget(m_browserWidget);
|
||||||
|
#endif
|
||||||
|
|
||||||
pageChanged();
|
pageChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,6 +79,9 @@ void DatabaseSettingsDialog::load(Database* db)
|
|||||||
m_generalWidget->load(db);
|
m_generalWidget->load(db);
|
||||||
m_masterKeyWidget->load(db);
|
m_masterKeyWidget->load(db);
|
||||||
m_encryptionWidget->load(db);
|
m_encryptionWidget->load(db);
|
||||||
|
#ifdef WITH_XC_BROWSER
|
||||||
|
m_browserWidget->load(db);
|
||||||
|
#endif
|
||||||
m_ui->advancedSettingsToggle->setChecked(config()->get("GUI/AdvancedSettings", false).toBool());
|
m_ui->advancedSettingsToggle->setChecked(config()->get("GUI/AdvancedSettings", false).toBool());
|
||||||
m_db = db;
|
m_db = db;
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#define KEEPASSX_DATABASESETTINGSWIDGET_H
|
#define KEEPASSX_DATABASESETTINGSWIDGET_H
|
||||||
|
|
||||||
#include "gui/DialogyWidget.h"
|
#include "gui/DialogyWidget.h"
|
||||||
|
#include "config-keepassx.h"
|
||||||
|
|
||||||
#include <QScopedPointer>
|
#include <QScopedPointer>
|
||||||
#include <QPointer>
|
#include <QPointer>
|
||||||
@ -27,6 +28,9 @@ class Database;
|
|||||||
class DatabaseSettingsWidgetGeneral;
|
class DatabaseSettingsWidgetGeneral;
|
||||||
class DatabaseSettingsWidgetEncryption;
|
class DatabaseSettingsWidgetEncryption;
|
||||||
class DatabaseSettingsWidgetMasterKey;
|
class DatabaseSettingsWidgetMasterKey;
|
||||||
|
#ifdef WITH_XC_BROWSER
|
||||||
|
class DatabaseSettingsWidgetBrowser;
|
||||||
|
#endif
|
||||||
class QTabWidget;
|
class QTabWidget;
|
||||||
|
|
||||||
namespace Ui
|
namespace Ui
|
||||||
@ -68,6 +72,9 @@ private:
|
|||||||
QPointer<QTabWidget> m_securityTabWidget;
|
QPointer<QTabWidget> m_securityTabWidget;
|
||||||
QPointer<DatabaseSettingsWidgetMasterKey> m_masterKeyWidget;
|
QPointer<DatabaseSettingsWidgetMasterKey> m_masterKeyWidget;
|
||||||
QPointer<DatabaseSettingsWidgetEncryption> m_encryptionWidget;
|
QPointer<DatabaseSettingsWidgetEncryption> m_encryptionWidget;
|
||||||
|
#ifdef WITH_XC_BROWSER
|
||||||
|
QPointer<DatabaseSettingsWidgetBrowser> m_browserWidget;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // KEEPASSX_DATABASESETTINGSWIDGET_H
|
#endif // KEEPASSX_DATABASESETTINGSWIDGET_H
|
||||||
|
245
src/gui/dbsettings/DatabaseSettingsWidgetBrowser.cpp
Normal file
245
src/gui/dbsettings/DatabaseSettingsWidgetBrowser.cpp
Normal file
@ -0,0 +1,245 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 KeePassXC Team <team@keepassxc.org>
|
||||||
|
* Copyright (C) 2018 Sami Vänttinen <sami.vanttinen@protonmail.com>
|
||||||
|
*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "DatabaseSettingsWidgetBrowser.h"
|
||||||
|
#include <QProgressDialog>
|
||||||
|
#include "core/Clock.h"
|
||||||
|
#include "core/Database.h"
|
||||||
|
#include "core/Entry.h"
|
||||||
|
#include "core/Group.h"
|
||||||
|
#include "core/Metadata.h"
|
||||||
|
#include "gui/MessageBox.h"
|
||||||
|
#include "browser/BrowserSettings.h"
|
||||||
|
#include "ui_DatabaseSettingsWidgetBrowser.h"
|
||||||
|
|
||||||
|
DatabaseSettingsWidgetBrowser::DatabaseSettingsWidgetBrowser(QWidget* parent)
|
||||||
|
: DatabaseSettingsWidget(parent), m_ui(new Ui::DatabaseSettingsWidgetBrowser())
|
||||||
|
, m_customData(new CustomData(this))
|
||||||
|
, m_customDataModel(new QStandardItemModel(this))
|
||||||
|
, m_browserService(nullptr)
|
||||||
|
{
|
||||||
|
m_ui->setupUi(this);
|
||||||
|
m_ui->removeCustomDataButton->setEnabled(false);
|
||||||
|
m_ui->customDataTable->setModel(m_customDataModel);
|
||||||
|
|
||||||
|
settingsWarning();
|
||||||
|
connect(m_ui->customDataTable->selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)),
|
||||||
|
SLOT(toggleRemoveButton(QItemSelection)));
|
||||||
|
connect(m_ui->removeCustomDataButton, SIGNAL(clicked()), SLOT(removeSelectedKey()));
|
||||||
|
connect(m_ui->convertToCustomData, SIGNAL(clicked()), this, SLOT(convertAttributesToCustomData()));
|
||||||
|
connect(m_ui->convertToCustomData, SIGNAL(clicked()), this, SLOT(updateSharedKeyList()));
|
||||||
|
connect(m_ui->removeSharedEncryptionKeys, SIGNAL(clicked()), this, SLOT(removeSharedEncryptionKeys()));
|
||||||
|
connect(m_ui->removeSharedEncryptionKeys, SIGNAL(clicked()), this, SLOT(updateSharedKeyList()));
|
||||||
|
connect(m_ui->removeStoredPermissions, SIGNAL(clicked()), this, SLOT(removeStoredPermissions()));
|
||||||
|
}
|
||||||
|
|
||||||
|
DatabaseSettingsWidgetBrowser::~DatabaseSettingsWidgetBrowser()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
CustomData* DatabaseSettingsWidgetBrowser::customData() const
|
||||||
|
{
|
||||||
|
// Returns the current database customData from metadata. Otherwise return an empty customData member.
|
||||||
|
if (m_db) {
|
||||||
|
return m_db->metadata()->customData();
|
||||||
|
}
|
||||||
|
return m_customData;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DatabaseSettingsWidgetBrowser::initialize()
|
||||||
|
{
|
||||||
|
updateModel();
|
||||||
|
settingsWarning();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DatabaseSettingsWidgetBrowser::uninitialize()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void DatabaseSettingsWidgetBrowser::showEvent(QShowEvent* event)
|
||||||
|
{
|
||||||
|
QWidget::showEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DatabaseSettingsWidgetBrowser::save()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DatabaseSettingsWidgetBrowser::removeSelectedKey()
|
||||||
|
{
|
||||||
|
if (QMessageBox::Yes != MessageBox::question(this,
|
||||||
|
tr("Delete the selected key?"),
|
||||||
|
tr("Do you really want to delete the selected key?\n"
|
||||||
|
"This may prevent connection to the browser plugin."),
|
||||||
|
QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Cancel)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QItemSelectionModel* itemSelectionModel = m_ui->customDataTable->selectionModel();
|
||||||
|
if (itemSelectionModel) {
|
||||||
|
for (const QModelIndex& index : itemSelectionModel->selectedRows(0)) {
|
||||||
|
QString key = index.data().toString();
|
||||||
|
key.insert(0, BrowserService::ASSOCIATE_KEY_PREFIX);
|
||||||
|
customData()->remove(key);
|
||||||
|
}
|
||||||
|
updateModel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DatabaseSettingsWidgetBrowser::toggleRemoveButton(const QItemSelection& selected)
|
||||||
|
{
|
||||||
|
m_ui->removeCustomDataButton->setEnabled(!selected.isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
void DatabaseSettingsWidgetBrowser::updateModel()
|
||||||
|
{
|
||||||
|
m_customDataModel->clear();
|
||||||
|
m_customDataModel->setHorizontalHeaderLabels({tr("Key"), tr("Value")});
|
||||||
|
|
||||||
|
for (const QString& key : customData()->keys()) {
|
||||||
|
if (key.startsWith(BrowserService::ASSOCIATE_KEY_PREFIX)) {
|
||||||
|
QString strippedKey = key;
|
||||||
|
strippedKey.remove(BrowserService::ASSOCIATE_KEY_PREFIX);
|
||||||
|
m_customDataModel->appendRow(QList<QStandardItem*>()
|
||||||
|
<< new QStandardItem(strippedKey)
|
||||||
|
<< new QStandardItem(customData()->value(key)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_ui->removeCustomDataButton->setEnabled(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DatabaseSettingsWidgetBrowser::settingsWarning()
|
||||||
|
{
|
||||||
|
if (!browserSettings()->isEnabled()) {
|
||||||
|
m_ui->convertToCustomData->setEnabled(false);
|
||||||
|
m_ui->removeSharedEncryptionKeys->setEnabled(false);
|
||||||
|
m_ui->removeStoredPermissions->setEnabled(false);
|
||||||
|
m_ui->customDataTable->setEnabled(false);
|
||||||
|
m_ui->warningWidget->showMessage(tr("Enable Browser Integration to access these settings."), MessageWidget::Warning);
|
||||||
|
m_ui->warningWidget->setCloseButtonVisible(false);
|
||||||
|
m_ui->warningWidget->setAutoHideTimeout(-1);
|
||||||
|
} else {
|
||||||
|
m_ui->convertToCustomData->setEnabled(true);
|
||||||
|
m_ui->removeSharedEncryptionKeys->setEnabled(true);
|
||||||
|
m_ui->removeStoredPermissions->setEnabled(true);
|
||||||
|
m_ui->customDataTable->setEnabled(true);
|
||||||
|
m_ui->warningWidget->hideMessage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DatabaseSettingsWidgetBrowser::removeSharedEncryptionKeys()
|
||||||
|
{
|
||||||
|
if (QMessageBox::Yes != MessageBox::question(this,
|
||||||
|
tr("Disconnect all browsers"),
|
||||||
|
tr("Do you really want to disconnect all browsers?\n"
|
||||||
|
"This may prevent connection to the browser plugin."),
|
||||||
|
QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Cancel)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList keysToRemove;
|
||||||
|
for (const QString& key : m_db->metadata()->customData()->keys()) {
|
||||||
|
if (key.startsWith(BrowserService::ASSOCIATE_KEY_PREFIX)) {
|
||||||
|
keysToRemove << key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (keysToRemove.isEmpty()) {
|
||||||
|
QMessageBox::information(this,
|
||||||
|
tr("KeePassXC: No keys found"),
|
||||||
|
tr("No shared encryption keys found in KeePassXC settings."),
|
||||||
|
QMessageBox::Ok);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const QString& key : keysToRemove) {
|
||||||
|
m_db->metadata()->customData()->remove(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
const int count = keysToRemove.count();
|
||||||
|
QMessageBox::information(this,
|
||||||
|
tr("KeePassXC: Removed keys from database"),
|
||||||
|
tr("Successfully removed %n encryption key(s) from KeePassXC settings.", "", count),
|
||||||
|
QMessageBox::Ok);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DatabaseSettingsWidgetBrowser::removeStoredPermissions()
|
||||||
|
{
|
||||||
|
if (QMessageBox::Yes != MessageBox::question(this,
|
||||||
|
tr("Forget all site-specific settings on entries"),
|
||||||
|
tr("Do you really want forget all site-specific settings on every entry?\n"
|
||||||
|
"Permissions to access entries will be revoked."),
|
||||||
|
QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Cancel)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<Entry*> entries = m_db->rootGroup()->entriesRecursive();
|
||||||
|
|
||||||
|
QProgressDialog progress(tr("Removing stored permissions…"), tr("Abort"), 0, entries.count());
|
||||||
|
progress.setWindowModality(Qt::WindowModal);
|
||||||
|
|
||||||
|
uint counter = 0;
|
||||||
|
for (Entry* entry : entries) {
|
||||||
|
if (progress.wasCanceled()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry->customData()->contains(BrowserService::KEEPASSXCBROWSER_NAME)) {
|
||||||
|
entry->beginUpdate();
|
||||||
|
entry->customData()->remove(BrowserService::KEEPASSXCBROWSER_NAME);
|
||||||
|
entry->endUpdate();
|
||||||
|
++counter;
|
||||||
|
}
|
||||||
|
progress.setValue(progress.value() + 1);
|
||||||
|
}
|
||||||
|
progress.reset();
|
||||||
|
|
||||||
|
if (counter > 0) {
|
||||||
|
QMessageBox::information(this,
|
||||||
|
tr("KeePassXC: Removed permissions"),
|
||||||
|
tr("Successfully removed permissions from %n entry(s).", "", counter),
|
||||||
|
QMessageBox::Ok);
|
||||||
|
} else {
|
||||||
|
QMessageBox::information(this,
|
||||||
|
tr("KeePassXC: No entry with permissions found!"),
|
||||||
|
tr("The active database does not contain an entry with permissions."),
|
||||||
|
QMessageBox::Ok);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DatabaseSettingsWidgetBrowser::convertAttributesToCustomData()
|
||||||
|
{
|
||||||
|
if (QMessageBox::Yes != MessageBox::question(this,
|
||||||
|
tr("Move KeePassHTTP attributes to custom data"),
|
||||||
|
tr("Do you really want to move all legacy browser integration data to the latest standard?\n"
|
||||||
|
"This is necessary to maintain compatibility with the browser plugin."),
|
||||||
|
QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Cancel)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_browserService.convertAttributesToCustomData(m_db);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Updates the shared key list after the list is cleared
|
||||||
|
void DatabaseSettingsWidgetBrowser::updateSharedKeyList()
|
||||||
|
{
|
||||||
|
updateModel();
|
||||||
|
}
|
||||||
|
|
78
src/gui/dbsettings/DatabaseSettingsWidgetBrowser.h
Normal file
78
src/gui/dbsettings/DatabaseSettingsWidgetBrowser.h
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 KeePassXC Team <team@keepassxc.org>
|
||||||
|
* Copyright (C) 2018 Sami Vänttinen <sami.vanttinen@protonmail.com>
|
||||||
|
*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef KEEPASSXC_DATABASESETTINGSWIDGETBROWSER_H
|
||||||
|
#define KEEPASSXC_DATABASESETTINGSWIDGETBROWSER_H
|
||||||
|
|
||||||
|
#include "DatabaseSettingsWidget.h"
|
||||||
|
|
||||||
|
#include <QPointer>
|
||||||
|
#include <QScopedPointer>
|
||||||
|
#include <QStandardItemModel>
|
||||||
|
#include <QItemSelection>
|
||||||
|
#include "core/CustomData.h"
|
||||||
|
#include "gui/DatabaseTabWidget.h"
|
||||||
|
#include "browser/BrowserService.h"
|
||||||
|
|
||||||
|
class Database;
|
||||||
|
namespace Ui
|
||||||
|
{
|
||||||
|
class DatabaseSettingsWidgetBrowser;
|
||||||
|
}
|
||||||
|
|
||||||
|
class DatabaseSettingsWidgetBrowser : public DatabaseSettingsWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit DatabaseSettingsWidgetBrowser(QWidget* parent = nullptr);
|
||||||
|
Q_DISABLE_COPY(DatabaseSettingsWidgetBrowser);
|
||||||
|
~DatabaseSettingsWidgetBrowser() override;
|
||||||
|
|
||||||
|
CustomData* customData() const;
|
||||||
|
inline bool hasAdvancedMode() const override { return false; }
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void initialize() override;
|
||||||
|
void uninitialize() override;
|
||||||
|
bool save() override;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void removeSelectedKey();
|
||||||
|
void toggleRemoveButton(const QItemSelection& selected);
|
||||||
|
void updateSharedKeyList();
|
||||||
|
void removeSharedEncryptionKeys();
|
||||||
|
void removeStoredPermissions();
|
||||||
|
void convertAttributesToCustomData();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void updateModel();
|
||||||
|
void settingsWarning();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void showEvent(QShowEvent* event) override;
|
||||||
|
|
||||||
|
const QScopedPointer<Ui::DatabaseSettingsWidgetBrowser> m_ui;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QPointer<CustomData> m_customData;
|
||||||
|
QPointer<QStandardItemModel> m_customDataModel;
|
||||||
|
BrowserService m_browserService;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //KEEPASSXC_DATABASESETTINGSWIDGETBROWSER_H
|
174
src/gui/dbsettings/DatabaseSettingsWidgetBrowser.ui
Normal file
174
src/gui/dbsettings/DatabaseSettingsWidgetBrowser.ui
Normal file
@ -0,0 +1,174 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>DatabaseSettingsWidgetBrowser</class>
|
||||||
|
<widget class="QWidget" name="DatabaseSettingsWidgetBrowser">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>453</width>
|
||||||
|
<height>374</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>450</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="MessageWidget" name="warningWidget" native="true">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="groupBox">
|
||||||
|
<property name="title">
|
||||||
|
<string>KeePassXC-Browser settings</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="removeSharedEncryptionKeys">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>&Disconnect all browsers</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="removeStoredPermissions">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Forg&et all site-specific settings on entries</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="convertToCustomData">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Move KeePassHTTP attributes to KeePassXC-Browser &custom data</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="groupBox_2">
|
||||||
|
<property name="title">
|
||||||
|
<string>Stored keys</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="groupBox">
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||||
|
<item>
|
||||||
|
<widget class="QTableView" name="customDataTable">
|
||||||
|
<property name="editTriggers">
|
||||||
|
<set>QAbstractItemView::NoEditTriggers</set>
|
||||||
|
</property>
|
||||||
|
<property name="selectionBehavior">
|
||||||
|
<enum>QAbstractItemView::SelectRows</enum>
|
||||||
|
</property>
|
||||||
|
<attribute name="horizontalHeaderDefaultSectionSize">
|
||||||
|
<number>200</number>
|
||||||
|
</attribute>
|
||||||
|
<attribute name="horizontalHeaderStretchLastSection">
|
||||||
|
<bool>true</bool>
|
||||||
|
</attribute>
|
||||||
|
<attribute name="verticalHeaderVisible">
|
||||||
|
<bool>false</bool>
|
||||||
|
</attribute>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="removeCustomDataButton">
|
||||||
|
<property name="text">
|
||||||
|
<string>Remove</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="verticalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>40</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<customwidgets>
|
||||||
|
<customwidget>
|
||||||
|
<class>MessageWidget</class>
|
||||||
|
<extends>QWidget</extends>
|
||||||
|
<header>gui/MessageWidget.h</header>
|
||||||
|
<container>1</container>
|
||||||
|
</customwidget>
|
||||||
|
</customwidgets>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
Loading…
Reference in New Issue
Block a user