diff --git a/src/browser/BrowserService.cpp b/src/browser/BrowserService.cpp index 5bc16eb36e..1271c083d1 100644 --- a/src/browser/BrowserService.cpp +++ b/src/browser/BrowserService.cpp @@ -1009,8 +1009,10 @@ bool BrowserService::removeFirstDomain(QString& hostname) bool BrowserService::handleEntry(Entry* entry, const QString& url, const QString& submitUrl) { // Use this special scheme to find entries by UUID - if (url.startsWith("keepassxc://")) { - return ("keepassxc://by-uuid/" + entry->uuidToHex()) == url; + if (url.startsWith("keepassxc://by-uuid/")) { + return url.endsWith("by-uuid/" + entry->uuidToHex()); + } else if (url.startsWith("keepassxc://by-path/")) { + return url.endsWith("by-path/" + entry->path()); } return handleURL(entry->url(), url, submitUrl); } diff --git a/src/core/Entry.cpp b/src/core/Entry.cpp index 82c9e7bc39..bc31e9caf8 100644 --- a/src/core/Entry.cpp +++ b/src/core/Entry.cpp @@ -503,6 +503,13 @@ QString Entry::totpSettingsString() const return {}; } +QString Entry::path() const +{ + auto path = group()->hierarchy(); + path << title(); + return path.mid(1).join("/"); +} + void Entry::setUuid(const QUuid& uuid) { Q_ASSERT(!uuid.isNull()); diff --git a/src/core/Entry.h b/src/core/Entry.h index a0dbbf7d4f..e76ee9acbf 100644 --- a/src/core/Entry.h +++ b/src/core/Entry.h @@ -109,6 +109,7 @@ class Entry : public QObject QString totpSettingsString() const; QSharedPointer totpSettings() const; int size() const; + QString path() const; bool hasTotp() const; bool isExpired() const; diff --git a/tests/TestBrowser.cpp b/tests/TestBrowser.cpp index 05f3155316..a82ed6ef80 100644 --- a/tests/TestBrowser.cpp +++ b/tests/TestBrowser.cpp @@ -216,6 +216,43 @@ void TestBrowser::testSearchEntries() QCOMPARE(result[3]->url(), QString("github.com/login")); } +void TestBrowser::testSearchEntriesByPath() +{ + auto db = QSharedPointer::create(); + auto* root = db->rootGroup(); + + QStringList urlsRoot = {"https://root.example.com/", "root.example.com/login"}; + auto entriesRoot = createEntries(urlsRoot, root); + + auto* groupLevel1 = new Group(); + groupLevel1->setParent(root); + groupLevel1->setName("TestGroup1"); + QStringList urlsLevel1 = {"https://1.example.com/", "1.example.com/login"}; + auto entriesLevel1 = createEntries(urlsLevel1, groupLevel1); + + auto* groupLevel2 = new Group(); + groupLevel2->setParent(groupLevel1); + groupLevel2->setName("TestGroup2"); + QStringList urlsLevel2 = {"https://2.example.com/", "2.example.com/login"}; + auto entriesLevel2 = createEntries(urlsLevel2, groupLevel2); + + compareEntriesByPath(db, entriesRoot, ""); + compareEntriesByPath(db, entriesLevel1, "TestGroup1/"); + compareEntriesByPath(db, entriesLevel2, "TestGroup1/TestGroup2/"); +} + +void TestBrowser::compareEntriesByPath(QSharedPointer db, QList entries, QString path) +{ + for (Entry* entry : entries) { + QString testUrl = "keepassxc://by-path/" + path + entry->title(); + /* Look for an entry with that path. First using handleEntry, then through the search */ + QCOMPARE(m_browserService->handleEntry(entry, testUrl, ""), true); + auto result = m_browserService->searchEntries(db, testUrl, ""); + QCOMPARE(result.length(), 1); + QCOMPARE(result[0], entry); + } +} + void TestBrowser::testSearchEntriesByUUID() { auto db = QSharedPointer::create(); @@ -461,6 +498,7 @@ QList TestBrowser::createEntries(QStringList& urls, Group* root) const entry->setUrl(urls[i]); entry->setUsername(QString("User %1").arg(i)); entry->setUuid(QUuid::createUuid()); + entry->setTitle(QString("Name_%1").arg(entry->uuidToHex())); entry->endUpdate(); entries.push_back(entry); } diff --git a/tests/TestBrowser.h b/tests/TestBrowser.h index bcdc609ddd..c04aa56277 100644 --- a/tests/TestBrowser.h +++ b/tests/TestBrowser.h @@ -42,6 +42,7 @@ private slots: void testSortPriority(); void testSortPriority_data(); void testSearchEntries(); + void testSearchEntriesByPath(); void testSearchEntriesByUUID(); void testSearchEntriesWithPort(); void testSearchEntriesWithAdditionalURLs(); @@ -54,9 +55,9 @@ private slots: private: QList createEntries(QStringList& urls, Group* root) const; + void compareEntriesByPath(QSharedPointer db, QList entries, QString path); QScopedPointer m_browserAction; QPointer m_browserService; }; - #endif // KEEPASSXC_TESTBROWSER_H