diff options
34 files changed, 129 insertions, 1625 deletions
@@ -18,8 +18,9 @@ List of things to do before 1.0 release ### Auto-destruct cookies - cookie whitelist and blacklist -### Adblocker -- adblocker load list (.config/smolbote/filter.d/*.txt) +### Request filter +- How are multiple IPs per hostname to be treated? +- review code ### No Script - there's already a profile setting to disable scripts diff --git a/lib/adblock/adblock.qbs b/lib/adblock/adblock.qbs deleted file mode 100644 index e4df779..0000000 --- a/lib/adblock/adblock.qbs +++ /dev/null @@ -1,37 +0,0 @@ -import qbs 1.0 - -Project { - name: "Filter" - - StaticLibrary { - name: "adblock" - - Depends { name: "cpp" } - Depends { - name: "Qt" - submodules: ["core"] - } - - files: [ - "filterrule.h", - "filterrule.cpp", - ] - } - - CppApplication { - name: "adblock-test" - - Depends { - name: "Qt" - submodules: ["core", "test"] - } - - Depends { name: "adblock" } - - files: [ - "test/main.cpp", - "test/filtertest.cpp", - "test/filtertest.h", - ] - } -} diff --git a/lib/adblock/filterrule.cpp b/lib/adblock/filterrule.cpp deleted file mode 100644 index 79ded6d..0000000 --- a/lib/adblock/filterrule.cpp +++ /dev/null @@ -1,90 +0,0 @@ -/* - * 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: git://neueland.iserlohn-fortress.net/smolbote.git - * - * SPDX-License-Identifier: GPL-3.0 - */ - -#include "filterrule.h" -#include <QUrl> - -/* TODO - * - split this class into two: FilterRule that only deals with matching, and AdBlockRule, which only deals with parsing - */ - -/* The AdBlock standard is an incredible mess, vaguely explaiend on: - * - https://adblockplus.org/filters - * - https://adblockplus.org/filter-cheatsheet - */ - -FilterRule::FilterRule(const QString &line) -{ - valid = parse(line); -} - -FilterRule::~FilterRule() -{ -} - -bool FilterRule::isValid() const -{ - return valid; -} - -bool FilterRule::isException() const -{ - return exception; -} - -bool FilterRule::shouldBlock(const QUrl &requestUrl) const -{ - QRegularExpressionMatch match = rule.match(requestUrl.toString()); - return match.hasMatch(); -} - -bool FilterRule::parse(const QString &line) -{ - // skip for comments and empty rules - if(line.startsWith('!') || line.trimmed().isEmpty()) { - return false; - } - - // make a copy of the pattern so we can snap off the parts we've already parsed - QString pattern = line; - - if(pattern.startsWith("@@")) { - exception = true; - pattern = pattern.mid(2); // remove @@ - } - - rule.setPattern(createRegExpPattern(pattern)); - return true; -} - -QString createRegExpPattern(const QString &line) -{ - QString pattern = line; - - // replace . (any character) with \. (a dot) - pattern.replace('.', "\\."); - - // translate adblock special characters into regex - // replace wildcard (*) with '.*' (zero or more of any element) - pattern.replace('*', ".*"); - - // replace separator (^) with '($|\?|\/)' (end of string, or ?, or /, or :number) - pattern.replace('^', "($|\\?|\\/|:\\d+)"); - - // replace || with ^\w+://([\w,\d,\.]+)? - pattern.replace("||", "^\\w+://([\\w,\\d,\\.]+)?"); - - if(pattern.startsWith('|') && pattern.endsWith('|')) { - // replace | at start with ^ (start of string) - pattern.replace(0, 1, '^'); - // replace | at end with $ (end of string) - pattern.replace('|', '$'); - } - - return pattern; -} diff --git a/lib/adblock/filterrule.h b/lib/adblock/filterrule.h deleted file mode 100644 index 084bd8c..0000000 --- a/lib/adblock/filterrule.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * 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: git://neueland.iserlohn-fortress.net/smolbote.git - * - * SPDX-License-Identifier: GPL-3.0 - */ - -#ifndef FILTERRULE_H -#define FILTERRULE_H - -#include <QRegularExpression> - -class QUrl; -class FilterRule -{ -public: - - FilterRule(const QString &line); - - // delete the copy constructor and assignment operator - FilterRule(const FilterRule&) = delete; - FilterRule& operator=(const FilterRule&) = delete; - - // move constructor - FilterRule(FilterRule&& other) { - valid = other.valid; - exception = other.exception; - rule = other.rule; - } - - ~FilterRule(); - - bool isValid() const; - bool isException() const; - bool shouldBlock(const QUrl &requestUrl) const; - -private: - bool parse(const QString &line); - - bool valid; - bool exception; - - QRegularExpression rule; - -}; - -QString createRegExpPattern(const QString &line); - -#endif // FILTERRULE_H diff --git a/lib/adblock/test/filtertest.cpp b/lib/adblock/test/filtertest.cpp deleted file mode 100644 index 76e607b..0000000 --- a/lib/adblock/test/filtertest.cpp +++ /dev/null @@ -1,71 +0,0 @@ -/* - * 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: git://neueland.iserlohn-fortress.net/smolbote.git - * - * SPDX-License-Identifier: GPL-3.0 - */ - -#include "filtertest.h" -#include <QtTest/QtTest> -#include "../filterrule.h" -#include <QUrl> - -FilterTest::FilterTest(QObject *parent) : QObject(parent) -{ -} - -void FilterTest::initTestCase() -{ - addressRule = new FilterRule("/banner/*/img^"); - QVERIFY(addressRule->isValid() == true); - QVERIFY(addressRule->isException() == false); - - domainRule = new FilterRule("||ads.example.com^"); - QVERIFY(domainRule->isValid() == true); - QVERIFY(domainRule->isException() == false); - - exactAddressRule = new FilterRule("|http://example.com/|"); - QVERIFY(exactAddressRule->isValid() == true); - QVERIFY(exactAddressRule->isException() == false); -} - -void FilterTest::testAddressBlock() -{ - // This rule blocks: - QVERIFY(addressRule->shouldBlock(QUrl("http://example.com/banner/foo/img")) == true); - QVERIFY(addressRule->shouldBlock(QUrl("http://example.com/banner/foo/bar/img?param")) == true); - QVERIFY(addressRule->shouldBlock(QUrl("http://example.com/banner//img/foo")) == true); - - // This rule doesn't block: - QVERIFY(addressRule->shouldBlock(QUrl("http://example.com/banner/img")) == false); - QVERIFY(addressRule->shouldBlock(QUrl("http://example.com/banner/foo/imgraph")) == false); - QVERIFY(addressRule->shouldBlock(QUrl("http://example.com/banner/foo/img.gif")) == false); -} - -void FilterTest::testDomainBlock() -{ - // This rule blocks: - QVERIFY(domainRule->shouldBlock(QUrl("http://ads.example.com/foo.gif")) == true); - QVERIFY(domainRule->shouldBlock(QUrl("http://server1.ads.example.com/foo.gif")) == true); - QVERIFY(domainRule->shouldBlock(QUrl("https://ads.example.com:8000/")) == true); - - // This rule doesn't block: - QVERIFY(domainRule->shouldBlock(QUrl("http://ads.example.com.ua/foo.gif")) == false); - QVERIFY(domainRule->shouldBlock(QUrl("http://example.com/redirect/http://ads.example.com/")) == false); -} - -void FilterTest::testExactAddressBlock() -{ - // This rule blocks: - QVERIFY(exactAddressRule->shouldBlock(QUrl("http://example.com/")) == true); - - // This rule doesn't block: - QVERIFY(exactAddressRule->shouldBlock(QUrl("http://example.com/foo.gif")) == false); - QVERIFY(exactAddressRule->shouldBlock(QUrl("http://example.info/redirect/http://example.com/")) == false); -} - -void FilterTest::cleanupTestCase() -{ - delete addressRule; -} diff --git a/lib/adblock/test/filtertest.h b/lib/adblock/test/filtertest.h deleted file mode 100644 index f91c3dd..0000000 --- a/lib/adblock/test/filtertest.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * 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: git://neueland.iserlohn-fortress.net/smolbote.git - * - * SPDX-License-Identifier: GPL-3.0 - */ - -#ifndef FILTERTEST_H -#define FILTERTEST_H - -#include <QObject> - -class FilterRule; -class FilterTest : public QObject -{ - Q_OBJECT -public: - explicit FilterTest(QObject *parent = nullptr); - -signals: - -private slots: - void initTestCase(); - void testAddressBlock(); - void testDomainBlock(); - void testExactAddressBlock(); - void cleanupTestCase(); - -private: - FilterRule *addressRule; - FilterRule *domainRule; - FilterRule *exactAddressRule; -}; - -#endif // FILTERTEST_H diff --git a/lib/adblock/test/main.cpp b/lib/adblock/test/main.cpp deleted file mode 100644 index b8c9dca..0000000 --- a/lib/adblock/test/main.cpp +++ /dev/null @@ -1,12 +0,0 @@ -/* - * 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: git://neueland.iserlohn-fortress.net/smolbote.git - * - * SPDX-License-Identifier: GPL-3.0 - */ - -#include <QtTest/QtTest> -#include "filtertest.h" - -QTEST_APPLESS_MAIN(FilterTest) diff --git a/smolbote.qbs b/smolbote.qbs index 7f0af2e..dc201d9 100644 --- a/smolbote.qbs +++ b/smolbote.qbs @@ -21,7 +21,6 @@ Project { "src/lib/downloads/downloads.qbs", "src/lib/navigation/navigation.qbs", "lib/settings/settings.qbs", - "lib/adblock/adblock.qbs", ] Probes.PkgConfigProbe { @@ -50,7 +49,7 @@ Project { Depends { name: "Qt" versionAtLeast: "5.7.1" - submodules: ["core", "widgets", "webengine", "webenginewidgets", "printsupport"] + submodules: ["core", "widgets", "webenginecore", "webenginewidgets", "printsupport"] } Depends { name: "navigation" } @@ -121,8 +120,8 @@ Project { Group { name: "Request Filter" files: [ - "src/filter/filter.cpp", - "src/filter/filter.h", + "src/webengine/hostrule.cpp", + "src/webengine/hostrule.h", "src/webengine/urlinterceptor.cpp", "src/webengine/urlinterceptor.h", ] diff --git a/src/browser.cpp b/src/browser.cpp index 4221eb9..c21fced 100644 --- a/src/browser.cpp +++ b/src/browser.cpp @@ -11,7 +11,6 @@ #include <downloads/downloadswidget.h> #include "webengine/urlinterceptor.h" #include "mainwindow.h" -#include <QtWebEngine> #include <QDir> #include <QWebEngineDownloadItem> diff --git a/src/filter/blockermanager.cpp b/src/filter/blockermanager.cpp deleted file mode 100644 index 718f8a1..0000000 --- a/src/filter/blockermanager.cpp +++ /dev/null @@ -1,41 +0,0 @@ -/* - * 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: git://neueland.iserlohn-fortress.net/smolbote.git - * - * SPDX-License-Identifier: GPL-3.0 - */ - -#include "blockermanager.h" -#include "ui_subscriptiondialog.h" - -#include "browser.h" -#include <QLabel> -#include <QListWidget> - -#include "filtercollection.h" - -BlockerManager::BlockerManager(QWidget *parent) : - QDialog(parent), - ui(new Ui::UrlInterceptorDialog) -{ - ui->setupUi(this); - - const QStringList subscriptions = browser->settings()->value("blocker.subscriptions").toStringList(); - QStringList::const_iterator i; - for(i = subscriptions.constBegin(); i != subscriptions.constEnd(); ++i) { - FilterCollection *sub = new FilterCollection(QString(*i), this); - m_subscriptions.append(sub); - ui->tabWidget->addTab(sub, sub->name()); - } -} - -BlockerManager::~BlockerManager() -{ - delete ui; -} - -QVector<FilterCollection *> BlockerManager::subscriptions() const -{ - return m_subscriptions; -} diff --git a/src/filter/blockermanager.h b/src/filter/blockermanager.h deleted file mode 100644 index df426b3..0000000 --- a/src/filter/blockermanager.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * 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: git://neueland.iserlohn-fortress.net/smolbote.git - * - * SPDX-License-Identifier: GPL-3.0 - */ - -#ifndef URLINTERCEPTORDIALOG_H -#define URLINTERCEPTORDIALOG_H - -#include <QDialog> - -namespace Ui { -class UrlInterceptorDialog; -} - -class FilterCollection; -class BlockerManager : public QDialog -{ - Q_OBJECT - -public: - explicit BlockerManager(QWidget *parent = 0); - ~BlockerManager(); - - QVector<FilterCollection* > subscriptions() const; - -private: - Ui::UrlInterceptorDialog *ui; - QVector<FilterCollection *> m_subscriptions; -}; - -#endif // URLINTERCEPTORDIALOG_H diff --git a/src/filter/filter.cpp b/src/filter/filter.cpp deleted file mode 100644 index 35eb9e7..0000000 --- a/src/filter/filter.cpp +++ /dev/null @@ -1,34 +0,0 @@ -/* - * 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: git://neueland.iserlohn-fortress.net/smolbote.git - * - * SPDX-License-Identifier: GPL-3.0 - */ - -#include "filter.h" -#include <QUrl> - -FilterRule::FilterRule(const QString &line) -{ - parse(line); -} - -FilterRule::~FilterRule() -{ -} - -bool FilterRule::shouldBlock(const QUrl &requestUrl) const -{ - if(matcher.indexIn(requestUrl.toString()) == -1) { - // pattern not found in url - return false; - } - - return true; -} - -void FilterRule::parse(const QString &line) -{ - matcher.setPattern(line); -} diff --git a/src/filter/filter.h b/src/filter/filter.h deleted file mode 100644 index f152e7a..0000000 --- a/src/filter/filter.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * 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: git://neueland.iserlohn-fortress.net/smolbote.git - * - * SPDX-License-Identifier: GPL-3.0 - */ - -#ifndef FILTERRULE_H -#define FILTERRULE_H - -#include <QStringMatcher> - -class QUrl; -class FilterRule -{ -public: - - FilterRule(const QString &line); - - // delete the copy constructor and assignment operator - FilterRule(const FilterRule&) = delete; - FilterRule& operator=(const FilterRule&) = delete; - - // move constructor - FilterRule(FilterRule&& other) { - matcher = other.matcher; - } - - ~FilterRule(); - - bool shouldBlock(const QUrl &requestUrl) const; - -private: - void parse(const QString &line); - - // QStringMatcher: holds a pattern you want to repeatedly match against some strings - QStringMatcher matcher; - -}; - -#endif // FILTERRULE_H diff --git a/src/filter/filtercollection.cpp b/src/filter/filtercollection.cpp deleted file mode 100644 index e151a10..0000000 --- a/src/filter/filtercollection.cpp +++ /dev/null @@ -1,157 +0,0 @@ -/* - * 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: git://neueland.iserlohn-fortress.net/smolbote.git - * - * SPDX-License-Identifier: GPL-3.0 - */ - -#include "filtercollection.h" -#include "ui_subscriptionform.h" - -#include "browser.h" -#include <QNetworkRequest> -#include <QNetworkReply> - -#include <QJsonDocument> -#include <QJsonObject> -#include <QJsonArray> - -#include <QListWidget> -#include <QLabel> - -#include <QTreeView> -#include "filtertree.h" -#include "filter.h" - -FilterCollection::FilterCollection(const QString path, QWidget *parent) : - QWidget(parent), - ui(new Ui::SubscriptionForm) -{ - ui->setupUi(this); - - ui->homepage->setText(path); - - qDebug("Adding subscription [%s]", qUtf8Printable(path)); - - m_filters = new FilterTree(this); - ui->treeView->setModel(m_filters); - - QFile filterFile(path); - if(!filterFile.open(QIODevice::ReadOnly)) { - qWarning("Could not open filter!"); - return; - } - - QJsonDocument filters(QJsonDocument::fromJson(filterFile.readAll())); - qDebug("Added %i rules", load(filters.object())); -} - -FilterCollection::~FilterCollection() -{ - delete ui; -} - -QString FilterCollection::name() const -{ - return ui->title->text(); -} - -/** - * Check if a URL request should be blocked or not - * @param info - * @return true if it should be blocked; false otherwise - */ -bool FilterCollection::match(QWebEngineUrlRequestInfo &info) -{ - for(QString domain : m_filterlist.keys()) { - if(domain.isEmpty() || info.firstPartyUrl().toString().contains(domain)) { - // domain matched - - for(QString rule : m_filterlist.value(domain).keys()) { - if(rule.isEmpty() || info.requestUrl().toString().contains(rule)) { - return m_filterlist.value(domain).value(rule); - } - } - } - } - - return false; -} - -/** - * Load rules from JSON object - * @param json - */ -int FilterCollection::load(const QJsonObject &json) -{ - int number = 0; - - ui->title->setText(json["name"].toString()); - ui->homepage->setText(json["url"].toString()); - - QJsonObject rules = json["rules"].toObject(); - for(QString key : rules.keys()) { - ++number; - qDebug("+ '%s'", qUtf8Printable(key)); - - QJsonObject domain = rules.value(key).toObject(); - QHash<QString, bool> d; - - for(QString r : domain.keys()) { - d.insert(r, domain.value(r).toBool()); - qDebug("|-'%s': %i", qUtf8Printable(r), domain.value(r).toBool()); - } - - m_filterlist.insert(key, d); - - } - return number; -} - -Filter::Resources FilterCollection::parseJsonRules(const QJsonValue &obj) -{ - Filter::Resources res; - for(QJsonValue v : obj.toArray()) { - QString t = v.toString(); - if(t == "MainFrame") { - res.setFlag(Filter::ResourceType::MainFrame); - } else if(t == "SubFrame") { - res.setFlag(Filter::ResourceType::SubFrame); - } else if(t == "Stylesheet") { - res.setFlag(Filter::ResourceType::Stylesheet); - } else if(t == "Script") { - res.setFlag(Filter::ResourceType::Script); - } else if(t == "Image") { - res.setFlag(Filter::ResourceType::Image); - } else if(t == "FontResource") { - res.setFlag(Filter::ResourceType::Font); - } else if(t == "SubResource") { - res.setFlag(Filter::ResourceType::SubResource); - } else if(t == "Object") { - res.setFlag(Filter::ResourceType::Object); - } else if(t == "Media") { - res.setFlag(Filter::ResourceType::Media); - } else if(t == "Worker") { - res.setFlag(Filter::ResourceType::Worker); - } else if(t == "SharedWorker") { - res.setFlag(Filter::ResourceType::SharedWorker); - } else if(t == "Prefetch") { - res.setFlag(Filter::ResourceType::Prefetch); - } else if(t == "Favicon") { - res.setFlag(Filter::ResourceType::Favicon); - } else if(t == "Xhr") { - res.setFlag(Filter::ResourceType::Xhr); - } else if(t == "Ping") { - res.setFlag(Filter::ResourceType::Ping); - } else if(t == "ServiceWorker") { - res.setFlag(Filter::ResourceType::ServiceWorker); - } else if(t == "CspWorker") { - res.setFlag(Filter::ResourceType::CspReport); - } else if(t == "PluginResource") { - res.setFlag(Filter::ResourceType::PluginResource); - } - } - - return res; -} diff --git a/src/filter/filtercollection.h b/src/filter/filtercollection.h deleted file mode 100644 index 4249eea..0000000 --- a/src/filter/filtercollection.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * 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: git://neueland.iserlohn-fortress.net/smolbote.git - * - * SPDX-License-Identifier: GPL-3.0 - */ - -#ifndef SUBSCRIPTIONFORM_H -#define SUBSCRIPTIONFORM_H - -#include <QWidget> -#include <QFile> -#include "filtertree.h" - -#include <QHash> - -namespace Ui { -class SubscriptionForm; -} - -class FilterCollection : public QWidget -{ - Q_OBJECT - -public: - struct MatchResult { - bool match; - bool block; - QString pattern; - }; - - explicit FilterCollection(const QString path, QWidget *parent = 0); - ~FilterCollection(); - - QString name() const; - bool match(QWebEngineUrlRequestInfo &info); - -private slots: - int load(const QJsonObject &json); - -private: - Filter::Resources parseJsonRules(const QJsonValue &obj); - - Ui::SubscriptionForm *ui; - - FilterTree *m_filters; - - QHash<QString, QHash<QString, bool>> m_filterlist; - -}; - -#endif // SUBSCRIPTIONFORM_H diff --git a/src/filter/filtertree.cpp b/src/filter/filtertree.cpp deleted file mode 100644 index 73cc261..0000000 --- a/src/filter/filtertree.cpp +++ /dev/null @@ -1,151 +0,0 @@ -/* - * 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: git://neueland.iserlohn-fortress.net/smolbote.git - * - * SPDX-License-Identifier: GPL-3.0 - */ - -#include "filtertree.h" - -FilterTree::FilterTree(QObject *parent) : - QAbstractItemModel(parent) -{ - rootItem = new Filter("", "", Filter::ResourceRules(), false); -} - -FilterTree::~FilterTree() -{ - delete rootItem; -} - -QModelIndex FilterTree::index(int row, int column, const QModelIndex &parent) const -{ - if(!hasIndex(row, column, parent)) { - return QModelIndex(); - } - - Filter *parentItem; - if(!parent.isValid()) { - parentItem = rootItem; - } else { - parentItem = static_cast<Filter*>(parent.internalPointer()); - } - - Filter *childItem = parentItem->child(row); - if(childItem) { - return createIndex(row, column, childItem); - } else { - return QModelIndex(); - } -} - -QModelIndex FilterTree::parent(const QModelIndex &index) const -{ - if(!index.isValid()) { - return QModelIndex(); - } - - Filter *childItem = static_cast<Filter*>(index.internalPointer()); - Filter *parentItem = childItem->parentItem(); - - if(parentItem == rootItem) { - return QModelIndex(); - } - - return createIndex(parentItem->row(), 0, parentItem); -} - -int FilterTree::rowCount(const QModelIndex &parent) const -{ - Filter *parentItem; - if(parent.column() > 0) { - return 0; - } - - if(!parent.isValid()) { - parentItem = rootItem; - } else { - parentItem = static_cast<Filter*>(parent.internalPointer()); - } - - return parentItem->childCount(); -} - -int FilterTree::columnCount(const QModelIndex &parent) const -{ - Q_UNUSED(parent) - return 5; -} - -QVariant FilterTree::data(const QModelIndex &index, int role) const -{ - if(!index.isValid()) { - return QVariant(); - } - - if(role != Qt::DisplayRole) { - return QVariant(); - } - - Filter *n = static_cast<Filter*>(index.internalPointer()); - switch (index.column()) { - case 0: // domain - return QVariant(n->domain()); - case 1: // request - return QVariant(n->request()); - case 2: // should block - return QVariant(n->isBlocking() ? "true" : "false"); - case 3: // allowed types - return QVariant(n->allowedTypes()); - case 4: // blocked types - return QVariant(n->blockedTypes()); - default: - return QVariant(); - } -} - -QVariant FilterTree::headerData(int section, Qt::Orientation orientation, int role) const -{ - if(orientation != Qt::Horizontal) { - return QVariant(); - } - - if(role != Qt::DisplayRole) { - return QVariant(); - } - - switch (section) { - case 0: - return QVariant(tr("Domain")); - case 1: - return QVariant(tr("Request")); - case 2: - return QVariant(tr("Should Block")); - case 3: - return QVariant(tr("Allowed Types")); - case 4: - return QVariant(tr("Blocked Types")); - default: - return QVariant(); - } -} - -Filter *FilterTree::addFilter(const QString &domain, const QString &request, Filter::ResourceRules rules, bool shouldBlock) -{ - Filter *node = new Filter(domain, request, rules, shouldBlock, rootItem); - node->enable(); - rootItem->appendChild(node); - return node; -} - -QVector<Filter*> FilterTree::filters(const QString &domain) -{ - QVector<Filter*> nodes; - for(int i = 0; i < rootItem->childCount(); ++i) { - if(rootItem->child(i)->hasDomainMatch(domain)) { - nodes.append(rootItem->child(i)); - } - } - return nodes; -} diff --git a/src/filter/filtertree.h b/src/filter/filtertree.h deleted file mode 100644 index cbf339f..0000000 --- a/src/filter/filtertree.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * 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: git://neueland.iserlohn-fortress.net/smolbote.git - * - * SPDX-License-Identifier: GPL-3.0 - */ - -#ifndef FILTERTREE_H -#define FILTERTREE_H - -#include <QAbstractItemModel> -#include <QModelIndex> -#include <QVariant> -#include "filter.h" - -class FilterTree : public QAbstractItemModel -{ - Q_OBJECT - -public: - explicit FilterTree(QObject *parent = 0); - ~FilterTree(); - - QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override; - QModelIndex parent(const QModelIndex &index) const override; - int rowCount(const QModelIndex &parent = QModelIndex()) const override; - int columnCount(const QModelIndex &parent = QModelIndex()) const override; - QVariant data(const QModelIndex &index, int role) const override; - QVariant headerData(int section, Qt::Orientation orientation, int role) const override; - - Filter *addFilter(const QString &domain, const QString &request, Filter::ResourceRules rules, bool shouldBlock); - QVector<Filter*> filters(const QString &domain = ""); - -private: - Filter *rootItem; -}; - -#endif // FILTERTREE_H diff --git a/src/filter/regexp.cpp b/src/filter/regexp.cpp deleted file mode 100644 index e46bc75..0000000 --- a/src/filter/regexp.cpp +++ /dev/null @@ -1,60 +0,0 @@ -/* - * 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: git://neueland.iserlohn-fortress.net/smolbote.git - * - * SPDX-License-Identifier: GPL-3.0 - */ - -#include "regexp.h" - -RegExp::RegExp(const QString &pattern, PatternOptions options) : - QRegularExpression() -{ - setPattern(pattern); - setPatternOptions(options); -} - -bool RegExp::hasMatch(const QString &subject, int offset, MatchType matchType, MatchOptions matchOptions) const -{ - // Empty matches all - if(pattern().isEmpty()) { - return true; - } - - return QRegularExpression::match(subject, offset, matchType, matchOptions).hasMatch(); -} - -void RegExp::setWildcardPattern(const QString &pattern) -{ - QString parsed; - - for(int i=0; i<pattern.length(); i++) { - const QChar c = pattern.at(i); - switch (c.toLatin1()) { - case '*': - // remove * at the start and end - if(i != 0 && i != pattern.length()-1) { - parsed.append(".*"); - } - break; - case '^': - parsed.append("(?:[^\\w\\d\\_\\-\\.\\%]|$)"); - break; - case '|': - if(i == 0) { - // beginning of string - parsed.append('^'); - } else { - // end of string - parsed.append('$'); - } - break; - default: - parsed.append(c); - break; - } - } - - setPattern(parsed); -} diff --git a/src/filter/regexp.h b/src/filter/regexp.h deleted file mode 100644 index 32ba5c3..0000000 --- a/src/filter/regexp.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * 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: git://neueland.iserlohn-fortress.net/smolbote.git - * - * SPDX-License-Identifier: GPL-3.0 - */ - -#ifndef REGEXP_H -#define REGEXP_H - -#include <QRegularExpression> - -/*! - * Regular Expression class for AdBlockPlus filters - */ -class RegExp : public QRegularExpression -{ -public: - explicit RegExp(const QString &pattern = "", PatternOptions options = NoPatternOption); - - bool hasMatch(const QString &subject, int offset=0, MatchType matchType=NormalMatch, MatchOptions matchOptions=NoMatchOption) const; - void setWildcardPattern(const QString &pattern); -}; - -#endif // REGEXP_H diff --git a/src/filter/subscriptiondialog.ui b/src/filter/subscriptiondialog.ui deleted file mode 100644 index 7a63cc9..0000000 --- a/src/filter/subscriptiondialog.ui +++ /dev/null @@ -1,67 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>UrlInterceptorDialog</class> - <widget class="QDialog" name="UrlInterceptorDialog"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>640</width> - <height>480</height> - </rect> - </property> - <property name="windowTitle"> - <string>Blocker</string> - </property> - <layout class="QVBoxLayout" name="verticalLayout"> - <item> - <widget class="QTabWidget" name="tabWidget"/> - </item> - <item> - <widget class="QDialogButtonBox" name="buttonBox"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="standardButtons"> - <set>QDialogButtonBox::Close</set> - </property> - </widget> - </item> - </layout> - </widget> - <resources/> - <connections> - <connection> - <sender>buttonBox</sender> - <signal>accepted()</signal> - <receiver>UrlInterceptorDialog</receiver> - <slot>accept()</slot> - <hints> - <hint type="sourcelabel"> - <x>248</x> - <y>254</y> - </hint> - <hint type="destinationlabel"> - <x>157</x> - <y>274</y> - </hint> - </hints> - </connection> - <connection> - <sender>buttonBox</sender> - <signal>rejected()</signal> - <receiver>UrlInterceptorDialog</receiver> - <slot>reject()</slot> - <hints> - <hint type="sourcelabel"> - <x>316</x> - <y>260</y> - </hint> - <hint type="destinationlabel"> - <x>286</x> - <y>274</y> - </hint> - </hints> - </connection> - </connections> -</ui> diff --git a/src/filter/subscriptionform.ui b/src/filter/subscriptionform.ui deleted file mode 100644 index 0a20582..0000000 --- a/src/filter/subscriptionform.ui +++ /dev/null @@ -1,125 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>SubscriptionForm</class> - <widget class="QWidget" name="SubscriptionForm"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>640</width> - <height>480</height> - </rect> - </property> - <property name="windowTitle"> - <string>Form</string> - </property> - <layout class="QVBoxLayout" name="verticalLayout"> - <item> - <widget class="QGroupBox" name="groupBox"> - <property name="title"> - <string>Subscription</string> - </property> - <layout class="QHBoxLayout" name="horizontalLayout"> - <item> - <layout class="QFormLayout" name="leftFormLayout"> - <item row="0" column="0"> - <widget class="QLabel" name="title_label"> - <property name="text"> - <string>Title</string> - </property> - </widget> - </item> - <item row="0" column="1"> - <widget class="QLabel" name="title"> - <property name="text"> - <string>TextLabel</string> - </property> - </widget> - </item> - <item row="1" column="0"> - <widget class="QLabel" name="homepage_label"> - <property name="text"> - <string>Homepage</string> - </property> - </widget> - </item> - <item row="1" column="1"> - <widget class="QLabel" name="homepage"> - <property name="text"> - <string>TextLabel</string> - </property> - </widget> - </item> - <item row="2" column="0"> - <widget class="QLabel" name="license_label"> - <property name="text"> - <string>License</string> - </property> - </widget> - </item> - <item row="2" column="1"> - <widget class="QLabel" name="license"> - <property name="text"> - <string>TextLabel</string> - </property> - </widget> - </item> - </layout> - </item> - <item> - <layout class="QFormLayout" name="rightFormLayout"> - <item row="0" column="0"> - <widget class="QLabel" name="version_label"> - <property name="text"> - <string>Version</string> - </property> - </widget> - </item> - <item row="0" column="1"> - <widget class="QLabel" name="version"> - <property name="text"> - <string>TextLabel</string> - </property> - </widget> - </item> - <item row="1" column="0"> - <widget class="QLabel" name="lastModified_label"> - <property name="text"> - <string>Last Modified</string> - </property> - </widget> - </item> - <item row="1" column="1"> - <widget class="QLabel" name="lastModified"> - <property name="text"> - <string>TextLabel</string> - </property> - </widget> - </item> - <item row="2" column="0"> - <widget class="QLabel" name="expires_label"> - <property name="text"> - <string>Expires</string> - </property> - </widget> - </item> - <item row="2" column="1"> - <widget class="QLabel" name="expires"> - <property name="text"> - <string>TextLabel</string> - </property> - </widget> - </item> - </layout> - </item> - </layout> - </widget> - </item> - <item> - <widget class="QTreeView" name="treeView"/> - </item> - </layout> - </widget> - <resources/> - <connections/> -</ui> diff --git a/src/formats/adblockrule.cpp b/src/formats/adblockrule.cpp deleted file mode 100644 index fa9d93a..0000000 --- a/src/formats/adblockrule.cpp +++ /dev/null @@ -1,198 +0,0 @@ -/* - * 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: git://neueland.iserlohn-fortress.net/smolbote.git - * - * SPDX-License-Identifier: GPL-3.0 - */ - -#include "blockerrule.h" - -/* AdBlock filter reference - * https://adblockplus.org/en/filters - * https://adblockplus.org/en/filter-cheatsheet - */ - -BlockerRule::BlockerRule(QString rule, QObject *parent) : - QObject(parent) -{ - m_filter = rule; - QString pattern = rule; - - // Empty rule or comment - if(pattern.trimmed().isEmpty() || pattern.startsWith("!")) { - m_valid = false; - return; - } - - // Exception - if(pattern.startsWith("@@")) { - m_exception = true; - pattern.remove(0, 2); - } - - // Ignore element hiding rules for now - if(pattern.contains("##") || pattern.contains("#@#")) { - m_valid = false; - return; - } - - // Options - if(pattern.contains("$")) { - QString opts = pattern.mid(pattern.indexOf("$")+1); - pattern.remove(pattern.indexOf("$"), pattern.length()); - - const QStringList optList = opts.split(','); - QStringList::const_iterator i; - for(i = optList.constBegin(); i != optList.constEnd(); ++i) { - parseOption(*i); - } - } - - // Regular expression - if(rule.startsWith("/") && rule.endsWith("/")) { - m_valid = true; - ruleExpression.setPattern(pattern); - return; - } - - // Domain rules - if(pattern.startsWith("||")) { - pattern.remove(0, 2); - // find the end point for the domain - int end = pattern.indexOf(QRegularExpression("(?:[^\\w\\d\\_\\-\\.\\%]|$)"), 0); - domainExpression.setPattern(pattern.mid(0, end)); - pattern.remove(0, end+1); - } else if(pattern.startsWith("|") && pattern.endsWith("|")) { - pattern.remove(0, 1); - pattern.chop(1); - domainExpression.setPattern(pattern); - } else { - domainExpression.setPattern(".*"); - } - - // Regular rule - ruleExpression.setWildcardPattern(pattern); - m_valid = true; -} - -bool BlockerRule::match(const QWebEngineUrlRequestInfo &info) -{ - if(!m_valid) { - return false; - } - - // if both domain and rule match - if(domainExpression.match(info.requestUrl().host()) && ruleExpression.match(info.requestUrl().toString())) { - - // option explicitly allows - if(matchOptions(info, m_whitelistOptions)) { - return false; - } - - // option explicitly bans - if(matchOptions(info, m_blacklistOptions)) { - return true; - } - - // no options, but both domain and rule match --> rule matches - return true; - } - - // domain and/or rule do not match - return false; -} - -bool BlockerRule::isValid() -{ - return m_valid; -} -bool BlockerRule::isException() -{ - return m_exception; -} - -QString BlockerRule::filter() const -{ - return m_filter; -} - -void BlockerRule::parseOption(const QString &opt) -{ - if(opt.startsWith("script")) { - m_blacklistOptions.setFlag(RuleOption::script, true); - } else if(opt.startsWith("~script")) { - m_whitelistOptions.setFlag(RuleOption::script, true); - - } else if(opt.startsWith("image")) { - m_blacklistOptions.setFlag(RuleOption::image, true); - } else if(opt.startsWith("~image")) { - m_whitelistOptions.setFlag(RuleOption::image, true); - - } else if(opt.startsWith("stylesheet")) { - m_blacklistOptions.setFlag(RuleOption::stylesheet, true); - } else if(opt.startsWith("~stylesheet")) { - m_whitelistOptions.setFlag(RuleOption::stylesheet, true); - - } else if(opt.startsWith("object")) { - m_blacklistOptions.setFlag(RuleOption::object, true); - } else if(opt.startsWith("~object")) { - m_whitelistOptions.setFlag(RuleOption::object, true); - - } else if(opt.startsWith("object-subrequest")) { - m_blacklistOptions.setFlag(RuleOption::objectsubrequest, true); - } else if(opt.startsWith("~object-subrequest")) { - m_whitelistOptions.setFlag(RuleOption::objectsubrequest, true); - - } else if(opt.startsWith("subdocument")) { - m_blacklistOptions.setFlag(RuleOption::subdocument, true); - } else if(opt.startsWith("~subdocument")) { - m_whitelistOptions.setFlag(RuleOption::subdocument, true); - } -} - -bool BlockerRule::matchOptions(const QWebEngineUrlRequestInfo &info, const RuleOptions &options) -{ - // no options are defined - if(options == 0) { - return false; - } - - bool hasOption = false; - switch (info.resourceType()) { - case QWebEngineUrlRequestInfo::ResourceTypeScript: - if(options.testFlag(RuleOption::script)) { - hasOption = true; - } - break; - case QWebEngineUrlRequestInfo::ResourceTypeImage: - if(options.testFlag(RuleOption::image)) { - hasOption = true; - } - break; - case QWebEngineUrlRequestInfo::ResourceTypeStylesheet: - if(options.testFlag(RuleOption::stylesheet)) { - hasOption = true; - } - break; - case QWebEngineUrlRequestInfo::ResourceTypeObject: - if(options.testFlag(RuleOption::object)) { - hasOption = true; - } - break; - case QWebEngineUrlRequestInfo::ResourceTypePluginResource: - if(options.testFlag(RuleOption::objectsubrequest)) { - hasOption = true; - } - break; - case QWebEngineUrlRequestInfo::ResourceTypeSubFrame: - if(options.testFlag(RuleOption::subdocument)) { - hasOption = true; - } - break; - default: - break; - } - - return hasOption; -} diff --git a/src/formats/adblockrule.h b/src/formats/adblockrule.h deleted file mode 100644 index a56be2a..0000000 --- a/src/formats/adblockrule.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * 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: git://neueland.iserlohn-fortress.net/smolbote.git - * - * SPDX-License-Identifier: GPL-3.0 - */ - -#ifndef ADBLOCKRULE_H -#define ADBLOCKRULE_H - -#include <QObject> -#include <QUrl> -#include "regexp.h" -#include <QWebEngineUrlRequestInfo> - -class BlockerRule : public QObject -{ - Q_OBJECT -public: - - // https://adblockplus.org/en/filters#options - enum RuleOption { - script = 1, - image = 2, - stylesheet = 4, - object = 8, - xmlhttprequest = 16, - objectsubrequest = 32, - subdocument = 64, - ping = 128, - websocket = 256, - document = 512, - elemhide = 1024, - generichide = 2048, - genericblock = 4096, - other = 8192 - }; - Q_DECLARE_FLAGS(RuleOptions, RuleOption) - - explicit BlockerRule(QString rule, QObject *parent = 0); - - bool match(const QWebEngineUrlRequestInfo &info); - bool isValid(); - bool isException(); - QString filter() const; - -signals: - -public slots: - -private: - void parseOption(const QString &opt); - bool matchOptions(const QWebEngineUrlRequestInfo &info, const RuleOptions &options); - - QString m_filter; - - bool m_valid; - bool m_exception = false; - bool m_elementRule; - - QStringList hostsBlacklist; - QStringList hostsWhitelist; - RegExp domainExpression; - RegExp ruleExpression; - - RuleOptions m_blacklistOptions; - RuleOptions m_whitelistOptions; -}; - -#endif // ADBLOCKRULE_H diff --git a/src/plugins/plugins.qbs b/src/plugins/plugins.qbs deleted file mode 100644 index 85f9c88..0000000 --- a/src/plugins/plugins.qbs +++ /dev/null @@ -1,5 +0,0 @@ -Project { - references: [ - //"tomleditor/tomleditor.qbs", - ] -} diff --git a/src/plugins/testplugin/testplugin.cpp b/src/plugins/testplugin/testplugin.cpp deleted file mode 100644 index bc62de5..0000000 --- a/src/plugins/testplugin/testplugin.cpp +++ /dev/null @@ -1,19 +0,0 @@ -/* - * 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: git://neueland.iserlohn-fortress.net/smolbote.git - * - * SPDX-License-Identifier: GPL-3.0 - */ - -#include "testplugin.h" - -TestPlugin::TestPlugin(QObject *parent) : QObject(parent) -{ - -} - -QString TestPlugin::name() const -{ - return QString("Test Plugin"); -} diff --git a/src/plugins/testplugin/testplugin.h b/src/plugins/testplugin/testplugin.h deleted file mode 100644 index 651e823..0000000 --- a/src/plugins/testplugin/testplugin.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * 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: git://neueland.iserlohn-fortress.net/smolbote.git - * - * SPDX-License-Identifier: GPL-3.0 - */ - -#ifndef TESTPLUGIN_H -#define TESTPLUGIN_H - -#include <QObject> -#include "interfaces.h" - -class TestPlugin : public QObject, - public PluginInterface -{ - Q_OBJECT - Q_PLUGIN_METADATA(IID PluginInterface_iid) - Q_INTERFACES(PluginInterface) - -public: - explicit TestPlugin(QObject *parent = nullptr); - - // PluginInterface - QString name() const override; - -signals: - -public slots: -}; - -#endif // TESTPLUGIN_H diff --git a/src/plugins/tomleditor/tomleditor.qbs b/src/plugins/tomleditor/tomleditor.qbs deleted file mode 100644 index 9b577a7..0000000 --- a/src/plugins/tomleditor/tomleditor.qbs +++ /dev/null @@ -1,26 +0,0 @@ -import qbs 1.0 - -Project { - name: "tomleditor" - - DynamicLibrary { - id: tomleditor - name: "tomleditor" - Depends { name: "cpp" } - Depends { name: "Qt"; submodules: ["core", "widgets", "webengine", "webenginewidgets"] } - - cpp.includePaths: ["../.."] - files: [ - "tomleditorform.cpp", - "tomleditorform.h", - "tomleditorform.ui", - ] - - Group { - fileTagsFilter: product.type - qbs.install: true - qbs.installDir: "lib/smolbote/plugins" - } - - } // DynamicLibrary testPlugin -} diff --git a/src/plugins/tomleditor/tomleditorform.cpp b/src/plugins/tomleditor/tomleditorform.cpp deleted file mode 100644 index c985b1e..0000000 --- a/src/plugins/tomleditor/tomleditorform.cpp +++ /dev/null @@ -1,41 +0,0 @@ -/* - * 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: git://neueland.iserlohn-fortress.net/smolbote.git - * - * SPDX-License-Identifier: GPL-3.0 - */ - -#include "tomleditorform.h" -#include "ui_tomleditorform.h" - -#include <QAction> - -TomlEditorForm::TomlEditorForm(QWidget *parent) : - QWidget(parent), - ui(new Ui::TomlEditorForm) -{ - ui->setupUi(this); - m_action = new QAction(tr("Editor")); - connect(m_action, SIGNAL(triggered()), this, SLOT(show())); -} - -TomlEditorForm::~TomlEditorForm() -{ - delete ui; -} - -QString TomlEditorForm::name() const -{ - return QString("Toml Editor Plugin"); -} - -QWidget *TomlEditorForm::widget() -{ - return this; -} - -QAction *TomlEditorForm::action() -{ - return m_action; -} diff --git a/src/plugins/tomleditor/tomleditorform.h b/src/plugins/tomleditor/tomleditorform.h deleted file mode 100644 index 77512ba..0000000 --- a/src/plugins/tomleditor/tomleditorform.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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: git://neueland.iserlohn-fortress.net/smolbote.git - * - * SPDX-License-Identifier: GPL-3.0 - */ - -#ifndef TOMLEDITORFORM_H -#define TOMLEDITORFORM_H - -#include <QWidget> -#include <interfaces.h> - -namespace Ui { -class TomlEditorForm; -} - -class TomlEditorForm : public QWidget, - public PluginInterface, - public GuiInterface -{ - Q_OBJECT - Q_PLUGIN_METADATA(IID PluginInterface_iid) - Q_INTERFACES(PluginInterface GuiInterface) - -public: - explicit TomlEditorForm(QWidget *parent = 0); - ~TomlEditorForm(); - - // PluginInterface - QString name() const override; - - // GuiInterface - QWidget *widget() override; - QAction *action() override; - -private: - Ui::TomlEditorForm *ui; - - QAction *m_action; -}; - -#endif // TOMLEDITORFORM_H diff --git a/src/plugins/tomleditor/tomleditorform.ui b/src/plugins/tomleditor/tomleditorform.ui deleted file mode 100644 index adc750e..0000000 --- a/src/plugins/tomleditor/tomleditorform.ui +++ /dev/null @@ -1,22 +0,0 @@ -<?xml version='1.0'?> -<ui version="4.0"> - <author/> - <comment/> - <exportmacro/> - <class>TomlEditorForm</class> - <widget name="TomlEditorForm" class="QWidget"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>240</width> - <height>320</height> - </rect> - </property> - <property name="windowTitle"> - <string>Form</string> - </property> - </widget> - <pixmapfunction/> - <connections/> -</ui> diff --git a/src/webengine/hostrule.cpp b/src/webengine/hostrule.cpp new file mode 100644 index 0000000..1605b78 --- /dev/null +++ b/src/webengine/hostrule.cpp @@ -0,0 +1,47 @@ +/* + * 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: git://neueland.iserlohn-fortress.net/smolbote.git + * + * SPDX-License-Identifier: GPL-3.0 + */ + +#include "hostrule.h" + +HostRule::HostRule(const QString &line) +{ + valid = parse(line); +} + +QString HostRule::pattern() const +{ + return domain; +} + +bool HostRule::shouldBlock(const QWebEngineUrlRequestInfo &info) const +{ + if(info.requestUrl().host().contains(domain)) { + return true; + } + return false; +} + +bool HostRule::parse(const QString &line) +{ + QStringList parts = line.split(' '); + if(parts.first() == "0.0.0.0") { + blocking = true; + } else { + qDebug("Skipping rule: '%s'", qUtf8Printable(line)); + } + + domain = parts.last(); + +#ifdef QT_DEBUG + if(domain.isEmpty()) { + qWarning("error parsing %s", qUtf8Printable(line)); + } +#endif + + return true; +} diff --git a/src/webengine/hostrule.h b/src/webengine/hostrule.h new file mode 100644 index 0000000..d1289a0 --- /dev/null +++ b/src/webengine/hostrule.h @@ -0,0 +1,31 @@ +/* + * 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: git://neueland.iserlohn-fortress.net/smolbote.git + * + * SPDX-License-Identifier: GPL-3.0 + */ + +#ifndef HOSTRULE_H +#define HOSTRULE_H + +#include <QString> +#include <QWebEngineUrlRequestInfo> + +class HostRule +{ +public: + HostRule(const QString &line); + QString pattern() const; + bool shouldBlock(const QWebEngineUrlRequestInfo &info) const; + +private: + bool valid = false; + + bool parse(const QString &line); + + QString domain; + bool blocking; +}; + +#endif // HOSTRULE_H diff --git a/src/webengine/urlinterceptor.cpp b/src/webengine/urlinterceptor.cpp index 363d3ba..9598f36 100644 --- a/src/webengine/urlinterceptor.cpp +++ b/src/webengine/urlinterceptor.cpp @@ -7,6 +7,7 @@ */ #include "urlinterceptor.h" +#include <QDir> #include <QFile> #include <QTextStream> @@ -17,46 +18,60 @@ UrlRequestInterceptor::UrlRequestInterceptor(const QString &path, QObject *paren qDebug("Reading request blocklist: %s", qUtf8Printable(path)); #endif - int n_rules = 0; - - QFile filter(path); - if(filter.open(QIODevice::ReadOnly | QIODevice::Text)) { - QTextStream out(&filter); - while(!out.atEnd()) { - const QString &line = out.readLine(); - if(!line.startsWith('!')) { - FilterRule r(line); - // check if valid - m_rules.push_back(std::move(r)); - ++n_rules; - } - } - filter.close(); + QDir hostsD(path); + for(const QString &file : hostsD.entryList(QDir::Files)) { + qDebug("Parsing hosts.d/%s: %i", qUtf8Printable(file), parseHostfile(hostsD.absoluteFilePath(file))); } +} - qDebug("Added %i rules", n_rules); +UrlRequestInterceptor::~UrlRequestInterceptor() +{ + for(HostRule *r : m_rules) { + delete r; + } } void UrlRequestInterceptor::interceptRequest(QWebEngineUrlRequestInfo &info) { - for(const FilterRule &test : m_rules) { - const QUrl &url = info.requestUrl(); +//#ifdef QT_DEBUG +// qDebug("%s -> %s", qUtf8Printable(info.firstPartyUrl().toString()), qUtf8Printable(info.requestUrl().toString())); +//#endif - if(test.shouldBlock(url)) { + for(HostRule *test : m_rules) { + if(test->shouldBlock(info)) { info.block(true); -#ifdef QT_DEBUG - qDebug("blocked [%s] %s", qUtf8Printable(info.firstPartyUrl().toString()), qUtf8Printable(url.toString())); -#endif +//#ifdef QT_DEBUG +// qDebug("blocked on pattern %s", qUtf8Printable(test->pattern())); +//#endif return; } } } -bool shouldBlock(const QUrl &url, const QString &test) +int UrlRequestInterceptor::parseHostfile(const QString &filename) { - if(url.toString().contains(test)) { - return true; + int numRules = 0; + QFile file(filename); + + // try to open the file + if(file.open(QIODevice::ReadOnly | QIODevice::Text)) { + + // with a QTextStream we can read lines without getting linebreaks at the end + QTextStream out(&file); + while(!out.atEnd()) { + const QString &line = out.readLine().trimmed(); + + // skip comments and empty lines + if(!line.startsWith('#') && !line.isEmpty()) { + HostRule *r = new HostRule(line); + m_rules.push_back(r); + ++numRules; + } + } + + // close once we're done with it + file.close(); } - return false; + return numRules; } diff --git a/src/webengine/urlinterceptor.h b/src/webengine/urlinterceptor.h index cf1597c..1ff786b 100644 --- a/src/webengine/urlinterceptor.h +++ b/src/webengine/urlinterceptor.h @@ -11,26 +11,22 @@ #include <QWebEngineUrlRequestInterceptor> #include <vector> -#include "filter/filter.h" +#include "hostrule.h" class UrlRequestInterceptor : public QWebEngineUrlRequestInterceptor { Q_OBJECT public: explicit UrlRequestInterceptor(const QString &path, QObject *parent = nullptr); - //~UrlRequestInterceptor(); + ~UrlRequestInterceptor(); void interceptRequest(QWebEngineUrlRequestInfo &info); -signals: - public slots: + int parseHostfile(const QString &filename); private: - - std::vector<FilterRule> m_rules; + std::vector<HostRule*> m_rules; }; -bool shouldBlock(const QUrl &url, const QString &test); - #endif // URLREQUESTINTERCEPTOR_H |