aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAqua-sama <aqua@iserlohn-fortress.net>2018-07-12 19:57:01 +0200
committerAqua-sama <aqua@iserlohn-fortress.net>2018-07-12 19:57:01 +0200
commitfde1d3399d0d51250c31315dca4cbc9044d36b9d (patch)
tree19e1afef9e8803f19f4f446a68303c5870e238f2
parentWebView: add Open in new tab and Save actions for images (diff)
downloadsmolbote-fde1d3399d0d51250c31315dca4cbc9044d36b9d.tar.xz
AdBlockRule: parse some options
-rw-r--r--lib/web/urlfilter/adblockrule.cpp65
-rw-r--r--lib/web/urlfilter/adblockrule.h2
-rw-r--r--test/urlfilter/adblocktest.cpp5
-rw-r--r--test/urlfilter/adblocktest.h2
4 files changed, 74 insertions, 0 deletions
diff --git a/lib/web/urlfilter/adblockrule.cpp b/lib/web/urlfilter/adblockrule.cpp
index d707783..505cda5 100644
--- a/lib/web/urlfilter/adblockrule.cpp
+++ b/lib/web/urlfilter/adblockrule.cpp
@@ -21,6 +21,32 @@ bool isMatchingDomain(const QString &domain, const QString &filter)
return index > 0 && domain[index - 1] == QLatin1Char('.');
}
+inline std::pair<QWebEngineUrlRequestInfo::ResourceType, bool> parseOption(const QString &option)
+{
+ if(option.endsWith(QLatin1Literal("script"))) {
+ return std::make_pair(QWebEngineUrlRequestInfo::ResourceTypeScript, !option.startsWith(QLatin1Literal("~")));
+
+ } else if(option.endsWith(QLatin1Literal("image"))) {
+ return std::make_pair(QWebEngineUrlRequestInfo::ResourceTypeImage, !option.startsWith(QLatin1Literal("~")));
+
+ } else if(option.endsWith(QLatin1Literal("stylesheet"))) {
+ return std::make_pair(QWebEngineUrlRequestInfo::ResourceTypeStylesheet, !option.startsWith(QLatin1Literal("~")));
+
+ } else if(option.endsWith(QLatin1Literal("object"))) {
+ return std::make_pair(QWebEngineUrlRequestInfo::ResourceTypeObject, !option.startsWith(QLatin1Literal("~")));
+
+ } else if(option.endsWith(QLatin1Literal("xmlhttprequest"))) {
+ return std::make_pair(QWebEngineUrlRequestInfo::ResourceTypeXhr, !option.startsWith(QLatin1Literal("~")));
+
+ } else if(option.endsWith(QLatin1Literal("other"))) {
+ return std::make_pair(QWebEngineUrlRequestInfo::ResourceTypeUnknown, !option.startsWith(QLatin1Literal("~")));
+
+ } else {
+ // unhandled pair
+ Q_ASSERT(false);
+ }
+}
+
// adblock format documentation
// https://adblockplus.org/filters
@@ -50,6 +76,31 @@ AdBlockRule::AdBlockRule(const QString &filter)
parsedLine.remove(0, 2);
}
+ // parse options
+ {
+ const int sepPos = parsedLine.indexOf(QLatin1Literal("$"));
+ if(sepPos != -1) {
+ const auto options = parsedLine.mid(sepPos + 1).split(QLatin1Literal(","));
+ parsedLine = parsedLine.mid(0, sepPos);
+
+ for(const QString &option : options) {
+ if(option.startsWith(QLatin1Literal("domain"))) {
+ const auto domainList = option.mid(7).split(QLatin1Literal("|"));
+ for(const QString &domain : domainList) {
+ if(domain.startsWith(QLatin1Literal("~")))
+ blockedDomains.append(domain.mid(1));
+ else
+ allowedDomains.append(domain);
+ }
+ } else {
+ auto optPair = parseOption(option);
+ m_resourceTypeOptions.insert(optPair.first, optPair.second);
+ }
+ }
+
+ }
+ }
+
// regular expression rules
if(parsedLine.startsWith(QLatin1Literal("/")) && parsedLine.endsWith(QLatin1Literal("/"))) {
parsedLine = parsedLine.mid(1, parsedLine.length() - 2);
@@ -101,6 +152,20 @@ bool AdBlockRule::isEnabled() const
return m_isEnabled;
}
+bool AdBlockRule::matches(QWebEngineUrlRequestInfo::ResourceType type) const
+{
+ // 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 AdBlockRule::shouldBlock(const QUrl &url) const
{
switch (matchType) {
diff --git a/lib/web/urlfilter/adblockrule.h b/lib/web/urlfilter/adblockrule.h
index e1cabae..a08fbb7 100644
--- a/lib/web/urlfilter/adblockrule.h
+++ b/lib/web/urlfilter/adblockrule.h
@@ -24,6 +24,7 @@ public:
AdBlockRule(const QString &filter);
bool isEnabled() const;
+ bool matches(QWebEngineUrlRequestInfo::ResourceType type) const;
bool shouldBlock(const QUrl &url) const;
private:
@@ -34,6 +35,7 @@ private:
MatchType matchType = InvalidMatch;
QHash<QWebEngineUrlRequestInfo::ResourceType, bool> m_resourceTypeOptions;
+ QStringList allowedDomains, blockedDomains;
QString match;
QRegularExpression regexp;
diff --git a/test/urlfilter/adblocktest.cpp b/test/urlfilter/adblocktest.cpp
index d1060f1..58bafc5 100644
--- a/test/urlfilter/adblocktest.cpp
+++ b/test/urlfilter/adblocktest.cpp
@@ -37,4 +37,9 @@ void AdBlockTest::blockExactAddress()
QCOMPARE(rule.shouldBlock(QUrl("http://example.info/redirect/http://example.com/")), false);
}
+void AdBlockTest::parseOptions()
+{
+ AdBlockRule rule("annoying_banners/ads$image,script");
+}
+
QTEST_GUILESS_MAIN(AdBlockTest)
diff --git a/test/urlfilter/adblocktest.h b/test/urlfilter/adblocktest.h
index a7b9f12..00ad118 100644
--- a/test/urlfilter/adblocktest.h
+++ b/test/urlfilter/adblocktest.h
@@ -10,6 +10,8 @@ private slots:
void blockByAddressPart();
void blockByDomain();
void blockExactAddress();
+
+ void parseOptions();
};
#endif // ADBLOCKTEST_H