aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAqua-sama <aqua@iserlohn-fortress.net>2020-11-22 21:54:01 +0200
committerAqua-sama <aqua@iserlohn-fortress.net>2020-11-23 12:52:38 +0200
commit5e0042a51d18eba0c1ce75889960e86f6e996b62 (patch)
tree3bc8c12034686e894d7ead582422935e1f9f8d80
parentFix test failures (diff)
downloadsmolbote-5e0042a51d18eba0c1ce75889960e86f6e996b62.tar.xz
Hostlist filter plugin can rewrite hostnames
skip clazy warnings in tests
-rw-r--r--plugins/AdblockFilter/test/filterlist.cpp2
-rw-r--r--plugins/AdblockFilter/test/options.cpp2
-rw-r--r--plugins/AdblockFilter/test/rule.cpp2
-rw-r--r--plugins/HostlistFilter/filterlist.cpp54
-rw-r--r--plugins/HostlistFilter/filterlist.h64
-rw-r--r--plugins/HostlistFilter/test/filterlist.cpp16
-rw-r--r--plugins/HostlistFilter/test/plugin.cpp2
-rw-r--r--plugins/HostlistFilter/test/rule.cpp58
8 files changed, 120 insertions, 80 deletions
diff --git a/plugins/AdblockFilter/test/filterlist.cpp b/plugins/AdblockFilter/test/filterlist.cpp
index d3ec513..90860fd 100644
--- a/plugins/AdblockFilter/test/filterlist.cpp
+++ b/plugins/AdblockFilter/test/filterlist.cpp
@@ -3,6 +3,8 @@
#include <QBuffer>
#include <catch2/catch.hpp>
+// clazy:skip
+
using namespace AdblockPlus;
QByteArray sampleList =
diff --git a/plugins/AdblockFilter/test/options.cpp b/plugins/AdblockFilter/test/options.cpp
index 67dc143..19f972c 100644
--- a/plugins/AdblockFilter/test/options.cpp
+++ b/plugins/AdblockFilter/test/options.cpp
@@ -2,6 +2,8 @@
#include "options.h"
#include <catch2/catch.hpp>
+// clazy:skip
+
using namespace AdblockPlus;
SCENARIO("parsing adblock options")
diff --git a/plugins/AdblockFilter/test/rule.cpp b/plugins/AdblockFilter/test/rule.cpp
index 07186b9..a1cd3ed 100644
--- a/plugins/AdblockFilter/test/rule.cpp
+++ b/plugins/AdblockFilter/test/rule.cpp
@@ -2,6 +2,8 @@
#include "rule.h"
#include <catch2/catch.hpp>
+// clazy:skip
+
using namespace AdblockPlus;
SCENARIO("MatcherRule")
diff --git a/plugins/HostlistFilter/filterlist.cpp b/plugins/HostlistFilter/filterlist.cpp
index a0fd414..8faa4ef 100644
--- a/plugins/HostlistFilter/filterlist.cpp
+++ b/plugins/HostlistFilter/filterlist.cpp
@@ -10,49 +10,47 @@
#include <QIODevice>
#include <QTextStream>
-using namespace Hostlist;
-
-#ifdef FUZZER
-extern "C" int LLVMFuzzerTestOneInput(const char *Data, long long Size)
+inline void Hostlist::parseRule(const QString &line, QStringList &blocked, QHash<QString, QString> &redirected)
{
- Filterlist::parseRule(QString::fromLatin1(Data, Size));
- return 0;
-}
-#endif
-
-std::map<Filterlist::DomainHash, Filterlist::Rule> Filterlist::parseRule(const QString &line)
-{
- if(line.isEmpty() || line.at(0) == '#') {
- return {};
- }
+ if(line.isEmpty() || line.at(0) == '#')
+ return;
auto parts = line.trimmed().split(' ');
- if(parts.size() < 2) {
- return {};
- }
+ if(parts.size() < 2)
+ return;
- const auto redirect = (parts[0] == "0.0.0.0") ? QString() : parts[0];
+ if(parts[0] == "0.0.0.0") {
+ parts.pop_front();
+ blocked << parts;
+ return;
+ }
- std::map<DomainHash, Rule> r;
for(int i = 1; i < parts.size(); ++i) {
- r.emplace(qHash(parts[i], 0), Filterlist::Rule{ parts[i], redirect });
+ redirected.insert(parts[i], parts[0]);
}
- return r;
}
-bool Filterlist::load(QIODevice &from)
+#ifdef FUZZER
+extern "C" int LLVMFuzzerTestOneInput(const char *Data, long long Size)
+{
+ QStringList b;
+ QHash<QString, QString> r;
+ Hostlist::parseRule(QString::fromLatin1(Data, static_cast<int>(Size)), b, r);
+ b.clear();
+ r.clear();
+ return 0;
+}
+#endif
+
+bool Hostlist::Filterlist::load(QIODevice &from)
{
if(!from.isReadable() || !from.isTextModeEnabled()) {
return false;
}
while(from.bytesAvailable() > 0) {
- const auto line = from.readLine(512).trimmed();
- auto r = parseRule(line);
- if(!r.empty()) {
- qDebug("merging in %lu rules", r.size());
- rules.merge(r);
- }
+ const auto line = from.readLine(512);
+ parseRule(line, blocked, redirected);
}
return true;
}
diff --git a/plugins/HostlistFilter/filterlist.h b/plugins/HostlistFilter/filterlist.h
index 7301f20..a0fa6f7 100644
--- a/plugins/HostlistFilter/filterlist.h
+++ b/plugins/HostlistFilter/filterlist.h
@@ -6,53 +6,79 @@
* SPDX-License-Identifier: GPL-3.0
*/
-#pragma once
+#ifndef SMOLBOTE_HOSTLIST_FILTERLIST
+#define SMOLBOTE_HOSTLIST_FILTERLIST
-#include <map>
+#include <QHash>
#include <smolbote/filterinterface.hpp>
namespace Hostlist
{
+void parseRule(const QString &line, QStringList &blocked, QHash<QString, QString> &redirected);
+
class Filterlist final : public FilterList
{
public:
- typedef uint DomainHash;
- struct Rule {
- QString domain;
- QString redirect;
- };
-
Filterlist() = default;
+ Filterlist(const Filterlist &) = delete;
+ Filterlist &operator=(const Filterlist &) = delete;
~Filterlist() = default;
- [[nodiscard]] bool findMatch(const QString &domain) const
+ enum Match {
+ NotFound,
+ Block,
+ Redirect
+ };
+
+ [[nodiscard]] Match findMatch(QUrl &url) const
{
- const auto hash = qHash(domain, 0);
- const auto found = rules.find(hash);
- if(found != rules.end()) {
- return true;
+ const auto domain = url.host();
+
+ if(blocked.contains(domain))
+ return Block;
+
+ const auto iter = redirected.find(domain);
+ if(iter != redirected.end()) {
+ url.setHost(iter.value());
+ return Redirect;
}
- return false;
+
+ return NotFound;
}
- int count() const
+
+ [[nodiscard]] auto count() const
{
- return rules.size();
+ return blocked.size() + redirected.size();
}
[[nodiscard]] bool filter(QWebEngineUrlRequestInfo &info) const
{
- return false;
+ auto url = info.requestUrl();
+ switch(findMatch(url)) {
+ case NotFound:
+ return false;
+ case Block:
+ info.block(true);
+ return true;
+ case Redirect:
+ info.block(false);
+ info.redirect(url);
+ return true;
+ }
}
+
[[nodiscard]] bool isUpToDate() const
{
return true;
}
bool load(QIODevice &device);
- [[nodiscard]] static std::map<DomainHash, Rule> parseRule(const QString &line);
private:
- std::map<DomainHash, Rule> rules;
+ QStringList blocked;
+ QHash<QString, QString> redirected;
};
} // namespace Hostlist
+
+#endif // SMOLBOTE_HOSTLIST_FILTERLIST
diff --git a/plugins/HostlistFilter/test/filterlist.cpp b/plugins/HostlistFilter/test/filterlist.cpp
index 4aa532b..b9b3812 100644
--- a/plugins/HostlistFilter/test/filterlist.cpp
+++ b/plugins/HostlistFilter/test/filterlist.cpp
@@ -3,6 +3,8 @@
#include <QFile>
#include <catch2/catch.hpp>
+// clazy:skip
+
using namespace Hostlist;
TEST_CASE("Hostlist")
@@ -20,10 +22,16 @@ TEST_CASE("Hostlist")
REQUIRE(list.count() == 4);
- REQUIRE(list.findMatch("blockeddomain.first"));
- REQUIRE(list.findMatch("blockeddomain.second"));
+ QUrl first("http://blockeddomain.first");
+ REQUIRE(list.findMatch(first) == Filterlist::Block);
+
+ QUrl second("http://blockeddomain.second/path/to/something");
+ REQUIRE(list.findMatch(second) == Filterlist::Block);
- REQUIRE(list.findMatch("localhost.localdomain"));
+ QUrl localhost("http://localhost.localdomain");
+ REQUIRE(list.findMatch(localhost) == Filterlist::Redirect);
+ REQUIRE(localhost.toString() == "http://127.0.0.1");
- REQUIRE(!list.findMatch("other.domain"));
+ QUrl other("http://other.domain");
+ REQUIRE(list.findMatch(other) == Filterlist::NotFound);
}
diff --git a/plugins/HostlistFilter/test/plugin.cpp b/plugins/HostlistFilter/test/plugin.cpp
index fad34f2..026f579 100644
--- a/plugins/HostlistFilter/test/plugin.cpp
+++ b/plugins/HostlistFilter/test/plugin.cpp
@@ -3,6 +3,8 @@
#include <QFile>
#include <catch2/catch.hpp>
+// clazy:skip
+
TEST_CASE("Hostlist")
{
HostlistFilterPlugin plugin;
diff --git a/plugins/HostlistFilter/test/rule.cpp b/plugins/HostlistFilter/test/rule.cpp
index b5ba6e0..5ee9881 100644
--- a/plugins/HostlistFilter/test/rule.cpp
+++ b/plugins/HostlistFilter/test/rule.cpp
@@ -2,56 +2,56 @@
#include "filterlist.h"
#include <catch2/catch.hpp>
+// clazy:skip
+
using namespace Hostlist;
SCENARIO("Hostlist::Rule")
{
GIVEN("an invalid rule")
{
- const auto rule = Filterlist::parseRule("0.0.0.0 ");
- REQUIRE(rule.empty());
+ QStringList b;
+ QHash<QString, QString> r;
+ parseRule("0.0.0.0 ", b, r);
+
+ REQUIRE(b.empty());
+ REQUIRE(r.empty());
}
GIVEN("127.0.0.1 localhost.localdomain")
{
- auto rule = Filterlist::parseRule("127.0.0.1 localhost.localdomain");
+ QStringList b;
+ QHash<QString, QString> r;
+ parseRule("127.0.0.1 localhost.localdomain", b, r);
- REQUIRE(!rule.empty());
- REQUIRE(rule.size() == 1);
+ REQUIRE(b.empty());
+ REQUIRE(r.size() == 1);
- // note: you need to force it to hash a string, rather than the address itself
- const auto index = qHash(QString("localhost.localdomain"), 0);
- REQUIRE(rule[index].domain == "localhost.localdomain");
- REQUIRE(rule[index].redirect == "127.0.0.1");
+ REQUIRE(r.value("localhost.localdomain") == "127.0.0.1");
}
GIVEN("0.0.0.0 blockeddomain.com")
{
- auto rule = Filterlist::parseRule("0.0.0.0 blockeddomain.com");
+ QStringList b;
+ QHash<QString, QString> r;
+ parseRule("0.0.0.0 blockeddomain.com", b, r);
- REQUIRE(!rule.empty());
- REQUIRE(rule.size() == 1);
+ REQUIRE(b.size() == 1);
+ REQUIRE(r.empty());
- const auto index = qHash(QString("blockeddomain.com"), 0);
- REQUIRE(rule[index].domain == "blockeddomain.com");
- REQUIRE(rule[index].redirect.isEmpty());
+ REQUIRE(b.contains("blockeddomain.com"));
;
}
GIVEN("0.0.0.0 blockeddomain.first blockeddomain.second")
{
- auto rule = Filterlist::parseRule("0.0.0.0 blockeddomain.first blockeddomain.second");
-
- REQUIRE(!rule.empty());
- REQUIRE(rule.size() == 2);
- {
- const auto index = qHash(QString("blockeddomain.first"), 0);
- REQUIRE(rule[index].domain == "blockeddomain.first");
- REQUIRE(rule[index].redirect.isEmpty());
- }
- {
- const auto index = qHash(QString("blockeddomain.second"), 0);
- REQUIRE(rule[index].domain == "blockeddomain.second");
- REQUIRE(rule[index].redirect.isEmpty());
- }
+ QStringList b;
+ QHash<QString, QString> r;
+ parseRule("0.0.0.0 blockeddomain.first blockeddomain.second", b, r);
+
+ REQUIRE(b.size() == 2);
+ REQUIRE(r.empty());
+
+ REQUIRE(b.contains("blockeddomain.first"));
+ REQUIRE(b.contains("blockeddomain.second"));
}
}