/* * 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