aboutsummaryrefslogtreecommitdiff
path: root/lib/smolblok
diff options
context:
space:
mode:
Diffstat (limited to 'lib/smolblok')
-rw-r--r--lib/smolblok/README.md8
-rw-r--r--lib/smolblok/filtermanager.hpp41
-rw-r--r--lib/smolblok/meson.build15
-rw-r--r--lib/smolblok/smolblok.cpp40
-rw-r--r--lib/smolblok/smolblok.hpp80
-rw-r--r--lib/smolblok/test/loader.cpp25
-rw-r--r--lib/smolblok/test/main.cpp22
-rw-r--r--lib/smolblok/test/sample-filters.txt10
8 files changed, 241 insertions, 0 deletions
diff --git a/lib/smolblok/README.md b/lib/smolblok/README.md
new file mode 100644
index 0000000..1793009
--- /dev/null
+++ b/lib/smolblok/README.md
@@ -0,0 +1,8 @@
+## smolblok
+
+### What is this
+This is a C++ library for URL filtering for Qt applications using QtWebEngine.
+
+### Supported formats
+- AdblockPlus without element hiding rules
+
diff --git a/lib/smolblok/filtermanager.hpp b/lib/smolblok/filtermanager.hpp
new file mode 100644
index 0000000..6ee4d3f
--- /dev/null
+++ b/lib/smolblok/filtermanager.hpp
@@ -0,0 +1,41 @@
+/*
+ * 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 <QWebEngineUrlRequestInterceptor>
+#include <smolbote/filterinterface.hpp>
+
+class FilterManager : public QWebEngineUrlRequestInterceptor
+{
+public:
+ FilterManager(QObject *parent = nullptr)
+ : QWebEngineUrlRequestInterceptor(parent)
+ {
+ }
+ ~FilterManager()
+ {
+ qDeleteAll(filters);
+ }
+
+ void addFilterList(FilterList *list) {
+ filters.append(list);
+ }
+
+ void interceptRequest(QWebEngineUrlRequestInfo &info) override
+ {
+ for(const auto *filter : qAsConst(filters)) {
+ if(filter->filter(info)) {
+ return;
+ }
+ }
+ }
+
+private:
+ QList<FilterList *> filters;
+};
diff --git a/lib/smolblok/meson.build b/lib/smolblok/meson.build
new file mode 100644
index 0000000..ea9e715
--- /dev/null
+++ b/lib/smolblok/meson.build
@@ -0,0 +1,15 @@
+dep_smolblok = declare_dependency(
+ include_directories: [ '.', smolbote_interfaces ],
+ link_with: library('smolblok', [ 'smolblok.cpp' ], include_directories: smolbote_interfaces, dependencies: dep_qt5)
+)
+
+poi_sourceset.add(dep_smolblok)
+
+smolblok_load = executable('smolblok-load',
+ dependencies: [ dep_qt5, dep_spdlog, dep_smolblok ],
+ sources: [ 'test/loader.cpp' ]
+)
+
+test('load', smolblok_load, suite: 'smolblok', should_fail: true)
+test('load', smolblok_load, suite: 'smolblok', args: files('meson.build'), should_fail: true)
+
diff --git a/lib/smolblok/smolblok.cpp b/lib/smolblok/smolblok.cpp
new file mode 100644
index 0000000..465c348
--- /dev/null
+++ b/lib/smolblok/smolblok.cpp
@@ -0,0 +1,40 @@
+/*
+ * 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 "smolblok.hpp"
+#include <QFile>
+#include <QSettings>
+
+bool smolblok::addSubscriptions(const QString &filename)
+{
+ if(filename.isEmpty()) {
+ return false;
+ }
+
+ QSettings listconf(filename, QSettings::IniFormat);
+
+ for(auto &group : listconf.childGroups()) {
+ listconf.beginGroup(group);
+ const auto *loader = m_formats.value(listconf.value("Format").toString()).instance;
+ if(loader != nullptr) {
+ QFile f(listconf.value("File").toString());
+ if(!f.exists()) {
+ continue;
+ }
+
+ auto *list = loader->load(f);
+ f.seek(0);
+ if(loader->parse(list, f)) {
+ m_subscriptions.addFilterList(list);
+ }
+ }
+ listconf.endGroup();
+ }
+ return false;
+}
+
diff --git a/lib/smolblok/smolblok.hpp b/lib/smolblok/smolblok.hpp
new file mode 100644
index 0000000..dc79232
--- /dev/null
+++ b/lib/smolblok/smolblok.hpp
@@ -0,0 +1,80 @@
+/*
+ * 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 SMOLBOTE_SMOLBLOK_HPP
+#define SMOLBOTE_SMOLBLOK_HPP
+
+#include "filtermanager.hpp"
+#include "smolbote/filterinterface.hpp"
+#include <QPluginLoader>
+#include <QWebEngineUrlRequestInterceptor>
+
+class smolblok
+{
+public:
+ smolblok() = default;
+ ~smolblok()
+ {
+ for(auto &plugin : m_formats) {
+ delete plugin.loader;
+ }
+ }
+
+ auto registerFormatPlugin(const QString &format, const QString &filename)
+ {
+ struct {
+ bool loaded = false;
+ QString error;
+ } ret;
+
+ if(format.isEmpty() || filename.isEmpty()) {
+ ret.error = "Format or filename is empty";
+ return ret;
+ }
+
+ auto *plugin = new QPluginLoader(filename);
+ if(!plugin->load()) {
+ ret.error = plugin->errorString();
+ delete plugin;
+ return ret;
+ }
+
+ auto *instance = qobject_cast<FilterPlugin *>(plugin->instance());
+ if(instance == nullptr) {
+ ret.error = "Unable to cast";
+ delete plugin;
+ return ret;
+ }
+
+ m_formats[format] = PluginInfo{ plugin, instance };
+ ret.loaded = true;
+ return ret;
+ }
+
+ auto formats() const
+ {
+ return m_formats.keys();
+ }
+
+ bool addSubscriptions(const QString &filename);
+ QWebEngineUrlRequestInterceptor *interceptor()
+ {
+ return &m_subscriptions;
+ }
+
+private:
+ struct PluginInfo {
+ QPluginLoader *loader = nullptr;
+ FilterPlugin *instance = nullptr;
+ };
+
+ QHash<QString, PluginInfo> m_formats;
+ FilterManager m_subscriptions;
+};
+
+#endif // SMOLBOTE_SMOLBLOK_HPP
diff --git a/lib/smolblok/test/loader.cpp b/lib/smolblok/test/loader.cpp
new file mode 100644
index 0000000..9e27a26
--- /dev/null
+++ b/lib/smolblok/test/loader.cpp
@@ -0,0 +1,25 @@
+#include "smolblok.hpp"
+#include <spdlog/spdlog.h>
+
+int main(int argc, char** argv)
+{
+ if(argc != 2) {
+ spdlog::error("usage: {} path/to/plugin.so", argv[0]);
+ return -1;
+ }
+
+ smolblok filter;
+ {
+ const auto r = filter.registerFormatPlugin("unused", argv[1]);
+ if(r.loaded) {
+ spdlog::info("Loaded plugin {}", argv[1]);
+ } else {
+ spdlog::error("Failed loading plugin {}", argv[1]);
+ spdlog::error(qUtf8Printable(r.error));
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
diff --git a/lib/smolblok/test/main.cpp b/lib/smolblok/test/main.cpp
new file mode 100644
index 0000000..5624ee9
--- /dev/null
+++ b/lib/smolblok/test/main.cpp
@@ -0,0 +1,22 @@
+#define CATCH_CONFIG_MAIN
+
+#include "smolblok.hpp"
+#include <catch2/catch.hpp>
+
+SCENARIO("smolblok")
+{
+ smolblok s;
+
+ GIVEN("invalid plugins")
+ {
+ REQUIRE(!s.registerFormatPlugin("", ""));
+ REQUIRE(!s.registerFormatPlugin("Format", "missing.dll"));
+ }
+
+ GIVEN("invalid subscriptions")
+ {
+ REQUIRE(!s.addSubscriptions(""));
+ REQUIRE(!s.addSubscriptions("missing.txt"));
+ }
+}
+
diff --git a/lib/smolblok/test/sample-filters.txt b/lib/smolblok/test/sample-filters.txt
new file mode 100644
index 0000000..59e0e7b
--- /dev/null
+++ b/lib/smolblok/test/sample-filters.txt
@@ -0,0 +1,10 @@
+[easylist-noelemhide]
+Format = AdblockPlus
+File = easylist_noelemhide.txt
+Href = https://easylist-downloads.adblockplus.org/easylist_noelemhide.txt
+
+[StevenBlack]
+Format = Hostlist
+File = stevenblack.txt
+Href = https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts
+