diff options
Diffstat (limited to 'lib/smolblok')
-rw-r--r-- | lib/smolblok/README.md | 8 | ||||
-rw-r--r-- | lib/smolblok/filtermanager.hpp | 41 | ||||
-rw-r--r-- | lib/smolblok/meson.build | 15 | ||||
-rw-r--r-- | lib/smolblok/smolblok.cpp | 40 | ||||
-rw-r--r-- | lib/smolblok/smolblok.hpp | 80 | ||||
-rw-r--r-- | lib/smolblok/test/loader.cpp | 25 | ||||
-rw-r--r-- | lib/smolblok/test/main.cpp | 22 | ||||
-rw-r--r-- | lib/smolblok/test/sample-filters.txt | 10 |
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 + |