aboutsummaryrefslogtreecommitdiff
path: root/lib/urlfilter/matcher.h
diff options
context:
space:
mode:
Diffstat (limited to 'lib/urlfilter/matcher.h')
-rw-r--r--lib/urlfilter/matcher.h109
1 files changed, 109 insertions, 0 deletions
diff --git a/lib/urlfilter/matcher.h b/lib/urlfilter/matcher.h
new file mode 100644
index 0000000..6696958
--- /dev/null
+++ b/lib/urlfilter/matcher.h
@@ -0,0 +1,109 @@
+/*
+ * This file is part of smolbote. It's copyrighted by the contributors recorded
+ * in the version control history of the file, available from its original
+ * location: https://neueland.iserlohn-fortress.net/gitea/aqua/smolbote
+ *
+ * SPDX-License-Identifier: GPL-3.0
+ */
+
+#ifndef SMOLBOTE_URLFILTER_MATCHER
+#define SMOLBOTE_URLFILTER_MATCHER
+
+#include <QUrl>
+#include <QString>
+#include <utility>
+#include <QRegularExpression>
+#include <QStringMatcher>
+#include <QWebEngineUrlRequestInfo>
+
+/** An interface class so we can use templated ContentsMatcher interchangeably
+ */
+class Matcher
+{
+public:
+ virtual ~Matcher() = default;
+
+ virtual void setCaseSensitive(bool matchCase) = 0;
+ virtual bool hasMatch(const QString &where) const = 0;
+};
+
+template <typename T>
+class ContentsMatcher : public Matcher
+{
+public:
+ ContentsMatcher(const QString &pattern, UrlFilter::MatchType type)
+ : patternLength(pattern.length())
+ , matchType(type)
+ {
+ if constexpr(std::is_same_v<T, QRegularExpression>) {
+ matcher.setPatternOptions(matcher.patternOptions() | QRegularExpression::CaseInsensitiveOption);
+ matcher.setPattern(pattern);
+ } else if constexpr(std::is_same_v<T, QStringMatcher>) {
+ matcher.setCaseSensitivity(Qt::CaseInsensitive);
+ matcher.setPattern(pattern);
+ } else if constexpr(std::is_same_v<T, QString>) {
+ matcher = QUrl::fromUserInput(pattern).host();
+ }
+ }
+ ~ContentsMatcher() = default;
+
+ void setCaseSensitive(bool matchCase) override
+ {
+ if constexpr(std::is_same_v<T, QRegularExpression>) {
+ auto options = matcher.patternOptions();
+ options.setFlag(QRegularExpression::CaseInsensitiveOption, !matchCase);
+ matcher.setPatternOptions(options);
+
+ } else if constexpr(std::is_same_v<T, QStringMatcher>) {
+ matcher.setCaseSensitivity(matchCase ? Qt::CaseSensitive : Qt::CaseInsensitive);
+ }
+ }
+
+ bool hasMatch(const QString &where) const override
+ {
+ if constexpr(std::is_same_v<T, QStringMatcher>) {
+ switch (matchType) {
+ case UrlFilter::InvalidMatch:
+ case UrlFilter::RegularExpressionMatch:
+ case UrlFilter::DomainMatch:
+ qWarning("ContentsMatcher is a String Matcher, but not doing string matching!");
+ return false;
+
+ case UrlFilter::StringContains:
+ return (matcher.indexIn(where) != -1);
+
+ case UrlFilter::StringStartsWith:
+ return (matcher.indexIn(where) == 0);
+
+ case UrlFilter::StringEndsWith:
+ return (matcher.indexIn(where) == where.length() - patternLength);
+
+ case UrlFilter::StringEquals:
+ return (matcher.indexIn(where) == 0) && (patternLength == where.length());
+ }
+
+ } else if constexpr(std::is_same_v<T, QRegularExpression>) {
+ if(matchType != UrlFilter::RegularExpressionMatch)
+ qWarning("ContentsMatcher is a regular expression, but not doing a regular expression match!");
+ return matcher.match(where).hasMatch();
+ } else if constexpr(std::is_same_v<T, QString>) {
+ // TODO: fix
+ if(matchType == UrlFilter::DomainMatch) {
+// qDebug("matching %s", qUtf8Printable(QUrl(where).host()));
+ return QUrl(where).host().endsWith(matcher);
+ } else
+ return matcher == where;
+ }
+
+ qWarning("Matcher has no backend, returning false");
+ return false;
+ }
+
+private:
+ const int patternLength;
+ const UrlFilter::MatchType matchType;
+ T matcher;
+};
+
+#endif // SMOLBOTE_URLFILTER_MATCHER
+