mirror of
https://github.com/keepassxreboot/keepassxc.git
synced 2024-12-24 14:59:44 -05:00
parent
4a21cee98c
commit
7f92504a2d
@ -281,7 +281,7 @@ QString Entry::effectiveAutoTypeSequence() const
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrive the autotype sequences matches for a given windowTitle
|
||||
* Retrieve the Auto-Type sequences matches for a given windowTitle
|
||||
* This returns a list with priority ordering. If you don't want duplicates call .toSet() on it.
|
||||
*/
|
||||
QList<QString> Entry::autoTypeSequences(const QString& windowTitle) const
|
||||
@ -295,13 +295,14 @@ QList<QString> Entry::autoTypeSequences(const QString& windowTitle) const
|
||||
auto windowMatches = [&](const QString& pattern) {
|
||||
// Regex searching
|
||||
if (pattern.startsWith("//") && pattern.endsWith("//") && pattern.size() >= 4) {
|
||||
QRegExp regExp(pattern.mid(2, pattern.size() - 4), Qt::CaseInsensitive, QRegExp::RegExp2);
|
||||
return (regExp.indexIn(windowTitle) != -1);
|
||||
QRegularExpression regExp(pattern.mid(2, pattern.size() - 4), QRegularExpression::CaseInsensitiveOption);
|
||||
return regExp.match(windowTitle).hasMatch();
|
||||
}
|
||||
|
||||
// Wildcard searching
|
||||
auto regex = Tools::convertToRegex(pattern, true, false, false);
|
||||
return windowTitle.contains(regex);
|
||||
const auto regExp = Tools::convertToRegex(
|
||||
pattern, Tools::RegexConvertOpts::EXACT_MATCH | Tools::RegexConvertOpts::WILDCARD_UNLIMITED_MATCH);
|
||||
return regExp.match(windowTitle).hasMatch();
|
||||
};
|
||||
|
||||
auto windowMatchesTitle = [&](const QString& entryTitle) {
|
||||
|
@ -277,7 +277,14 @@ void EntrySearcher::parseSearchTerms(const QString& searchString)
|
||||
auto mods = result.captured(1);
|
||||
|
||||
// Convert term to regex
|
||||
term.regex = Tools::convertToRegex(term.word, !mods.contains("*"), mods.contains("+"), m_caseSensitive);
|
||||
int opts = m_caseSensitive ? Tools::RegexConvertOpts::CASE_SENSITIVE : Tools::RegexConvertOpts::DEFAULT;
|
||||
if (!mods.contains("*")) {
|
||||
opts |= Tools::RegexConvertOpts::WILDCARD_ALL;
|
||||
}
|
||||
if (mods.contains("+")) {
|
||||
opts |= Tools::RegexConvertOpts::EXACT_MATCH;
|
||||
}
|
||||
term.regex = Tools::convertToRegex(term.word, opts);
|
||||
|
||||
// Exclude modifier
|
||||
term.exclude = mods.contains("-") || mods.contains("!");
|
||||
|
@ -296,27 +296,35 @@ namespace Tools
|
||||
return true;
|
||||
}
|
||||
|
||||
// Escape common regex symbols except for *, ?, and |
|
||||
auto regexEscape = QRegularExpression(R"re(([-[\]{}()+.,\\\/^$#]))re");
|
||||
// Escape regex symbols
|
||||
auto regexEscape = QRegularExpression(R"re(([-[\]{}()+.,\\\/^$#|*?]))re");
|
||||
|
||||
QRegularExpression convertToRegex(const QString& string, bool useWildcards, bool exactMatch, bool caseSensitive)
|
||||
QRegularExpression convertToRegex(const QString& string, int opts)
|
||||
{
|
||||
QString pattern = string;
|
||||
|
||||
// Wildcard support (*, ?, |)
|
||||
if (useWildcards) {
|
||||
if (opts & RegexConvertOpts::WILDCARD_ALL || opts & RegexConvertOpts::ESCAPE_REGEX) {
|
||||
pattern.replace(regexEscape, "\\\\1");
|
||||
pattern.replace("*", ".*");
|
||||
pattern.replace("?", ".");
|
||||
|
||||
if (opts & RegexConvertOpts::WILDCARD_UNLIMITED_MATCH) {
|
||||
pattern.replace("\\*", ".*");
|
||||
}
|
||||
if (opts & RegexConvertOpts::WILDCARD_SINGLE_MATCH) {
|
||||
pattern.replace("\\?", ".");
|
||||
}
|
||||
if (opts & RegexConvertOpts::WILDCARD_LOGICAL_OR) {
|
||||
pattern.replace("\\|", "|");
|
||||
}
|
||||
}
|
||||
|
||||
// Exact modifier
|
||||
if (exactMatch) {
|
||||
if (opts & RegexConvertOpts::EXACT_MATCH) {
|
||||
pattern = "^" + pattern + "$";
|
||||
}
|
||||
|
||||
auto regex = QRegularExpression(pattern);
|
||||
if (!caseSensitive) {
|
||||
if ((opts & RegexConvertOpts::CASE_SENSITIVE) != RegexConvertOpts::CASE_SENSITIVE) {
|
||||
regex.setPatternOptions(QRegularExpression::CaseInsensitiveOption);
|
||||
}
|
||||
|
||||
|
@ -42,13 +42,23 @@ namespace Tools
|
||||
QString uuidToHex(const QUuid& uuid);
|
||||
QUuid hexToUuid(const QString& uuid);
|
||||
bool isValidUuid(const QString& uuidStr);
|
||||
QRegularExpression convertToRegex(const QString& string,
|
||||
bool useWildcards = false,
|
||||
bool exactMatch = false,
|
||||
bool caseSensitive = false);
|
||||
QString envSubstitute(const QString& filepath,
|
||||
QProcessEnvironment environment = QProcessEnvironment::systemEnvironment());
|
||||
|
||||
enum RegexConvertOpts
|
||||
{
|
||||
DEFAULT = 0,
|
||||
WILDCARD_UNLIMITED_MATCH = 0x1,
|
||||
WILDCARD_SINGLE_MATCH = 0x2,
|
||||
WILDCARD_LOGICAL_OR = 0x4,
|
||||
WILDCARD_ALL = WILDCARD_UNLIMITED_MATCH | WILDCARD_SINGLE_MATCH | WILDCARD_LOGICAL_OR,
|
||||
EXACT_MATCH = 0x8,
|
||||
CASE_SENSITIVE = 0x16,
|
||||
ESCAPE_REGEX = 0x32,
|
||||
};
|
||||
|
||||
QRegularExpression convertToRegex(const QString& string, int opts = RegexConvertOpts::DEFAULT);
|
||||
|
||||
template <typename RandomAccessIterator, typename T>
|
||||
RandomAccessIterator binaryFind(RandomAccessIterator begin, RandomAccessIterator end, const T& value)
|
||||
{
|
||||
|
@ -294,11 +294,10 @@ namespace FdoSecrets
|
||||
term.field = attrKeyToField.value(key, EntrySearcher::Field::AttributeValue);
|
||||
term.word = key;
|
||||
term.exclude = false;
|
||||
|
||||
const auto useWildcards = false;
|
||||
const auto exactMatch = true;
|
||||
const auto caseSensitive = true;
|
||||
term.regex = Tools::convertToRegex(QRegularExpression::escape(value), useWildcards, exactMatch, caseSensitive);
|
||||
term.regex =
|
||||
Tools::convertToRegex(value,
|
||||
Tools::RegexConvertOpts::EXACT_MATCH | Tools::RegexConvertOpts::CASE_SENSITIVE
|
||||
| Tools::RegexConvertOpts::ESCAPE_REGEX);
|
||||
|
||||
return term;
|
||||
}
|
||||
|
@ -19,6 +19,7 @@
|
||||
|
||||
#include "core/Clock.h"
|
||||
|
||||
#include <QRegularExpression>
|
||||
#include <QTest>
|
||||
#include <QUuid>
|
||||
|
||||
@ -163,3 +164,37 @@ void TestTools::testBackupFilePatternSubstitution()
|
||||
|
||||
QCOMPARE(Tools::substituteBackupFilePath(pattern, dbFilePath), expectedSubstitution);
|
||||
}
|
||||
|
||||
void TestTools::testConvertToRegex()
|
||||
{
|
||||
QFETCH(QString, input);
|
||||
QFETCH(int, options);
|
||||
QFETCH(QString, expected);
|
||||
|
||||
auto regex = Tools::convertToRegex(input, options).pattern();
|
||||
QCOMPARE(regex, expected);
|
||||
}
|
||||
|
||||
void TestTools::testConvertToRegex_data()
|
||||
{
|
||||
const QString input = R"(te|st*t?[5]^(test);',.)";
|
||||
|
||||
QTest::addColumn<QString>("input");
|
||||
QTest::addColumn<int>("options");
|
||||
QTest::addColumn<QString>("expected");
|
||||
|
||||
QTest::newRow("No Options") << input << static_cast<int>(Tools::RegexConvertOpts::DEFAULT)
|
||||
<< QString(R"(te|st*t?[5]^(test);',.)");
|
||||
QTest::newRow("Exact Match") << input << static_cast<int>(Tools::RegexConvertOpts::EXACT_MATCH)
|
||||
<< QString(R"(^te|st*t?[5]^(test);',.$)");
|
||||
QTest::newRow("Exact Match & Wildcard")
|
||||
<< input << static_cast<int>(Tools::RegexConvertOpts::EXACT_MATCH | Tools::RegexConvertOpts::WILDCARD_ALL)
|
||||
<< QString(R"(^te|st.*t.\[5\]\^\(test\);'\,\.$)");
|
||||
QTest::newRow("Wildcard Single Match") << input << static_cast<int>(Tools::RegexConvertOpts::WILDCARD_SINGLE_MATCH)
|
||||
<< QString(R"(te\|st\*t.\[5\]\^\(test\);'\,\.)");
|
||||
QTest::newRow("Wildcard OR") << input << static_cast<int>(Tools::RegexConvertOpts::WILDCARD_LOGICAL_OR)
|
||||
<< QString(R"(te|st\*t\?\[5\]\^\(test\);'\,\.)");
|
||||
QTest::newRow("Wildcard Unlimited Match")
|
||||
<< input << static_cast<int>(Tools::RegexConvertOpts::WILDCARD_UNLIMITED_MATCH)
|
||||
<< QString(R"(te\|st.*t\?\[5\]\^\(test\);'\,\.)");
|
||||
}
|
||||
|
@ -31,6 +31,8 @@ private slots:
|
||||
void testValidUuid();
|
||||
void testBackupFilePatternSubstitution_data();
|
||||
void testBackupFilePatternSubstitution();
|
||||
void testConvertToRegex();
|
||||
void testConvertToRegex_data();
|
||||
};
|
||||
|
||||
#endif // KEEPASSX_TESTTOOLS_H
|
||||
|
Loading…
Reference in New Issue
Block a user