From 3d2ae07c455c0e423c64f19e445518427a5684fa Mon Sep 17 00:00:00 2001 From: Aqua-sama Date: Wed, 9 Jan 2019 19:38:58 +0100 Subject: Rewrite lib/urlfilter - Make HostList and AdBlockList implementations independent from each other - Move urlfilter tests to lib/urlfilter --- lib/urlfilter/matcher.h | 109 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 lib/urlfilter/matcher.h (limited to 'lib/urlfilter/matcher.h') 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 +#include +#include +#include +#include +#include + +/** 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 +class ContentsMatcher : public Matcher +{ +public: + ContentsMatcher(const QString &pattern, UrlFilter::MatchType type) + : patternLength(pattern.length()) + , matchType(type) + { + if constexpr(std::is_same_v) { + matcher.setPatternOptions(matcher.patternOptions() | QRegularExpression::CaseInsensitiveOption); + matcher.setPattern(pattern); + } else if constexpr(std::is_same_v) { + matcher.setCaseSensitivity(Qt::CaseInsensitive); + matcher.setPattern(pattern); + } else if constexpr(std::is_same_v) { + matcher = QUrl::fromUserInput(pattern).host(); + } + } + ~ContentsMatcher() = default; + + void setCaseSensitive(bool matchCase) override + { + if constexpr(std::is_same_v) { + auto options = matcher.patternOptions(); + options.setFlag(QRegularExpression::CaseInsensitiveOption, !matchCase); + matcher.setPatternOptions(options); + + } else if constexpr(std::is_same_v) { + matcher.setCaseSensitivity(matchCase ? Qt::CaseSensitive : Qt::CaseInsensitive); + } + } + + bool hasMatch(const QString &where) const override + { + if constexpr(std::is_same_v) { + 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) { + 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) { + // 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 + -- cgit v1.2.1