diff --git a/src/browser/BrowserEntryConfig.cpp b/src/browser/BrowserEntryConfig.cpp
index 2fcc48a281..248e92c06c 100644
--- a/src/browser/BrowserEntryConfig.cpp
+++ b/src/browser/BrowserEntryConfig.cpp
@@ -21,7 +21,7 @@
#include "core/Entry.h"
#include "core/EntryAttributes.h"
-static const char KEEPASSBROWSER_NAME[] = "KeePassXC-Browser Settings";
+static const char KEEPASSXCBROWSER_NAME[] = "KeePassXC-Browser Settings";
BrowserEntryConfig::BrowserEntryConfig(QObject* parent) :
@@ -83,7 +83,7 @@ void BrowserEntryConfig::setRealm(const QString& realm)
bool BrowserEntryConfig::load(const Entry* entry)
{
- QString s = entry->customData()->value(KEEPASSBROWSER_NAME);
+ QString s = entry->customData()->value(KEEPASSXCBROWSER_NAME);
if (s.isEmpty()) {
return false;
}
@@ -105,5 +105,5 @@ void BrowserEntryConfig::save(Entry* entry)
QVariantMap v = qo2qv(this);
QJsonObject o = QJsonObject::fromVariantMap(v);
QByteArray json = QJsonDocument(o).toJson(QJsonDocument::Compact);
- entry->customData()->set(KEEPASSBROWSER_NAME, json);
+ entry->customData()->set(KEEPASSXCBROWSER_NAME, json);
}
diff --git a/src/browser/BrowserOptionDialog.cpp b/src/browser/BrowserOptionDialog.cpp
index 835a8f502b..bb1b7b97a5 100755
--- a/src/browser/BrowserOptionDialog.cpp
+++ b/src/browser/BrowserOptionDialog.cpp
@@ -39,7 +39,7 @@ BrowserOptionDialog::BrowserOptionDialog(DatabaseTabWidget* parent) :
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, SIGNAL(convertAttributesToCustomData()));
connect(m_ui->removeSharedEncryptionKeys, SIGNAL(clicked()), this, SIGNAL(removeSharedEncryptionKeys()));
connect(m_ui->removeStoredPermissions, SIGNAL(clicked()), this, SIGNAL(removeStoredPermissions()));
diff --git a/src/browser/BrowserOptionDialog.h b/src/browser/BrowserOptionDialog.h
index 4f6855798d..bf4c39bb4f 100755
--- a/src/browser/BrowserOptionDialog.h
+++ b/src/browser/BrowserOptionDialog.h
@@ -49,6 +49,7 @@ public slots:
signals:
void removeSharedEncryptionKeys();
void removeStoredPermissions();
+ void convertAttributesToCustomData();
private slots:
void showProxyLocationFileDialog();
diff --git a/src/browser/BrowserOptionDialog.ui b/src/browser/BrowserOptionDialog.ui
index 69caf693fe..f4ef971174 100755
--- a/src/browser/BrowserOptionDialog.ui
+++ b/src/browser/BrowserOptionDialog.ui
@@ -230,6 +230,23 @@
+ -
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+ Move KeePassHTTP attributes to KeePassXC-Browser &custom data
+
+
+
+
+
-
diff --git a/src/browser/BrowserService.cpp b/src/browser/BrowserService.cpp
index 472a0ddbea..814547db0c 100644
--- a/src/browser/BrowserService.cpp
+++ b/src/browser/BrowserService.cpp
@@ -44,6 +44,9 @@ static const char KEEPASSXCBROWSER_NAME[] = "KeePassXC-Browser Settings";
static const char ASSOCIATE_KEY_PREFIX[] = "Public Key: ";
static const char KEEPASSXCBROWSER_GROUP_NAME[] = "KeePassXC-Browser Passwords";
static int KEEPASSXCBROWSER_DEFAULT_ICON = 1;
+// These are for the settings and password conversion
+static const char KEEPASSHTTP_NAME[] = "KeePassHttp Settings";
+static const char KEEPASSHTTP_GROUP_NAME[] = "KeePassHttp Passwords";
BrowserService::BrowserService(DatabaseTabWidget* parent) :
m_dbTabWidget(parent),
@@ -132,36 +135,6 @@ QString BrowserService::getDatabaseRecycleBinUuid()
return recycleBin->uuid().toHex();
}
-Entry* BrowserService::getConfigEntry(bool create)
-{
- Entry* entry = nullptr;
- Database* db = getDatabase();
- if (!db) {
- return nullptr;
- }
-
- entry = db->resolveEntry(KEEPASSXCBROWSER_UUID);
- if (!entry && create) {
- entry = new Entry();
- entry->setTitle(QLatin1String(KEEPASSXCBROWSER_NAME));
- entry->setUuid(KEEPASSXCBROWSER_UUID);
- 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 id;
@@ -500,6 +473,69 @@ void BrowserService::removeStoredPermissions()
}
}
+void BrowserService::convertAttributesToCustomData()
+{
+ 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) {
+ return;
+ }
+
+ QList entries = db->rootGroup()->entriesRecursive();
+
+ QProgressDialog progress(tr("Converting attributes to custom data…"), tr("Abort"), 0, entries.count());
+ progress.setWindowModality(Qt::WindowModal);
+
+ uint counter = 0;
+ for (Entry* entry : entries) {
+ if (progress.wasCanceled()) {
+ return;
+ }
+
+ if (moveSettingsToCustomData(entry, KEEPASSHTTP_NAME)) {
+ ++counter;
+ }
+ if (moveSettingsToCustomData(entry, KEEPASSXCBROWSER_NAME)) {
+ ++counter;
+ }
+ progress.setValue(progress.value() + 1);
+ }
+ progress.reset();
+
+ if (counter > 0) {
+ QMessageBox::information(0, tr("KeePassXC: Converted KeePassHTTP attributes"),
+ tr("Successfully converted attributes from %n entry(s).", "", counter),
+ QMessageBox::Ok);
+ } else {
+ QMessageBox::information(0, tr("KeePassXC: No entry with KeePassHTTP attributes found!"),
+ tr("The active database does not contain an entry with KeePassHTTP attributes."),
+ 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 BrowserService::sortEntries(QList& pwEntries, const QString& host, const QString& entryUrl)
{
QUrl url(entryUrl);
@@ -715,6 +751,21 @@ Database* BrowserService::getDatabase()
return nullptr;
}
+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;
+}
+
void BrowserService::databaseLocked(DatabaseWidget* dbWidget)
{
if (dbWidget) {
diff --git a/src/browser/BrowserService.h b/src/browser/BrowserService.h
index 5a96e1ecd2..6e7a88a575 100644
--- a/src/browser/BrowserService.h
+++ b/src/browser/BrowserService.h
@@ -38,13 +38,13 @@ class BrowserService : public QObject
bool openDatabase(bool triggerUnlock);
QString getDatabaseRootUuid();
QString getDatabaseRecycleBinUuid();
- Entry* getConfigEntry(bool create = false);
QString getKey(const QString& id);
void addEntry(const QString& id, const QString& login, const QString& password, const QString& url, const QString& submitUrl, const QString& realm);
QList searchEntries(Database* db, const QString& hostname);
QList searchEntries(const QString& text);
void removeSharedEncryptionKeys();
void removeStoredPermissions();
+ void convertAttributesToCustomData();
public slots:
QJsonArray findMatchingEntries(const QString& id, const QString& url, const QString& submitUrl, const QString& realm);
@@ -73,6 +73,7 @@ public slots:
bool matchUrlScheme(const QString& url);
bool removeFirstDomain(QString& hostname);
Database* getDatabase();
+ bool moveSettingsToCustomData(Entry* entry, const QString& name) const;
private:
DatabaseTabWidget* const m_dbTabWidget;
diff --git a/src/browser/NativeMessagingHost.cpp b/src/browser/NativeMessagingHost.cpp
index 4dfa87d511..9d2c36136c 100755
--- a/src/browser/NativeMessagingHost.cpp
+++ b/src/browser/NativeMessagingHost.cpp
@@ -193,6 +193,12 @@ void NativeMessagingHost::removeStoredPermissions()
m_browserService.removeStoredPermissions();
}
+void NativeMessagingHost::convertAttributesToCustomData()
+{
+ QMutexLocker locker(&m_mutex);
+ m_browserService.convertAttributesToCustomData();
+}
+
void NativeMessagingHost::databaseLocked()
{
QJsonObject response;
diff --git a/src/browser/NativeMessagingHost.h b/src/browser/NativeMessagingHost.h
index 80825237b3..9db062badb 100755
--- a/src/browser/NativeMessagingHost.h
+++ b/src/browser/NativeMessagingHost.h
@@ -40,6 +40,7 @@ class NativeMessagingHost : public NativeMessagingBase
public slots:
void removeSharedEncryptionKeys();
void removeStoredPermissions();
+ void convertAttributesToCustomData();
signals:
void quit();
diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp
index dd0c036019..a802e757a2 100644
--- a/src/gui/MainWindow.cpp
+++ b/src/gui/MainWindow.cpp
@@ -140,6 +140,7 @@ class BrowserPlugin: public ISettingsPage
BrowserOptionDialog* dlg = new BrowserOptionDialog(m_dbTabWidget);
QObject::connect(dlg, SIGNAL(removeSharedEncryptionKeys()), m_nativeMessagingHost.data(), SLOT(removeSharedEncryptionKeys()));
QObject::connect(dlg, SIGNAL(removeStoredPermissions()), m_nativeMessagingHost.data(), SLOT(removeStoredPermissions()));
+ QObject::connect(dlg, SIGNAL(convertAttributesToCustomData()), m_nativeMessagingHost.data(), SLOT(convertAttributesToCustomData()));
return dlg;
}