aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAqua-sama <aqua@iserlohn-fortress.net>2017-05-24 15:29:25 +0200
committerAqua-sama <aqua@iserlohn-fortress.net>2017-05-24 15:29:25 +0200
commit863da92c57a5d6245bac3885936f59da88041e75 (patch)
tree9125ee3ac879c8be44019e5ffc27a5c3b4d2a92e /src
parentReworking URL filter (diff)
downloadsmolbote-863da92c57a5d6245bac3885936f59da88041e75.tar.xz
Improved filter rules
Diffstat (limited to 'src')
-rw-r--r--src/blocker/blockermanager.cpp2
-rw-r--r--src/blocker/blockerrule.cpp62
-rw-r--r--src/blocker/blockersubscription.cpp104
-rw-r--r--src/blocker/filtercollection.cpp174
-rw-r--r--src/blocker/filtercollection.h (renamed from src/blocker/blockersubscription.h)10
-rw-r--r--src/blocker/filterrule.cpp119
-rw-r--r--src/blocker/filterrule.h (renamed from src/blocker/blockerrule.h)69
-rw-r--r--src/blocker/regexp.cpp4
-rw-r--r--src/webengine/urlinterceptor.cpp6
9 files changed, 337 insertions, 213 deletions
diff --git a/src/blocker/blockermanager.cpp b/src/blocker/blockermanager.cpp
index 8763502..ee30b65 100644
--- a/src/blocker/blockermanager.cpp
+++ b/src/blocker/blockermanager.cpp
@@ -25,7 +25,7 @@
#include <QLabel>
#include <QListWidget>
-#include "blocker/blockersubscription.h"
+#include "blocker/filtercollection.h"
BlockerManager::BlockerManager(QWidget *parent) :
QDialog(parent),
diff --git a/src/blocker/blockerrule.cpp b/src/blocker/blockerrule.cpp
deleted file mode 100644
index ca4f339..0000000
--- a/src/blocker/blockerrule.cpp
+++ /dev/null
@@ -1,62 +0,0 @@
-/*******************************************************************************
- **
- ** smolbote: yet another qute browser
- ** Copyright (C) 2017 Xian Nox
- **
- ** This program is free software: you can redistribute it and/or modify
- ** it under the terms of the GNU General Public License as published by
- ** the Free Software Foundation, either version 3 of the License, or
- ** (at your option) any later version.
- **
- ** This program is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ** GNU General Public License for more details.
- **
- ** You should have received a copy of the GNU General Public License
- ** along with this program. If not, see <http://www.gnu.org/licenses/>.
- **
- ******************************************************************************/
-
-#include "blockerrule.h"
-
-BlockerRule::BlockerRule(RegExp firstPartyUrl, RegExp requestUrl, NavigationType nav, ResourceType res, bool shouldBlock, QObject *parent) :
- QObject(parent)
-{
- m_firstPartyUrl = firstPartyUrl;
- m_requestUrl = requestUrl;
- m_navRules = nav;
- m_resRules = res;
- m_shouldBlock = shouldBlock;
-
- m_valid = true;
-
-}
-
-bool BlockerRule::match(const QWebEngineUrlRequestInfo &info)
-{
- if(!m_valid) {
- return false;
- }
-
- // if both domain and rule match
- if(m_firstPartyUrl.hasMatch(info.firstPartyUrl().toString()) && m_requestUrl.hasMatch(info.requestUrl().toString())) {
-
- // TODO: check options
-
- return m_shouldBlock;
- }
-
- // domain and/or rule do not match
- return false;
-}
-
-bool BlockerRule::isValid()
-{
- return m_valid;
-}
-
-QString BlockerRule::filter() const
-{
- return m_firstPartyUrl.pattern() + m_requestUrl.pattern();
-}
diff --git a/src/blocker/blockersubscription.cpp b/src/blocker/blockersubscription.cpp
deleted file mode 100644
index c452511..0000000
--- a/src/blocker/blockersubscription.cpp
+++ /dev/null
@@ -1,104 +0,0 @@
-/*******************************************************************************
- **
- ** smolbote: yet another qute browser
- ** Copyright (C) 2017 Xian Nox
- **
- ** This program is free software: you can redistribute it and/or modify
- ** it under the terms of the GNU General Public License as published by
- ** the Free Software Foundation, either version 3 of the License, or
- ** (at your option) any later version.
- **
- ** This program is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ** GNU General Public License for more details.
- **
- ** You should have received a copy of the GNU General Public License
- ** along with this program. If not, see <http://www.gnu.org/licenses/>.
- **
- ******************************************************************************/
-
-#include "blockersubscription.h"
-#include "ui_subscriptionform.h"
-
-#include "browser.h"
-#include <QNetworkRequest>
-#include <QNetworkReply>
-
-#include <QJsonDocument>
-#include <QJsonObject>
-#include <QJsonArray>
-
-FilterCollection::FilterCollection(const QString path, QWidget *parent) :
- QWidget(parent),
- ui(new Ui::SubscriptionForm)
-{
- ui->setupUi(this);
-
- m_name = "TODO";
- m_path = path;
-
- qDebug("Adding subscription [%s]", qUtf8Printable(m_path));
-
-
- QFile filterFile(m_path);
- if(!filterFile.open(QIODevice::ReadOnly)) {
- qWarning("Could not open filter!");
- return;
- }
-
- QJsonDocument filters(QJsonDocument::fromJson(filterFile.readAll()));
- load(filters.object());
-
- qDebug("Added %i rules", m_rules.size());
-}
-
-FilterCollection::~FilterCollection()
-{
- delete ui;
-}
-
-QString FilterCollection::name() const
-{
- return m_name;
-}
-
-/**
- * Check if a URL request should be blocked or not
- * @param info
- * @return true if it should be blocked; false otherwise
- */
-FilterCollection::MatchResult FilterCollection::match(QWebEngineUrlRequestInfo &info)
-{
- MatchResult result;
-
- for(auto rule : qAsConst(m_rules)) {
- result.match = true;
- result.block = rule->match(info);
- result.pattern = rule->filter();
- return result;
- }
-
- // request matches neither whitelist nor blacklist
- result.match = false;
- result.block = false;
- return result;
-}
-
-void FilterCollection::load(const QJsonObject &json)
-{
- for(QJsonValue v : json["rules"].toArray()) {
- m_rules.append(createRule(v.toObject()));
- }
-}
-
-BlockerRule* FilterCollection::createRule(const QJsonObject &obj)
-{
- BlockerRule *rule;
-
- BlockerRule::NavigationType n;
- BlockerRule::ResourceType r;
- rule = new BlockerRule(RegExp(obj["firstPartyUrl"].toString()), RegExp(obj["requestUrl"].toString()), n, r, obj["shouldBlock"].toBool(), this);
-
- return rule;
-}
diff --git a/src/blocker/filtercollection.cpp b/src/blocker/filtercollection.cpp
new file mode 100644
index 0000000..2262008
--- /dev/null
+++ b/src/blocker/filtercollection.cpp
@@ -0,0 +1,174 @@
+/*******************************************************************************
+ **
+ ** smolbote: yet another qute browser
+ ** Copyright (C) 2017 Xian Nox
+ **
+ ** This program is free software: you can redistribute it and/or modify
+ ** it under the terms of the GNU General Public License as published by
+ ** the Free Software Foundation, either version 3 of the License, or
+ ** (at your option) any later version.
+ **
+ ** This program is distributed in the hope that it will be useful,
+ ** but WITHOUT ANY WARRANTY; without even the implied warranty of
+ ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ ** GNU General Public License for more details.
+ **
+ ** You should have received a copy of the GNU General Public License
+ ** along with this program. If not, see <http://www.gnu.org/licenses/>.
+ **
+ ******************************************************************************/
+
+#include "filtercollection.h"
+#include "ui_subscriptionform.h"
+
+#include "browser.h"
+#include <QNetworkRequest>
+#include <QNetworkReply>
+
+#include <QJsonDocument>
+#include <QJsonObject>
+#include <QJsonArray>
+
+#include <QListWidget>
+#include <QLabel>
+
+FilterCollection::FilterCollection(const QString path, QWidget *parent) :
+ QWidget(parent),
+ ui(new Ui::SubscriptionForm)
+{
+ ui->setupUi(this);
+
+ m_name = "TODO";
+ m_url = path;
+
+ qDebug("Adding subscription [%s]", qUtf8Printable(m_url));
+
+
+ QFile filterFile(m_url);
+ if(!filterFile.open(QIODevice::ReadOnly)) {
+ qWarning("Could not open filter!");
+ return;
+ }
+
+ QJsonDocument filters(QJsonDocument::fromJson(filterFile.readAll()));
+ load(filters.object());
+
+ qDebug("Added %i rules", m_rules.size());
+}
+
+FilterCollection::~FilterCollection()
+{
+ delete ui;
+}
+
+QString FilterCollection::name() const
+{
+ return m_name;
+}
+
+/**
+ * Check if a URL request should be blocked or not
+ * @param info
+ * @return true if it should be blocked; false otherwise
+ */
+FilterCollection::MatchResult FilterCollection::match(QWebEngineUrlRequestInfo &info)
+{
+ MatchResult result;
+
+ for(FilterRule *rule : qAsConst(m_rules)) {
+ result.match = rule->hasMatch(info);
+ if(result.match) {
+ result.block = rule->shouldBlock(info);
+ } else {
+ result.block = false;
+ }
+ result.pattern = rule->filter();
+ return result;
+ }
+
+ // request matches neither whitelist nor blacklist
+ result.match = false;
+ result.block = false;
+ return result;
+}
+
+void FilterCollection::load(const QJsonObject &json)
+{
+ m_name = json["name"].toString();
+ ui->title->setText(m_name);
+
+ m_url = json["url"].toString();
+ ui->homepage->setText(m_url);
+
+ FilterRule *r;
+ for(QJsonValue v : json["rules"].toArray()) {
+ r = createRule(v.toObject());
+ m_rules.append(r);
+ ui->blacklist_listWidget->addItem(r->filter());
+ }
+}
+
+/**
+ * Create rule from JSON object
+ * @param obj
+ * @return
+ */
+FilterRule* FilterCollection::createRule(const QJsonObject &obj)
+{
+ FilterRule *rule;
+
+ FilterRule::ResourceRules r;
+ r.allowed = parseJsonRules(obj["allowTypes"]);
+ r.blocked = parseJsonRules(obj["blockTypes"]);
+
+ rule = new FilterRule(obj["firstPartyUrl"].toString(), obj["requestUrl"].toString(), r, obj["shouldBlock"].toBool(), this);
+
+ return rule;
+}
+
+FilterRule::Resources FilterCollection::parseJsonRules(const QJsonValue &obj)
+{
+ FilterRule::Resources res;
+ for(QJsonValue v : obj.toArray()) {
+ QString t = v.toString();
+ if(t == "MainFrame") {
+ res.setFlag(FilterRule::ResourceType::MainFrame);
+ } else if(t == "SubFrame") {
+ res.setFlag(FilterRule::ResourceType::SubFrame);
+ } else if(t == "Stylesheet") {
+ res.setFlag(FilterRule::ResourceType::Stylesheet);
+ } else if(t == "Script") {
+ res.setFlag(FilterRule::ResourceType::Script);
+ } else if(t == "Image") {
+ res.setFlag(FilterRule::ResourceType::Image);
+ } else if(t == "FontResource") {
+ res.setFlag(FilterRule::ResourceType::FontResource);
+ } else if(t == "SubResource") {
+ res.setFlag(FilterRule::ResourceType::SubResource);
+ } else if(t == "Object") {
+ res.setFlag(FilterRule::ResourceType::Object);
+ } else if(t == "Media") {
+ res.setFlag(FilterRule::ResourceType::Media);
+ } else if(t == "Worker") {
+ res.setFlag(FilterRule::ResourceType::Worker);
+ } else if(t == "SharedWorker") {
+ res.setFlag(FilterRule::ResourceType::SharedWorker);
+ } else if(t == "Prefetch") {
+ res.setFlag(FilterRule::ResourceType::Prefetch);
+ } else if(t == "Favicon") {
+ res.setFlag(FilterRule::ResourceType::Favicon);
+ } else if(t == "Xhr") {
+ res.setFlag(FilterRule::ResourceType::Xhr);
+ } else if(t == "Ping") {
+ res.setFlag(FilterRule::ResourceType::Ping);
+ } else if(t == "ServiceWorker") {
+ res.setFlag(FilterRule::ResourceType::ServiceWorker);
+ } else if(t == "CspWorker") {
+ res.setFlag(FilterRule::ResourceType::CspReport);
+ } else if(t == "PluginResource") {
+ res.setFlag(FilterRule::ResourceType::PluginResource);
+ }
+ }
+
+ return res;
+}
diff --git a/src/blocker/blockersubscription.h b/src/blocker/filtercollection.h
index 26ef7e2..08b42f3 100644
--- a/src/blocker/blockersubscription.h
+++ b/src/blocker/filtercollection.h
@@ -23,7 +23,7 @@
#include <QWidget>
#include <QFile>
-#include "blocker/blockerrule.h"
+#include "blocker/filterrule.h"
namespace Ui {
class SubscriptionForm;
@@ -50,14 +50,14 @@ private slots:
void load(const QJsonObject &json);
private:
-
- BlockerRule* createRule(const QJsonObject &obj);
+ FilterRule* createRule(const QJsonObject &obj);
+ FilterRule::Resources parseJsonRules(const QJsonValue &obj);
Ui::SubscriptionForm *ui;
QString m_name;
- QString m_path;
+ QString m_url;
- QVector<BlockerRule*> m_rules;
+ QVector<FilterRule*> m_rules;
};
diff --git a/src/blocker/filterrule.cpp b/src/blocker/filterrule.cpp
new file mode 100644
index 0000000..f7ba00b
--- /dev/null
+++ b/src/blocker/filterrule.cpp
@@ -0,0 +1,119 @@
+/*******************************************************************************
+ **
+ ** smolbote: yet another qute browser
+ ** Copyright (C) 2017 Xian Nox
+ **
+ ** This program is free software: you can redistribute it and/or modify
+ ** it under the terms of the GNU General Public License as published by
+ ** the Free Software Foundation, either version 3 of the License, or
+ ** (at your option) any later version.
+ **
+ ** This program is distributed in the hope that it will be useful,
+ ** but WITHOUT ANY WARRANTY; without even the implied warranty of
+ ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ ** GNU General Public License for more details.
+ **
+ ** You should have received a copy of the GNU General Public License
+ ** along with this program. If not, see <http://www.gnu.org/licenses/>.
+ **
+ ******************************************************************************/
+
+#include "filterrule.h"
+
+FilterRule::FilterRule(const QString firstPartyUrl, const QString requestUrl, ResourceRules rules, bool shouldBlock, QObject *parent) :
+ QObject(parent)
+{
+ m_firstPartyUrl.setPattern(firstPartyUrl);
+ m_requestUrl.setPattern(requestUrl);
+ m_rules = rules;
+ m_shouldBlock = shouldBlock;
+
+ m_valid = true;
+
+#ifdef DEBUG_VERBOSE
+ qDebug("Created rule [%s] [%s]", qUtf8Printable(firstPartyUrl), qUtf8Printable(requestUrl));
+#endif
+
+}
+
+bool FilterRule::hasMatch(const QWebEngineUrlRequestInfo &info)
+{
+ if(m_firstPartyUrl.hasMatch(info.firstPartyUrl().toString()) && m_requestUrl.hasMatch(info.requestUrl().toString())) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool FilterRule::shouldBlock(const QWebEngineUrlRequestInfo &info)
+{
+ if(!m_valid) {
+ return false;
+ }
+
+ // Check options
+ switch (info.resourceType()) {
+ case QWebEngineUrlRequestInfo::ResourceTypeMainFrame:
+ return testFlag(MainFrame);
+ case QWebEngineUrlRequestInfo::ResourceTypeSubFrame:
+ return testFlag(SubFrame);
+ case QWebEngineUrlRequestInfo::ResourceTypeStylesheet:
+ return testFlag(Stylesheet);
+ case QWebEngineUrlRequestInfo::ResourceTypeScript:
+ return testFlag(Script);
+ case QWebEngineUrlRequestInfo::ResourceTypeImage:
+ return testFlag(Image);
+ case QWebEngineUrlRequestInfo::ResourceTypeFontResource:
+ return testFlag(FontResource);
+ case QWebEngineUrlRequestInfo::ResourceTypeSubResource:
+ return testFlag(SubResource);
+ case QWebEngineUrlRequestInfo::ResourceTypeObject:
+ return testFlag(Object);
+ case QWebEngineUrlRequestInfo::ResourceTypeMedia:
+ return testFlag(Media);
+ case QWebEngineUrlRequestInfo::ResourceTypeWorker:
+ return testFlag(Worker);
+ case QWebEngineUrlRequestInfo::ResourceTypeSharedWorker:
+ return testFlag(SharedWorker);
+ case QWebEngineUrlRequestInfo::ResourceTypePrefetch:
+ return testFlag(Prefetch);
+ case QWebEngineUrlRequestInfo::ResourceTypeFavicon:
+ return testFlag(Favicon);
+ case QWebEngineUrlRequestInfo::ResourceTypeXhr:
+ return testFlag(Xhr);
+ case QWebEngineUrlRequestInfo::ResourceTypePing:
+ return testFlag(Ping);
+ case QWebEngineUrlRequestInfo::ResourceTypeServiceWorker:
+ return testFlag(ServiceWorker);
+ case QWebEngineUrlRequestInfo::ResourceTypeCspReport:
+ return testFlag(CspReport);
+ case QWebEngineUrlRequestInfo::ResourceTypePluginResource:
+ return testFlag(PluginResource);
+ case QWebEngineUrlRequestInfo::ResourceTypeUnknown:
+ break;
+ }
+
+ return m_shouldBlock;
+
+}
+
+bool FilterRule::isValid()
+{
+ return m_valid;
+}
+
+QString FilterRule::filter() const
+{
+ return "'" + m_firstPartyUrl.pattern() + "' | '" + m_requestUrl.pattern() + "'";
+}
+
+bool FilterRule::testFlag(ResourceType flag)
+{
+ if(m_rules.allowed.testFlag(flag)) {
+ return false;
+ } else if(m_rules.blocked.testFlag(flag)) {
+ return true;
+ } else {
+ return m_shouldBlock;
+ }
+}
diff --git a/src/blocker/blockerrule.h b/src/blocker/filterrule.h
index 758366d..44340fc 100644
--- a/src/blocker/blockerrule.h
+++ b/src/blocker/filterrule.h
@@ -26,50 +26,44 @@
#include "regexp.h"
#include <QWebEngineUrlRequestInfo>
-class BlockerRule : public QObject
+class FilterRule : public QObject
{
Q_OBJECT
public:
- enum TypeState {
- Allow = 1,
- Deny = 2,
- None = 0
+ enum ResourceType {
+ NoType = 0,
+ MainFrame = 1,
+ SubFrame = 2,
+ Stylesheet = 4,
+ Script = 8,
+ Image = 16,
+ FontResource = 32,
+ SubResource = 64,
+ Object = 128,
+ Media = 256,
+ Worker = 512,
+ SharedWorker = 1024,
+ Prefetch = 2048,
+ Favicon = 4096,
+ Xhr = 8192,
+ Ping = 16384,
+ ServiceWorker = 32768,
+ CspReport = 65536,
+ PluginResource = 131072,
+ Unknown = 262144
};
+ Q_DECLARE_FLAGS(Resources, ResourceType)
- struct NavigationType {
- TypeState link;
- TypeState typed;
- TypeState form;
- TypeState history;
- TypeState reload;
- TypeState other;
+ struct ResourceRules {
+ Resources allowed;
+ Resources blocked;
};
- struct ResourceType {
- TypeState MainFrame;
- TypeState SubFrame;
- TypeState Stylesheet;
- TypeState Script;
- TypeState FontResource;
- TypeState SubResource;
- TypeState Object;
- TypeState Media;
- TypeState Worker;
- TypeState SharedWorker;
- TypeState Prefetch;
- TypeState Favicon;
- TypeState Xhr;
- TypeState Ping;
- TypeState ServiceWorker;
- TypeState CspWorker;
- TypeState PluginResource;
- TypeState Unknown;
- };
-
- explicit BlockerRule(RegExp firstPartyUrl, RegExp requestUrl, NavigationType nav, ResourceType res, bool shouldBlock, QObject *parent = 0);
+ explicit FilterRule(const QString firstPartyUrl, const QString requestUrl, ResourceRules rules, bool shouldBlock, QObject *parent = 0);
- bool match(const QWebEngineUrlRequestInfo &info);
+ bool hasMatch(const QWebEngineUrlRequestInfo &info);
+ bool shouldBlock(const QWebEngineUrlRequestInfo &info);
bool isValid();
@@ -80,11 +74,12 @@ signals:
public slots:
private:
+ bool testFlag(ResourceType flag);
+
RegExp m_firstPartyUrl;
RegExp m_requestUrl;
- NavigationType m_navRules;
- ResourceType m_resRules;
+ ResourceRules m_rules;
bool m_valid = false;
bool m_shouldBlock;
diff --git a/src/blocker/regexp.cpp b/src/blocker/regexp.cpp
index 8560455..1f3c449 100644
--- a/src/blocker/regexp.cpp
+++ b/src/blocker/regexp.cpp
@@ -21,8 +21,10 @@
#include "regexp.h"
RegExp::RegExp(const QString &pattern, PatternOptions options) :
- QRegularExpression(pattern, options)
+ QRegularExpression()
{
+ setPattern(pattern);
+ setPatternOptions(options);
}
bool RegExp::hasMatch(const QString &subject, int offset, MatchType matchType, MatchOptions matchOptions) const
diff --git a/src/webengine/urlinterceptor.cpp b/src/webengine/urlinterceptor.cpp
index ab5ee12..da2925c 100644
--- a/src/webengine/urlinterceptor.cpp
+++ b/src/webengine/urlinterceptor.cpp
@@ -19,7 +19,7 @@
******************************************************************************/
#include "urlinterceptor.h"
-#include "blocker/blockersubscription.h"
+#include "blocker/filtercollection.h"
UrlRequestInterceptor::UrlRequestInterceptor(QObject *parent) :
QWebEngineUrlRequestInterceptor(parent)
@@ -29,7 +29,7 @@ UrlRequestInterceptor::UrlRequestInterceptor(QObject *parent) :
void UrlRequestInterceptor::interceptRequest(QWebEngineUrlRequestInfo &info)
{
#ifdef DEBUG_VERBOSE
- qDebug("%s", qUtf8Printable(info.requestUrl().toString()));
+ qDebug("%s --> [%i] %s", qUtf8Printable(info.firstPartyUrl().toString()), info.resourceType(), qUtf8Printable(info.requestUrl().toString()));
#endif
for(auto s : m_manager->subscriptions()) {
@@ -37,7 +37,7 @@ void UrlRequestInterceptor::interceptRequest(QWebEngineUrlRequestInfo &info)
if(r.match) {
info.block(r.block);
#ifdef DEBUG_VERBOSE
- qDebug("+--> matched [%s] [%s]", r.block ? "blocked" : "allowed", qUtf8Printable(r.pattern));
+ qDebug(">> matched [%s] [%s]", r.block ? "blocked" : "allowed", qUtf8Printable(r.pattern));
#endif
return;
}