/* * 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 "formats/hostlistrule.h" #include 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; } FilterTree::~FilterTree() { for(auto &branch : m_branches) { qDeleteAll(branch.leaves); branch.leaves.clear(); } } const QStringList FilterTree::branches() const { QStringList branches; for(auto &branch : m_branches) { branches.append(branch.domain.host()); } return branches; } QVector FilterTree::match(const QUrl &domain, const QUrl &requestUrl) const { QVector leaves; for(const auto &branch : m_branches) { if(branch.domain.matches(domain)) { for(const auto leaf : branch.leaves) { if(leaf->match(requestUrl)) { leaves.append(leaf); } } } } return leaves; } bool FilterTree::addRule(FilterLeaf *rule, const QString &domain) { branchLock.lock(); this->branch(domain).leaves.emplace_back(rule); branchLock.unlock(); return true; } FilterTree::Branch & FilterTree::branch(const QString& domain) { for(auto &branch : m_branches) { if(branch.domain.matches(QUrl(domain))) return branch; } // no branch was found Branch branch(domain); return m_branches.emplace_back(std::move(branch)); }