From 3a21265f0cfe0cc995f1d9a85a5ac08f3646107b Mon Sep 17 00:00:00 2001 From: Martin Rotter Date: Mon, 3 May 2021 14:14:55 +0200 Subject: [PATCH] =?UTF-8?q?save=C2=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- resources/scripts/adblock/adblock-server.js | 41 +- src/librssguard/definitions/definitions.h | 2 +- src/librssguard/gui/reusable/treewidget.cpp | 202 ----- src/librssguard/gui/reusable/treewidget.h | 83 -- src/librssguard/librssguard.pro | 24 +- src/librssguard/miscellaneous/application.cpp | 4 - src/librssguard/miscellaneous/settings.cpp | 10 +- src/librssguard/miscellaneous/settings.h | 8 +- src/librssguard/miscellaneous/skinfactory.cpp | 5 +- src/librssguard/miscellaneous/skinfactory.h | 2 +- .../adblock/adblockaddsubscriptiondialog.cpp | 16 +- .../adblock/adblockaddsubscriptiondialog.h | 1 - .../adblock/adblockaddsubscriptiondialog.ui | 24 +- .../network-web/adblock/adblockdialog.cpp | 87 +- .../network-web/adblock/adblockdialog.h | 20 - .../network-web/adblock/adblockdialog.ui | 24 +- .../network-web/adblock/adblockicon.cpp | 69 +- .../network-web/adblock/adblockicon.h | 1 - .../network-web/adblock/adblockmanager.cpp | 230 +----- .../network-web/adblock/adblockmanager.h | 38 +- .../network-web/adblock/adblockmatcher.cpp | 237 ------ .../network-web/adblock/adblockmatcher.h | 65 -- .../network-web/adblock/adblockrule.cpp | 742 ------------------ .../network-web/adblock/adblockrule.h | 195 ----- .../network-web/adblock/adblocksearchtree.cpp | 136 ---- .../network-web/adblock/adblocksearchtree.h | 57 -- .../adblock/adblocksubscription.cpp | 404 ---------- .../network-web/adblock/adblocksubscription.h | 134 ---- .../network-web/adblock/adblocktreewidget.cpp | 258 ------ .../network-web/adblock/adblocktreewidget.h | 63 -- .../adblock/adblockurlinterceptor.cpp | 2 +- src/librssguard/network-web/webpage.cpp | 19 +- 32 files changed, 132 insertions(+), 3071 deletions(-) delete mode 100755 src/librssguard/gui/reusable/treewidget.cpp delete mode 100755 src/librssguard/gui/reusable/treewidget.h delete mode 100644 src/librssguard/network-web/adblock/adblockmatcher.cpp delete mode 100644 src/librssguard/network-web/adblock/adblockmatcher.h delete mode 100644 src/librssguard/network-web/adblock/adblockrule.cpp delete mode 100644 src/librssguard/network-web/adblock/adblockrule.h delete mode 100644 src/librssguard/network-web/adblock/adblocksearchtree.cpp delete mode 100644 src/librssguard/network-web/adblock/adblocksearchtree.h delete mode 100644 src/librssguard/network-web/adblock/adblocksubscription.cpp delete mode 100644 src/librssguard/network-web/adblock/adblocksubscription.h delete mode 100644 src/librssguard/network-web/adblock/adblocktreewidget.cpp delete mode 100644 src/librssguard/network-web/adblock/adblocktreewidget.h diff --git a/resources/scripts/adblock/adblock-server.js b/resources/scripts/adblock/adblock-server.js index de6fe1a08..c542aed6a 100755 --- a/resources/scripts/adblock/adblock-server.js +++ b/resources/scripts/adblock/adblock-server.js @@ -1,5 +1,4 @@ -// Simple local HTTP server providing ad-blocking -// functionality via https://github.com/cliqz-oss/adblocker +// Simple local HTTP server providing ad-blocking functionality via https://github.com/cliqz-oss/adblocker // // How to install: // npm i -g @cliqz/adblocker @@ -8,10 +7,16 @@ // npm i -g node-fetch // // How to run: -// NODE_PATH="C:\Users\\AppData\Roaming\npm\node_modules" node ./adblock-server.js +// NODE_PATH="C:\Users\\AppData\Roaming\npm\node_modules" node ./adblock-server.js "" "" // // How to use: -// curl -i -X POST --data '{"url": "http://gompoozu.net", "url_type": "main_frame"}' 'http://localhost:48484' +// curl -i -X POST --data ' +// { +// "url": "http://gompoozu.net", +// "url_type": "main_frame", +// "filter": true, +// "cosmetic": true +// }' 'http://localhost:' const fs = require('fs'); const psl = require('psl'); @@ -21,15 +26,10 @@ const concat = require('concat-stream'); const constants = require('node:http2'); const fetch = require("node-fetch"); -let engine; - -adblock.FiltersEngine.fromLists(fetch, [ - 'https://easylist.to/easylist/easylist.txt', - 'https://raw.githubusercontent.com/tomasko126/easylistczechandslovak/master/filters.txt', -]).then(function (res) { engine = res; }); - +const port = process.argv[2]; +const filtersFile = process.argv[3]; +const engine = adblock.FiltersEngine.parse(fs.readFileSync(filtersFile, 'utf-8')); const hostname = '127.0.0.1'; -const port = 48484; const server = http.createServer((req, res) => { try { @@ -41,19 +41,22 @@ const server = http.createServer((req, res) => { const jsonStruct = JSON.parse(jsonData.toString()); const askUrl = jsonStruct['url']; + const askFilter = jsonStruct['filter']; const askCosmetic = jsonStruct['cosmetic']; const askUrlType = jsonStruct['url_type']; const fullUrl = new URL(askUrl); resultJson = {}; - const adblockMatch = engine.match(adblock.Request.fromRawDetails({ - type: askUrlType, - url: askUrl, - })); + if (askFilter) { + const adblockMatch = engine.match(adblock.Request.fromRawDetails({ + type: askUrlType, + url: askUrl, + })); - resultJson["filter"] = adblockMatch; - console.log(`adblocker: Filter is:\n${JSON.stringify(adblockMatch)}.`) + resultJson["filter"] = adblockMatch; + console.log(`adblocker: Filter is:\n${JSON.stringify(adblockMatch)}.`) + } if (askCosmetic) { const adblockCosmetic = engine.getCosmeticsFilters({ @@ -65,7 +68,7 @@ const server = http.createServer((req, res) => { resultJson["cosmetic"] = adblockCosmetic; console.log(`adblocker: Cosmetic is:\n${JSON.stringify(adblockCosmetic)}.`) } - + res.statusCode = 200; res.setHeader('Content-Type', 'application/json'); res.end(JSON.stringify(resultJson)); diff --git a/src/librssguard/definitions/definitions.h b/src/librssguard/definitions/definitions.h index 98c0e6cef..540ab4613 100755 --- a/src/librssguard/definitions/definitions.h +++ b/src/librssguard/definitions/definitions.h @@ -14,7 +14,7 @@ #define SERVICE_CODE_INOREADER "inoreader" #define SERVICE_CODE_GMAIL "gmail" -#define ADBLOCK_HOWTO_FILTERS "https://help.eyeo.com/en/adblockplus/how-to-write-filters" +#define ADBLOCK_HOWTO "https://github.com/martinrotter/rssguard/blob/master/resources/docs/Documentation.md#adblock" #define ADBLOCK_UPDATE_DAYS_INTERVAL 14 #define ADBLOCK_ICON_ACTIVE "adblock" #define ADBLOCK_ICON_DISABLED "adblock-disabled" diff --git a/src/librssguard/gui/reusable/treewidget.cpp b/src/librssguard/gui/reusable/treewidget.cpp deleted file mode 100755 index 0c902c738..000000000 --- a/src/librssguard/gui/reusable/treewidget.cpp +++ /dev/null @@ -1,202 +0,0 @@ -// For license of this file, see /LICENSE.md. - -// -// Copyright (C) 2011-2017 by Martin Rotter -// Copyright (C) 2010-2014 by David Rosca -// -// RSS Guard 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. -// -// RSS Guard 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 RSS Guard. If not, see . - -#include "gui/reusable/treewidget.h" - -#include - -TreeWidget::TreeWidget(QWidget* parent) - : QTreeWidget(parent), m_refreshAllItemsNeeded(true), m_showMode(ItemShowMode::ItemsCollapsed) { - connect(this, &TreeWidget::itemChanged, this, &TreeWidget::sheduleRefresh); -} - -void TreeWidget::clear() { - QTreeWidget::clear(); - m_allTreeItems.clear(); -} - -void TreeWidget::sheduleRefresh() { - m_refreshAllItemsNeeded = true; -} - -void TreeWidget::addTopLevelItem(QTreeWidgetItem* item) { - m_allTreeItems.append(item); - QTreeWidget::addTopLevelItem(item); -} - -void TreeWidget::addTopLevelItems(const QList& items) { - m_allTreeItems.append(items); - QTreeWidget::addTopLevelItems(items); -} - -void TreeWidget::insertTopLevelItem(int index, QTreeWidgetItem* item) { - m_allTreeItems.append(item); - QTreeWidget::insertTopLevelItem(index, item); -} - -void TreeWidget::insertTopLevelItems(int index, const QList& items) { - m_allTreeItems.append(items); - QTreeWidget::insertTopLevelItems(index, items); -} - -void TreeWidget::mousePressEvent(QMouseEvent* event) { - if (event->modifiers() == Qt::ControlModifier) { - emit itemControlClicked(itemAt(event->pos())); - } - - if (event->buttons() == Qt::MiddleButton) { - emit itemMiddleButtonClicked(itemAt(event->pos())); - } - - QTreeWidget::mousePressEvent(event); -} - -void TreeWidget::iterateAllItems(QTreeWidgetItem* parent) { - int count = parent ? parent->childCount() : topLevelItemCount(); - - for (int i = 0; i < count; i++) { - QTreeWidgetItem* item = parent ? parent->child(i) : topLevelItem(i); - - if (item->childCount() == 0) { - m_allTreeItems.append(item); - } - - iterateAllItems(item); - } -} - -QList TreeWidget::allItems() { - if (m_refreshAllItemsNeeded) { - m_allTreeItems.clear(); - iterateAllItems(0); - m_refreshAllItemsNeeded = false; - } - - return m_allTreeItems; -} - -void TreeWidget::filterString(const QString& string) { - QList _allItems = allItems(); - QList parents; - bool stringIsEmpty = string.isEmpty(); - - for (QTreeWidgetItem* item : _allItems) { - bool containsString = stringIsEmpty || item->text(0).contains(string, Qt::CaseSensitivity::CaseInsensitive); - - if (containsString) { - item->setHidden(false); - - if (item->parent()) { - if (!parents.contains(item->parent())) { - parents << item->parent(); - } - } - } - else { - item->setHidden(true); - - if (item->parent()) { - item->parent()->setHidden(true); - } - } - } - - for (int i = 0; i < parents.size(); ++i) { - QTreeWidgetItem* parentItem = parents.at(i); - - parentItem->setHidden(false); - - if (stringIsEmpty) { - parentItem->setExpanded(m_showMode == ItemShowMode::ItemsExpanded); - } - else { - parentItem->setExpanded(true); - } - - if (parentItem->parent() && !parents.contains(parentItem->parent())) { - parents << parentItem->parent(); - } - } -} - -bool TreeWidget::appendToParentItem(const QString& parentText, QTreeWidgetItem* item) { - QList list = findItems(parentText, Qt::MatchFlag::MatchExactly); - - if (list.count() == 0) { - return false; - } - - QTreeWidgetItem* parentItem = list.at(0); - - if (!parentItem) { - return false; - } - - m_allTreeItems.append(item); - parentItem->addChild(item); - return true; -} - -bool TreeWidget::appendToParentItem(QTreeWidgetItem* parent, QTreeWidgetItem* item) { - if (!parent || parent->treeWidget() != this) { - return false; - } - - m_allTreeItems.append(item); - parent->addChild(item); - return true; -} - -bool TreeWidget::prependToParentItem(const QString& parentText, QTreeWidgetItem* item) { - QList list = findItems(parentText, Qt::MatchFlag::MatchExactly); - - if (list.count() == 0) { - return false; - } - - QTreeWidgetItem* parentItem = list.at(0); - - if (!parentItem) { - return false; - } - - m_allTreeItems.append(item); - parentItem->insertChild(0, item); - return true; -} - -bool TreeWidget::prependToParentItem(QTreeWidgetItem* parent, QTreeWidgetItem* item) { - if (!parent || parent->treeWidget() != this) { - return false; - } - - m_allTreeItems.append(item); - parent->insertChild(0, item); - return true; -} - -void TreeWidget::deleteItem(QTreeWidgetItem* item) { - m_refreshAllItemsNeeded = true; - delete item; -} - -void TreeWidget::deleteItems(const QList& items) { - m_refreshAllItemsNeeded = true; - qDeleteAll(items); -} diff --git a/src/librssguard/gui/reusable/treewidget.h b/src/librssguard/gui/reusable/treewidget.h deleted file mode 100755 index 23de0a2c0..000000000 --- a/src/librssguard/gui/reusable/treewidget.h +++ /dev/null @@ -1,83 +0,0 @@ -// For license of this file, see /LICENSE.md. - -// -// Copyright (C) 2011-2017 by Martin Rotter -// Copyright (C) 2010-2014 by David Rosca -// -// RSS Guard 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. -// -// RSS Guard 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 RSS Guard. If not, see . - -#ifndef BOOKMARKSTREEWIDGET_H -#define BOOKMARKSTREEWIDGET_H - -#include - -class TreeWidget : public QTreeWidget { - Q_OBJECT - - public: - explicit TreeWidget(QWidget* parent = nullptr); - - enum class ItemShowMode { - ItemsCollapsed = 0, - ItemsExpanded = 1 - }; - - ItemShowMode defaultItemShowMode(); - void setDefaultItemShowMode(ItemShowMode mode); - QList allItems(); - - bool appendToParentItem(const QString& parentText, QTreeWidgetItem* item); - bool appendToParentItem(QTreeWidgetItem* parent, QTreeWidgetItem* item); - bool prependToParentItem(const QString& parentText, QTreeWidgetItem* item); - bool prependToParentItem(QTreeWidgetItem* parent, QTreeWidgetItem* item); - - void addTopLevelItem(QTreeWidgetItem* item); - void addTopLevelItems(const QList& items); - void insertTopLevelItem(int index, QTreeWidgetItem* item); - void insertTopLevelItems(int index, const QList& items); - - void deleteItem(QTreeWidgetItem* item); - void deleteItems(const QList& items); - - signals: - void itemControlClicked(QTreeWidgetItem* item); - void itemMiddleButtonClicked(QTreeWidgetItem* item); - - public slots: - void filterString(const QString& string); - void clear(); - - private slots: - void sheduleRefresh(); - - protected: - void mousePressEvent(QMouseEvent* event); - - private: - void iterateAllItems(QTreeWidgetItem* parent); - - bool m_refreshAllItemsNeeded; - QList m_allTreeItems; - ItemShowMode m_showMode; -}; - -inline TreeWidget::ItemShowMode TreeWidget::defaultItemShowMode() { - return m_showMode; -} - -inline void TreeWidget::setDefaultItemShowMode(TreeWidget::ItemShowMode mode) { - m_showMode = mode; -} - -#endif // BOOKMARKSTREEWIDGET_H diff --git a/src/librssguard/librssguard.pro b/src/librssguard/librssguard.pro index 53945b532..9bcc16c4d 100644 --- a/src/librssguard/librssguard.pro +++ b/src/librssguard/librssguard.pro @@ -74,7 +74,6 @@ HEADERS += core/feeddownloader.h \ gui/dialogs/formrestoredatabasesettings.h \ gui/dialogs/formsettings.h \ gui/dialogs/formupdate.h \ - gui/reusable/edittableview.h \ gui/feedmessageviewer.h \ gui/toolbars/feedstoolbar.h \ gui/feedsview.h \ @@ -82,6 +81,8 @@ HEADERS += core/feeddownloader.h \ gui/reusable/labelsmenu.h \ gui/reusable/labelwithstatus.h \ gui/reusable/lineeditwithstatus.h \ + gui/reusable/squeezelabel.h \ + gui/reusable/edittableview.h \ gui/messagebox.h \ gui/reusable/messagecountspinbox.h \ gui/messagepreviewer.h \ @@ -101,7 +102,6 @@ HEADERS += core/feeddownloader.h \ gui/settings/settingslocalization.h \ gui/settings/settingspanel.h \ gui/settings/settingsshortcuts.h \ - gui/reusable/squeezelabel.h \ gui/toolbars/statusbar.h \ gui/reusable/styleditemdelegatewithoutfocus.h \ gui/systemtrayicon.h \ @@ -252,13 +252,14 @@ SOURCES += core/feeddownloader.cpp \ gui/dialogs/formrestoredatabasesettings.cpp \ gui/dialogs/formsettings.cpp \ gui/dialogs/formupdate.cpp \ - gui/reusable/edittableview.cpp \ gui/feedmessageviewer.cpp \ gui/toolbars/feedstoolbar.cpp \ gui/feedsview.cpp \ gui/guiutilities.cpp \ gui/reusable/labelsmenu.cpp \ + gui/reusable/edittableview.cpp \ gui/reusable/labelwithstatus.cpp \ + gui/reusable/squeezelabel.cpp \ gui/reusable/lineeditwithstatus.cpp \ gui/messagebox.cpp \ gui/reusable/messagecountspinbox.cpp \ @@ -279,7 +280,6 @@ SOURCES += core/feeddownloader.cpp \ gui/settings/settingslocalization.cpp \ gui/settings/settingspanel.cpp \ gui/settings/settingsshortcuts.cpp \ - gui/reusable/squeezelabel.cpp \ gui/toolbars/statusbar.cpp \ gui/reusable/styleditemdelegatewithoutfocus.cpp \ gui/systemtrayicon.cpp \ @@ -445,30 +445,18 @@ equals(USE_WEBENGINE, true) { network-web/adblock/adblockdialog.h \ network-web/adblock/adblockicon.h \ network-web/adblock/adblockmanager.h \ - network-web/adblock/adblockmatcher.h \ - network-web/adblock/adblockrule.h \ - network-web/adblock/adblocksearchtree.h \ - network-web/adblock/adblocksubscription.h \ - network-web/adblock/adblocktreewidget.h \ network-web/adblock/adblockurlinterceptor.h \ network-web/adblock/adblockrequestinfo.h \ network-web/urlinterceptor.h \ - network-web/networkurlinterceptor.h \ - gui/reusable/treewidget.h + network-web/networkurlinterceptor.h SOURCES += network-web/adblock/adblockaddsubscriptiondialog.cpp \ network-web/adblock/adblockdialog.cpp \ network-web/adblock/adblockicon.cpp \ network-web/adblock/adblockmanager.cpp \ - network-web/adblock/adblockmatcher.cpp \ - network-web/adblock/adblockrule.cpp \ - network-web/adblock/adblocksearchtree.cpp \ - network-web/adblock/adblocksubscription.cpp \ - network-web/adblock/adblocktreewidget.cpp \ network-web/adblock/adblockurlinterceptor.cpp \ network-web/adblock/adblockrequestinfo.cpp \ - network-web/networkurlinterceptor.cpp \ - gui/reusable/treewidget.cpp + network-web/networkurlinterceptor.cpp FORMS += network-web/adblock/adblockaddsubscriptiondialog.ui \ network-web/adblock/adblockdialog.ui diff --git a/src/librssguard/miscellaneous/application.cpp b/src/librssguard/miscellaneous/application.cpp index faa6cb3e9..77b77da81 100755 --- a/src/librssguard/miscellaneous/application.cpp +++ b/src/librssguard/miscellaneous/application.cpp @@ -500,10 +500,6 @@ void Application::onAboutToQuit() { m_quitLogicDone = true; -#if defined(USE_WEBENGINE) - m_webFactory->adBlock()->save(); -#endif - // Make sure that we obtain close lock BEFORE even trying to quit the application. const bool locked_safely = feedUpdateLock()->tryLock(4 * CLOSE_LOCK_TIMEOUT); diff --git a/src/librssguard/miscellaneous/settings.cpp b/src/librssguard/miscellaneous/settings.cpp index ea0f6ddac..0347f19bf 100755 --- a/src/librssguard/miscellaneous/settings.cpp +++ b/src/librssguard/miscellaneous/settings.cpp @@ -21,14 +21,14 @@ DKEY Cookies::ID = "cookies"; // AdBlock. DKEY AdBlock::ID = "adblock"; -DKEY AdBlock::DisabledRules = "disabled_rules"; -DVALUE(QStringList) AdBlock::DisabledRulesDef = QStringList(); - DKEY AdBlock::AdBlockEnabled = "enabled"; DVALUE(bool) AdBlock::AdBlockEnabledDef = false; -DKEY AdBlock::LastUpdatedOn = "last_updated_on"; -DVALUE(QDateTime) AdBlock::LastUpdatedOnDef = QDateTime(); +DKEY AdBlock::FilterLists = "filter_lists"; +DVALUE(QStringList) AdBlock::FilterListsDef = {}; + +DKEY AdBlock::CustomFilters = "custom_filters"; +DVALUE(QStringList) AdBlock::CustomFiltersDef = {}; // Feeds. DKEY Feeds::ID = "feeds"; diff --git a/src/librssguard/miscellaneous/settings.h b/src/librssguard/miscellaneous/settings.h index 55fc8fab8..be23959b1 100644 --- a/src/librssguard/miscellaneous/settings.h +++ b/src/librssguard/miscellaneous/settings.h @@ -42,11 +42,11 @@ namespace AdBlock { KEY AdBlockEnabled; VALUE(bool) AdBlockEnabledDef; - KEY DisabledRules; - VALUE(QStringList) DisabledRulesDef; + KEY FilterLists; + VALUE(QStringList) FilterListsDef; - KEY LastUpdatedOn; - VALUE(QDateTime) LastUpdatedOnDef; + KEY CustomFilters; + VALUE(QStringList) CustomFiltersDef; } // Feeds. diff --git a/src/librssguard/miscellaneous/skinfactory.cpp b/src/librssguard/miscellaneous/skinfactory.cpp index 1ab1d6c61..c43de3de9 100644 --- a/src/librssguard/miscellaneous/skinfactory.cpp +++ b/src/librssguard/miscellaneous/skinfactory.cpp @@ -60,10 +60,9 @@ QString SkinFactory::selectedSkinName() const { return qApp->settings()->value(GROUP(GUI), SETTING(GUI::Skin)).toString(); } -QString SkinFactory::adBlockedPage(const QString& subscription, const QString& rule) { +QString SkinFactory::adBlockedPage(const QString& url) { const QString& adblocked = currentSkin().m_adblocked.arg(tr("This page was blocked by AdBlock"), - tr(R"(Blocked by set: "%1"
Blocked by filter: "%2")") - .arg(subscription, rule)); + tr(R"(Blocked URL: "%1")").arg(url)); return currentSkin().m_layoutMarkupWrapper.arg(tr("This page was blocked by AdBlock"), adblocked); } diff --git a/src/librssguard/miscellaneous/skinfactory.h b/src/librssguard/miscellaneous/skinfactory.h index 9c6b7073a..9471ddcd9 100644 --- a/src/librssguard/miscellaneous/skinfactory.h +++ b/src/librssguard/miscellaneous/skinfactory.h @@ -50,7 +50,7 @@ class RSSGUARD_DLLSPEC SkinFactory : public QObject { // after application restart. QString selectedSkinName() const; - QString adBlockedPage(const QString& subscription, const QString& rule); + QString adBlockedPage(const QString& url); // Gets skin about a particular skin. Skin skinInfo(const QString& skin_name, bool* ok = nullptr) const; diff --git a/src/librssguard/network-web/adblock/adblockaddsubscriptiondialog.cpp b/src/librssguard/network-web/adblock/adblockaddsubscriptiondialog.cpp index 89a6d63b1..f02923429 100644 --- a/src/librssguard/network-web/adblock/adblockaddsubscriptiondialog.cpp +++ b/src/librssguard/network-web/adblock/adblockaddsubscriptiondialog.cpp @@ -48,37 +48,23 @@ AdBlockAddSubscriptionDialog::AdBlockAddSubscriptionDialog(QWidget* parent) tr("Add subscription")); } -QString AdBlockAddSubscriptionDialog::title() const { - return m_ui->m_txtTitle->text(); -} - QString AdBlockAddSubscriptionDialog::url() const { return m_ui->m_txtUrl->text(); } void AdBlockAddSubscriptionDialog::indexChanged(int index) { const Subscription subscription = m_knownSubscriptions.at(index); - const int pos = subscription.m_title.indexOf(QLatin1Char('(')); - - if (pos > 0) { - m_ui->m_txtTitle->setText(subscription.m_title.left(pos).trimmed()); - } - else { - m_ui->m_txtTitle->setText(subscription.m_title); - } m_ui->m_txtUrl->setText(subscription.m_url); } void AdBlockAddSubscriptionDialog::presetsEnabledChanged(bool enabled) { - m_ui->m_txtTitle->setEnabled(!enabled); m_ui->m_txtUrl->setEnabled(!enabled); m_ui->m_cmbPresets->setEnabled(enabled); if (!enabled) { - m_ui->m_txtTitle->clear(); m_ui->m_txtUrl->clear(); - m_ui->m_txtTitle->setFocus(); + m_ui->m_txtUrl->setFocus(); } else { indexChanged(m_ui->m_cmbPresets->currentIndex()); diff --git a/src/librssguard/network-web/adblock/adblockaddsubscriptiondialog.h b/src/librssguard/network-web/adblock/adblockaddsubscriptiondialog.h index 879f772eb..058590ee2 100644 --- a/src/librssguard/network-web/adblock/adblockaddsubscriptiondialog.h +++ b/src/librssguard/network-web/adblock/adblockaddsubscriptiondialog.h @@ -36,7 +36,6 @@ class AdBlockAddSubscriptionDialog : public QDialog { explicit AdBlockAddSubscriptionDialog(QWidget* parent = nullptr); virtual ~AdBlockAddSubscriptionDialog(); - QString title() const; QString url() const; private slots: diff --git a/src/librssguard/network-web/adblock/adblockaddsubscriptiondialog.ui b/src/librssguard/network-web/adblock/adblockaddsubscriptiondialog.ui index 592f5eb61..cca22a22c 100644 --- a/src/librssguard/network-web/adblock/adblockaddsubscriptiondialog.ui +++ b/src/librssguard/network-web/adblock/adblockaddsubscriptiondialog.ui @@ -33,23 +33,6 @@ - - - Title - - - m_txtTitle - - - - - - - Title of subscription - - - - URL @@ -59,14 +42,14 @@ - + Absolute URL to online subscription file - + Qt::Vertical @@ -79,7 +62,7 @@ - + Qt::Horizontal @@ -94,7 +77,6 @@ m_cbUsePredefined m_cmbPresets - m_txtTitle m_txtUrl diff --git a/src/librssguard/network-web/adblock/adblockdialog.cpp b/src/librssguard/network-web/adblock/adblockdialog.cpp index 5c37b0b14..cbff41400 100644 --- a/src/librssguard/network-web/adblock/adblockdialog.cpp +++ b/src/librssguard/network-web/adblock/adblockdialog.cpp @@ -21,8 +21,6 @@ #include "network-web/adblock/adblockaddsubscriptiondialog.h" #include "network-web/adblock/adblockmanager.h" -#include "network-web/adblock/adblocksubscription.h" -#include "network-web/adblock/adblocktreewidget.h" #include "definitions/definitions.h" #include "gui/guiutilities.h" @@ -36,8 +34,7 @@ #include AdBlockDialog::AdBlockDialog(QWidget* parent) - : QDialog(parent), m_manager(qApp->web()->adBlock()), m_currentTreeWidget(nullptr), m_currentSubscription(nullptr), - m_loaded(false), m_ui(new Ui::AdBlockDialog) { + : QDialog(parent), m_manager(qApp->web()->adBlock()), m_loaded(false), m_ui(new Ui::AdBlockDialog) { m_ui->setupUi(this); m_ui->m_cbEnable->setChecked(m_manager->isEnabled()); @@ -50,50 +47,19 @@ AdBlockDialog::AdBlockDialog(QWidget* parent) btn_options->setText(tr("Options")); auto* menu = new QMenu(btn_options); - m_actionAddRule = menu->addAction(tr("Add rule"), this, &AdBlockDialog::addRule); - m_actionRemoveRule = menu->addAction(tr("Remove rule"), this, &AdBlockDialog::removeRule); - menu->addSeparator(); m_actionAddSubscription = menu->addAction(tr("Add subscription"), this, &AdBlockDialog::addSubscription); - m_actionRemoveSubscription = menu->addAction(tr("Remove subscription"), this, &AdBlockDialog::removeSubscription); - menu->addAction(tr("Update subscriptions"), m_manager, &AdBlockManager::updateAllSubscriptions); menu->addSeparator(); menu->addAction(tr("Learn about writing rules..."), this, &AdBlockDialog::learnAboutRules); btn_options->setMenu(menu); - connect(menu, &QMenu::aboutToShow, this, &AdBlockDialog::aboutToShowMenu); connect(m_ui->m_cbEnable, &QCheckBox::toggled, this, &AdBlockDialog::enableAdBlock); - connect(m_ui->m_tabSubscriptions, &QTabWidget::currentChanged, this, &AdBlockDialog::currentChanged); connect(m_ui->m_buttonBox, &QDialogButtonBox::rejected, this, &AdBlockDialog::close); load(); m_ui->m_buttonBox->setFocus(); } -void AdBlockDialog::showRule(const AdBlockRule* rule) const { - AdBlockSubscription* subscription = rule->subscription(); - - if (subscription != nullptr) { - for (int i = 0; i < m_ui->m_tabSubscriptions->count(); ++i) { - auto* tree_widget = qobject_cast(m_ui->m_tabSubscriptions->widget(i)); - - if (subscription == tree_widget->subscription()) { - tree_widget->showRule(rule); - m_ui->m_tabSubscriptions->setCurrentIndex(i); - break; - } - } - } -} - -void AdBlockDialog::addRule() { - m_currentTreeWidget->addRule(); -} - -void AdBlockDialog::removeRule() { - m_currentTreeWidget->removeRule(); -} - void AdBlockDialog::addSubscription() { AdBlockAddSubscriptionDialog dialog(this); @@ -101,28 +67,9 @@ void AdBlockDialog::addSubscription() { return; } - QString title = dialog.title(); QString url = dialog.url(); - if (AdBlockSubscription* subscription = m_manager->addSubscription(title, url)) { - auto* tree = new AdBlockTreeWidget(subscription, m_ui->m_tabSubscriptions); - int index = m_ui->m_tabSubscriptions->insertTab(m_ui->m_tabSubscriptions->count() - 1, tree, subscription->title()); - - m_ui->m_tabSubscriptions->setCurrentIndex(index); - } -} - -void AdBlockDialog::removeSubscription() { - if (m_manager->removeSubscription(m_currentSubscription)) { - delete m_currentTreeWidget; - } -} - -void AdBlockDialog::currentChanged(int index) { - if (index != -1) { - m_currentTreeWidget = qobject_cast(m_ui->m_tabSubscriptions->widget(index)); - m_currentSubscription = m_currentTreeWidget->subscription(); - } + // TODO: add filter list. } void AdBlockDialog::enableAdBlock(bool state) { @@ -133,25 +80,8 @@ void AdBlockDialog::enableAdBlock(bool state) { } } -void AdBlockDialog::aboutToShowMenu() { - bool subscriptionEditable = (m_currentSubscription != nullptr) && m_currentSubscription->canEditRules(); - bool subscriptionRemovable = (m_currentSubscription != nullptr) && m_currentSubscription->canBeRemoved(); - - m_actionAddRule->setEnabled(subscriptionEditable); - m_actionRemoveRule->setEnabled(subscriptionEditable); - m_actionRemoveSubscription->setEnabled(subscriptionRemovable); -} - void AdBlockDialog::learnAboutRules() { - qApp->web()->openUrlInExternalBrowser(QSL(ADBLOCK_HOWTO_FILTERS)); -} - -void AdBlockDialog::loadSubscriptions() { - for (int i = 0; i < m_ui->m_tabSubscriptions->count(); ++i) { - auto* tree_widget = qobject_cast(m_ui->m_tabSubscriptions->widget(i)); - - tree_widget->refresh(); - } + qApp->web()->openUrlInExternalBrowser(QSL(ADBLOCK_HOWTO)); } void AdBlockDialog::load() { @@ -159,14 +89,5 @@ void AdBlockDialog::load() { return; } - auto subs = m_manager->subscriptions(); - - for (AdBlockSubscription* subscription : qAsConst(subs)) { - auto* tree = new AdBlockTreeWidget(subscription, m_ui->m_tabSubscriptions); - - m_ui->m_tabSubscriptions->addTab(tree, subscription->title()); - } - - m_loaded = true; - QTimer::singleShot(50, this, &AdBlockDialog::loadSubscriptions); + // TODO: load } diff --git a/src/librssguard/network-web/adblock/adblockdialog.h b/src/librssguard/network-web/adblock/adblockdialog.h index 9e351d4ec..e0bcba891 100644 --- a/src/librssguard/network-web/adblock/adblockdialog.h +++ b/src/librssguard/network-web/adblock/adblockdialog.h @@ -24,10 +24,7 @@ #include "ui_adblockdialog.h" -class AdBlockSubscription; -class AdBlockTreeWidget; class AdBlockManager; -class AdBlockRule; class AdBlockDialog : public QDialog { Q_OBJECT @@ -35,34 +32,17 @@ class AdBlockDialog : public QDialog { public: explicit AdBlockDialog(QWidget* parent = nullptr); - void showRule(const AdBlockRule* rule) const; - private slots: - void addRule(); - void removeRule(); - void addSubscription(); - void removeSubscription(); - - void currentChanged(int index); void enableAdBlock(bool state); - - void aboutToShowMenu(); void learnAboutRules(); - void loadSubscriptions(); - private: void load(); private: AdBlockManager* m_manager; - AdBlockTreeWidget* m_currentTreeWidget; - AdBlockSubscription* m_currentSubscription; - QAction* m_actionAddRule; - QAction* m_actionRemoveRule; QAction* m_actionAddSubscription; - QAction* m_actionRemoveSubscription; bool m_loaded; Ui::AdBlockDialog* m_ui; diff --git a/src/librssguard/network-web/adblock/adblockdialog.ui b/src/librssguard/network-web/adblock/adblockdialog.ui index 734be0f1b..da1672fc1 100644 --- a/src/librssguard/network-web/adblock/adblockdialog.ui +++ b/src/librssguard/network-web/adblock/adblockdialog.ui @@ -25,10 +25,30 @@ - + - -1 + 1 + + + Filter lists (list per line) + + + + + + + + + + Custom filters + + + + + + + diff --git a/src/librssguard/network-web/adblock/adblockicon.cpp b/src/librssguard/network-web/adblock/adblockicon.cpp index 260fe8123..3461cffe2 100644 --- a/src/librssguard/network-web/adblock/adblockicon.cpp +++ b/src/librssguard/network-web/adblock/adblockicon.cpp @@ -24,14 +24,11 @@ #include "gui/webviewer.h" #include "miscellaneous/application.h" #include "network-web/adblock/adblockmanager.h" -#include "network-web/adblock/adblockrule.h" -#include "network-web/adblock/adblocksubscription.h" #include "network-web/webpage.h" #include -AdBlockIcon::AdBlockIcon(AdBlockManager* parent) - : QAction(parent), m_manager(parent) { +AdBlockIcon::AdBlockIcon(AdBlockManager* parent) : QAction(parent), m_manager(parent) { setToolTip(tr("AdBlock lets you block unwanted content on web pages")); setText(QSL("AdBlock")); setMenu(new QMenu()); @@ -61,32 +58,34 @@ void AdBlockIcon::createMenu(QMenu* menu) { } menu->clear(); - AdBlockCustomList* custom_list = m_manager->customList(); - WebPage* page = qApp->mainForm()->tabWidget()->currentWidget()->webBrowser()->viewer()->page(); - const QUrl page_url = page->url(); - menu->addAction(tr("Show AdBlock &settings"), m_manager, &AdBlockManager::showDialog); - menu->addSeparator(); - if (!page_url.host().isEmpty() && m_manager->isEnabled() && m_manager->canRunOnScheme(page_url.scheme())) { - const QString host = page->url().host().contains(QLatin1String("www.")) ? page_url.host().mid(4) : page_url.host(); - const QString host_filter = QString("@@||%1^$document").arg(host); - const QString page_filter = QString("@@|%1|$document").arg(page_url.toString()); - QAction* act = menu->addAction(tr("Disable on %1").arg(host)); + /* + WebPage* page = qApp->mainForm()->tabWidget()->currentWidget()->webBrowser()->viewer()->page(); + const QUrl page_url = page->url(); + AdBlockCustomList* custom_list = m_manager->customList(); - act->setCheckable(true); - act->setChecked(custom_list->containsFilter(host_filter)); - act->setData(host_filter); - connect(act, &QAction::triggered, this, &AdBlockIcon::toggleCustomFilter); + menu->addSeparator(); - act = menu->addAction(tr("Disable only on this page")); - act->setCheckable(true); - act->setChecked(custom_list->containsFilter(page_filter)); - act->setData(page_filter); - connect(act, &QAction::triggered, this, &AdBlockIcon::toggleCustomFilter); + if (!page_url.host().isEmpty() && m_manager->isEnabled() && m_manager->canRunOnScheme(page_url.scheme())) { + const QString host = page->url().host().contains(QLatin1String("www.")) ? page_url.host().mid(4) : page_url.host(); + const QString host_filter = QString("@@||%1^$document").arg(host); + const QString page_filter = QString("@@|%1|$document").arg(page_url.toString()); + QAction* act = menu->addAction(tr("Disable on %1").arg(host)); - menu->addSeparator(); - } + act->setCheckable(true); + act->setChecked(custom_list->containsFilter(host_filter)); + act->setData(host_filter); + connect(act, &QAction::triggered, this, &AdBlockIcon::toggleCustomFilter); + + act = menu->addAction(tr("Disable only on this page")); + act->setCheckable(true); + act->setChecked(custom_list->containsFilter(page_filter)); + act->setData(page_filter); + connect(act, &QAction::triggered, this, &AdBlockIcon::toggleCustomFilter); + + menu->addSeparator(); + }*/ } void AdBlockIcon::showMenu(const QPoint& pos) { @@ -96,26 +95,6 @@ void AdBlockIcon::showMenu(const QPoint& pos) { menu.exec(pos); } -void AdBlockIcon::toggleCustomFilter() { - auto* action = qobject_cast(sender()); - - if (action == nullptr) { - return; - } - - const QString filter = action->data().toString(); - AdBlockCustomList* custom_list = m_manager->customList(); - - if (custom_list->containsFilter(filter)) { - custom_list->removeFilter(filter); - } - else { - auto* rule = new AdBlockRule(filter, custom_list); - - custom_list->addRule(rule); - } -} - void AdBlockIcon::setEnabled(bool enabled) { if (enabled) { setIcon(qApp->icons()->miscIcon(ADBLOCK_ICON_ACTIVE)); diff --git a/src/librssguard/network-web/adblock/adblockicon.h b/src/librssguard/network-web/adblock/adblockicon.h index 62058762e..594bf8443 100644 --- a/src/librssguard/network-web/adblock/adblockicon.h +++ b/src/librssguard/network-web/adblock/adblockicon.h @@ -37,7 +37,6 @@ class AdBlockIcon : public QAction { private slots: void showMenu(const QPoint& pos); - void toggleCustomFilter(); private: void createMenu(QMenu* menu = nullptr); diff --git a/src/librssguard/network-web/adblock/adblockmanager.cpp b/src/librssguard/network-web/adblock/adblockmanager.cpp index 5ddfee207..9a05fb645 100644 --- a/src/librssguard/network-web/adblock/adblockmanager.cpp +++ b/src/librssguard/network-web/adblock/adblockmanager.cpp @@ -23,9 +23,7 @@ #include "miscellaneous/settings.h" #include "network-web/adblock/adblockdialog.h" #include "network-web/adblock/adblockicon.h" -#include "network-web/adblock/adblockmatcher.h" #include "network-web/adblock/adblockrequestinfo.h" -#include "network-web/adblock/adblocksubscription.h" #include "network-web/adblock/adblockurlinterceptor.h" #include "network-web/networkurlinterceptor.h" #include "network-web/webfactory.h" @@ -41,111 +39,30 @@ #include AdBlockManager::AdBlockManager(QObject* parent) - : QObject(parent), m_loaded(false), m_enabled(false), m_matcher(new AdBlockMatcher(this)), - m_interceptor(new AdBlockUrlInterceptor(this)) { + : QObject(parent), m_loaded(false), m_enabled(false), m_interceptor(new AdBlockUrlInterceptor(this)) { m_adblockIcon = new AdBlockIcon(this); m_adblockIcon->setObjectName(QSL("m_adblockIconAction")); + + m_unifiedFiltersFile = qApp->userDataFolder() + QDir::separator() + QSL("adblock-unified-filters.txt"); } -AdBlockManager::~AdBlockManager() { - qDeleteAll(m_subscriptions); -} - -QList AdBlockManager::subscriptions() const { - return m_subscriptions; -} - -const AdBlockRule* AdBlockManager::block(const AdblockRequestInfo& request) { +bool AdBlockManager::block(const AdblockRequestInfo& request) { QMutexLocker locker(&m_mutex); if (!isEnabled()) { - return nullptr; - } - - const QString url_string = request.requestUrl().toEncoded().toLower(); - const QString url_domain = request.requestUrl().host().toLower(); - const QString url_scheme = request.requestUrl().scheme().toLower(); - - if (!canRunOnScheme(url_scheme) || !canBeBlocked(request.firstPartyUrl())) { - return nullptr; - } - else { - const AdBlockRule* blocked_rule = m_matcher->match(request, url_domain, url_string); - - return blocked_rule; - } -} - -QStringList AdBlockManager::disabledRules() const { - return m_disabledRules; -} - -void AdBlockManager::addDisabledRule(const QString& filter) { - m_disabledRules.append(filter); -} - -void AdBlockManager::removeDisabledRule(const QString& filter) { - m_disabledRules.removeOne(filter); -} - -AdBlockSubscription* AdBlockManager::addSubscription(const QString& title, const QString& url) { - if (title.isEmpty() || url.isEmpty()) { - return nullptr; - } - - QString fileName = title + QSL(".txt"); - QString filePath = storedListsPath() + QDir::separator() + fileName; - QByteArray data = QString("Title: %1\nUrl: %2\n[Adblock Plus 1.1.1]").arg(title, url).toLatin1(); - QSaveFile file(filePath); - - if (!file.open(QFile::WriteOnly)) { - qWarningNN << LOGSEC_ADBLOCK - << "Cannot save AdBlock subscription to file" - << QUOTE_W_SPACE_DOT(filePath); - return nullptr; - } - - file.write(data); - file.commit(); - auto* subscription = new AdBlockSubscription(title, this); - - subscription->setUrl(QUrl(url)); - subscription->setFilePath(filePath); - subscription->loadSubscription(m_disabledRules); - m_subscriptions.insert(m_subscriptions.count() - 1, subscription); - - connect(subscription, &AdBlockSubscription::subscriptionChanged, this, &AdBlockManager::updateMatcher); - return subscription; -} - -bool AdBlockManager::removeSubscription(AdBlockSubscription* subscription) { - QMutexLocker locker(&m_mutex); - - if (!m_subscriptions.contains(subscription) || !subscription->canBeRemoved()) { return false; } - QFile(subscription->filePath()).remove(); - m_subscriptions.removeOne(subscription); - m_matcher->update(); - delete subscription; - return true; -} + const QString url_string = request.requestUrl().toEncoded().toLower(); + const QString url_scheme = request.requestUrl().scheme().toLower(); -AdBlockCustomList* AdBlockManager::customList() const { - for (AdBlockSubscription* subscription : m_subscriptions) { - auto* list = qobject_cast(subscription); - - if (list != nullptr) { - return list; - } + if (!canRunOnScheme(url_scheme)) { + return false; + } + else { + // TODO: start server if needed, call it. + return false; } - - return nullptr; -} - -QString AdBlockManager::storedListsPath() { - return qApp->userDataFolder() + QDir::separator() + ADBLOCK_LISTS_SUBDIRECTORY; } void AdBlockManager::load(bool initial_load) { @@ -168,133 +85,33 @@ void AdBlockManager::load(bool initial_load) { m_enabled = new_enabled; if (!m_loaded) { - m_disabledRules = qApp->settings()->value(GROUP(AdBlock), SETTING(AdBlock::DisabledRules)).toStringList(); - - QDateTime last_update = qApp->settings()->value(GROUP(AdBlock), SETTING(AdBlock::LastUpdatedOn)).toDateTime(); - QDir adblock_dir(storedListsPath()); - - // Create if neccessary - if (!adblock_dir.exists()) { - QDir().mkpath(storedListsPath()); - } - - auto subs_files = adblock_dir.entryList({ QSL("*.txt") }, QDir::Filter::Files); - - for (const QString& subscription_file_name : qAsConst(subs_files)) { - if (subscription_file_name == ADBLOCK_CUSTOMLIST_NAME) { - continue; - } - - const QString absolute_path = adblock_dir.absoluteFilePath(subscription_file_name); - QFile file(absolute_path); - - if (!file.open(QFile::OpenModeFlag::ReadOnly)) { - continue; - } - - QTextStream subscription_stream(&file); - - subscription_stream.setCodec("UTF-8"); - QString title = subscription_stream.readLine(1024).remove(QLatin1String("Title: ")); - QUrl url = QUrl(subscription_stream.readLine(1024).remove(QLatin1String("Url: "))); - - if (title.isEmpty() || !url.isValid()) { - qWarningNN << LOGSEC_ADBLOCK - << "Invalid AdBlock subscription file" - << QUOTE_W_SPACE_DOT(absolute_path); - continue; - } - - auto* subscription = new AdBlockSubscription(title, this); - - subscription->setUrl(url); - subscription->setFilePath(absolute_path); - m_subscriptions.append(subscription); - } - - // Append CustomList. - auto* custom_list = new AdBlockCustomList(this); - - m_subscriptions.append(custom_list); - - // Load all subscriptions. - for (AdBlockSubscription* subscription : qAsConst(m_subscriptions)) { - subscription->loadSubscription(m_disabledRules); - connect(subscription, &AdBlockSubscription::subscriptionChanged, this, &AdBlockManager::updateMatcher); - } - - if (last_update.addDays(ADBLOCK_UPDATE_DAYS_INTERVAL) < QDateTime::currentDateTime()) { - QTimer::singleShot(1000 * 60, this, &AdBlockManager::updateAllSubscriptions); - } - qApp->web()->urlIinterceptor()->installUrlInterceptor(m_interceptor); m_loaded = true; } if (m_enabled) { - m_matcher->update(); + if (!QFile::exists(m_unifiedFiltersFile)) { + updateUnifiedFiltersFile(); + } } else { - m_matcher->clear(); + if (QFile::exists(m_unifiedFiltersFile)) { + QFile::remove(m_unifiedFiltersFile); + } } } -void AdBlockManager::updateMatcher() { - QMutexLocker locker(&m_mutex); - - m_matcher->update(); -} - -void AdBlockManager::updateAllSubscriptions() { - for (AdBlockSubscription* subscription : qAsConst(m_subscriptions)) { - subscription->updateSubscription(); - } - - qApp->settings()->setValue(GROUP(AdBlock), AdBlock::LastUpdatedOn, QDateTime::currentDateTime()); -} - -void AdBlockManager::save() { - if (!m_loaded) { - return; - } - - for (AdBlockSubscription* subscription : qAsConst(m_subscriptions)) { - subscription->saveSubscription(); - } - - qApp->settings()->setValue(GROUP(AdBlock), AdBlock::AdBlockEnabled, m_enabled); - qApp->settings()->setValue(GROUP(AdBlock), AdBlock::DisabledRules, m_disabledRules); -} - bool AdBlockManager::isEnabled() const { return m_enabled; } bool AdBlockManager::canRunOnScheme(const QString& scheme) const { - return !(scheme == QSL("file") || scheme == QSL("qrc") || - scheme == QSL("data") || scheme == QSL("abp")); -} - -bool AdBlockManager::canBeBlocked(const QUrl& url) const { - return !m_matcher->adBlockDisabledForUrl(url); -} - -QString AdBlockManager::elementHidingRules(const QUrl& url) const { - if (!isEnabled() || !canRunOnScheme(url.scheme()) || !canBeBlocked(url)) { - return QString(); - } - else { - return m_matcher->elementHidingRules(); - } + return !(scheme == QSL("file") || scheme == QSL("qrc") || scheme == QSL("data") || scheme == QSL("abp")); } QString AdBlockManager::elementHidingRulesForDomain(const QUrl& url) const { - if (!isEnabled() || !canRunOnScheme(url.scheme()) || !canBeBlocked(url)) { - return QString(); - } - else { - return m_matcher->elementHidingRulesForDomain(url.host()); - } + // TODO: call service for cosmetic rules. + return {}; } QString AdBlockManager::generateJsForElementHiding(const QString& css) const { @@ -317,3 +134,8 @@ QString AdBlockManager::generateJsForElementHiding(const QString& css) const { void AdBlockManager::showDialog() { AdBlockDialog(qApp->mainFormWidget()).exec(); } + +void AdBlockManager::updateUnifiedFiltersFile() { + // TODO: download contents of all filter lists + append custom filters + // and combine into single file. +} diff --git a/src/librssguard/network-web/adblock/adblockmanager.h b/src/librssguard/network-web/adblock/adblockmanager.h index 5b802ef24..6c0e35e80 100644 --- a/src/librssguard/network-web/adblock/adblockmanager.h +++ b/src/librssguard/network-web/adblock/adblockmanager.h @@ -27,10 +27,6 @@ class QUrl; class AdblockRequestInfo; -class AdBlockMatcher; -class AdBlockCustomList; -class AdBlockSubscription; -class AdBlockRule; class AdBlockUrlInterceptor; class AdBlockIcon; @@ -39,62 +35,40 @@ class AdBlockManager : public QObject { public: explicit AdBlockManager(QObject* parent = nullptr); - virtual ~AdBlockManager(); - // If "initial_load" is true, then we want to explicitly turn off + // If "initial_load" is false, then we want to explicitly turn off // Adblock if it is running or turn on when not running. // if "initial_load" is true, then we want to forcefully perform // initial loading of Adblock. void load(bool initial_load); - // Save all subscriptions to file(s). - void save(); - - // General method for adblocking. Returns pointer to rule if request should - // be blocked. - const AdBlockRule* block(const AdblockRequestInfo& request); + // General method for adblocking. Returns true if request should be blocked. + bool block(const AdblockRequestInfo& request); bool isEnabled() const; bool canRunOnScheme(const QString& scheme) const; - QString elementHidingRules(const QUrl& url) const; QString elementHidingRulesForDomain(const QUrl& url) const; QString generateJsForElementHiding(const QString& css) const; - QList subscriptions() const; - - QStringList disabledRules() const; - void addDisabledRule(const QString& filter); - void removeDisabledRule(const QString& filter); - - AdBlockSubscription* addSubscription(const QString& title, const QString& url); - bool removeSubscription(AdBlockSubscription* subscription); - - AdBlockCustomList* customList() const; AdBlockIcon* adBlockIcon() const; - static QString storedListsPath(); - public slots: - void updateMatcher(); - void updateAllSubscriptions(); void showDialog(); signals: void enabledChanged(bool enabled); - private: - inline bool canBeBlocked(const QUrl& url) const; + private slots: + void updateUnifiedFiltersFile(); private: bool m_loaded; bool m_enabled; AdBlockIcon* m_adblockIcon; - QList m_subscriptions; - AdBlockMatcher* m_matcher; - QStringList m_disabledRules; AdBlockUrlInterceptor* m_interceptor; QMutex m_mutex; + QString m_unifiedFiltersFile; }; inline AdBlockIcon* AdBlockManager::adBlockIcon() const { diff --git a/src/librssguard/network-web/adblock/adblockmatcher.cpp b/src/librssguard/network-web/adblock/adblockmatcher.cpp deleted file mode 100644 index 71edec90f..000000000 --- a/src/librssguard/network-web/adblock/adblockmatcher.cpp +++ /dev/null @@ -1,237 +0,0 @@ -// For license of this file, see /LICENSE.md. - -// -// Copyright (C) 2011-2017 by Martin Rotter -// Copyright (C) 2010-2014 by David Rosca -// -// RSS Guard 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. -// -// RSS Guard 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 RSS Guard. If not, see . - -#include "network-web/adblock/adblockmatcher.h" - -#include "definitions/definitions.h" -#include "network-web/adblock/adblockmanager.h" -#include "network-web/adblock/adblockrule.h" -#include "network-web/adblock/adblocksubscription.h" - -AdBlockMatcher::AdBlockMatcher(AdBlockManager* manager) - : QObject(manager), m_manager(manager) {} - -AdBlockMatcher::~AdBlockMatcher() { - clear(); -} - -const AdBlockRule* AdBlockMatcher::match(const AdblockRequestInfo& request, const QString& urlDomain, - const QString& urlString) const { - // Exception rules. - if (m_networkExceptionTree.find(request, urlDomain, urlString) != nullptr) { - return nullptr; - } - - int count = m_networkExceptionRules.count(); - - for (int i = 0; i < count; ++i) { - const AdBlockRule* rule = m_networkExceptionRules.at(i); - - if (rule->networkMatch(request, urlDomain, urlString)) { - return nullptr; - } - } - - // Block rules. - if (const AdBlockRule* rule = m_networkBlockTree.find(request, urlDomain, urlString)) { - return rule; - } - - count = m_networkBlockRules.count(); - - for (int i = 0; i < count; ++i) { - const AdBlockRule* rule = m_networkBlockRules.at(i); - - if (rule->networkMatch(request, urlDomain, urlString)) { - return rule; - } - } - - return nullptr; -} - -bool AdBlockMatcher::adBlockDisabledForUrl(const QUrl& url) const { - int count = m_documentRules.count(); - - for (int i = 0; i < count; ++i) { - if (m_documentRules.at(i)->urlMatch(url)) { - return true; - } - } - - return false; -} - -bool AdBlockMatcher::elemHideDisabledForUrl(const QUrl& url) const { - if (adBlockDisabledForUrl(url)) { - return true; - } - - int count = m_elemhideRules.count(); - - for (int i = 0; i < count; ++i) { - if (m_elemhideRules.at(i)->urlMatch(url)) { - return true; - } - } - - return false; -} - -QString AdBlockMatcher::elementHidingRules() const { - return m_elementHidingRules; -} - -QString AdBlockMatcher::elementHidingRulesForDomain(const QString& domain) const { - QString rules; - int addedRulesCount = 0; - int count = m_domainRestrictedCssRules.count(); - - for (int i = 0; i < count; ++i) { - const AdBlockRule* rule = m_domainRestrictedCssRules.at(i); - - if (!rule->matchDomain(domain)) { - continue; - } - - if (Q_UNLIKELY(addedRulesCount == 1000)) { - rules.append(rule->cssSelector()); - rules.append(QSL("{display:none !important;}\n")); - addedRulesCount = 0; - } - else { - rules.append(rule->cssSelector() + QLatin1Char(',')); - addedRulesCount++; - } - } - - if (addedRulesCount != 0) { - rules = rules.left(rules.size() - 1); - rules.append(QSL("{display:none !important;}\n")); - } - - return rules; -} - -void AdBlockMatcher::update() { - clear(); - QHash cssRulesHash; - QVector exceptionCssRules; - auto subs = m_manager->subscriptions(); - - for (AdBlockSubscription* subscription : qAsConst(subs)) { - auto rls = subscription->allRules(); - - for (const AdBlockRule* rule : qAsConst(rls)) { - // Don't add internally disabled rules to cache. - if (rule->isInternalDisabled()) { - continue; - } - - if (rule->isCssRule()) { - // We will add only enabled css rules to cache, because there is no enabled/disabled - // check on match. They are directly embedded to pages. - if (!rule->isEnabled()) { - continue; - } - - if (rule->isException()) { - exceptionCssRules.append(rule); - } - else { - cssRulesHash.insert(rule->cssSelector(), rule); - } - } - else if (rule->isDocument()) { - m_documentRules.append(rule); - } - else if (rule->isElemhide()) { - m_elemhideRules.append(rule); - } - else if (rule->isException()) { - if (!m_networkExceptionTree.add(rule)) { - m_networkExceptionRules.append(rule); - } - } - else { - if (!m_networkBlockTree.add(rule)) { - m_networkBlockRules.append(rule); - } - } - } - } - - for (const AdBlockRule* rule : exceptionCssRules) { - const AdBlockRule* originalRule = cssRulesHash.value(rule->cssSelector()); - - // If we don't have this selector, the exception does nothing. - if (originalRule == nullptr) { - continue; - } - - AdBlockRule* copiedRule = originalRule->copy(); - - copiedRule->m_options |= AdBlockRule::RuleOption::DomainRestrictedOption; - copiedRule->m_blockedDomains.append(rule->m_allowedDomains); - cssRulesHash[rule->cssSelector()] = copiedRule; - m_createdRules.append(copiedRule); - } - - // Apparently, excessive amount of selectors for one CSS rule is not what WebKit likes. - // (In my testings, 4931 is the number that makes it crash). - // So let's split it by 1000 selectors. - int hidingRulesCount = 0; - QHashIterator it(cssRulesHash); - - while (it.hasNext()) { - it.next(); - const AdBlockRule* rule = it.value(); - - if (rule->isDomainRestricted()) { - m_domainRestrictedCssRules.append(rule); - } - else if (Q_UNLIKELY(hidingRulesCount == 1000)) { - m_elementHidingRules.append(rule->cssSelector()); - m_elementHidingRules.append(QL1S("{display:none !important;} ")); - hidingRulesCount = 0; - } - else { - m_elementHidingRules.append(rule->cssSelector() + QLatin1Char(',')); - hidingRulesCount++; - } - } - - if (hidingRulesCount != 0) { - m_elementHidingRules = m_elementHidingRules.left(m_elementHidingRules.size() - 1); - m_elementHidingRules.append(QL1S("{display:none !important;} ")); - } -} - -void AdBlockMatcher::clear() { - m_networkExceptionTree.clear(); - m_networkExceptionRules.clear(); - m_networkBlockTree.clear(); - m_networkBlockRules.clear(); - m_domainRestrictedCssRules.clear(); - m_elementHidingRules.clear(); - m_documentRules.clear(); - m_elemhideRules.clear(); - qDeleteAll(m_createdRules); - m_createdRules.clear(); -} diff --git a/src/librssguard/network-web/adblock/adblockmatcher.h b/src/librssguard/network-web/adblock/adblockmatcher.h deleted file mode 100644 index 0af9ec8e9..000000000 --- a/src/librssguard/network-web/adblock/adblockmatcher.h +++ /dev/null @@ -1,65 +0,0 @@ -// For license of this file, see /LICENSE.md. - -// -// Copyright (C) 2011-2017 by Martin Rotter -// Copyright (C) 2010-2014 by David Rosca -// -// RSS Guard 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. -// -// RSS Guard 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 RSS Guard. If not, see . - -#ifndef ADBLOCKMATCHER_H -#define ADBLOCKMATCHER_H - -#include - -#include "network-web/adblock/adblocksearchtree.h" - -#include -#include - -class AdblockRequestInfo; -class AdBlockManager; - -class AdBlockMatcher : public QObject { - Q_OBJECT - - public: - explicit AdBlockMatcher(AdBlockManager* manager); - virtual ~AdBlockMatcher(); - - const AdBlockRule* match(const AdblockRequestInfo& request, const QString& url_domain, const QString& url_string) const; - - bool adBlockDisabledForUrl(const QUrl& url) const; - bool elemHideDisabledForUrl(const QUrl& url) const; - - QString elementHidingRules() const; - QString elementHidingRulesForDomain(const QString& domain) const; - - public slots: - void update(); - void clear(); - - private: - AdBlockManager* m_manager; - QVector m_createdRules; - QVector m_networkExceptionRules; - QVector m_networkBlockRules; - QVector m_domainRestrictedCssRules; - QVector m_documentRules; - QVector m_elemhideRules; - QString m_elementHidingRules; - AdBlockSearchTree m_networkBlockTree; - AdBlockSearchTree m_networkExceptionTree; -}; - -#endif // ADBLOCKMATCHER_H diff --git a/src/librssguard/network-web/adblock/adblockrule.cpp b/src/librssguard/network-web/adblock/adblockrule.cpp deleted file mode 100644 index 770f94988..000000000 --- a/src/librssguard/network-web/adblock/adblockrule.cpp +++ /dev/null @@ -1,742 +0,0 @@ -// For license of this file, see /LICENSE.md. - -// -// Copyright (C) 2011-2017 by Martin Rotter -// Copyright (C) 2010-2014 by David Rosca -// -// RSS Guard 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. -// -// RSS Guard 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 RSS Guard. If not, see . - -/** - * Copyright (c) 2009, Zsombor Gegesy - * Copyright (c) 2009, Benjamin C. Meyer - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Benjamin Meyer nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "network-web/adblock/adblockrule.h" - -#include "definitions/definitions.h" -#include "network-web/adblock/adblockrequestinfo.h" -#include "network-web/adblock/adblocksubscription.h" - -#include "network-web/urltld.cpp" - -#include -#include -#include -#include -#include - -static QString toSecondLevelDomain(const QUrl& url) { - const QString tld = topLevelDomain(url); - const QString urlHost = url.host(); - - if (tld.isEmpty() || urlHost.isEmpty()) { - return QString(); - } - - QString domain = urlHost.left(urlHost.size() - tld.size()); - - if (domain.count(QL1C('.')) == 0) { - return urlHost; - } - - while (domain.count(QL1C('.')) != 0) { - domain = domain.mid(domain.indexOf(QL1C('.')) + 1); - } - - return domain + tld; -} - -AdBlockRule::AdBlockRule(const QString& filter, AdBlockSubscription* subscription) - : m_subscription(subscription), m_type(StringContainsMatchRule), m_caseSensitivity(Qt::CaseInsensitive), - m_isEnabled(true), m_isException(false), m_isInternalDisabled(false) { - setFilter(filter); -} - -AdBlockRule* AdBlockRule::copy() const { - AdBlockRule* rule = new AdBlockRule(); - - rule->m_subscription = m_subscription; - rule->m_type = m_type; - rule->m_options = m_options; - rule->m_exceptions = m_exceptions; - rule->m_filter = m_filter; - rule->m_matchString = m_matchString; - rule->m_caseSensitivity = m_caseSensitivity; - rule->m_isEnabled = m_isEnabled; - rule->m_isException = m_isException; - rule->m_isInternalDisabled = m_isInternalDisabled; - rule->m_allowedDomains = m_allowedDomains; - rule->m_blockedDomains = m_blockedDomains; - rule->matchers = matchers; - - return rule; -} - -AdBlockSubscription* AdBlockRule::subscription() const { - return m_subscription; -} - -void AdBlockRule::setSubscription(AdBlockSubscription* subscription) { - m_subscription = subscription; -} - -QString AdBlockRule::filter() const { - return m_filter; -} - -void AdBlockRule::setFilter(const QString& filter) { - m_filter = filter; - parseFilter(); -} - -bool AdBlockRule::isCssRule() const { - return m_type == CssRule; -} - -QString AdBlockRule::cssSelector() const { - return m_matchString; -} - -bool AdBlockRule::isDocument() const { - return hasOption(DocumentOption); -} - -bool AdBlockRule::isElemhide() const { - return hasOption(ElementHideOption); -} - -bool AdBlockRule::isDomainRestricted() const { - return hasOption(DomainRestrictedOption); -} - -bool AdBlockRule::isException() const { - return m_isException; -} - -bool AdBlockRule::isComment() const { - return m_filter.startsWith(QL1C('!')); -} - -bool AdBlockRule::isEnabled() const { - return m_isEnabled; -} - -void AdBlockRule::setEnabled(bool enabled) { - m_isEnabled = enabled; -} - -bool AdBlockRule::isSlow() const { - return !m_regexPattern.isEmpty(); -} - -bool AdBlockRule::isInternalDisabled() const { - return m_isInternalDisabled; -} - -bool AdBlockRule::urlMatch(const QUrl& url) const { - if (!hasOption(DocumentOption) && !hasOption(ElementHideOption)) { - return false; - } - else { - const QString encodedUrl = url.toEncoded(); - const QString domain = url.host(); - - return stringMatch(domain, encodedUrl); - } -} - -bool AdBlockRule::networkMatch(const AdblockRequestInfo& request, - const QString& domain, - const QString& encoded_url) const { - if (m_type == CssRule || !m_isEnabled || m_isInternalDisabled) { - return false; - } - - bool matched = stringMatch(domain, encoded_url); - - if (matched) { - // Check domain restrictions. - if (hasOption(DomainRestrictedOption) && !matchDomain(request.firstPartyUrl().host())) { - return false; - } - - // Check third-party restriction. - if (hasOption(ThirdPartyOption) && !matchThirdParty(request)) { - return false; - } - - // Check object restrictions. - if (hasOption(ObjectOption) && !matchObject(request)) { - return false; - } - - // Check subdocument restriction. - if (hasOption(SubdocumentOption) && !matchSubdocument(request)) { - return false; - } - - // Check xmlhttprequest restriction. - if (hasOption(XMLHttpRequestOption) && !matchXmlHttpRequest(request)) { - return false; - } - - // Check image restriction. - if (hasOption(ImageOption) && !matchImage(request)) { - return false; - } - - // Check script restriction. - if (hasOption(ScriptOption) && !matchScript(request)) { - return false; - } - - // Check stylesheet restriction. - if (hasOption(StyleSheetOption) && !matchStyleSheet(request)) { - return false; - } - - // Check object-subrequest restriction. - if (hasOption(ObjectSubrequestOption) && !matchObjectSubrequest(request)) { - return false; - } - } - - return matched; -} - -bool AdBlockRule::matchDomain(const QString& domain) const { - if (!m_isEnabled) { - return false; - } - - if (!hasOption(DomainRestrictedOption)) { - return true; - } - - if (m_blockedDomains.isEmpty()) { - for (const QString& d : m_allowedDomains) { - if (isMatchingDomain(domain, d)) { - return true; - } - } - } - else if (m_allowedDomains.isEmpty()) { - for (const QString& d : m_blockedDomains) { - if (isMatchingDomain(domain, d)) { - return false; - } - } - - return true; - } - else { - for (const QString& d : m_blockedDomains) { - if (isMatchingDomain(domain, d)) { - return false; - } - } - - for (const QString& d : m_allowedDomains) { - if (isMatchingDomain(domain, d)) { - return true; - } - } - } - - return false; -} - -bool AdBlockRule::matchThirdParty(const AdblockRequestInfo& request) const { - // Third-party matching should be performed on second-level domains. - const QString firstPartyHost = toSecondLevelDomain(request.firstPartyUrl()); - const QString host = toSecondLevelDomain(request.requestUrl()); - bool match = firstPartyHost != host; - - return hasException(ThirdPartyOption) ? !match : match; -} - -bool AdBlockRule::matchObject(const AdblockRequestInfo& request) const { - bool match = request.resourceType() == QWebEngineUrlRequestInfo::ResourceType::ResourceTypeObject; - - return hasException(ObjectOption) ? !match : match; -} - -bool AdBlockRule::matchSubdocument(const AdblockRequestInfo& request) const { - bool match = request.resourceType() == QWebEngineUrlRequestInfo::ResourceType::ResourceTypeSubFrame; - - return hasException(SubdocumentOption) ? !match : match; -} - -bool AdBlockRule::matchXmlHttpRequest(const AdblockRequestInfo& request) const { - bool match = request.resourceType() == QWebEngineUrlRequestInfo::ResourceType::ResourceTypeXhr; - - return hasException(XMLHttpRequestOption) ? !match : match; -} - -bool AdBlockRule::matchImage(const AdblockRequestInfo& request) const { - bool match = request.resourceType() == QWebEngineUrlRequestInfo::ResourceType::ResourceTypeImage; - - return hasException(ImageOption) ? !match : match; -} - -bool AdBlockRule::matchScript(const AdblockRequestInfo& request) const { - bool match = request.resourceType() == QWebEngineUrlRequestInfo::ResourceType::ResourceTypeScript; - - return hasException(ScriptOption) ? !match : match; -} - -bool AdBlockRule::matchStyleSheet(const AdblockRequestInfo& request) const { - bool match = request.resourceType() == QWebEngineUrlRequestInfo::ResourceType::ResourceTypeStylesheet; - - return hasException(StyleSheetOption) ? !match : match; -} - -bool AdBlockRule::matchObjectSubrequest(const AdblockRequestInfo& request) const { - bool match = request.resourceType() == QWebEngineUrlRequestInfo::ResourceType::ResourceTypeSubResource; - - return hasException(ObjectSubrequestOption) ? !match : match; -} - -void AdBlockRule::parseFilter() { - QString parsedLine = m_filter; - - // Empty rule or just comment. - if (m_filter.trimmed().isEmpty() || m_filter.startsWith(QL1C('!'))) { - // We want to differentiate rule disabled by user and rule disabled in subscription file - // m_isInternalDisabled is also used when rule is disabled due to all options not being supported. - m_isEnabled = false; - m_isInternalDisabled = true; - m_type = Invalid; - return; - } - - // CSS Element hiding rule. - if (parsedLine.contains(QL1S("##")) || parsedLine.contains(QL1S("#@#"))) { - m_type = CssRule; - int pos = parsedLine.indexOf(QL1C('#')); - - // Domain restricted rule. - if (!parsedLine.startsWith(QL1S("##"))) { - QString domains = parsedLine.left(pos); - - parseDomains(domains, QL1C(',')); - } - - m_isException = parsedLine.at(pos + 1) == QL1C('@'); - m_matchString = parsedLine.mid(m_isException ? pos + 3 : pos + 2); - - // CSS rule cannot have more options -> stop parsing. - return; - } - - // Exception always starts with @@. - if (parsedLine.startsWith(QL1S("@@"))) { - m_isException = true; - parsedLine = parsedLine.mid(2); - } - - // Parse all options following $ char - int optionsIndex = parsedLine.indexOf(QL1C('$')); - - if (optionsIndex >= 0) { - const QStringList options = parsedLine.mid(optionsIndex + 1).split(QL1C(','), -#if QT_VERSION >= 0x050F00 // Qt >= 5.15.0 - Qt::SplitBehaviorFlags::SkipEmptyParts); -#else - QString::SplitBehavior::SkipEmptyParts); -#endif - int handledOptions = 0; - - for (const QString& option : options) { - if (option.startsWith(QL1S("domain="))) { - parseDomains(option.mid(7), QL1C('|')); - ++handledOptions; - } - else if (option == QL1S("match-case")) { - m_caseSensitivity = Qt::CaseSensitivity::CaseSensitive; - ++handledOptions; - } - else if (option.endsWith(QL1S("third-party"))) { - setOption(RuleOption::ThirdPartyOption); - setException(RuleOption::ThirdPartyOption, option.startsWith(QL1C('~'))); - ++handledOptions; - } - else if (option.endsWith(QL1S("object"))) { - setOption(RuleOption::ObjectOption); - setException(RuleOption::ObjectOption, option.startsWith(QL1C('~'))); - ++handledOptions; - } - else if (option.endsWith(QL1S("subdocument"))) { - setOption(RuleOption::SubdocumentOption); - setException(RuleOption::SubdocumentOption, option.startsWith(QL1C('~'))); - ++handledOptions; - } - else if (option.endsWith(QL1S("xmlhttprequest"))) { - setOption(RuleOption::XMLHttpRequestOption); - setException(RuleOption::XMLHttpRequestOption, option.startsWith(QL1C('~'))); - ++handledOptions; - } - else if (option.endsWith(QL1S("image"))) { - setOption(RuleOption::ImageOption); - setException(RuleOption::ImageOption, option.startsWith(QL1C('~'))); - ++handledOptions; - } - else if (option.endsWith(QL1S("script"))) { - setOption(RuleOption::ScriptOption); - setException(RuleOption::ScriptOption, option.startsWith(QL1C('~'))); - ++handledOptions; - } - else if (option.endsWith(QL1S("stylesheet"))) { - setOption(RuleOption::StyleSheetOption); - setException(RuleOption::StyleSheetOption, option.startsWith(QL1C('~'))); - ++handledOptions; - } - else if (option.endsWith(QL1S("object-subrequest"))) { - setOption(RuleOption::ObjectSubrequestOption); - setException(RuleOption::ObjectSubrequestOption, option.startsWith(QL1C('~'))); - ++handledOptions; - } - else if (option == QL1S("document") && m_isException) { - setOption(RuleOption::DocumentOption); - ++handledOptions; - } - else if (option == QL1S("elemhide") && m_isException) { - setOption(RuleOption::ElementHideOption); - ++handledOptions; - } - else if (option == QL1S("collapse")) { - // Hiding placeholders of blocked elements is enabled by default. - ++handledOptions; - } - } - - // If we don't handle all options, it's safer to just disable this rule. - if (handledOptions != options.count()) { - m_isInternalDisabled = true; - m_type = RuleType::Invalid; - return; - } - - parsedLine = parsedLine.left(optionsIndex); - } - - // Rule is classic regexp. - if (parsedLine.startsWith(QL1C('/')) && parsedLine.endsWith(QL1C('/'))) { - parsedLine = parsedLine.mid(1); - parsedLine = parsedLine.left(parsedLine.size() - 1); - m_type = RuleType::RegExpMatchRule; - m_regexPattern = parsedLine; - matchers = createStringMatchers(parseRegExpFilter(parsedLine)); - return; - } - - // Remove starting and ending wildcards (*). - if (parsedLine.startsWith(QL1C('*'))) { - parsedLine = parsedLine.mid(1); - } - - if (parsedLine.endsWith(QL1C('*'))) { - parsedLine = parsedLine.left(parsedLine.size() - 1); - } - - // We can use fast string matching for domain here. - if (filterIsOnlyDomain(parsedLine)) { - parsedLine = parsedLine.mid(2); - parsedLine = parsedLine.left(parsedLine.size() - 1); - m_type = RuleType::DomainMatchRule; - m_matchString = parsedLine; - return; - } - - // If rule contains only | at end, we can also use string matching. - if (filterIsOnlyEndsMatch(parsedLine)) { - parsedLine = parsedLine.left(parsedLine.size() - 1); - m_type = RuleType::StringEndsMatchRule; - m_matchString = parsedLine; - return; - } - - // If we still find a wildcard (*) or separator (^) or (|) - // we must modify parsedLine to comply with SimpleRegExp. - if (parsedLine.contains(QL1C('*')) || parsedLine.contains(QL1C('^')) || parsedLine.contains(QL1C('|'))) { - m_type = RuleType::RegExpMatchRule; - m_regexPattern = createRegExpFromFilter(parsedLine); - matchers = createStringMatchers(parseRegExpFilter(parsedLine)); - return; - } - - // We haven't found anything that needs use of regexp, yay! - m_type = RuleType::StringContainsMatchRule; - m_matchString = parsedLine; -} - -void AdBlockRule::parseDomains(const QString& domains, const QChar& separator) { - QStringList domainsList = domains.split(separator, -#if QT_VERSION >= 0x050F00 // Qt >= 5.15.0 - Qt::SplitBehaviorFlags::SkipEmptyParts); -#else - QString::SplitBehavior::SkipEmptyParts); -#endif - - for (const QString& domain : domainsList) { - if (domain.isEmpty()) { - continue; - } - - if (domain.startsWith(QL1C('~'))) { - m_blockedDomains.append(domain.mid(1)); - } - else { - m_allowedDomains.append(domain); - } - } - - if (!m_blockedDomains.isEmpty() || !m_allowedDomains.isEmpty()) { - setOption(RuleOption::DomainRestrictedOption); - } -} - -bool AdBlockRule::filterIsOnlyDomain(const QString& filter) const { - if (!filter.endsWith(QL1C('^')) || !filter.startsWith(QL1S("||"))) { - return false; - } - - for (auto i : filter) { - switch (i.toLatin1()) { - case '/': - case ':': - case '?': - case '=': - case '&': - case '*': - return false; - - default: - break; - } - } - - return true; -} - -bool AdBlockRule::filterIsOnlyEndsMatch(const QString& filter) const { - for (int i = 0; i < filter.size(); ++i) { - switch (filter.at(i).toLatin1()) { - case '^': - case '*': - return false; - - case '|': - return i == filter.size() - 1; - - default: - break; - } - } - - return false; -} - -static bool wordCharacter(const QChar& c) { - return c.isLetterOrNumber() || c.isMark() || c == QL1C('_'); -} - -QString AdBlockRule::createRegExpFromFilter(const QString& filter) const { - QString parsed; - - parsed.reserve(filter.size()); - bool hadWildcard = false; // Filter multiple wildcards. - - for (int i = 0; i < filter.size(); ++i) { - const QChar c = filter.at(i); - - switch (c.toLatin1()) { - case '^': - parsed.append(QL1S("(?:[^\\w\\d\\-.%]|$)")); - break; - - case '*': - if (!hadWildcard) { - parsed.append(QL1S(".*")); - } - - break; - - case '|': - if (i == 0) { - if (filter.size() > 1 && filter.at(1) == QL1C('|')) { - parsed.append(QL1S("^[\\w\\-]+:\\/+(?!\\/)(?:[^\\/]+\\.)?")); - i++; - } - else { - parsed.append('^'); - } - - break; - } - else if (i == filter.size() - 1) { - parsed.append(QL1C('$')); - break; - } - - [[fallthrough]]; - - default: - if (!wordCharacter(c)) { - parsed.append(QL1C('\\') + c); - } - else { - parsed.append(c); - } - } - - hadWildcard = c == QL1C('*'); - } - - return parsed; -} - -QList AdBlockRule::createStringMatchers(const QStringList& filters) const { - QList mtchrs; - - mtchrs.reserve(filters.size()); - - for (const QString& filter : filters) { - mtchrs.append(QStringMatcher(filter, m_caseSensitivity)); - } - - return mtchrs; -} - -int AdBlockRule::regexMatched(const QString& str, int offset) const { - QRegularExpression exp(m_regexPattern); - - if (m_caseSensitivity == Qt::CaseSensitivity::CaseInsensitive) { - exp.setPatternOptions(exp.patternOptions() | QRegularExpression::PatternOption::CaseInsensitiveOption); - } - - QRegularExpressionMatch m = exp.match(str, offset); - - if (!m.hasMatch()) { - return -1; - } - else { - return m.capturedStart(); - } -} - -bool AdBlockRule::stringMatch(const QString& domain, const QString& encodedUrl) const { - if (m_type == RuleType::StringContainsMatchRule) { - return encodedUrl.contains(m_matchString, m_caseSensitivity); - } - else if (m_type == RuleType::DomainMatchRule) { - return isMatchingDomain(domain, m_matchString); - } - else if (m_type == RuleType::StringEndsMatchRule) { - return encodedUrl.endsWith(m_matchString, m_caseSensitivity); - } - else if (m_type == RuleType::RegExpMatchRule) { - if (!isMatchingRegExpStrings(encodedUrl)) { - return false; - } - else { - return (regexMatched(encodedUrl) != -1); - } - } - - return false; -} - -bool AdBlockRule::matchDomain(const QString& pattern, const QString& domain) const { - if (pattern == domain) { - return true; - } - - if (!domain.endsWith(pattern)) { - return false; - } - - int index = domain.indexOf(pattern); - - return index > 0 && domain[index - 1] == QLatin1Char('.'); -} - -bool AdBlockRule::isMatchingDomain(const QString& domain, const QString& filter) const { - return matchDomain(filter, domain); -} - -bool AdBlockRule::isMatchingRegExpStrings(const QString& url) const { - for (const QStringMatcher& matcher : matchers) { - if (matcher.indexIn(url) == -1) { - return false; - } - } - - return true; -} - -// Split regexp filter into strings that can be used with QString::contains -// Don't use parts that contains only 1 char and duplicated parts. -QStringList AdBlockRule::parseRegExpFilter(const QString& filter) const { - QStringList list; - int startPos = -1; - - for (int i = 0; i < filter.size(); ++i) { - const QChar c = filter.at(i); - - // Meta characters in AdBlock rules are | * ^ - if (c == QL1C('|') || c == QL1C('*') || c == QL1C('^')) { - const QString sub = filter.mid(startPos, i - startPos); - - if (sub.size() > 1) { - list.append(sub); - } - - startPos = i + 1; - } - } - - const QString sub = filter.mid(startPos); - - if (sub.size() > 1) { - list.append(sub); - } - - list.removeDuplicates(); - return list; -} diff --git a/src/librssguard/network-web/adblock/adblockrule.h b/src/librssguard/network-web/adblock/adblockrule.h deleted file mode 100644 index 8b38949f2..000000000 --- a/src/librssguard/network-web/adblock/adblockrule.h +++ /dev/null @@ -1,195 +0,0 @@ -// For license of this file, see /LICENSE.md. - -// -// Copyright (C) 2011-2017 by Martin Rotter -// Copyright (C) 2010-2014 by David Rosca -// -// RSS Guard 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. -// -// RSS Guard 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 RSS Guard. If not, see . - -/** - * Copyright (c) 2009, Benjamin C. Meyer - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Benjamin Meyer nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef ADBLOCKRULE_H -#define ADBLOCKRULE_H - -#include -#include -#include - -class QUrl; -class AdblockRequestInfo; -class AdBlockSubscription; - -class AdBlockRule { - Q_DISABLE_COPY(AdBlockRule) - - public: - explicit AdBlockRule(const QString& filter = QString(), AdBlockSubscription* subscription = nullptr); - virtual ~AdBlockRule() = default; - - AdBlockRule* copy() const; - - AdBlockSubscription* subscription() const; - void setSubscription(AdBlockSubscription* subscription); - - QString filter() const; - void setFilter(const QString& filter); - - bool isCssRule() const; - QString cssSelector() const; - - bool isDocument() const; - bool isElemhide() const; - - bool isDomainRestricted() const; - bool isException() const; - - bool isComment() const; - bool isEnabled() const; - void setEnabled(bool enabled); - - bool isSlow() const; - bool isInternalDisabled() const; - - bool urlMatch(const QUrl& url) const; - bool networkMatch(const AdblockRequestInfo& request, const QString& domain, const QString& encoded_url) const; - - bool matchDomain(const QString& domain) const; - bool matchThirdParty(const AdblockRequestInfo& request) const; - bool matchObject(const AdblockRequestInfo& request) const; - bool matchSubdocument(const AdblockRequestInfo& request) const; - bool matchXmlHttpRequest(const AdblockRequestInfo& request) const; - bool matchImage(const AdblockRequestInfo& request) const; - bool matchScript(const AdblockRequestInfo& request) const; - bool matchStyleSheet(const AdblockRequestInfo& request) const; - bool matchObjectSubrequest(const AdblockRequestInfo& request) const; - - protected: - bool matchDomain(const QString& pattern, const QString& domain) const; - bool stringMatch(const QString& domain, const QString& encodedUrl) const; - bool isMatchingDomain(const QString& domain, const QString& filter) const; - bool isMatchingRegExpStrings(const QString& url) const; - QStringList parseRegExpFilter(const QString& filter) const; - - private: - enum RuleType { - CssRule = 0, - DomainMatchRule = 1, - RegExpMatchRule = 2, - StringEndsMatchRule = 3, - StringContainsMatchRule = 4, - Invalid = 5 - }; - - enum RuleOption { - DomainRestrictedOption = 1, - ThirdPartyOption = 2, - ObjectOption = 4, - SubdocumentOption = 8, - XMLHttpRequestOption = 16, - ImageOption = 32, - ScriptOption = 64, - StyleSheetOption = 128, - ObjectSubrequestOption = 256, - - // Exception only options. - DocumentOption = 1024, - ElementHideOption = 2048 - }; - - Q_DECLARE_FLAGS(RuleOptions, RuleOption) - - bool hasOption(const RuleOption& opt) const; - bool hasException(const RuleOption& opt) const; - void setOption(const RuleOption& opt); - void setException(const RuleOption& opt, bool on); - - void parseFilter(); - void parseDomains(const QString& domains, const QChar& separator); - bool filterIsOnlyDomain(const QString& filter) const; - bool filterIsOnlyEndsMatch(const QString& filter) const; - int regexMatched(const QString& str, int offset = 0) const; - QString createRegExpFromFilter(const QString& filter) const; - QList createStringMatchers(const QStringList& filters) const; - - AdBlockSubscription* m_subscription; - RuleType m_type; - RuleOptions m_options; - RuleOptions m_exceptions; - - // Original rule filter - QString m_filter; - - // Parsed rule for string matching (CSS Selector for CSS rules) - QString m_matchString; - - // Case sensitivity for string matching - Qt::CaseSensitivity m_caseSensitivity; - bool m_isEnabled; - bool m_isException; - bool m_isInternalDisabled; - QStringList m_allowedDomains; - QStringList m_blockedDomains; - QString m_regexPattern; - QList matchers; - - friend class AdBlockMatcher; - friend class AdBlockSearchTree; - friend class AdBlockSubscription; -}; - -inline bool AdBlockRule::hasOption(const AdBlockRule::RuleOption& opt) const { - return (m_options & opt) != 0; -} - -inline bool AdBlockRule::hasException(const AdBlockRule::RuleOption& opt) const { - return (m_exceptions & opt) != 0; -} - -inline void AdBlockRule::setOption(const AdBlockRule::RuleOption& opt) { - m_options |= opt; -} - -inline void AdBlockRule::setException(const AdBlockRule::RuleOption& opt, bool on) { - if (on) { - m_exceptions |= opt; - } -} - -#endif // ADBLOCKRULE_H diff --git a/src/librssguard/network-web/adblock/adblocksearchtree.cpp b/src/librssguard/network-web/adblock/adblocksearchtree.cpp deleted file mode 100644 index cddc4ff3c..000000000 --- a/src/librssguard/network-web/adblock/adblocksearchtree.cpp +++ /dev/null @@ -1,136 +0,0 @@ -// For license of this file, see /LICENSE.md. - -// -// Copyright (C) 2011-2017 by Martin Rotter -// Copyright (C) 2010-2014 by David Rosca -// -// RSS Guard 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. -// -// RSS Guard 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 RSS Guard. If not, see . - -#include "network-web/adblock/adblocksearchtree.h" - -#include "definitions/definitions.h" -#include "network-web/adblock/adblockrequestinfo.h" -#include "network-web/adblock/adblockrule.h" - -AdBlockSearchTree::AdBlockSearchTree() : m_root(new Node) {} - -AdBlockSearchTree::~AdBlockSearchTree() { - deleteNode(m_root); -} - -void AdBlockSearchTree::clear() { - deleteNode(m_root); - m_root = new Node; -} - -bool AdBlockSearchTree::add(const AdBlockRule* rule) { - if (rule->m_type != AdBlockRule::StringContainsMatchRule) { - return false; - } - - const QString filter = rule->m_matchString; - int len = filter.size(); - - if (len <= 0) { - qWarningNN << LOGSEC_ADBLOCK << "Inserting rule with filter len <= 0!"; - return false; - } - - Node* node = m_root; - - for (int i = 0; i < len; ++i) { - const QChar c = filter.at(i); - Node* next = node->children.value(c); - - if (next == nullptr) { - next = new Node; - next->c = c; - node->children[c] = next; - } - - node = next; - } - - node->rule = rule; - return true; -} - -const AdBlockRule* AdBlockSearchTree::find(const AdblockRequestInfo& request, - const QString& domain, - const QString& urlString) const { - int len = urlString.size(); - - if (len <= 0) { - return nullptr; - } - - for (int i = 0; i < len; ++i) { - const AdBlockRule* rule = prefixSearch(request, domain, urlString, urlString.mid(i), len - i); - - if (rule != nullptr) { - return rule; - } - } - - return nullptr; -} - -const AdBlockRule* AdBlockSearchTree::prefixSearch(const AdblockRequestInfo& request, const QString& domain, - const QString& urlString, const QString& choppedUrlString, - int len) const { - if (len <= 0) { - return nullptr; - } - - Node* node = m_root->children.value(choppedUrlString.at(0)); - - if (node == nullptr) { - return nullptr; - } - - for (int i = 1; i < len; ++i) { - const QChar c = choppedUrlString.at(i); - - if ((node->rule != nullptr) && node->rule->networkMatch(request, domain, urlString)) { - return node->rule; - } - - node = node->children.value(c); - - if (node == nullptr) { - return nullptr; - } - } - - if ((node->rule != nullptr) && node->rule->networkMatch(request, domain, urlString)) { - return node->rule; - } - - return nullptr; -} - -void AdBlockSearchTree::deleteNode(AdBlockSearchTree::Node* node) { - if (node == nullptr) { - return; - } - - QHashIterator i(node->children); - - while (i.hasNext()) { - i.next(); - deleteNode(i.value()); - } - - delete node; -} diff --git a/src/librssguard/network-web/adblock/adblocksearchtree.h b/src/librssguard/network-web/adblock/adblocksearchtree.h deleted file mode 100644 index 8ea1b3ecb..000000000 --- a/src/librssguard/network-web/adblock/adblocksearchtree.h +++ /dev/null @@ -1,57 +0,0 @@ -// For license of this file, see /LICENSE.md. - -// -// Copyright (C) 2011-2017 by Martin Rotter -// Copyright (C) 2010-2014 by David Rosca -// -// RSS Guard 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. -// -// RSS Guard 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 RSS Guard. If not, see . - -#ifndef ADBLOCKSEARCHTREE_H -#define ADBLOCKSEARCHTREE_H - -#include -#include - -class AdblockRequestInfo; -class AdBlockRule; - -class AdBlockSearchTree { - public: - explicit AdBlockSearchTree(); - virtual ~AdBlockSearchTree(); - - void clear(); - - bool add(const AdBlockRule* rule); - const AdBlockRule* find(const AdblockRequestInfo& request, const QString& domain, const QString& urlString) const; - - private: - struct Node { - Node() : c(0), rule(0) {} - - QChar c; - const AdBlockRule* rule; - QHash children; - }; - - const AdBlockRule* prefixSearch(const AdblockRequestInfo& request, const QString& domain, - const QString& urlString, const QString& choppedUrlString, - int len) const; - - void deleteNode(Node* node); - - Node* m_root; -}; - -#endif // ADBLOCKSEARCHTREE_H diff --git a/src/librssguard/network-web/adblock/adblocksubscription.cpp b/src/librssguard/network-web/adblock/adblocksubscription.cpp deleted file mode 100644 index 9ab410de0..000000000 --- a/src/librssguard/network-web/adblock/adblocksubscription.cpp +++ /dev/null @@ -1,404 +0,0 @@ -// For license of this file, see /LICENSE.md. - -// -// Copyright (C) 2011-2017 by Martin Rotter -// Copyright (C) 2010-2014 by David Rosca -// -// RSS Guard 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. -// -// RSS Guard 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 RSS Guard. If not, see . - -/** - * Copyright (c) 2009, Benjamin C. Meyer - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Benjamin Meyer nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "network-web/adblock/adblocksubscription.h" - -#include "definitions/definitions.h" -#include "exceptions/applicationexception.h" -#include "miscellaneous/application.h" -#include "miscellaneous/iofactory.h" -#include "network-web/adblock/adblockmanager.h" -#include "network-web/adblock/adblocksearchtree.h" -#include "network-web/silentnetworkaccessmanager.h" -#include "network-web/webfactory.h" - -#include -#include -#include -#include -#include -#include - -AdBlockSubscription::AdBlockSubscription(QString title, QObject* parent) - : QObject(parent), m_reply(nullptr), m_title(std::move(title)), m_updated(false) {} - -QString AdBlockSubscription::title() const { - return m_title; -} - -QString AdBlockSubscription::filePath() const { - return m_filePath; -} - -void AdBlockSubscription::setFilePath(const QString& path) { - m_filePath = path; -} - -QUrl AdBlockSubscription::url() const { - return m_url; -} - -void AdBlockSubscription::setUrl(const QUrl& url) { - m_url = url; -} - -void AdBlockSubscription::loadSubscription(const QStringList& disabledRules) { - QFile file(m_filePath); - - if (!file.exists()) { - QTimer::singleShot(0, this, &AdBlockSubscription::updateSubscription); - return; - } - - if (!file.open(QFile::ReadOnly)) { - qWarningNN << LOGSEC_ADBLOCK - << "Unable to open adblock file" - << QUOTE_W_SPACE(m_filePath) - << "for reading."; - QTimer::singleShot(0, this, &AdBlockSubscription::updateSubscription); - return; - } - - QTextStream textStream(&file); - - textStream.setCodec("UTF-8"); - - // Header is on 3rd line. - textStream.readLine(1024); - textStream.readLine(1024); - QString header = textStream.readLine(1024); - - if (!header.startsWith(QL1S("[Adblock")) || m_title.isEmpty()) { - qWarningNN << LOGSEC_ADBLOCK - << "Invalid format of AdBlock file" - << QUOTE_W_SPACE_DOT(m_filePath); - QTimer::singleShot(0, this, &AdBlockSubscription::updateSubscription); - return; - } - - m_rules.clear(); - - while (!textStream.atEnd()) { - AdBlockRule* rule = new AdBlockRule(textStream.readLine(), this); - - if (disabledRules.contains(rule->filter())) { - rule->setEnabled(false); - } - - m_rules.append(rule); - } - - // Initial update. - if (m_rules.isEmpty() && !m_updated) { - QTimer::singleShot(0, this, &AdBlockSubscription::updateSubscription); - } -} - -void AdBlockSubscription::saveSubscription() {} - -void AdBlockSubscription::updateSubscription() { - if ((m_reply != nullptr) || !m_url.isValid()) { - return; - } - - auto* mgs = new SilentNetworkAccessManager(this); - - m_reply = mgs->get(QNetworkRequest(m_url)); - connect(m_reply, &QNetworkReply::finished, this, &AdBlockSubscription::subscriptionDownloaded); -} - -void AdBlockSubscription::subscriptionDownloaded() { - if (m_reply != qobject_cast(sender())) { - return; - } - - bool error = false; - const QByteArray response = QString::fromUtf8(m_reply->readAll()).toUtf8(); - - if (m_reply->error() != QNetworkReply::NoError || !response.startsWith(QByteArray("[Adblock")) || !saveDownloadedData(response)) { - error = true; - } - - m_reply->manager()->deleteLater(); - m_reply->deleteLater(); - m_reply = nullptr; - - if (error) { - emit subscriptionError(tr("Cannot load subscription!")); - - return; - } - - loadSubscription(qApp->web()->adBlock()->disabledRules()); - emit subscriptionUpdated(); - emit subscriptionChanged(); -} - -bool AdBlockSubscription::saveDownloadedData(const QByteArray& data) { - QSaveFile file(m_filePath); - - if (!file.open(QFile::WriteOnly)) { - qWarningNN << LOGSEC_ADBLOCK - << "Unable to open AdBlock file" - << QUOTE_W_SPACE(m_filePath) - << "for writing."; - return false; - } - else { - // Write subscription header - file.write(QString("Title: %1\nUrl: %2\n").arg(title(), url().toString()).toUtf8()); - file.write(data); - file.commit(); - return true; - } -} - -const AdBlockRule* AdBlockSubscription::rule(int offset) const { - if (IS_IN_ARRAY(offset, m_rules)) { - return m_rules[offset]; - } - else { - return nullptr; - } -} - -QVector AdBlockSubscription::allRules() const { - return m_rules; -} - -const AdBlockRule* AdBlockSubscription::enableRule(int offset) { - if (IS_IN_ARRAY(offset, m_rules)) { - AdBlockRule* rule = m_rules[offset]; - - rule->setEnabled(true); - qApp->web()->adBlock()->removeDisabledRule(rule->filter()); - emit subscriptionChanged(); - - return rule; - } - else { - return nullptr; - } -} - -const AdBlockRule* AdBlockSubscription::disableRule(int offset) { - if (!IS_IN_ARRAY(offset, m_rules)) { - return nullptr; - } - - AdBlockRule* rule = m_rules[offset]; - - rule->setEnabled(false); - qApp->web()->adBlock()->addDisabledRule(rule->filter()); - emit subscriptionChanged(); - - return rule; -} - -bool AdBlockSubscription::canEditRules() const { - return false; -} - -bool AdBlockSubscription::canBeRemoved() const { - return true; -} - -int AdBlockSubscription::addRule(AdBlockRule* rule) { - Q_UNUSED(rule) - return -1; -} - -bool AdBlockSubscription::removeRule(int offset) { - Q_UNUSED(offset) - return false; -} - -const AdBlockRule* AdBlockSubscription::replaceRule(AdBlockRule* rule, int offset) { - Q_UNUSED(rule) - Q_UNUSED(offset) - return nullptr; -} - -AdBlockSubscription::~AdBlockSubscription() { - qDeleteAll(m_rules); -} - -// AdBlockCustomList - -AdBlockCustomList::AdBlockCustomList(QObject* parent) - : AdBlockSubscription(tr("Custom rules"), parent) { - setFilePath(AdBlockManager::storedListsPath() + QDir::separator() + ADBLOCK_CUSTOMLIST_NAME); -} - -void AdBlockCustomList::loadSubscription(const QStringList& disabledRules) { - // DuckDuckGo ad whitelist rules - // They cannot be removed, but can be disabled. - // Please consider not disabling them. Thanks! - const QString ddg1 = QSL("@@||duckduckgo.com^$document"); - const QString ddg2 = QSL("duckduckgo.com#@#.has-ad"); - QString rules; - - try { - rules = QString::fromUtf8(IOFactory::readFile(filePath())); - } - catch (ApplicationException&) {} - - QFile file(filePath()); - - if (!file.exists()) { - saveSubscription(); - } - - if (file.open(QFile::WriteOnly | QFile::Append)) { - QTextStream stream(&file); - - stream.setCodec("UTF-8"); - - if (!rules.contains(ddg1 + QL1C('\n'))) { - stream << ddg1 << QL1C('\n'); - } - - if (!rules.contains(QL1C('\n') + ddg2)) { - stream << ddg2 << QL1C('\n'); - } - } - - file.close(); - AdBlockSubscription::loadSubscription(disabledRules); -} - -void AdBlockCustomList::saveSubscription() { - QFile file(filePath()); - - if (!file.open(QFile::ReadWrite | QFile::Truncate)) { - qWarningNN << LOGSEC_ADBLOCK - << "Unable to open AdBlock file" - << QUOTE_W_SPACE(filePath()) - << "for writing."; - return; - } - - QTextStream textStream(&file); - - textStream.setCodec("UTF-8"); - textStream << "Title: " << title() << QL1C('\n'); - textStream << "Url: " << url().toString() << QL1C('\n'); - textStream << "[Adblock Plus 1.1.1]" << QL1C('\n'); - - for (const AdBlockRule* rule : qAsConst(m_rules)) { - textStream << rule->filter() << QL1C('\n'); - } - - file.close(); -} - -bool AdBlockCustomList::canEditRules() const { - return true; -} - -bool AdBlockCustomList::canBeRemoved() const { - return false; -} - -bool AdBlockCustomList::containsFilter(const QString& filter) const { - for (const AdBlockRule* rule : m_rules) { - if (rule->filter() == filter) { - return true; - } - } - - return false; -} - -bool AdBlockCustomList::removeFilter(const QString& filter) { - for (int i = 0; i < m_rules.count(); ++i) { - const AdBlockRule* rule = m_rules.at(i); - - if (rule->filter() == filter) { - return removeRule(i); - } - } - - return false; -} - -int AdBlockCustomList::addRule(AdBlockRule* rule) { - m_rules.append(rule); - emit subscriptionChanged(); - - return m_rules.count() - 1; -} - -bool AdBlockCustomList::removeRule(int offset) { - if (!IS_IN_ARRAY(offset, m_rules)) { - return false; - } - - AdBlockRule* rule = m_rules.at(offset); - const QString filter = rule->filter(); - - m_rules.remove(offset); - emit subscriptionChanged(); - - qApp->web()->adBlock()->removeDisabledRule(filter); - delete rule; - return true; -} - -const AdBlockRule* AdBlockCustomList::replaceRule(AdBlockRule* rule, int offset) { - if (!IS_IN_ARRAY(offset, m_rules)) { - return nullptr; - } - - AdBlockRule* oldRule = m_rules.at(offset); - - m_rules[offset] = rule; - emit subscriptionChanged(); - - delete oldRule; - return m_rules[offset]; -} diff --git a/src/librssguard/network-web/adblock/adblocksubscription.h b/src/librssguard/network-web/adblock/adblocksubscription.h deleted file mode 100644 index 3eefce3cf..000000000 --- a/src/librssguard/network-web/adblock/adblocksubscription.h +++ /dev/null @@ -1,134 +0,0 @@ -// For license of this file, see /LICENSE.md. - -// -// Copyright (C) 2011-2017 by Martin Rotter -// Copyright (C) 2010-2014 by David Rosca -// -// RSS Guard 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. -// -// RSS Guard 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 RSS Guard. If not, see . - -/** - * Copyright (c) 2009, Benjamin C. Meyer - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Benjamin Meyer nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef ADBLOCKSUBSCRIPTION_H -#define ADBLOCKSUBSCRIPTION_H - -#include -#include - -#include "network-web/adblock/adblockrule.h" -#include "network-web/adblock/adblocksearchtree.h" - -class QUrl; -class QNetworkReply; - -class AdBlockSubscription : public QObject { - Q_OBJECT - - public: - explicit AdBlockSubscription(QString title, QObject* parent = nullptr); - virtual ~AdBlockSubscription(); - - QString title() const; - - QString filePath() const; - void setFilePath(const QString& path); - - QUrl url() const; - void setUrl(const QUrl& url); - - const AdBlockRule* rule(int offset) const; - - QVector allRules() const; - - const AdBlockRule* enableRule(int offset); - const AdBlockRule* disableRule(int offset); - virtual void loadSubscription(const QStringList& disabledRules); - virtual void saveSubscription(); - virtual bool canEditRules() const; - virtual bool canBeRemoved() const; - virtual int addRule(AdBlockRule* rule); - virtual bool removeRule(int offset); - virtual const AdBlockRule* replaceRule(AdBlockRule* rule, int offset); - - public slots: - void updateSubscription(); - - signals: - void subscriptionChanged(); - void subscriptionUpdated(); - void subscriptionError(const QString& message); - - protected slots: - void subscriptionDownloaded(); - - protected: - virtual bool saveDownloadedData(const QByteArray& data); - - protected: - QNetworkReply* m_reply; - QVector m_rules; - - private: - QString m_title; - QString m_filePath; - QUrl m_url; - bool m_updated; -}; - -class AdBlockCustomList : public AdBlockSubscription { - Q_OBJECT - - public: - explicit AdBlockCustomList(QObject* parent = nullptr); - - void loadSubscription(const QStringList& disabledRules); - void saveSubscription(); - - bool canEditRules() const; - bool canBeRemoved() const; - - bool containsFilter(const QString& filter) const; - bool removeFilter(const QString& filter); - - int addRule(AdBlockRule* rule); - bool removeRule(int offset); - const AdBlockRule* replaceRule(AdBlockRule* rule, int offset); -}; - -#endif // ADBLOCKSUBSCRIPTION_H diff --git a/src/librssguard/network-web/adblock/adblocktreewidget.cpp b/src/librssguard/network-web/adblock/adblocktreewidget.cpp deleted file mode 100644 index 823b16b18..000000000 --- a/src/librssguard/network-web/adblock/adblocktreewidget.cpp +++ /dev/null @@ -1,258 +0,0 @@ -// For license of this file, see /LICENSE.md. - -// -// Copyright (C) 2011-2017 by Martin Rotter -// Copyright (C) 2010-2014 by David Rosca -// -// RSS Guard 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. -// -// RSS Guard 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 RSS Guard. If not, see . - -#include "network-web/adblock/adblocktreewidget.h" - -#include "network-web/adblock/adblocksubscription.h" - -#include -#include -#include -#include -#include - -AdBlockTreeWidget::AdBlockTreeWidget(AdBlockSubscription* subscription, QWidget* parent) - : TreeWidget(parent), m_subscription(subscription), m_topItem(nullptr), m_itemChangingBlock(false) { - setContextMenuPolicy(Qt::ContextMenuPolicy::CustomContextMenu); - setDefaultItemShowMode(TreeWidget::ItemShowMode::ItemsExpanded); - setHeaderHidden(true); - setAlternatingRowColors(true); - setLayoutDirection(Qt::LayoutDirection::LeftToRight); - setIndentation(5); - - connect(this, &QWidget::customContextMenuRequested, this, &AdBlockTreeWidget::contextMenuRequested); - connect(this, &QTreeWidget::itemChanged, this, &AdBlockTreeWidget::itemChanged); - connect(m_subscription, &AdBlockSubscription::subscriptionUpdated, this, &AdBlockTreeWidget::subscriptionUpdated); - connect(m_subscription, &AdBlockSubscription::subscriptionError, this, &AdBlockTreeWidget::subscriptionError); -} - -AdBlockSubscription* AdBlockTreeWidget::subscription() const { - return m_subscription; -} - -void AdBlockTreeWidget::showRule(const AdBlockRule* rule) { - if ((m_topItem == nullptr) && (rule != nullptr)) { - m_ruleToBeSelected = rule->filter(); - } - else if (!m_ruleToBeSelected.isEmpty()) { - QList items = findItems(m_ruleToBeSelected, Qt::MatchFlag::MatchRecursive); - - if (!items.isEmpty()) { - QTreeWidgetItem* item = items.at(0); - - setCurrentItem(item); - scrollToItem(item, QAbstractItemView::ScrollHint::PositionAtCenter); - } - - m_ruleToBeSelected.clear(); - } -} - -void AdBlockTreeWidget::contextMenuRequested(const QPoint& pos) { - if (!m_subscription->canEditRules()) { - return; - } - - QTreeWidgetItem* item = itemAt(pos); - - if (item == nullptr) { - return; - } - - QMenu menu; - - menu.addAction(tr("Add rule"), this, &AdBlockTreeWidget::addRule); - menu.addSeparator(); - QAction* deleteAction = menu.addAction(tr("Remove rule"), this, &AdBlockTreeWidget::removeRule); - - if (item->parent() == nullptr) { - deleteAction->setDisabled(true); - } - - menu.exec(viewport()->mapToGlobal(pos)); -} - -void AdBlockTreeWidget::itemChanged(QTreeWidgetItem* item) { - if ((item == nullptr) || m_itemChangingBlock) { - return; - } - - m_itemChangingBlock = true; - int offset = item->data(0, Qt::UserRole + 10).toInt(); - const AdBlockRule* oldRule = m_subscription->rule(offset); - - if (item->checkState(0) == Qt::Unchecked && oldRule->isEnabled()) { - // Disable rule. - const AdBlockRule* rule = m_subscription->disableRule(offset); - - adjustItemFeatures(item, rule); - } - else if (item->checkState(0) == Qt::Checked && !oldRule->isEnabled()) { - // Enable rule. - const AdBlockRule* rule = m_subscription->enableRule(offset); - - adjustItemFeatures(item, rule); - } - else if (m_subscription->canEditRules()) { - // Custom rule has been changed. - AdBlockRule* newRule = new AdBlockRule(item->text(0), m_subscription); - const AdBlockRule* rule = m_subscription->replaceRule(newRule, offset); - - adjustItemFeatures(item, rule); - } - - m_itemChangingBlock = false; -} - -void AdBlockTreeWidget::copyFilter() { - QTreeWidgetItem* item = currentItem(); - - if (item == nullptr) { - return; - } - - QApplication::clipboard()->setText(item->text(0)); -} - -void AdBlockTreeWidget::addRule() { - if (!m_subscription->canEditRules()) { - return; - } - - QString newRule = QInputDialog::getText(this, tr("Add custom rule"), tr("Please write your rule here:")); - - if (newRule.isEmpty()) { - return; - } - - auto* rule = new AdBlockRule(newRule, m_subscription); - int offset = m_subscription->addRule(rule); - auto* item = new QTreeWidgetItem(); - - item->setText(0, newRule); - item->setData(0, Qt::ItemDataRole::UserRole + 10, offset); - item->setFlags(item->flags() | Qt::ItemFlag::ItemIsEditable); - m_itemChangingBlock = true; - m_topItem->addChild(item); - m_itemChangingBlock = false; - adjustItemFeatures(item, rule); -} - -void AdBlockTreeWidget::removeRule() { - QTreeWidgetItem* item = currentItem(); - - if ((item == nullptr) || !m_subscription->canEditRules() || item == m_topItem) { - return; - } - - int offset = item->data(0, Qt::ItemDataRole::UserRole + 10).toInt(); - - m_subscription->removeRule(offset); - deleteItem(item); -} - -void AdBlockTreeWidget::subscriptionUpdated() { - refresh(); - m_itemChangingBlock = true; - m_topItem->setText(0, tr("%1 (recently updated)").arg(m_subscription->title())); - m_itemChangingBlock = false; -} - -void AdBlockTreeWidget::subscriptionError(const QString& message) { - refresh(); - m_itemChangingBlock = true; - m_topItem->setText(0, tr("%1 (error: %2)").arg(m_subscription->title(), message)); - m_itemChangingBlock = false; -} - -void AdBlockTreeWidget::adjustItemFeatures(QTreeWidgetItem* item, const AdBlockRule* rule) { - if (!rule->isEnabled()) { - QFont font; - - font.setItalic(true); - item->setForeground(0, QColor(Qt::GlobalColor::gray)); - - if (!rule->isComment()) { - item->setFlags(item->flags() | Qt::ItemFlag::ItemIsUserCheckable); - item->setCheckState(0, Qt::CheckState::Unchecked); - item->setFont(0, font); - } - } - else { - item->setFlags(item->flags() | Qt::ItemFlag::ItemIsUserCheckable); - item->setCheckState(0, Qt::CheckState::Checked); - - if (rule->isException()) { - item->setForeground(0, QColor(Qt::GlobalColor::darkGreen)); - item->setFont(0, QFont()); - } - else if (rule->isCssRule()) { - item->setForeground(0, QColor(Qt::GlobalColor::darkBlue)); - item->setFont(0, QFont()); - } - else { - item->setForeground(0, QColor(Qt::GlobalColor::black)); - item->setFont(0, QFont()); - } - } -} - -void AdBlockTreeWidget::keyPressEvent(QKeyEvent* event) { - if (event->key() == Qt::Key::Key_C && (event->modifiers() & Qt::KeyboardModifier::ControlModifier) != 0) { - copyFilter(); - } - - if (event->key() == Qt::Key::Key_Delete) { - removeRule(); - } - - TreeWidget::keyPressEvent(event); -} - -void AdBlockTreeWidget::refresh() { - m_itemChangingBlock = true; - clear(); - QFont boldFont; - - boldFont.setBold(true); - m_topItem = new QTreeWidgetItem(this); - m_topItem->setText(0, m_subscription->title()); - m_topItem->setFont(0, boldFont); - m_topItem->setExpanded(true); - addTopLevelItem(m_topItem); - const QVector& allRules = m_subscription->allRules(); - int index = 0; - - for (const AdBlockRule* rule : allRules) { - auto* item = new QTreeWidgetItem(m_topItem); - - item->setText(0, rule->filter()); - item->setData(0, Qt::ItemDataRole::UserRole + 10, index); - - if (m_subscription->canEditRules()) { - item->setFlags(item->flags() | Qt::ItemFlag::ItemIsEditable); - } - - adjustItemFeatures(item, rule); - ++index; - } - - showRule(nullptr); - m_itemChangingBlock = false; -} diff --git a/src/librssguard/network-web/adblock/adblocktreewidget.h b/src/librssguard/network-web/adblock/adblocktreewidget.h deleted file mode 100644 index cb10185aa..000000000 --- a/src/librssguard/network-web/adblock/adblocktreewidget.h +++ /dev/null @@ -1,63 +0,0 @@ -// For license of this file, see /LICENSE.md. - -// -// Copyright (C) 2011-2017 by Martin Rotter -// Copyright (C) 2010-2014 by David Rosca -// -// RSS Guard 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. -// -// RSS Guard 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 RSS Guard. If not, see . - -#ifndef ADBLOCKTREEWIDGET_H -#define ADBLOCKTREEWIDGET_H - -#include "gui/reusable/treewidget.h" - -class AdBlockSubscription; -class AdBlockRule; - -class AdBlockTreeWidget : public TreeWidget { - Q_OBJECT - - public: - explicit AdBlockTreeWidget(AdBlockSubscription* subscription, QWidget* parent = nullptr); - - AdBlockSubscription* subscription() const; - - void showRule(const AdBlockRule* rule); - void refresh(); - - public slots: - void addRule(); - void removeRule(); - - private slots: - void contextMenuRequested(const QPoint& pos); - void itemChanged(QTreeWidgetItem* item); - void copyFilter(); - - void subscriptionUpdated(); - void subscriptionError(const QString& message); - - protected: - virtual void keyPressEvent(QKeyEvent* event); - - private: - void adjustItemFeatures(QTreeWidgetItem* item, const AdBlockRule* rule); - - AdBlockSubscription* m_subscription; - QTreeWidgetItem* m_topItem; - QString m_ruleToBeSelected; - bool m_itemChangingBlock; -}; - -#endif // ADBLOCKTREEWIDGET_H diff --git a/src/librssguard/network-web/adblock/adblockurlinterceptor.cpp b/src/librssguard/network-web/adblock/adblockurlinterceptor.cpp index c287aacd4..ee26e0a00 100644 --- a/src/librssguard/network-web/adblock/adblockurlinterceptor.cpp +++ b/src/librssguard/network-web/adblock/adblockurlinterceptor.cpp @@ -27,7 +27,7 @@ AdBlockUrlInterceptor::AdBlockUrlInterceptor(AdBlockManager* manager) : UrlInterceptor(manager), m_manager(manager) {} void AdBlockUrlInterceptor::interceptRequest(QWebEngineUrlRequestInfo& info) { - if (m_manager->block(AdblockRequestInfo(info)) != nullptr) { + if (m_manager->block(AdblockRequestInfo(info))) { info.block(true); qWarningNN << LOGSEC_ADBLOCK << "Blocked request:" << QUOTE_W_SPACE_DOT(info.requestUrl().toString()); diff --git a/src/librssguard/network-web/webpage.cpp b/src/librssguard/network-web/webpage.cpp index 28ee7e3fb..0d6cf8f42 100644 --- a/src/librssguard/network-web/webpage.cpp +++ b/src/librssguard/network-web/webpage.cpp @@ -7,8 +7,6 @@ #include "miscellaneous/application.h" #include "network-web/adblock/adblockmanager.h" #include "network-web/adblock/adblockrequestinfo.h" -#include "network-web/adblock/adblockrule.h" -#include "network-web/adblock/adblocksubscription.h" #include "network-web/webfactory.h" #include "services/abstract/rootitem.h" #include "services/abstract/serviceroot.h" @@ -34,16 +32,7 @@ void WebPage::hideUnwantedElements() { return; } - auto css = qApp->web()->adBlock()->elementHidingRules(url()); - - if (!css.isEmpty()) { - auto js = qApp->web()->adBlock()->generateJsForElementHiding(css); - - runJavaScript(js); - qDebugNN << LOGSEC_JS << "Running global JS for element hiding rules."; - } - - css = qApp->web()->adBlock()->elementHidingRulesForDomain(url()); + auto css = qApp->web()->adBlock()->elementHidingRulesForDomain(url()); if (!css.isEmpty()) { auto js = qApp->web()->adBlock()->generateJsForElementHiding(css); @@ -57,11 +46,11 @@ bool WebPage::acceptNavigationRequest(const QUrl& url, NavigationType type, bool const RootItem* root = view()->root(); if (is_main_frame) { - auto* adblock_rule = qApp->web()->adBlock()->block(AdblockRequestInfo(url)); + auto blocked = qApp->web()->adBlock()->block(AdblockRequestInfo(url)); - if (adblock_rule != nullptr) { + if (blocked) { // This website is entirely blocked. - setHtml(qApp->skins()->adBlockedPage(adblock_rule->subscription()->title(), adblock_rule->filter()), + setHtml(qApp->skins()->adBlockedPage(url.toString()), QUrl::fromUserInput(INTERNAL_URL_ADBLOCKED)); return false; }