Refactoring of adblock.

This commit is contained in:
Martin Rotter 2015-06-18 09:06:03 +02:00
parent 4e0cd01fb7
commit a74e1c43f1
20 changed files with 848 additions and 1101 deletions

View File

@ -33,7 +33,8 @@ StatusBar::StatusBar(QWidget *parent) : QStatusBar(parent) {
setSizeGripEnabled(false); setSizeGripEnabled(false);
setContentsMargins(0, 0, 0, 0); setContentsMargins(0, 0, 0, 0);
m_adblockIcon = new AdBlockIcon(this); m_adBlockIcon = new AdBlockIcon(this);
m_adBlockIcon->activate();
// Initializations of widgets for status bar. // Initializations of widgets for status bar.
m_fullscreenSwitcher = new PlainToolButton(this); m_fullscreenSwitcher = new PlainToolButton(this);
@ -69,7 +70,7 @@ StatusBar::StatusBar(QWidget *parent) : QStatusBar(parent) {
addPermanentWidget(m_barProgressFeeds); addPermanentWidget(m_barProgressFeeds);
addPermanentWidget(m_lblProgressDownload); addPermanentWidget(m_lblProgressDownload);
addPermanentWidget(m_barProgressDownload); addPermanentWidget(m_barProgressDownload);
addPermanentWidget(m_adblockIcon); addPermanentWidget(m_adBlockIcon);
addPermanentWidget(m_fullscreenSwitcher); addPermanentWidget(m_fullscreenSwitcher);
} }

View File

@ -39,7 +39,7 @@ class StatusBar : public QStatusBar {
} }
inline AdBlockIcon *adBlockIcon() { inline AdBlockIcon *adBlockIcon() {
return m_adblockIcon; return m_adBlockIcon;
} }
public slots: public slots:
@ -59,7 +59,7 @@ class StatusBar : public QStatusBar {
QProgressBar *m_barProgressDownload; QProgressBar *m_barProgressDownload;
QLabel *m_lblProgressDownload; QLabel *m_lblProgressDownload;
PlainToolButton *m_fullscreenSwitcher; PlainToolButton *m_fullscreenSwitcher;
AdBlockIcon* m_adblockIcon; AdBlockIcon* m_adBlockIcon;
}; };
#endif // STATUSBAR_H #endif // STATUSBAR_H

View File

@ -208,6 +208,8 @@ QSqlDatabase DatabaseFactory::sqliteInitializeInMemoryDatabase() {
copy_contents.exec(QString("INSERT INTO main.%1 SELECT * FROM storage.%1;").arg(table)); copy_contents.exec(QString("INSERT INTO main.%1 SELECT * FROM storage.%1;").arg(table));
} }
qDebug("Copying data from file-based database into working in-memory database.");
// Detach database and finish. // Detach database and finish.
copy_contents.exec("DETACH 'storage'"); copy_contents.exec("DETACH 'storage'");
copy_contents.finish(); copy_contents.finish();

View File

