diff --git a/plugins/messageviewer/bodypartformatter/calendar/memorycalendarmemento.cpp b/plugins/messageviewer/bodypartformatter/calendar/memorycalendarmemento.cpp index 2d80bb05..c5c870a0 100644 --- a/plugins/messageviewer/bodypartformatter/calendar/memorycalendarmemento.cpp +++ b/plugins/messageviewer/bodypartformatter/calendar/memorycalendarmemento.cpp @@ -1,76 +1,76 @@ /* Copyright (C) 2010 Klarälvdalens Datakonsult AB, a KDAB Group company Author: Sérgio Martins This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License or (at your option) version 3 or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), which shall act as a proxy defined in Section 14 of version 3 of the license. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see . + along with this program. If not, see . */ #include "memorycalendarmemento.h" #include #include #include #include "text_calendar_debug.h" using namespace MessageViewer; using namespace Akonadi; MemoryCalendarMemento::MemoryCalendarMemento() : QObject(nullptr) , mFinished(false) { Akonadi::ETMCalendar::Ptr etmCalendar = CalendarSupport::calendarSingleton(/*createIfNull=*/ false); if (etmCalendar && etmCalendar->isLoaded()) { // Good, either korganizer or kontact summary view are already running, so reuse ETM to save memory mCalendar = etmCalendar; QMetaObject::invokeMethod(this, "finalize", Qt::QueuedConnection); } else { FetchJobCalendar::Ptr calendar = FetchJobCalendar::Ptr(new FetchJobCalendar(this)); mCalendar = calendar; connect(calendar.data(), &FetchJobCalendar::loadFinished, this, &MemoryCalendarMemento::slotCalendarLoaded); } } void MemoryCalendarMemento::slotCalendarLoaded(bool success, const QString &errorMessage) { qCDebug(TEXT_CALENDAR_LOG) << "MemoryCalendarMemento::slotCalendarLoaded: " << success; if (!success) { qCWarning(TEXT_CALENDAR_LOG) << "Unable to fetch incidences:" << errorMessage; } finalize(); } void MemoryCalendarMemento::finalize() { mFinished = true; Q_EMIT update(MimeTreeParser::Delayed); } bool MemoryCalendarMemento::finished() const { return mFinished; } Akonadi::CalendarBase::Ptr MemoryCalendarMemento::calendar() const { Q_ASSERT(mFinished); return mCalendar; } void MemoryCalendarMemento::detach() { disconnect(this, &MemoryCalendarMemento::update, nullptr, nullptr); } diff --git a/plugins/messageviewer/bodypartformatter/calendar/memorycalendarmemento.h b/plugins/messageviewer/bodypartformatter/calendar/memorycalendarmemento.h index e5804ca4..f48f877c 100644 --- a/plugins/messageviewer/bodypartformatter/calendar/memorycalendarmemento.h +++ b/plugins/messageviewer/bodypartformatter/calendar/memorycalendarmemento.h @@ -1,55 +1,55 @@ /* Copyright (C) 2010 Klarälvdalens Datakonsult AB, a KDAB Group company Author: Sérgio Martins This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License or (at your option) version 3 or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), which shall act as a proxy defined in Section 14 of version 3 of the license. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see . + along with this program. If not, see . */ #ifndef MEMORYCALENDARMEMENTO_H #define MEMORYCALENDARMEMENTO_H #include #include #include #include namespace MessageViewer { class MemoryCalendarMemento : public QObject, public MimeTreeParser::Interface::BodyPartMemento { Q_OBJECT public: MemoryCalendarMemento(); bool finished() const; Akonadi::CalendarBase::Ptr calendar() const; void detach() override; Q_SIGNALS: // TODO: Factor our update and detach into base class void update(MimeTreeParser::UpdateMode); private Q_SLOTS: void finalize(); private: void slotCalendarLoaded(bool success, const QString &errorMessage); bool mFinished = false; Akonadi::CalendarBase::Ptr mCalendar; }; } #endif diff --git a/plugins/plasma/pimeventsplugin/PimEventsConfig.qml b/plugins/plasma/pimeventsplugin/PimEventsConfig.qml index 142d1185..41ac8b4c 100644 --- a/plugins/plasma/pimeventsplugin/PimEventsConfig.qml +++ b/plugins/plasma/pimeventsplugin/PimEventsConfig.qml @@ -1,112 +1,112 @@ /* * Copyright 2016 Daniel Vrátil * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License or (at your option) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program. If not, see + * along with this program. If not, see */ import QtQuick 2.0 import QtQuick.Controls 1.4 // gives us TextSingleton import QtQuick.Controls.Private 1.0 import QtQuick.Layouts 1.0 import QtQuick.Dialogs 1.1 import org.kde.plasma.core 2.0 import org.kde.plasma.PimCalendars 1.0 Item { id: pimEventsConfig width: parent.width height: parent.height signal configurationChanged function saveConfig() { calendarModel.saveConfig(); } PimCalendarsModel { id: calendarModel } // Invisible, used to measure implicitHeight of checkboxes so we can // adjust row height in rowDelegate CheckBox { id: checkboxSize visible: false } TreeView { id: calendarTreeView; anchors.fill: parent model: calendarModel TableViewColumn { role: "data" title: i18n("Select Calendars"); delegate: Item { CheckBox { id: checkbox visible: styleData.value["enabled"] checked: styleData.value["checked"] onCheckedChanged: { if (checked === styleData.value["checked"]) { return; } calendarModel.setChecked(styleData.value["id"], checked); pimEventsConfig.configurationChanged(); } width: 24 height: 24 } IconItem { id: icon anchors.left: checkbox.visible ? checkbox.right : parent.left visible: valid source: styleData.value["iconName"] height: 20 width: 20 } Text { anchors.left: icon.visible ? icon.right : checkbox.visible ? checkbox.right : parent.left text: styleData.value["name"] horizontalAlignment: Qt.AlignLeft verticalAlignment: Qt.AlignVCenter color: styleData.textColor height: 24 } } } // Based on Desktop.TableViewStyle rowDelegate: BorderImage { visible: styleData.selected || styleData.alternate source: "image://__tablerow/" + (styleData.alternate ? "alternate_" : "") + (styleData.selected ? "selected_" : "") + (calendarTreeView.activeFocus ? "active" : "") // Make sure the checkbox always fits, add 4 for some small margin height: Math.min(checkboxSize.implicitHeight, Math.max(16, TextSingleton.implicitHeight * 1.2)) + 4 border { left: 4 right: 4 } } } } diff --git a/plugins/webengineurlinterceptor/adblock/lib/adblockmatcher.cpp b/plugins/webengineurlinterceptor/adblock/lib/adblockmatcher.cpp index af6b3069..5b0adbc5 100644 --- a/plugins/webengineurlinterceptor/adblock/lib/adblockmatcher.cpp +++ b/plugins/webengineurlinterceptor/adblock/lib/adblockmatcher.cpp @@ -1,262 +1,262 @@ /* Copyright (C) 2016-2018 Montel Laurent This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* ============================================================ * QupZilla - WebKit based browser * Copyright (C) 2014 David Rosca * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License -* along with this program. If not, see . +* along with this program. If not, see . * ============================================================ */ #include "adblockmatcher.h" #include "adblockmanager.h" #include "adblockrule.h" #include "adblocksubscription.h" using namespace AdBlock; AdBlockMatcher::AdBlockMatcher(AdblockManager *manager) : QObject(manager) , m_manager(manager) { connect(manager, &AdblockManager::enabledChanged, this, &AdBlockMatcher::enabledChanged); } AdBlockMatcher::~AdBlockMatcher() { clear(); } const AdBlockRule *AdBlockMatcher::match(const QWebEngineUrlRequestInfo &request, const QString &urlDomain, const QString &urlString) const { // Exception rules if (m_networkExceptionTree.find(request, urlDomain, urlString)) { 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 { 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; } const 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; const 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(QLatin1String("{display:none !important;}\n")); addedRulesCount = 0; } else { rules.append(rule->cssSelector() + QLatin1Char(',')); addedRulesCount++; } } if (addedRulesCount != 0) { rules = rules.left(rules.size() - 1); rules.append(QLatin1String("{display:none !important;}\n")); } return rules; } bool AdBlockMatcher::isEnabled() const { return m_enabled; } void AdBlockMatcher::update() { clear(); QHash cssRulesHash; QVector exceptionCssRules; Q_FOREACH (AdBlockSubscription *subscription, m_manager->subscriptions()) { Q_FOREACH (const AdBlockRule *rule, subscription->allRules()) { // 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); } } } } foreach (const AdBlockRule *rule, exceptionCssRules) { const AdBlockRule *originalRule = cssRulesHash.value(rule->cssSelector()); // If we don't have this selector, the exception does nothing if (!originalRule) { continue; } AdBlockRule *copiedRule = originalRule->copy(); copiedRule->m_options |= AdBlockRule::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(QStringLiteral("{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(QLatin1String("{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(); } void AdBlockMatcher::enabledChanged(bool enabled) { m_enabled = enabled; if (m_enabled) { update(); } else { clear(); } } diff --git a/plugins/webengineurlinterceptor/adblock/lib/adblockmatcher.h b/plugins/webengineurlinterceptor/adblock/lib/adblockmatcher.h index 050fc582..8645a2df 100644 --- a/plugins/webengineurlinterceptor/adblock/lib/adblockmatcher.h +++ b/plugins/webengineurlinterceptor/adblock/lib/adblockmatcher.h @@ -1,89 +1,89 @@ /* Copyright (C) 2016-2018 Montel Laurent This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* ============================================================ * QupZilla - WebKit based browser * Copyright (C) 2014 David Rosca * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License -* along with this program. If not, see . +* along with this program. If not, see . * ============================================================ */ #ifndef ADBLOCKMATCHER_H #define ADBLOCKMATCHER_H #include #include #include #include "adblockrule.h" #include "adblocksearchtree.h" class QWebEngineUrlRequestInfo; namespace AdBlock { class AdblockManager; class AdBlockMatcher : public QObject { Q_OBJECT public: explicit AdBlockMatcher(AdblockManager *manager); ~AdBlockMatcher(); const AdBlockRule *match(const QWebEngineUrlRequestInfo &request, const QString &urlDomain, const QString &urlString) const; bool adBlockDisabledForUrl(const QUrl &url) const; bool elemHideDisabledForUrl(const QUrl &url) const; QString elementHidingRules() const; QString elementHidingRulesForDomain(const QString &domain) const; bool isEnabled() const; public Q_SLOTS: void update(); void clear(); private: void enabledChanged(bool enabled); AdblockManager *m_manager = nullptr; 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; bool m_enabled = false; }; } #endif // ADBLOCKMATCHER_H diff --git a/plugins/webengineurlinterceptor/adblock/lib/adblockregexp.cpp b/plugins/webengineurlinterceptor/adblock/lib/adblockregexp.cpp index 56d11582..62bee6d5 100644 --- a/plugins/webengineurlinterceptor/adblock/lib/adblockregexp.cpp +++ b/plugins/webengineurlinterceptor/adblock/lib/adblockregexp.cpp @@ -1,100 +1,100 @@ /* Copyright (c) 2016-2018 Montel Laurent * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License -* along with this program. If not, see . +* along with this program. If not, see . */ /* ============================================================ * QupZilla - WebKit based browser * Copyright (C) 2013-2014 David Rosca * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License -* along with this program. If not, see . +* along with this program. If not, see . * ============================================================ */ #include "adblockregexp.h" #include "adblockutil.h" using namespace AdBlock; AdblockRegExp::AdblockRegExp() : QRegularExpression(QString(), QRegularExpression::DotMatchesEverythingOption) , m_matchedLength(-1) { } AdblockRegExp::AdblockRegExp(const QString &pattern, Qt::CaseSensitivity cs) : QRegularExpression(pattern, QRegularExpression::DotMatchesEverythingOption) , m_matchedLength(-1) { if (cs == Qt::CaseInsensitive) { setPatternOptions(patternOptions() | QRegularExpression::CaseInsensitiveOption); } } AdblockRegExp::AdblockRegExp(const AdblockRegExp &re) : QRegularExpression(re) , m_matchedLength(-1) { } void AdblockRegExp::setMinimal(bool minimal) { QRegularExpression::PatternOptions opt; if (minimal) { opt = patternOptions() | QRegularExpression::InvertedGreedinessOption; } else { opt = patternOptions() & ~QRegularExpression::InvertedGreedinessOption; } setPatternOptions(opt); } int AdblockRegExp::indexIn(const QString &str, int offset) const { AdblockRegExp *that = const_cast(this); QRegularExpressionMatch m = match(str, offset); if (!m.hasMatch()) { that->m_matchedLength = -1; that->m_capturedTexts.clear(); return -1; } that->m_matchedLength = m.capturedLength(); that->m_capturedTexts = m.capturedTexts(); return m.capturedStart(); } int AdblockRegExp::matchedLength() const { return m_matchedLength; } QString AdblockRegExp::cap(int nth) const { if (!AdblockUtil::containsIndex(m_capturedTexts, nth)) { return QString(); } return m_capturedTexts.at(nth); } diff --git a/plugins/webengineurlinterceptor/adblock/lib/adblockregexp.h b/plugins/webengineurlinterceptor/adblock/lib/adblockregexp.h index 52f7ab29..a6e2f80e 100644 --- a/plugins/webengineurlinterceptor/adblock/lib/adblockregexp.h +++ b/plugins/webengineurlinterceptor/adblock/lib/adblockregexp.h @@ -1,57 +1,57 @@ /* Copyright (c) 2016-2018 Montel Laurent * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License -* along with this program. If not, see . +* along with this program. If not, see . */ /* ============================================================ * QupZilla - WebKit based browser * Copyright (C) 2013-2014 David Rosca * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License -* along with this program. If not, see . +* along with this program. If not, see . * ============================================================ */ #ifndef ADBLOCKREGEXP_H #define ADBLOCKREGEXP_H #include #include namespace AdBlock { class AdblockRegExp : public QRegularExpression { public: AdblockRegExp(); AdblockRegExp(const QString &pattern, Qt::CaseSensitivity cs = Qt::CaseSensitive); AdblockRegExp(const AdblockRegExp &re); void setMinimal(bool minimal); int indexIn(const QString &str, int offset = 0) const; int matchedLength() const; QString cap(int nth = 0) const; private: QStringList m_capturedTexts; int m_matchedLength; }; } #endif diff --git a/plugins/webengineurlinterceptor/adblock/lib/adblockrule.cpp b/plugins/webengineurlinterceptor/adblock/lib/adblockrule.cpp index ebe77e5a..f8c7cf64 100644 --- a/plugins/webengineurlinterceptor/adblock/lib/adblockrule.cpp +++ b/plugins/webengineurlinterceptor/adblock/lib/adblockrule.cpp @@ -1,759 +1,759 @@ /* Copyright (c) 2016-2018 Montel Laurent * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License -* along with this program. If not, see . +* along with this program. If not, see . */ /* ============================================================ * QupZilla - WebKit based browser * Copyright (C) 2010-2014 David Rosca * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License -* along with this program. If not, see . +* along with this program. 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 "adblockrule.h" #include "adblocksubscription.h" #include "adblockutil.h" #include "adblockregexp.h" #include #include #include #include using namespace AdBlock; static QString toSecondLevelDomain(const QUrl &url) { const QString topLevelDomain = url.topLevelDomain(); const QString urlHost = url.host(); if (topLevelDomain.isEmpty() || urlHost.isEmpty()) { return QString(); } QString domain = urlHost.left(urlHost.size() - topLevelDomain.size()); if (domain.count(QLatin1Char('.')) == 0) { return urlHost; } while (domain.count(QLatin1Char('.')) != 0) { domain = domain.mid(domain.indexOf(QLatin1Char('.')) + 1); } return domain + topLevelDomain; } 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) , m_regExp(nullptr) { setFilter(filter); } AdBlockRule::~AdBlockRule() { delete m_regExp; } 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; if (m_regExp) { rule->m_regExp = new RegExp; rule->m_regExp->regExp = m_regExp->regExp; rule->m_regExp->matchers = m_regExp->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(QLatin1Char('!')); } bool AdBlockRule::isEnabled() const { return m_isEnabled; } void AdBlockRule::setEnabled(bool enabled) { m_isEnabled = enabled; } bool AdBlockRule::isSlow() const { return m_regExp != nullptr; } bool AdBlockRule::isInternalDisabled() const { return m_isInternalDisabled; } bool AdBlockRule::urlMatch(const QUrl &url) const { if (!hasOption(DocumentOption) && !hasOption(ElementHideOption)) { return false; } const QString encodedUrl = QString::fromLatin1(url.toEncoded()); const QString domain = url.host(); return stringMatch(domain, encodedUrl); } bool AdBlockRule::networkMatch(const QWebEngineUrlRequestInfo &request, const QString &domain, const QString &encodedUrl) const { if (m_type == CssRule || !m_isEnabled || m_isInternalDisabled) { return false; } bool matched = stringMatch(domain, encodedUrl); 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()) { foreach (const QString &d, m_allowedDomains) { if (isMatchingDomain(domain, d)) { return true; } } } else if (m_allowedDomains.isEmpty()) { foreach (const QString &d, m_blockedDomains) { if (isMatchingDomain(domain, d)) { return false; } } return true; } else { foreach (const QString &d, m_blockedDomains) { if (isMatchingDomain(domain, d)) { return false; } } foreach (const QString &d, m_allowedDomains) { if (isMatchingDomain(domain, d)) { return true; } } } return false; } bool AdBlockRule::matchThirdParty(const QWebEngineUrlRequestInfo &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 QWebEngineUrlRequestInfo &request) const { bool match = request.resourceType() == QWebEngineUrlRequestInfo::ResourceTypeObject; return hasException(ObjectOption) ? !match : match; } bool AdBlockRule::matchSubdocument(const QWebEngineUrlRequestInfo &request) const { bool match = request.resourceType() == QWebEngineUrlRequestInfo::ResourceTypeSubFrame; return hasException(SubdocumentOption) ? !match : match; } bool AdBlockRule::matchXmlHttpRequest(const QWebEngineUrlRequestInfo &request) const { bool match = request.resourceType() == QWebEngineUrlRequestInfo::ResourceTypeXhr; return hasException(XMLHttpRequestOption) ? !match : match; } bool AdBlockRule::matchImage(const QWebEngineUrlRequestInfo &request) const { bool match = request.resourceType() == QWebEngineUrlRequestInfo::ResourceTypeImage; return hasException(ImageOption) ? !match : match; } bool AdBlockRule::matchScript(const QWebEngineUrlRequestInfo &request) const { bool match = request.resourceType() == QWebEngineUrlRequestInfo::ResourceTypeScript; return hasException(ScriptOption) ? !match : match; } bool AdBlockRule::matchStyleSheet(const QWebEngineUrlRequestInfo &request) const { bool match = request.resourceType() == QWebEngineUrlRequestInfo::ResourceTypeStylesheet; return hasException(StyleSheetOption) ? !match : match; } bool AdBlockRule::matchObjectSubrequest(const QWebEngineUrlRequestInfo &request) const { bool match = request.resourceType() == QWebEngineUrlRequestInfo::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(QLatin1Char('!'))) { // 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(QLatin1String("##")) || parsedLine.contains(QLatin1String("#@#"))) { m_type = CssRule; int pos = parsedLine.indexOf(QLatin1Char('#')); // Domain restricted rule if (!parsedLine.startsWith(QLatin1String("##"))) { QString domains = parsedLine.left(pos); parseDomains(domains, QLatin1Char(',')); } m_isException = parsedLine.at(pos + 1) == QLatin1Char('@'); 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(QLatin1String("@@"))) { m_isException = true; parsedLine = parsedLine.mid(2); } // Parse all options following $ char int optionsIndex = parsedLine.indexOf(QLatin1Char('$')); if (optionsIndex >= 0) { const QStringList options = parsedLine.mid(optionsIndex + 1).split(QLatin1Char(','), QString::SkipEmptyParts); int handledOptions = 0; for (const QString &option : options) { if (option.startsWith(QLatin1String("domain="))) { parseDomains(option.mid(7), QLatin1Char('|')); ++handledOptions; } else if (option == QLatin1String("match-case")) { m_caseSensitivity = Qt::CaseSensitive; ++handledOptions; } else if (option.endsWith(QLatin1String("third-party"))) { setOption(ThirdPartyOption); setException(ThirdPartyOption, option.startsWith(QLatin1Char('~'))); ++handledOptions; } else if (option.endsWith(QLatin1String("object"))) { setOption(ObjectOption); setException(ObjectOption, option.startsWith(QLatin1Char('~'))); ++handledOptions; } else if (option.endsWith(QLatin1String("subdocument"))) { setOption(SubdocumentOption); setException(SubdocumentOption, option.startsWith(QLatin1Char('~'))); ++handledOptions; } else if (option.endsWith(QLatin1String("xmlhttprequest"))) { setOption(XMLHttpRequestOption); setException(XMLHttpRequestOption, option.startsWith(QLatin1Char('~'))); ++handledOptions; } else if (option.endsWith(QLatin1String("image"))) { setOption(ImageOption); setException(ImageOption, option.startsWith(QLatin1Char('~'))); ++handledOptions; } else if (option.endsWith(QLatin1String("script"))) { setOption(ScriptOption); setException(ScriptOption, option.startsWith(QLatin1Char('~'))); ++handledOptions; } else if (option.endsWith(QLatin1String("stylesheet"))) { setOption(StyleSheetOption); setException(StyleSheetOption, option.startsWith(QLatin1Char('~'))); ++handledOptions; } else if (option.endsWith(QLatin1String("object-subrequest"))) { setOption(ObjectSubrequestOption); setException(ObjectSubrequestOption, option.startsWith(QLatin1Char('~'))); ++handledOptions; } else if (option == QLatin1String("document") && m_isException) { setOption(DocumentOption); ++handledOptions; } else if (option == QLatin1String("elemhide") && m_isException) { setOption(ElementHideOption); ++handledOptions; } else if (option == QLatin1String("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 = Invalid; return; } parsedLine = parsedLine.left(optionsIndex); } // Rule is classic regexp if (parsedLine.startsWith(QLatin1Char('/')) && parsedLine.endsWith(QLatin1Char('/'))) { parsedLine = parsedLine.mid(1); parsedLine = parsedLine.left(parsedLine.size() - 1); m_type = RegExpMatchRule; m_regExp = new RegExp; m_regExp->regExp = AdblockRegExp(parsedLine, m_caseSensitivity); m_regExp->matchers = createStringMatchers(parseRegExpFilter(parsedLine)); return; } // Remove starting and ending wildcards (*) if (parsedLine.startsWith(QLatin1Char('*'))) { parsedLine = parsedLine.mid(1); } if (parsedLine.endsWith(QLatin1Char('*'))) { 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 = 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 = StringEndsMatchRule; m_matchString = parsedLine; return; } // If we still find a wildcard (*) or separator (^) or (|) // we must modify parsedLine to comply with QzRegExp if (parsedLine.contains(QLatin1Char('*')) || parsedLine.contains(QLatin1Char('^')) || parsedLine.contains(QLatin1Char('|')) ) { m_type = RegExpMatchRule; m_regExp = new RegExp; m_regExp->regExp = AdblockRegExp(createRegExpFromFilter(parsedLine), m_caseSensitivity); m_regExp->matchers = createStringMatchers(parseRegExpFilter(parsedLine)); return; } // We haven't found anything that needs use of regexp, yay! m_type = StringContainsMatchRule; m_matchString = parsedLine; } void AdBlockRule::parseDomains(const QString &domains, QChar separator) { const QStringList domainsList = domains.split(separator, QString::SkipEmptyParts); for (const QString &domain : domainsList) { if (domain.isEmpty()) { continue; } if (domain.startsWith(QLatin1Char('~'))) { m_blockedDomains.append(domain.mid(1)); } else { m_allowedDomains.append(domain); } } if (!m_blockedDomains.isEmpty() || !m_allowedDomains.isEmpty()) { setOption(DomainRestrictedOption); } } bool AdBlockRule::filterIsOnlyDomain(const QString &filter) const { if (!filter.endsWith(QLatin1Char('^')) || !filter.startsWith(QLatin1String("||"))) { return false; } for (int i = 0; i < filter.size(); ++i) { switch (filter.at(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, total = filter.size(); i < total; ++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 == QLatin1Char('_'); } QString AdBlockRule::createRegExpFromFilter(const QString &filter) const { const int filterSize = filter.size(); QString parsed; parsed.reserve(filterSize); bool hadWildcard = false; // Filter multiple wildcards for (int i = 0; i < filterSize; ++i) { const QChar c = filter.at(i); switch (c.toLatin1()) { case '^': parsed.append(QLatin1String("(?:[^\\w\\d\\-.%]|$)")); break; case '*': if (!hadWildcard) { parsed.append(QLatin1String(".*")); } break; case '|': if (i == 0) { if (filterSize > 1 && filter.at(1) == QLatin1Char('|')) { parsed.append(QLatin1String("^[\\w\\-]+:\\/+(?!\\/)(?:[^\\/]+\\.)?")); i++; } else { parsed.append(QLatin1Char('^')); } break; } else if (i == filterSize - 1) { parsed.append(QLatin1Char('$')); break; } // fallthrough Q_FALLTHROUGH(); default: if (!wordCharacter(c)) { parsed.append(QLatin1Char('\\') + c); } else { parsed.append(c); } } hadWildcard = c == QLatin1Char('*'); } return parsed; } QList AdBlockRule::createStringMatchers(const QStringList &filters) const { QList matchers; matchers.reserve(filters.size()); for (const QString &filter : filters) { matchers.append(QStringMatcher(filter, m_caseSensitivity)); } return matchers; } bool AdBlockRule::stringMatch(const QString &domain, const QString &encodedUrl) const { if (m_type == StringContainsMatchRule) { return encodedUrl.contains(m_matchString, m_caseSensitivity); } else if (m_type == DomainMatchRule) { return isMatchingDomain(domain, m_matchString); } else if (m_type == StringEndsMatchRule) { return encodedUrl.endsWith(m_matchString, m_caseSensitivity); } else if (m_type == RegExpMatchRule) { if (!isMatchingRegExpStrings(encodedUrl)) { return false; } return m_regExp->regExp.indexIn(encodedUrl) != -1; } return false; } bool AdBlockRule::isMatchingDomain(const QString &domain, const QString &filter) const { return AdblockUtil::matchDomain(filter, domain); } bool AdBlockRule::isMatchingRegExpStrings(const QString &url) const { Q_ASSERT(m_regExp); foreach (const QStringMatcher &matcher, m_regExp->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 == QLatin1Char('|') || c == QLatin1Char('*') || c == QLatin1Char('^')) { 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; } bool AdBlockRule::hasOption(const AdBlockRule::RuleOption &opt) const { return m_options & opt; } bool AdBlockRule::hasException(const AdBlockRule::RuleOption &opt) const { return m_exceptions & opt; } void AdBlockRule::setOption(const AdBlockRule::RuleOption &opt) { m_options |= opt; } void AdBlockRule::setException(const AdBlockRule::RuleOption &opt, bool on) { if (on) { m_exceptions |= opt; } } diff --git a/plugins/webengineurlinterceptor/adblock/lib/adblockrule.h b/plugins/webengineurlinterceptor/adblock/lib/adblockrule.h index fdc14eda..7c5382ef 100644 --- a/plugins/webengineurlinterceptor/adblock/lib/adblockrule.h +++ b/plugins/webengineurlinterceptor/adblock/lib/adblockrule.h @@ -1,198 +1,198 @@ /* Copyright (c) 2016-2018 Montel Laurent * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License -* along with this program. If not, see . +* along with this program. If not, see . */ /* ============================================================ * QupZilla - WebKit based browser * Copyright (C) 2010-2014 David Rosca * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License -* along with this program. If not, see . +* along with this program. 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 "adblockregexp.h" class QUrl; class QWebEngineUrlRequestInfo; namespace AdBlock { class AdBlockSubscription; class AdBlockRule { Q_DISABLE_COPY(AdBlockRule) public: AdBlockRule(const QString &filter = QString(), AdBlockSubscription *subscription = nullptr); ~AdBlockRule(); 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 QWebEngineUrlRequestInfo &request, const QString &domain, const QString &encodedUrl) const; bool matchDomain(const QString &domain) const; bool matchThirdParty(const QWebEngineUrlRequestInfo &request) const; bool matchObject(const QWebEngineUrlRequestInfo &request) const; bool matchSubdocument(const QWebEngineUrlRequestInfo &request) const; bool matchXmlHttpRequest(const QWebEngineUrlRequestInfo &request) const; bool matchImage(const QWebEngineUrlRequestInfo &request) const; bool matchScript(const QWebEngineUrlRequestInfo &request) const; bool matchStyleSheet(const QWebEngineUrlRequestInfo &request) const; bool matchObjectSubrequest(const QWebEngineUrlRequestInfo &request) const; protected: 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) inline bool hasOption(const RuleOption &opt) const; inline bool hasException(const RuleOption &opt) const; inline void setOption(const RuleOption &opt); inline void setException(const RuleOption &opt, bool on); void parseFilter(); void parseDomains(const QString &domains, QChar separator); bool filterIsOnlyDomain(const QString &filter) const; bool filterIsOnlyEndsMatch(const QString &filter) const; QString createRegExpFromFilter(const QString &filter) const; QList createStringMatchers(const QStringList &filters) const; AdBlockSubscription *m_subscription = nullptr; 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; struct RegExp { AdblockRegExp regExp; QList matchers; }; // Use dynamic allocation to save memory RegExp *m_regExp = nullptr; friend class AdBlockMatcher; friend class AdBlockSearchTree; friend class AdBlockSubscription; }; } #endif // ADBLOCKRULE_H diff --git a/plugins/webengineurlinterceptor/adblock/lib/adblocksearchtree.cpp b/plugins/webengineurlinterceptor/adblock/lib/adblocksearchtree.cpp index 867f8dc4..b5a6d975 100644 --- a/plugins/webengineurlinterceptor/adblock/lib/adblocksearchtree.cpp +++ b/plugins/webengineurlinterceptor/adblock/lib/adblocksearchtree.cpp @@ -1,157 +1,157 @@ /* Copyright (c) 2016-2018 Montel Laurent * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License -* along with this program. If not, see . +* along with this program. If not, see . */ /* ============================================================ * QupZilla - WebKit based browser * Copyright (C) 2013-2014 David Rosca * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License -* along with this program. If not, see . +* along with this program. If not, see . * ============================================================ */ #include "adblocksearchtree.h" #include "adblockrule.h" #include "adblockinterceptor_debug.h" #include using namespace AdBlock; AdBlockSearchTree::AdBlockSearchTree() : m_root(new Node) { } AdBlockSearchTree::~AdBlockSearchTree() { deleteNode(m_root); m_root = nullptr; } 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) { qCDebug(ADBLOCKINTERCEPTOR_LOG) << "AdBlockSearchTree: 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); if (!node->children.contains(c)) { Node *n = new Node; n->c = c; node->children[c] = n; } node = node->children[c]; } node->rule = rule; return true; } const AdBlockRule *AdBlockSearchTree::find(const QWebEngineUrlRequestInfo &request, const QString &domain, const QString &urlString) const { int len = urlString.size(); if (len <= 0) { return 0; } const QChar *string = urlString.constData(); for (int i = 0; i < len; ++i) { const AdBlockRule *rule = prefixSearch(request, domain, urlString, string++, len - i); if (rule) { return rule; } } return 0; } const AdBlockRule *AdBlockSearchTree::prefixSearch(const QWebEngineUrlRequestInfo &request, const QString &domain, const QString &urlString, const QChar *string, int len) const { if (len <= 0) { return nullptr; } QChar c = string[0]; if (!m_root->children.contains(c)) { return nullptr; } Node *node = m_root->children[c]; for (int i = 1; i < len; ++i) { const QChar c = (++string)[0]; if (node->rule && node->rule->networkMatch(request, domain, urlString)) { return node->rule; } if (!node->children.contains(c)) { return nullptr; } node = node->children[c]; } if (node->rule && node->rule->networkMatch(request, domain, urlString)) { return node->rule; } return nullptr; } void AdBlockSearchTree::deleteNode(AdBlockSearchTree::Node *node) { if (!node) { return; } QHashIterator i(node->children); while (i.hasNext()) { i.next(); deleteNode(i.value()); } delete node; } diff --git a/plugins/webengineurlinterceptor/adblock/lib/adblocksearchtree.h b/plugins/webengineurlinterceptor/adblock/lib/adblocksearchtree.h index d14ea1f6..a312e120 100644 --- a/plugins/webengineurlinterceptor/adblock/lib/adblocksearchtree.h +++ b/plugins/webengineurlinterceptor/adblock/lib/adblocksearchtree.h @@ -1,71 +1,71 @@ /* Copyright (c) 2016-2018 Montel Laurent * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License -* along with this program. If not, see . +* along with this program. If not, see . */ /* ============================================================ * QupZilla - WebKit based browser * Copyright (C) 2013-2014 David Rosca * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License -* along with this program. If not, see . +* along with this program. If not, see . * ============================================================ */ #ifndef ADBLOCKSEARCHTREE_H #define ADBLOCKSEARCHTREE_H #include #include class QWebEngineUrlRequestInfo; namespace AdBlock { class AdBlockRule; class AdBlockSearchTree { public: AdBlockSearchTree(); ~AdBlockSearchTree(); void clear(); bool add(const AdBlockRule *rule); const AdBlockRule *find(const QWebEngineUrlRequestInfo &request, const QString &domain, const QString &urlString) const; private: struct Node { QChar c; const AdBlockRule *rule = nullptr; QHash children; Node() : c(0) { } }; const AdBlockRule *prefixSearch(const QWebEngineUrlRequestInfo &request, const QString &domain, const QString &urlString, const QChar *string, int len) const; void deleteNode(Node *node); Node *m_root = nullptr; }; } #endif // ADBLOCKSEARCHTREE_H diff --git a/plugins/webengineurlinterceptor/adblock/lib/adblocksubscription.cpp b/plugins/webengineurlinterceptor/adblock/lib/adblocksubscription.cpp index 7c645b5c..af459caa 100644 --- a/plugins/webengineurlinterceptor/adblock/lib/adblocksubscription.cpp +++ b/plugins/webengineurlinterceptor/adblock/lib/adblocksubscription.cpp @@ -1,483 +1,483 @@ /* Copyright (c) 2016-2018 Montel Laurent * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License -* along with this program. If not, see . +* along with this program. If not, see . */ /* ============================================================ * QupZilla - WebKit based browser * Copyright (C) 2010-2014 David Rosca * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License -* along with this program. If not, see . +* along with this program. 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 "adblocksubscription.h" #include "adblockmanager.h" #include "adblocksearchtree.h" //#include "networkmanager.h" //#include "datapaths.h" #include "adblockutil.h" //#include "followredirectreply.h" #include "adblockinterceptor_debug.h" #include #include #include #include #include using namespace AdBlock; AdBlockSubscription::AdBlockSubscription(const QString &title, QObject *parent) : QObject(parent) , mTitle(title) { } QString AdBlockSubscription::title() const { return mTitle; } QString AdBlockSubscription::filePath() const { return mFilePath; } void AdBlockSubscription::setFilePath(const QString &path) { mFilePath = path; } QUrl AdBlockSubscription::url() const { return mUrl; } void AdBlockSubscription::setUrl(const QUrl &url) { mUrl = url; } void AdBlockSubscription::loadSubscription(const QStringList &disabledRules) { QFile file(mFilePath); if (!file.exists()) { QTimer::singleShot(0, this, &AdBlockSubscription::updateSubscription); return; } if (!file.open(QFile::ReadOnly)) { qCWarning(ADBLOCKINTERCEPTOR_LOG) << "AdBlockSubscription::" << __FUNCTION__ << "Unable to open adblock file for reading" << mFilePath; 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(QLatin1String("[Adblock")) || mTitle.isEmpty()) { qCWarning(ADBLOCKINTERCEPTOR_LOG) << "AdBlockSubscription::" << __FUNCTION__ << "invalid format of adblock file" << mFilePath; QTimer::singleShot(0, this, &AdBlockSubscription::updateSubscription); return; } mRules.clear(); while (!textStream.atEnd()) { AdBlockRule *rule = new AdBlockRule(textStream.readLine(), this); if (disabledRules.contains(rule->filter())) { rule->setEnabled(false); } mRules.append(rule); } // Initial update if (mRules.isEmpty() && !mUpdated) { QTimer::singleShot(0, this, &AdBlockSubscription::updateSubscription); } } void AdBlockSubscription::saveSubscription() { } void AdBlockSubscription::updateSubscription() { #if 0 if (m_reply || !m_url.isValid()) { return; } m_reply = new FollowRedirectReply(m_url, mApp->networkManager()); connect(m_reply, SIGNAL(finished()), this, SLOT(subscriptionDownloaded())); #endif } void AdBlockSubscription::subscriptionDownloaded() { #if 0 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->deleteLater(); m_reply = 0; if (error) { Q_EMIT subscriptionError(i18n("Cannot load subscription!")); return; } loadSubscription(AdBlockManager::instance()->disabledRules()); Q_EMIT subscriptionUpdated(); Q_EMIT subscriptionChanged(); #endif } bool AdBlockSubscription::saveDownloadedData(const QByteArray &data) { #if 0 QFile file(m_filePath); if (!file.open(QFile::ReadWrite | QFile::Truncate)) { qCWarning(ADBLOCKINTERCEPTOR_LOG) << "AdBlockSubscription::" << __FUNCTION__ << "Unable to open adblock file for writing:" << m_filePath; return false; } // Write subscription header file.write(QString("Title: %1\nUrl: %2\n").arg(title(), url().toString()).toUtf8()); if (AdBlockManager::instance()->useLimitedEasyList() && m_url == QUrl(ADBLOCK_EASYLIST_URL)) { // Third-party advertisers rules are with start domain (||) placeholder which needs regexps // So we are ignoring it for keeping good performance // But we will use whitelist rules at the end of list QByteArray part1 = data.left(data.indexOf(QLatin1String("!-----------------------------Third-party adverts-----------------------------!"))); QByteArray part2 = data.mid(data.indexOf(QLatin1String("!---------------------------------Whitelists----------------------------------!"))); file.write(part1); file.write(part2); file.close(); return true; } file.write(data); file.close(); #else Q_UNUSED(data); #endif return true; } const AdBlockRule *AdBlockSubscription::rule(int offset) const { if (!AdblockUtil::containsIndex(mRules, offset)) { return nullptr; } return mRules[offset]; } QVector AdBlockSubscription::allRules() const { return mRules; } const AdBlockRule *AdBlockSubscription::enableRule(int offset) { if (!AdblockUtil::containsIndex(mRules, offset)) { return nullptr; } AdBlockRule *rule = mRules[offset]; rule->setEnabled(true); AdblockManager::self()->removeDisabledRule(rule->filter()); Q_EMIT subscriptionChanged(); if (rule->isCssRule()) { //FIXME mApp->reloadUserStyleSheet(); } return rule; } const AdBlockRule *AdBlockSubscription::disableRule(int offset) { if (!AdblockUtil::containsIndex(mRules, offset)) { return nullptr; } AdBlockRule *rule = mRules[offset]; rule->setEnabled(false); AdblockManager::self()->addDisabledRule(rule->filter()); Q_EMIT subscriptionChanged(); if (rule->isCssRule()) { //FIXME mApp->reloadUserStyleSheet(); } 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(mRules); } // AdBlockCustomList AdBlockCustomList::AdBlockCustomList(QObject *parent) : AdBlockSubscription(i18n("Custom Rules"), parent) { setFilePath(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QLatin1String("/adblock/customlist.txt")); } 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 = QStringLiteral("@@||duckduckgo.com^$document"); const QString ddg2 = QStringLiteral("duckduckgo.com#@#.has-ad"); const QString rules = QString::fromUtf8(readAllFileByteContents(filePath())); QFile file(filePath()); if (file.open(QFile::WriteOnly | QFile::Append)) { QTextStream stream(&file); stream.setCodec("UTF-8"); if (!rules.contains(ddg1 + QLatin1String("\n"))) { stream << ddg1 << endl; } if (!rules.contains(QLatin1String("\n") + ddg2)) { stream << ddg2 << endl; } } file.close(); AdBlockSubscription::loadSubscription(disabledRules); } QByteArray AdBlockCustomList::readAllFileByteContents(const QString &filename) { QFile file(filename); if (!filename.isEmpty() && file.open(QFile::ReadOnly)) { const QByteArray a = file.readAll(); file.close(); return a; } return QByteArray(); } void AdBlockCustomList::saveSubscription() { QFile file(filePath()); if (!file.open(QFile::ReadWrite | QFile::Truncate)) { qCWarning(ADBLOCKINTERCEPTOR_LOG) << "AdBlockSubscription::" << __FUNCTION__ << "Unable to open adblock file for writing:" << filePath(); return; } QTextStream textStream(&file); textStream.setCodec("UTF-8"); textStream << "Title: " << title() << endl; textStream << "Url: " << url().toString() << endl; textStream << "[Adblock Plus 1.1.1]" << endl; foreach (const AdBlockRule *rule, mRules) { textStream << rule->filter() << endl; } file.close(); } bool AdBlockCustomList::canEditRules() const { return true; } bool AdBlockCustomList::canBeRemoved() const { return false; } bool AdBlockCustomList::containsFilter(const QString &filter) const { foreach (const AdBlockRule *rule, mRules) { if (rule->filter() == filter) { return true; } } return false; } bool AdBlockCustomList::removeFilter(const QString &filter) { const int numberRules(mRules.count()); for (int i = 0; i < numberRules; ++i) { const AdBlockRule *rule = mRules.at(i); if (rule->filter() == filter) { return removeRule(i); } } return false; } int AdBlockCustomList::addRule(AdBlockRule *rule) { mRules.append(rule); Q_EMIT subscriptionChanged(); if (rule->isCssRule()) { //FIXME mApp->reloadUserStyleSheet(); } return mRules.count() - 1; } bool AdBlockCustomList::removeRule(int offset) { if (!AdblockUtil::containsIndex(mRules, offset)) { return false; } AdBlockRule *rule = mRules.at(offset); const QString filter = rule->filter(); mRules.remove(offset); Q_EMIT subscriptionChanged(); if (rule->isCssRule()) { //FIXME mApp->reloadUserStyleSheet(); } //FIXME AdBlockManager::instance()->removeDisabledRule(filter); delete rule; return true; } const AdBlockRule *AdBlockCustomList::replaceRule(AdBlockRule *rule, int offset) { if (!AdblockUtil::containsIndex(mRules, offset)) { return nullptr; } AdBlockRule *oldRule = mRules.at(offset); mRules[offset] = rule; Q_EMIT subscriptionChanged(); if (rule->isCssRule() || oldRule->isCssRule()) { //FIXME mApp->reloadUserStyleSheet(); } delete oldRule; return mRules[offset]; } diff --git a/plugins/webengineurlinterceptor/adblock/lib/adblocksubscription.h b/plugins/webengineurlinterceptor/adblock/lib/adblocksubscription.h index b72e715f..3e115074 100644 --- a/plugins/webengineurlinterceptor/adblock/lib/adblocksubscription.h +++ b/plugins/webengineurlinterceptor/adblock/lib/adblocksubscription.h @@ -1,153 +1,153 @@ /* Copyright (c) 2016-2018 Montel Laurent * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License -* along with this program. If not, see . +* along with this program. If not, see . */ /* ============================================================ * QupZilla - WebKit based browser * Copyright (C) 2010-2014 David Rosca * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License -* along with this program. If not, see . +* along with this program. 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 "adblockrule.h" #include "adblocksearchtree.h" class QUrl; class FollowRedirectReply; namespace AdBlock { class AdBlockSubscription : public QObject { Q_OBJECT public: explicit AdBlockSubscription(const QString &title, QObject *parent = nullptr); ~AdBlockSubscription(); QString title() const; QString filePath() const; void setFilePath(const QString &path); QUrl url() const; void setUrl(const QUrl &url); virtual void loadSubscription(const QStringList &disabledRules); virtual void saveSubscription(); const AdBlockRule *rule(int offset) const; QVector allRules() const; const AdBlockRule *enableRule(int offset); const AdBlockRule *disableRule(int offset); 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 Q_SLOTS: void updateSubscription(); Q_SIGNALS: void subscriptionChanged(); void subscriptionUpdated(); void subscriptionError(const QString &message); protected Q_SLOTS: void subscriptionDownloaded(); protected: virtual bool saveDownloadedData(const QByteArray &data); FollowRedirectReply *mReply = nullptr; QVector mRules; private: QString mTitle; QString mFilePath; QUrl mUrl; bool mUpdated = false; }; class AdBlockCustomList : public AdBlockSubscription { Q_OBJECT public: explicit AdBlockCustomList(QObject *parent = nullptr); void loadSubscription(const QStringList &disabledRules) override; void saveSubscription() override; bool canEditRules() const override; bool canBeRemoved() const override; bool containsFilter(const QString &filter) const; bool removeFilter(const QString &filter); int addRule(AdBlockRule *rule) override; bool removeRule(int offset) override; const AdBlockRule *replaceRule(AdBlockRule *rule, int offset) override; private: QByteArray readAllFileByteContents(const QString &filename); }; } #endif // ADBLOCKSUBSCRIPTION_H diff --git a/plugins/webengineurlinterceptor/adblock/lib/adblockutil.cpp b/plugins/webengineurlinterceptor/adblock/lib/adblockutil.cpp index 3713d12c..4cb1d784 100644 --- a/plugins/webengineurlinterceptor/adblock/lib/adblockutil.cpp +++ b/plugins/webengineurlinterceptor/adblock/lib/adblockutil.cpp @@ -1,52 +1,52 @@ /* Copyright (c) 2016-2018 Montel Laurent * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License -* along with this program. If not, see . +* along with this program. If not, see . */ /* ============================================================ * QupZilla - WebKit based browser * Copyright (C) 2010-2014 David Rosca * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License -* along with this program. If not, see . +* along with this program. If not, see . * ============================================================ */ #include "adblockutil.h" using namespace AdBlock; // Matches domain (assumes both pattern and domain not starting with dot) // pattern = domain to be matched // domain = site domain bool AdblockUtil::matchDomain(const QString &pattern, const QString &domain) { if (pattern == domain) { return true; } if (!domain.endsWith(pattern)) { return false; } int index = domain.indexOf(pattern); return index > 0 && domain[index - 1] == QLatin1Char('.'); } diff --git a/plugins/webengineurlinterceptor/adblock/lib/adblockutil.h b/plugins/webengineurlinterceptor/adblock/lib/adblockutil.h index c57f3aba..7fd7d860 100644 --- a/plugins/webengineurlinterceptor/adblock/lib/adblockutil.h +++ b/plugins/webengineurlinterceptor/adblock/lib/adblockutil.h @@ -1,50 +1,50 @@ /* Copyright (c) 2016-2018 Montel Laurent * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License -* along with this program. If not, see . +* along with this program. If not, see . */ /* ============================================================ * QupZilla - WebKit based browser * Copyright (C) 2010-2014 David Rosca * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License -* along with this program. If not, see . +* along with this program. If not, see . * ============================================================ */ #ifndef ADBLOCKUTILS_H #define ADBLOCKUTILS_H #include namespace AdBlock { class AdblockUtil { public: static bool matchDomain(const QString &pattern, const QString &domain); template static bool containsIndex(const T &container, int index) { return index >= 0 && container.count() > index; } }; } #endif diff --git a/plugins/webengineurlinterceptor/adblock/lib/widgets/adblocksettingwidget.cpp b/plugins/webengineurlinterceptor/adblock/lib/widgets/adblocksettingwidget.cpp index 669dbc54..85ab0923 100644 --- a/plugins/webengineurlinterceptor/adblock/lib/widgets/adblocksettingwidget.cpp +++ b/plugins/webengineurlinterceptor/adblock/lib/widgets/adblocksettingwidget.cpp @@ -1,501 +1,501 @@ /* ============================================================ * * This file is a part of the rekonq project * * Copyright (c) 2013-2018 Montel Laurent * based on code from rekonq * Copyright (C) 2010-2012 by Andrea Diamantini * * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License or (at your option) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License -* along with this program. If not, see . +* along with this program. If not, see . * * ============================================================ */ // Self Includes #include "adblocksettingwidget.h" #include "ui_settings_adblock.h" #include "globalsettings_webengineurlinterceptoradblock.h" #include "adblockaddsubscriptiondialog.h" #include "adblockinterceptor_debug.h" #include "adblockmanager.h" #include "adblockshowlistdialog.h" #include "adblockutil.h" #include "PimCommon/ConfigureImmutableWidgetUtils" using namespace PimCommon::ConfigureImmutableWidgetUtils; #include "PimCommon/PimUtil" // KDE Includes #include #include #include #include #include // Qt Includes #include #include #include #include #include #include #include #include #include using namespace AdBlock; AdBlockSettingWidget::AdBlockSettingWidget(QWidget *parent) : QWidget(parent) , mChanged(false) { mUi = new Ui::adblock; mUi->setupUi(this); mUi->hintLabel->setText(i18n("Filter expression (e.g. http://www.example.com/ad/*, more information):")); connect(mUi->hintLabel, &QLabel::linkActivated, this, &AdBlockSettingWidget::slotInfoLinkActivated); mUi->hintLabel->setContextMenuPolicy(Qt::NoContextMenu); mUi->manualFiltersListWidget->setSelectionMode(QAbstractItemView::MultiSelection); mUi->searchLine->setListWidget(mUi->manualFiltersListWidget); mUi->insertButton->setIcon(QIcon::fromTheme(QStringLiteral("list-add"))); connect(mUi->insertButton, &QToolButton::clicked, this, &AdBlockSettingWidget::insertRule); mUi->removeButton->setIcon(QIcon::fromTheme(QStringLiteral("list-remove"))); connect(mUi->removeButton, &QPushButton::clicked, this, &AdBlockSettingWidget::removeRule); connect(mUi->removeSubscription, &QPushButton::clicked, this, &AdBlockSettingWidget::slotRemoveSubscription); connect(mUi->manualFiltersListWidget, &QListWidget::currentItemChanged, this, &AdBlockSettingWidget::slotUpdateManualButtons); connect(mUi->manualFiltersListWidget, &QListWidget::itemChanged, this, &AdBlockSettingWidget::hasChanged); mUi->spinBox->setSuffix(ki18np(" day", " days")); mUi->removeSubscription->setEnabled(false); mUi->showList->setEnabled(false); // Q_EMIT changed signal connect(mUi->checkEnableAdblock, &QCheckBox::stateChanged, this, &AdBlockSettingWidget::hasChanged); connect(mUi->checkHideAds, &QCheckBox::stateChanged, this, &AdBlockSettingWidget::hasChanged); connect(mUi->spinBox, QOverload::of(&KPluralHandlingSpinBox::valueChanged), this, &AdBlockSettingWidget::hasChanged); connect(mUi->addFilters, &QPushButton::clicked, this, &AdBlockSettingWidget::slotAddFilter); connect(mUi->showList, &QPushButton::clicked, this, &AdBlockSettingWidget::slotShowList); connect(mUi->editFilter, &QPushButton::clicked, this, &AdBlockSettingWidget::slotEditFilter); connect(mUi->automaticFiltersListWidget, &AdBlock::AdBlockListWidget::itemChanged, this, &AdBlockSettingWidget::hasChanged); connect(mUi->automaticFiltersListWidget, &AdBlock::AdBlockListWidget::currentItemChanged, this, &AdBlockSettingWidget::slotUpdateButtons); connect(mUi->automaticFiltersListWidget, &AdBlock::AdBlockListWidget::itemDoubleClicked, this, &AdBlockSettingWidget::slotAutomaticFilterDouble); connect(mUi->importFilters, &QPushButton::clicked, this, &AdBlockSettingWidget::slotImportFilters); connect(mUi->exportFilters, &QPushButton::clicked, this, &AdBlockSettingWidget::slotExportFilters); connect(mUi->addFilterLineEdit, &QLineEdit::textChanged, this, &AdBlockSettingWidget::slotManualFilterLineEditTextChanged); slotUpdateManualButtons(); mUi->insertButton->setEnabled(false); } AdBlockSettingWidget::~AdBlockSettingWidget() { delete mUi; } void AdBlockSettingWidget::slotManualFilterLineEditTextChanged(const QString &text) { mUi->insertButton->setEnabled(!text.trimmed().isEmpty()); } void AdBlockSettingWidget::slotEditFilter() { QListWidgetItem *item = mUi->manualFiltersListWidget->currentItem(); if (item) { mUi->manualFiltersListWidget->editItem(item); } } void AdBlockSettingWidget::slotUpdateButtons() { const bool enabled = mUi->automaticFiltersListWidget->currentItem(); mUi->removeSubscription->setEnabled(enabled); mUi->showList->setEnabled(enabled); } void AdBlockSettingWidget::slotUpdateManualButtons() { const bool enabled = mUi->manualFiltersListWidget->currentItem(); mUi->removeButton->setEnabled(enabled); mUi->editFilter->setEnabled(enabled); mUi->exportFilters->setEnabled(mUi->manualFiltersListWidget->count() > 0); } void AdBlockSettingWidget::slotInfoLinkActivated(const QString &url) { Q_UNUSED(url) const QString href = QStringLiteral("https://adblockplus.org/en/filters"); const QString hintHelpString = i18n("

