From 7f6c9b22d1016aa0dba709495fabf41397676039 Mon Sep 17 00:00:00 2001 From: Aqua-sama Date: Tue, 28 Feb 2017 10:18:08 +0100 Subject: Blocker rewrites Some code commenting Moved Blocker files for src/blocker Keyboard shortcut for Blocker dialog --- src/blocker/blockermanager.cpp | 45 ++++++++ src/blocker/blockermanager.h | 42 ++++++++ src/blocker/blockerrule.cpp | 209 ++++++++++++++++++++++++++++++++++++ src/blocker/blockerrule.h | 79 ++++++++++++++ src/blocker/blockersubscription.cpp | 138 ++++++++++++++++++++++++ src/blocker/blockersubscription.h | 55 ++++++++++ src/blocker/regexp.cpp | 70 ++++++++++++ src/blocker/regexp.h | 38 +++++++ src/blocker/subscriptiondialog.ui | 67 ++++++++++++ src/blocker/subscriptionform.ui | 149 +++++++++++++++++++++++++ 10 files changed, 892 insertions(+) create mode 100644 src/blocker/blockermanager.cpp create mode 100644 src/blocker/blockermanager.h create mode 100644 src/blocker/blockerrule.cpp create mode 100644 src/blocker/blockerrule.h create mode 100644 src/blocker/blockersubscription.cpp create mode 100644 src/blocker/blockersubscription.h create mode 100644 src/blocker/regexp.cpp create mode 100644 src/blocker/regexp.h create mode 100644 src/blocker/subscriptiondialog.ui create mode 100644 src/blocker/subscriptionform.ui (limited to 'src/blocker') diff --git a/src/blocker/blockermanager.cpp b/src/blocker/blockermanager.cpp new file mode 100644 index 0000000..3dd516c --- /dev/null +++ b/src/blocker/blockermanager.cpp @@ -0,0 +1,45 @@ +/** LICENSE ******************************************************************** + ** + ** 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 "blockermanager.h" +#include "ui_subscriptiondialog.h" + +#include "browser.h" +#include +#include + +#include "blocker/blockersubscription.h" + +BlockerManager::BlockerManager(QWidget *parent) : + QDialog(parent), + ui(new Ui::UrlInterceptorDialog) +{ + ui->setupUi(this); + + for(QString listUrl : sSettings->value("blocker.subscriptions").toStringList()) { + BlockerSubscription *sub = new BlockerSubscription(listUrl, this); + ui->tabWidget->addTab(sub, sub->name()); + } +} + +BlockerManager::~BlockerManager() +{ + delete ui; +} diff --git a/src/blocker/blockermanager.h b/src/blocker/blockermanager.h new file mode 100644 index 0000000..eb5e04e --- /dev/null +++ b/src/blocker/blockermanager.h @@ -0,0 +1,42 @@ +/** LICENSE ******************************************************************** + ** + ** 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 . + ** + ******************************************************************************/ + +#ifndef URLINTERCEPTORDIALOG_H +#define URLINTERCEPTORDIALOG_H + +#include + +namespace Ui { +class UrlInterceptorDialog; +} + +class BlockerManager : public QDialog +{ + Q_OBJECT + +public: + explicit BlockerManager(QWidget *parent = 0); + ~BlockerManager(); + +private: + Ui::UrlInterceptorDialog *ui; +}; + +#endif // URLINTERCEPTORDIALOG_H diff --git a/src/blocker/blockerrule.cpp b/src/blocker/blockerrule.cpp new file mode 100644 index 0000000..1c118e2 --- /dev/null +++ b/src/blocker/blockerrule.cpp @@ -0,0 +1,209 @@ +/** LICENSE ******************************************************************** + ** + ** 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 "blockerrule.h" + +/* AdBlock filter reference + * https://adblockplus.org/en/filters + * https://adblockplus.org/en/filter-cheatsheet + */ + +BlockerRule::BlockerRule(QString rule, QObject *parent) : + QObject(parent) +{ + QString pattern = rule; + + // Empty rule or comment + if(pattern.trimmed().isEmpty() || pattern.startsWith("!")) { + m_valid = false; + return; + } + + // Ignore element hiding rules for now + if(pattern.contains("##") || pattern.contains("#@#")) { + m_valid = false; + return; + } + + // Exception + if(pattern.startsWith("@@")) { + m_exception = true; + pattern.remove(0, 2); + } + + // Options + if(pattern.contains("$")) { + QString opts = pattern.mid(pattern.indexOf("$")+1); + for(QString opt : opts.split(',')) { + if(opt.endsWith("script")) { + if(opt.startsWith("~")) { + m_whitelistOptions.setFlag(RuleOption::script, true); + } else { + m_blacklistOptions.setFlag(RuleOption::script, true); + } + } else if(opt.endsWith("image")) { + if(opt.startsWith("~")) { + m_whitelistOptions.setFlag(RuleOption::image, true); + } else { + m_blacklistOptions.setFlag(RuleOption::image, true); + } + } else if(opt.endsWith("stylesheet")) { + if(opt.startsWith("~")) { + m_whitelistOptions.setFlag(RuleOption::stylesheet, true); + } else { + m_blacklistOptions.setFlag(RuleOption::stylesheet, true); + } + } else if(opt.endsWith("object")) { + if(opt.startsWith("~")) { + m_whitelistOptions.setFlag(RuleOption::object, true); + } else { + m_blacklistOptions.setFlag(RuleOption::object, true); + } + } else if(opt.endsWith("object-subrequest")) { + if(opt.startsWith("~")) { + m_whitelistOptions.setFlag(RuleOption::objectsubrequest, true); + } else { + m_blacklistOptions.setFlag(RuleOption::objectsubrequest, true); + } + } else if(opt.endsWith("subdocument")) { + if(opt.startsWith("~")) { + m_whitelistOptions.setFlag(RuleOption::subdocument, true); + } else { + m_blacklistOptions.setFlag(RuleOption::subdocument, true); + } + } + } + + pattern.remove(pattern.indexOf("$"), pattern.length()); + } + + // Regular expression + if(rule.startsWith("/") && rule.endsWith("/")) { + m_valid = true; + ruleExpression.setPattern(pattern); + return; + } + + // Domain rules + if(pattern.startsWith("||")) { + pattern.remove(0, 2); + // find the end point for the domain + int end = pattern.indexOf(QRegularExpression("(?:[^\\w\\d\\_\\-\\.\\%]|$)"), 0); + domainExpression.setPattern(pattern.mid(0, end)); + pattern.remove(0, end+1); + } else if(pattern.startsWith("|") && pattern.endsWith("|")) { + pattern.remove(0, 1); + pattern.chop(1); + domainExpression.setPattern(pattern); + } else { + domainExpression.setPattern(".*"); + } + + // Regular rule + ruleExpression.setWildcardPattern(pattern); + m_valid = true; +} + +bool BlockerRule::match(const QWebEngineUrlRequestInfo &info) +{ + if(!m_valid) { + return false; + } + + // if both domain and rule match + if(domainExpression.match(info.requestUrl().host()) && ruleExpression.match(info.requestUrl().toString())) { + + // option explicitly allows + if(matchOptions(info, m_whitelistOptions)) { + return false; + } + + // option explicitly bans + if(matchOptions(info, m_blacklistOptions)) { + return true; + } + + // no options, but both domain and rule match --> rule matches + return true; + } + + // domain and/or rule do not match + return false; +} + +bool BlockerRule::isValid() +{ + return m_valid; +} +bool BlockerRule::isException() +{ + return m_exception; +} + +QString BlockerRule::toString() const +{ + return QString("On [%1]: %2 %3").arg(domainExpression.pattern()).arg(ruleExpression.pattern()).arg(QString::number(m_blacklistOptions, 2)); +} + +bool BlockerRule::matchOptions(const QWebEngineUrlRequestInfo &info, const RuleOptions &options) +{ + // no options are defined + if(options == 0) { + return false; + } + + bool hasOption = false; + switch (info.resourceType()) { + case QWebEngineUrlRequestInfo::ResourceTypeScript: + if(options.testFlag(RuleOption::script)) { + hasOption = true; + } + break; + case QWebEngineUrlRequestInfo::ResourceTypeImage: + if(options.testFlag(RuleOption::image)) { + hasOption = true; + } + break; + case QWebEngineUrlRequestInfo::ResourceTypeStylesheet: + if(options.testFlag(RuleOption::stylesheet)) { + hasOption = true; + } + break; + case QWebEngineUrlRequestInfo::ResourceTypeObject: + if(options.testFlag(RuleOption::object)) { + hasOption = true; + } + break; + case QWebEngineUrlRequestInfo::ResourceTypePluginResource: + if(options.testFlag(RuleOption::objectsubrequest)) { + hasOption = true; + } + break; + case QWebEngineUrlRequestInfo::ResourceTypeSubFrame: + if(options.testFlag(RuleOption::subdocument)) { + hasOption = true; + } + break; + default: + break; + } + + return hasOption; +} diff --git a/src/blocker/blockerrule.h b/src/blocker/blockerrule.h new file mode 100644 index 0000000..0981514 --- /dev/null +++ b/src/blocker/blockerrule.h @@ -0,0 +1,79 @@ +/** LICENSE ******************************************************************** + ** + ** 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 . + ** + ******************************************************************************/ + +#ifndef ADBLOCKRULE_H +#define ADBLOCKRULE_H + +#include +#include +#include "regexp.h" +#include + +class BlockerRule : public QObject +{ + Q_OBJECT +public: + enum RuleOption { + script = 1, + image = 2, + stylesheet = 4, + object = 8, + xmlhttprequest = 16, + objectsubrequest = 32, + subdocument = 64, + ping = 128, + websocket = 256, + document = 512, + + elemhide = 1024, + generichide = 2048, + genericblock = 4096, + + other = 8192 + }; + + Q_DECLARE_FLAGS(RuleOptions, RuleOption) + + explicit BlockerRule(QString rule, QObject *parent = 0); + + bool match(const QWebEngineUrlRequestInfo &info); + bool isValid(); + bool isException(); + QString toString() const; + +signals: + +public slots: + +private: + bool matchOptions(const QWebEngineUrlRequestInfo &info, const RuleOptions &options); + + bool m_valid; + bool m_exception = false; + QStringList hostsBlacklist; + QStringList hostsWhitelist; + RegExp domainExpression; + RegExp ruleExpression; + + RuleOptions m_blacklistOptions; + RuleOptions m_whitelistOptions; +}; + +#endif // ADBLOCKRULE_H diff --git a/src/blocker/blockersubscription.cpp b/src/blocker/blockersubscription.cpp new file mode 100644 index 0000000..02def48 --- /dev/null +++ b/src/blocker/blockersubscription.cpp @@ -0,0 +1,138 @@ +/** LICENSE ******************************************************************** + ** + ** 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 "blockersubscription.h" +#include "ui_subscriptionform.h" + +#include "browser.h" +#include +#include +#include + +BlockerSubscription::BlockerSubscription(const QString url, QWidget *parent) : + QWidget(parent), + ui(new Ui::SubscriptionForm) +{ + ui->setupUi(this); + QUrl _url = QUrl::fromUserInput(url); + m_name = _url.fileName(); + + if(!sSettings->value("blocker.path").toString().isEmpty()) { + QString cacheName = sSettings->value("blocker.path").toString() + m_name; + QFile *cache = new QFile(cacheName); + if(cache->exists()) { + load(cache); + } + + } else { + + // no cache path specified - pull the subscription + QNetworkRequest request; + request.setUrl(QUrl::fromUserInput(url)); + + QNetworkReply *reply = sNetwork->get(request); + connect(reply, &QNetworkReply::finished, [this, reply]() { + this->load(reply); + }); + } +} + +BlockerSubscription::~BlockerSubscription() +{ + delete ui; +} + +QString BlockerSubscription::name() const +{ + return m_name; +} + +void BlockerSubscription::load(QIODevice *dev) +{ + QTextStream subscription(dev); + + QString header = subscription.readLine(); + if(!header.startsWith("[Adblock Plus")) { + qDebug("Invalid format of subscription: %s", qUtf8Printable(m_name)); + return; + } + + // clear all lists + m_urlBlacklist.clear(); + m_urlWhitelist.clear(); + int rules = 0; + + while(!subscription.atEnd()) { + QString line = subscription.readLine(); + if(!line.isEmpty()) { + if(line.startsWith('!')) { + parseComment(line); + } else { + // The line is not a comment + + rules++; + BlockerRule *rule = new BlockerRule(line, this); + + if(rule->isValid()) { + if(rule->isException()) { + m_urlWhitelist.append(rule); + ui->whitelist_listWidget->addItem(rule->toString()); + } else { + ui->blacklist_listWidget->addItem(rule->toString()); + m_urlBlacklist.append(rule); + } + } + + } + } + } + + qDebug("Loaded %i/%i rules from subscription %s", m_urlBlacklist.count() + m_urlWhitelist.count(), rules, qUtf8Printable(m_name)); + dev->deleteLater(); +} + + +void BlockerSubscription::parseComment(const QString &line) +{ + if(line.startsWith("! Title: ")) { + ui->title->setText(line.right(line.length() - 9)); + return; + } + if(line.startsWith("! Homepage: ")) { + ui->homepage->setText(line.right(line.length() - 12)); + return; + } + if(line.startsWith("! Licence: ")) { + ui->license->setText(line.right(line.length() - 11)); + return; + } + if(line.startsWith("! Version: ")) { + ui->version->setText(line.right(line.length() - 11)); + return; + } + if(line.startsWith("! Last modified: ")) { + ui->lastModified->setText(line.right(line.length() - 17)); + return; + } + if(line.startsWith("! Expires: ")) { + ui->expires->setText(line.right(line.length() - 11).left(2)); + return; + } +} diff --git a/src/blocker/blockersubscription.h b/src/blocker/blockersubscription.h new file mode 100644 index 0000000..fddb93d --- /dev/null +++ b/src/blocker/blockersubscription.h @@ -0,0 +1,55 @@ +/** LICENSE ******************************************************************** + ** + ** 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 . + ** + ******************************************************************************/ + +#ifndef SUBSCRIPTIONFORM_H +#define SUBSCRIPTIONFORM_H + +#include +#include "blocker/blockerrule.h" + +namespace Ui { +class SubscriptionForm; +} + +class BlockerSubscription : public QWidget +{ + Q_OBJECT + +public: + explicit BlockerSubscription(const QString url, QWidget *parent = 0); + ~BlockerSubscription(); + + QString name() const; + +private slots: + void load(QIODevice *dev); + +private: + void parseComment(const QString &line); + + Ui::SubscriptionForm *ui; + QString m_name; + + QList m_urlWhitelist; // exception rules + QList m_urlBlacklist; // block rules + +}; + +#endif // SUBSCRIPTIONFORM_H diff --git a/src/blocker/regexp.cpp b/src/blocker/regexp.cpp new file mode 100644 index 0000000..a8dff79 --- /dev/null +++ b/src/blocker/regexp.cpp @@ -0,0 +1,70 @@ +/** LICENSE ******************************************************************** + ** + ** 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 "regexp.h" + +RegExp::RegExp() : + QRegularExpression() +{ +} + +bool RegExp::match(const QString &subject, int offset, MatchType matchType, MatchOptions matchOptions) const +{ + // Empty matches all + if(pattern().isEmpty()) { + return true; + } + + return QRegularExpression::match(subject, offset, matchType, matchOptions).hasMatch(); +} + +void RegExp::setWildcardPattern(const QString &pattern) +{ + QString parsed; + + for(int i=0; i. + ** + ******************************************************************************/ + +#ifndef REGEXP_H +#define REGEXP_H + +#include + +/*! + * Regular Expression class for AdBlockPlus filters + */ +class RegExp : public QRegularExpression +{ +public: + explicit RegExp(); + + bool match(const QString &subject, int offset=0, MatchType matchType=NormalMatch, MatchOptions matchOptions=NoMatchOption) const; + void setWildcardPattern(const QString &pattern); +}; + +#endif // REGEXP_H diff --git a/src/blocker/subscriptiondialog.ui b/src/blocker/subscriptiondialog.ui new file mode 100644 index 0000000..7a63cc9 --- /dev/null +++ b/src/blocker/subscriptiondialog.ui @@ -0,0 +1,67 @@ + + + UrlInterceptorDialog + + + + 0 + 0 + 640 + 480 + + + + Blocker + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Close + + + + + + + + + buttonBox + accepted() + UrlInterceptorDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + UrlInterceptorDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/src/blocker/subscriptionform.ui b/src/blocker/subscriptionform.ui new file mode 100644 index 0000000..703fb6d --- /dev/null +++ b/src/blocker/subscriptionform.ui @@ -0,0 +1,149 @@ + + + SubscriptionForm + + + + 0 + 0 + 640 + 480 + + + + Form + + + + + + Subscription + + + + + + + + Title + + + + + + + TextLabel + + + + + + + Homepage + + + + + + + TextLabel + + + + + + + License + + + + + + + TextLabel + + + + + + + + + + + Version + + + + + + + TextLabel + + + + + + + Last Modified + + + + + + + TextLabel + + + + + + + Expires + + + + + + + TextLabel + + + + + + + + + + + + 0 + + + + URL Blacklist + + + + + + + + + + URL Whitelist + + + + + + + + + + + + + + -- cgit v1.2.1