@ -50,7 +50,7 @@ void AdBlockIcon::popupBlocked(const QString &rule_string, const QUrl &url) {
return; return;
} }
QPair<AdBlockRule*, QUrl> pair; QPair<AdBlockRule*,QUrl> pair;
pair.first = new AdBlockRule(filter, subscription); pair.first = new AdBlockRule(filter, subscription);
pair.second = url; pair.second = url;
m_blockedPopups.append(pair); m_blockedPopups.append(pair);
@ -85,6 +85,10 @@ QAction *AdBlockIcon::menuAction() {
return m_menuAction; return m_menuAction;
} }
void AdBlockIcon::activate() {
setEnabled(AdBlockManager::instance()->shouldBeEnabled());
}
void AdBlockIcon::createMenu(QMenu *menu) { void AdBlockIcon::createMenu(QMenu *menu) {
if (menu == NULL) { if (menu == NULL) {
menu = qobject_cast<QMenu*>(sender()); menu = qobject_cast<QMenu*>(sender());

View File

@ -38,6 +38,7 @@ class AdBlockIcon : public PlainToolButton {
QAction *menuAction(); QAction *menuAction();
public slots: public slots:
void activate();
void setEnabled(bool enabled); void setEnabled(bool enabled);
void createMenu(QMenu *menu = NULL); void createMenu(QMenu *menu = NULL);

View File

@ -173,6 +173,10 @@ AdBlockCustomList *AdBlockManager::customList() const {
return NULL; return NULL;
} }
bool AdBlockManager::shouldBeEnabled() {
return qApp->settings()->value(GROUP(AdBlock), SETTING(AdBlock::Enabled)).toBool();
}
void AdBlockManager::load() { void AdBlockManager::load() {
if (m_loaded) { if (m_loaded) {
// It is already loaded: subscriptions are loaded from files into objects, // It is already loaded: subscriptions are loaded from files into objects,
@ -327,6 +331,7 @@ AdBlockSubscription *AdBlockManager::subscriptionByName(const QString &name) con
AdBlockDialog *AdBlockManager::showDialog() { AdBlockDialog *AdBlockManager::showDialog() {
QPointer<AdBlockDialog> form_pointer = new AdBlockDialog(qApp->mainForm()); QPointer<AdBlockDialog> form_pointer = new AdBlockDialog(qApp->mainForm());
form_pointer.data()->setModal(true);
form_pointer.data()->show(); form_pointer.data()->show();
form_pointer.data()->raise(); form_pointer.data()->raise();
form_pointer.data()->activateWindow(); form_pointer.data()->activateWindow();

View File

@ -69,6 +69,8 @@ class AdBlockManager : public QObject {
AdBlockCustomList *customList() const; AdBlockCustomList *customList() const;
bool shouldBeEnabled();
static AdBlockManager *instance(); static AdBlockManager *instance();
signals: signals:

View File

@ -1,37 +1,21 @@
/* ============================================================ // This file is part of RSS Guard.
* QuiteRSS is a open-source cross-platform RSS/Atom news feeds reader //
* Copyright (C) 2011-2015 QuiteRSS Team <quiterssteam@gmail.com> // Copyright (C) 2014-2015 by Martin Rotter <rotter.martinos@gmail.com>
* // Copyright (C) 2010-2014 by David Rosca <nowrep@gmail.com>
* 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 // RSS Guard is free software: you can redistribute it and/or modify
* the Free Software Foundation, either version 3 of the License, or // it under the terms of the GNU General Public License as published by
* (at your option) any later version. // the Free Software Foundation, either version 3 of the License, or
* // (at your option) any later version.
* This program is distributed in the hope that it will be useful, //
* but WITHOUT ANY WARRANTY; without even the implied warranty of // RSS Guard is distributed in the hope that it will be useful,
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // but WITHOUT ANY WARRANTY; without even the implied warranty of
* GNU General Public License for more details. // 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 <http://www.gnu.org/licenses/>. // You should have received a copy of the GNU General Public License
* ============================================================ */ // along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
/* ============================================================
* QupZilla - WebKit based browser
* Copyright (C) 2010-2014 David Rosca <nowrep@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* ============================================================ */
/** /**
* Copyright (c) 2009, Zsombor Gegesy <gzsombor@gmail.com> * Copyright (c) 2009, Zsombor Gegesy <gzsombor@gmail.com>
* Copyright (c) 2009, Benjamin C. Meyer <ben@meyerhome.net> * Copyright (c) 2009, Benjamin C. Meyer <ben@meyerhome.net>
@ -61,13 +45,13 @@
* SUCH DAMAGE. * SUCH DAMAGE.
*/ */
#include "adblockrule.h" #include "network-web/adblock/adblockrule.h"
#include "adblocksubscription.h"
#include "adblockmanager.h"
#include "network-web/adblock/adblocksubscription.h"
#include "network-web/adblock/adblockmanager.h"
#include "network-web/webfactory.h"
#include "definitions/definitions.h" #include "definitions/definitions.h"
#include <QDebug>
#include <QUrl> #include <QUrl>
#include <QString> #include <QString>
#include <QStringList> #include <QStringList>
@ -75,63 +59,18 @@
#include <QWebFrame> #include <QWebFrame>
#include <QWebPage> #include <QWebPage>
// Version for Qt < 4.8 has one issue, it will wrongly
// count .co.uk (and others) as second-level domain
static QString toSecondLevelDomain(const QUrl &url)
{
#if QT_VERSION >= 0x040800
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(QL1C('.')) == 0) {
return urlHost;
}
while (domain.count(QL1C('.')) != 0) {
domain = domain.mid(domain.indexOf(QL1C('.')) + 1);
}
return domain + topLevelDomain;
#else
QString domain = url.host();
if (domain.count(QL1C('.')) == 0) {
return QString();
}
while (domain.count(QL1C('.')) != 1) {
domain = domain.mid(domain.indexOf(QL1C('.')) + 1);
}
return domain;
#endif
}
AdBlockRule::AdBlockRule(const QString &filter, AdBlockSubscription* subscription) AdBlockRule::AdBlockRule(const QString &filter, AdBlockSubscription* subscription)
: m_subscription(subscription) : m_subscription(subscription), m_type(StringContainsMatchRule), m_caseSensitivity(Qt::CaseInsensitive), m_isEnabled(true),
, m_type(StringContainsMatchRule) m_isException(false), m_isInternalDisabled(false), m_regExp(NULL) {
, m_caseSensitivity(Qt::CaseInsensitive)
, m_isEnabled(true)
, m_isException(false)
, m_isInternalDisabled(false)
, m_regExp(0)
{
setFilter(filter); setFilter(filter);
} }
AdBlockRule::~AdBlockRule() AdBlockRule::~AdBlockRule() {
{
delete m_regExp; delete m_regExp;
} }
AdBlockRule* AdBlockRule::copy() const AdBlockRule *AdBlockRule::copy() const {
{
AdBlockRule* rule = new AdBlockRule(); AdBlockRule* rule = new AdBlockRule();
rule->m_subscription = m_subscription; rule->m_subscription = m_subscription;
rule->m_type = m_type; rule->m_type = m_type;
@ -146,8 +85,8 @@ AdBlockRule* AdBlockRule::copy() const
rule->m_allowedDomains = m_allowedDomains; rule->m_allowedDomains = m_allowedDomains;
rule->m_blockedDomains = m_blockedDomains; rule->m_blockedDomains = m_blockedDomains;
if (m_regExp) { if (m_regExp != NULL) {
rule->m_regExp = new RegExp; rule->m_regExp = new RegExp();
rule->m_regExp->regExp = m_regExp->regExp; rule->m_regExp->regExp = m_regExp->regExp;
rule->m_regExp->matchers = m_regExp->matchers; rule->m_regExp->matchers = m_regExp->matchers;
} }
@ -155,96 +94,77 @@ AdBlockRule* AdBlockRule::copy() const
return rule; return rule;
} }
AdBlockSubscription* AdBlockRule::subscription() const AdBlockSubscription *AdBlockRule::subscription() const {
{
return m_subscription; return m_subscription;
} }
void AdBlockRule::setSubscription(AdBlockSubscription* subscription) void AdBlockRule::setSubscription(AdBlockSubscription *subscription) {
{
m_subscription = subscription; m_subscription = subscription;
} }
QString AdBlockRule::filter() const QString AdBlockRule::filter() const {
{
return m_filter; return m_filter;
} }
void AdBlockRule::setFilter(const QString &filter) void AdBlockRule::setFilter(const QString &filter) {
{
m_filter = filter; m_filter = filter;
parseFilter(); parseFilter();
} }
bool AdBlockRule::isCssRule() const bool AdBlockRule::isCssRule() const {
{
return m_type == CssRule; return m_type == CssRule;
} }
QString AdBlockRule::cssSelector() const QString AdBlockRule::cssSelector() const {
{
return m_matchString; return m_matchString;
} }
bool AdBlockRule::isDocument() const bool AdBlockRule::isDocument() const {
{
return hasOption(DocumentOption); return hasOption(DocumentOption);
} }
bool AdBlockRule::isElemhide() const bool AdBlockRule::isElemhide() const {
{
return hasOption(ElementHideOption); return hasOption(ElementHideOption);
} }
bool AdBlockRule::isDomainRestricted() const bool AdBlockRule::isDomainRestricted() const {
{
return hasOption(DomainRestrictedOption); return hasOption(DomainRestrictedOption);
} }
bool AdBlockRule::isException() const bool AdBlockRule::isException() const {
{
return m_isException; return m_isException;
} }
bool AdBlockRule::isComment() const bool AdBlockRule::isComment() const {
{
return m_filter.startsWith(QL1C('!')); return m_filter.startsWith(QL1C('!'));
} }
bool AdBlockRule::isEnabled() const bool AdBlockRule::isEnabled() const {
{
return m_isEnabled; return m_isEnabled;
} }
void AdBlockRule::setEnabled(bool enabled) void AdBlockRule::setEnabled(bool enabled) {
{
m_isEnabled = enabled; m_isEnabled = enabled;
} }
bool AdBlockRule::isSlow() const bool AdBlockRule::isSlow() const {
{ return m_regExp != NULL;
return m_regExp != 0;
} }
bool AdBlockRule::isInternalDisabled() const bool AdBlockRule::isInternalDisabled() const {
{
return m_isInternalDisabled; return m_isInternalDisabled;
} }
bool AdBlockRule::urlMatch(const QUrl &url) const bool AdBlockRule::urlMatch(const QUrl &url) const {
{
if (!hasOption(DocumentOption) && !hasOption(ElementHideOption)) { if (!hasOption(DocumentOption) && !hasOption(ElementHideOption)) {
return false; return false;
} }
else {
const QString encodedUrl = url.toEncoded(); return networkMatch(QNetworkRequest(url), url.host(), url.toEncoded());
const QString domain = url.host(); }
return networkMatch(QNetworkRequest(url), domain, encodedUrl);
} }
bool AdBlockRule::networkMatch(const QNetworkRequest &request, const QString &domain, const QString &encodedUrl) const bool AdBlockRule::networkMatch(const QNetworkRequest &request, const QString &domain, const QString &encoded_url) const {
{
if (m_type == CssRule || !m_isEnabled || m_isInternalDisabled) { if (m_type == CssRule || !m_isEnabled || m_isInternalDisabled) {
return false; return false;
} }
@ -252,39 +172,39 @@ bool AdBlockRule::networkMatch(const QNetworkRequest &request, const QString &do
bool matched = false; bool matched = false;
if (m_type == StringContainsMatchRule) { if (m_type == StringContainsMatchRule) {
matched = encodedUrl.contains(m_matchString, m_caseSensitivity); matched = encoded_url.contains(m_matchString, m_caseSensitivity);
} }
else if (m_type == DomainMatchRule) { else if (m_type == DomainMatchRule) {
matched = isMatchingDomain(domain, m_matchString); matched = isMatchingDomain(domain, m_matchString);
} }
else if (m_type == StringEndsMatchRule) { else if (m_type == StringEndsMatchRule) {
matched = encodedUrl.endsWith(m_matchString, m_caseSensitivity); matched = encoded_url.endsWith(m_matchString, m_caseSensitivity);
} }
else if (m_type == RegExpMatchRule) { else if (m_type == RegExpMatchRule) {
if (!isMatchingRegExpStrings(encodedUrl)) { if (!isMatchingRegExpStrings(encoded_url)) {
return false; return false;
} }
matched = (m_regExp->regExp.indexIn(encodedUrl) != -1); matched = (m_regExp->regExp.indexIn(encoded_url) != -1);
} }
if (matched) { if (matched) {
// Check domain restrictions // Check domain restrictions.
if (hasOption(DomainRestrictedOption) && !matchDomain(domain)) { if (hasOption(DomainRestrictedOption) && !matchDomain(domain)) {
return false; return false;
} }
// Check third-party restriction // Check third-party restriction.
if (hasOption(ThirdPartyOption) && !matchThirdParty(request)) { if (hasOption(ThirdPartyOption) && !matchThirdParty(request)) {
return false; return false;
} }
// Check object restrictions // Check object restrictions.
if (hasOption(ObjectOption) && !matchObject(request)) { if (hasOption(ObjectOption) && !matchObject(request)) {
return false; return false;
} }
// Check subdocument restriction // Check subdocument restriction.
if (hasOption(SubdocumentOption) && !matchSubdocument(request)) { if (hasOption(SubdocumentOption) && !matchSubdocument(request)) {
return false; return false;
} }
@ -295,7 +215,7 @@ bool AdBlockRule::networkMatch(const QNetworkRequest &request, const QString &do
} }
// Check image restriction // Check image restriction
if (hasOption(ImageOption) && !matchImage(encodedUrl)) { if (hasOption(ImageOption) && !matchImage(encoded_url)) {
return false; return false;
} }
} }
@ -303,8 +223,7 @@ bool AdBlockRule::networkMatch(const QNetworkRequest &request, const QString &do
return matched; return matched;
} }
bool AdBlockRule::matchDomain(const QString &domain) const bool AdBlockRule::matchDomain(const QString &domain) const {
{
if (!m_isEnabled) { if (!m_isEnabled) {
return false; return false;
} }
@ -326,6 +245,7 @@ bool AdBlockRule::matchDomain(const QString &domain) const
return false; return false;
} }
} }
return true; return true;
} }
else { else {
@ -345,39 +265,38 @@ bool AdBlockRule::matchDomain(const QString &domain) const
return false; return false;
} }
bool AdBlockRule::matchThirdParty(const QNetworkRequest &request) const bool AdBlockRule::matchThirdParty(const QNetworkRequest &request) const {
{
const QString referer = request.attribute(QNetworkRequest::Attribute(QNetworkRequest::User + 151), QString()).toString(); const QString referer = request.attribute(QNetworkRequest::Attribute(QNetworkRequest::User + 151), QString()).toString();
if (referer.isEmpty()) { if (referer.isEmpty()) {
return false; return false;
} }
// Third-party matching should be performed on second-level domains // Third-party matching should be performed on second-level domains.
const QString refererHost = toSecondLevelDomain(QUrl(referer)); const QString refererHost = WebFactory::instance()->toSecondLevelDomain(QUrl(referer));
const QString host = toSecondLevelDomain(request.url()); const QString host = WebFactory::instance()->toSecondLevelDomain(request.url());
bool match = refererHost != host; bool match = refererHost != host;
return hasException(ThirdPartyOption) ? !match : match; return hasException(ThirdPartyOption) ? !match : match;
} }
bool AdBlockRule::matchObject(const QNetworkRequest &request) const bool AdBlockRule::matchObject(const QNetworkRequest &request) const {
{
bool match = request.attribute(QNetworkRequest::Attribute(QNetworkRequest::User + 150)).toString() == QL1S("object"); bool match = request.attribute(QNetworkRequest::Attribute(QNetworkRequest::User + 150)).toString() == QL1S("object");
return hasException(ObjectOption) ? !match : match; return hasException(ObjectOption) ? !match : match;
} }
bool AdBlockRule::matchSubdocument(const QNetworkRequest &request) const bool AdBlockRule::matchSubdocument(const QNetworkRequest &request) const {
{ QWebFrame *originatingFrame = static_cast<QWebFrame*>(request.originatingObject());
QWebFrame* originatingFrame = static_cast<QWebFrame*>(request.originatingObject());
if (!originatingFrame) { if (originatingFrame == NULL) {
return false; return false;
} }
QWebPage* page = originatingFrame->page(); QWebPage *page = originatingFrame->page();
if (!page) {
if (page == NULL) {
return false; return false;
} }
@ -386,65 +305,62 @@ bool AdBlockRule::matchSubdocument(const QNetworkRequest &request) const
return hasException(SubdocumentOption) ? !match : match; return hasException(SubdocumentOption) ? !match : match;
} }
bool AdBlockRule::matchXmlHttpRequest(const QNetworkRequest &request) const bool AdBlockRule::matchXmlHttpRequest(const QNetworkRequest &request) const {
{
bool match = request.rawHeader("X-Requested-With") == QByteArray("XMLHttpRequest"); bool match = request.rawHeader("X-Requested-With") == QByteArray("XMLHttpRequest");
return hasException(XMLHttpRequestOption) ? !match : match; return hasException(XMLHttpRequestOption) ? !match : match;
} }
bool AdBlockRule::matchImage(const QString &encodedUrl) const bool AdBlockRule::matchImage(const QString &encoded_url) const {
{ bool match = encoded_url.endsWith(QL1S(".png")) ||
bool match = encodedUrl.endsWith(QL1S(".png")) || encoded_url.endsWith(QL1S(".jpg")) ||
encodedUrl.endsWith(QL1S(".jpg")) || encoded_url.endsWith(QL1S(".gif")) ||
encodedUrl.endsWith(QL1S(".gif")) || encoded_url.endsWith(QL1S(".jpeg"));
encodedUrl.endsWith(QL1S(".jpeg"));
return hasException(ImageOption) ? !match : match; return hasException(ImageOption) ? !match : match;
} }
void AdBlockRule::parseFilter() void AdBlockRule::parseFilter() {
{ QString parsed_line = m_filter;
QString parsedLine = m_filter;
// Empty rule or just comment // Empty rule or just comment.
if (m_filter.trimmed().isEmpty() || m_filter.startsWith(QL1C('!'))) { if (m_filter.trimmed().isEmpty() || m_filter.startsWith(QL1C('!'))) {
// We want to differentiate rule disabled by user and rule disabled in subscription file // 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_isInternalDisabled is also used when rule is disabled due to all options not being supported.
m_isEnabled = false; m_isEnabled = false;
m_isInternalDisabled = true; m_isInternalDisabled = true;
m_type = Invalid; m_type = Invalid;
return; return;
} }
// CSS Element hiding rule // CSS Element hiding rule.
if (parsedLine.contains(QL1S("##")) || parsedLine.contains(QL1S("#@#"))) { if (parsed_line.contains(QL1S("##")) || parsed_line.contains(QL1S("#@#"))) {
m_type = CssRule; m_type = CssRule;
int pos = parsedLine.indexOf(QL1C('#')); int pos = parsed_line.indexOf(QL1C('#'));
// Domain restricted rule // Domain restricted rule
if (!parsedLine.startsWith(QL1S("##"))) { if (!parsed_line.startsWith(QL1S("##"))) {
QString domains = parsedLine.left(pos); QString domains = parsed_line.left(pos);
parseDomains(domains, QL1C(',')); parseDomains(domains, QL1C(','));
} }
m_isException = parsedLine.at(pos + 1) == QL1C('@'); m_isException = parsed_line.at(pos + 1) == QL1C('@');
m_matchString = parsedLine.mid(m_isException ? pos + 3 : pos + 2); m_matchString = parsed_line.mid(m_isException ? pos + 3 : pos + 2);
// CSS rule cannot have more options -> stop parsing // CSS rule cannot have more options -> stop parsing.
return; return;
} }
// Exception always starts with @@ // Exception always starts with @@
if (parsedLine.startsWith(QL1S("@@"))) { if (parsed_line.startsWith(QL1S("@@"))) {
m_isException = true; m_isException = true;
parsedLine = parsedLine.mid(2); parsed_line = parsed_line.mid(2);
} }
// Parse all options following $ char // Parse all options following $ char.
int optionsIndex = parsedLine.indexOf(QL1C('$')); int optionsIndex = parsed_line.indexOf(QL1C('$'));
if (optionsIndex >= 0) { if (optionsIndex >= 0) {
const QStringList options = parsedLine.mid(optionsIndex + 1).split(QL1C(','), QString::SkipEmptyParts); const QStringList options = parsed_line.mid(optionsIndex + 1).split(QL1C(','), QString::SkipEmptyParts);
int handledOptions = 0; int handledOptions = 0;
foreach (const QString &option, options) { foreach (const QString &option, options) {
@ -490,92 +406,90 @@ void AdBlockRule::parseFilter()
++handledOptions; ++handledOptions;
} }
else if (option == QL1S("collapse")) { else if (option == QL1S("collapse")) {
// Hiding placeholders of blocked elements is enabled by default // Hiding placeholders of blocked elements is enabled by default.
++handledOptions; ++handledOptions;
} }
} }
// If we don't handle all options, it's safer to just disable this rule // If we don't handle all options, it's safer to just disable this rule.
if (handledOptions != options.count()) { if (handledOptions != options.count()) {
m_isInternalDisabled = true; m_isInternalDisabled = true;
m_type = Invalid; m_type = Invalid;
return; return;
} }
parsedLine = parsedLine.left(optionsIndex); parsed_line = parsed_line.left(optionsIndex);
} }
// Rule is classic regexp // Rule is classic regexp.
if (parsedLine.startsWith(QL1C('/')) && parsedLine.endsWith(QL1C('/'))) { if (parsed_line.startsWith(QL1C('/')) && parsed_line.endsWith(QL1C('/'))) {
parsedLine = parsedLine.mid(1); parsed_line = parsed_line.mid(1);
parsedLine = parsedLine.left(parsedLine.size() - 1); parsed_line = parsed_line.left(parsed_line.size() - 1);
m_type = RegExpMatchRule; m_type = RegExpMatchRule;
m_regExp = new RegExp; m_regExp = new RegExp();
m_regExp->regExp = QRegExp(parsedLine, m_caseSensitivity); m_regExp->regExp = QRegExp(parsed_line, m_caseSensitivity);
m_regExp->matchers = createStringMatchers(parseRegExpFilter(parsedLine)); m_regExp->matchers = createStringMatchers(parseRegExpFilter(parsed_line));
return; return;
} }
// Remove starting and ending wildcards (*) // Remove starting and ending wildcards (*).
if (parsedLine.startsWith(QL1C('*'))) { if (parsed_line.startsWith(QL1C('*'))) {
parsedLine = parsedLine.mid(1); parsed_line = parsed_line.mid(1);
} }
if (parsedLine.endsWith(QL1C('*'))) { if (parsed_line.endsWith(QL1C('*'))) {
parsedLine = parsedLine.left(parsedLine.size() - 1); parsed_line = parsed_line.left(parsed_line.size() - 1);
} }
// We can use fast string matching for domain here // We can use fast string matching for domain here.
if (filterIsOnlyDomain(parsedLine)) { if (filterIsOnlyDomain(parsed_line)) {
parsedLine = parsedLine.mid(2); parsed_line = parsed_line.mid(2);
parsedLine = parsedLine.left(parsedLine.size() - 1); parsed_line = parsed_line.left(parsed_line.size() - 1);
m_type = DomainMatchRule; m_type = DomainMatchRule;
m_matchString = parsedLine; m_matchString = parsed_line;
return; return;
} }
// If rule contains only | at end, we can also use string matching // If rule contains only | at end, we can also use string matching.
if (filterIsOnlyEndsMatch(parsedLine)) { if (filterIsOnlyEndsMatch(parsed_line)) {
parsedLine = parsedLine.left(parsedLine.size() - 1); parsed_line = parsed_line.left(parsed_line.size() - 1);
m_type = StringEndsMatchRule; m_type = StringEndsMatchRule;
m_matchString = parsedLine; m_matchString = parsed_line;
return; return;
} }
// If we still find a wildcard (*) or separator (^) or (|) // If we still find a wildcard (*) or separator (^) or (|)
// we must modify parsedLine to comply with QzRegExp // we must modify parsedLine to comply with QzRegExp.
if (parsedLine.contains(QL1C('*')) || if (parsed_line.contains(QL1C('*')) ||
parsedLine.contains(QL1C('^')) || parsed_line.contains(QL1C('^')) ||
parsedLine.contains(QL1C('|')) parsed_line.contains(QL1C('|'))
) { ) {
m_type = RegExpMatchRule; m_type = RegExpMatchRule;
m_regExp = new RegExp; m_regExp = new RegExp;
m_regExp->regExp = QRegExp(createRegExpFromFilter(parsedLine), m_caseSensitivity); m_regExp->regExp = QRegExp(createRegExpFromFilter(parsed_line), m_caseSensitivity);
m_regExp->matchers = createStringMatchers(parseRegExpFilter(parsedLine)); m_regExp->matchers = createStringMatchers(parseRegExpFilter(parsed_line));
return; return;
} }
// We haven't found anything that needs use of regexp, yay! // We haven't found anything that needs use of regexp, yay!
m_type = StringContainsMatchRule; m_type = StringContainsMatchRule;
m_matchString = parsedLine; m_matchString = parsed_line;
} }
void AdBlockRule::parseDomains(const QString &domains, const QChar &separator) void AdBlockRule::parseDomains(const QString &domains, const QChar &separator) {
{ QStringList domains_list = domains.split(separator, QString::SkipEmptyParts);
QStringList domainsList = domains.split(separator, QString::SkipEmptyParts);
foreach (const QString domain, domainsList) { foreach (const QString domain, domains_list) {
if (domain.isEmpty()) { if (!domain.isEmpty()) {
continue; if (domain.startsWith(QL1C('~'))) {
} m_blockedDomains.append(domain.mid(1));
if (domain.startsWith(QL1C('~'))) { }
m_blockedDomains.append(domain.mid(1)); else {
} m_allowedDomains.append(domain);
else { }
m_allowedDomains.append(domain);
} }
} }
@ -584,91 +498,94 @@ void AdBlockRule::parseDomains(const QString &domains, const QChar &separator)
} }
} }
bool AdBlockRule::filterIsOnlyDomain(const QString &filter) const bool AdBlockRule::filterIsOnlyDomain(const QString &filter) const {
{ if (!filter.endsWith(QL1C('^')) || !filter.startsWith(QL1S("||"))) {
if (!filter.endsWith(QL1C('^')) || !filter.startsWith(QL1S("||")))
return false; return false;
}
for (int i = 0; i < filter.size(); ++i) { for (int i = 0; i < filter.size(); i++) {
switch (filter.at(i).toLatin1()) { switch (filter.at(i).toLatin1()) {
case '/': case '/':
case ':': case ':':
case '?': case '?':
case '=': case '=':
case '&': case '&':
case '*': case '*':
return false; return false;
default:
break; default:
break;
} }
} }
return true; return true;
} }
bool AdBlockRule::filterIsOnlyEndsMatch(const QString &filter) const bool AdBlockRule::filterIsOnlyEndsMatch(const QString &filter) const {
{
for (int i = 0; i < filter.size(); ++i) { for (int i = 0; i < filter.size(); ++i) {
switch (filter.at(i).toLatin1()) { switch (filter.at(i).toLatin1()) {
case '^': case '^':
case '*': case '*':
return false; return false;
case '|':
return i == filter.size() - 1; case '|':
default: return i == filter.size() - 1;
break;
default:
break;
} }
} }
return false; return false;
} }
static bool wordCharacter(const QChar &c) static bool wordCharacter(const QChar &c) {
{
return c.isLetterOrNumber() || c.isMark() || c == QL1C('_'); return c.isLetterOrNumber() || c.isMark() || c == QL1C('_');
} }
QString AdBlockRule::createRegExpFromFilter(const QString &filter) const QString AdBlockRule::createRegExpFromFilter(const QString &filter) const {
{
QString parsed; QString parsed;
parsed.reserve(filter.size()); parsed.reserve(filter.size());
bool hadWildcard = false; // Filter multiple wildcards bool hadWildcard = false; // Filter multiple wildcards.
for (int i = 0; i < filter.size(); ++i) { for (int i = 0; i < filter.size(); i++) {
const QChar c = filter.at(i); const QChar c = filter.at(i);
switch (c.toLatin1()) { switch (c.toLatin1()) {
case '^': case '^':
parsed.append(QL1S("(?:[^\\w\\d\\-.%]|$)")); parsed.append(QL1S("(?:[^\\w\\d\\-.%]|$)"));
break; break;
case '*': case '*':
if (!hadWildcard) if (!hadWildcard)
parsed.append(QL1S(".*")); parsed.append(QL1S(".*"));
break; break;
case '|': case '|':
if (i == 0) { if (i == 0) {
if (filter.size() > 1 && filter.at(1) == QL1C('|')) { if (filter.size() > 1 && filter.at(1) == QL1C('|')) {
parsed.append(QL1S("^[\\w\\-]+:\\/+(?!\\/)(?:[^\\/]+\\.)?")); parsed.append(QL1S("^[\\w\\-]+:\\/+(?!\\/)(?:[^\\/]+\\.)?"));
i++; i++;
}
else {
parsed.append('^');
}
break;
}
else if (i == filter.size() - 1) {
parsed.append(QL1C('$'));
break;
}
// Fall through.
default:
if (!wordCharacter(c)) {
parsed.append(QL1C('\\') + c);
} }
else { else {
parsed.append('^'); parsed.append(c);
} }
break;
}
else if (i == filter.size() - 1) {
parsed.append(QL1C('$'));
break;
}
// fallthrough
default:
if (!wordCharacter(c))
parsed.append(QL1C('\\') + c);
else
parsed.append(c);
} }
hadWildcard = c == QL1C('*'); hadWildcard = c == QL1C('*');
@ -677,8 +594,7 @@ QString AdBlockRule::createRegExpFromFilter(const QString &filter) const
return parsed; return parsed;
} }
QList<QStringMatcher> AdBlockRule::createStringMatchers(const QStringList &filters) const QList<QStringMatcher> AdBlockRule::createStringMatchers(const QStringList &filters) const {
{
QList<QStringMatcher> matchers; QList<QStringMatcher> matchers;
matchers.reserve(filters.size()); matchers.reserve(filters.size());
@ -689,8 +605,7 @@ QList<QStringMatcher> AdBlockRule::createStringMatchers(const QStringList &filte
return matchers; return matchers;
} }
bool AdBlockRule::isMatchingDomain(const QString &domain, const QString &pattern) const bool AdBlockRule::isMatchingDomain(const QString &domain, const QString &pattern) const {
{
if (pattern == domain) { if (pattern == domain) {
return true; return true;
} }
@ -704,62 +619,63 @@ bool AdBlockRule::isMatchingDomain(const QString &domain, const QString &pattern
return index > 0 && domain[index - 1] == QLatin1Char('.'); return index > 0 && domain[index - 1] == QLatin1Char('.');
} }
bool AdBlockRule::isMatchingRegExpStrings(const QString &url) const bool AdBlockRule::isMatchingRegExpStrings(const QString &url) const {
{
Q_ASSERT(m_regExp); Q_ASSERT(m_regExp);
foreach (const QStringMatcher &matcher, m_regExp->matchers) { foreach (const QStringMatcher &matcher, m_regExp->matchers) {
if (matcher.indexIn(url) == -1) if (matcher.indexIn(url) == -1) {
return false; return false;
}
} }
return true; return true;
} }
// Split regexp filter into strings that can be used with QString::contains // Split regexp filter into strings that can be used with QString::contains.
// Don't use parts that contains only 1 char and duplicated parts // Don't use parts that contains only 1 char and duplicated parts.
QStringList AdBlockRule::parseRegExpFilter(const QString &filter) const QStringList AdBlockRule::parseRegExpFilter(const QString &filter) const {
{
QStringList list; QStringList list;
int startPos = -1; int start_pos = -1;
for (int i = 0; i < filter.size(); ++i) { for (int i = 0; i < filter.size(); i++) {
const QChar c = filter.at(i); const QChar c = filter.at(i);
// Meta characters in AdBlock rules are | * ^
// Meta characters in AdBlock rules are "| * ^".
if (c == QL1C('|') || c == QL1C('*') || c == QL1C('^')) { if (c == QL1C('|') || c == QL1C('*') || c == QL1C('^')) {
const QString sub = filter.mid(startPos, i - startPos); const QString sub = filter.mid(start_pos, i - start_pos);
if (sub.size() > 1)
if (sub.size() > 1) {
list.append(sub); list.append(sub);
startPos = i + 1; }
start_pos = i + 1;
} }
} }
const QString sub = filter.mid(startPos); const QString sub = filter.mid(start_pos);
if (sub.size() > 1)
if (sub.size() > 1) {
list.append(sub); list.append(sub);
}
list.removeDuplicates(); list.removeDuplicates();
return list; return list;
} }
bool AdBlockRule::hasOption(const AdBlockRule::RuleOption &opt) const bool AdBlockRule::hasOption(const AdBlockRule::RuleOption &opt) const {
{
return (m_options & opt); return (m_options & opt);
} }
bool AdBlockRule::hasException(const AdBlockRule::RuleOption &opt) const bool AdBlockRule::hasException(const AdBlockRule::RuleOption &opt) const {
{
return (m_exceptions & opt); return (m_exceptions & opt);
} }
void AdBlockRule::setOption(const AdBlockRule::RuleOption &opt) void AdBlockRule::setOption(const AdBlockRule::RuleOption &opt) {
{
m_options |= opt; m_options |= opt;
} }
void AdBlockRule::setException(const AdBlockRule::RuleOption &opt, bool on) void AdBlockRule::setException(const AdBlockRule::RuleOption &opt, bool on) {
{
if (on) { if (on) {
m_exceptions |= opt; m_exceptions |= opt;
} }

View File

@ -1,37 +1,21 @@
/* ============================================================ // This file is part of RSS Guard.
* QuiteRSS is a open-source cross-platform RSS/Atom news feeds reader //
* Copyright (C) 2011-2015 QuiteRSS Team <quiterssteam@gmail.com> // Copyright (C) 2014-2015 by Martin Rotter <rotter.martinos@gmail.com>
* // Copyright (C) 2010-2014 by David Rosca <nowrep@gmail.com>
* 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 // RSS Guard is free software: you can redistribute it and/or modify
* the Free Software Foundation, either version 3 of the License, or // it under the terms of the GNU General Public License as published by
* (at your option) any later version. // the Free Software Foundation, either version 3 of the License, or
* // (at your option) any later version.
* This program is distributed in the hope that it will be useful, //
* but WITHOUT ANY WARRANTY; without even the implied warranty of // RSS Guard is distributed in the hope that it will be useful,
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // but WITHOUT ANY WARRANTY; without even the implied warranty of
* GNU General Public License for more details. // 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 <http://www.gnu.org/licenses/>. // You should have received a copy of the GNU General Public License
* ============================================================ */ // along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
/* ============================================================
* QupZilla - WebKit based browser
* Copyright (C) 2010-2014 David Rosca <nowrep@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* ============================================================ */
/** /**
* Copyright (c) 2009, Benjamin C. Meyer <ben@meyerhome.net> * Copyright (c) 2009, Benjamin C. Meyer <ben@meyerhome.net>
* *
@ -71,120 +55,125 @@ class QUrl;
class AdBlockSubscription; class AdBlockSubscription;
class AdBlockRule class AdBlockRule {
{ friend class AdBlockMatcher;
public: friend class AdBlockSearchTree;
AdBlockRule(const QString &filter = QString(), AdBlockSubscription* subscription = NULL); friend class AdBlockSubscription;
~AdBlockRule();
AdBlockRule* copy() const; public:
explicit AdBlockRule(const QString &filter = QString(), AdBlockSubscription* subscription = NULL);
virtual ~AdBlockRule();
AdBlockSubscription* subscription() const; AdBlockRule *copy() const;
void setSubscription(AdBlockSubscription* subscription);
QString filter() const; AdBlockSubscription *subscription() const;
void setFilter(const QString &filter); void setSubscription(AdBlockSubscription *subscription);
bool isCssRule() const; QString filter() const;
QString cssSelector() const; void setFilter(const QString &filter);
bool isDocument() const; bool isCssRule() const;
bool isElemhide() const; QString cssSelector() const;
bool isDomainRestricted() const; bool isDocument() const;
bool isException() const; bool isElemhide() const;
bool isComment() const; bool isDomainRestricted() const;
bool isEnabled() const; bool isException() const;
void setEnabled(bool enabled);
bool isSlow() const; bool isComment() const;
bool isInternalDisabled() const; bool isEnabled() const;
void setEnabled(bool enabled);
bool urlMatch(const QUrl &url) const; bool isSlow() const;
bool networkMatch(const QNetworkRequest &request, const QString &domain, const QString &encodedUrl) const; bool isInternalDisabled() const;
bool matchDomain(const QString &domain) const; bool urlMatch(const QUrl &url) const;
bool matchThirdParty(const QNetworkRequest &request) const; bool networkMatch(const QNetworkRequest &request, const QString &domain, const QString &encoded_url) const;
bool matchObject(const QNetworkRequest &request) const;
bool matchSubdocument(const QNetworkRequest &request) const;
bool matchXmlHttpRequest(const QNetworkRequest &request) const;
bool matchImage(const QString &encodedUrl) const;
protected: bool matchDomain(const QString &domain) const;
bool isMatchingDomain(const QString &domain, const QString &pattern) const; bool matchThirdParty(const QNetworkRequest &request) const;
bool isMatchingRegExpStrings(const QString &url) const; bool matchObject(const QNetworkRequest &request) const;
QStringList parseRegExpFilter(const QString &filter) const; bool matchSubdocument(const QNetworkRequest &request) const;
bool matchXmlHttpRequest(const QNetworkRequest &request) const;
bool matchImage(const QString &encoded_url) const;
private: protected:
enum RuleType { bool isMatchingDomain(const QString &domain, const QString &pattern) const;
CssRule = 0, bool isMatchingRegExpStrings(const QString &url) const;
DomainMatchRule = 1, QStringList parseRegExpFilter(const QString &filter) const;
RegExpMatchRule = 2,
StringEndsMatchRule = 3,
StringContainsMatchRule = 4,
Invalid = 5
};
enum RuleOption { private:
DomainRestrictedOption = 1, enum RuleType {
ThirdPartyOption = 2, CssRule = 0,
ObjectOption = 4, DomainMatchRule = 1,
SubdocumentOption = 8, RegExpMatchRule = 2,
XMLHttpRequestOption = 16, StringEndsMatchRule = 3,
ImageOption = 32, StringContainsMatchRule = 4,
Invalid = 5
};
// Exception only options enum RuleOption {
DocumentOption = 64, DomainRestrictedOption = 1,
ElementHideOption = 128 ThirdPartyOption = 2,
}; ObjectOption = 4,
SubdocumentOption = 8,
XMLHttpRequestOption = 16,
ImageOption = 32,
Q_DECLARE_FLAGS(RuleOptions, RuleOption) // Exception only options.
DocumentOption = 64,
ElementHideOption = 128
};
inline bool hasOption(const RuleOption &opt) const; Q_DECLARE_FLAGS(RuleOptions, RuleOption)
inline bool hasException(const RuleOption &opt) const;
inline void setOption(const RuleOption &opt); inline bool hasOption(const RuleOption &opt) const;
inline void setException(const RuleOption &opt, bool on); inline bool hasException(const RuleOption &opt) const;
void parseFilter(); inline void setOption(const RuleOption &opt);
void parseDomains(const QString &domains, const QChar &separator); inline void setException(const RuleOption &opt, bool on);
bool filterIsOnlyDomain(const QString &filter) const;
bool filterIsOnlyEndsMatch(const QString &filter) const;
QString createRegExpFromFilter(const QString &filter) const;
QList<QStringMatcher> createStringMatchers(const QStringList &filters) const;
AdBlockSubscription* m_subscription; void parseFilter();
void parseDomains(const QString &domains, const QChar &separator);
bool filterIsOnlyDomain(const QString &filter) const;
bool filterIsOnlyEndsMatch(const QString &filter) const;
QString createRegExpFromFilter(const QString &filter) const;
QList<QStringMatcher> createStringMatchers(const QStringList &filters) const;
RuleType m_type; AdBlockSubscription *m_subscription;
RuleOptions m_options;
RuleOptions m_exceptions;
// Original rule filter RuleType m_type;
QString m_filter; RuleOptions m_options;
// Parsed rule for string matching (CSS Selector for CSS rules) RuleOptions m_exceptions;
QString m_matchString;
// Case sensitivity for string matching
Qt::CaseSensitivity m_caseSensitivity;
bool m_isEnabled; // Original rule filter.
bool m_isException; QString m_filter;
bool m_isInternalDisabled;
QStringList m_allowedDomains; // Parsed rule for string matching (CSS Selector for CSS rules).
QStringList m_blockedDomains; QString m_matchString;
struct RegExp { // Case sensitivity for string matching.
QRegExp regExp; Qt::CaseSensitivity m_caseSensitivity;
QList<QStringMatcher> matchers;
};
// Use dynamic allocation to save memory bool m_isEnabled;
RegExp* m_regExp; bool m_isException;
bool m_isInternalDisabled;
friend class AdBlockMatcher; QStringList m_allowedDomains;
friend class AdBlockSearchTree; QStringList m_blockedDomains;
friend class AdBlockSubscription;
struct RegExp {
public:
explicit RegExp() {
}
QRegExp regExp;
QList<QStringMatcher> matchers;
};
// Use dynamic allocation to save memory
RegExp *m_regExp;
}; };
#endif // ADBLOCKRULE_H #endif // ADBLOCKRULE_H

View File

@ -1,60 +1,38 @@
/* ============================================================ // This file is part of RSS Guard.
* QuiteRSS is a open-source cross-platform RSS/Atom news feeds reader //
* Copyright (C) 2011-2015 QuiteRSS Team <quiterssteam@gmail.com> // Copyright (C) 2014-2015 by Martin Rotter <rotter.martinos@gmail.com>
* // Copyright (C) 2010-2014 by David Rosca <nowrep@gmail.com>
* 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 // RSS Guard is free software: you can redistribute it and/or modify
* the Free Software Foundation, either version 3 of the License, or // it under the terms of the GNU General Public License as published by
* (at your option) any later version. // the Free Software Foundation, either version 3 of the License, or
* // (at your option) any later version.
* This program is distributed in the hope that it will be useful, //
* but WITHOUT ANY WARRANTY; without even the implied warranty of // RSS Guard is distributed in the hope that it will be useful,
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // but WITHOUT ANY WARRANTY; without even the implied warranty of
* GNU General Public License for more details. // 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 <http://www.gnu.org/licenses/>. // You should have received a copy of the GNU General Public License
* ============================================================ */ // along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
/* ============================================================
* QupZilla - WebKit based browser
* Copyright (C) 2013-2014 David Rosca <nowrep@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* ============================================================ */
#include "adblocksearchtree.h"
#include "adblockrule.h"
#include <QDebug> #include "network-web/adblock/adblocksearchtree.h"
#include "network-web/adblock/adblockrule.h"
AdBlockSearchTree::AdBlockSearchTree()
: m_root(new Node) AdBlockSearchTree::AdBlockSearchTree() : m_root(new Node()) {
{
} }
AdBlockSearchTree::~AdBlockSearchTree() AdBlockSearchTree::~AdBlockSearchTree() {
{
deleteNode(m_root); deleteNode(m_root);
} }
void AdBlockSearchTree::clear() void AdBlockSearchTree::clear() {
{
deleteNode(m_root); deleteNode(m_root);
m_root = new Node; m_root = new Node();
} }
bool AdBlockSearchTree::add(const AdBlockRule* rule) bool AdBlockSearchTree::add(const AdBlockRule *rule) {
{
if (rule->m_type != AdBlockRule::StringContainsMatchRule) { if (rule->m_type != AdBlockRule::StringContainsMatchRule) {
return false; return false;
} }
@ -63,16 +41,17 @@ bool AdBlockSearchTree::add(const AdBlockRule* rule)
int len = filter.size(); int len = filter.size();
if (len <= 0) { if (len <= 0) {
qDebug() << "AdBlockSearchTree: Inserting rule with filter len <= 0!"; qWarning("Inserting rule with filter len <= 0!");
return false; return false;
} }
Node* node = m_root; Node *node = m_root;
for (int i = 0; i < len; ++i) { for (int i = 0; i < len; i++) {
const QChar c = filter.at(i); const QChar c = filter.at(i);
if (!node->children.contains(c)) { if (!node->children.contains(c)) {
Node* n = new Node; Node *n = new Node();
n->c = c; n->c = c;
node->children[c] = n; node->children[c] = n;
@ -86,19 +65,20 @@ bool AdBlockSearchTree::add(const AdBlockRule* rule)
return true; return true;
} }
const AdBlockRule* AdBlockSearchTree::find(const QNetworkRequest &request, const QString &domain, const QString &urlString) const const AdBlockRule *AdBlockSearchTree::find(const QNetworkRequest &request, const QString &domain,
{ const QString &url_string) const {
int len = urlString.size(); int len = url_string.size();
if (len <= 0) { if (len <= 0) {
return NULL; return NULL;
} }
const QChar* string = urlString.constData(); const QChar *string = url_string.constData();
for (int i = 0; i < len; ++i) { for (int i = 0; i < len; i++) {
const AdBlockRule* rule = prefixSearch(request, domain, urlString, string++, len - i); const AdBlockRule *rule = prefixSearch(request, domain, url_string, string++, len - i);
if (rule) {
if (rule != NULL) {
return rule; return rule;
} }
} }
@ -106,48 +86,48 @@ const AdBlockRule* AdBlockSearchTree::find(const QNetworkRequest &request, const
return NULL; return NULL;
} }
const AdBlockRule* AdBlockSearchTree::prefixSearch(const QNetworkRequest &request, const QString &domain, const QString &urlString, const QChar* string, int len) const const AdBlockRule *AdBlockSearchTree::prefixSearch(const QNetworkRequest &request, const QString &domain,
{ const QString &url_string, const QChar* string, int len) const {
if (len <= 0) { if (len <= 0) {
return 0; return NULL;
} }
QChar c = string[0]; QChar c = string[0];
if (!m_root->children.contains(c)) { if (!m_root->children.contains(c)) {
return 0; return NULL;
} }
Node* node = m_root->children[c]; Node *node = m_root->children[c];
for (int i = 1; i < len; ++i) { for (int i = 1; i < len; i++) {
const QChar c = (++string)[0]; const QChar c = (++string)[0];
if (node->rule && node->rule->networkMatch(request, domain, urlString)) { if (node->rule && node->rule->networkMatch(request, domain, url_string)) {
return node->rule; return node->rule;
} }
if (!node->children.contains(c)) { if (!node->children.contains(c)) {
return 0; return NULL;
} }
node = node->children[c]; node = node->children[c];
} }
if (node->rule && node->rule->networkMatch(request, domain, urlString)) { if (node->rule && node->rule->networkMatch(request, domain, url_string)) {
return node->rule; return node->rule;
} }
return 0; return NULL;
} }
void AdBlockSearchTree::deleteNode(AdBlockSearchTree::Node* node) void AdBlockSearchTree::deleteNode(Node *node) {
{ if (node == NULL) {
if (!node) {
return; return;
} }
QHashIterator<QChar, Node*> i(node->children); QHashIterator<QChar,Node*> i(node->children);
while (i.hasNext()) { while (i.hasNext()) {
i.next(); i.next();
deleteNode(i.value()); deleteNode(i.value());

View File

@ -1,73 +1,57 @@
/* ============================================================ // This file is part of RSS Guard.
* QuiteRSS is a open-source cross-platform RSS/Atom news feeds reader //
* Copyright (C) 2011-2015 QuiteRSS Team <quiterssteam@gmail.com> // Copyright (C) 2014-2015 by Martin Rotter <rotter.martinos@gmail.com>
* // Copyright (C) 2010-2014 by David Rosca <nowrep@gmail.com>
* 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 // RSS Guard is free software: you can redistribute it and/or modify
* the Free Software Foundation, either version 3 of the License, or // it under the terms of the GNU General Public License as published by
* (at your option) any later version. // the Free Software Foundation, either version 3 of the License, or
* // (at your option) any later version.
* This program is distributed in the hope that it will be useful, //
* but WITHOUT ANY WARRANTY; without even the implied warranty of // RSS Guard is distributed in the hope that it will be useful,
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // but WITHOUT ANY WARRANTY; without even the implied warranty of
* GNU General Public License for more details. // 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 <http://www.gnu.org/licenses/>. // You should have received a copy of the GNU General Public License
* ============================================================ */ // along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
/* ============================================================
* QupZilla - WebKit based browser
* Copyright (C) 2013-2014 David Rosca <nowrep@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* ============================================================ */
#ifndef ADBLOCKSEARCHTREE_H #ifndef ADBLOCKSEARCHTREE_H
#define ADBLOCKSEARCHTREE_H #define ADBLOCKSEARCHTREE_H
#include <QChar> #include <QChar>
#include <QHash> #include <QHash>
class QNetworkRequest;
class QNetworkRequest;
class AdBlockRule; class AdBlockRule;
class AdBlockSearchTree class AdBlockSearchTree {
{ public:
public: explicit AdBlockSearchTree();
explicit AdBlockSearchTree(); virtual ~AdBlockSearchTree();
~AdBlockSearchTree();
void clear(); void clear();
bool add(const AdBlockRule* rule); bool add(const AdBlockRule *rule);
const AdBlockRule* find(const QNetworkRequest &request, const QString &domain, const QString &urlString) const; const AdBlockRule *find(const QNetworkRequest &request, const QString &domain, const QString &url_string) const;
private: private:
struct Node { struct Node {
QChar c; public:
const AdBlockRule* rule; QChar c;
QHash<QChar, Node*> children; const AdBlockRule *rule;
QHash<QChar,Node*> children;
Node() : c(0) , rule(0) { } Node() : c(0) , rule(0) {
}; }
};
const AdBlockRule* prefixSearch(const QNetworkRequest &request, const QString &domain, void deleteNode(Node *node);
const QString &urlString, const QChar* string, int len) const; const AdBlockRule *prefixSearch(const QNetworkRequest &request, const QString &domain,
const QString &url_string, const QChar* string, int len) const;
void deleteNode(Node* node); Node *m_root;
Node* m_root;
}; };
#endif // ADBLOCKSEARCHTREE_H #endif // ADBLOCKSEARCHTREE_H

View File

@ -1,37 +1,21 @@
/* ============================================================ // This file is part of RSS Guard.
* QuiteRSS is a open-source cross-platform RSS/Atom news feeds reader //
* Copyright (C) 2011-2015 QuiteRSS Team <quiterssteam@gmail.com> // Copyright (C) 2014-2015 by Martin Rotter <rotter.martinos@gmail.com>
* // Copyright (C) 2010-2014 by David Rosca <nowrep@gmail.com>
* 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 // RSS Guard is free software: you can redistribute it and/or modify
* the Free Software Foundation, either version 3 of the License, or // it under the terms of the GNU General Public License as published by
* (at your option) any later version. // the Free Software Foundation, either version 3 of the License, or
* // (at your option) any later version.
* This program is distributed in the hope that it will be useful, //
* but WITHOUT ANY WARRANTY; without even the implied warranty of // RSS Guard is distributed in the hope that it will be useful,
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // but WITHOUT ANY WARRANTY; without even the implied warranty of
* GNU General Public License for more details. // 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 <http://www.gnu.org/licenses/>. // You should have received a copy of the GNU General Public License
* ============================================================ */ // along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
/* ============================================================
* QupZilla - WebKit based browser
* Copyright (C) 2010-2014 David Rosca <nowrep@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* ============================================================ */
/** /**
* Copyright (c) 2009, Benjamin C. Meyer <ben@meyerhome.net> * Copyright (c) 2009, Benjamin C. Meyer <ben@meyerhome.net>
* *
@ -59,85 +43,78 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
*/ */
#include "adblocksubscription.h"
#include "adblockmanager.h"
#include "adblocksearchtree.h"
#include "followredirectreply.h"
#include "network-web/adblock/adblocksubscription.h"
#include "network-web/adblock/adblockmanager.h"
#include "network-web/adblock/adblocksearchtree.h"
#include "network-web/adblock/followredirectreply.h"
#include "network-web/silentnetworkaccessmanager.h" #include "network-web/silentnetworkaccessmanager.h"
#include "miscellaneous/iofactory.h" #include "miscellaneous/iofactory.h"
#include "miscellaneous/application.h" #include "miscellaneous/application.h"
#include "exceptions/applicationexception.h"
#include <QFile> #include <QFile>
#include <QTimer> #include <QTimer>
#include <QNetworkReply> #include <QNetworkReply>
#include <QDebug> #include <QDir>
#include <QWebPage> #include <QWebPage>
#include <exceptions/applicationexception.h>
AdBlockSubscription::AdBlockSubscription(const QString &title, QObject* parent) AdBlockSubscription::AdBlockSubscription(const QString &title, QObject *parent)
: QObject(parent) : QObject(parent), m_reply(NULL), m_title(title), m_updated(false) {
, m_reply(0)
, m_title(title)
, m_updated(false)
{
} }
QString AdBlockSubscription::title() const QString AdBlockSubscription::title() const {
{
return m_title; return m_title;
} }
void AdBlockSubscription::setTitle(const QString &title) void AdBlockSubscription::setTitle(const QString &title) {
{
m_title = title; m_title = title;
} }
QString AdBlockSubscription::filePath() const QString AdBlockSubscription::filePath() const {
{
return m_filePath; return m_filePath;
} }
void AdBlockSubscription::setFilePath(const QString &path) void AdBlockSubscription::setFilePath(const QString &path) {
{
m_filePath = path; m_filePath = path;
} }
QUrl AdBlockSubscription::url() const QUrl AdBlockSubscription::url() const {
{
return m_url; return m_url;
} }
void AdBlockSubscription::setUrl(const QUrl &url) void AdBlockSubscription::setUrl(const QUrl &url) {
{
m_url = url; m_url = url;
} }
void AdBlockSubscription::loadSubscription(const QStringList &disabledRules) void AdBlockSubscription::loadSubscription(const QStringList &disabled_rules) {
{
QFile file(m_filePath); QFile file(m_filePath);
if (!file.exists()) { if (!file.exists()) {
qWarning("Cannot load subscription '%s'. Requesting its update.", qPrintable(title()));
QTimer::singleShot(0, this, SLOT(updateSubscription())); QTimer::singleShot(0, this, SLOT(updateSubscription()));
return; return;
} }
if (!file.open(QFile::ReadOnly)) { if (!file.open(QFile::ReadOnly)) {
qWarning() << "AdBlockSubscription::" << __FUNCTION__ << "Unable to open adblock file for reading" << m_filePath; qWarning("Unable to open subscription file '%s' for reading.", qPrintable(QDir::toNativeSeparators(m_filePath)));
QTimer::singleShot(0, this, SLOT(updateSubscription())); QTimer::singleShot(0, this, SLOT(updateSubscription()));
return; return;
} }
QTextStream textStream(&file); QTextStream textStream(&file);
textStream.setCodec("UTF-8"); textStream.setCodec("UTF-8");
// Header is on 3rd line
// Header is on 3rd line.
textStream.readLine(1024); textStream.readLine(1024);
textStream.readLine(1024); textStream.readLine(1024);
QString header = textStream.readLine(1024); QString header = textStream.readLine(1024);
if (!header.startsWith(QLatin1String("[Adblock")) || m_title.isEmpty()) { if (!header.startsWith(QLatin1String("[Adblock")) || m_title.isEmpty()) {
qWarning() << "AdBlockSubscription::" << __FUNCTION__ << "invalid format of adblock file" << m_filePath; qWarning("Invalid format of subscription file '%s'.", qPrintable(QDir::toNativeSeparators(m_filePath)));
file.close();
QTimer::singleShot(0, this, SLOT(updateSubscription())); QTimer::singleShot(0, this, SLOT(updateSubscription()));
return; return;
} }
@ -145,38 +122,38 @@ void AdBlockSubscription::loadSubscription(const QStringList &disabledRules)
m_rules.clear(); m_rules.clear();
while (!textStream.atEnd()) { while (!textStream.atEnd()) {
AdBlockRule* rule = new AdBlockRule(textStream.readLine(), this); AdBlockRule *rule = new AdBlockRule(textStream.readLine(), this);
if (disabledRules.contains(rule->filter())) { if (disabled_rules.contains(rule->filter())) {
rule->setEnabled(false); rule->setEnabled(false);
} }
m_rules.append(rule); m_rules.append(rule);
} }
// Initial update file.close();
// Initial update.
if (m_rules.isEmpty() && !m_updated) { if (m_rules.isEmpty() && !m_updated) {
QTimer::singleShot(0, this, SLOT(updateSubscription())); QTimer::singleShot(0, this, SLOT(updateSubscription()));
} }
} }
void AdBlockSubscription::saveSubscription() void AdBlockSubscription::saveSubscription() {
{
} }
void AdBlockSubscription::updateSubscription() void AdBlockSubscription::updateSubscription() {
{ if (m_reply != NULL || !m_url.isValid()) {
if (m_reply || !m_url.isValid()) {
return; return;
} }
// TODO: Refaktorovat.
m_reply = new FollowRedirectReply(m_url, SilentNetworkAccessManager::instance()); m_reply = new FollowRedirectReply(m_url, SilentNetworkAccessManager::instance());
connect(m_reply, SIGNAL(finished()), this, SLOT(subscriptionDownloaded())); connect(m_reply, SIGNAL(finished()), this, SLOT(subscriptionDownloaded()));
} }
void AdBlockSubscription::subscriptionDownloaded() void AdBlockSubscription::subscriptionDownloaded() {
{
if (m_reply != qobject_cast<FollowRedirectReply*>(sender())) { if (m_reply != qobject_cast<FollowRedirectReply*>(sender())) {
return; return;
} }
@ -186,8 +163,7 @@ void AdBlockSubscription::subscriptionDownloaded()
if (m_reply->error() != QNetworkReply::NoError || if (m_reply->error() != QNetworkReply::NoError ||
!response.startsWith(QByteArray("[Adblock")) || !response.startsWith(QByteArray("[Adblock")) ||
!saveDownloadedData(response) !saveDownloadedData(response)) {
) {
error = true; error = true;
} }
@ -196,21 +172,20 @@ void AdBlockSubscription::subscriptionDownloaded()
if (error) { if (error) {
emit subscriptionError(tr("Cannot load subscription!")); emit subscriptionError(tr("Cannot load subscription!"));
return;
} }
else {
loadSubscription(AdBlockManager::instance()->disabledRules());
loadSubscription(AdBlockManager::instance()->disabledRules()); emit subscriptionUpdated();
emit subscriptionChanged();
emit subscriptionUpdated(); }
emit subscriptionChanged();
} }
bool AdBlockSubscription::saveDownloadedData(const QByteArray &data) bool AdBlockSubscription::saveDownloadedData(const QByteArray &data) {
{
QFile file(m_filePath); QFile file(m_filePath);
if (!file.open(QFile::ReadWrite | QFile::Truncate)) { if (!file.open(QFile::ReadWrite | QFile::Truncate)) {
qWarning() << "AdBlockSubscription::" << __FUNCTION__ << "Unable to open adblock file for writing:" << m_filePath; qWarning("Unable to open subscription file '%s' for writting.", qPrintable(QDir::toNativeSeparators(m_filePath)));
return false; return false;
} }
@ -227,36 +202,36 @@ bool AdBlockSubscription::saveDownloadedData(const QByteArray &data)
file.write(part1); file.write(part1);
file.write(part2); file.write(part2);
file.flush();
file.close(); file.close();
return true; return true;
} }
file.write(data); file.write(data);
file.flush();
file.close(); file.close();
return true; return true;
} }
const AdBlockRule* AdBlockSubscription::rule(int offset) const const AdBlockRule *AdBlockSubscription::rule(int offset) const{
{ if (!(offset >= 0 && m_rules.size() > offset)) {
if (!(offset >= 0 && m_rules.count() > offset)) { return NULL;
return 0; }
else {
return m_rules[offset];
} }
return m_rules[offset];
} }
QVector<AdBlockRule*> AdBlockSubscription::allRules() const QVector<AdBlockRule*> AdBlockSubscription::allRules() const {
{
return m_rules; return m_rules;
} }
const AdBlockRule* AdBlockSubscription::enableRule(int offset) const AdBlockRule *AdBlockSubscription::enableRule(int offset) {
{ if (!(offset >= 0 && m_rules.size() > offset)) {
if (!(offset >= 0 && m_rules.count() > offset)) { return NULL;
return 0;
} }
AdBlockRule* rule = m_rules[offset]; AdBlockRule *rule = m_rules[offset];
rule->setEnabled(true); rule->setEnabled(true);
AdBlockManager::instance()->removeDisabledRule(rule->filter()); AdBlockManager::instance()->removeDisabledRule(rule->filter());
@ -270,13 +245,12 @@ const AdBlockRule* AdBlockSubscription::enableRule(int offset)
return rule; return rule;
} }
const AdBlockRule* AdBlockSubscription::disableRule(int offset) const AdBlockRule *AdBlockSubscription::disableRule(int offset) {
{ if (!(offset >= 0 && m_rules.size() > offset)) {
if (!(offset >= 0 && m_rules.count() > offset)) { return NULL;
return 0;
} }
AdBlockRule* rule = m_rules[offset]; AdBlockRule *rule = m_rules[offset];
rule->setEnabled(false); rule->setEnabled(false);
AdBlockManager::instance()->addDisabledRule(rule->filter()); AdBlockManager::instance()->addDisabledRule(rule->filter());
@ -291,87 +265,48 @@ const AdBlockRule* AdBlockSubscription::disableRule(int offset)
return rule; return rule;
} }
bool AdBlockSubscription::canEditRules() const bool AdBlockSubscription::canEditRules() const {
{
return false; return false;
} }
bool AdBlockSubscription::canBeRemoved() const bool AdBlockSubscription::canBeRemoved() const {
{
return true; return true;
} }
int AdBlockSubscription::addRule(AdBlockRule* rule) int AdBlockSubscription::addRule(AdBlockRule *rule) {
{
Q_UNUSED(rule) Q_UNUSED(rule)
return -1; return -1;
} }
bool AdBlockSubscription::removeRule(int offset) bool AdBlockSubscription::removeRule(int offset) {
{
Q_UNUSED(offset) Q_UNUSED(offset)
return false; return false;
} }
const AdBlockRule* AdBlockSubscription::replaceRule(AdBlockRule* rule, int offset) const AdBlockRule *AdBlockSubscription::replaceRule(AdBlockRule *rule, int offset) {
{
Q_UNUSED(rule) Q_UNUSED(rule)
Q_UNUSED(offset) Q_UNUSED(offset)
return 0; return 0;
} }
AdBlockSubscription::~AdBlockSubscription() AdBlockSubscription::~AdBlockSubscription() {
{
qDeleteAll(m_rules); qDeleteAll(m_rules);
} }
// AdBlockCustomList AdBlockCustomList::AdBlockCustomList(QObject *parent) : AdBlockSubscription(tr("Custom rules"), parent) {
AdBlockCustomList::AdBlockCustomList(QObject* parent) : AdBlockSubscription(tr("Custom rules"), parent) {
setTitle(tr("Custom rules")); setTitle(tr("Custom rules"));
// TODO // TODO cesta
setFilePath(qApp->homeFolderPath() + "/adblock/customlist.txt"); setFilePath(qApp->homeFolderPath() + "/adblock/customlist.txt");
} }
void AdBlockCustomList::loadSubscription(const QStringList &disabledRules) AdBlockCustomList::~AdBlockCustomList() {
{
// DuckDuckGo ad whitelist rules
// They cannot be removed, but can be disabled.
// Please consider not disabling them. Thanks!
const QString ddg1 = QSL("@@||duckduckgo.com^$document");
const QString ddg2 = QSL("duckduckgo.com#@#.has-ad");
QString rules = QString();
try {
rules = QString::fromUtf8(IOFactory::readTextFile((filePath())));
}
catch (ApplicationException &ex) {
}
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);
} }
void AdBlockCustomList::saveSubscription() void AdBlockCustomList::saveSubscription() {
{ QFile file(m_filePath);
QFile file(filePath());
if (!file.open(QFile::ReadWrite | QFile::Truncate)) { if (!file.open(QFile::WriteOnly | QFile::Truncate)) {
qWarning() << "AdBlockSubscription::" << __FUNCTION__ << "Unable to open adblock file for writing:" << filePath(); qWarning("Unable to open custom subscription file '%s' for writting.", qPrintable(QDir::toNativeSeparators(m_filePath)));
return; return;
} }
@ -385,22 +320,20 @@ void AdBlockCustomList::saveSubscription()
textStream << rule->filter() << endl; textStream << rule->filter() << endl;
} }
file.flush();
file.close(); file.close();
} }
bool AdBlockCustomList::canEditRules() const bool AdBlockCustomList::canEditRules() const {
{
return true; return true;
} }
bool AdBlockCustomList::canBeRemoved() const bool AdBlockCustomList::canBeRemoved() const {
{
return false; return false;
} }
bool AdBlockCustomList::containsFilter(const QString &filter) const bool AdBlockCustomList::containsFilter(const QString &filter) const {
{ foreach (const AdBlockRule *rule, m_rules) {
foreach (const AdBlockRule* rule, m_rules) {
if (rule->filter() == filter) { if (rule->filter() == filter) {
return true; return true;
} }
@ -409,10 +342,9 @@ bool AdBlockCustomList::containsFilter(const QString &filter) const
return false; return false;
} }
bool AdBlockCustomList::removeFilter(const QString &filter) bool AdBlockCustomList::removeFilter(const QString &filter) {
{ for (int i = 0; i < m_rules.size(); i++) {
for (int i = 0; i < m_rules.count(); ++i) { const AdBlockRule *rule = m_rules.at(i);
const AdBlockRule* rule = m_rules.at(i);
if (rule->filter() == filter) { if (rule->filter() == filter) {
return removeRule(i); return removeRule(i);
@ -422,10 +354,8 @@ bool AdBlockCustomList::removeFilter(const QString &filter)
return false; return false;
} }
int AdBlockCustomList::addRule(AdBlockRule* rule) int AdBlockCustomList::addRule(AdBlockRule *rule) {
{
m_rules.append(rule); m_rules.append(rule);
emit subscriptionChanged(); emit subscriptionChanged();
// TODO // TODO
@ -433,20 +363,18 @@ int AdBlockCustomList::addRule(AdBlockRule* rule)
if (rule->isCssRule()) if (rule->isCssRule())
mainApp->reloadUserStyleBrowser(); mainApp->reloadUserStyleBrowser();
*/ */
return m_rules.count() - 1; return m_rules.size() - 1;
} }
bool AdBlockCustomList::removeRule(int offset) bool AdBlockCustomList::removeRule(int offset) {
{ if (!(offset >= 0 && m_rules.size() > offset)) {
if (!(offset >= 0 && m_rules.count() > offset)) {
return false; return false;
} }
AdBlockRule* rule = m_rules.at(offset); AdBlockRule *rule = m_rules.at(offset);
const QString filter = rule->filter(); const QString filter = rule->filter();
m_rules.remove(offset); m_rules.remove(offset);
emit subscriptionChanged(); emit subscriptionChanged();
// TODO // TODO
/* /*
@ -455,20 +383,17 @@ bool AdBlockCustomList::removeRule(int offset)
*/ */
AdBlockManager::instance()->removeDisabledRule(filter); AdBlockManager::instance()->removeDisabledRule(filter);
delete rule; delete rule;
return true; return true;
} }
const AdBlockRule* AdBlockCustomList::replaceRule(AdBlockRule* rule, int offset) const AdBlockRule *AdBlockCustomList::replaceRule(AdBlockRule *rule, int offset) {
{ if (!(offset >= 0 && m_rules.size() > offset)) {
if (!(offset >= 0 && m_rules.count() > offset)) { return NULL;
return 0;
} }
AdBlockRule* oldRule = m_rules.at(offset); AdBlockRule *oldRule = m_rules.at(offset);
m_rules[offset] = rule; m_rules[offset] = rule;
emit subscriptionChanged(); emit subscriptionChanged();
// TODO // TODO

View File

@ -1,37 +1,21 @@
/* ============================================================ // This file is part of RSS Guard.
* QuiteRSS is a open-source cross-platform RSS/Atom news feeds reader //
* Copyright (C) 2011-2015 QuiteRSS Team <quiterssteam@gmail.com> // Copyright (C) 2014-2015 by Martin Rotter <rotter.martinos@gmail.com>
* // Copyright (C) 2010-2014 by David Rosca <nowrep@gmail.com>
* 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 // RSS Guard is free software: you can redistribute it and/or modify
* the Free Software Foundation, either version 3 of the License, or // it under the terms of the GNU General Public License as published by
* (at your option) any later version. // the Free Software Foundation, either version 3 of the License, or
* // (at your option) any later version.
* This program is distributed in the hope that it will be useful, //
* but WITHOUT ANY WARRANTY; without even the implied warranty of // RSS Guard is distributed in the hope that it will be useful,
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // but WITHOUT ANY WARRANTY; without even the implied warranty of
* GNU General Public License for more details. // 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 <http://www.gnu.org/licenses/>. // You should have received a copy of the GNU General Public License
* ============================================================ */ // along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
/* ============================================================
* QupZilla - WebKit based browser
* Copyright (C) 2010-2014 David Rosca <nowrep@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* ============================================================ */
/** /**
* Copyright (c) 2009, Benjamin C. Meyer <ben@meyerhome.net> * Copyright (c) 2009, Benjamin C. Meyer <ben@meyerhome.net>
* *
@ -63,24 +47,26 @@
#ifndef ADBLOCKSUBSCRIPTION_H #ifndef ADBLOCKSUBSCRIPTION_H
#define ADBLOCKSUBSCRIPTION_H #define ADBLOCKSUBSCRIPTION_H
#include <QObject>
#include <QVector> #include <QVector>
#include <QUrl> #include <QUrl>
#include "adblockrule.h" #include "network-web/adblock/adblockrule.h"
#include "adblocksearchtree.h" #include "network-web/adblock/adblocksearchtree.h"
class QNetworkRequest; class QNetworkRequest;
class QNetworkReply; class QNetworkReply;
class QUrl; class QUrl;
class FollowRedirectReply; class FollowRedirectReply;
class AdBlockSubscription : public QObject class AdBlockSubscription : public QObject {
{
Q_OBJECT Q_OBJECT
public: public:
explicit AdBlockSubscription(const QString &title, QObject* parent = 0); explicit AdBlockSubscription(const QString &title, QObject *parent = 0);
~AdBlockSubscription(); virtual ~AdBlockSubscription();
QString title() const; QString title() const;
void setTitle(const QString &title); void setTitle(const QString &title);
@ -91,21 +77,21 @@ class AdBlockSubscription : public QObject
QUrl url() const; QUrl url() const;
void setUrl(const QUrl &url); void setUrl(const QUrl &url);
virtual void loadSubscription(const QStringList &disabledRules); virtual void loadSubscription(const QStringList &disabled_rules);
virtual void saveSubscription(); virtual void saveSubscription();
const AdBlockRule* rule(int offset) const; const AdBlockRule *rule(int offset) const;
QVector<AdBlockRule*> allRules() const; QVector<AdBlockRule*> allRules() const;
const AdBlockRule* enableRule(int offset); const AdBlockRule *enableRule(int offset);
const AdBlockRule* disableRule(int offset); const AdBlockRule *disableRule(int offset);
virtual bool canEditRules() const; virtual bool canEditRules() const;
virtual bool canBeRemoved() const; virtual bool canBeRemoved() const;
virtual int addRule(AdBlockRule* rule); virtual int addRule(AdBlockRule *rule);
virtual bool removeRule(int offset); virtual bool removeRule(int offset);
virtual const AdBlockRule* replaceRule(AdBlockRule* rule, int offset); virtual const AdBlockRule *replaceRule(AdBlockRule *rule, int offset);
public slots: public slots:
void updateSubscription(); void updateSubscription();
@ -121,25 +107,23 @@ class AdBlockSubscription : public QObject
protected: protected:
virtual bool saveDownloadedData(const QByteArray &data); virtual bool saveDownloadedData(const QByteArray &data);
FollowRedirectReply* m_reply;
QVector<AdBlockRule*> m_rules; QVector<AdBlockRule*> m_rules;
private:
QString m_title; QString m_title;
QString m_filePath; QString m_filePath;
private:
FollowRedirectReply *m_reply;
QUrl m_url; QUrl m_url;
bool m_updated; bool m_updated;
}; };
class AdBlockCustomList : public AdBlockSubscription class AdBlockCustomList : public AdBlockSubscription {
{
Q_OBJECT Q_OBJECT
public: public:
explicit AdBlockCustomList(QObject* parent = 0); explicit AdBlockCustomList(QObject* parent = 0);
virtual ~AdBlockCustomList();
void loadSubscription(const QStringList &disabledRules);
void saveSubscription(); void saveSubscription();
bool canEditRules() const; bool canEditRules() const;
@ -148,9 +132,9 @@ class AdBlockCustomList : public AdBlockSubscription
bool containsFilter(const QString &filter) const; bool containsFilter(const QString &filter) const;
bool removeFilter(const QString &filter); bool removeFilter(const QString &filter);
int addRule(AdBlockRule* rule); int addRule(AdBlockRule *rule);
bool removeRule(int offset); bool removeRule(int offset);
const AdBlockRule* replaceRule(AdBlockRule* rule, int offset); const AdBlockRule *replaceRule(AdBlockRule *rule, int offset);
}; };
#endif // ADBLOCKSUBSCRIPTION_H #endif // ADBLOCKSUBSCRIPTION_H

View File

@ -1,39 +1,24 @@
/* ============================================================ // This file is part of RSS Guard.
* QuiteRSS is a open-source cross-platform RSS/Atom news feeds reader //
* Copyright (C) 2011-2015 QuiteRSS Team <quiterssteam@gmail.com> // Copyright (C) 2014-2015 by Martin Rotter <rotter.martinos@gmail.com>
* // Copyright (C) 2010-2014 by David Rosca <nowrep@gmail.com>
* 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 // RSS Guard is free software: you can redistribute it and/or modify
* the Free Software Foundation, either version 3 of the License, or // it under the terms of the GNU General Public License as published by
* (at your option) any later version. // the Free Software Foundation, either version 3 of the License, or
* // (at your option) any later version.
* This program is distributed in the hope that it will be useful, //
* but WITHOUT ANY WARRANTY; without even the implied warranty of // RSS Guard is distributed in the hope that it will be useful,
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // but WITHOUT ANY WARRANTY; without even the implied warranty of
* GNU General Public License for more details. // 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 <http://www.gnu.org/licenses/>. // You should have received a copy of the GNU General Public License
* ============================================================ */ // along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
/* ============================================================
* QupZilla - WebKit based browser #include "network-web/adblock/adblocktreewidget.h"
* Copyright (C) 2010-2014 David Rosca <nowrep@gmail.com>
* #include "network-web/adblock/adblocksubscription.h"
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* ============================================================ */
#include "adblocktreewidget.h"
#include "adblocksubscription.h"
#include <QMenu> #include <QMenu>
#include <QKeyEvent> #include <QKeyEvent>
@ -41,13 +26,10 @@
#include <QApplication> #include <QApplication>
#include <QInputDialog> #include <QInputDialog>
AdBlockTreeWidget::AdBlockTreeWidget(AdBlockSubscription* subscription, QWidget* parent)
: QTreeWidget(parent) AdBlockTreeWidget::AdBlockTreeWidget(AdBlockSubscription *subscription, QWidget *parent)
, m_subscription(subscription) : QTreeWidget(parent), m_subscription(subscription), m_topItem(NULL),
, m_topItem(0) m_itemChangingBlock(false), m_refreshAllItemsNeeded(true) {
, m_itemChangingBlock(false)
, m_refreshAllItemsNeeded(true)
{
setContextMenuPolicy(Qt::CustomContextMenu); setContextMenuPolicy(Qt::CustomContextMenu);
setHeaderHidden(true); setHeaderHidden(true);
setAlternatingRowColors(true); setAlternatingRowColors(true);
@ -59,20 +41,20 @@ AdBlockTreeWidget::AdBlockTreeWidget(AdBlockSubscription* subscription, QWidget*
connect(m_subscription, SIGNAL(subscriptionError(QString)), this, SLOT(subscriptionError(QString))); connect(m_subscription, SIGNAL(subscriptionError(QString)), this, SLOT(subscriptionError(QString)));
} }
AdBlockSubscription* AdBlockTreeWidget::subscription() const AdBlockSubscription *AdBlockTreeWidget::subscription() const {
{
return m_subscription; return m_subscription;
} }
void AdBlockTreeWidget::showRule(const AdBlockRule* rule) void AdBlockTreeWidget::showRule(const AdBlockRule *rule) {
{ if (m_topItem == NULL && rule) {
if (!m_topItem && rule) { // Dialog is not loaded yet. Mark rule for late loading.
m_ruleToBeSelected = rule->filter(); m_ruleToBeSelected = rule->filter();
} }
else if (!m_ruleToBeSelected.isEmpty()) { else if (!m_ruleToBeSelected.isEmpty()) {
QList<QTreeWidgetItem*> items = findItems(m_ruleToBeSelected, Qt::MatchRecursive); QList<QTreeWidgetItem*> items = findItems(m_ruleToBeSelected, Qt::MatchRecursive);
if (!items.isEmpty()) { if (!items.isEmpty()) {
QTreeWidgetItem* item = items.at(0); QTreeWidgetItem *item = items.at(0);
setCurrentItem(item); setCurrentItem(item);
scrollToItem(item, QAbstractItemView::PositionAtCenter); scrollToItem(item, QAbstractItemView::PositionAtCenter);
@ -82,58 +64,56 @@ void AdBlockTreeWidget::showRule(const AdBlockRule* rule)
} }
} }
void AdBlockTreeWidget::contextMenuRequested(const QPoint &pos) void AdBlockTreeWidget::contextMenuRequested(const QPoint &pos) {
{
if (!m_subscription->canEditRules()) { if (!m_subscription->canEditRules()) {
return; return;
} }
QTreeWidgetItem* item = itemAt(pos); QTreeWidgetItem *item = itemAt(pos);
if (!item) {
return; if (item != NULL) {
QMenu menu;
menu.addAction(tr("Add Rule"), this, SLOT(addRule()));
menu.addSeparator();
QAction *delete_action = menu.addAction(tr("Remove Rule"), this, SLOT(removeRule()));
if (item->parent() == NULL) {
delete_action->setDisabled(true);
}
menu.exec(viewport()->mapToGlobal(pos));
} }
QMenu menu;
menu.addAction(tr("Add Rule"), this, SLOT(addRule()));
menu.addSeparator();
QAction* deleteAction = menu.addAction(tr("Remove Rule"), this, SLOT(removeRule()));
if (!item->parent()) {
deleteAction->setDisabled(true);
}
menu.exec(viewport()->mapToGlobal(pos));
} }
void AdBlockTreeWidget::itemChanged(QTreeWidgetItem* item) void AdBlockTreeWidget::itemChanged(QTreeWidgetItem *item) {
{
m_refreshAllItemsNeeded = true; m_refreshAllItemsNeeded = true;
if (!item || m_itemChangingBlock) { if (item == NULL || m_itemChangingBlock) {
return; return;
} }
m_itemChangingBlock = true; m_itemChangingBlock = true;
int offset = item->data(0, Qt::UserRole + 10).toInt(); int offset = item->data(0, Qt::UserRole + 10).toInt();
const AdBlockRule* oldRule = m_subscription->rule(offset); const AdBlockRule *old_rle = m_subscription->rule(offset);
if (item->checkState(0) == Qt::Unchecked && oldRule->isEnabled()) { if (item->checkState(0) == Qt::Unchecked && old_rle->isEnabled()) {
// Disable rule // Disable rule.
const AdBlockRule* rule = m_subscription->disableRule(offset); const AdBlockRule *rule = m_subscription->disableRule(offset);
adjustItemFeatures(item, rule); adjustItemFeatures(item, rule);
} }
else if (item->checkState(0) == Qt::Checked && !oldRule->isEnabled()) { else if (item->checkState(0) == Qt::Checked && !old_rle->isEnabled()) {
// Enable rule // Enable rule
const AdBlockRule* rule = m_subscription->enableRule(offset); const AdBlockRule *rule = m_subscription->enableRule(offset);
adjustItemFeatures(item, rule); adjustItemFeatures(item, rule);
} }
else if (m_subscription->canEditRules()) { else if (m_subscription->canEditRules()) {
// Custom rule has been changed // Custom rule has been changed
AdBlockRule* newRule = new AdBlockRule(item->text(0), m_subscription); AdBlockRule *new_rule = new AdBlockRule(item->text(0), m_subscription);
const AdBlockRule* rule = m_subscription->replaceRule(newRule, offset); const AdBlockRule *rule = m_subscription->replaceRule(new_rule, offset);
adjustItemFeatures(item, rule); adjustItemFeatures(item, rule);
} }
@ -141,32 +121,29 @@ void AdBlockTreeWidget::itemChanged(QTreeWidgetItem* item)
m_itemChangingBlock = false; m_itemChangingBlock = false;
} }
void AdBlockTreeWidget::copyFilter() void AdBlockTreeWidget::copyFilter() {
{ QTreeWidgetItem *item = currentItem();
QTreeWidgetItem* item = currentItem();
if (!item) {
return;
}
QApplication::clipboard()->setText(item->text(0)); if (item != NULL) {
QApplication::clipboard()->setText(item->text(0));
}
} }
void AdBlockTreeWidget::addRule() void AdBlockTreeWidget::addRule() {
{
if (!m_subscription->canEditRules()) { if (!m_subscription->canEditRules()) {
return; return;
} }
QString newRule = QInputDialog::getText(this, tr("Add Custom Rule"), tr("Please write your rule here:")); QString new_rule = QInputDialog::getText(this, tr("Add Rule"), tr("Please write your rule here"));
if (newRule.isEmpty()) { if (new_rule.isEmpty()) {
return; return;
} }
AdBlockRule* rule = new AdBlockRule(newRule, m_subscription); AdBlockRule *rule = new AdBlockRule(new_rule, m_subscription);
int offset = m_subscription->addRule(rule); int offset = m_subscription->addRule(rule);
QTreeWidgetItem* item = new QTreeWidgetItem(); QTreeWidgetItem *item = new QTreeWidgetItem();
item->setText(0, newRule); item->setText(0, new_rule);
item->setData(0, Qt::UserRole + 10, offset); item->setData(0, Qt::UserRole + 10, offset);
item->setFlags(item->flags() | Qt::ItemIsEditable); item->setFlags(item->flags() | Qt::ItemIsEditable);
@ -177,21 +154,18 @@ void AdBlockTreeWidget::addRule()
adjustItemFeatures(item, rule); adjustItemFeatures(item, rule);
} }
void AdBlockTreeWidget::removeRule() void AdBlockTreeWidget::removeRule() {
{ QTreeWidgetItem *item = currentItem();
QTreeWidgetItem* item = currentItem(); if (item == NULL || !m_subscription->canEditRules() || item == m_topItem) {
if (!item || !m_subscription->canEditRules() || item == m_topItem) {
return; return;
} }
int offset = item->data(0, Qt::UserRole + 10).toInt(); int offset = item->data(0, Qt::UserRole + 10).toInt();
m_subscription->removeRule(offset); m_subscription->removeRule(offset);
delete item; delete item;
} }
void AdBlockTreeWidget::subscriptionUpdated() void AdBlockTreeWidget::subscriptionUpdated() {
{
refresh(); refresh();
m_itemChangingBlock = true; m_itemChangingBlock = true;
@ -199,17 +173,15 @@ void AdBlockTreeWidget::subscriptionUpdated()
m_itemChangingBlock = false; m_itemChangingBlock = false;
} }
void AdBlockTreeWidget::subscriptionError(const QString &message) void AdBlockTreeWidget::subscriptionError(const QString &message) {
{
refresh(); refresh();
m_itemChangingBlock = true; m_itemChangingBlock = true;
m_topItem->setText(0, tr("%1 (Error: %2)").arg(m_subscription->title(), message)); m_topItem->setText(0, tr("%1 (error: %2)").arg(m_subscription->title(), message));
m_itemChangingBlock = false; m_itemChangingBlock = false;
} }
void AdBlockTreeWidget::adjustItemFeatures(QTreeWidgetItem* item, const AdBlockRule* rule) void AdBlockTreeWidget::adjustItemFeatures(QTreeWidgetItem *item, const AdBlockRule *rule) {
{
if (!rule->isEnabled()) { if (!rule->isEnabled()) {
QFont font; QFont font;
font.setItalic(true); font.setItalic(true);
@ -241,8 +213,7 @@ void AdBlockTreeWidget::adjustItemFeatures(QTreeWidgetItem* item, const AdBlockR
} }
} }
void AdBlockTreeWidget::keyPressEvent(QKeyEvent* event) void AdBlockTreeWidget::keyPressEvent(QKeyEvent* event) {
{
if (event->key() == Qt::Key_C && event->modifiers() & Qt::ControlModifier) { if (event->key() == Qt::Key_C && event->modifiers() & Qt::ControlModifier) {
copyFilter(); copyFilter();
} }
@ -254,8 +225,7 @@ void AdBlockTreeWidget::keyPressEvent(QKeyEvent* event)
QTreeWidget::keyPressEvent(event); QTreeWidget::keyPressEvent(event);
} }
void AdBlockTreeWidget::refresh() void AdBlockTreeWidget::refresh() {
{
m_itemChangingBlock = true; m_itemChangingBlock = true;
clear(); clear();
@ -269,10 +239,10 @@ void AdBlockTreeWidget::refresh()
addTopLevelItem(m_topItem); addTopLevelItem(m_topItem);
const QVector<AdBlockRule*> &allRules = m_subscription->allRules(); const QVector<AdBlockRule*> &allRules = m_subscription->allRules();
int index = 0; int index = 0;
foreach (const AdBlockRule* rule, allRules) {
QTreeWidgetItem* item = new QTreeWidgetItem(m_topItem); foreach (const AdBlockRule *rule, allRules) {
QTreeWidgetItem *item = new QTreeWidgetItem(m_topItem);
item->setText(0, rule->filter()); item->setText(0, rule->filter());
item->setData(0, Qt::UserRole + 10, index); item->setData(0, Qt::UserRole + 10, index);
@ -281,31 +251,29 @@ void AdBlockTreeWidget::refresh()
} }
adjustItemFeatures(item, rule); adjustItemFeatures(item, rule);
++index; index++;
} }
showRule(0); showRule(0);
m_itemChangingBlock = false; m_itemChangingBlock = false;
} }
void AdBlockTreeWidget::clear() void AdBlockTreeWidget::clear() {
{
QTreeWidget::clear(); QTreeWidget::clear();
m_allTreeItems.clear(); m_allTreeItems.clear();
} }
void AdBlockTreeWidget::addTopLevelItem(QTreeWidgetItem* item) void AdBlockTreeWidget::addTopLevelItem(QTreeWidgetItem *item) {
{
m_allTreeItems.append(item); m_allTreeItems.append(item);
QTreeWidget::addTopLevelItem(item); QTreeWidget::addTopLevelItem(item);
} }
void AdBlockTreeWidget::iterateAllItems(QTreeWidgetItem* parent) void AdBlockTreeWidget::iterateAllItems(QTreeWidgetItem *parent)
{ {
int count = parent ? parent->childCount() : topLevelItemCount(); int count = parent ? parent->childCount() : topLevelItemCount();
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
QTreeWidgetItem* item = parent ? parent->child(i) : topLevelItem(i); QTreeWidgetItem *item = parent ? parent->child(i) : topLevelItem(i);
if (item->childCount() == 0) { if (item->childCount() == 0) {
m_allTreeItems.append(item); m_allTreeItems.append(item);
@ -315,8 +283,7 @@ void AdBlockTreeWidget::iterateAllItems(QTreeWidgetItem* parent)
} }
} }
QList<QTreeWidgetItem*> AdBlockTreeWidget::allItems() QList<QTreeWidgetItem*> AdBlockTreeWidget::allItems() {
{
if (m_refreshAllItemsNeeded) { if (m_refreshAllItemsNeeded) {
m_allTreeItems.clear(); m_allTreeItems.clear();
iterateAllItems(0); iterateAllItems(0);
@ -326,16 +293,18 @@ QList<QTreeWidgetItem*> AdBlockTreeWidget::allItems()
return m_allTreeItems; return m_allTreeItems;
} }
void AdBlockTreeWidget::filterString(const QString &string) void AdBlockTreeWidget::filterString(const QString &string) {
{ QList<QTreeWidgetItem*> all_items = allItems();
QList<QTreeWidgetItem*> _allItems = allItems();
QList<QTreeWidgetItem*> parents; QList<QTreeWidgetItem*> parents;
bool stringIsEmpty = string.isEmpty(); bool string_empty = string.isEmpty();
foreach (QTreeWidgetItem* item, _allItems) {
bool containsString = stringIsEmpty || item->text(0).contains(string, Qt::CaseInsensitive); foreach (QTreeWidgetItem *item, all_items) {
if (containsString) { bool contains_string = string_empty || item->text(0).contains(string, Qt::CaseInsensitive);
if (contains_string) {
item->setHidden(false); item->setHidden(false);
if (item->parent()) {
if (item->parent() != NULL) {
if (!parents.contains(item->parent())) { if (!parents.contains(item->parent())) {
parents << item->parent(); parents << item->parent();
} }
@ -343,18 +312,19 @@ void AdBlockTreeWidget::filterString(const QString &string)
} }
else { else {
item->setHidden(true); item->setHidden(true);
if (item->parent()) {
if (item->parent() != NULL) {
item->parent()->setHidden(true); item->parent()->setHidden(true);
} }
} }
} }
for (int i = 0; i < parents.size(); ++i) { for (int i = 0; i < parents.size(); i++) {
QTreeWidgetItem* parentItem = parents.at(i); QTreeWidgetItem *parentItem = parents.at(i);
parentItem->setHidden(false); parentItem->setHidden(false);
parentItem->setExpanded(true); parentItem->setExpanded(true);
if (parentItem->parent() && !parents.contains(parentItem->parent())) { if (parentItem->parent() != NULL && !parents.contains(parentItem->parent())) {
parents << parentItem->parent(); parents << parentItem->parent();
} }
} }

View File

@ -1,86 +1,72 @@
/* ============================================================ // This file is part of RSS Guard.
* QuiteRSS is a open-source cross-platform RSS/Atom news feeds reader //
* Copyright (C) 2011-2015 QuiteRSS Team <quiterssteam@gmail.com> // Copyright (C) 2014-2015 by Martin Rotter <rotter.martinos@gmail.com>
* // Copyright (C) 2010-2014 by David Rosca <nowrep@gmail.com>
* 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 // RSS Guard is free software: you can redistribute it and/or modify
* the Free Software Foundation, either version 3 of the License, or // it under the terms of the GNU General Public License as published by
* (at your option) any later version. // the Free Software Foundation, either version 3 of the License, or
* // (at your option) any later version.
* This program is distributed in the hope that it will be useful, //
* but WITHOUT ANY WARRANTY; without even the implied warranty of // RSS Guard is distributed in the hope that it will be useful,
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // but WITHOUT ANY WARRANTY; without even the implied warranty of
* GNU General Public License for more details. // 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 <http://www.gnu.org/licenses/>. // You should have received a copy of the GNU General Public License
* ============================================================ */ // along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
/* ============================================================
* QupZilla - WebKit based browser
* Copyright (C) 2010-2014 David Rosca <nowrep@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* ============================================================ */
#ifndef ADBLOCKTREEWIDGET_H #ifndef ADBLOCKTREEWIDGET_H
#define ADBLOCKTREEWIDGET_H #define ADBLOCKTREEWIDGET_H
#include <QTreeWidget> #include <QTreeWidget>
class AdBlockSubscription; class AdBlockSubscription;
class AdBlockRule; class AdBlockRule;
class AdBlockTreeWidget : public QTreeWidget class AdBlockTreeWidget : public QTreeWidget {
{ Q_OBJECT
Q_OBJECT
public:
explicit AdBlockTreeWidget(AdBlockSubscription* subscription, QWidget* parent = 0);
AdBlockSubscription* subscription() const; public:
explicit AdBlockTreeWidget(AdBlockSubscription* subscription, QWidget* parent = 0);
void showRule(const AdBlockRule* rule); AdBlockSubscription *subscription() const;
void refresh();
public slots: void showRule(const AdBlockRule *rule);
void addRule(); void refresh();
void removeRule();
void filterString(const QString &string);
void clear();
private slots: public slots:
void contextMenuRequested(const QPoint &pos); void addRule();
void itemChanged(QTreeWidgetItem* item); void removeRule();
void copyFilter(); void filterString(const QString &string);
void clear();
void subscriptionUpdated(); private slots:
void subscriptionError(const QString &message); void contextMenuRequested(const QPoint &pos);
void itemChanged(QTreeWidgetItem *item);
void copyFilter();
private: void subscriptionUpdated();
void adjustItemFeatures(QTreeWidgetItem* item, const AdBlockRule* rule); void subscriptionError(const QString &message);
void keyPressEvent(QKeyEvent* event);
void addTopLevelItem(QTreeWidgetItem* item);
QList<QTreeWidgetItem*> allItems();
void iterateAllItems(QTreeWidgetItem* parent);
AdBlockSubscription* m_subscription; protected:
QTreeWidgetItem* m_topItem; void keyPressEvent(QKeyEvent *event);
QString m_ruleToBeSelected; private:
bool m_itemChangingBlock; void adjustItemFeatures(QTreeWidgetItem *item, const AdBlockRule *rule);
void addTopLevelItem(QTreeWidgetItem *item);
QList<QTreeWidgetItem*> allItems();
void iterateAllItems(QTreeWidgetItem *parent);
bool m_refreshAllItemsNeeded; AdBlockSubscription *m_subscription;
QList<QTreeWidgetItem*> m_allTreeItems; QTreeWidgetItem *m_topItem;
QString m_ruleToBeSelected;
bool m_itemChangingBlock;
bool m_refreshAllItemsNeeded;
QList<QTreeWidgetItem*> m_allTreeItems;
}; };
#endif // ADBLOCKTREEWIDGET_H #endif // ADBLOCKTREEWIDGET_H

View File

@ -1,96 +1,71 @@
/* ============================================================ // This file is part of RSS Guard.
* QuiteRSS is a open-source cross-platform RSS/Atom news feeds reader //
* Copyright (C) 2011-2015 QuiteRSS Team <quiterssteam@gmail.com> // Copyright (C) 2014-2015 by Martin Rotter <rotter.martinos@gmail.com>
* // Copyright (C) 2010-2014 by David Rosca <nowrep@gmail.com>
* 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 // RSS Guard is free software: you can redistribute it and/or modify
* the Free Software Foundation, either version 3 of the License, or // it under the terms of the GNU General Public License as published by
* (at your option) any later version. // the Free Software Foundation, either version 3 of the License, or
* // (at your option) any later version.
* This program is distributed in the hope that it will be useful, //
* but WITHOUT ANY WARRANTY; without even the implied warranty of // RSS Guard is distributed in the hope that it will be useful,
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // but WITHOUT ANY WARRANTY; without even the implied warranty of
* GNU General Public License for more details. // 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 <http://www.gnu.org/licenses/>. // You should have received a copy of the GNU General Public License
* ============================================================ */ // along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
/* ============================================================
* QupZilla - WebKit based browser #include "network-web/adblock/followredirectreply.h"
* Copyright (C) 2010-2014 David Rosca <nowrep@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* ============================================================ */
#include "followredirectreply.h"
#include <QNetworkAccessManager> #include <QNetworkAccessManager>
FollowRedirectReply::FollowRedirectReply(const QUrl &url, QNetworkAccessManager* manager)
: QObject() FollowRedirectReply::FollowRedirectReply(const QUrl &url, QNetworkAccessManager *manager)
, m_manager(manager) : QObject(), m_manager(manager), m_redirectCount(0) {
, m_redirectCount(0)
{
m_reply = m_manager->get(QNetworkRequest(url)); m_reply = m_manager->get(QNetworkRequest(url));
connect(m_reply, SIGNAL(finished()), this, SLOT(replyFinished())); connect(m_reply, SIGNAL(finished()), this, SLOT(replyFinished()));
} }
QNetworkReply* FollowRedirectReply::reply() const QNetworkReply *FollowRedirectReply::reply() const {
{
return m_reply; return m_reply;
} }
QUrl FollowRedirectReply::originalUrl() const QUrl FollowRedirectReply::originalUrl() const {
{
return m_reply->request().url(); return m_reply->request().url();
} }
QUrl FollowRedirectReply::url() const QUrl FollowRedirectReply::url() const {
{
return m_reply->url(); return m_reply->url();
} }
QNetworkReply::NetworkError FollowRedirectReply::error() const QNetworkReply::NetworkError FollowRedirectReply::error() const {
{
return m_reply->error(); return m_reply->error();
} }
QByteArray FollowRedirectReply::readAll() QByteArray FollowRedirectReply::readAll() {
{
return m_reply->readAll(); return m_reply->readAll();
} }
void FollowRedirectReply::replyFinished() void FollowRedirectReply::replyFinished() {
{ int reply_status = m_reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
int replyStatus = m_reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
if ((replyStatus != 301 && replyStatus != 302) || m_redirectCount == 5) { if ((reply_status != 301 && reply_status != 302) || m_redirectCount == 5) {
emit finished(); emit finished();
return; return;
} }
m_redirectCount++; m_redirectCount++;
QUrl redirectUrl = m_reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl(); QUrl redirect_url = m_reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl();
m_reply->close(); m_reply->close();
m_reply->deleteLater(); m_reply->deleteLater();
m_reply = m_manager->get(QNetworkRequest(redirectUrl)); m_reply = m_manager->get(QNetworkRequest(redirect_url));
connect(m_reply, SIGNAL(finished()), this, SLOT(replyFinished())); connect(m_reply, SIGNAL(finished()), this, SLOT(replyFinished()));
} }
FollowRedirectReply::~FollowRedirectReply() FollowRedirectReply::~FollowRedirectReply() {
{
m_reply->close(); m_reply->close();
m_reply->deleteLater(); m_reply->deleteLater();
} }

View File

@ -1,73 +1,57 @@
/* ============================================================ // This file is part of RSS Guard.
* QuiteRSS is a open-source cross-platform RSS/Atom news feeds reader //
* Copyright (C) 2011-2015 QuiteRSS Team <quiterssteam@gmail.com> // Copyright (C) 2014-2015 by Martin Rotter <rotter.martinos@gmail.com>
* // Copyright (C) 2010-2014 by David Rosca <nowrep@gmail.com>
* 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 // RSS Guard is free software: you can redistribute it and/or modify
* the Free Software Foundation, either version 3 of the License, or // it under the terms of the GNU General Public License as published by
* (at your option) any later version. // the Free Software Foundation, either version 3 of the License, or
* // (at your option) any later version.
* This program is distributed in the hope that it will be useful, //
* but WITHOUT ANY WARRANTY; without even the implied warranty of // RSS Guard is distributed in the hope that it will be useful,
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // but WITHOUT ANY WARRANTY; without even the implied warranty of
* GNU General Public License for more details. // 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 <http://www.gnu.org/licenses/>. // You should have received a copy of the GNU General Public License
* ============================================================ */ // along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
/* ============================================================
* QupZilla - WebKit based browser
* Copyright (C) 2010-2014 David Rosca <nowrep@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* ============================================================ */
#ifndef FOLLOWREDIRECTREPLY_H #ifndef FOLLOWREDIRECTREPLY_H
#define FOLLOWREDIRECTREPLY_H #define FOLLOWREDIRECTREPLY_H
#include <QObject> #include <QObject>
#include <QNetworkReply> #include <QNetworkReply>
class QNetworkAccessManager; class QNetworkAccessManager;
class QNetworkReply; class QNetworkReply;
class QUrl; class QUrl;
class FollowRedirectReply : public QObject class FollowRedirectReply : public QObject {
{ Q_OBJECT
Q_OBJECT
public:
explicit FollowRedirectReply(const QUrl &url, QNetworkAccessManager* manager);
~FollowRedirectReply();
QNetworkReply* reply() const; public:
QUrl originalUrl() const; explicit FollowRedirectReply(const QUrl &url, QNetworkAccessManager* manager);
QUrl url() const; virtual ~FollowRedirectReply();
QNetworkReply::NetworkError error() const; QNetworkReply *reply() const;
QByteArray readAll(); QUrl originalUrl() const;
QUrl url() const;
signals: QNetworkReply::NetworkError error() const;
void finished(); QByteArray readAll();
private slots: signals:
void replyFinished(); void finished();
private: private slots:
QNetworkAccessManager* m_manager; void replyFinished();
QNetworkReply* m_reply;
int m_redirectCount;
private:
QNetworkAccessManager *m_manager;
QNetworkReply *m_reply;
int m_redirectCount;
}; };
#endif // FOLLOWREDIRECTREPLY_H #endif // FOLLOWREDIRECTREPLY_H

View File

@ -23,7 +23,7 @@
Downloader::Downloader(QObject *parent) Downloader::Downloader(QObject *parent)
: QObject(parent), m_activeReply(NULL), m_downloadManager(SilentNetworkAccessManager::instance()), : QObject(parent), m_activeReply(NULL), m_downloadManager(new SilentNetworkAccessManager(this)),
m_timer(new QTimer(this)), m_customHeaders(QHash<QByteArray, QByteArray>()), m_lastOutputData(QByteArray()), m_timer(new QTimer(this)), m_customHeaders(QHash<QByteArray, QByteArray>()), m_lastOutputData(QByteArray()),
m_lastOutputError(QNetworkReply::NoError), m_lastContentType(QVariant()) { m_lastOutputError(QNetworkReply::NoError), m_lastContentType(QVariant()) {
@ -34,7 +34,7 @@ Downloader::Downloader(QObject *parent)
} }
Downloader::~Downloader() { Downloader::~Downloader() {
//m_downloadManager->deleteLater(); m_downloadManager->deleteLater();
} }
void Downloader::downloadFile(const QString &url, int timeout, bool protected_contents, const QString &username, const QString &password) { void Downloader::downloadFile(const QString &url, int timeout, bool protected_contents, const QString &username, const QString &password) {

View File

@ -135,6 +135,41 @@ QString WebFactory::deEscapeHtml(const QString &text) {
return output; return output;
} }
QString WebFactory::toSecondLevelDomain(const QUrl &url) {
#if QT_VERSION >= 0x040800
const QString top_level_domain = url.topLevelDomain();
const QString url_host = url.host();
if (top_level_domain.isEmpty() || url_host.isEmpty()) {
return QString();
}
QString domain = url_host.left(url_host.size() - top_level_domain.size());
if (domain.count(QL1C('.')) == 0) {
return url_host;
}
while (domain.count(QL1C('.')) != 0) {
domain = domain.mid(domain.indexOf(QL1C('.')) + 1);
}
return domain + top_level_domain;
#else
QString domain = url.host();
if (domain.count(QL1C('.')) == 0) {
return QString();
}
while (domain.count(QL1C('.')) != 1) {
domain = domain.mid(domain.indexOf(QL1C('.')) + 1);
}
return domain;
#endif
}
void WebFactory::generetaEscapes() { void WebFactory::generetaEscapes() {
m_escapes["&lt;"] = '<'; m_escapes["&lt;"] = '<';
m_escapes["&gt;"] = '>'; m_escapes["&gt;"] = '>';

4
src/network-web/webfactory.h Normal file → Executable file
View File

@ -30,6 +30,10 @@ class WebFactory : public QObject {
QString escapeHtml(const QString &html); QString escapeHtml(const QString &html);
QString deEscapeHtml(const QString &text); QString deEscapeHtml(const QString &text);
// BUG: Version for Qt < 4.8 has one issue, it will wrongly
// count .co.uk (and others) as second-level domain
QString toSecondLevelDomain(const QUrl &url);
// Switchers. // Switchers.
bool javascriptEnabled() const; bool javascriptEnabled() const;
bool pluginsEnabled() const; bool pluginsEnabled() const;