From 3d2ae07c455c0e423c64f19e445518427a5684fa Mon Sep 17 00:00:00 2001 From: Aqua-sama Date: Wed, 9 Jan 2019 19:38:58 +0100 Subject: Rewrite lib/urlfilter - Make HostList and AdBlockList implementations independent from each other - Move urlfilter tests to lib/urlfilter --- src/browser.cpp | 30 +++++++++++++++-- src/browser.h | 4 +-- src/meson.build | 3 +- src/webengine/filter.cpp | 70 ---------------------------------------- src/webengine/filter.h | 43 ------------------------ src/webengine/urlinterceptor.cpp | 53 ++++++++++++++++++++++-------- src/webengine/urlinterceptor.h | 16 +++++---- 7 files changed, 79 insertions(+), 140 deletions(-) delete mode 100644 src/webengine/filter.cpp delete mode 100644 src/webengine/filter.h (limited to 'src') diff --git a/src/browser.cpp b/src/browser.cpp index 42bbc5d..3a23eeb 100644 --- a/src/browser.cpp +++ b/src/browser.cpp @@ -18,7 +18,6 @@ #include "profilemanager.h" #include "subwindow/subwindow.h" #include "util.h" -#include "webengine/filter.h" #include "webengine/urlinterceptor.h" #include "webprofile.h" #include @@ -35,6 +34,9 @@ #include #include "mainwindow/menubar.h" #include "webengine/webview.h" +#include "urlfilter.h" +#include "adblock/adblocklist.h" +#include "hostlist/hostlist.h" Browser::Browser(int &argc, char *argv[], bool allowSecondary) : SingleApplication(argc, argv, allowSecondary, SingleApplication::User | SingleApplication::SecondaryNotification | SingleApplication::ExcludeAppVersion) @@ -99,7 +101,16 @@ QPair Browser::loadProfile(const QString &id, bool isOffTheR profile = m_profileManager->createProfile(id, isOffTheRecord); } connect(profile, &WebProfile::downloadRequested, m_downloads.get(), &DownloadsWidget::addDownload); - auto *interceptor = new UrlRequestInterceptor(m_urlFilter.get(), profile, profile); + auto *interceptor = new UrlRequestInterceptor(profile, profile); + for(UrlFilter *filter : m_filters) { + interceptor->addFilter(filter); + } + const auto headers = m_config->value("filter.header").value_or(QStringList()); + for(const QString &header : headers) { + const auto h = header.split(QLatin1Literal(":")); + if(h.length() == 2) + interceptor->addHttpHeader(h.at(0).toLatin1(), h.at(1).toLatin1()); + } profile->setRequestInterceptor(interceptor); return QPair(m_profileManager->id(profile), profile); @@ -164,7 +175,20 @@ void Browser::setup(QVector plugins) // downloads m_downloads = std::make_unique(m_config->value("downloads.path").value()); // url request filter - m_urlFilter = std::make_unique(m_config); + for(const QString &hostlist : Util::files(m_config->value("filter.hosts").value_or(QString()))) { + QFile f(hostlist); + if(f.open(QIODevice::ReadOnly | QIODevice::Text)) { + m_filters.append(new HostList(&f)); + f.close(); + } + } + for(const QString &adblock : Util::files(m_config->value("filter.adblock").value_or(QString()))) { + QFile f(adblock); + if(f.open(QIODevice::ReadOnly | QIODevice::Text)) { + m_filters.append(new AdBlockList(&f)); + f.close(); + } + } // cookie request filter // load profiles diff --git a/src/browser.h b/src/browser.h index 53ee521..8a40152 100644 --- a/src/browser.h +++ b/src/browser.h @@ -19,10 +19,10 @@ #include #include +class UrlFilter; class Configuration; class BookmarksWidget; class DownloadsWidget; -class Filter; class MainWindow; class ProfileManager; class Browser : public SingleApplication, public BrowserInterface @@ -91,7 +91,7 @@ private: std::shared_ptr m_bookmarks; std::unique_ptr m_downloads; ProfileManager *m_profileManager; - std::unique_ptr m_urlFilter; + QVector m_filters; QVector m_windows; QVector m_plugins; diff --git a/src/meson.build b/src/meson.build index f07a2ec..fb338d8 100644 --- a/src/meson.build +++ b/src/meson.build @@ -4,7 +4,7 @@ poi_moc = qt5.preprocess( 'mainwindow/mainwindow.h', 'mainwindow/menubar.h', 'mainwindow/widgets/dockwidget.h', 'mainwindow/widgets/menusearch.h', 'mainwindow/widgets/navigationbar.h', 'mainwindow/widgets/searchform.h', 'session/savesessiondialog.h', 'session/sessiondialog.h', 'session/sessionform.h', 'subwindow/subwindow.h', 'subwindow/tabwidget.h', - 'webengine/filter.h', 'webengine/urlinterceptor.h', 'webengine/webpage.h', 'webengine/webview.h'], + 'webengine/urlinterceptor.h', 'webengine/webpage.h', 'webengine/webview.h'], ui_files: ['mainwindow/widgets/searchform.ui', 'session/savesessiondialog.ui', 'session/sessiondialog.ui', 'session/sessionform.ui'], qresources: '../data/resources.qrc', rcc_extra_arguments: ['--format-version=1'], @@ -35,7 +35,6 @@ poi = executable(get_option('poiName'), install: true, 'subwindow/subwindow.cpp', 'subwindow/tabwidget.cpp', - 'webengine/filter.cpp', 'webengine/urlinterceptor.cpp', 'webengine/webpage.cpp', 'webengine/webview.cpp', diff --git a/src/webengine/filter.cpp b/src/webengine/filter.cpp deleted file mode 100644 index f1a38af..0000000 --- a/src/webengine/filter.cpp +++ /dev/null @@ -1,70 +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: https://neueland.iserlohn-fortress.net/gitea/aqua/smolbote - * - * SPDX-License-Identifier: GPL-3.0 - */ - -#include "filter.h" -#include "configuration.h" -#include "urlinterceptor.h" -#include "util.h" -#include -#include -#include -#include - -Filter::Filter::Filter(const std::unique_ptr &config, QObject *parent) - : QObject(parent) -{ - // parse headers - if(config->exists("filter.header")) { - const auto headers = config->value("filter.header").value(); - for(const QString header : headers) { - const auto list = header.split(QLatin1Literal(":")); - if(list.length() == 2) - m_headers.insert(list.at(0).toLatin1(), list.at(1).toLatin1()); - } -#ifdef QT_DEBUG - qDebug("Added %i custom http headers", m_headers.size()); -#endif - } - - const QStringList hostfiles = Util::files(config->value("filter.hosts").value()); - //qDebug("filter.path=[%s]", qUtf8Printable(config->value("filter.hosts").value())); - for(const QString &hostfile : hostfiles) { - QFile f(hostfile); - if(f.open(QIODevice::ReadOnly | QIODevice::Text)) { -#ifdef QT_DEBUG - qDebug("Loading hostlist filters [%s]", qUtf8Printable(hostfile)); -#endif - loadHostlist(f, &filters); - f.close(); - } - } -} - -void Filter::filterRequest(QWebEngineUrlRequestInfo &info) const -{ - auto matches = filters.match(info.firstPartyUrl().toString(), info.requestUrl().toString()); - for(const auto &rule : matches) { - switch(rule->action().first) { - case FilterLeaf::NotMatched: -#ifdef QT_DEBUG - qDebug("Paradoxical match: request matched, but not matched."); - qDebug(" - %s", qUtf8Printable(info.requestUrl().toString())); -#endif - break; - case FilterLeaf::Block: - //qDebug("block %s", qUtf8Printable(info.requestUrl().toString())); - info.block(true); - break; - case FilterLeaf::Allow: - info.block(false); - break; - //case FilterLeaf::Redirect: - // break; - } - } -} diff --git a/src/webengine/filter.h b/src/webengine/filter.h deleted file mode 100644 index c49bed9..0000000 --- a/src/webengine/filter.h +++ /dev/null @@ -1,43 +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: https://neueland.iserlohn-fortress.net/gitea/aqua/smolbote - * - * SPDX-License-Identifier: GPL-3.0 - */ - -#ifndef SMOLBOTE_FILTER_H -#define SMOLBOTE_FILTER_H - -#include -#include -#include -#include -#include -#include "filtertree.h" - -class Configuration; -class Filter : public QObject -{ - Q_OBJECT -public: - struct HostRule { - bool isBlocking; - }; - - explicit Filter(const std::unique_ptr &config, QObject *parent = nullptr); - ~Filter() override = default; - - void filterRequest(QWebEngineUrlRequestInfo &info) const; - - const QMap headers() const - { - return qAsConst(m_headers); - } - -private: - FilterTree filters; - QMap m_headers; -}; - -#endif // SMOLBOTE_FILTER_H diff --git a/src/webengine/urlinterceptor.cpp b/src/webengine/urlinterceptor.cpp index 7e5630f..490dea6 100644 --- a/src/webengine/urlinterceptor.cpp +++ b/src/webengine/urlinterceptor.cpp @@ -7,36 +7,61 @@ */ #include "urlinterceptor.h" -#include "formats/adblockrule.h" -#include -#include -#include -#include -#include -#include "configuration.h" -#include "filter.h" #include "webprofile.h" +#include "urlfilter.h" // test DNT on https://browserleaks.com/donottrack -UrlRequestInterceptor::UrlRequestInterceptor(Filter* filter, WebProfile* profile, QObject* parent) +UrlRequestInterceptor::UrlRequestInterceptor(WebProfile* profile, QObject* parent) : QWebEngineUrlRequestInterceptor(parent) { - Q_CHECK_PTR(filter); - m_filter = filter; Q_CHECK_PTR(profile); m_profile = profile; } +void UrlRequestInterceptor::addHttpHeader(const QByteArray &key, const QByteArray &value) +{ + headers.append(qMakePair(key, value)); +} + +void UrlRequestInterceptor::addFilter(UrlFilter *filter) +{ + if(filter != nullptr) + filters.append(filter); +} +void UrlRequestInterceptor::removeFilter(UrlFilter *filter) +{ + if(filter != nullptr) + filters.removeOne(filter); +} + void UrlRequestInterceptor::interceptRequest(QWebEngineUrlRequestInfo &info) { - m_filter->filterRequest(info); + for(const auto *filter : filters) { + const auto match = filter->match(info.firstPartyUrl(), info.requestUrl(), info.resourceType()); + + // skip if no match + if(match.first == UrlFilter::NotMatched) + continue; + + else { + if(match.first == UrlFilter::Allow) + info.block(false); + else if(match.first == UrlFilter::Block) + info.block(true); + else if(match.first == UrlFilter::Redirect) + info.redirect(QUrl::fromUserInput(match.second)); + // we found a match, skip the rest + break; + } + } // set headers - for(auto i = m_filter->headers().constBegin(); i != m_filter->headers().constEnd(); ++i) { - info.setHttpHeader(i.key(), i.value()); + for(const auto &header : headers) { + info.setHttpHeader(header.first, header.second); } for(auto i = m_profile->headers().constBegin(); i != m_profile->headers().constEnd(); ++i) { info.setHttpHeader(i.key(), i.value()); } } + diff --git a/src/webengine/urlinterceptor.h b/src/webengine/urlinterceptor.h index 62fd683..4909586 100644 --- a/src/webengine/urlinterceptor.h +++ b/src/webengine/urlinterceptor.h @@ -9,26 +9,30 @@ #ifndef SMOLBOTE_URLREQUESTINTERCEPTOR_H #define SMOLBOTE_URLREQUESTINTERCEPTOR_H -#include #include #include -#include +#include -class Filter; +class UrlFilter; class WebProfile; -class Configuration; class UrlRequestInterceptor : public QWebEngineUrlRequestInterceptor { Q_OBJECT public: - explicit UrlRequestInterceptor(Filter *filter, WebProfile *profile, QObject *parent = nullptr); + explicit UrlRequestInterceptor(WebProfile *profile, QObject *parent = nullptr); ~UrlRequestInterceptor() override = default; + void addHttpHeader(const QByteArray &key, const QByteArray &value); + + void addFilter(UrlFilter *filter); + void removeFilter(UrlFilter *filter); + void interceptRequest(QWebEngineUrlRequestInfo &info) override; private: - Filter *m_filter; WebProfile *m_profile; + QVector> headers; + QVector filters; }; #endif // SMOLBOTE_URLREQUESTINTERCEPTOR_H -- cgit v1.2.1