aboutsummaryrefslogtreecommitdiff
path: root/subprojects
diff options
context:
space:
mode:
authorAqua-sama <aqua@iserlohn-fortress.net>2020-04-20 13:29:06 +0300
committerAqua-sama <aqua@iserlohn-fortress.net>2020-04-21 20:14:58 +0300
commit8d484d153dd054be89be51b7b4e9815450c0065a (patch)
tree44a4c1045969909197312003957611f90d9be582 /subprojects
parentAdd plugin loading code to smolblok (diff)
downloadsmolbote-8d484d153dd054be89be51b7b4e9815450c0065a.tar.xz
Move staging/hostlist to subprojects/plugin_hostlist
Diffstat (limited to 'subprojects')
-rw-r--r--subprojects/plugin_hostlist/filterlist.cpp49
-rw-r--r--subprojects/plugin_hostlist/filterlist.hpp58
-rw-r--r--subprojects/plugin_hostlist/meson.build43
-rw-r--r--subprojects/plugin_hostlist/meson_options.txt1
-rw-r--r--subprojects/plugin_hostlist/plugin/plugin.cpp32
-rw-r--r--subprojects/plugin_hostlist/plugin/plugin.h28
-rw-r--r--subprojects/plugin_hostlist/plugin/smolblokHostlistPlugin.json4
-rw-r--r--subprojects/plugin_hostlist/test/filterlist.cpp29
-rw-r--r--subprojects/plugin_hostlist/test/hostlist.txt6
-rw-r--r--subprojects/plugin_hostlist/test/rule.cpp57
10 files changed, 307 insertions, 0 deletions
diff --git a/subprojects/plugin_hostlist/filterlist.cpp b/subprojects/plugin_hostlist/filterlist.cpp
new file mode 100644
index 0000000..42be349
--- /dev/null
+++ b/subprojects/plugin_hostlist/filterlist.cpp
@@ -0,0 +1,49 @@
+/*
+ * 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://library.iserlohn-fortress.net/aqua/smolbote.git
+ *
+ * SPDX-License-Identifier: GPL-3.0
+ */
+
+#include "filterlist.hpp"
+#include <QIODevice>
+#include <QTextStream>
+
+using namespace Hostlist;
+
+std::map<Filterlist::DomainHash, Filterlist::Rule> Filterlist::parseRule(const QString &line)
+{
+ auto parts = line.trimmed().split(' ');
+ if(parts.size() < 2) {
+ return {};
+ }
+
+ const auto redirect = (parts[0] == "0.0.0.0") ? QString() : parts[0];
+
+ std::map<DomainHash, Rule> r;
+ for(int i = 1; i < parts.size(); ++i) {
+ r.emplace(qHash(parts[i], 0), Filterlist::Rule{ parts[i], redirect });
+ }
+ return r;
+}
+
+bool Filterlist::load(QIODevice &from)
+{
+ if(!from.isReadable() || !from.isTextModeEnabled()) {
+ return false;
+ }
+
+ while(from.bytesAvailable() > 0) {
+ const auto line = from.readLine(512).trimmed();
+ if(!line.isEmpty() && line.at(0) != '#') {
+ auto r = parseRule(line);
+ if(!r.empty()) {
+ qDebug("merging in %lu rules", r.size());
+ rules.merge(r);
+ }
+ }
+ }
+ return true;
+}
+
diff --git a/subprojects/plugin_hostlist/filterlist.hpp b/subprojects/plugin_hostlist/filterlist.hpp
new file mode 100644
index 0000000..7301f20
--- /dev/null
+++ b/subprojects/plugin_hostlist/filterlist.hpp
@@ -0,0 +1,58 @@
+/*
+ * 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://library.iserlohn-fortress.net/aqua/smolbote.git
+ *
+ * SPDX-License-Identifier: GPL-3.0
+ */
+
+#pragma once
+
+#include <map>
+#include <smolbote/filterinterface.hpp>
+
+namespace Hostlist
+{
+
+class Filterlist final : public FilterList
+{
+public:
+ typedef uint DomainHash;
+ struct Rule {
+ QString domain;
+ QString redirect;
+ };
+
+ Filterlist() = default;
+ ~Filterlist() = default;
+
+ [[nodiscard]] bool findMatch(const QString &domain) const
+ {
+ const auto hash = qHash(domain, 0);
+ const auto found = rules.find(hash);
+ if(found != rules.end()) {
+ return true;
+ }
+ return false;
+ }
+ int count() const
+ {
+ return rules.size();
+ }
+
+ [[nodiscard]] bool filter(QWebEngineUrlRequestInfo &info) const
+ {
+ return false;
+ }
+ [[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;
+};
+} // namespace Hostlist
diff --git a/subprojects/plugin_hostlist/meson.build b/subprojects/plugin_hostlist/meson.build
new file mode 100644
index 0000000..d8286d1
--- /dev/null
+++ b/subprojects/plugin_hostlist/meson.build
@@ -0,0 +1,43 @@
+project('hostlistfilter', 'cpp')
+
+mod_qt5 = import('qt5')
+dep_qt5 = dependency('qt5',
+ modules: [ 'Core', 'Network', 'WebEngineWidgets' ],
+ include_type: 'system'
+)
+dep_catch = dependency('catch2', required: true, fallback: ['catch2', 'catch2_dep'] )
+
+smolbote_interface = include_directories(get_option('interface'))
+message(get_option('interface'))
+
+lib_hostlistfilter = static_library('hostlistfilter',
+ [ 'filterlist.cpp' ],
+ include_directories: smolbote_interface,
+ dependencies: [dep_qt5]
+)
+
+dep_hostlistfilter = declare_dependency(
+ include_directories: [ '.', smolbote_interface ],
+ link_with: lib_hostlistfilter
+)
+
+# plugin
+plugin = shared_library('smolblokHostlistPlugin',
+ [ 'plugin/plugin.cpp',
+ mod_qt5.preprocess(include_directories: smolbote_interface, moc_headers: 'plugin/plugin.h', dependencies: dep_qt5) ],
+ include_directories: smolbote_interface,
+ dependencies: [ dep_hostlistfilter, dep_qt5 ],
+ install: true,
+ install_dir: get_option('libdir')/'smolbote/plugins'
+)
+
+# tests
+test('rule parsing', executable('rule',
+ sources: 'test/rule.cpp',
+ dependencies: [dep_qt5, dep_catch, dep_hostlistfilter]))
+
+test('filterlist', executable('filterlist',
+ sources: 'test/filterlist.cpp',
+ dependencies: [dep_qt5, dep_catch, dep_hostlistfilter]),
+ env: 'HOSTLIST_TXT='+meson.current_source_dir()/'test/hostlist.txt'
+)
diff --git a/subprojects/plugin_hostlist/meson_options.txt b/subprojects/plugin_hostlist/meson_options.txt
new file mode 100644
index 0000000..e4aed19
--- /dev/null
+++ b/subprojects/plugin_hostlist/meson_options.txt
@@ -0,0 +1 @@
+option('interface', description: 'Interfaces path', type: 'string', value: '/usr/local/include')
diff --git a/subprojects/plugin_hostlist/plugin/plugin.cpp b/subprojects/plugin_hostlist/plugin/plugin.cpp
new file mode 100644
index 0000000..2399510
--- /dev/null
+++ b/subprojects/plugin_hostlist/plugin/plugin.cpp
@@ -0,0 +1,32 @@
+/*
+ * 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://library.iserlohn-fortress.net/aqua/smolbote.git
+ *
+ * SPDX-License-Identifier: GPL-3.0
+ */
+
+#include "plugin.h"
+#include "filterlist.hpp"
+
+FilterList* HostlistFilterPlugin::load(QIODevice &from) const
+{
+ if(!from.isOpen())
+ return nullptr;
+
+ auto *list = new Hostlist::Filterlist;
+ return list;
+}
+
+bool HostlistFilterPlugin::parse(FilterList *list, QIODevice &from) const
+{
+ if(list == nullptr || !from.isOpen()) {
+ return false;
+ }
+ auto *l = dynamic_cast<Hostlist::Filterlist*>(list);
+ if(l == nullptr) {
+ return false;
+ }
+ return l->load(from);
+}
+
diff --git a/subprojects/plugin_hostlist/plugin/plugin.h b/subprojects/plugin_hostlist/plugin/plugin.h
new file mode 100644
index 0000000..53b5d36
--- /dev/null
+++ b/subprojects/plugin_hostlist/plugin/plugin.h
@@ -0,0 +1,28 @@
+/*
+ * 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://library.iserlohn-fortress.net/aqua/smolbote.git
+ *
+ * SPDX-License-Identifier: GPL-3.0
+ */
+
+#ifndef SMOLBLOK_FILTER_PLUGIN_H
+#define SMOLBLOK_FILTER_PLUGIN_H
+
+#include <smolbote/filterinterface.hpp>
+
+class HostlistFilterPlugin : public QObject, public FilterPlugin
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID FilterPluginIid FILE "smolblokHostlistPlugin.json")
+ Q_INTERFACES(FilterPlugin)
+
+public:
+ ~HostlistFilterPlugin() = default;
+
+ FilterList *load(QIODevice &from) const override;
+ bool parse(FilterList *list, QIODevice &from) const override;
+};
+
+#endif // SMOLBLOK_FILTER_PLUGIN_H
+
diff --git a/subprojects/plugin_hostlist/plugin/smolblokHostlistPlugin.json b/subprojects/plugin_hostlist/plugin/smolblokHostlistPlugin.json
new file mode 100644
index 0000000..aa53cdd
--- /dev/null
+++ b/subprojects/plugin_hostlist/plugin/smolblokHostlistPlugin.json
@@ -0,0 +1,4 @@
+{
+ "name": "smolblok Hostlist filter plugin",
+ "author": "Aqua <aqua@iserlohn-fortress.net>"
+}
diff --git a/subprojects/plugin_hostlist/test/filterlist.cpp b/subprojects/plugin_hostlist/test/filterlist.cpp
new file mode 100644
index 0000000..fb71068
--- /dev/null
+++ b/subprojects/plugin_hostlist/test/filterlist.cpp
@@ -0,0 +1,29 @@
+#define CATCH_CONFIG_MAIN
+#include "filterlist.hpp"
+#include <QFile>
+#include <catch2/catch.hpp>
+
+using namespace Hostlist;
+
+TEST_CASE("Hostlist")
+{
+ Filterlist list;
+
+ const QString filename(qgetenv("HOSTLIST_TXT"));
+ REQUIRE(!filename.isEmpty());
+
+ QFile f(filename);
+ REQUIRE(f.open(QIODevice::ReadOnly | QIODevice::Text));
+
+ REQUIRE(list.load(f));
+ f.close();
+
+ REQUIRE(list.count() == 4);
+
+ REQUIRE(list.findMatch("blockeddomain.first"));
+ REQUIRE(list.findMatch("blockeddomain.second"));
+
+ REQUIRE(list.findMatch("localhost.localdomain"));
+
+ REQUIRE(!list.findMatch("other.domain"));
+}
diff --git a/subprojects/plugin_hostlist/test/hostlist.txt b/subprojects/plugin_hostlist/test/hostlist.txt
new file mode 100644
index 0000000..a0b4e5c
--- /dev/null
+++ b/subprojects/plugin_hostlist/test/hostlist.txt
@@ -0,0 +1,6 @@
+# This is a comment, and after it comes a blank line
+
+127.0.0.1 localhost.localdomain
+
+0.0.0.0 blockeddomain.com
+0.0.0.0 blockeddomain.first blockeddomain.second
diff --git a/subprojects/plugin_hostlist/test/rule.cpp b/subprojects/plugin_hostlist/test/rule.cpp
new file mode 100644
index 0000000..6b1ea70
--- /dev/null
+++ b/subprojects/plugin_hostlist/test/rule.cpp
@@ -0,0 +1,57 @@
+#define CATCH_CONFIG_MAIN
+#include "filterlist.hpp"
+#include <catch2/catch.hpp>
+
+using namespace Hostlist;
+
+SCENARIO("Hostlist::Rule")
+{
+ GIVEN("an invalid rule")
+ {
+ const auto rule = Filterlist::parseRule("0.0.0.0 ");
+ REQUIRE(rule.empty());
+ }
+ GIVEN("127.0.0.1 localhost.localdomain")
+ {
+ auto rule = Filterlist::parseRule("127.0.0.1 localhost.localdomain");
+
+ REQUIRE(!rule.empty());
+ REQUIRE(rule.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");
+ }
+
+ GIVEN("0.0.0.0 blockeddomain.com")
+ {
+ auto rule = Filterlist::parseRule("0.0.0.0 blockeddomain.com");
+
+ REQUIRE(!rule.empty());
+ REQUIRE(rule.size() == 1);
+
+ const auto index = qHash(QString("blockeddomain.com"), 0);
+ REQUIRE(rule[index].domain == "blockeddomain.com");
+ REQUIRE(rule[index].redirect.isEmpty());
+ ;
+ }
+
+ 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());
+ }
+ }
+}