diff options
-rw-r--r-- | baseconfig | 2 | ||||
-rw-r--r-- | lib/configuration/configuration.cpp | 2 | ||||
-rw-r--r-- | lib/urlfilter/domain.cpp | 4 | ||||
-rw-r--r-- | lib/urlfilter/filterleaf.h | 2 | ||||
-rw-r--r-- | lib/urlfilter/filtertree.cpp | 4 | ||||
-rw-r--r-- | lib/urlfilter/filtertree.h | 2 | ||||
-rw-r--r-- | lib/urlfilter/formats/hostlistrule.cpp | 5 | ||||
-rw-r--r-- | lib/urlfilter/formats/hostlistrule.h | 2 | ||||
-rw-r--r-- | linux/.config | 2 | ||||
-rw-r--r-- | src/webengine/filter.cpp | 74 | ||||
-rw-r--r-- | src/webengine/filter.h | 9 | ||||
-rw-r--r-- | src/webengine/urlinterceptor.cpp | 5 | ||||
-rw-r--r-- | test/hostlist/hostlisttest.cpp | 10 |
13 files changed, 44 insertions, 79 deletions
@@ -52,7 +52,7 @@ menu "Configuration defaults" default "~/.config/smolbote/crash.d" config PATH_FILTER string "Host filter path" - default "~/.config/smolbote/host.d" + default "~/.config/smolbote/hosts.d" config PATH_PLUGINS string "Plugin load location" default "~/.config/smolbote/plugins.d" diff --git a/lib/configuration/configuration.cpp b/lib/configuration/configuration.cpp index cf58d82..25f783c 100644 --- a/lib/configuration/configuration.cpp +++ b/lib/configuration/configuration.cpp @@ -100,7 +100,7 @@ Configuration::Configuration(QObject *parent) ("subwindow.shortcuts.fullscreen", po::value<std::string>()->default_value("F11")) // Filter settings - ("filter.path", po::value<std::string>()->default_value(Path_Filter)) + ("filter.hosts", po::value<std::string>()->default_value(Path_Filter)) ("filter.adblock", po::value<std::string>()) ("filter.header", po::value<std::vector<std::string>>()) // ("filter.cookies.block.all", po::value<bool>()->default_value(false)) diff --git a/lib/urlfilter/domain.cpp b/lib/urlfilter/domain.cpp index 20c4f3a..2bfd524 100644 --- a/lib/urlfilter/domain.cpp +++ b/lib/urlfilter/domain.cpp @@ -29,6 +29,10 @@ Domain &Domain::operator=(Domain &&other) bool Domain::matches(const QUrl &url) const { + // empty domain matches all + if(m_domain.isEmpty() || url.isEmpty()) + return true; + const QString domain = url.host(); // domain and filter are the same diff --git a/lib/urlfilter/filterleaf.h b/lib/urlfilter/filterleaf.h index 36c00e9..dcd3ec0 100644 --- a/lib/urlfilter/filterleaf.h +++ b/lib/urlfilter/filterleaf.h @@ -28,7 +28,7 @@ public: FilterLeaf &operator=(FilterLeaf &&other); ~FilterLeaf() = default; - virtual bool match(const QString &requestUrl) const = 0; + virtual bool match(const QUrl &requestUrl) const = 0; virtual Action action() const = 0; const QString request() const; diff --git a/lib/urlfilter/filtertree.cpp b/lib/urlfilter/filtertree.cpp index dcde196..2cdd6d0 100644 --- a/lib/urlfilter/filtertree.cpp +++ b/lib/urlfilter/filtertree.cpp @@ -57,11 +57,11 @@ const QStringList FilterTree::branches() const return branches; } -QVector<const FilterLeaf *> FilterTree::match(const QString &domain, const QString &requestUrl) const +QVector<const FilterLeaf *> FilterTree::match(const QUrl &domain, const QUrl &requestUrl) const { QVector<const FilterLeaf *> leaves; for(const auto &branch : m_branches) { - if(branch.domain.matches(QUrl(domain))) { + if(branch.domain.matches(domain)) { for(const auto leaf : branch.leaves) { if(leaf->match(requestUrl)) { diff --git a/lib/urlfilter/filtertree.h b/lib/urlfilter/filtertree.h index 3da82e0..f453a3d 100644 --- a/lib/urlfilter/filtertree.h +++ b/lib/urlfilter/filtertree.h @@ -30,7 +30,7 @@ public: ~FilterTree(); const QStringList branches() const; - QVector<const FilterLeaf *> match(const QString &domain, const QString &requestUrl) const; + QVector<const FilterLeaf *> match(const QUrl &domain, const QUrl &requestUrl) const; bool addRule(FilterLeaf *rule, const QString &domain); diff --git a/lib/urlfilter/formats/hostlistrule.cpp b/lib/urlfilter/formats/hostlistrule.cpp index f0cb4af..e4561f0 100644 --- a/lib/urlfilter/formats/hostlistrule.cpp +++ b/lib/urlfilter/formats/hostlistrule.cpp @@ -15,9 +15,10 @@ HostlistRule::HostlistRule(const QString &domain, const QString &redirect) this->m_redirect = redirect; } -bool HostlistRule::match(const QString &requestUrl) const +bool HostlistRule::match(const QUrl &requestUrl) const { - return (m_request == requestUrl); + //qDebug("checking [%s] against [%s]", qUtf8Printable(requestUrl.host()), qUtf8Printable(m_request)); + return (m_request == requestUrl.host()); } FilterLeaf::Action HostlistRule::action() const diff --git a/lib/urlfilter/formats/hostlistrule.h b/lib/urlfilter/formats/hostlistrule.h index 19fd63f..c65a98f 100644 --- a/lib/urlfilter/formats/hostlistrule.h +++ b/lib/urlfilter/formats/hostlistrule.h @@ -17,7 +17,7 @@ class HostlistRule : public FilterLeaf public: explicit HostlistRule(const QString &domain, const QString &redirect); - bool match(const QString &requestUrl) const override; + bool match(const QUrl &requestUrl) const override; FilterLeaf::Action action() const override; }; diff --git a/linux/.config b/linux/.config index 8a84cad..09b5a4a 100644 --- a/linux/.config +++ b/linux/.config @@ -36,7 +36,7 @@ CONFIG_POI_EXE="poi" # CONFIG_PATH_CONFIG="~/.config/smolbote/smolbote.cfg" CONFIG_PATH_CRASHDUMP="~/.config/smolbote/crash.d" -CONFIG_PATH_FILTER="~/.config/smolbote/host.d" +CONFIG_PATH_FILTER="~/.config/smolbote/hosts.d" CONFIG_PATH_PLUGINS="~/.config/smolbote/plugins.d" CONFIG_PATH_PROFILES="~/.config/smolbote/profiles.d" CONFIG_PATH_BOOKMARKS="~/.config/smolbote/bookmarks.xbel" diff --git a/src/webengine/filter.cpp b/src/webengine/filter.cpp index b250843..3ff6a04 100644 --- a/src/webengine/filter.cpp +++ b/src/webengine/filter.cpp @@ -15,53 +15,6 @@ #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) { @@ -95,9 +48,17 @@ Filter::Filter::Filter(const std::unique_ptr<Configuration> &config, QObject* pa } } - const QStringList hostfiles = Util::files(config->value<QString>("filter.path").value()); + const QStringList hostfiles = Util::files(config->value<QString>("filter.hosts").value()); + //qDebug("filter.path=[%s]", qUtf8Printable(config->value<QString>("filter.hosts").value())); for(const QString &hostfile : hostfiles) { - m_hostlist.unite(parseHostlist(hostfile)); + 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(); + } } /* @@ -107,10 +68,15 @@ Filter::Filter::Filter(const std::unique_ptr<Configuration> &config, QObject* pa */ } -std::optional<Filter::HostRule> Filter::hostlistRule(const QString& url) const +void Filter::filterRequest(QWebEngineUrlRequestInfo& info) const { - if(!m_hostlist.contains(url)) - return std::nullopt; - - return std::optional<Filter::HostRule>(m_hostlist.value(url)); + auto matches = filters.match(info.firstPartyUrl().toString(), info.requestUrl().toString()); + for(const auto &rule : matches) { + switch(rule->action()) { + case FilterLeaf::Block: + qDebug("block %s", qUtf8Printable(info.requestUrl().toString())); + info.block(true); + break; + } + } } diff --git a/src/webengine/filter.h b/src/webengine/filter.h index 3eac5ee..c610b29 100644 --- a/src/webengine/filter.h +++ b/src/webengine/filter.h @@ -13,6 +13,7 @@ #include <QByteArray> #include <QVector> #include <optional> +#include "urlfilter/filtertree.h" class Configuration; class Filter : public QObject @@ -26,11 +27,7 @@ public: 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; + void filterRequest(QWebEngineUrlRequestInfo &info) const; const QMap<QByteArray, QByteArray> headers() const { @@ -38,7 +35,7 @@ public: } private: - QHash<QString, HostRule> m_hostlist; + FilterTree filters; QMap<QByteArray, QByteArray> m_headers; }; diff --git a/src/webengine/urlinterceptor.cpp b/src/webengine/urlinterceptor.cpp index cf9b85f..e6bd523 100644 --- a/src/webengine/urlinterceptor.cpp +++ b/src/webengine/urlinterceptor.cpp @@ -30,10 +30,7 @@ UrlRequestInterceptor::UrlRequestInterceptor(Filter* filter, WebProfile* profile void UrlRequestInterceptor::interceptRequest(QWebEngineUrlRequestInfo &info) { - auto hostlistCheck = m_filter->hostlistRule(info.requestUrl().host()); - if(hostlistCheck) { - info.block(hostlistCheck.value().isBlocking); - } + m_filter->filterRequest(info); // set headers for(auto i = m_filter->headers().constBegin(); i != m_filter->headers().constEnd(); ++i) { diff --git a/test/hostlist/hostlisttest.cpp b/test/hostlist/hostlisttest.cpp index 46f6a85..cd1d39f 100644 --- a/test/hostlist/hostlisttest.cpp +++ b/test/hostlist/hostlisttest.cpp @@ -16,26 +16,26 @@ void HostlistTest::parseList() void HostlistTest::checkRules() { // test block - QVector<const FilterLeaf *> block = tree.match(QString(), "blockeddomain.com"); + QVector<const FilterLeaf *> block = tree.match(QUrl(), QUrl::fromUserInput("blockeddomain.com")); QCOMPARE(block.length(), 1); QCOMPARE(block.constFirst()->action(), FilterLeaf::Block); // test redirect - QVector<const FilterLeaf *> redirectResult = tree.match(QString(), "localhost.localdomain"); + QVector<const FilterLeaf *> redirectResult = tree.match(QUrl(), QUrl::fromUserInput("localhost.localdomain")); QCOMPARE(redirectResult.length(), 1); QCOMPARE(redirectResult.at(0)->action(), FilterLeaf::Redirect); QCOMPARE(redirectResult.at(0)->redirect(), "127.0.0.1"); // two domains on one line - QVector<const FilterLeaf *> blockFirst = tree.match(QString(), "blockeddomain.first"); + QVector<const FilterLeaf *> blockFirst = tree.match(QUrl(), QUrl::fromUserInput("blockeddomain.first")); QCOMPARE(blockFirst.length(), 1); QCOMPARE(blockFirst.constFirst()->action(), FilterLeaf::Block); - QVector<const FilterLeaf *> blockSecond = tree.match(QString(), "blockeddomain.second"); + QVector<const FilterLeaf *> blockSecond = tree.match(QUrl(), QUrl::fromUserInput("blockeddomain.second")); QCOMPARE(blockSecond.length(), 1); QCOMPARE(blockSecond.constFirst()->action(), FilterLeaf::Block); // domain not on list - QVector<const FilterLeaf *> missing = tree.match(QString(), "other.domain"); + QVector<const FilterLeaf *> missing = tree.match(QUrl(), QUrl::fromUserInput("other.domain")); QCOMPARE(missing.length(), 0); } |