File indexing completed on 2024-05-12 04:57:50

0001 /* ============================================================
0002 * Falkon - Qt web browser
0003 * Copyright (C) 2013-2017 David Rosca <nowrep@gmail.com>
0004 *
0005 * This program is free software: you can redistribute it and/or modify
0006 * it under the terms of the GNU General Public License as published by
0007 * the Free Software Foundation, either version 3 of the License, or
0008 * (at your option) any later version.
0009 *
0010 * This program is distributed in the hope that it will be useful,
0011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
0012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0013 * GNU General Public License for more details.
0014 *
0015 * You should have received a copy of the GNU General Public License
0016 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
0017 * ============================================================ */
0018 #include "adblocksearchtree.h"
0019 #include "adblockrule.h"
0020 
0021 #include <QWebEngineUrlRequestInfo>
0022 
0023 AdBlockSearchTree::AdBlockSearchTree()
0024     : m_root(new Node)
0025 {
0026 }
0027 
0028 AdBlockSearchTree::~AdBlockSearchTree()
0029 {
0030     deleteNode(m_root);
0031 }
0032 
0033 void AdBlockSearchTree::clear()
0034 {
0035     deleteNode(m_root);
0036     m_root = new Node;
0037 }
0038 
0039 bool AdBlockSearchTree::add(const AdBlockRule* rule)
0040 {
0041     if (rule->m_type != AdBlockRule::StringContainsMatchRule) {
0042         return false;
0043     }
0044 
0045     const QString filter = rule->m_matchString;
0046     int len = filter.size();
0047 
0048     if (len <= 0) {
0049         qDebug() << "AdBlockSearchTree: Inserting rule with filter len <= 0!" << rule->filter();
0050         return false;
0051     }
0052 
0053     Node* node = m_root;
0054 
0055     for (int i = 0; i < len; ++i) {
0056         const QChar c = filter.at(i);
0057         Node *next = node->children.value(c);
0058         if (!next) {
0059             next = new Node;
0060             next->c = c;
0061             node->children[c] = next;
0062         }
0063         node = next;
0064     }
0065 
0066     node->rule = rule;
0067 
0068     return true;
0069 }
0070 
0071 const AdBlockRule* AdBlockSearchTree::find(const QWebEngineUrlRequestInfo &request, const QString &domain, const QString &urlString) const
0072 {
0073     int len = urlString.size();
0074 
0075     if (len <= 0) {
0076         return nullptr;
0077     }
0078 
0079     const QChar* string = urlString.constData();
0080 
0081     for (int i = 0; i < len; ++i) {
0082         const AdBlockRule* rule = prefixSearch(request, domain, urlString, string++, len - i);
0083         if (rule) {
0084             return rule;
0085         }
0086     }
0087 
0088     return nullptr;
0089 }
0090 
0091 const AdBlockRule* AdBlockSearchTree::prefixSearch(const QWebEngineUrlRequestInfo &request, const QString &domain, const QString &urlString, const QChar* string, int len) const
0092 {
0093     if (len <= 0) {
0094         return nullptr;
0095     }
0096 
0097     QChar c = string[0];
0098 
0099     Node* node = m_root->children.value(c);
0100     if (!node) {
0101         return nullptr;
0102     }
0103 
0104     for (int i = 1; i < len; ++i) {
0105         const QChar c = (++string)[0];
0106 
0107         if (node->rule && node->rule->networkMatch(request, domain, urlString)) {
0108             return node->rule;
0109         }
0110 
0111         node = node->children.value(c);
0112         if (!node) {
0113             return nullptr;
0114         }
0115     }
0116 
0117     if (node->rule && node->rule->networkMatch(request, domain, urlString)) {
0118         return node->rule;
0119     }
0120 
0121     return nullptr;
0122 }
0123 
0124 void AdBlockSearchTree::deleteNode(AdBlockSearchTree::Node* node)
0125 {
0126     if (!node) {
0127         return;
0128     }
0129 
0130     QHashIterator<QChar, Node*> i(node->children);
0131     while (i.hasNext()) {
0132         i.next();
0133         deleteNode(i.value());
0134     }
0135 
0136     delete node;
0137 }