aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt2
-rw-r--r--src/browser.cpp6
-rw-r--r--src/browser.h4
-rw-r--r--src/webengine/filter.cpp116
-rw-r--r--src/webengine/filter.h45
-rw-r--r--src/webengine/urlinterceptor.cpp127
-rw-r--r--src/webengine/urlinterceptor.h18
7 files changed, 190 insertions, 128 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 45a4c06..e8f2794 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -38,6 +38,8 @@ set(srclist
subwindow/tabwidget.h
# webengine
+ webengine/filter.cpp
+ webengine/filter.h
webengine/urlinterceptor.cpp
webengine/urlinterceptor.h
webengine/webpage.cpp
diff --git a/src/browser.cpp b/src/browser.cpp
index 7bf4adf..7295b56 100644
--- a/src/browser.cpp
+++ b/src/browser.cpp
@@ -27,6 +27,7 @@
#include <version.h>
#include <web/profilemanager.h>
#include <web/webprofile.h>
+#include "webengine/filter.h"
Browser::Browser(int &argc, char *argv[], bool allowSecondary)
: SingleApplication(argc, argv, allowSecondary, SingleApplication::User | SingleApplication::SecondaryNotification | SingleApplication::ExcludeAppVersion)
@@ -58,7 +59,8 @@ QPair<QString, WebProfile *> Browser::loadProfile(const QString &id)
{
WebProfile *profile = m_profileManager->loadProfile(id);
connect(profile, &WebProfile::downloadRequested, m_downloads.get(), &DownloadsWidget::addDownload);
- profile->setRequestInterceptor(m_urlFilter.get());
+ auto *interceptor = new UrlRequestInterceptor(m_urlFilter.get(), profile, profile);
+ profile->setRequestInterceptor(interceptor);
return QPair<QString, WebProfile *>(m_profileManager->id(profile), profile);
}
@@ -107,7 +109,7 @@ void Browser::setup()
// downloads
m_downloads = std::make_unique<DownloadsWidget>(m_config->value<QString>("downloads.path").value());
// url request filter
- m_urlFilter = std::make_unique<UrlRequestInterceptor>(m_config);
+ m_urlFilter = std::make_unique<Filter>(m_config);
// cookie request filter
// load profiles
diff --git a/src/browser.h b/src/browser.h
index b4352a7..6731f59 100644
--- a/src/browser.h
+++ b/src/browser.h
@@ -20,7 +20,7 @@
class Configuration;
class BookmarksWidget;
class DownloadsWidget;
-class UrlRequestInterceptor;
+class Filter;
class MainWindow;
class WebProfile;
class Browser : public SingleApplication, public BrowserInterface
@@ -62,7 +62,7 @@ private:
std::shared_ptr<BookmarksWidget> m_bookmarks;
std::unique_ptr<DownloadsWidget> m_downloads;
ProfileManager *m_profileManager;
- std::unique_ptr<UrlRequestInterceptor> m_urlFilter;
+ std::unique_ptr<Filter> m_urlFilter;
QVector<MainWindow *> m_windows;
QVector<Plugin> m_plugins;
diff --git a/src/webengine/filter.cpp b/src/webengine/filter.cpp
new file mode 100644
index 0000000..b250843
--- /dev/null
+++ b/src/webengine/filter.cpp
@@ -0,0 +1,116 @@
+/*
+ * 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 "urlinterceptor.h"
+#include <QDir>
+#include <QJsonArray>
+#include <QJsonDocument>
+#include <QTextStream>
+#include <configuration/configuration.h>
+#include "util.h"
+
+
+QHash<QString, Filter::HostRule> parseHostlist(const QString &filename)
+{
+ QHash<QString, Filter::HostRule> rules;
+
+ if(QFile hostfile(filename); hostfile.open(QIODevice::ReadOnly | QIODevice::Text)) {
+
+ // with a QTextStream we can read lines without getting linebreaks at the end
+ QTextStream hostfile_stream(&hostfile);
+
+ while(!hostfile_stream.atEnd()) {
+
+ // read line and remove any whitespace at the end
+ const QString &line = hostfile_stream.readLine().trimmed();
+
+ // skip comments and empty lines
+ if(line.isEmpty() || line.startsWith('#'))
+ continue;
+
+ // everything else should be a rule
+ // format is <redirect> <host>
+ // 0.0.0.0 hostname
+ const QStringList &parts = line.split(' ');
+ const QString &redirect = parts.at(0);
+
+ for(auto i = parts.constBegin() + 1; i != parts.constEnd(); ++i) {
+ if(!rules.contains(*i)) {
+ Filter::HostRule rule{};
+ rule.isBlocking = (redirect == "0.0.0.0");
+ rules.insert(*i, rule);
+ }
+ }
+
+ // for(const QString &host : parts.mid(1)) {
+ // if(!rules.contains(host)) {
+ // UrlRequestInterceptor::HostRule rule{};
+ // rule.isBlocking = redirect == "0.0.0.0";
+ // rules.insert(host, rule);
+ // }
+ // }
+ }
+
+ hostfile.close();
+ }
+
+ return rules;
+}
+/*
+inline std::vector<FilterRule> parseAdBlockList(const QString &filename)
+{
+ std::vector<FilterRule> rules;
+ QFile list(filename);
+
+ if(list.open(QIODevice::ReadOnly | QIODevice::Text), true) {
+ QTextStream l(&list);
+ QString line;
+ while(l.readLineInto(&line)) {
+ AdBlockRule rule(line);
+ if(rule.isEnabled()) {
+ rules.emplace_back(std::move(rule));
+ }
+ }
+ list.close();
+ }
+
+ return rules;
+}*/
+
+Filter::Filter::Filter(const std::unique_ptr<Configuration> &config, QObject* parent)
+ : QObject(parent)
+{
+ // parse headers
+ if(const auto headers = config->value<QStringList>("filter.header"); headers) {
+ for(const QString &header : headers.value()) {
+ const auto list = header.split(QLatin1Literal(":"));
+ if(list.length() == 2)
+ m_headers.insert(list.at(0).toLatin1(), list.at(1).toLatin1());
+ }
+ }
+
+ const QStringList hostfiles = Util::files(config->value<QString>("filter.path").value());
+ for(const QString &hostfile : hostfiles) {
+ m_hostlist.unite(parseHostlist(hostfile));
+ }
+
+ /*
+ auto filtersPath = config->value<QString>("filter.adblock");
+ if(filtersPath)
+ filters = parseAdBlockList(filtersPath.value());
+ */
+}
+
+std::optional<Filter::HostRule> Filter::hostlistRule(const QString& url) const
+{
+ if(!m_hostlist.contains(url))
+ return std::nullopt;
+
+ return std::optional<Filter::HostRule>(m_hostlist.value(url));
+}
diff --git a/src/webengine/filter.h b/src/webengine/filter.h
new file mode 100644
index 0000000..3eac5ee
--- /dev/null
+++ b/src/webengine/filter.h
@@ -0,0 +1,45 @@
+/*
+ * 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 "urlfilter/filterrule.h"
+#include <QByteArray>
+#include <QVector>
+#include <optional>
+
+class Configuration;
+class Filter : public QObject
+{
+ Q_OBJECT
+public:
+ struct HostRule {
+ bool isBlocking;
+ };
+
+ explicit Filter(const std::unique_ptr<Configuration> &config, QObject *parent = nullptr);
+ ~Filter() override = default;
+
+ const QHash<QString, HostRule> hostlist() const
+ {
+ return qAsConst(m_hostlist);
+ }
+ std::optional<HostRule> hostlistRule(const QString &url) const;
+
+ const QMap<QByteArray, QByteArray> headers() const
+ {
+ return qAsConst(m_headers);
+ }
+
+private:
+ QHash<QString, HostRule> m_hostlist;
+ QMap<QByteArray, QByteArray> m_headers;
+};
+
+#endif // SMOLBOTE_FILTER_H
diff --git a/src/webengine/urlinterceptor.cpp b/src/webengine/urlinterceptor.cpp
index db4aea9..cf9b85f 100644
--- a/src/webengine/urlinterceptor.cpp
+++ b/src/webengine/urlinterceptor.cpp
@@ -14,127 +14,32 @@
#include <QTextStream>
#include <boost/algorithm/string.hpp>
#include <configuration/configuration.h>
+#include "filter.h"
+#include <web/webprofile.h>
-inline std::vector<FilterRule> parseAdBlockList(const QString &filename)
-{
- std::vector<FilterRule> rules;
- QFile list(filename);
-
- if(list.open(QIODevice::ReadOnly | QIODevice::Text), true) {
- QTextStream l(&list);
- QString line;
- while(l.readLineInto(&line)) {
- AdBlockRule rule(line);
- if(rule.isEnabled()) {
- rules.emplace_back(std::move(rule));
- }
- }
- list.close();
- }
-
- return rules;
-}
+// test DNT on https://browserleaks.com/donottrack
-UrlRequestInterceptor::UrlRequestInterceptor(const std::unique_ptr<Configuration> &config, QObject *parent)
+UrlRequestInterceptor::UrlRequestInterceptor(Filter* filter, WebProfile* profile, QObject* parent)
: QWebEngineUrlRequestInterceptor(parent)
{
- QDir hostsD(config->value<QString>("filter.path").value());
- const QStringList hostFiles = hostsD.entryList(QDir::Files);
- for(const QString &file : hostFiles) {
- const QString absPath = hostsD.absoluteFilePath(file);
- auto r = parse(absPath);
-#ifdef QT_DEBUG
- qDebug("Parsed %i rules from %s", r.count(), qUtf8Printable(absPath));
-#endif
-
- rules.unite(r);
- }
-
- const auto header = config->value<std::vector<std::string>>("filter.header");
- if(header) {
- for(const std::string &h : header.value()) {
- std::vector<std::string> s;
- boost::split(s, h, boost::is_any_of(":="));
- auto pair = std::make_pair(s.at(0), s.at(1));
- m_headers.emplace_back(pair);
- }
- }
-
- auto filtersPath = config->value<QString>("filter.adblock");
- if(filtersPath)
- filters = parseAdBlockList(filtersPath.value());
+ Q_CHECK_PTR(filter);
+ m_filter = filter;
+ Q_CHECK_PTR(profile);
+ m_profile = profile;
}
-// test DNT on https://browserleaks.com/donottrack
void UrlRequestInterceptor::interceptRequest(QWebEngineUrlRequestInfo &info)
{
- for(const Header &header : m_headers) {
- info.setHttpHeader(QByteArray::fromStdString(header.first), QByteArray::fromStdString(header.second));
+ auto hostlistCheck = m_filter->hostlistRule(info.requestUrl().host());
+ if(hostlistCheck) {
+ info.block(hostlistCheck.value().isBlocking);
}
- if(rules.contains(info.requestUrl().host())) {
- info.block(rules.value(info.requestUrl().host()).isBlocking);
- return;
+ // set headers
+ for(auto i = m_filter->headers().constBegin(); i != m_filter->headers().constEnd(); ++i) {
+ info.setHttpHeader(i.key(), i.value());
}
-
- const uint domainHash = qHash(info.firstPartyUrl().host());
- const QWebEngineUrlRequestInfo::ResourceType type = info.resourceType();
- const QUrl requestUrl = info.requestUrl();
- for(const FilterRule &rule : filters) {
- if(rule.matchesDomain(domainHash) && rule.matchesType(type) && rule.matchesUrl(requestUrl)) {
- info.block(rule.isBlocking());
-#ifdef QT_DEBUG
- qDebug("--> blocked %s", qUtf8Printable(info.requestUrl().toString()));
-#endif
- break;
- }
+ for(auto i = m_profile->headers().constBegin(); i != m_profile->headers().constEnd(); ++i) {
+ info.setHttpHeader(i.key(), i.value());
}
}
-
-QHash<QString, UrlRequestInterceptor::HostRule> parse(const QString &filename)
-{
- QHash<QString, UrlRequestInterceptor::HostRule> rules;
-
- QFile hostfile(filename);
- if(hostfile.open(QIODevice::ReadOnly | QIODevice::Text)) {
-
- // with a QTextStream we can read lines without getting linebreaks at the end
- QTextStream hostfile_stream(&hostfile);
-
- while(!hostfile_stream.atEnd()) {
-
- // read line and remove any whitespace at the end
- const QString &line = hostfile_stream.readLine().trimmed();
-
- // skip comments and empty lines
- if(line.isEmpty() || line.startsWith('#'))
- continue;
-
- // everything else should be a rule
- // format is <redirect> <host>
- // 0.0.0.0 hostname
- const QStringList &parts = line.split(' ');
- const QString &redirect = parts.at(0);
-
- for(auto i = parts.constBegin() + 1; i != parts.constEnd(); ++i) {
- if(!rules.contains(*i)) {
- UrlRequestInterceptor::HostRule rule{};
- rule.isBlocking = (redirect == "0.0.0.0");
- rules.insert(*i, rule);
- }
- }
-
- // for(const QString &host : parts.mid(1)) {
- // if(!rules.contains(host)) {
- // UrlRequestInterceptor::HostRule rule{};
- // rule.isBlocking = redirect == "0.0.0.0";
- // rules.insert(host, rule);
- // }
- // }
- }
-
- hostfile.close();
- }
-
- return rules;
-}
diff --git a/src/webengine/urlinterceptor.h b/src/webengine/urlinterceptor.h
index 575e0c9..420a161 100644
--- a/src/webengine/urlinterceptor.h
+++ b/src/webengine/urlinterceptor.h
@@ -15,29 +15,21 @@
#include <QWebEngineUrlRequestInterceptor>
#include <memory>
-typedef std::pair<std::string, std::string> Header;
-
+class Filter;
+class WebProfile;
class Configuration;
class UrlRequestInterceptor : public QWebEngineUrlRequestInterceptor
{
Q_OBJECT
public:
- struct HostRule {
- bool isBlocking;
- };
-
- explicit UrlRequestInterceptor(const std::unique_ptr<Configuration> &config, QObject *parent = nullptr);
+ explicit UrlRequestInterceptor(Filter *filter, WebProfile *profile, QObject *parent = nullptr);
~UrlRequestInterceptor() override = default;
void interceptRequest(QWebEngineUrlRequestInfo &info) override;
private:
- QHash<QString, HostRule> rules;
- std::vector<FilterRule> filters;
- std::vector<Header> m_headers;
+ Filter *m_filter;
+ WebProfile *m_profile;
};
-QHash<QString, UrlRequestInterceptor::HostRule> parse(const QString &filename);
-inline std::vector<FilterRule> parseAdBlockList(const QString &filename);
-
#endif // SMOLBOTE_URLREQUESTINTERCEPTOR_H