/******************************************************************************* ** ** smolbote: yet another qute browser ** Copyright (C) 2017 Xian Nox ** ** This program is free software: you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation, either version 3 of the License, or ** (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program. If not, see . ** ******************************************************************************/ #include "filtercollection.h" #include "ui_subscriptionform.h" #include "browser.h" #include #include #include #include #include #include #include #include #include "filtertree.h" #include "filter.h" FilterCollection::FilterCollection(const QString path, QWidget *parent) : QWidget(parent), ui(new Ui::SubscriptionForm) { ui->setupUi(this); ui->homepage->setText(path); qDebug("Adding subscription [%s]", qUtf8Printable(path)); m_filters = new FilterTree(this); ui->treeView->setModel(m_filters); QFile filterFile(path); if(!filterFile.open(QIODevice::ReadOnly)) { qWarning("Could not open filter!"); return; } QJsonDocument filters(QJsonDocument::fromJson(filterFile.readAll())); qDebug("Added %i rules", load(filters.object())); } FilterCollection::~FilterCollection() { delete ui; } QString FilterCollection::name() const { return ui->title->text(); } /** * Check if a URL request should be blocked or not * @param info * @return true if it should be blocked; false otherwise */ FilterCollection::MatchResult FilterCollection::match(QWebEngineUrlRequestInfo &info) { MatchResult result; for(Filter *rule : m_filters->filters(info.firstPartyUrl().toString())) { if(rule->isValid()) { result.match = rule->hasMatch(info); if(result.match) { result.block = rule->shouldBlock(info); } else { result.block = false; } result.pattern = rule->domain() + " | " + rule->request(); return result; } } // request matches neither whitelist nor blacklist result.match = false; result.block = false; return result; } /** * Load rules from JSON object * @param json */ int FilterCollection::load(const QJsonObject &json) { int number = 0; ui->title->setText(json["name"].toString()); ui->homepage->setText(json["url"].toString()); for(QJsonValue v : json["rules"].toArray()) { ++number; QJsonObject obj = v.toObject(); Filter::ResourceRules r; r.allowed = parseJsonRules(obj["allowTypes"]); r.blocked = parseJsonRules(obj["blockTypes"]); m_filters->addFilter(obj["firstPartyUrl"].toString(), obj["requestUrl"].toString(), r, obj["shouldBlock"].toBool()); } return number; } Filter::Resources FilterCollection::parseJsonRules(const QJsonValue &obj) { Filter::Resources res; for(QJsonValue v : obj.toArray()) { QString t = v.toString(); if(t == "MainFrame") { res.setFlag(Filter::ResourceType::MainFrame); } else if(t == "SubFrame") { res.setFlag(Filter::ResourceType::SubFrame); } else if(t == "Stylesheet") { res.setFlag(Filter::ResourceType::Stylesheet); } else if(t == "Script") { res.setFlag(Filter::ResourceType::Script); } else if(t == "Image") { res.setFlag(Filter::ResourceType::Image); } else if(t == "FontResource") { res.setFlag(Filter::ResourceType::Font); } else if(t == "SubResource") { res.setFlag(Filter::ResourceType::SubResource); } else if(t == "Object") { res.setFlag(Filter::ResourceType::Object); } else if(t == "Media") { res.setFlag(Filter::ResourceType::Media); } else if(t == "Worker") { res.setFlag(Filter::ResourceType::Worker); } else if(t == "SharedWorker") { res.setFlag(Filter::ResourceType::SharedWorker); } else if(t == "Prefetch") { res.setFlag(Filter::ResourceType::Prefetch); } else if(t == "Favicon") { res.setFlag(Filter::ResourceType::Favicon); } else if(t == "Xhr") { res.setFlag(Filter::ResourceType::Xhr); } else if(t == "Ping") { res.setFlag(Filter::ResourceType::Ping); } else if(t == "ServiceWorker") { res.setFlag(Filter::ResourceType::ServiceWorker); } else if(t == "CspWorker") { res.setFlag(Filter::ResourceType::CspReport); } else if(t == "PluginResource") { res.setFlag(Filter::ResourceType::PluginResource); } } return res; }