From f507a7a5557c7cca9570c684920e055c5251b08e Mon Sep 17 00:00:00 2001 From: Aqua-sama Date: Wed, 18 Jul 2018 10:07:51 +0200 Subject: AdBlockRule: move matching logic to FilterRule --- lib/web/urlfilter/filterrule.cpp | 168 ++++++++++++++------------------------- 1 file changed, 59 insertions(+), 109 deletions(-) (limited to 'lib/web/urlfilter/filterrule.cpp') diff --git a/lib/web/urlfilter/filterrule.cpp b/lib/web/urlfilter/filterrule.cpp index 73b357b..ba2181f 100644 --- a/lib/web/urlfilter/filterrule.cpp +++ b/lib/web/urlfilter/filterrule.cpp @@ -1,139 +1,89 @@ #include "filterrule.h" -#include -#include -void parseJson(std::unique_ptr &rule, const QJsonObject &filter) +inline bool isMatchingDomain(const QString &domain, const QString &filter) { - // set action - { - if(!filter.value("whitelist").isUndefined()) { - rule->setActionType(FilterRule::Whitelist); - - } else if(!filter.value("blacklist").isUndefined()) { - rule->setActionType(FilterRule::Blacklist); - - } else if(!filter.value("redirect").isUndefined()) { - rule->setActionType(FilterRule::Redirect); - rule->setRedirectUrl(QUrl::fromUserInput(filter.value("redirect").toString())); - - } else if(!filter.value("setheader").isUndefined()) { - rule->setActionType(FilterRule::SetHeader); - for(const QJsonValue v : filter.value("setheader").toArray()) { - QStringList h = v.toString().split(':'); - rule->addHeaderRule(h.at(0).toLatin1(), h.at(1).toLatin1()); - } - } - + // domain and filter are the same + if(domain == filter) { + return true; } - // set match type - { - const QJsonValue regexpValue = filter.value("regexp"); - const QJsonValue endswithValue = filter.value("endswith"); - const QJsonValue containsValue = filter.value("contains"); - - if(!regexpValue.isUndefined()) { - rule->setMatchType(FilterRule::RegExpMatchRule, regexpValue.toString()); - - } else if(!endswithValue.isUndefined()) { - rule->setMatchType(FilterRule::StringEndsMatchRule, endswithValue.toString()); - - } else if(!containsValue.isUndefined()) { - rule->setMatchType(FilterRule::StringContainsMatchRule, containsValue.toString()); - - } else - rule->setMatchType(FilterRule::MatchAllUrlsRule); + // domain can't be matched by filter if it doesn't end with filter + // ex. example2.com isn't matched by example.com + if(!domain.endsWith(filter)) { + return false; } -} + // match with subdomains + // ex. subdomain.example.com is matched by example.com + int index = domain.indexOf(filter); -FilterRule::FilterRule(const QJsonObject &filter) -{ - m_matcher.setCaseSensitivity(Qt::CaseInsensitive); + // match if (domain ends with filter) && (filter has been found) and (character before filter is '.') + return index > 0 && domain[index - 1] == QLatin1Char('.'); } -void FilterRule::setActionType(ActionType type) +bool FilterRule::isEnabled() const { - m_actionType = type; + return m_isEnabled; } -void FilterRule::setMatchType(MatchType type, const QString &pattern) +bool FilterRule::matchesDomain(const QString &domain) const { - m_matchType = type; - switch (type) { - case RegExpMatchRule: - m_regexp.setPattern(pattern); - break; - case StringEndsMatchRule: - m_pattern = pattern; - break; - case StringContainsMatchRule: - m_matcher.setPattern(pattern); - default: - break; + // no domains have been allowed or blocked -> allow on all domains + if(allowedDomains.isEmpty() && blockedDomains.isEmpty()) + return true; + + if(!blockedDomains.isEmpty()) { + // do not match rule if the domain has been blocked + if(blockedDomains.contains(domain)) + return false; } -} -void FilterRule::setRedirectUrl(const QUrl &url) -{ - m_redirectUrl = url; -} + if(!allowedDomains.isEmpty()) { + if(allowedDomains.contains(domain)) + return true; + } -void FilterRule::addHeaderRule(const QByteArray &header, const QByteArray &value) -{ - m_headers.insert(header, value); + return false; } -bool FilterRule::isValid() const +bool FilterRule::matchesType(QWebEngineUrlRequestInfo::ResourceType type) const { - return (m_matchType != MatchType::InvalidMatch) && (m_actionType != ActionType::InvalidAction); + // no options have been specified -> match all resource types + if(m_resourceTypeOptions.isEmpty()) + return true; + + // this resource type has not been specified -> reject it + if(!m_resourceTypeOptions.contains(type)) + return false; + + // resource type has been specified; true to match, false to exception + return m_resourceTypeOptions.value(type); } -bool FilterRule::process(QWebEngineUrlRequestInfo &info) const +bool FilterRule::matchesUrl(const QUrl &url) const { - Q_ASSERT(m_actionType != ActionType::InvalidAction); + switch (urlMatchType) { + case InvalidMatch: + return false; - if(matchRequestUrl(info.requestUrl().toString(), info.resourceType())) { - switch (m_actionType) { - case ActionType::Whitelist: - info.block(false); - return true; - case ActionType::Blacklist: - info.block(true); - return true; - case ActionType::Redirect: - info.redirect(m_redirectUrl); - return true; - case ActionType::SetHeader: - for(auto it = m_headers.constBegin(); it != m_headers.constEnd(); ++it) { - info.setHttpHeader(it.key(), it.value()); - } - return true; - case ActionType::InvalidAction: - break; - } - } + case RegularExpressionMatch: + if(regexp.match(url.toString()).hasMatch()) + return !m_isException; - return false; -} + case StringContains: + return url.toString().contains(match); -bool FilterRule::matchRequestUrl(const QString &requestUrl, const QWebEngineUrlRequestInfo::ResourceType type) const -{ - Q_ASSERT(m_matchType != MatchType::InvalidMatch); + case StringStartsWith: + return url.toString().startsWith(match); - if(!m_resourceTypeOptions.isEmpty() && !m_resourceTypeOptions.contains(type)) - return false; + case StringEndsWith: + return url.toString().endsWith(match); + + case StringEquals: + return url.toString() == match; + + case DomainMatch: + return isMatchingDomain(url.host(), match); - switch (m_matchType) { - case MatchType::RegExpMatchRule: - return m_regexp.match(requestUrl).hasMatch(); - case MatchType::StringEndsMatchRule: - return requestUrl.endsWith(m_pattern); - case MatchType::StringContainsMatchRule: - return m_matcher.indexIn(requestUrl) != -1; - case MatchType::MatchAllUrlsRule: - return true; - default: - return false; } } -- cgit v1.2.1