aboutsummaryrefslogtreecommitdiff
path: root/lib/urlfilter/filtertree.cpp
diff options
context:
space:
mode:
authorAqua-sama <aqua@iserlohn-fortress.net>2018-10-16 17:25:40 +0200
committerAqua-sama <aqua@iserlohn-fortress.net>2018-10-16 17:25:40 +0200
commitc74367d82c1c7bec393548d2e5014c794333822f (patch)
tree909bcde935c84e566db528b1ab25d81778e13036 /lib/urlfilter/filtertree.cpp
parentAdd workaround for QTBUG-62511 (diff)
downloadsmolbote-c74367d82c1c7bec393548d2e5014c794333822f.tar.xz
urlfilter: Add FilterTree class
FilterTree is a class that holds filter rules, sorted by the domain they are to be applied on. The rules are to follow FilterLeaf as interface. - Add a hostlist rule format to FilterTree. - Add a test for hostlist format.
Diffstat (limited to 'lib/urlfilter/filtertree.cpp')
-rw-r--r--lib/urlfilter/filtertree.cpp86
1 files changed, 86 insertions, 0 deletions
diff --git a/lib/urlfilter/filtertree.cpp b/lib/urlfilter/filtertree.cpp
new file mode 100644
index 0000000..8844a76
--- /dev/null
+++ b/lib/urlfilter/filtertree.cpp
@@ -0,0 +1,86 @@
+/*
+ * 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://neueland.iserlohn-fortress.net/gitea/aqua/smolbote
+ *
+ * SPDX-License-Identifier: GPL-3.0
+ */
+
+#include "filtertree.h"
+#include "filterleaf.h"
+#include <QTextStream>
+#include "formats/hostlistrule.h"
+
+bool loadHostlist(QIODevice &from, FilterTree* tree)
+{
+ Q_ASSERT(from.isReadable());
+ QTextStream stream(&from);
+ while(!stream.atEnd()) {
+ const QString line = stream.readLine().trimmed();
+ if(line.isEmpty() || line.startsWith(QLatin1Literal("#")))
+ continue;
+
+ const QStringList &parts = line.split(QLatin1Literal(" "));
+ if(parts.length() < 2) {
+#ifdef QT_DEBUG
+ qDebug("Cannot parse: %s", qUtf8Printable(line));
+#endif
+ return false;
+ }
+
+ for(int i = 1; i < parts.length(); ++i) {
+ // HostlistRule(domain, redirect)
+ auto *rule = new HostlistRule(parts.at(i), parts.constFirst());
+ // addRule(rule, enable_on_domain)
+ const bool added = tree->addRule(rule, QString());
+ if(!added)
+ return false;
+ }
+
+ }
+ return true;
+}
+
+const QStringList FilterTree::branches() const
+{
+ QStringList branches;
+ for(auto &branch : m_branches) {
+ branches.append(QString::fromStdString(branch.domain));
+ }
+ return branches;
+}
+
+QVector<const FilterLeaf *> FilterTree::match(const QString& domain, const QString& requestUrl) const
+{
+ QVector<const FilterLeaf *> leaves;
+ for(const auto &branch : m_branches) {
+ if(branch.domain == domain.toStdString()) {
+
+ for(const auto leaf : branch.leaves) {
+ if(leaf->match(requestUrl)) {
+ leaves.append(leaf);
+ }
+ }
+
+ }
+ }
+ return leaves;
+}
+
+bool FilterTree::addRule(FilterLeaf *rule, const QString& domain)
+{
+ for(auto &branch : m_branches) {
+ if(branch.domain == domain.toStdString()) {
+ branch.leaves.emplace_back(rule);
+ return true;
+ }
+ }
+
+ // no branch was found
+ Branch branch;
+ branch.domain = domain.toStdString();
+ // TODO: for some reason, can't add rule here
+ //branch.leaves.emplace_back(rule);
+ m_branches.emplace_back(std::move(branch));
+ return this->addRule(rule, domain);
+}