Enter an expression to filter. Filters can be defined as either:" "

  • a shell-style wildcard, e.g. http://www.example.com/ads*, " "the wildcards *?[] may be used
  • " "
  • a full regular expression by surrounding the string with '/', " "e.g. /\\/(ad|banner)\\./
" "

Any filter string can be preceded by '@@' to whitelist (allow) any matching URL, " "which takes priority over any blacklist (blocking) filter.
%2", href, i18n("More information")); QWhatsThis::showText(QCursor::pos(), hintHelpString, this); } bool AdBlockSettingWidget::event(QEvent *event) { if (event->type() == QEvent::WhatsThisClicked) { QWhatsThisClickedEvent *clicked = static_cast(event); new KRun(QUrl(clicked->href()), this); return true; } return QWidget::event(event); } void AdBlockSettingWidget::insertRule() { const QString rule = mUi->addFilterLineEdit->text(); if (rule.isEmpty()) { return; } const int numberItem(mUi->manualFiltersListWidget->count()); for (int i = 0; i < numberItem; ++i) { if (mUi->manualFiltersListWidget->item(i)->text() == rule) { mUi->addFilterLineEdit->clear(); return; } } addManualFilter(rule); mUi->exportFilters->setEnabled(mUi->manualFiltersListWidget->count() > 0); mUi->addFilterLineEdit->clear(); hasChanged(); } void AdBlockSettingWidget::removeRule() { const QList select = mUi->manualFiltersListWidget->selectedItems(); if (select.isEmpty()) { return; } if (KMessageBox::No == KMessageBox::warningYesNo(this, i18np("Do you want to remove this rule?", "Do you want to remove these rules?", select.count()), i18n("Remove"))) { return; } for (QListWidgetItem *item : select) { delete item; } mUi->exportFilters->setEnabled(mUi->manualFiltersListWidget->count() > 0); hasChanged(); } void AdBlockSettingWidget::doResetToDefaultsOther() { const bool bUseDefaults = AdBlock::AdBlockSettings::self()->useDefaults(true); loadWidget(mUi->checkEnableAdblock, AdBlock::AdBlockSettings::self()->adBlockEnabledItem()); mUi->tabWidget->setEnabled(AdBlock::AdBlockSettings::self()->adBlockEnabled()); loadWidget(mUi->checkHideAds, AdBlock::AdBlockSettings::self()->hideAdsEnabledItem()); loadWidget(mUi->spinBox, AdBlock::AdBlockSettings::self()->adBlockUpdateIntervalItem()); AdBlock::AdBlockSettings::self()->useDefaults(bUseDefaults); } void AdBlockSettingWidget::doLoadFromGlobalSettings() { mUi->manualFiltersListWidget->clear(); mUi->automaticFiltersListWidget->clear(); loadWidget(mUi->checkEnableAdblock, AdBlock::AdBlockSettings::self()->adBlockEnabledItem()); // update enabled status mUi->tabWidget->setEnabled(AdBlock::AdBlockSettings::self()->adBlockEnabled()); loadWidget(mUi->checkHideAds, AdBlock::AdBlockSettings::self()->hideAdsEnabledItem()); loadWidget(mUi->spinBox, AdBlock::AdBlockSettings::self()->adBlockUpdateIntervalItem()); // ------------------------------------------------------------------------------ // automatic filters KConfig config(QStringLiteral("AdBlockadblockrc")); const QStringList itemList = config.groupList().filter(QRegularExpression(QStringLiteral("FilterList \\d+"))); for (const QString &item : itemList) { KConfigGroup filtersGroup(&config, item); const bool isFilterEnabled = filtersGroup.readEntry(QStringLiteral("FilterEnabled"), false); const QString url = filtersGroup.readEntry(QStringLiteral("url")); const QString path = filtersGroup.readEntry(QStringLiteral("path")); const QString name = filtersGroup.readEntry(QStringLiteral("name")); const QDateTime lastUpdate = filtersGroup.readEntry(QStringLiteral("lastUpdate"), QDateTime()); if (url.isEmpty() || path.isEmpty() || name.isEmpty()) { continue; } QListWidgetItem *subItem = new QListWidgetItem(mUi->automaticFiltersListWidget); subItem->setFlags(Qt::ItemIsEnabled | Qt::ItemIsUserCheckable | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled); if (isFilterEnabled) { subItem->setCheckState(Qt::Checked); } else { subItem->setCheckState(Qt::Unchecked); } subItem->setData(UrlList, url); subItem->setData(PathList, path); subItem->setData(LastUpdateList, lastUpdate); subItem->setText(name); } // ------------------------------------------------------------------------------ // local filters const QString localRulesFilePath = AdBlock::AdBlockUtil::localFilterPath(); QFile ruleFile(localRulesFilePath); if (!ruleFile.open(QFile::ReadOnly | QFile::Text)) { qCDebug(ADBLOCKINTERCEPTOR_LOG) << "Unable to open rule file" << localRulesFilePath; return; } KConfigGroup grp = config.group(QStringLiteral("DisableRules")); const QStringList disableRules = grp.readEntry("DisableRules", QStringList()); QTextStream in(&ruleFile); while (!in.atEnd()) { QString stringRule = in.readLine(); addManualFilter(stringRule, disableRules); } updateCheckBox(); } void AdBlockSettingWidget::save() { if (!mChanged) { return; } // General settings saveCheckBox(mUi->checkEnableAdblock, AdBlock::AdBlockSettings::self()->adBlockEnabledItem()); saveCheckBox(mUi->checkHideAds, AdBlock::AdBlockSettings::self()->hideAdsEnabledItem()); saveSpinBox(mUi->spinBox, AdBlock::AdBlockSettings::self()->adBlockUpdateIntervalItem()); // automatic filters KConfig config(QStringLiteral("AdBlockadblockrc")); const QStringList list = config.groupList().filter(QRegularExpression(QStringLiteral("FilterList \\d+"))); for (const QString &group : list) { config.deleteGroup(group); } // make sure the directory exists, otherwise saving the filters will fail QDir().mkpath(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QStringLiteral("/adblock")); const int numberItem(mUi->automaticFiltersListWidget->count()); for (int i = 0; i < numberItem; ++i) { QListWidgetItem *subItem = mUi->automaticFiltersListWidget->item(i); KConfigGroup grp = config.group(QStringLiteral("FilterList %1").arg(i)); grp.writeEntry(QStringLiteral("FilterEnabled"), subItem->checkState() == Qt::Checked); grp.writeEntry(QStringLiteral("url"), subItem->data(UrlList).toString()); grp.writeEntry(QStringLiteral("name"), subItem->text()); if (subItem->data(LastUpdateList).toDateTime().isValid()) { grp.writeEntry(QStringLiteral("lastUpdate"), subItem->data(LastUpdateList).toDateTime()); } QString path = subItem->data(PathList).toString(); if (path.isEmpty()) { path = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QStringLiteral("/adblock/adblockrules-%1").arg(i); } grp.writeEntry(QStringLiteral("path"), path); } config.sync(); // local filters const QString localRulesFilePath = AdBlock::AdBlockUtil::localFilterPath(); QFile ruleFile(localRulesFilePath); if (!ruleFile.open(QFile::WriteOnly | QFile::Text)) { qCDebug(ADBLOCKINTERCEPTOR_LOG) << "Unable to open rule file" << localRulesFilePath; return; } QStringList disableCustomFilter; QTextStream out(&ruleFile); for (int i = 0, total = mUi->manualFiltersListWidget->count(); i < total; ++i) { QListWidgetItem *subItem = mUi->manualFiltersListWidget->item(i); const QString stringRule = subItem->text(); if (!stringRule.trimmed().isEmpty()) { out << stringRule << '\n'; } if (subItem->checkState() == Qt::Unchecked) { disableCustomFilter << stringRule; } } if (!disableCustomFilter.isEmpty()) { KConfigGroup grp = config.group(QStringLiteral("DisableRules")); grp.writeEntry("DisableRules", disableCustomFilter); } else { config.deleteGroup(QStringLiteral("DisableRules")); } // ------------------------------------------------------------------------------- mChanged = false; Q_EMIT changed(false); AdBlock::AdBlockSettings::self()->save(); AdBlock::AdblockManager::self()->reloadConfig(); } void AdBlockSettingWidget::updateCheckBox() { // update enabled status mUi->checkHideAds->setEnabled(mUi->checkEnableAdblock->isChecked()); mUi->tabWidget->setEnabled(mUi->checkEnableAdblock->isChecked()); } void AdBlockSettingWidget::hasChanged() { updateCheckBox(); mChanged = true; Q_EMIT changed(true); Q_EMIT settingsChanged(); } bool AdBlockSettingWidget::changed() const { return mChanged; } void AdBlockSettingWidget::slotAddFilter() { QStringList excludeList; const int numberItem(mUi->automaticFiltersListWidget->count()); excludeList.reserve(numberItem); for (int i = 0; i < numberItem; ++i) { excludeList << mUi->automaticFiltersListWidget->item(i)->text(); } QPointer dlg = new AdBlock::AdBlockAddSubscriptionDialog(excludeList, this); if (dlg->exec()) { QString name; QString url; dlg->selectedList(name, url); QListWidgetItem *subItem = new QListWidgetItem(mUi->automaticFiltersListWidget); subItem->setFlags(Qt::ItemIsEnabled | Qt::ItemIsUserCheckable | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled); subItem->setCheckState(Qt::Checked); subItem->setText(name); subItem->setData(UrlList, url); subItem->setData(LastUpdateList, QDateTime()); subItem->setData(PathList, QString()); hasChanged(); } delete dlg; } void AdBlockSettingWidget::slotRemoveSubscription() { QListWidgetItem *item = mUi->automaticFiltersListWidget->currentItem(); if (item) { if (KMessageBox::questionYesNo(this, i18n("Do you want to delete list \"%1\"?", item->text()), i18n("Delete current list")) == KMessageBox::Yes) { const QString path = item->data(PathList).toString(); if (!path.isEmpty()) { if (!QFile(path).remove()) { qCDebug(ADBLOCKINTERCEPTOR_LOG) << " we can not remove file:" << path; } } delete item; } hasChanged(); } } void AdBlockSettingWidget::slotShowList() { showAutomaticFilterList(mUi->automaticFiltersListWidget->currentItem()); } void AdBlockSettingWidget::showAutomaticFilterList(QListWidgetItem *item) { if (item) { QPointer dlg = new AdBlockShowListDialog(true, this); dlg->setListName(item->text()); dlg->setAdBlockListPath(item->data(PathList).toString(), item->data(UrlList).toString()); connect(dlg.data(), &AdBlockShowListDialog::deleteList, this, &AdBlockSettingWidget::slotDeleteList); dlg->exec(); delete dlg; } } void AdBlockSettingWidget::slotDeleteList(const QString &listName) { QListWidgetItem *item = mUi->automaticFiltersListWidget->currentItem(); if (item && item->text() == listName) { const QString path = item->data(PathList).toString(); if (!path.isEmpty()) { if (!QFile(path).remove()) { qCDebug(ADBLOCKINTERCEPTOR_LOG) << " we can not remove file:" << path; } } delete item; hasChanged(); } } void AdBlockSettingWidget::slotImportFilters() { const QString filter = i18n("All Files (*)"); const QString result = PimCommon::Util::loadToFile(filter, this, QUrl(), i18n("Import Filters")); if (result.isEmpty()) { return; } const QStringList listFilter = result.split(QLatin1Char('\n')); QStringList excludeFilter; const int numberOfElements(mUi->manualFiltersListWidget->count()); excludeFilter.reserve(numberOfElements); for (int i = 0; i < numberOfElements; ++i) { QListWidgetItem *subItem = mUi->manualFiltersListWidget->item(i); excludeFilter.append(subItem->text()); } for (const QString &element : listFilter) { if (element == QLatin1String("\n")) { continue; } if (excludeFilter.contains(element)) { continue; } addManualFilter(element); } } void AdBlockSettingWidget::addManualFilter(const QString &text, const QStringList &excludeRules) { QListWidgetItem *subItem = new QListWidgetItem(mUi->manualFiltersListWidget); subItem->setFlags(Qt::ItemIsEnabled | Qt::ItemIsUserCheckable | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled | Qt::ItemIsEditable); subItem->setCheckState(excludeRules.contains(text) ? Qt::Unchecked : Qt::Checked); subItem->setText(text); } void AdBlockSettingWidget::slotExportFilters() { const QString filter = i18n("All Files (*)"); QString exportFilters; const int numberOfElement(mUi->manualFiltersListWidget->count()); for (int i = 0; i < numberOfElement; ++i) { QListWidgetItem *subItem = mUi->manualFiltersListWidget->item(i); const QString stringRule = subItem->text(); if (!stringRule.isEmpty()) { exportFilters += stringRule + QLatin1Char('\n'); } } PimCommon::Util::saveTextAs(exportFilters, filter, this, QUrl(), i18n("Export Filters")); } void AdBlockSettingWidget::slotAutomaticFilterDouble(QListWidgetItem *item) { showAutomaticFilterList(item); } diff --git a/plugins/webengineurlinterceptor/adblock/lib/widgets/adblocksettingwidget.h b/plugins/webengineurlinterceptor/adblock/lib/widgets/adblocksettingwidget.h index 6f90f260..b8159df3 100644 --- a/plugins/webengineurlinterceptor/adblock/lib/widgets/adblocksettingwidget.h +++ b/plugins/webengineurlinterceptor/adblock/lib/widgets/adblocksettingwidget.h @@ -1,91 +1,91 @@ /* ============================================================ * * This file is a part of the rekonq project * Copyright (c) 2013-2018 Montel Laurent * based on code from rekonq * Copyright (C) 2010-2012 by Andrea Diamantini * * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License or (at your option) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License -* along with this program. If not, see . +* along with this program. If not, see . * * ============================================================ */ #ifndef AD_BLOCK_SETTING_WIDGET_H #define AD_BLOCK_SETTING_WIDGET_H #include "adblocklib_export.h" // Qt Includes #include class QListWidgetItem; namespace Ui { class adblock; } namespace AdBlock { class ADBLOCKLIB_EXPORT AdBlockSettingWidget : public QWidget { Q_OBJECT public: explicit AdBlockSettingWidget(QWidget *parent = nullptr); ~AdBlockSettingWidget() override; bool changed() const; void save(); void doLoadFromGlobalSettings(); void doResetToDefaultsOther(); Q_SIGNALS: void changed(bool); void settingsChanged(); protected: bool event(QEvent *event) override; private: void hasChanged(); void slotInfoLinkActivated(const QString &); void insertRule(); void removeRule(); void slotAddFilter(); void slotRemoveSubscription(); void slotUpdateButtons(); void slotShowList(); void slotImportFilters(); void slotExportFilters(); void slotUpdateManualButtons(); void slotEditFilter(); void slotManualFilterLineEditTextChanged(const QString &); void slotAutomaticFilterDouble(QListWidgetItem *item); void slotDeleteList(const QString &listName); void updateCheckBox(); void addManualFilter(const QString &text, const QStringList &excludeRules = QStringList()); void showAutomaticFilterList(QListWidgetItem *item); enum List { UrlList = Qt::UserRole + 1, PathList = Qt::UserRole + 2, LastUpdateList = Qt::UserRole + 3 }; Ui::adblock *mUi = nullptr; bool mChanged = false; }; } #endif // AD_BLOCK_SETTING_WIDGET_H