Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/keepassxreboot/keepassxc.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/EntrySearcher.cpp')
-rw-r--r--src/core/EntrySearcher.cpp44
1 files changed, 32 insertions, 12 deletions
diff --git a/src/core/EntrySearcher.cpp b/src/core/EntrySearcher.cpp
index 21b86a7a1..3b9472c6f 100644
--- a/src/core/EntrySearcher.cpp
+++ b/src/core/EntrySearcher.cpp
@@ -21,8 +21,9 @@
#include "core/Group.h"
#include "core/Tools.h"
-EntrySearcher::EntrySearcher(bool caseSensitive)
+EntrySearcher::EntrySearcher(bool caseSensitive, bool skipProtected)
: m_caseSensitive(caseSensitive)
+ , m_skipProtected(skipProtected)
, m_termParser(R"re(([-!*+]+)?(?:(\w*):)?(?:(?=")"((?:[^"\\]|\\.)*)"|([^ ]*))( |$))re")
// Group 1 = modifiers, Group 2 = field, Group 3 = quoted string, Group 4 = unquoted string
{
@@ -54,7 +55,6 @@ QList<Entry*> EntrySearcher::search(const QList<SearchTerm>& searchTerms, const
QList<Entry*> EntrySearcher::search(const QString& searchString, const Group* baseGroup, bool forceSearch)
{
Q_ASSERT(baseGroup);
-
parseSearchTerms(searchString);
return repeat(baseGroup, forceSearch);
}
@@ -73,7 +73,7 @@ QList<Entry*> EntrySearcher::repeat(const Group* baseGroup, bool forceSearch)
QList<Entry*> results;
for (const auto group : baseGroup->groupsRecursive(true)) {
if (forceSearch || group->resolveSearchingEnabled()) {
- for (auto* entry : group->entries()) {
+ for (const auto entry : group->entries()) {
if (searchEntryImpl(entry)) {
results.append(entry);
}
@@ -137,19 +137,23 @@ void EntrySearcher::setCaseSensitive(bool state)
m_caseSensitive = state;
}
-bool EntrySearcher::isCaseSensitive()
+bool EntrySearcher::isCaseSensitive() const
{
return m_caseSensitive;
}
-bool EntrySearcher::searchEntryImpl(Entry* entry)
+bool EntrySearcher::searchEntryImpl(const Entry* entry)
{
// Pre-load in case they are needed
auto attributes_keys = entry->attributes()->customKeys();
auto attributes = QStringList(attributes_keys + entry->attributes()->values(attributes_keys));
auto attachments = QStringList(entry->attachments()->keys());
+ // Build a group hierarchy to allow searching for e.g. /group1/subgroup*
+ auto hierarchy = entry->group()->hierarchy().join('/').prepend("/");
- bool found;
+ // By default, empty term matches every entry.
+ // However when skipping protected fields, we will recject everything instead
+ bool found = !m_skipProtected;
for (const auto& term : m_searchTerms) {
switch (term.field) {
case Field::Title:
@@ -159,6 +163,9 @@ bool EntrySearcher::searchEntryImpl(Entry* entry)
found = term.regex.match(entry->resolvePlaceholder(entry->username())).hasMatch();
break;
case Field::Password:
+ if (m_skipProtected) {
+ continue;
+ }
found = term.regex.match(entry->resolvePlaceholder(entry->password())).hasMatch();
break;
case Field::Url:
@@ -174,13 +181,20 @@ bool EntrySearcher::searchEntryImpl(Entry* entry)
found = !attachments.filter(term.regex).empty();
break;
case Field::AttributeValue:
- // skip protected attributes
- if (entry->attributes()->isProtected(term.word)) {
+ if (m_skipProtected && entry->attributes()->isProtected(term.word)) {
continue;
}
found = entry->attributes()->contains(term.word)
&& term.regex.match(entry->attributes()->value(term.word)).hasMatch();
break;
+ case Field::Group:
+ // Match against the full hierarchy if the word contains a '/' otherwise just the group name
+ if (term.word.contains('/')) {
+ found = term.regex.match(hierarchy).hasMatch();
+ } else {
+ found = term.regex.match(entry->group()->name()).hasMatch();
+ }
+ break;
default:
// Terms without a specific field try to match title, username, url, and notes
found = term.regex.match(entry->resolvePlaceholder(entry->title())).hasMatch()
@@ -189,13 +203,18 @@ bool EntrySearcher::searchEntryImpl(Entry* entry)
|| term.regex.match(entry->notes()).hasMatch();
}
- // Short circuit if we failed to match or we matched and are excluding this term
- if ((!found && !term.exclude) || (found && term.exclude)) {
+ // negate the result if exclude:
+ // * if found and not excluding, the entry matches
+ // * if didn't found but excluding, the entry also matches
+ found = (found && !term.exclude) || (!found && term.exclude);
+
+ // short circuit if we failed the match
+ if (!found) {
return false;
}
}
- return true;
+ return found;
}
void EntrySearcher::parseSearchTerms(const QString& searchString)
@@ -209,7 +228,8 @@ void EntrySearcher::parseSearchTerms(const QString& searchString)
{QStringLiteral("title"), Field::Title},
{QStringLiteral("u"), Field::Username}, // u: stands for username rather than url
{QStringLiteral("url"), Field::Url},
- {QStringLiteral("username"), Field::Username}};
+ {QStringLiteral("username"), Field::Username},
+ {QStringLiteral("group"), Field::Group}};
m_searchTerms.clear();
auto results = m_termParser.globalMatch(searchString);