VERY VERY experimental merge of AdBlock from Qupzilla and QuiteRSS. Code will undergoe heavy optimizations to fit RSS Guard philosophy.
This commit is contained in:
parent
d2fda0560d
commit
2dbba7c5dc
@ -419,6 +419,20 @@ set(APP_SOURCES
|
||||
src/network-web/discoverfeedsbutton.cpp
|
||||
src/network-web/googlesuggest.cpp
|
||||
|
||||
src/network-web/adblock/adblockaddsubscriptiondialog.cpp
|
||||
src/network-web/adblock/adblockblockednetworkreply.cpp
|
||||
src/network-web/adblock/adblockdialog.cpp
|
||||
src/network-web/adblock/adblockicon.cpp
|
||||
src/network-web/adblock/adblockmanager.cpp
|
||||
src/network-web/adblock/adblockmatcher.cpp
|
||||
src/network-web/adblock/adblockrule.cpp
|
||||
src/network-web/adblock/adblocksearchtree.cpp
|
||||
src/network-web/adblock/adblocksubscription.cpp
|
||||
src/network-web/adblock/adblocktreewidget.cpp
|
||||
src/network-web/adblock/followredirectreply.cpp
|
||||
|
||||
|
||||
|
||||
# MAIN sources.
|
||||
src/main.cpp
|
||||
)
|
||||
@ -505,6 +519,18 @@ set(APP_HEADERS
|
||||
src/network-web/downloadmanager.h
|
||||
src/network-web/discoverfeedsbutton.h
|
||||
src/network-web/googlesuggest.h
|
||||
|
||||
src/network-web/adblock/adblockaddsubscriptiondialog.h
|
||||
src/network-web/adblock/adblockblockednetworkreply.h
|
||||
src/network-web/adblock/adblockdialog.h
|
||||
src/network-web/adblock/adblockicon.h
|
||||
src/network-web/adblock/adblockmanager.h
|
||||
src/network-web/adblock/adblockmatcher.h
|
||||
src/network-web/adblock/adblockrule.h
|
||||
src/network-web/adblock/adblocksearchtree.h
|
||||
src/network-web/adblock/adblocksubscription.h
|
||||
src/network-web/adblock/adblocktreewidget.h
|
||||
src/network-web/adblock/followredirectreply.h
|
||||
)
|
||||
|
||||
# APP form files.
|
||||
@ -522,6 +548,9 @@ set(APP_FORMS
|
||||
src/gui/formdatabasecleanup.ui
|
||||
src/network-web/downloadmanager.ui
|
||||
src/network-web/downloaditem.ui
|
||||
|
||||
src/network-web/adblock/adblockaddsubscriptiondialog.ui
|
||||
src/network-web/adblock/adblockdialog.ui
|
||||
)
|
||||
|
||||
# APP translations.
|
||||
|
@ -31,6 +31,8 @@ StatusBar::StatusBar(QWidget *parent) : QStatusBar(parent) {
|
||||
setSizeGripEnabled(false);
|
||||
setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
adblockIcon_ = new AdBlockIcon(this);
|
||||
|
||||
// Initializations of widgets for status bar.
|
||||
m_fullscreenSwitcher = new QToolButton(this);
|
||||
m_fullscreenSwitcher->setAutoRaise(true);
|
||||
@ -67,6 +69,7 @@ StatusBar::StatusBar(QWidget *parent) : QStatusBar(parent) {
|
||||
addPermanentWidget(m_lblProgressDownload);
|
||||
addPermanentWidget(m_barProgressDownload);
|
||||
addPermanentWidget(m_fullscreenSwitcher);
|
||||
addPermanentWidget(adblockIcon_);
|
||||
}
|
||||
|
||||
StatusBar::~StatusBar() {
|
||||
|
@ -20,6 +20,8 @@
|
||||
|
||||
#include <QStatusBar>
|
||||
|
||||
#include <adblock/adblockicon.h>
|
||||
|
||||
|
||||
class QProgressBar;
|
||||
class QToolButton;
|
||||
@ -37,6 +39,8 @@ class StatusBar : public QStatusBar {
|
||||
return m_fullscreenSwitcher;
|
||||
}
|
||||
|
||||
AdBlockIcon *adBlockIcon() { return adblockIcon_; }
|
||||
|
||||
public slots:
|
||||
// Progress bar operations
|
||||
void showProgressFeeds(int progress, const QString &label);
|
||||
@ -55,7 +59,8 @@ class StatusBar : public QStatusBar {
|
||||
QLabel *m_lblProgressFeeds;
|
||||
QProgressBar *m_barProgressDownload;
|
||||
QLabel *m_lblProgressDownload;
|
||||
QToolButton *m_fullscreenSwitcher;
|
||||
QToolButton *m_fullscreenSwitcher;
|
||||
AdBlockIcon* adblockIcon_;
|
||||
};
|
||||
|
||||
#endif // STATUSBAR_H
|
||||
|
@ -31,6 +31,8 @@
|
||||
#include <QThread>
|
||||
#include <QProcess>
|
||||
|
||||
#include <adblock/adblockmanager.h>
|
||||
|
||||
|
||||
Application::Application(const QString &id, int &argc, char **argv)
|
||||
: QtSingleApplication(id, argc, argv),
|
||||
@ -208,6 +210,7 @@ void Application::onAboutToQuit() {
|
||||
mainForm()->tabWidget()->feedMessageViewer()->quit();
|
||||
database()->saveDatabase();
|
||||
mainForm()->saveSize();
|
||||
AdBlockManager::instance()->save();
|
||||
|
||||
if (locked_safely) {
|
||||
// Application obtained permission to close in a safe way.
|
||||
|
114
src/network-web/adblock/adblockaddsubscriptiondialog.cpp
Executable file
114
src/network-web/adblock/adblockaddsubscriptiondialog.cpp
Executable file
@ -0,0 +1,114 @@
|
||||
/* ============================================================
|
||||
* QuiteRSS is a open-source cross-platform RSS/Atom news feeds reader
|
||||
* Copyright (C) 2011-2015 QuiteRSS Team <quiterssteam@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/>.
|
||||
* ============================================================ */
|
||||
/* ============================================================
|
||||
* 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/>.
|
||||
* ============================================================ */
|
||||
#include "adblockaddsubscriptiondialog.h"
|
||||
#include "adblockmanager.h"
|
||||
#include "ui_adblockaddsubscriptiondialog.h"
|
||||
|
||||
AdBlockAddSubscriptionDialog::AdBlockAddSubscriptionDialog(QWidget* parent)
|
||||
: QDialog(parent)
|
||||
, ui(new Ui::AdBlockAddSubscriptionDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
m_knownSubscriptions << Subscription("EasyList (English)", ADBLOCK_EASYLIST_URL)
|
||||
<< Subscription("Fanboy's List (English)", "http://www.fanboy.co.nz/adblock/fanboy-adblock.txt")
|
||||
<< Subscription("Adversity (English)", "http://adversity.googlecode.com/hg/Adversity.txt")
|
||||
<< Subscription("BSI Lista Polska (Polish)", "http://www.bsi.info.pl/filtrABP.txt")
|
||||
<< Subscription("Czech List (Czech)", "http://adblock.dajbych.net/adblock.txt")
|
||||
<< Subscription("dutchblock (Dutch)", "http://groenewoudt.net/dutchblock/list.txt")
|
||||
<< Subscription("Filtros Nauscopicos (Spanish)", "http://abp.mozilla-hispano.org/nauscopio/filtros.txt")
|
||||
<< Subscription("hufilter (Hungarian)", "http://www.hufilter.hu/hufilter.txt")
|
||||
<< Subscription("IsraelList (Hebrew)", "http://secure.fanboy.co.nz/israelilist/IsraelList.txt")
|
||||
<< Subscription("Lista Basa (Polish)", "http://plok.studentlive.pl/abp.txt")
|
||||
<< Subscription("NLBlock (Dutch)", "http://www.verzijlbergh.com/adblock/nlblock.txt")
|
||||
<< Subscription("Peter Lowe's list (English)", "http://pgl.yoyo.org/adservers/serverlist.php?hostformat=adblockplus&mimetype=plaintext")
|
||||
<< Subscription("PLgeneral (Polish)", "http://www.niecko.pl/adblock/adblock.txt")
|
||||
<< Subscription("Schacks Adblock Plus liste (Danish)", "http://adblock.schack.dk/block.txt")
|
||||
<< Subscription("Xfiles (Italian)", "http://mozilla.gfsolone.com/filtri.txt")
|
||||
<< Subscription("EasyPrivacy (English)", "http://easylist-downloads.adblockplus.org/easyprivacy.txt")
|
||||
<< Subscription("Antisocial (English)", "http://adversity.googlecode.com/hg/Antisocial.txt")
|
||||
<< Subscription("RuAdList+EasyList (Russian, Ukrainian)", "https://easylist-downloads.adblockplus.org/ruadlist+easylist.txt")
|
||||
<< Subscription("RU AdList (Russian, Ukrainian)", "https://easylist-downloads.adblockplus.org/advblock.txt")
|
||||
<< Subscription("ABPindo (Indonesian)", "https://indonesianadblockrules.googlecode.com/hg/subscriptions/abpindo.txt")
|
||||
<< Subscription("ChinaList (Chinese)", "http://adblock-chinalist.googlecode.com/svn/trunk/adblock.txt")
|
||||
<< Subscription("Malware Domains list", "https://easylist-downloads.adblockplus.org/malwaredomains_full.txt");
|
||||
|
||||
foreach (const Subscription &subscription, m_knownSubscriptions) {
|
||||
ui->comboBox->addItem(subscription.title);
|
||||
}
|
||||
|
||||
connect(ui->comboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(indexChanged(int)));
|
||||
indexChanged(0);
|
||||
}
|
||||
|
||||
QString AdBlockAddSubscriptionDialog::title() const
|
||||
{
|
||||
return ui->title->text();
|
||||
}
|
||||
|
||||
QString AdBlockAddSubscriptionDialog::url() const
|
||||
{
|
||||
return ui->url->text();
|
||||
}
|
||||
|
||||
void AdBlockAddSubscriptionDialog::indexChanged(int index)
|
||||
{
|
||||
const Subscription subscription = m_knownSubscriptions.at(index);
|
||||
|
||||
// "Other..." entry
|
||||
if (subscription.url.isEmpty()) {
|
||||
ui->title->clear();
|
||||
ui->url->clear();
|
||||
}
|
||||
else {
|
||||
int pos = subscription.title.indexOf(QLatin1Char('('));
|
||||
QString title = subscription.title;
|
||||
|
||||
if (pos > 0) {
|
||||
title = title.left(pos).trimmed();
|
||||
}
|
||||
|
||||
ui->title->setText(title);
|
||||
ui->title->setCursorPosition(0);
|
||||
|
||||
ui->url->setText(subscription.url);
|
||||
ui->url->setCursorPosition(0);
|
||||
}
|
||||
}
|
||||
|
||||
AdBlockAddSubscriptionDialog::~AdBlockAddSubscriptionDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
78
src/network-web/adblock/adblockaddsubscriptiondialog.h
Executable file
78
src/network-web/adblock/adblockaddsubscriptiondialog.h
Executable file
@ -0,0 +1,78 @@
|
||||
/* ============================================================
|
||||
* QuiteRSS is a open-source cross-platform RSS/Atom news feeds reader
|
||||
* Copyright (C) 2011-2015 QuiteRSS Team <quiterssteam@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/>.
|
||||
* ============================================================ */
|
||||
/* ============================================================
|
||||
* 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 ADBLOCKADDSUBSCRIPTIONDIALOG_H
|
||||
#define ADBLOCKADDSUBSCRIPTIONDIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
#include <QVector>
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class AdBlockAddSubscriptionDialog;
|
||||
}
|
||||
|
||||
class AdBlockAddSubscriptionDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit AdBlockAddSubscriptionDialog(QWidget* parent = 0);
|
||||
~AdBlockAddSubscriptionDialog();
|
||||
|
||||
QString title() const;
|
||||
QString url() const;
|
||||
|
||||
private slots:
|
||||
void indexChanged(int index);
|
||||
|
||||
private:
|
||||
Ui::AdBlockAddSubscriptionDialog* ui;
|
||||
|
||||
struct Subscription {
|
||||
QString title;
|
||||
QString url;
|
||||
|
||||
Subscription() {}
|
||||
|
||||
Subscription(const QString &t, const QString &u) {
|
||||
title = t;
|
||||
url = u;
|
||||
}
|
||||
};
|
||||
|
||||
QVector<Subscription> m_knownSubscriptions;
|
||||
};
|
||||
|
||||
#endif // ADBLOCKADDSUBSCRIPTIONDIALOG_H
|
94
src/network-web/adblock/adblockaddsubscriptiondialog.ui
Executable file
94
src/network-web/adblock/adblockaddsubscriptiondialog.ui
Executable file
@ -0,0 +1,94 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>AdBlockAddSubscriptionDialog</class>
|
||||
<widget class="QDialog" name="AdBlockAddSubscriptionDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>557</width>
|
||||
<height>162</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Add Subscription</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="QComboBox" name="comboBox"/>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Title:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="title"/>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Address:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLineEdit" name="url"/>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Add new subscription to AdBlock:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>AdBlockAddSubscriptionDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>AdBlockAddSubscriptionDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
99
src/network-web/adblock/adblockblockednetworkreply.cpp
Executable file
99
src/network-web/adblock/adblockblockednetworkreply.cpp
Executable file
@ -0,0 +1,99 @@
|
||||
/* ============================================================
|
||||
* QuiteRSS is a open-source cross-platform RSS/Atom news feeds reader
|
||||
* Copyright (C) 2011-2015 QuiteRSS Team <quiterssteam@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/>.
|
||||
* ============================================================ */
|
||||
/* ============================================================
|
||||
* 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>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Benjamin Meyer nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "adblockblockednetworkreply.h"
|
||||
#include "adblocksubscription.h"
|
||||
#include "adblockrule.h"
|
||||
|
||||
#include <QNetworkRequest>
|
||||
#include <QTimer>
|
||||
|
||||
AdBlockBlockedNetworkReply::AdBlockBlockedNetworkReply(const AdBlockRule* rule, QObject* parent)
|
||||
: QNetworkReply(parent)
|
||||
{
|
||||
setOperation(QNetworkAccessManager::GetOperation);
|
||||
setError(QNetworkReply::ContentAccessDenied, QString("AdBlock: %1 (%2)").arg(rule->subscription()->title(), rule->filter()));
|
||||
|
||||
open(QIODevice::ReadOnly);
|
||||
|
||||
QTimer::singleShot(0, this, SLOT(delayedFinished()));
|
||||
}
|
||||
|
||||
void AdBlockBlockedNetworkReply::setRequest(const QNetworkRequest &request)
|
||||
{
|
||||
QNetworkReply::setRequest(request);
|
||||
setUrl(request.url());
|
||||
}
|
||||
|
||||
qint64 AdBlockBlockedNetworkReply::readData(char* data, qint64 maxSize)
|
||||
{
|
||||
Q_UNUSED(data);
|
||||
Q_UNUSED(maxSize);
|
||||
return -1;
|
||||
}
|
||||
|
||||
void AdBlockBlockedNetworkReply::delayedFinished()
|
||||
{
|
||||
emit error(QNetworkReply::ContentAccessDenied);
|
||||
emit finished();
|
||||
}
|
||||
|
90
src/network-web/adblock/adblockblockednetworkreply.h
Executable file
90
src/network-web/adblock/adblockblockednetworkreply.h
Executable file
@ -0,0 +1,90 @@
|
||||
/* ============================================================
|
||||
* QuiteRSS is a open-source cross-platform RSS/Atom news feeds reader
|
||||
* Copyright (C) 2011-2015 QuiteRSS Team <quiterssteam@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/>.
|
||||
* ============================================================ */
|
||||
/* ============================================================
|
||||
* 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>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Benjamin Meyer nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef ADBLOCKBLOCKEDNETWORKREPLY_H
|
||||
#define ADBLOCKBLOCKEDNETWORKREPLY_H
|
||||
|
||||
#include <QNetworkReply>
|
||||
|
||||
class AdBlockRule;
|
||||
class AdBlockSubscription;
|
||||
|
||||
class AdBlockBlockedNetworkReply : public QNetworkReply
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
AdBlockBlockedNetworkReply(const AdBlockRule* rule, QObject* parent = 0);
|
||||
void abort() {}
|
||||
|
||||
void setRequest(const QNetworkRequest &request);
|
||||
|
||||
protected:
|
||||
qint64 readData(char* data, qint64 maxSize);
|
||||
|
||||
private slots:
|
||||
void delayedFinished();
|
||||
|
||||
};
|
||||
|
||||
#endif // ADBLOCKBLOCKEDNETWORKREPLY_H
|
||||
|
223
src/network-web/adblock/adblockdialog.cpp
Executable file
223
src/network-web/adblock/adblockdialog.cpp
Executable file
@ -0,0 +1,223 @@
|
||||
/* ============================================================
|
||||
* QuiteRSS is a open-source cross-platform RSS/Atom news feeds reader
|
||||
* Copyright (C) 2011-2015 QuiteRSS Team <quiterssteam@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/>.
|
||||
* ============================================================ */
|
||||
/* ============================================================
|
||||
* 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/>.
|
||||
* ============================================================ */
|
||||
#include "adblockdialog.h"
|
||||
#include "adblockmanager.h"
|
||||
#include "adblocksubscription.h"
|
||||
#include "adblocktreewidget.h"
|
||||
#include "adblockaddsubscriptiondialog.h"
|
||||
|
||||
#include <QDesktopWidget>
|
||||
#include <QMenu>
|
||||
#include <QTimer>
|
||||
#include <QMessageBox>
|
||||
#include <QInputDialog>
|
||||
|
||||
AdBlockDialog::AdBlockDialog(QWidget* parent)
|
||||
: QWidget(parent)
|
||||
, m_manager(AdBlockManager::instance())
|
||||
, m_currentTreeWidget(0)
|
||||
, m_currentSubscription(0)
|
||||
, m_loaded(false)
|
||||
, m_useLimitedEasyList(false)
|
||||
{
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
setupUi(this);
|
||||
|
||||
const QRect screen = QApplication::desktop()->screenGeometry();
|
||||
const QRect size = geometry();
|
||||
move((screen.width() - size.width()) / 2, (screen.height() - size.height()) / 2);
|
||||
tabWidget->setDocumentMode(false);
|
||||
#ifdef Q_OS_MAC
|
||||
tabWidget->setDocumentMode(false);
|
||||
#endif
|
||||
adblockCheckBox->setChecked(m_manager->isEnabled());
|
||||
|
||||
buttonOptions->setText(buttonOptions->text() % " ");
|
||||
|
||||
QMenu* menu = new QMenu(buttonOptions);
|
||||
m_actionAddRule = menu->addAction(tr("Add Rule"), this, SLOT(addRule()));
|
||||
m_actionRemoveRule = menu->addAction(tr("Remove Rule"), this, SLOT(removeRule()));
|
||||
menu->addSeparator();
|
||||
m_actionAddSubscription = menu->addAction(tr("Add Subscription"), this, SLOT(addSubscription()));
|
||||
m_actionRemoveSubscription = menu->addAction(tr("Remove Subscription"), this, SLOT(removeSubscription()));
|
||||
menu->addAction(tr("Update Subscriptions"), m_manager, SLOT(updateAllSubscriptions()));
|
||||
menu->addSeparator();
|
||||
menu->addAction(tr("Learn about writing rules..."), this, SLOT(learnAboutRules()));
|
||||
|
||||
buttonOptions->setMenu(menu);
|
||||
connect(menu, SIGNAL(aboutToShow()), this, SLOT(aboutToShowMenu()));
|
||||
|
||||
connect(adblockCheckBox, SIGNAL(toggled(bool)), this, SLOT(enableAdBlock(bool)));
|
||||
connect(search, SIGNAL(textChanged(QString)), this, SLOT(filterString(QString)));
|
||||
connect(tabWidget, SIGNAL(currentChanged(int)), this, SLOT(currentChanged(int)));
|
||||
connect(buttonBox, SIGNAL(accepted()), this, SLOT(close()));
|
||||
|
||||
load();
|
||||
|
||||
buttonBox->setFocus();
|
||||
}
|
||||
|
||||
void AdBlockDialog::showRule(const AdBlockRule* rule) const
|
||||
{
|
||||
AdBlockSubscription* subscription = rule->subscription();
|
||||
if (!subscription) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < tabWidget->count(); ++i) {
|
||||
AdBlockTreeWidget* treeWidget = qobject_cast<AdBlockTreeWidget*>(tabWidget->widget(i));
|
||||
|
||||
if (subscription == treeWidget->subscription()) {
|
||||
treeWidget->showRule(rule);
|
||||
tabWidget->setCurrentIndex(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AdBlockDialog::addRule()
|
||||
{
|
||||
m_currentTreeWidget->addRule();
|
||||
}
|
||||
|
||||
void AdBlockDialog::removeRule()
|
||||
{
|
||||
m_currentTreeWidget->removeRule();
|
||||
}
|
||||
|
||||
void AdBlockDialog::addSubscription()
|
||||
{
|
||||
AdBlockAddSubscriptionDialog dialog(this);
|
||||
if (dialog.exec() != QDialog::Accepted) {
|
||||
return;
|
||||
}
|
||||
|
||||
QString title = dialog.title();
|
||||
QString url = dialog.url();
|
||||
|
||||
if (AdBlockSubscription* subscription = m_manager->addSubscription(title, url)) {
|
||||
AdBlockTreeWidget* tree = new AdBlockTreeWidget(subscription, tabWidget);
|
||||
int index = tabWidget->insertTab(tabWidget->count() - 1, tree, subscription->title());
|
||||
|
||||
tabWidget->setCurrentIndex(index);
|
||||
}
|
||||
}
|
||||
|
||||
void AdBlockDialog::removeSubscription()
|
||||
{
|
||||
if (m_manager->removeSubscription(m_currentSubscription)) {
|
||||
delete m_currentTreeWidget;
|
||||
}
|
||||
}
|
||||
|
||||
void AdBlockDialog::currentChanged(int index)
|
||||
{
|
||||
if (index != -1) {
|
||||
m_currentTreeWidget = qobject_cast<AdBlockTreeWidget*>(tabWidget->widget(index));
|
||||
m_currentSubscription = m_currentTreeWidget->subscription();
|
||||
|
||||
bool isEasyList = m_currentSubscription->url() == QUrl(ADBLOCK_EASYLIST_URL);
|
||||
useLimitedEasyList->setVisible(isEasyList);
|
||||
}
|
||||
}
|
||||
|
||||
void AdBlockDialog::filterString(const QString &string)
|
||||
{
|
||||
if (m_currentTreeWidget && adblockCheckBox->isChecked()) {
|
||||
m_currentTreeWidget->filterString(string);
|
||||
}
|
||||
}
|
||||
|
||||
void AdBlockDialog::enableAdBlock(bool state)
|
||||
{
|
||||
m_manager->setEnabled(state);
|
||||
|
||||
if (state) {
|
||||
load();
|
||||
}
|
||||
}
|
||||
|
||||
void AdBlockDialog::aboutToShowMenu()
|
||||
{
|
||||
bool subscriptionEditable = m_currentSubscription && m_currentSubscription->canEditRules();
|
||||
bool subscriptionRemovable = m_currentSubscription && m_currentSubscription->canBeRemoved();
|
||||
|
||||
m_actionAddRule->setEnabled(subscriptionEditable);
|
||||
m_actionRemoveRule->setEnabled(subscriptionEditable);
|
||||
m_actionRemoveSubscription->setEnabled(subscriptionRemovable);
|
||||
}
|
||||
|
||||
void AdBlockDialog::learnAboutRules()
|
||||
{
|
||||
// TODO
|
||||
//mainApp->mainWindow()->openNewsTab_ = NEW_TAB_FOREGROUND;
|
||||
//mainApp->mainWindow()->createWebTab(QUrl("http://adblockplus.org/en/filters"));
|
||||
}
|
||||
|
||||
void AdBlockDialog::loadSubscriptions()
|
||||
{
|
||||
for (int i = 0; i < tabWidget->count(); ++i) {
|
||||
AdBlockTreeWidget* treeWidget = qobject_cast<AdBlockTreeWidget*>(tabWidget->widget(i));
|
||||
treeWidget->refresh();
|
||||
}
|
||||
}
|
||||
|
||||
void AdBlockDialog::load()
|
||||
{
|
||||
if (m_loaded || !adblockCheckBox->isChecked()) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (AdBlockSubscription* subscription, m_manager->subscriptions()) {
|
||||
AdBlockTreeWidget* tree = new AdBlockTreeWidget(subscription, tabWidget);
|
||||
tabWidget->addTab(tree, subscription->title());
|
||||
}
|
||||
|
||||
m_useLimitedEasyList = m_manager->useLimitedEasyList();
|
||||
useLimitedEasyList->setChecked(m_useLimitedEasyList);
|
||||
|
||||
m_loaded = true;
|
||||
|
||||
QTimer::singleShot(50, this, SLOT(loadSubscriptions()));
|
||||
}
|
||||
|
||||
void AdBlockDialog::closeEvent(QCloseEvent* ev)
|
||||
{
|
||||
if (useLimitedEasyList->isChecked() != m_useLimitedEasyList) {
|
||||
m_manager->setUseLimitedEasyList(useLimitedEasyList->isChecked());
|
||||
}
|
||||
|
||||
QWidget::closeEvent(ev);
|
||||
}
|
90
src/network-web/adblock/adblockdialog.h
Executable file
90
src/network-web/adblock/adblockdialog.h
Executable file
@ -0,0 +1,90 @@
|
||||
/* ============================================================
|
||||
* QuiteRSS is a open-source cross-platform RSS/Atom news feeds reader
|
||||
* Copyright (C) 2011-2015 QuiteRSS Team <quiterssteam@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/>.
|
||||
* ============================================================ */
|
||||
/* ============================================================
|
||||
* 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 ADBLOCKDIALOG_H
|
||||
#define ADBLOCKDIALOG_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
#include "ui_adblockdialog.h"
|
||||
|
||||
class AdBlockSubscription;
|
||||
class AdBlockTreeWidget;
|
||||
class AdBlockManager;
|
||||
class AdBlockRule;
|
||||
|
||||
class AdBlockDialog : public QWidget, public Ui_AdBlockDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit AdBlockDialog(QWidget* parent = 0);
|
||||
|
||||
void showRule(const AdBlockRule* rule) const;
|
||||
|
||||
private slots:
|
||||
void addRule();
|
||||
void removeRule();
|
||||
|
||||
void addSubscription();
|
||||
void removeSubscription();
|
||||
|
||||
void currentChanged(int index);
|
||||
void filterString(const QString &string);
|
||||
void enableAdBlock(bool state);
|
||||
|
||||
void aboutToShowMenu();
|
||||
void learnAboutRules();
|
||||
|
||||
void loadSubscriptions();
|
||||
void load();
|
||||
|
||||
private:
|
||||
void closeEvent(QCloseEvent* ev);
|
||||
|
||||
AdBlockManager* m_manager;
|
||||
AdBlockTreeWidget* m_currentTreeWidget;
|
||||
AdBlockSubscription* m_currentSubscription;
|
||||
|
||||
QAction* m_actionAddRule;
|
||||
QAction* m_actionRemoveRule;
|
||||
QAction* m_actionAddSubscription;
|
||||
QAction* m_actionRemoveSubscription;
|
||||
|
||||
bool m_loaded;
|
||||
bool m_useLimitedEasyList;
|
||||
};
|
||||
|
||||
#endif // ADBLOCKDIALOG_H
|
||||
|
161
src/network-web/adblock/adblockdialog.ui
Executable file
161
src/network-web/adblock/adblockdialog.ui
Executable file
@ -0,0 +1,161 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>AdBlockDialog</class>
|
||||
<widget class="QWidget" name="AdBlockDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>546</width>
|
||||
<height>462</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>AdBlock Configuration</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="adblockCheckBox">
|
||||
<property name="text">
|
||||
<string>Enable AdBlock</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<widget class="QLineEdit" name="search">
|
||||
<property name="placeholderText">
|
||||
<string>Search...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="adblockWidget" native="true">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<property name="margin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="4" column="0" colspan="2">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QPushButton" name="buttonOptions">
|
||||
<property name="text">
|
||||
<string>Options</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../QuiteRSS.qrc">
|
||||
<normaloff>:/images/images/adblock.png</normaloff>:/images/images/adblock.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>AdBlock</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QTabWidget" name="tabWidget">
|
||||
<property name="currentIndex">
|
||||
<number>-1</number>
|
||||
</property>
|
||||
<property name="documentMode">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="useLimitedEasyList">
|
||||
<property name="text">
|
||||
<string>Use only essential part of EasyList (for performance reasons)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="../../QuiteRSS.qrc"/>
|
||||
</resources>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>adblockCheckBox</sender>
|
||||
<signal>toggled(bool)</signal>
|
||||
<receiver>adblockWidget</receiver>
|
||||
<slot>setEnabled(bool)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>106</x>
|
||||
<y>39</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>349</x>
|
||||
<y>74</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
270
src/network-web/adblock/adblockicon.cpp
Executable file
270
src/network-web/adblock/adblockicon.cpp
Executable file
@ -0,0 +1,270 @@
|
||||
/* ============================================================
|
||||
* QuiteRSS is a open-source cross-platform RSS/Atom news feeds reader
|
||||
* Copyright (C) 2011-2015 QuiteRSS Team <quiterssteam@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/>.
|
||||
* ============================================================ */
|
||||
/* ============================================================
|
||||
* 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/>.
|
||||
* ============================================================ */
|
||||
#include "adblockicon.h"
|
||||
#include "adblockrule.h"
|
||||
#include "adblockmanager.h"
|
||||
#include "adblocksubscription.h"
|
||||
#include "webpage.h"
|
||||
|
||||
#include "miscellaneous/application.h"
|
||||
#include "gui/formmain.h"
|
||||
#include "gui/tabwidget.h"
|
||||
#include "network-web/webbrowser.h"
|
||||
|
||||
#include <QMenu>
|
||||
#include <QMouseEvent>
|
||||
#include <QTimer>
|
||||
#include <QWebFrame>
|
||||
|
||||
|
||||
AdBlockIcon::AdBlockIcon(QWidget *window, QWidget *parent)
|
||||
: QToolButton(parent)
|
||||
, m_window(window)
|
||||
, m_menuAction(0)
|
||||
, m_flashTimer(0)
|
||||
, m_timerTicks(0)
|
||||
, m_enabled(false)
|
||||
{
|
||||
setFocusPolicy(Qt::NoFocus);
|
||||
setStyleSheet("QToolButton { border: none; padding: 0px; }");
|
||||
|
||||
connect(this, SIGNAL(clicked(QPoint)), this, SLOT(showMenu(QPoint)));
|
||||
connect(AdBlockManager::instance(), SIGNAL(enabledChanged(bool)), this, SLOT(setEnabled(bool)));
|
||||
}
|
||||
|
||||
void AdBlockIcon::retranslateStrings()
|
||||
{
|
||||
setToolTip(tr("AdBlock lets you block unwanted content on web pages"));
|
||||
|
||||
AdBlockManager::instance()->customList()->retranslateStrings();
|
||||
}
|
||||
|
||||
void AdBlockIcon::popupBlocked(const QString &ruleString, const QUrl &url)
|
||||
{
|
||||
int index = ruleString.lastIndexOf(QLatin1String(" ("));
|
||||
|
||||
const QString subscriptionName = ruleString.left(index);
|
||||
const QString filter = ruleString.mid(index + 2, ruleString.size() - index - 3);
|
||||
AdBlockSubscription* subscription = AdBlockManager::instance()->subscriptionByName(subscriptionName);
|
||||
if (filter.isEmpty() || !subscription) {
|
||||
return;
|
||||
}
|
||||
|
||||
QPair<AdBlockRule*, QUrl> pair;
|
||||
pair.first = new AdBlockRule(filter, subscription);
|
||||
pair.second = url;
|
||||
m_blockedPopups.append(pair);
|
||||
|
||||
//!** FIXME
|
||||
// mApp->desktopNotifications()->showNotification(QPixmap(":images/images/adblock_big.png"), tr("Blocked popup window"), tr("AdBlock blocked unwanted popup window."));
|
||||
|
||||
if (!m_flashTimer) {
|
||||
m_flashTimer = new QTimer(this);
|
||||
}
|
||||
|
||||
if (m_flashTimer->isActive()) {
|
||||
stopAnimation();
|
||||
}
|
||||
|
||||
m_flashTimer->setInterval(500);
|
||||
m_flashTimer->start();
|
||||
|
||||
connect(m_flashTimer, SIGNAL(timeout()), this, SLOT(animateIcon()));
|
||||
}
|
||||
|
||||
QAction* AdBlockIcon::menuAction()
|
||||
{
|
||||
if (!m_menuAction) {
|
||||
m_menuAction = new QAction(tr("AdBlock"), this);
|
||||
m_menuAction->setMenu(new QMenu);
|
||||
connect(m_menuAction->menu(), SIGNAL(aboutToShow()), this, SLOT(createMenu()));
|
||||
}
|
||||
|
||||
m_menuAction->setIcon(QIcon(m_enabled ? ":images/images/adblock.png" : ":images/images/adblock-disabled.png"));
|
||||
|
||||
return m_menuAction;
|
||||
}
|
||||
|
||||
void AdBlockIcon::createMenu(QMenu* menu)
|
||||
{
|
||||
if (!menu) {
|
||||
menu = qobject_cast<QMenu*>(sender());
|
||||
if (!menu) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
menu->clear();
|
||||
|
||||
AdBlockManager* manager = AdBlockManager::instance();
|
||||
AdBlockCustomList* customList = manager->customList();
|
||||
|
||||
WebPage* page = qApp->mainForm()->tabWidget()->widget(qApp->mainForm()->tabWidget()->currentIndex())->webBrowser()->view()->page();
|
||||
const QUrl pageUrl = page->mainFrame()->url();
|
||||
|
||||
menu->addAction(tr("Show AdBlock &Settings"), manager, SLOT(showDialog()));
|
||||
menu->addSeparator();
|
||||
|
||||
if (!pageUrl.host().isEmpty() && m_enabled && manager->canRunOnScheme(pageUrl.scheme())) {
|
||||
const QString host = pageUrl.host().contains(QLatin1String("www.")) ? pageUrl.host().mid(4) : pageUrl.host();
|
||||
const QString hostFilter = QString("@@||%1^$document").arg(host);
|
||||
const QString pageFilter = QString("@@|%1|$document").arg(pageUrl.toString());
|
||||
|
||||
QAction* act = menu->addAction(tr("Disable on %1").arg(host));
|
||||
act->setCheckable(true);
|
||||
act->setChecked(customList->containsFilter(hostFilter));
|
||||
act->setData(hostFilter);
|
||||
connect(act, SIGNAL(triggered()), this, SLOT(toggleCustomFilter()));
|
||||
|
||||
act = menu->addAction(tr("Disable only on this page"));
|
||||
act->setCheckable(true);
|
||||
act->setChecked(customList->containsFilter(pageFilter));
|
||||
act->setData(pageFilter);
|
||||
connect(act, SIGNAL(triggered()), this, SLOT(toggleCustomFilter()));
|
||||
|
||||
menu->addSeparator();
|
||||
}
|
||||
|
||||
if (!m_blockedPopups.isEmpty()) {
|
||||
menu->addAction(tr("Blocked Popup Windows"))->setEnabled(false);
|
||||
for (int i = 0; i < m_blockedPopups.count(); i++) {
|
||||
const QPair<AdBlockRule*, QUrl> &pair = m_blockedPopups.at(i);
|
||||
|
||||
QString address = pair.second.toString().right(55);
|
||||
QString actionText = tr("%1 with (%2)").arg(address, pair.first->filter()).replace(QLatin1Char('&'), QLatin1String("&&"));
|
||||
|
||||
QAction* action = menu->addAction(actionText, manager, SLOT(showRule()));
|
||||
action->setData(QVariant::fromValue((void*)pair.first));
|
||||
}
|
||||
}
|
||||
|
||||
menu->addSeparator();
|
||||
|
||||
QVector<WebPage::AdBlockedEntry> entries = page->adBlockedEntries();
|
||||
if (entries.isEmpty()) {
|
||||
menu->addAction(tr("No content blocked"))->setEnabled(false);
|
||||
}
|
||||
else {
|
||||
menu->addAction(tr("Blocked URL (AdBlock Rule) - click to edit rule"))->setEnabled(false);
|
||||
foreach (const WebPage::AdBlockedEntry &entry, entries) {
|
||||
QString address = entry.url.toString().right(55);
|
||||
QString actionText = tr("%1 with (%2)").arg(address, entry.rule->filter()).replace(QLatin1Char('&'), QLatin1String("&&"));
|
||||
|
||||
QAction* action = menu->addAction(actionText, manager, SLOT(showRule()));
|
||||
action->setData(QVariant::fromValue((void*)entry.rule));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AdBlockIcon::showMenu(const QPoint &pos)
|
||||
{
|
||||
QMenu menu;
|
||||
createMenu(&menu);
|
||||
|
||||
menu.exec(pos);
|
||||
}
|
||||
|
||||
void AdBlockIcon::toggleCustomFilter()
|
||||
{
|
||||
QAction* action = qobject_cast<QAction*>(sender());
|
||||
if (!action) {
|
||||
return;
|
||||
}
|
||||
|
||||
const QString filter = action->data().toString();
|
||||
AdBlockManager* manager = AdBlockManager::instance();
|
||||
AdBlockCustomList* customList = manager->customList();
|
||||
|
||||
if (customList->containsFilter(filter)) {
|
||||
customList->removeFilter(filter);
|
||||
}
|
||||
else {
|
||||
AdBlockRule* rule = new AdBlockRule(filter, customList);
|
||||
customList->addRule(rule);
|
||||
}
|
||||
}
|
||||
|
||||
void AdBlockIcon::animateIcon()
|
||||
{
|
||||
++m_timerTicks;
|
||||
if (m_timerTicks > 10) {
|
||||
stopAnimation();
|
||||
return;
|
||||
}
|
||||
|
||||
if (icon().isNull()) {
|
||||
setIcon(QIcon(":images/images/adblock.png"));
|
||||
}
|
||||
else {
|
||||
setIcon(QIcon());
|
||||
}
|
||||
}
|
||||
|
||||
void AdBlockIcon::stopAnimation()
|
||||
{
|
||||
m_timerTicks = 0;
|
||||
m_flashTimer->stop();
|
||||
disconnect(m_flashTimer, SIGNAL(timeout()), this, SLOT(animateIcon()));
|
||||
|
||||
setEnabled(m_enabled);
|
||||
}
|
||||
|
||||
void AdBlockIcon::setEnabled(bool enabled)
|
||||
{
|
||||
if (enabled) {
|
||||
setIcon(QIcon(":images/images/adblock.png"));
|
||||
}
|
||||
else {
|
||||
setIcon(QIcon(":images/images/adblock-disabled.png"));
|
||||
}
|
||||
|
||||
m_enabled = enabled;
|
||||
}
|
||||
|
||||
void AdBlockIcon::mouseReleaseEvent(QMouseEvent* event)
|
||||
{
|
||||
if (event->button() == Qt::LeftButton && rect().contains(event->pos())) {
|
||||
if (event->modifiers() != Qt::ControlModifier) {
|
||||
emit clicked(event->globalPos());
|
||||
}
|
||||
}
|
||||
else {
|
||||
QToolButton::mouseReleaseEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
AdBlockIcon::~AdBlockIcon()
|
||||
{
|
||||
}
|
84
src/network-web/adblock/adblockicon.h
Executable file
84
src/network-web/adblock/adblockicon.h
Executable file
@ -0,0 +1,84 @@
|
||||
/* ============================================================
|
||||
* QuiteRSS is a open-source cross-platform RSS/Atom news feeds reader
|
||||
* Copyright (C) 2011-2015 QuiteRSS Team <quiterssteam@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/>.
|
||||
* ============================================================ */
|
||||
/* ============================================================
|
||||
* 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 ADBLOCKICON_H
|
||||
#define ADBLOCKICON_H
|
||||
|
||||
#include <QToolButton>
|
||||
|
||||
#include "adblockrule.h"
|
||||
|
||||
class QMenu;
|
||||
class QUrl;
|
||||
class MainWindow;
|
||||
|
||||
class AdBlockIcon : public QToolButton
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit AdBlockIcon(QWidget *window, QWidget *parent = 0);
|
||||
~AdBlockIcon();
|
||||
|
||||
void retranslateStrings();
|
||||
void popupBlocked(const QString &ruleString, const QUrl &url);
|
||||
QAction* menuAction();
|
||||
|
||||
signals:
|
||||
void clicked(QPoint);
|
||||
|
||||
public slots:
|
||||
void setEnabled(bool enabled);
|
||||
void createMenu(QMenu* menu = 0);
|
||||
|
||||
private slots:
|
||||
void showMenu(const QPoint &pos);
|
||||
void toggleCustomFilter();
|
||||
|
||||
void animateIcon();
|
||||
void stopAnimation();
|
||||
|
||||
private:
|
||||
void mouseReleaseEvent(QMouseEvent* event);
|
||||
|
||||
QWidget *m_window;
|
||||
QAction* m_menuAction;
|
||||
|
||||
QVector<QPair<AdBlockRule*, QUrl> > m_blockedPopups;
|
||||
QTimer* m_flashTimer;
|
||||
|
||||
int m_timerTicks;
|
||||
bool m_enabled;
|
||||
};
|
||||
|
||||
#endif // ADBLOCKICON_H
|
470
src/network-web/adblock/adblockmanager.cpp
Executable file
470
src/network-web/adblock/adblockmanager.cpp
Executable file
@ -0,0 +1,470 @@
|
||||
/* ============================================================
|
||||
* QuiteRSS is a open-source cross-platform RSS/Atom news feeds reader
|
||||
* Copyright (C) 2011-2015 QuiteRSS Team <quiterssteam@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/>.
|
||||
* ============================================================ */
|
||||
/* ============================================================
|
||||
* 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/>.
|
||||
* ============================================================ */
|
||||
#include "adblockmanager.h"
|
||||
#include "adblockdialog.h"
|
||||
#include "adblockmatcher.h"
|
||||
#include "adblocksubscription.h"
|
||||
#include "adblockblockednetworkreply.h"
|
||||
#include "adblockicon.h"
|
||||
#include "webpage.h"
|
||||
|
||||
#include "miscellaneous/application.h"
|
||||
#include "miscellaneous/settings.h"
|
||||
#include "network-web/silentnetworkaccessmanager.h"
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QTextStream>
|
||||
#include <QDir>
|
||||
#include <QTimer>
|
||||
#include <QWebFrame>
|
||||
#include <QDebug>
|
||||
|
||||
#define ADBLOCK_DEBUG
|
||||
|
||||
#ifdef ADBLOCK_DEBUG
|
||||
#include <QElapsedTimer>
|
||||
#endif
|
||||
|
||||
AdBlockManager* AdBlockManager::s_adBlockManager = 0;
|
||||
|
||||
AdBlockManager::AdBlockManager(QObject* parent)
|
||||
: QObject(parent)
|
||||
, m_loaded(false)
|
||||
, m_enabled(true)
|
||||
, m_useLimitedEasyList(true)
|
||||
, m_matcher(new AdBlockMatcher(this)), m_subscriptions(QList<AdBlockSubscription*>())
|
||||
{
|
||||
load();
|
||||
}
|
||||
|
||||
AdBlockManager::~AdBlockManager()
|
||||
{
|
||||
qDeleteAll(m_subscriptions);
|
||||
}
|
||||
|
||||
AdBlockManager* AdBlockManager::instance()
|
||||
{
|
||||
if (!s_adBlockManager) {
|
||||
s_adBlockManager = new AdBlockManager(SilentNetworkAccessManager::instance());
|
||||
}
|
||||
|
||||
return s_adBlockManager;
|
||||
}
|
||||
|
||||
QString AdBlockManager::filterCharsFromFilename(const QString &name)
|
||||
{
|
||||
QString value = name;
|
||||
|
||||
value.replace(QLatin1Char('/'), QLatin1Char('-'));
|
||||
value.remove(QLatin1Char('\\'));
|
||||
value.remove(QLatin1Char(':'));
|
||||
value.remove(QLatin1Char('*'));
|
||||
value.remove(QLatin1Char('?'));
|
||||
value.remove(QLatin1Char('"'));
|
||||
value.remove(QLatin1Char('<'));
|
||||
value.remove(QLatin1Char('>'));
|
||||
value.remove(QLatin1Char('|'));
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
QString AdBlockManager::ensureUniqueFilename(const QString &name, const QString &appendFormat)
|
||||
{
|
||||
if (!QFile::exists(name)) {
|
||||
return name;
|
||||
}
|
||||
|
||||
QString tmpFileName = name;
|
||||
int i = 1;
|
||||
while (QFile::exists(tmpFileName)) {
|
||||
tmpFileName = name;
|
||||
int index = tmpFileName.lastIndexOf(QLatin1Char('.'));
|
||||
|
||||
QString appendString = appendFormat.arg(i);
|
||||
if (index == -1) {
|
||||
tmpFileName.append(appendString);
|
||||
}
|
||||
else {
|
||||
tmpFileName = tmpFileName.left(index) + appendString + tmpFileName.mid(index);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return tmpFileName;
|
||||
}
|
||||
|
||||
void AdBlockManager::setEnabled(bool enabled)
|
||||
{
|
||||
if (m_enabled == enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_enabled = enabled;
|
||||
emit enabledChanged(enabled);
|
||||
|
||||
Settings *settings = qApp->settings();
|
||||
settings->beginGroup("AdBlock");
|
||||
settings->setValue("enabled", m_enabled);
|
||||
settings->endGroup();
|
||||
|
||||
load();
|
||||
// TODO
|
||||
//mainApp->reloadUserStyleBrowser();
|
||||
}
|
||||
|
||||
QList<AdBlockSubscription*> AdBlockManager::subscriptions() const
|
||||
{
|
||||
return m_subscriptions;
|
||||
}
|
||||
|
||||
QNetworkReply* AdBlockManager::block(const QNetworkRequest &request)
|
||||
{
|
||||
#ifdef ADBLOCK_DEBUG
|
||||
QElapsedTimer timer;
|
||||
timer.start();
|
||||
#endif
|
||||
const QString urlString = request.url().toEncoded().toLower();
|
||||
const QString urlDomain = request.url().host().toLower();
|
||||
const QString urlScheme = request.url().scheme().toLower();
|
||||
|
||||
if (!isEnabled() || !canRunOnScheme(urlScheme))
|
||||
return 0;
|
||||
|
||||
const AdBlockRule* blockedRule = m_matcher->match(request, urlDomain, urlString);
|
||||
|
||||
if (blockedRule) {
|
||||
QVariant v = request.attribute((QNetworkRequest::Attribute)(QNetworkRequest::User + 100));
|
||||
WebPage* webPage = static_cast<WebPage*>(v.value<void*>());
|
||||
if (WebPage::isPointerSafeToUse(webPage)) {
|
||||
if (!canBeBlocked(webPage->mainFrame()->url())) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
webPage->addAdBlockRule(blockedRule, request.url());
|
||||
}
|
||||
|
||||
AdBlockBlockedNetworkReply* reply = new AdBlockBlockedNetworkReply(blockedRule, this);
|
||||
reply->setRequest(request);
|
||||
|
||||
#ifdef ADBLOCK_DEBUG
|
||||
qDebug() << "BLOCKED: " << timer.elapsed() << blockedRule->filter() << request.url();
|
||||
#endif
|
||||
|
||||
return reply;
|
||||
}
|
||||
|
||||
#ifdef ADBLOCK_DEBUG
|
||||
qDebug() << timer.elapsed() << request.url();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
QStringList AdBlockManager::disabledRules() const
|
||||
{
|
||||
return m_disabledRules;
|
||||
}
|
||||
|
||||
void AdBlockManager::addDisabledRule(const QString &filter)
|
||||
{
|
||||
m_disabledRules.append(filter);
|
||||
}
|
||||
|
||||
void AdBlockManager::removeDisabledRule(const QString &filter)
|
||||
{
|
||||
m_disabledRules.removeOne(filter);
|
||||
}
|
||||
|
||||
AdBlockSubscription* AdBlockManager::addSubscription(const QString &title, const QString &url)
|
||||
{
|
||||
if (title.isEmpty() || url.isEmpty()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
QString fileName = filterCharsFromFilename(title.toLower()) + ".txt";
|
||||
QString filePath = ensureUniqueFilename(qApp->homeFolderPath() + "/adblock/" + fileName);
|
||||
|
||||
QByteArray data = QString("Title: %1\nUrl: %2\n[Adblock Plus 1.1.1]").arg(title, url).toLatin1();
|
||||
|
||||
QFile file(filePath);
|
||||
if (!file.open(QFile::WriteOnly | QFile::Truncate)) {
|
||||
qWarning() << "AdBlockManager: Cannot write to file" << filePath;
|
||||
return 0;
|
||||
}
|
||||
|
||||
file.write(data);
|
||||
file.close();
|
||||
|
||||
AdBlockSubscription* subscription = new AdBlockSubscription(title, this);
|
||||
subscription->setUrl(QUrl(url));
|
||||
subscription->setFilePath(filePath);
|
||||
subscription->loadSubscription(m_disabledRules);
|
||||
|
||||
m_subscriptions.insert(m_subscriptions.count() - 1, subscription);
|
||||
|
||||
return subscription;
|
||||
}
|
||||
|
||||
bool AdBlockManager::removeSubscription(AdBlockSubscription* subscription)
|
||||
{
|
||||
if (!m_subscriptions.contains(subscription) || !subscription->canBeRemoved()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
QFile(subscription->filePath()).remove();
|
||||
m_subscriptions.removeOne(subscription);
|
||||
|
||||
delete subscription;
|
||||
return true;
|
||||
}
|
||||
|
||||
AdBlockCustomList* AdBlockManager::customList() const
|
||||
{
|
||||
foreach (AdBlockSubscription* subscription, m_subscriptions) {
|
||||
AdBlockCustomList* list = qobject_cast<AdBlockCustomList*>(subscription);
|
||||
|
||||
if (list) {
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void AdBlockManager::load()
|
||||
{
|
||||
if (m_loaded) {
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef ADBLOCK_DEBUG
|
||||
QElapsedTimer timer;
|
||||
timer.start();
|
||||
#endif
|
||||
|
||||
Settings *settings = qApp->settings();
|
||||
m_enabled = settings->value("AdBlock","enabled", m_enabled).toBool();
|
||||
m_useLimitedEasyList = settings->value("AdBlock","useLimitedEasyList", m_useLimitedEasyList).toBool();
|
||||
m_disabledRules = settings->value("AdBlock","disabledRules", QStringList()).toStringList();
|
||||
QDateTime lastUpdate = settings->value("AdBlock","lastUpdate", QDateTime()).toDateTime();
|
||||
|
||||
if (!m_enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
QDir adblockDir(qApp->homeFolderPath() + "/adblock");
|
||||
// Create if neccessary
|
||||
if (!adblockDir.exists()) {
|
||||
QDir(qApp->homeFolderPath()).mkdir("adblock");
|
||||
}
|
||||
|
||||
foreach (const QString &fileName, adblockDir.entryList(QStringList("*.txt"), QDir::Files)) {
|
||||
if (fileName == QLatin1String("customlist.txt")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const QString absolutePath = adblockDir.absoluteFilePath(fileName);
|
||||
QFile file(absolutePath);
|
||||
if (!file.open(QFile::ReadOnly)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
QTextStream textStream(&file);
|
||||
textStream.setCodec("UTF-8");
|
||||
QString title = textStream.readLine(1024).remove(QLatin1String("Title: "));
|
||||
QUrl url = QUrl(textStream.readLine(1024).remove(QLatin1String("Url: ")));
|
||||
|
||||
if (title.isEmpty() || !url.isValid()) {
|
||||
qWarning() << "AdBlockManager: Invalid subscription file" << absolutePath;
|
||||
continue;
|
||||
}
|
||||
|
||||
AdBlockSubscription* subscription = new AdBlockSubscription(title, this);
|
||||
subscription->setUrl(url);
|
||||
subscription->setFilePath(absolutePath);
|
||||
|
||||
m_subscriptions.append(subscription);
|
||||
}
|
||||
|
||||
// Prepend EasyList if subscriptions are empty
|
||||
if (m_subscriptions.isEmpty()) {
|
||||
AdBlockSubscription* easyList = new AdBlockSubscription(tr("EasyList"), this);
|
||||
easyList->setUrl(QUrl(ADBLOCK_EASYLIST_URL));
|
||||
easyList->setFilePath(qApp->homeFolderPath() + "/adblock/easylist.txt");
|
||||
|
||||
// TODO
|
||||
//connect(easyList, SIGNAL(subscriptionUpdated()), mainApp, SLOT(reloadUserStyleBrowser()));
|
||||
|
||||
m_subscriptions.prepend(easyList);
|
||||
}
|
||||
|
||||
// Append CustomList
|
||||
AdBlockCustomList* customList = new AdBlockCustomList(this);
|
||||
m_subscriptions.append(customList);
|
||||
|
||||
// Load all subscriptions
|
||||
foreach (AdBlockSubscription* subscription, m_subscriptions) {
|
||||
subscription->loadSubscription(m_disabledRules);
|
||||
|
||||
// TODO
|
||||
//connect(subscription, SIGNAL(subscriptionUpdated()), mainApp, SLOT(reloadUserStyleBrowser()));
|
||||
connect(subscription, SIGNAL(subscriptionChanged()), m_matcher, SLOT(update()));
|
||||
}
|
||||
|
||||
if (lastUpdate.addDays(5) < QDateTime::currentDateTime()) {
|
||||
QTimer::singleShot(1000 * 60, this, SLOT(updateAllSubscriptions()));
|
||||
}
|
||||
|
||||
#ifdef ADBLOCK_DEBUG
|
||||
qDebug() << "AdBlock loaded in" << timer.elapsed();
|
||||
#endif
|
||||
|
||||
m_matcher->update();
|
||||
m_loaded = true;
|
||||
}
|
||||
|
||||
void AdBlockManager::updateAllSubscriptions()
|
||||
{
|
||||
foreach (AdBlockSubscription* subscription, m_subscriptions) {
|
||||
subscription->updateSubscription();
|
||||
}
|
||||
|
||||
Settings *settings = qApp->settings();
|
||||
settings->beginGroup("AdBlock");
|
||||
settings->setValue("lastUpdate", QDateTime::currentDateTime());
|
||||
settings->endGroup();
|
||||
}
|
||||
|
||||
void AdBlockManager::save()
|
||||
{
|
||||
if (!m_loaded) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (AdBlockSubscription* subscription, m_subscriptions) {
|
||||
subscription->saveSubscription();
|
||||
}
|
||||
|
||||
Settings *settings = qApp->settings();
|
||||
settings->beginGroup("AdBlock");
|
||||
settings->setValue("enabled", m_enabled);
|
||||
settings->setValue("useLimitedEasyList", m_useLimitedEasyList);
|
||||
settings->setValue("disabledRules", m_disabledRules);
|
||||
settings->endGroup();
|
||||
}
|
||||
|
||||
bool AdBlockManager::isEnabled() const
|
||||
{
|
||||
return m_enabled;
|
||||
}
|
||||
|
||||
bool AdBlockManager::canRunOnScheme(const QString &scheme) const
|
||||
{
|
||||
return !(scheme == QLatin1String("file") || scheme == QLatin1String("qrc")
|
||||
|| scheme == QLatin1String("qupzilla") || scheme == QLatin1String("data")
|
||||
|| scheme == QLatin1String("abp"));
|
||||
}
|
||||
|
||||
bool AdBlockManager::useLimitedEasyList() const
|
||||
{
|
||||
return m_useLimitedEasyList;
|
||||
}
|
||||
|
||||
void AdBlockManager::setUseLimitedEasyList(bool useLimited)
|
||||
{
|
||||
m_useLimitedEasyList = useLimited;
|
||||
|
||||
foreach (AdBlockSubscription* subscription, m_subscriptions) {
|
||||
if (subscription->url() == QUrl(ADBLOCK_EASYLIST_URL)) {
|
||||
subscription->updateSubscription();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool AdBlockManager::canBeBlocked(const QUrl &url) const
|
||||
{
|
||||
return !m_matcher->adBlockDisabledForUrl(url);
|
||||
}
|
||||
|
||||
QString AdBlockManager::elementHidingRules() const
|
||||
{
|
||||
return m_matcher->elementHidingRules();
|
||||
}
|
||||
|
||||
QString AdBlockManager::elementHidingRulesForDomain(const QUrl &url) const
|
||||
{
|
||||
if (!isEnabled() || !canRunOnScheme(url.scheme()) || !canBeBlocked(url))
|
||||
return QString();
|
||||
|
||||
// Acid3 doesn't like the way element hiding rules are embedded into page
|
||||
if (url.host() == QLatin1String("acid3.acidtests.org"))
|
||||
return QString();
|
||||
|
||||
return m_matcher->elementHidingRulesForDomain(url.host());
|
||||
}
|
||||
|
||||
AdBlockSubscription* AdBlockManager::subscriptionByName(const QString &name) const
|
||||
{
|
||||
foreach (AdBlockSubscription* subscription, m_subscriptions) {
|
||||
if (subscription->title() == name) {
|
||||
return subscription;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
AdBlockDialog* AdBlockManager::showDialog()
|
||||
{
|
||||
if (!m_adBlockDialog) {
|
||||
m_adBlockDialog = new AdBlockDialog;
|
||||
}
|
||||
|
||||
m_adBlockDialog.data()->show();
|
||||
m_adBlockDialog.data()->raise();
|
||||
m_adBlockDialog.data()->activateWindow();
|
||||
|
||||
return m_adBlockDialog.data();
|
||||
}
|
||||
|
||||
void AdBlockManager::showRule()
|
||||
{
|
||||
if (QAction* action = qobject_cast<QAction*>(sender())) {
|
||||
const AdBlockRule* rule = static_cast<const AdBlockRule*>(action->data().value<void*>());
|
||||
|
||||
if (rule) {
|
||||
showDialog()->showRule(rule);
|
||||
}
|
||||
}
|
||||
}
|
138
src/network-web/adblock/adblockmanager.h
Executable file
138
src/network-web/adblock/adblockmanager.h
Executable file
@ -0,0 +1,138 @@
|
||||
/* ============================================================
|
||||
* QuiteRSS is a open-source cross-platform RSS/Atom news feeds reader
|
||||
* Copyright (C) 2011-2015 QuiteRSS Team <quiterssteam@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/>.
|
||||
* ============================================================ */
|
||||
/* ============================================================
|
||||
* 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 ADBLOCKMANAGER_H
|
||||
#define ADBLOCKMANAGER_H
|
||||
|
||||
#define ADBLOCK_EASYLIST_URL "https://easylist-downloads.adblockplus.org/easylist.txt"
|
||||
|
||||
#ifndef QSL
|
||||
#if QT_VERSION >= 0x050000
|
||||
#define QSL(x) QStringLiteral(x)
|
||||
#else
|
||||
#define QSL(x) QLatin1String(x)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef QL1S
|
||||
#define QL1S(x) QLatin1String(x)
|
||||
#endif
|
||||
|
||||
#ifndef QL1C
|
||||
#define QL1C(x) QLatin1Char(x)
|
||||
#endif
|
||||
|
||||
|
||||
#include <QObject>
|
||||
#include <QStringList>
|
||||
#include <QPointer>
|
||||
|
||||
class QUrl;
|
||||
class QNetworkReply;
|
||||
class QNetworkRequest;
|
||||
|
||||
class AdBlockRule;
|
||||
class AdBlockDialog;
|
||||
class AdBlockMatcher;
|
||||
class AdBlockCustomList;
|
||||
class AdBlockSubscription;
|
||||
|
||||
class AdBlockManager : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
AdBlockManager(QObject* parent = 0);
|
||||
~AdBlockManager();
|
||||
|
||||
static AdBlockManager* instance();
|
||||
|
||||
static QString filterCharsFromFilename(const QString &name);
|
||||
|
||||
static QString ensureUniqueFilename(const QString &name, const QString &appendFormat = QString("(%1)"));
|
||||
|
||||
void load();
|
||||
void save();
|
||||
|
||||
bool isEnabled() const;
|
||||
bool canRunOnScheme(const QString &scheme) const;
|
||||
|
||||
bool useLimitedEasyList() const;
|
||||
void setUseLimitedEasyList(bool useLimited);
|
||||
|
||||
QString elementHidingRules() const;
|
||||
QString elementHidingRulesForDomain(const QUrl &url) const;
|
||||
|
||||
AdBlockSubscription* subscriptionByName(const QString &name) const;
|
||||
QList<AdBlockSubscription*> subscriptions() const;
|
||||
|
||||
QNetworkReply* block(const QNetworkRequest &request);
|
||||
|
||||
QStringList disabledRules() const;
|
||||
void addDisabledRule(const QString &filter);
|
||||
void removeDisabledRule(const QString &filter);
|
||||
|
||||
AdBlockSubscription* addSubscription(const QString &title, const QString &url);
|
||||
bool removeSubscription(AdBlockSubscription* subscription);
|
||||
|
||||
AdBlockCustomList* customList() const;
|
||||
|
||||
signals:
|
||||
void enabledChanged(bool enabled);
|
||||
|
||||
public slots:
|
||||
void setEnabled(bool enabled);
|
||||
void showRule();
|
||||
|
||||
void updateAllSubscriptions();
|
||||
|
||||
AdBlockDialog* showDialog();
|
||||
|
||||
private:
|
||||
inline bool canBeBlocked(const QUrl &url) const;
|
||||
|
||||
bool m_loaded;
|
||||
bool m_enabled;
|
||||
bool m_useLimitedEasyList;
|
||||
|
||||
QList<AdBlockSubscription*> m_subscriptions;
|
||||
static AdBlockManager* s_adBlockManager;
|
||||
AdBlockMatcher* m_matcher;
|
||||
QStringList m_disabledRules;
|
||||
|
||||
QPointer<AdBlockDialog> m_adBlockDialog;
|
||||
};
|
||||
|
||||
#endif // ADBLOCKMANAGER_H
|
||||
|
245
src/network-web/adblock/adblockmatcher.cpp
Executable file
245
src/network-web/adblock/adblockmatcher.cpp
Executable file
@ -0,0 +1,245 @@
|
||||
/* ============================================================
|
||||
* QuiteRSS is a open-source cross-platform RSS/Atom news feeds reader
|
||||
* Copyright (C) 2011-2015 QuiteRSS Team <quiterssteam@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/>.
|
||||
* ============================================================ */
|
||||
/* ============================================================
|
||||
* QupZilla - WebKit based browser
|
||||
* Copyright (C) 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 "adblockmatcher.h"
|
||||
#include "adblockmanager.h"
|
||||
#include "adblockrule.h"
|
||||
#include "adblocksubscription.h"
|
||||
|
||||
AdBlockMatcher::AdBlockMatcher(AdBlockManager* manager)
|
||||
: QObject(manager)
|
||||
, m_manager(manager)
|
||||
{
|
||||
connect(manager, SIGNAL(enabledChanged(bool)), this, SLOT(enabledChanged(bool)));
|
||||
}
|
||||
|
||||
AdBlockMatcher::~AdBlockMatcher()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
const AdBlockRule* AdBlockMatcher::match(const QNetworkRequest &request, const QString &urlDomain, const QString &urlString) const
|
||||
{
|
||||
// Exception rules
|
||||
if (m_networkExceptionTree.find(request, urlDomain, urlString))
|
||||
return 0;
|
||||
|
||||
int count = m_networkExceptionRules.count();
|
||||
for (int i = 0; i < count; ++i) {
|
||||
const AdBlockRule* rule = m_networkExceptionRules.at(i);
|
||||
if (rule->networkMatch(request, urlDomain, urlString))
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Block rules
|
||||
if (const AdBlockRule* rule = m_networkBlockTree.find(request, urlDomain, urlString))
|
||||
return rule;
|
||||
|
||||
count = m_networkBlockRules.count();
|
||||
for (int i = 0; i < count; ++i) {
|
||||
const AdBlockRule* rule = m_networkBlockRules.at(i);
|
||||
if (rule->networkMatch(request, urlDomain, urlString))
|
||||
return rule;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool AdBlockMatcher::adBlockDisabledForUrl(const QUrl &url) const
|
||||
{
|
||||
int count = m_documentRules.count();
|
||||
|
||||
for (int i = 0; i < count; ++i)
|
||||
if (m_documentRules.at(i)->urlMatch(url))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AdBlockMatcher::elemHideDisabledForUrl(const QUrl &url) const
|
||||
{
|
||||
if (adBlockDisabledForUrl(url))
|
||||
return true;
|
||||
|
||||
int count = m_elemhideRules.count();
|
||||
|
||||
for (int i = 0; i < count; ++i)
|
||||
if (m_elemhideRules.at(i)->urlMatch(url))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
QString AdBlockMatcher::elementHidingRules() const
|
||||
{
|
||||
return m_elementHidingRules;
|
||||
}
|
||||
|
||||
QString AdBlockMatcher::elementHidingRulesForDomain(const QString &domain) const
|
||||
{
|
||||
QString rules;
|
||||
int addedRulesCount = 0;
|
||||
int count = m_domainRestrictedCssRules.count();
|
||||
|
||||
for (int i = 0; i < count; ++i) {
|
||||
const AdBlockRule* rule = m_domainRestrictedCssRules.at(i);
|
||||
if (!rule->matchDomain(domain))
|
||||
continue;
|
||||
|
||||
if (Q_UNLIKELY(addedRulesCount == 1000)) {
|
||||
rules.append(rule->cssSelector());
|
||||
rules.append(QLatin1String("{display:none !important;}\n"));
|
||||
addedRulesCount = 0;
|
||||
}
|
||||
else {
|
||||
rules.append(rule->cssSelector() + QLatin1Char(','));
|
||||
addedRulesCount++;
|
||||
}
|
||||
}
|
||||
|
||||
if (addedRulesCount != 0) {
|
||||
rules = rules.left(rules.size() - 1);
|
||||
rules.append(QLatin1String("{display:none !important;}\n"));
|
||||
}
|
||||
|
||||
return rules;
|
||||
}
|
||||
|
||||
void AdBlockMatcher::update()
|
||||
{
|
||||
clear();
|
||||
|
||||
QHash<QString, const AdBlockRule*> cssRulesHash;
|
||||
QVector<const AdBlockRule*> exceptionCssRules;
|
||||
|
||||
foreach (AdBlockSubscription* subscription, m_manager->subscriptions()) {
|
||||
foreach (const AdBlockRule* rule, subscription->allRules()) {
|
||||
// Don't add internally disabled rules to cache
|
||||
if (rule->isInternalDisabled())
|
||||
continue;
|
||||
|
||||
if (rule->isCssRule()) {
|
||||
// We will add only enabled css rules to cache, because there is no enabled/disabled
|
||||
// check on match. They are directly embedded to pages.
|
||||
if (!rule->isEnabled())
|
||||
continue;
|
||||
|
||||
if (rule->isException())
|
||||
exceptionCssRules.append(rule);
|
||||
else
|
||||
cssRulesHash.insert(rule->cssSelector(), rule);
|
||||
}
|
||||
else if (rule->isDocument()) {
|
||||
m_documentRules.append(rule);
|
||||
}
|
||||
else if (rule->isElemhide()) {
|
||||
m_elemhideRules.append(rule);
|
||||
}
|
||||
else if (rule->isException()) {
|
||||
if (!m_networkExceptionTree.add(rule))
|
||||
m_networkExceptionRules.append(rule);
|
||||
}
|
||||
else {
|
||||
if (!m_networkBlockTree.add(rule))
|
||||
m_networkBlockRules.append(rule);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (const AdBlockRule* rule, exceptionCssRules) {
|
||||
const AdBlockRule* originalRule = cssRulesHash.value(rule->cssSelector());
|
||||
|
||||
// If we don't have this selector, the exception does nothing
|
||||
if (!originalRule)
|
||||
continue;
|
||||
|
||||
AdBlockRule* copiedRule = originalRule->copy();
|
||||
copiedRule->m_options |= AdBlockRule::DomainRestrictedOption;
|
||||
copiedRule->m_blockedDomains.append(rule->m_allowedDomains);
|
||||
|
||||
cssRulesHash[rule->cssSelector()] = copiedRule;
|
||||
m_createdRules.append(copiedRule);
|
||||
}
|
||||
|
||||
// Apparently, excessive amount of selectors for one CSS rule is not what WebKit likes.
|
||||
// (In my testings, 4931 is the number that makes it crash)
|
||||
// So let's split it by 1000 selectors...
|
||||
int hidingRulesCount = 0;
|
||||
|
||||
QHashIterator<QString, const AdBlockRule*> it(cssRulesHash);
|
||||
while (it.hasNext()) {
|
||||
it.next();
|
||||
const AdBlockRule* rule = it.value();
|
||||
|
||||
if (rule->isDomainRestricted()) {
|
||||
m_domainRestrictedCssRules.append(rule);
|
||||
}
|
||||
else if (Q_UNLIKELY(hidingRulesCount == 1000)) {
|
||||
m_elementHidingRules.append(rule->cssSelector());
|
||||
m_elementHidingRules.append(QLatin1String("{display:none !important;} "));
|
||||
hidingRulesCount = 0;
|
||||
}
|
||||
else {
|
||||
m_elementHidingRules.append(rule->cssSelector() + QLatin1Char(','));
|
||||
hidingRulesCount++;
|
||||
}
|
||||
}
|
||||
|
||||
if (hidingRulesCount != 0) {
|
||||
m_elementHidingRules = m_elementHidingRules.left(m_elementHidingRules.size() - 1);
|
||||
m_elementHidingRules.append(QLatin1String("{display:none !important;} "));
|
||||
}
|
||||
}
|
||||
|
||||
void AdBlockMatcher::clear()
|
||||
{
|
||||
m_networkExceptionTree.clear();
|
||||
m_networkExceptionRules.clear();
|
||||
m_networkBlockTree.clear();
|
||||
m_networkBlockRules.clear();
|
||||
m_domainRestrictedCssRules.clear();
|
||||
m_elementHidingRules.clear();
|
||||
m_documentRules.clear();
|
||||
m_elemhideRules.clear();
|
||||
qDeleteAll(m_createdRules);
|
||||
m_createdRules.clear();
|
||||
}
|
||||
|
||||
void AdBlockMatcher::enabledChanged(bool enabled)
|
||||
{
|
||||
if (enabled)
|
||||
update();
|
||||
else
|
||||
clear();
|
||||
}
|
85
src/network-web/adblock/adblockmatcher.h
Executable file
85
src/network-web/adblock/adblockmatcher.h
Executable file
@ -0,0 +1,85 @@
|
||||
/* ============================================================
|
||||
* QuiteRSS is a open-source cross-platform RSS/Atom news feeds reader
|
||||
* Copyright (C) 2011-2015 QuiteRSS Team <quiterssteam@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/>.
|
||||
* ============================================================ */
|
||||
/* ============================================================
|
||||
* QupZilla - WebKit based browser
|
||||
* Copyright (C) 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 ADBLOCKMATCHER_H
|
||||
#define ADBLOCKMATCHER_H
|
||||
|
||||
#include <QUrl>
|
||||
#include <QObject>
|
||||
#include <QVector>
|
||||
|
||||
#include "adblocksearchtree.h"
|
||||
|
||||
class AdBlockManager;
|
||||
class AdBlockRule;
|
||||
|
||||
class AdBlockMatcher : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit AdBlockMatcher(AdBlockManager* manager);
|
||||
~AdBlockMatcher();
|
||||
|
||||
const AdBlockRule* match(const QNetworkRequest &request, const QString &urlDomain, const QString &urlString) const;
|
||||
|
||||
bool adBlockDisabledForUrl(const QUrl &url) const;
|
||||
bool elemHideDisabledForUrl(const QUrl &url) const;
|
||||
|
||||
QString elementHidingRules() const;
|
||||
QString elementHidingRulesForDomain(const QString &domain) const;
|
||||
|
||||
public slots:
|
||||
void update();
|
||||
void clear();
|
||||
|
||||
private slots:
|
||||
void enabledChanged(bool enabled);
|
||||
|
||||
private:
|
||||
AdBlockManager* m_manager;
|
||||
|
||||
QVector<AdBlockRule*> m_createdRules;
|
||||
QVector<const AdBlockRule*> m_networkExceptionRules;
|
||||
QVector<const AdBlockRule*> m_networkBlockRules;
|
||||
QVector<const AdBlockRule*> m_domainRestrictedCssRules;
|
||||
QVector<const AdBlockRule*> m_documentRules;
|
||||
QVector<const AdBlockRule*> m_elemhideRules;
|
||||
|
||||
QString m_elementHidingRules;
|
||||
AdBlockSearchTree m_networkBlockTree;
|
||||
AdBlockSearchTree m_networkExceptionTree;
|
||||
};
|
||||
|
||||
#endif // ADBLOCKMATCHER_H
|
764
src/network-web/adblock/adblockrule.cpp
Executable file
764
src/network-web/adblock/adblockrule.cpp
Executable file
@ -0,0 +1,764 @@
|
||||
/* ============================================================
|
||||
* QuiteRSS is a open-source cross-platform RSS/Atom news feeds reader
|
||||
* Copyright (C) 2011-2015 QuiteRSS Team <quiterssteam@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/>.
|
||||
* ============================================================ */
|
||||
/* ============================================================
|
||||
* 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, Benjamin C. Meyer <ben@meyerhome.net>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Benjamin Meyer nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "adblockrule.h"
|
||||
#include "adblocksubscription.h"
|
||||
#include "adblockmanager.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QUrl>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
#include <QNetworkRequest>
|
||||
#include <QWebFrame>
|
||||
#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)
|
||||
: m_subscription(subscription)
|
||||
, m_type(StringContainsMatchRule)
|
||||
, m_caseSensitivity(Qt::CaseInsensitive)
|
||||
, m_isEnabled(true)
|
||||
, m_isException(false)
|
||||
, m_isInternalDisabled(false)
|
||||
, m_regExp(0)
|
||||
{
|
||||
setFilter(filter);
|
||||
}
|
||||
|
||||
AdBlockRule::~AdBlockRule()
|
||||
{
|
||||
delete m_regExp;
|
||||
}
|
||||
|
||||
AdBlockRule* AdBlockRule::copy() const
|
||||
{
|
||||
AdBlockRule* rule = new AdBlockRule();
|
||||
rule->m_subscription = m_subscription;
|
||||
rule->m_type = m_type;
|
||||
rule->m_options = m_options;
|
||||
rule->m_exceptions = m_exceptions;
|
||||
rule->m_filter = m_filter;
|
||||
rule->m_matchString = m_matchString;
|
||||
rule->m_caseSensitivity = m_caseSensitivity;
|
||||
rule->m_isEnabled = m_isEnabled;
|
||||
rule->m_isException = m_isException;
|
||||
rule->m_isInternalDisabled = m_isInternalDisabled;
|
||||
rule->m_allowedDomains = m_allowedDomains;
|
||||
rule->m_blockedDomains = m_blockedDomains;
|
||||
|
||||
if (m_regExp) {
|
||||
rule->m_regExp = new RegExp;
|
||||
rule->m_regExp->regExp = m_regExp->regExp;
|
||||
rule->m_regExp->matchers = m_regExp->matchers;
|
||||
}
|
||||
|
||||
return rule;
|
||||
}
|
||||
|
||||
AdBlockSubscription* AdBlockRule::subscription() const
|
||||
{
|
||||
return m_subscription;
|
||||
}
|
||||
|
||||
void AdBlockRule::setSubscription(AdBlockSubscription* subscription)
|
||||
{
|
||||
m_subscription = subscription;
|
||||
}
|
||||
|
||||
QString AdBlockRule::filter() const
|
||||
{
|
||||
return m_filter;
|
||||
}
|
||||
|
||||
void AdBlockRule::setFilter(const QString &filter)
|
||||
{
|
||||
m_filter = filter;
|
||||
parseFilter();
|
||||
}
|
||||
|
||||
bool AdBlockRule::isCssRule() const
|
||||
{
|
||||
return m_type == CssRule;
|
||||
}
|
||||
|
||||
QString AdBlockRule::cssSelector() const
|
||||
{
|
||||
return m_matchString;
|
||||
}
|
||||
|
||||
bool AdBlockRule::isDocument() const
|
||||
{
|
||||
return hasOption(DocumentOption);
|
||||
}
|
||||
|
||||
bool AdBlockRule::isElemhide() const
|
||||
{
|
||||
return hasOption(ElementHideOption);
|
||||
}
|
||||
|
||||
bool AdBlockRule::isDomainRestricted() const
|
||||
{
|
||||
return hasOption(DomainRestrictedOption);
|
||||
}
|
||||
|
||||
bool AdBlockRule::isException() const
|
||||
{
|
||||
return m_isException;
|
||||
}
|
||||
|
||||
bool AdBlockRule::isComment() const
|
||||
{
|
||||
return m_filter.startsWith(QL1C('!'));
|
||||
}
|
||||
|
||||
bool AdBlockRule::isEnabled() const
|
||||
{
|
||||
return m_isEnabled;
|
||||
}
|
||||
|
||||
void AdBlockRule::setEnabled(bool enabled)
|
||||
{
|
||||
m_isEnabled = enabled;
|
||||
}
|
||||
|
||||
bool AdBlockRule::isSlow() const
|
||||
{
|
||||
return m_regExp != 0;
|
||||
}
|
||||
|
||||
bool AdBlockRule::isInternalDisabled() const
|
||||
{
|
||||
return m_isInternalDisabled;
|
||||
}
|
||||
|
||||
bool AdBlockRule::urlMatch(const QUrl &url) const
|
||||
{
|
||||
if (!hasOption(DocumentOption) && !hasOption(ElementHideOption)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const QString encodedUrl = 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
|
||||
{
|
||||
if (m_type == CssRule || !m_isEnabled || m_isInternalDisabled) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool matched = false;
|
||||
|
||||
if (m_type == StringContainsMatchRule) {
|
||||
matched = encodedUrl.contains(m_matchString, m_caseSensitivity);
|
||||
}
|
||||
else if (m_type == DomainMatchRule) {
|
||||
matched = isMatchingDomain(domain, m_matchString);
|
||||
}
|
||||
else if (m_type == StringEndsMatchRule) {
|
||||
matched = encodedUrl.endsWith(m_matchString, m_caseSensitivity);
|
||||
}
|
||||
else if (m_type == RegExpMatchRule) {
|
||||
if (!isMatchingRegExpStrings(encodedUrl)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
matched = (m_regExp->regExp.indexIn(encodedUrl) != -1);
|
||||
}
|
||||
|
||||
if (matched) {
|
||||
// Check domain restrictions
|
||||
if (hasOption(DomainRestrictedOption) && !matchDomain(domain)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check third-party restriction
|
||||
if (hasOption(ThirdPartyOption) && !matchThirdParty(request)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check object restrictions
|
||||
if (hasOption(ObjectOption) && !matchObject(request)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check subdocument restriction
|
||||
if (hasOption(SubdocumentOption) && !matchSubdocument(request)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check xmlhttprequest restriction
|
||||
if (hasOption(XMLHttpRequestOption) && !matchXmlHttpRequest(request)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check image restriction
|
||||
if (hasOption(ImageOption) && !matchImage(encodedUrl)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return matched;
|
||||
}
|
||||
|
||||
bool AdBlockRule::matchDomain(const QString &domain) const
|
||||
{
|
||||
if (!m_isEnabled) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!hasOption(DomainRestrictedOption)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (m_blockedDomains.isEmpty()) {
|
||||
foreach (const QString &d, m_allowedDomains) {
|
||||
if (isMatchingDomain(domain, d)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (m_allowedDomains.isEmpty()) {
|
||||
foreach (const QString &d, m_blockedDomains) {
|
||||
if (isMatchingDomain(domain, d)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
foreach (const QString &d, m_blockedDomains) {
|
||||
if (isMatchingDomain(domain, d)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (const QString &d, m_allowedDomains) {
|
||||
if (isMatchingDomain(domain, d)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AdBlockRule::matchThirdParty(const QNetworkRequest &request) const
|
||||
{
|
||||
const QString referer = request.attribute(QNetworkRequest::Attribute(QNetworkRequest::User + 151), QString()).toString();
|
||||
|
||||
if (referer.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Third-party matching should be performed on second-level domains
|
||||
const QString refererHost = toSecondLevelDomain(QUrl(referer));
|
||||
const QString host = toSecondLevelDomain(request.url());
|
||||
|
||||
bool match = refererHost != host;
|
||||
|
||||
return hasException(ThirdPartyOption) ? !match : match;
|
||||
}
|
||||
|
||||
bool AdBlockRule::matchObject(const QNetworkRequest &request) const
|
||||
{
|
||||
bool match = request.attribute(QNetworkRequest::Attribute(QNetworkRequest::User + 150)).toString() == QL1S("object");
|
||||
|
||||
return hasException(ObjectOption) ? !match : match;
|
||||
}
|
||||
|
||||
bool AdBlockRule::matchSubdocument(const QNetworkRequest &request) const
|
||||
{
|
||||
QWebFrame* originatingFrame = static_cast<QWebFrame*>(request.originatingObject());
|
||||
if (!originatingFrame) {
|
||||
return false;
|
||||
}
|
||||
|
||||
QWebPage* page = originatingFrame->page();
|
||||
if (!page) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool match = !(originatingFrame == page->mainFrame());
|
||||
|
||||
return hasException(SubdocumentOption) ? !match : match;
|
||||
}
|
||||
|
||||
bool AdBlockRule::matchXmlHttpRequest(const QNetworkRequest &request) const
|
||||
{
|
||||
bool match = request.rawHeader("X-Requested-With") == QByteArray("XMLHttpRequest");
|
||||
|
||||
return hasException(XMLHttpRequestOption) ? !match : match;
|
||||
}
|
||||
|
||||
bool AdBlockRule::matchImage(const QString &encodedUrl) const
|
||||
{
|
||||
bool match = encodedUrl.endsWith(QL1S(".png")) ||
|
||||
encodedUrl.endsWith(QL1S(".jpg")) ||
|
||||
encodedUrl.endsWith(QL1S(".gif")) ||
|
||||
encodedUrl.endsWith(QL1S(".jpeg"));
|
||||
|
||||
return hasException(ImageOption) ? !match : match;
|
||||
}
|
||||
|
||||
void AdBlockRule::parseFilter()
|
||||
{
|
||||
QString parsedLine = m_filter;
|
||||
|
||||
// Empty rule or just comment
|
||||
if (m_filter.trimmed().isEmpty() || m_filter.startsWith(QL1C('!'))) {
|
||||
// We want to differentiate rule disabled by user and rule disabled in subscription file
|
||||
// m_isInternalDisabled is also used when rule is disabled due to all options not being supported
|
||||
m_isEnabled = false;
|
||||
m_isInternalDisabled = true;
|
||||
m_type = Invalid;
|
||||
return;
|
||||
}
|
||||
|
||||
// CSS Element hiding rule
|
||||
if (parsedLine.contains(QL1S("##")) || parsedLine.contains(QL1S("#@#"))) {
|
||||
m_type = CssRule;
|
||||
int pos = parsedLine.indexOf(QL1C('#'));
|
||||
|
||||
// Domain restricted rule
|
||||
if (!parsedLine.startsWith(QL1S("##"))) {
|
||||
QString domains = parsedLine.left(pos);
|
||||
parseDomains(domains, QL1C(','));
|
||||
}
|
||||
|
||||
m_isException = parsedLine.at(pos + 1) == QL1C('@');
|
||||
m_matchString = parsedLine.mid(m_isException ? pos + 3 : pos + 2);
|
||||
|
||||
// CSS rule cannot have more options -> stop parsing
|
||||
return;
|
||||
}
|
||||
|
||||
// Exception always starts with @@
|
||||
if (parsedLine.startsWith(QL1S("@@"))) {
|
||||
m_isException = true;
|
||||
parsedLine = parsedLine.mid(2);
|
||||
}
|
||||
|
||||
// Parse all options following $ char
|
||||
int optionsIndex = parsedLine.indexOf(QL1C('$'));
|
||||
if (optionsIndex >= 0) {
|
||||
const QStringList options = parsedLine.mid(optionsIndex + 1).split(QL1C(','), QString::SkipEmptyParts);
|
||||
|
||||
int handledOptions = 0;
|
||||
foreach (const QString &option, options) {
|
||||
if (option.startsWith(QL1S("domain="))) {
|
||||
parseDomains(option.mid(7), QL1C('|'));
|
||||
++handledOptions;
|
||||
}
|
||||
else if (option == QL1S("match-case")) {
|
||||
m_caseSensitivity = Qt::CaseSensitive;
|
||||
++handledOptions;
|
||||
}
|
||||
else if (option.endsWith(QL1S("third-party"))) {
|
||||
setOption(ThirdPartyOption);
|
||||
setException(ThirdPartyOption, option.startsWith(QL1C('~')));
|
||||
++handledOptions;
|
||||
}
|
||||
else if (option.endsWith(QL1S("object"))) {
|
||||
setOption(ObjectOption);
|
||||
setException(ObjectOption, option.startsWith(QL1C('~')));
|
||||
++handledOptions;
|
||||
}
|
||||
else if (option.endsWith(QL1S("subdocument"))) {
|
||||
setOption(SubdocumentOption);
|
||||
setException(SubdocumentOption, option.startsWith(QL1C('~')));
|
||||
++handledOptions;
|
||||
}
|
||||
else if (option.endsWith(QL1S("xmlhttprequest"))) {
|
||||
setOption(XMLHttpRequestOption);
|
||||
setException(XMLHttpRequestOption, option.startsWith(QL1C('~')));
|
||||
++handledOptions;
|
||||
}
|
||||
else if (option.endsWith(QL1S("image"))) {
|
||||
setOption(ImageOption);
|
||||
setException(ImageOption, option.startsWith(QL1C('~')));
|
||||
++handledOptions;
|
||||
}
|
||||
else if (option == QL1S("document") && m_isException) {
|
||||
setOption(DocumentOption);
|
||||
++handledOptions;
|
||||
}
|
||||
else if (option == QL1S("elemhide") && m_isException) {
|
||||
setOption(ElementHideOption);
|
||||
++handledOptions;
|
||||
}
|
||||
else if (option == QL1S("collapse")) {
|
||||
// Hiding placeholders of blocked elements is enabled by default
|
||||
++handledOptions;
|
||||
}
|
||||
}
|
||||
|
||||
// If we don't handle all options, it's safer to just disable this rule
|
||||
if (handledOptions != options.count()) {
|
||||
m_isInternalDisabled = true;
|
||||
m_type = Invalid;
|
||||
return;
|
||||
}
|
||||
|
||||
parsedLine = parsedLine.left(optionsIndex);
|
||||
}
|
||||
|
||||
// Rule is classic regexp
|
||||
if (parsedLine.startsWith(QL1C('/')) && parsedLine.endsWith(QL1C('/'))) {
|
||||
parsedLine = parsedLine.mid(1);
|
||||
parsedLine = parsedLine.left(parsedLine.size() - 1);
|
||||
|
||||
m_type = RegExpMatchRule;
|
||||
m_regExp = new RegExp;
|
||||
m_regExp->regExp = QRegExp(parsedLine, m_caseSensitivity);
|
||||
m_regExp->matchers = createStringMatchers(parseRegExpFilter(parsedLine));
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove starting and ending wildcards (*)
|
||||
if (parsedLine.startsWith(QL1C('*'))) {
|
||||
parsedLine = parsedLine.mid(1);
|
||||
}
|
||||
|
||||
if (parsedLine.endsWith(QL1C('*'))) {
|
||||
parsedLine = parsedLine.left(parsedLine.size() - 1);
|
||||
}
|
||||
|
||||
// We can use fast string matching for domain here
|
||||
if (filterIsOnlyDomain(parsedLine)) {
|
||||
parsedLine = parsedLine.mid(2);
|
||||
parsedLine = parsedLine.left(parsedLine.size() - 1);
|
||||
|
||||
m_type = DomainMatchRule;
|
||||
m_matchString = parsedLine;
|
||||
return;
|
||||
}
|
||||
|
||||
// If rule contains only | at end, we can also use string matching
|
||||
if (filterIsOnlyEndsMatch(parsedLine)) {
|
||||
parsedLine = parsedLine.left(parsedLine.size() - 1);
|
||||
|
||||
m_type = StringEndsMatchRule;
|
||||
m_matchString = parsedLine;
|
||||
return;
|
||||
}
|
||||
|
||||
// If we still find a wildcard (*) or separator (^) or (|)
|
||||
// we must modify parsedLine to comply with QzRegExp
|
||||
if (parsedLine.contains(QL1C('*')) ||
|
||||
parsedLine.contains(QL1C('^')) ||
|
||||
parsedLine.contains(QL1C('|'))
|
||||
) {
|
||||
m_type = RegExpMatchRule;
|
||||
m_regExp = new RegExp;
|
||||
m_regExp->regExp = QRegExp(createRegExpFromFilter(parsedLine), m_caseSensitivity);
|
||||
m_regExp->matchers = createStringMatchers(parseRegExpFilter(parsedLine));
|
||||
return;
|
||||
}
|
||||
|
||||
// We haven't found anything that needs use of regexp, yay!
|
||||
m_type = StringContainsMatchRule;
|
||||
m_matchString = parsedLine;
|
||||
}
|
||||
|
||||
void AdBlockRule::parseDomains(const QString &domains, const QChar &separator)
|
||||
{
|
||||
QStringList domainsList = domains.split(separator, QString::SkipEmptyParts);
|
||||
|
||||
foreach (const QString domain, domainsList) {
|
||||
if (domain.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
if (domain.startsWith(QL1C('~'))) {
|
||||
m_blockedDomains.append(domain.mid(1));
|
||||
}
|
||||
else {
|
||||
m_allowedDomains.append(domain);
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_blockedDomains.isEmpty() || !m_allowedDomains.isEmpty()) {
|
||||
setOption(DomainRestrictedOption);
|
||||
}
|
||||
}
|
||||
|
||||
bool AdBlockRule::filterIsOnlyDomain(const QString &filter) const
|
||||
{
|
||||
if (!filter.endsWith(QL1C('^')) || !filter.startsWith(QL1S("||")))
|
||||
return false;
|
||||
|
||||
for (int i = 0; i < filter.size(); ++i) {
|
||||
switch (filter.at(i).toLatin1()) {
|
||||
case '/':
|
||||
case ':':
|
||||
case '?':
|
||||
case '=':
|
||||
case '&':
|
||||
case '*':
|
||||
return false;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AdBlockRule::filterIsOnlyEndsMatch(const QString &filter) const
|
||||
{
|
||||
for (int i = 0; i < filter.size(); ++i) {
|
||||
switch (filter.at(i).toLatin1()) {
|
||||
case '^':
|
||||
case '*':
|
||||
return false;
|
||||
case '|':
|
||||
return i == filter.size() - 1;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool wordCharacter(const QChar &c)
|
||||
{
|
||||
return c.isLetterOrNumber() || c.isMark() || c == QL1C('_');
|
||||
}
|
||||
|
||||
QString AdBlockRule::createRegExpFromFilter(const QString &filter) const
|
||||
{
|
||||
QString parsed;
|
||||
parsed.reserve(filter.size());
|
||||
|
||||
bool hadWildcard = false; // Filter multiple wildcards
|
||||
|
||||
for (int i = 0; i < filter.size(); ++i) {
|
||||
const QChar c = filter.at(i);
|
||||
switch (c.toLatin1()) {
|
||||
case '^':
|
||||
parsed.append(QL1S("(?:[^\\w\\d\\-.%]|$)"));
|
||||
break;
|
||||
|
||||
case '*':
|
||||
if (!hadWildcard)
|
||||
parsed.append(QL1S(".*"));
|
||||
break;
|
||||
|
||||
case '|':
|
||||
if (i == 0) {
|
||||
if (filter.size() > 1 && filter.at(1) == QL1C('|')) {
|
||||
parsed.append(QL1S("^[\\w\\-]+:\\/+(?!\\/)(?:[^\\/]+\\.)?"));
|
||||
i++;
|
||||
}
|
||||
else {
|
||||
parsed.append('^');
|
||||
}
|
||||
break;
|
||||
}
|
||||
else if (i == filter.size() - 1) {
|
||||
parsed.append(QL1C('$'));
|
||||
break;
|
||||
}
|
||||
// fallthrough
|
||||
|
||||
default:
|
||||
if (!wordCharacter(c))
|
||||
parsed.append(QL1C('\\') + c);
|
||||
else
|
||||
parsed.append(c);
|
||||
}
|
||||
|
||||
hadWildcard = c == QL1C('*');
|
||||
}
|
||||
|
||||
return parsed;
|
||||
}
|
||||
|
||||
QList<QStringMatcher> AdBlockRule::createStringMatchers(const QStringList &filters) const
|
||||
{
|
||||
QList<QStringMatcher> matchers;
|
||||
matchers.reserve(filters.size());
|
||||
|
||||
foreach (const QString &filter, filters) {
|
||||
matchers.append(QStringMatcher(filter, m_caseSensitivity));
|
||||
}
|
||||
|
||||
return matchers;
|
||||
}
|
||||
|
||||
bool AdBlockRule::isMatchingDomain(const QString &domain, const QString &pattern) const
|
||||
{
|
||||
if (pattern == domain) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!domain.endsWith(pattern)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int index = domain.indexOf(pattern);
|
||||
|
||||
return index > 0 && domain[index - 1] == QLatin1Char('.');
|
||||
}
|
||||
|
||||
bool AdBlockRule::isMatchingRegExpStrings(const QString &url) const
|
||||
{
|
||||
Q_ASSERT(m_regExp);
|
||||
|
||||
foreach (const QStringMatcher &matcher, m_regExp->matchers) {
|
||||
if (matcher.indexIn(url) == -1)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Split regexp filter into strings that can be used with QString::contains
|
||||
// Don't use parts that contains only 1 char and duplicated parts
|
||||
QStringList AdBlockRule::parseRegExpFilter(const QString &filter) const
|
||||
{
|
||||
QStringList list;
|
||||
int startPos = -1;
|
||||
|
||||
for (int i = 0; i < filter.size(); ++i) {
|
||||
const QChar c = filter.at(i);
|
||||
// Meta characters in AdBlock rules are | * ^
|
||||
if (c == QL1C('|') || c == QL1C('*') || c == QL1C('^')) {
|
||||
const QString sub = filter.mid(startPos, i - startPos);
|
||||
if (sub.size() > 1)
|
||||
list.append(sub);
|
||||
startPos = i + 1;
|
||||
}
|
||||
}
|
||||
|
||||
const QString sub = filter.mid(startPos);
|
||||
if (sub.size() > 1)
|
||||
list.append(sub);
|
||||
|
||||
list.removeDuplicates();
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
bool AdBlockRule::hasOption(const AdBlockRule::RuleOption &opt) const
|
||||
{
|
||||
return (m_options & opt);
|
||||
}
|
||||
|
||||
bool AdBlockRule::hasException(const AdBlockRule::RuleOption &opt) const
|
||||
{
|
||||
return (m_exceptions & opt);
|
||||
}
|
||||
|
||||
void AdBlockRule::setOption(const AdBlockRule::RuleOption &opt)
|
||||
{
|
||||
m_options |= opt;
|
||||
}
|
||||
|
||||
void AdBlockRule::setException(const AdBlockRule::RuleOption &opt, bool on)
|
||||
{
|
||||
if (on) {
|
||||
m_exceptions |= opt;
|
||||
}
|
||||
}
|
191
src/network-web/adblock/adblockrule.h
Executable file
191
src/network-web/adblock/adblockrule.h
Executable file
@ -0,0 +1,191 @@
|
||||
/* ============================================================
|
||||
* QuiteRSS is a open-source cross-platform RSS/Atom news feeds reader
|
||||
* Copyright (C) 2011-2015 QuiteRSS Team <quiterssteam@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/>.
|
||||
* ============================================================ */
|
||||
/* ============================================================
|
||||
* 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>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Benjamin Meyer nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef ADBLOCKRULE_H
|
||||
#define ADBLOCKRULE_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QStringList>
|
||||
|
||||
class QNetworkRequest;
|
||||
class QUrl;
|
||||
|
||||
class AdBlockSubscription;
|
||||
|
||||
class AdBlockRule
|
||||
{
|
||||
public:
|
||||
AdBlockRule(const QString &filter = QString(), AdBlockSubscription* subscription = 0);
|
||||
~AdBlockRule();
|
||||
|
||||
AdBlockRule* copy() const;
|
||||
|
||||
AdBlockSubscription* subscription() const;
|
||||
void setSubscription(AdBlockSubscription* subscription);
|
||||
|
||||
QString filter() const;
|
||||
void setFilter(const QString &filter);
|
||||
|
||||
bool isCssRule() const;
|
||||
QString cssSelector() const;
|
||||
|
||||
bool isDocument() const;
|
||||
bool isElemhide() const;
|
||||
|
||||
bool isDomainRestricted() const;
|
||||
bool isException() const;
|
||||
|
||||
bool isComment() const;
|
||||
bool isEnabled() const;
|
||||
void setEnabled(bool enabled);
|
||||
|
||||
bool isSlow() const;
|
||||
bool isInternalDisabled() const;
|
||||
|
||||
bool urlMatch(const QUrl &url) const;
|
||||
bool networkMatch(const QNetworkRequest &request, const QString &domain, const QString &encodedUrl) const;
|
||||
|
||||
bool matchDomain(const QString &domain) const;
|
||||
bool matchThirdParty(const QNetworkRequest &request) 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 isMatchingDomain(const QString &domain, const QString &pattern) const;
|
||||
bool isMatchingRegExpStrings(const QString &url) const;
|
||||
QStringList parseRegExpFilter(const QString &filter) const;
|
||||
|
||||
private:
|
||||
enum RuleType {
|
||||
CssRule = 0,
|
||||
DomainMatchRule = 1,
|
||||
RegExpMatchRule = 2,
|
||||
StringEndsMatchRule = 3,
|
||||
StringContainsMatchRule = 4,
|
||||
Invalid = 5
|
||||
};
|
||||
|
||||
enum RuleOption {
|
||||
DomainRestrictedOption = 1,
|
||||
ThirdPartyOption = 2,
|
||||
ObjectOption = 4,
|
||||
SubdocumentOption = 8,
|
||||
XMLHttpRequestOption = 16,
|
||||
ImageOption = 32,
|
||||
|
||||
// Exception only options
|
||||
DocumentOption = 64,
|
||||
ElementHideOption = 128
|
||||
};
|
||||
|
||||
Q_DECLARE_FLAGS(RuleOptions, RuleOption)
|
||||
|
||||
inline bool hasOption(const RuleOption &opt) const;
|
||||
inline bool hasException(const RuleOption &opt) const;
|
||||
|
||||
inline void setOption(const RuleOption &opt);
|
||||
inline void setException(const RuleOption &opt, bool on);
|
||||
|
||||
void parseFilter();
|
||||
void parseDomains(const QString &domains, 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;
|
||||
|
||||
AdBlockSubscription* m_subscription;
|
||||
|
||||
RuleType m_type;
|
||||
RuleOptions m_options;
|
||||
RuleOptions m_exceptions;
|
||||
|
||||
// Original rule filter
|
||||
QString m_filter;
|
||||
// Parsed rule for string matching (CSS Selector for CSS rules)
|
||||
QString m_matchString;
|
||||
// Case sensitivity for string matching
|
||||
Qt::CaseSensitivity m_caseSensitivity;
|
||||
|
||||
bool m_isEnabled;
|
||||
bool m_isException;
|
||||
bool m_isInternalDisabled;
|
||||
|
||||
QStringList m_allowedDomains;
|
||||
QStringList m_blockedDomains;
|
||||
|
||||
struct RegExp {
|
||||
QRegExp regExp;
|
||||
QList<QStringMatcher> matchers;
|
||||
};
|
||||
|
||||
// Use dynamic allocation to save memory
|
||||
RegExp* m_regExp;
|
||||
|
||||
friend class AdBlockMatcher;
|
||||
friend class AdBlockSearchTree;
|
||||
friend class AdBlockSubscription;
|
||||
};
|
||||
|
||||
#endif // ADBLOCKRULE_H
|
||||
|
157
src/network-web/adblock/adblocksearchtree.cpp
Executable file
157
src/network-web/adblock/adblocksearchtree.cpp
Executable file
@ -0,0 +1,157 @@
|
||||
/* ============================================================
|
||||
* QuiteRSS is a open-source cross-platform RSS/Atom news feeds reader
|
||||
* Copyright (C) 2011-2015 QuiteRSS Team <quiterssteam@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/>.
|
||||
* ============================================================ */
|
||||
/* ============================================================
|
||||
* 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>
|
||||
|
||||
AdBlockSearchTree::AdBlockSearchTree()
|
||||
: m_root(new Node)
|
||||
{
|
||||
}
|
||||
|
||||
AdBlockSearchTree::~AdBlockSearchTree()
|
||||
{
|
||||
deleteNode(m_root);
|
||||
}
|
||||
|
||||
void AdBlockSearchTree::clear()
|
||||
{
|
||||
deleteNode(m_root);
|
||||
m_root = new Node;
|
||||
}
|
||||
|
||||
bool AdBlockSearchTree::add(const AdBlockRule* rule)
|
||||
{
|
||||
if (rule->m_type != AdBlockRule::StringContainsMatchRule) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const QString filter = rule->m_matchString;
|
||||
int len = filter.size();
|
||||
|
||||
if (len <= 0) {
|
||||
qDebug() << "AdBlockSearchTree: Inserting rule with filter len <= 0!";
|
||||
return false;
|
||||
}
|
||||
|
||||
Node* node = m_root;
|
||||
|
||||
for (int i = 0; i < len; ++i) {
|
||||
const QChar c = filter.at(i);
|
||||
if (!node->children.contains(c)) {
|
||||
Node* n = new Node;
|
||||
n->c = c;
|
||||
|
||||
node->children[c] = n;
|
||||
}
|
||||
|
||||
node = node->children[c];
|
||||
}
|
||||
|
||||
node->rule = rule;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const AdBlockRule* AdBlockSearchTree::find(const QNetworkRequest &request, const QString &domain, const QString &urlString) const
|
||||
{
|
||||
int len = urlString.size();
|
||||
|
||||
if (len <= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const QChar* string = urlString.constData();
|
||||
|
||||
for (int i = 0; i < len; ++i) {
|
||||
const AdBlockRule* rule = prefixSearch(request, domain, urlString, string++, len - i);
|
||||
if (rule) {
|
||||
return rule;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const AdBlockRule* AdBlockSearchTree::prefixSearch(const QNetworkRequest &request, const QString &domain, const QString &urlString, const QChar* string, int len) const
|
||||
{
|
||||
if (len <= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
QChar c = string[0];
|
||||
|
||||
if (!m_root->children.contains(c)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
Node* node = m_root->children[c];
|
||||
|
||||
for (int i = 1; i < len; ++i) {
|
||||
const QChar c = (++string)[0];
|
||||
|
||||
if (node->rule && node->rule->networkMatch(request, domain, urlString)) {
|
||||
return node->rule;
|
||||
}
|
||||
|
||||
if (!node->children.contains(c)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
node = node->children[c];
|
||||
}
|
||||
|
||||
if (node->rule && node->rule->networkMatch(request, domain, urlString)) {
|
||||
return node->rule;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void AdBlockSearchTree::deleteNode(AdBlockSearchTree::Node* node)
|
||||
{
|
||||
if (!node) {
|
||||
return;
|
||||
}
|
||||
|
||||
QHashIterator<QChar, Node*> i(node->children);
|
||||
while (i.hasNext()) {
|
||||
i.next();
|
||||
deleteNode(i.value());
|
||||
}
|
||||
|
||||
delete node;
|
||||
}
|
73
src/network-web/adblock/adblocksearchtree.h
Executable file
73
src/network-web/adblock/adblocksearchtree.h
Executable file
@ -0,0 +1,73 @@
|
||||
/* ============================================================
|
||||
* QuiteRSS is a open-source cross-platform RSS/Atom news feeds reader
|
||||
* Copyright (C) 2011-2015 QuiteRSS Team <quiterssteam@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/>.
|
||||
* ============================================================ */
|
||||
/* ============================================================
|
||||
* 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
|
||||
#define ADBLOCKSEARCHTREE_H
|
||||
|
||||
#include <QChar>
|
||||
#include <QHash>
|
||||
|
||||
class QNetworkRequest;
|
||||
|
||||
class AdBlockRule;
|
||||
|
||||
class AdBlockSearchTree
|
||||
{
|
||||
public:
|
||||
explicit AdBlockSearchTree();
|
||||
~AdBlockSearchTree();
|
||||
|
||||
void clear();
|
||||
|
||||
bool add(const AdBlockRule* rule);
|
||||
const AdBlockRule* find(const QNetworkRequest &request, const QString &domain, const QString &urlString) const;
|
||||
|
||||
private:
|
||||
struct Node {
|
||||
QChar c;
|
||||
const AdBlockRule* rule;
|
||||
QHash<QChar, Node*> children;
|
||||
|
||||
Node() : c(0) , rule(0) { }
|
||||
};
|
||||
|
||||
const AdBlockRule* prefixSearch(const QNetworkRequest &request, const QString &domain,
|
||||
const QString &urlString, const QChar* string, int len) const;
|
||||
|
||||
void deleteNode(Node* node);
|
||||
|
||||
Node* m_root;
|
||||
};
|
||||
|
||||
#endif // ADBLOCKSEARCHTREE_H
|
488
src/network-web/adblock/adblocksubscription.cpp
Executable file
488
src/network-web/adblock/adblocksubscription.cpp
Executable file
@ -0,0 +1,488 @@
|
||||
/* ============================================================
|
||||
* QuiteRSS is a open-source cross-platform RSS/Atom news feeds reader
|
||||
* Copyright (C) 2011-2015 QuiteRSS Team <quiterssteam@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/>.
|
||||
* ============================================================ */
|
||||
/* ============================================================
|
||||
* 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>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Benjamin Meyer nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
#include "adblocksubscription.h"
|
||||
#include "adblockmanager.h"
|
||||
#include "adblocksearchtree.h"
|
||||
#include "followredirectreply.h"
|
||||
|
||||
#include "network-web/silentnetworkaccessmanager.h"
|
||||
#include "miscellaneous/iofactory.h"
|
||||
#include "miscellaneous/application.h"
|
||||
|
||||
#include <QFile>
|
||||
#include <QTimer>
|
||||
#include <QNetworkReply>
|
||||
#include <QDebug>
|
||||
#include <QWebPage>
|
||||
|
||||
#include <exceptions/applicationexception.h>
|
||||
|
||||
AdBlockSubscription::AdBlockSubscription(const QString &title, QObject* parent)
|
||||
: QObject(parent)
|
||||
, m_reply(0)
|
||||
, m_title(title)
|
||||
, m_updated(false)
|
||||
{
|
||||
}
|
||||
|
||||
QString AdBlockSubscription::title() const
|
||||
{
|
||||
return m_title;
|
||||
}
|
||||
|
||||
void AdBlockSubscription::setTitle(const QString &title)
|
||||
{
|
||||
m_title = title;
|
||||
}
|
||||
|
||||
QString AdBlockSubscription::filePath() const
|
||||
{
|
||||
return m_filePath;
|
||||
}
|
||||
|
||||
void AdBlockSubscription::setFilePath(const QString &path)
|
||||
{
|
||||
m_filePath = path;
|
||||
}
|
||||
|
||||
QUrl AdBlockSubscription::url() const
|
||||
{
|
||||
return m_url;
|
||||
}
|
||||
|
||||
void AdBlockSubscription::setUrl(const QUrl &url)
|
||||
{
|
||||
m_url = url;
|
||||
}
|
||||
|
||||
void AdBlockSubscription::loadSubscription(const QStringList &disabledRules)
|
||||
{
|
||||
QFile file(m_filePath);
|
||||
|
||||
if (!file.exists()) {
|
||||
QTimer::singleShot(0, this, SLOT(updateSubscription()));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!file.open(QFile::ReadOnly)) {
|
||||
qWarning() << "AdBlockSubscription::" << __FUNCTION__ << "Unable to open adblock file for reading" << m_filePath;
|
||||
QTimer::singleShot(0, this, SLOT(updateSubscription()));
|
||||
return;
|
||||
}
|
||||
|
||||
QTextStream textStream(&file);
|
||||
textStream.setCodec("UTF-8");
|
||||
// Header is on 3rd line
|
||||
textStream.readLine(1024);
|
||||
textStream.readLine(1024);
|
||||
QString header = textStream.readLine(1024);
|
||||
|
||||
if (!header.startsWith(QLatin1String("[Adblock")) || m_title.isEmpty()) {
|
||||
qWarning() << "AdBlockSubscription::" << __FUNCTION__ << "invalid format of adblock file" << m_filePath;
|
||||
QTimer::singleShot(0, this, SLOT(updateSubscription()));
|
||||
return;
|
||||
}
|
||||
|
||||
m_rules.clear();
|
||||
|
||||
while (!textStream.atEnd()) {
|
||||
AdBlockRule* rule = new AdBlockRule(textStream.readLine(), this);
|
||||
|
||||
if (disabledRules.contains(rule->filter())) {
|
||||
rule->setEnabled(false);
|
||||
}
|
||||
|
||||
m_rules.append(rule);
|
||||
}
|
||||
|
||||
// Initial update
|
||||
if (m_rules.isEmpty() && !m_updated) {
|
||||
QTimer::singleShot(0, this, SLOT(updateSubscription()));
|
||||
}
|
||||
}
|
||||
|
||||
void AdBlockSubscription::saveSubscription()
|
||||
{
|
||||
}
|
||||
|
||||
void AdBlockSubscription::updateSubscription()
|
||||
{
|
||||
if (m_reply || !m_url.isValid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_reply = new FollowRedirectReply(m_url, SilentNetworkAccessManager::instance());
|
||||
|
||||
connect(m_reply, SIGNAL(finished()), this, SLOT(subscriptionDownloaded()));
|
||||
}
|
||||
|
||||
void AdBlockSubscription::subscriptionDownloaded()
|
||||
{
|
||||
if (m_reply != qobject_cast<FollowRedirectReply*>(sender())) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool error = false;
|
||||
const QByteArray response = QString::fromUtf8(m_reply->readAll()).toUtf8();
|
||||
|
||||
if (m_reply->error() != QNetworkReply::NoError ||
|
||||
!response.startsWith(QByteArray("[Adblock")) ||
|
||||
!saveDownloadedData(response)
|
||||
) {
|
||||
error = true;
|
||||
}
|
||||
|
||||
m_reply->deleteLater();
|
||||
m_reply = 0;
|
||||
|
||||
if (error) {
|
||||
emit subscriptionError(tr("Cannot load subscription!"));
|
||||
return;
|
||||
}
|
||||
|
||||
loadSubscription(AdBlockManager::instance()->disabledRules());
|
||||
|
||||
emit subscriptionUpdated();
|
||||
emit subscriptionChanged();
|
||||
}
|
||||
|
||||
bool AdBlockSubscription::saveDownloadedData(const QByteArray &data)
|
||||
{
|
||||
QFile file(m_filePath);
|
||||
|
||||
if (!file.open(QFile::ReadWrite | QFile::Truncate)) {
|
||||
qWarning() << "AdBlockSubscription::" << __FUNCTION__ << "Unable to open adblock file for writing:" << m_filePath;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Write subscription header
|
||||
file.write(QString("Title: %1\nUrl: %2\n").arg(title(), url().toString()).toUtf8());
|
||||
|
||||
if (AdBlockManager::instance()->useLimitedEasyList() && m_url == QUrl(ADBLOCK_EASYLIST_URL)) {
|
||||
// Third-party advertisers rules are with start domain (||) placeholder which needs regexps
|
||||
// So we are ignoring it for keeping good performance
|
||||
// But we will use whitelist rules at the end of list
|
||||
|
||||
QByteArray part1 = data.left(data.indexOf(QLatin1String("!-----------------------------Third-party adverts-----------------------------!")));
|
||||
QByteArray part2 = data.mid(data.indexOf(QLatin1String("!---------------------------------Whitelists----------------------------------!")));
|
||||
|
||||
file.write(part1);
|
||||
file.write(part2);
|
||||
file.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
file.write(data);
|
||||
file.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
const AdBlockRule* AdBlockSubscription::rule(int offset) const
|
||||
{
|
||||
if (!(offset >= 0 && m_rules.count() > offset)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return m_rules[offset];
|
||||
}
|
||||
|
||||
QVector<AdBlockRule*> AdBlockSubscription::allRules() const
|
||||
{
|
||||
return m_rules;
|
||||
}
|
||||
|
||||
const AdBlockRule* AdBlockSubscription::enableRule(int offset)
|
||||
{
|
||||
if (!(offset >= 0 && m_rules.count() > offset)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
AdBlockRule* rule = m_rules[offset];
|
||||
rule->setEnabled(true);
|
||||
AdBlockManager::instance()->removeDisabledRule(rule->filter());
|
||||
|
||||
emit subscriptionChanged();
|
||||
|
||||
// TODO
|
||||
/*
|
||||
if (rule->isCssRule())
|
||||
mainApp->reloadUserStyleBrowser();
|
||||
*/
|
||||
return rule;
|
||||
}
|
||||
|
||||
const AdBlockRule* AdBlockSubscription::disableRule(int offset)
|
||||
{
|
||||
if (!(offset >= 0 && m_rules.count() > offset)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
AdBlockRule* rule = m_rules[offset];
|
||||
rule->setEnabled(false);
|
||||
AdBlockManager::instance()->addDisabledRule(rule->filter());
|
||||
|
||||
emit subscriptionChanged();
|
||||
|
||||
// TODO
|
||||
/*
|
||||
if (rule->isCssRule())
|
||||
mainApp->reloadUserStyleBrowser();
|
||||
*/
|
||||
|
||||
return rule;
|
||||
}
|
||||
|
||||
bool AdBlockSubscription::canEditRules() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AdBlockSubscription::canBeRemoved() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
int AdBlockSubscription::addRule(AdBlockRule* rule)
|
||||
{
|
||||
Q_UNUSED(rule)
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool AdBlockSubscription::removeRule(int offset)
|
||||
{
|
||||
Q_UNUSED(offset)
|
||||
return false;
|
||||
}
|
||||
|
||||
const AdBlockRule* AdBlockSubscription::replaceRule(AdBlockRule* rule, int offset)
|
||||
{
|
||||
Q_UNUSED(rule)
|
||||
Q_UNUSED(offset)
|
||||
return 0;
|
||||
}
|
||||
|
||||
AdBlockSubscription::~AdBlockSubscription()
|
||||
{
|
||||
qDeleteAll(m_rules);
|
||||
}
|
||||
|
||||
// AdBlockCustomList
|
||||
|
||||
AdBlockCustomList::AdBlockCustomList(QObject* parent)
|
||||
: AdBlockSubscription(tr("Custom Rules"), parent)
|
||||
{
|
||||
// TODO
|
||||
setFilePath(qApp->homeFolderPath() + "/adblock/customlist.txt");
|
||||
}
|
||||
|
||||
void AdBlockCustomList::retranslateStrings()
|
||||
{
|
||||
setTitle(tr("Custom Rules"));
|
||||
}
|
||||
|
||||
void AdBlockCustomList::loadSubscription(const QStringList &disabledRules)
|
||||
{
|
||||
// DuckDuckGo ad whitelist rules
|
||||
// They cannot be removed, but can be disabled.
|
||||
// Please consider not disabling them. Thanks!
|
||||
|
||||
const QString ddg1 = QSL("@@||duckduckgo.com^$document");
|
||||
const QString ddg2 = QSL("duckduckgo.com#@#.has-ad");
|
||||
|
||||
QString rules = 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()
|
||||
{
|
||||
QFile file(filePath());
|
||||
|
||||
if (!file.open(QFile::ReadWrite | QFile::Truncate)) {
|
||||
qWarning() << "AdBlockSubscription::" << __FUNCTION__ << "Unable to open adblock file for writing:" << filePath();
|
||||
return;
|
||||
}
|
||||
|
||||
QTextStream textStream(&file);
|
||||
textStream.setCodec("UTF-8");
|
||||
textStream << "Title: " << title() << endl;
|
||||
textStream << "Url: " << url().toString() << endl;
|
||||
textStream << "[Adblock Plus 1.1.1]" << endl;
|
||||
|
||||
foreach (const AdBlockRule* rule, m_rules) {
|
||||
textStream << rule->filter() << endl;
|
||||
}
|
||||
|
||||
file.close();
|
||||
}
|
||||
|
||||
bool AdBlockCustomList::canEditRules() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AdBlockCustomList::canBeRemoved() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AdBlockCustomList::containsFilter(const QString &filter) const
|
||||
{
|
||||
foreach (const AdBlockRule* rule, m_rules) {
|
||||
if (rule->filter() == filter) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AdBlockCustomList::removeFilter(const QString &filter)
|
||||
{
|
||||
for (int i = 0; i < m_rules.count(); ++i) {
|
||||
const AdBlockRule* rule = m_rules.at(i);
|
||||
|
||||
if (rule->filter() == filter) {
|
||||
return removeRule(i);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int AdBlockCustomList::addRule(AdBlockRule* rule)
|
||||
{
|
||||
m_rules.append(rule);
|
||||
|
||||
emit subscriptionChanged();
|
||||
|
||||
// TODO
|
||||
/*
|
||||
if (rule->isCssRule())
|
||||
mainApp->reloadUserStyleBrowser();
|
||||
*/
|
||||
return m_rules.count() - 1;
|
||||
}
|
||||
|
||||
bool AdBlockCustomList::removeRule(int offset)
|
||||
{
|
||||
if (!(offset >= 0 && m_rules.count() > offset)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
AdBlockRule* rule = m_rules.at(offset);
|
||||
const QString filter = rule->filter();
|
||||
|
||||
m_rules.remove(offset);
|
||||
|
||||
emit subscriptionChanged();
|
||||
// TODO
|
||||
/*
|
||||
if (rule->isCssRule())
|
||||
mainApp->reloadUserStyleBrowser();
|
||||
*/
|
||||
|
||||
AdBlockManager::instance()->removeDisabledRule(filter);
|
||||
|
||||
delete rule;
|
||||
return true;
|
||||
}
|
||||
|
||||
const AdBlockRule* AdBlockCustomList::replaceRule(AdBlockRule* rule, int offset)
|
||||
{
|
||||
if (!(offset >= 0 && m_rules.count() > offset)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
AdBlockRule* oldRule = m_rules.at(offset);
|
||||
m_rules[offset] = rule;
|
||||
|
||||
emit subscriptionChanged();
|
||||
|
||||
// TODO
|
||||
/*
|
||||
if (rule->isCssRule() || oldRule->isCssRule())
|
||||
mainApp->reloadUserStyleBrowser();
|
||||
*/
|
||||
|
||||
delete oldRule;
|
||||
return m_rules[offset];
|
||||
}
|
159
src/network-web/adblock/adblocksubscription.h
Executable file
159
src/network-web/adblock/adblocksubscription.h
Executable file
@ -0,0 +1,159 @@
|
||||
/* ============================================================
|
||||
* QuiteRSS is a open-source cross-platform RSS/Atom news feeds reader
|
||||
* Copyright (C) 2011-2015 QuiteRSS Team <quiterssteam@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/>.
|
||||
* ============================================================ */
|
||||
/* ============================================================
|
||||
* 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>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Benjamin Meyer nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef ADBLOCKSUBSCRIPTION_H
|
||||
#define ADBLOCKSUBSCRIPTION_H
|
||||
|
||||
#include <QVector>
|
||||
#include <QUrl>
|
||||
|
||||
#include "adblockrule.h"
|
||||
#include "adblocksearchtree.h"
|
||||
|
||||
class QNetworkRequest;
|
||||
class QNetworkReply;
|
||||
class QUrl;
|
||||
|
||||
class FollowRedirectReply;
|
||||
|
||||
class AdBlockSubscription : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit AdBlockSubscription(const QString &title, QObject* parent = 0);
|
||||
~AdBlockSubscription();
|
||||
|
||||
QString title() const;
|
||||
void setTitle(const QString &title);
|
||||
|
||||
QString filePath() const;
|
||||
void setFilePath(const QString &path);
|
||||
|
||||
QUrl url() const;
|
||||
void setUrl(const QUrl &url);
|
||||
|
||||
virtual void loadSubscription(const QStringList &disabledRules);
|
||||
virtual void saveSubscription();
|
||||
|
||||
const AdBlockRule* rule(int offset) const;
|
||||
QVector<AdBlockRule*> allRules() const;
|
||||
|
||||
const AdBlockRule* enableRule(int offset);
|
||||
const AdBlockRule* disableRule(int offset);
|
||||
|
||||
virtual bool canEditRules() const;
|
||||
virtual bool canBeRemoved() const;
|
||||
|
||||
virtual int addRule(AdBlockRule* rule);
|
||||
virtual bool removeRule(int offset);
|
||||
virtual const AdBlockRule* replaceRule(AdBlockRule* rule, int offset);
|
||||
|
||||
public slots:
|
||||
void updateSubscription();
|
||||
|
||||
signals:
|
||||
void subscriptionChanged();
|
||||
void subscriptionUpdated();
|
||||
void subscriptionError(const QString &message);
|
||||
|
||||
protected slots:
|
||||
void subscriptionDownloaded();
|
||||
|
||||
protected:
|
||||
virtual bool saveDownloadedData(const QByteArray &data);
|
||||
|
||||
FollowRedirectReply* m_reply;
|
||||
|
||||
QVector<AdBlockRule*> m_rules;
|
||||
|
||||
private:
|
||||
QString m_title;
|
||||
QString m_filePath;
|
||||
|
||||
QUrl m_url;
|
||||
bool m_updated;
|
||||
};
|
||||
|
||||
class AdBlockCustomList : public AdBlockSubscription
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit AdBlockCustomList(QObject* parent = 0);
|
||||
|
||||
void retranslateStrings();
|
||||
|
||||
void loadSubscription(const QStringList &disabledRules);
|
||||
void saveSubscription();
|
||||
|
||||
bool canEditRules() const;
|
||||
bool canBeRemoved() const;
|
||||
|
||||
bool containsFilter(const QString &filter) const;
|
||||
bool removeFilter(const QString &filter);
|
||||
|
||||
int addRule(AdBlockRule* rule);
|
||||
bool removeRule(int offset);
|
||||
const AdBlockRule* replaceRule(AdBlockRule* rule, int offset);
|
||||
};
|
||||
|
||||
#endif // ADBLOCKSUBSCRIPTION_H
|
||||
|
361
src/network-web/adblock/adblocktreewidget.cpp
Executable file
361
src/network-web/adblock/adblocktreewidget.cpp
Executable file
@ -0,0 +1,361 @@
|
||||
/* ============================================================
|
||||
* QuiteRSS is a open-source cross-platform RSS/Atom news feeds reader
|
||||
* Copyright (C) 2011-2015 QuiteRSS Team <quiterssteam@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/>.
|
||||
* ============================================================ */
|
||||
/* ============================================================
|
||||
* 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/>.
|
||||
* ============================================================ */
|
||||
#include "adblocktreewidget.h"
|
||||
#include "adblocksubscription.h"
|
||||
|
||||
#include <QMenu>
|
||||
#include <QKeyEvent>
|
||||
#include <QClipboard>
|
||||
#include <QApplication>
|
||||
#include <QInputDialog>
|
||||
|
||||
AdBlockTreeWidget::AdBlockTreeWidget(AdBlockSubscription* subscription, QWidget* parent)
|
||||
: QTreeWidget(parent)
|
||||
, m_subscription(subscription)
|
||||
, m_topItem(0)
|
||||
, m_itemChangingBlock(false)
|
||||
, m_refreshAllItemsNeeded(true)
|
||||
{
|
||||
setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
setHeaderHidden(true);
|
||||
setAlternatingRowColors(true);
|
||||
setFrameStyle(QFrame::NoFrame);
|
||||
|
||||
connect(this, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(contextMenuRequested(QPoint)));
|
||||
connect(this, SIGNAL(itemChanged(QTreeWidgetItem*,int)), this, SLOT(itemChanged(QTreeWidgetItem*)));
|
||||
connect(m_subscription, SIGNAL(subscriptionUpdated()), this, SLOT(subscriptionUpdated()));
|
||||
connect(m_subscription, SIGNAL(subscriptionError(QString)), this, SLOT(subscriptionError(QString)));
|
||||
}
|
||||
|
||||
AdBlockSubscription* AdBlockTreeWidget::subscription() const
|
||||
{
|
||||
return m_subscription;
|
||||
}
|
||||
|
||||
void AdBlockTreeWidget::showRule(const AdBlockRule* rule)
|
||||
{
|
||||
if (!m_topItem && rule) {
|
||||
m_ruleToBeSelected = rule->filter();
|
||||
}
|
||||
else if (!m_ruleToBeSelected.isEmpty()) {
|
||||
QList<QTreeWidgetItem*> items = findItems(m_ruleToBeSelected, Qt::MatchRecursive);
|
||||
if (!items.isEmpty()) {
|
||||
QTreeWidgetItem* item = items.at(0);
|
||||
|
||||
setCurrentItem(item);
|
||||
scrollToItem(item, QAbstractItemView::PositionAtCenter);
|
||||
}
|
||||
|
||||
m_ruleToBeSelected.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void AdBlockTreeWidget::contextMenuRequested(const QPoint &pos)
|
||||
{
|
||||
if (!m_subscription->canEditRules()) {
|
||||
return;
|
||||
}
|
||||
|
||||
QTreeWidgetItem* item = itemAt(pos);
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
m_refreshAllItemsNeeded = true;
|
||||
|
||||
if (!item || m_itemChangingBlock) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_itemChangingBlock = true;
|
||||
|
||||
int offset = item->data(0, Qt::UserRole + 10).toInt();
|
||||
const AdBlockRule* oldRule = m_subscription->rule(offset);
|
||||
|
||||
if (item->checkState(0) == Qt::Unchecked && oldRule->isEnabled()) {
|
||||
// Disable rule
|
||||
const AdBlockRule* rule = m_subscription->disableRule(offset);
|
||||
|
||||
adjustItemFeatures(item, rule);
|
||||
}
|
||||
else if (item->checkState(0) == Qt::Checked && !oldRule->isEnabled()) {
|
||||
// Enable rule
|
||||
const AdBlockRule* rule = m_subscription->enableRule(offset);
|
||||
|
||||
adjustItemFeatures(item, rule);
|
||||
}
|
||||
else if (m_subscription->canEditRules()) {
|
||||
// Custom rule has been changed
|
||||
AdBlockRule* newRule = new AdBlockRule(item->text(0), m_subscription);
|
||||
const AdBlockRule* rule = m_subscription->replaceRule(newRule, offset);
|
||||
|
||||
adjustItemFeatures(item, rule);
|
||||
}
|
||||
|
||||
m_itemChangingBlock = false;
|
||||
}
|
||||
|
||||
void AdBlockTreeWidget::copyFilter()
|
||||
{
|
||||
QTreeWidgetItem* item = currentItem();
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
|
||||
QApplication::clipboard()->setText(item->text(0));
|
||||
}
|
||||
|
||||
void AdBlockTreeWidget::addRule()
|
||||
{
|
||||
if (!m_subscription->canEditRules()) {
|
||||
return;
|
||||
}
|
||||
|
||||
QString newRule = QInputDialog::getText(this, tr("Add Custom Rule"), tr("Please write your rule here:"));
|
||||
if (newRule.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
AdBlockRule* rule = new AdBlockRule(newRule, m_subscription);
|
||||
int offset = m_subscription->addRule(rule);
|
||||
|
||||
QTreeWidgetItem* item = new QTreeWidgetItem();
|
||||
item->setText(0, newRule);
|
||||
item->setData(0, Qt::UserRole + 10, offset);
|
||||
item->setFlags(item->flags() | Qt::ItemIsEditable);
|
||||
|
||||
m_itemChangingBlock = true;
|
||||
m_topItem->addChild(item);
|
||||
m_itemChangingBlock = false;
|
||||
|
||||
adjustItemFeatures(item, rule);
|
||||
}
|
||||
|
||||
void AdBlockTreeWidget::removeRule()
|
||||
{
|
||||
QTreeWidgetItem* item = currentItem();
|
||||
if (!item || !m_subscription->canEditRules() || item == m_topItem) {
|
||||
return;
|
||||
}
|
||||
|
||||
int offset = item->data(0, Qt::UserRole + 10).toInt();
|
||||
|
||||
m_subscription->removeRule(offset);
|
||||
delete item;
|
||||
}
|
||||
|
||||
void AdBlockTreeWidget::subscriptionUpdated()
|
||||
{
|
||||
refresh();
|
||||
|
||||
m_itemChangingBlock = true;
|
||||
m_topItem->setText(0, tr("%1 (recently updated)").arg(m_subscription->title()));
|
||||
m_itemChangingBlock = false;
|
||||
}
|
||||
|
||||
void AdBlockTreeWidget::subscriptionError(const QString &message)
|
||||
{
|
||||
refresh();
|
||||
|
||||
m_itemChangingBlock = true;
|
||||
m_topItem->setText(0, tr("%1 (Error: %2)").arg(m_subscription->title(), message));
|
||||
m_itemChangingBlock = false;
|
||||
}
|
||||
|
||||
void AdBlockTreeWidget::adjustItemFeatures(QTreeWidgetItem* item, const AdBlockRule* rule)
|
||||
{
|
||||
if (!rule->isEnabled()) {
|
||||
QFont font;
|
||||
font.setItalic(true);
|
||||
item->setForeground(0, QColor(Qt::gray));
|
||||
|
||||
if (!rule->isComment()) {
|
||||
item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
|
||||
item->setCheckState(0, Qt::Unchecked);
|
||||
item->setFont(0, font);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
|
||||
item->setCheckState(0, Qt::Checked);
|
||||
|
||||
if (rule->isException()) {
|
||||
item->setForeground(0, QColor(Qt::darkGreen));
|
||||
item->setFont(0, QFont());
|
||||
}
|
||||
else if (rule->isCssRule()) {
|
||||
item->setForeground(0, QColor(Qt::darkBlue));
|
||||
item->setFont(0, QFont());
|
||||
}
|
||||
else {
|
||||
item->setForeground(0, QColor());
|
||||
item->setFont(0, QFont());
|
||||
}
|
||||
}
|
||||
|
||||
void AdBlockTreeWidget::keyPressEvent(QKeyEvent* event)
|
||||
{
|
||||
if (event->key() == Qt::Key_C && event->modifiers() & Qt::ControlModifier) {
|
||||
copyFilter();
|
||||
}
|
||||
|
||||
if (event->key() == Qt::Key_Delete) {
|
||||
removeRule();
|
||||
}
|
||||
|
||||
QTreeWidget::keyPressEvent(event);
|
||||
}
|
||||
|
||||
void AdBlockTreeWidget::refresh()
|
||||
{
|
||||
m_itemChangingBlock = true;
|
||||
clear();
|
||||
|
||||
QFont boldFont;
|
||||
boldFont.setBold(true);
|
||||
|
||||
m_topItem = new QTreeWidgetItem(this);
|
||||
m_topItem->setText(0, m_subscription->title());
|
||||
m_topItem->setFont(0, boldFont);
|
||||
m_topItem->setExpanded(true);
|
||||
addTopLevelItem(m_topItem);
|
||||
|
||||
const QVector<AdBlockRule*> &allRules = m_subscription->allRules();
|
||||
|
||||
int index = 0;
|
||||
foreach (const AdBlockRule* rule, allRules) {
|
||||
QTreeWidgetItem* item = new QTreeWidgetItem(m_topItem);
|
||||
item->setText(0, rule->filter());
|
||||
item->setData(0, Qt::UserRole + 10, index);
|
||||
|
||||
if (m_subscription->canEditRules()) {
|
||||
item->setFlags(item->flags() | Qt::ItemIsEditable);
|
||||
}
|
||||
|
||||
adjustItemFeatures(item, rule);
|
||||
++index;
|
||||
}
|
||||
|
||||
showRule(0);
|
||||
m_itemChangingBlock = false;
|
||||
}
|
||||
|
||||
void AdBlockTreeWidget::clear()
|
||||
{
|
||||
QTreeWidget::clear();
|
||||
m_allTreeItems.clear();
|
||||
}
|
||||
|
||||
void AdBlockTreeWidget::addTopLevelItem(QTreeWidgetItem* item)
|
||||
{
|
||||
m_allTreeItems.append(item);
|
||||
QTreeWidget::addTopLevelItem(item);
|
||||
}
|
||||
|
||||
void AdBlockTreeWidget::iterateAllItems(QTreeWidgetItem* parent)
|
||||
{
|
||||
int count = parent ? parent->childCount() : topLevelItemCount();
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
QTreeWidgetItem* item = parent ? parent->child(i) : topLevelItem(i);
|
||||
|
||||
if (item->childCount() == 0) {
|
||||
m_allTreeItems.append(item);
|
||||
}
|
||||
|
||||
iterateAllItems(item);
|
||||
}
|
||||
}
|
||||
|
||||
QList<QTreeWidgetItem*> AdBlockTreeWidget::allItems()
|
||||
{
|
||||
if (m_refreshAllItemsNeeded) {
|
||||
m_allTreeItems.clear();
|
||||
iterateAllItems(0);
|
||||
m_refreshAllItemsNeeded = false;
|
||||
}
|
||||
|
||||
return m_allTreeItems;
|
||||
}
|
||||
|
||||
void AdBlockTreeWidget::filterString(const QString &string)
|
||||
{
|
||||
QList<QTreeWidgetItem*> _allItems = allItems();
|
||||
QList<QTreeWidgetItem*> parents;
|
||||
bool stringIsEmpty = string.isEmpty();
|
||||
foreach (QTreeWidgetItem* item, _allItems) {
|
||||
bool containsString = stringIsEmpty || item->text(0).contains(string, Qt::CaseInsensitive);
|
||||
if (containsString) {
|
||||
item->setHidden(false);
|
||||
if (item->parent()) {
|
||||
if (!parents.contains(item->parent())) {
|
||||
parents << item->parent();
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
item->setHidden(true);
|
||||
if (item->parent()) {
|
||||
item->parent()->setHidden(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < parents.size(); ++i) {
|
||||
QTreeWidgetItem* parentItem = parents.at(i);
|
||||
parentItem->setHidden(false);
|
||||
parentItem->setExpanded(true);
|
||||
|
||||
if (parentItem->parent() && !parents.contains(parentItem->parent())) {
|
||||
parents << parentItem->parent();
|
||||
}
|
||||
}
|
||||
}
|
86
src/network-web/adblock/adblocktreewidget.h
Executable file
86
src/network-web/adblock/adblocktreewidget.h
Executable file
@ -0,0 +1,86 @@
|
||||
/* ============================================================
|
||||
* QuiteRSS is a open-source cross-platform RSS/Atom news feeds reader
|
||||
* Copyright (C) 2011-2015 QuiteRSS Team <quiterssteam@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/>.
|
||||
* ============================================================ */
|
||||
/* ============================================================
|
||||
* 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
|
||||
#define ADBLOCKTREEWIDGET_H
|
||||
|
||||
#include <QTreeWidget>
|
||||
|
||||
class AdBlockSubscription;
|
||||
class AdBlockRule;
|
||||
|
||||
class AdBlockTreeWidget : public QTreeWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit AdBlockTreeWidget(AdBlockSubscription* subscription, QWidget* parent = 0);
|
||||
|
||||
AdBlockSubscription* subscription() const;
|
||||
|
||||
void showRule(const AdBlockRule* rule);
|
||||
void refresh();
|
||||
|
||||
public slots:
|
||||
void addRule();
|
||||
void removeRule();
|
||||
void filterString(const QString &string);
|
||||
void clear();
|
||||
|
||||
private slots:
|
||||
void contextMenuRequested(const QPoint &pos);
|
||||
void itemChanged(QTreeWidgetItem* item);
|
||||
void copyFilter();
|
||||
|
||||
void subscriptionUpdated();
|
||||
void subscriptionError(const QString &message);
|
||||
|
||||
private:
|
||||
void adjustItemFeatures(QTreeWidgetItem* item, const AdBlockRule* rule);
|
||||
void keyPressEvent(QKeyEvent* event);
|
||||
void addTopLevelItem(QTreeWidgetItem* item);
|
||||
QList<QTreeWidgetItem*> allItems();
|
||||
void iterateAllItems(QTreeWidgetItem* parent);
|
||||
|
||||
AdBlockSubscription* m_subscription;
|
||||
QTreeWidgetItem* m_topItem;
|
||||
|
||||
QString m_ruleToBeSelected;
|
||||
bool m_itemChangingBlock;
|
||||
|
||||
bool m_refreshAllItemsNeeded;
|
||||
QList<QTreeWidgetItem*> m_allTreeItems;
|
||||
|
||||
};
|
||||
|
||||
#endif // ADBLOCKTREEWIDGET_H
|
96
src/network-web/adblock/followredirectreply.cpp
Executable file
96
src/network-web/adblock/followredirectreply.cpp
Executable file
@ -0,0 +1,96 @@
|
||||
/* ============================================================
|
||||
* QuiteRSS is a open-source cross-platform RSS/Atom news feeds reader
|
||||
* Copyright (C) 2011-2015 QuiteRSS Team <quiterssteam@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/>.
|
||||
* ============================================================ */
|
||||
/* ============================================================
|
||||
* 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/>.
|
||||
* ============================================================ */
|
||||
#include "followredirectreply.h"
|
||||
|
||||
#include <QNetworkAccessManager>
|
||||
|
||||
FollowRedirectReply::FollowRedirectReply(const QUrl &url, QNetworkAccessManager* manager)
|
||||
: QObject()
|
||||
, m_manager(manager)
|
||||
, m_redirectCount(0)
|
||||
{
|
||||
m_reply = m_manager->get(QNetworkRequest(url));
|
||||
connect(m_reply, SIGNAL(finished()), this, SLOT(replyFinished()));
|
||||
}
|
||||
|
||||
QNetworkReply* FollowRedirectReply::reply() const
|
||||
{
|
||||
return m_reply;
|
||||
}
|
||||
|
||||
QUrl FollowRedirectReply::originalUrl() const
|
||||
{
|
||||
return m_reply->request().url();
|
||||
}
|
||||
|
||||
QUrl FollowRedirectReply::url() const
|
||||
{
|
||||
return m_reply->url();
|
||||
}
|
||||
|
||||
QNetworkReply::NetworkError FollowRedirectReply::error() const
|
||||
{
|
||||
return m_reply->error();
|
||||
}
|
||||
|
||||
QByteArray FollowRedirectReply::readAll()
|
||||
{
|
||||
return m_reply->readAll();
|
||||
}
|
||||
|
||||
void FollowRedirectReply::replyFinished()
|
||||
{
|
||||
int replyStatus = m_reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||
|
||||
if ((replyStatus != 301 && replyStatus != 302) || m_redirectCount == 5) {
|
||||
emit finished();
|
||||
return;
|
||||
}
|
||||
|
||||
m_redirectCount++;
|
||||
|
||||
QUrl redirectUrl = m_reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl();
|
||||
m_reply->close();
|
||||
m_reply->deleteLater();
|
||||
|
||||
m_reply = m_manager->get(QNetworkRequest(redirectUrl));
|
||||
connect(m_reply, SIGNAL(finished()), this, SLOT(replyFinished()));
|
||||
}
|
||||
|
||||
FollowRedirectReply::~FollowRedirectReply()
|
||||
{
|
||||
m_reply->close();
|
||||
m_reply->deleteLater();
|
||||
}
|
73
src/network-web/adblock/followredirectreply.h
Executable file
73
src/network-web/adblock/followredirectreply.h
Executable file
@ -0,0 +1,73 @@
|
||||
/* ============================================================
|
||||
* QuiteRSS is a open-source cross-platform RSS/Atom news feeds reader
|
||||
* Copyright (C) 2011-2015 QuiteRSS Team <quiterssteam@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/>.
|
||||
* ============================================================ */
|
||||
/* ============================================================
|
||||
* 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
|
||||
#define FOLLOWREDIRECTREPLY_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QNetworkReply>
|
||||
|
||||
class QNetworkAccessManager;
|
||||
class QNetworkReply;
|
||||
class QUrl;
|
||||
|
||||
class FollowRedirectReply : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit FollowRedirectReply(const QUrl &url, QNetworkAccessManager* manager);
|
||||
~FollowRedirectReply();
|
||||
|
||||
QNetworkReply* reply() const;
|
||||
QUrl originalUrl() const;
|
||||
QUrl url() const;
|
||||
|
||||
QNetworkReply::NetworkError error() const;
|
||||
QByteArray readAll();
|
||||
|
||||
signals:
|
||||
void finished();
|
||||
|
||||
private slots:
|
||||
void replyFinished();
|
||||
|
||||
private:
|
||||
QNetworkAccessManager* m_manager;
|
||||
QNetworkReply* m_reply;
|
||||
int m_redirectCount;
|
||||
|
||||
};
|
||||
|
||||
#endif // FOLLOWREDIRECTREPLY_H
|
@ -34,7 +34,7 @@ Downloader::Downloader(QObject *parent)
|
||||
}
|
||||
|
||||
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) {
|
||||
|
@ -56,6 +56,10 @@ class WebBrowser : public TabContent {
|
||||
return m_webView->icon();
|
||||
}
|
||||
|
||||
inline WebView *view() {
|
||||
return m_webView;
|
||||
}
|
||||
|
||||
// Sets this WebBrowser instance as focused.
|
||||
inline void setFocus(Qt::FocusReason reason) {
|
||||
m_txtLocation->setFocus(reason);
|
||||
|
@ -19,13 +19,15 @@
|
||||
|
||||
#include "miscellaneous/application.h"
|
||||
|
||||
#include "network-web/adblock/adblockmanager.h"
|
||||
|
||||
#include <QNetworkReply>
|
||||
|
||||
|
||||
QPointer<WebBrowserNetworkAccessManager> WebBrowserNetworkAccessManager::s_instance;
|
||||
|
||||
WebBrowserNetworkAccessManager::WebBrowserNetworkAccessManager(QObject *parent)
|
||||
: BaseNetworkAccessManager(parent) {
|
||||
WebBrowserNetworkAccessManager::WebBrowserNetworkAccessManager(WebPage *page, QObject *parent)
|
||||
: BaseNetworkAccessManager(parent), page_(page) {
|
||||
connect(this, SIGNAL(authenticationRequired(QNetworkReply*,QAuthenticator*)),
|
||||
this, SLOT(onAuthenticationRequired(QNetworkReply*,QAuthenticator*)));
|
||||
}
|
||||
@ -41,9 +43,27 @@ void WebBrowserNetworkAccessManager::onAuthenticationRequired(QNetworkReply *rep
|
||||
qDebug("URL '%s' requested authentication but username/password is not available.", qPrintable(reply->url().toString()));
|
||||
}
|
||||
|
||||
QNetworkReply *WebBrowserNetworkAccessManager::createRequest(QNetworkAccessManager::Operation op, const QNetworkRequest &request, QIODevice *outgoingData) {
|
||||
if (page_) {
|
||||
QNetworkRequest pageRequest = request;
|
||||
page_->populateNetworkRequest(pageRequest);
|
||||
return WebBrowserNetworkAccessManager::instance()->createRequest(op, pageRequest, outgoingData);
|
||||
}
|
||||
|
||||
if (op == QNetworkAccessManager::GetOperation) {
|
||||
QNetworkReply *reply = AdBlockManager::instance()->block(request);
|
||||
|
||||
if (reply) {
|
||||
return reply;
|
||||
}
|
||||
}
|
||||
|
||||
return BaseNetworkAccessManager::createRequest(op, request, outgoingData);
|
||||
}
|
||||
|
||||
WebBrowserNetworkAccessManager *WebBrowserNetworkAccessManager::instance() {
|
||||
if (s_instance.isNull()) {
|
||||
s_instance = new WebBrowserNetworkAccessManager(qApp);
|
||||
s_instance = new WebBrowserNetworkAccessManager(0, qApp);
|
||||
}
|
||||
|
||||
return s_instance;
|
||||
|
10
src/network-web/webbrowsernetworkaccessmanager.h
Normal file → Executable file
10
src/network-web/webbrowsernetworkaccessmanager.h
Normal file → Executable file
@ -20,6 +20,8 @@
|
||||
|
||||
#include "network-web/basenetworkaccessmanager.h"
|
||||
|
||||
#include "webpage.h"
|
||||
|
||||
#include <QPointer>
|
||||
|
||||
|
||||
@ -29,7 +31,7 @@ class WebBrowserNetworkAccessManager : public BaseNetworkAccessManager {
|
||||
|
||||
public:
|
||||
// Constructors and destructors.
|
||||
explicit WebBrowserNetworkAccessManager(QObject *parent = 0);
|
||||
explicit WebBrowserNetworkAccessManager(WebPage *page = 0, QObject *parent = 0);
|
||||
virtual ~WebBrowserNetworkAccessManager();
|
||||
|
||||
// Returns pointer to global network access manager
|
||||
@ -40,7 +42,13 @@ class WebBrowserNetworkAccessManager : public BaseNetworkAccessManager {
|
||||
void onAuthenticationRequired(QNetworkReply *reply, QAuthenticator *authenticator);
|
||||
|
||||
private:
|
||||
WebPage* page_;
|
||||
|
||||
static QPointer<WebBrowserNetworkAccessManager> s_instance;
|
||||
|
||||
// QNetworkAccessManager interface
|
||||
protected:
|
||||
QNetworkReply *createRequest(Operation op, const QNetworkRequest &request, QIODevice *outgoingData);
|
||||
};
|
||||
|
||||
#endif // WEBBROWSERNETWORKACCESSMANAGER_H
|
||||
|
142
src/network-web/webpage.cpp
Normal file → Executable file
142
src/network-web/webpage.cpp
Normal file → Executable file
@ -21,26 +21,161 @@
|
||||
#include "network-web/webbrowser.h"
|
||||
#include "miscellaneous/application.h"
|
||||
|
||||
#include "network-web/adblock/adblockmanager.h"
|
||||
|
||||
#include <QNetworkReply>
|
||||
#include <QWebElement>
|
||||
#include <QWebFrame>
|
||||
|
||||
|
||||
QList<WebPage*> WebPage::livingPages_;
|
||||
|
||||
WebPage::WebPage(QObject *parent)
|
||||
: QWebPage(parent) {
|
||||
: QWebPage(parent), loadProgress_(-1) {
|
||||
// Setup global network access manager.
|
||||
// NOTE: This makes network settings easy for all web browsers.
|
||||
setNetworkAccessManager(WebBrowserNetworkAccessManager::instance());
|
||||
setNetworkAccessManager(new WebBrowserNetworkAccessManager(this, this));
|
||||
setForwardUnsupportedContent(true);
|
||||
connect(this, SIGNAL(unsupportedContent(QNetworkReply*)), this, SLOT(handleUnsupportedContent(QNetworkReply*)));
|
||||
|
||||
connect(this, SIGNAL(loadProgress(int)), this, SLOT(progress(int)));
|
||||
connect(this, SIGNAL(loadFinished(bool)), this, SLOT(finished()));
|
||||
|
||||
livingPages_.append(this);
|
||||
}
|
||||
|
||||
WebPage::~WebPage() {
|
||||
livingPages_.removeOne(this);
|
||||
}
|
||||
|
||||
bool WebPage::isLoading() const
|
||||
{
|
||||
return loadProgress_ < 100;
|
||||
}
|
||||
|
||||
void WebPage::progress(int prog)
|
||||
{
|
||||
loadProgress_ = prog;
|
||||
}
|
||||
|
||||
void WebPage::finished()
|
||||
{
|
||||
progress(100);
|
||||
|
||||
// AdBlock
|
||||
cleanBlockedObjects();
|
||||
}
|
||||
|
||||
void WebPage::cleanBlockedObjects()
|
||||
{
|
||||
AdBlockManager* manager = AdBlockManager::instance();
|
||||
if (!manager->isEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const QWebElement docElement = mainFrame()->documentElement();
|
||||
|
||||
foreach (const AdBlockedEntry &entry, adBlockedEntries_) {
|
||||
const QString urlString = entry.url.toString();
|
||||
if (urlString.endsWith(QLatin1String(".js")) || urlString.endsWith(QLatin1String(".css"))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
QString urlEnd;
|
||||
|
||||
int pos = urlString.lastIndexOf(QLatin1Char('/'));
|
||||
if (pos > 8) {
|
||||
urlEnd = urlString.mid(pos + 1);
|
||||
}
|
||||
|
||||
if (urlString.endsWith(QLatin1Char('/'))) {
|
||||
urlEnd = urlString.left(urlString.size() - 1);
|
||||
}
|
||||
|
||||
QString selector("img[src$=\"%1\"], iframe[src$=\"%1\"],embed[src$=\"%1\"]");
|
||||
QWebElementCollection elements = docElement.findAll(selector.arg(urlEnd));
|
||||
|
||||
foreach (QWebElement element, elements) {
|
||||
QString src = element.attribute("src");
|
||||
src.remove(QLatin1String("../"));
|
||||
|
||||
if (urlString.contains(src)) {
|
||||
element.setStyleProperty("display", "none");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Apply domain-specific element hiding rules
|
||||
QString elementHiding = manager->elementHidingRulesForDomain(mainFrame()->url());
|
||||
if (elementHiding.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
elementHiding.append(QLatin1String("\n</style>"));
|
||||
|
||||
QWebElement bodyElement = docElement.findFirst("body");
|
||||
bodyElement.appendInside("<style type=\"text/css\">\n/* AdBlock for QupZilla */\n" + elementHiding);
|
||||
|
||||
// When hiding some elements, scroll position of page will change
|
||||
// If user loaded anchor link in background tab (and didn't show it yet), fix the scroll position
|
||||
if (view() && !view()->isVisible() && !mainFrame()->url().fragment().isEmpty()) {
|
||||
mainFrame()->scrollToAnchor(mainFrame()->url().fragment());
|
||||
}
|
||||
}
|
||||
|
||||
void WebPage::urlChanged(const QUrl &url)
|
||||
{
|
||||
Q_UNUSED(url)
|
||||
|
||||
if (isLoading()) {
|
||||
adBlockedEntries_.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void WebPage::addAdBlockRule(const AdBlockRule* rule, const QUrl &url)
|
||||
{
|
||||
AdBlockedEntry entry;
|
||||
entry.rule = rule;
|
||||
entry.url = url;
|
||||
|
||||
if (!adBlockedEntries_.contains(entry)) {
|
||||
adBlockedEntries_.append(entry);
|
||||
}
|
||||
}
|
||||
|
||||
QVector<WebPage::AdBlockedEntry> WebPage::adBlockedEntries() const
|
||||
{
|
||||
return adBlockedEntries_;
|
||||
}
|
||||
|
||||
bool WebPage::isPointerSafeToUse(WebPage* page)
|
||||
{
|
||||
// Pointer to WebPage is passed with every QNetworkRequest casted to void*
|
||||
// So there is no way to test whether pointer is still valid or not, except
|
||||
// this hack.
|
||||
|
||||
return page == 0 ? false : livingPages_.contains(page);
|
||||
}
|
||||
|
||||
QString WebPage::toPlainText() const {
|
||||
return mainFrame()->toPlainText();
|
||||
}
|
||||
|
||||
void WebPage::populateNetworkRequest(QNetworkRequest &request)
|
||||
{
|
||||
WebPage* pagePointer = this;
|
||||
|
||||
QVariant variant = QVariant::fromValue((void*) pagePointer);
|
||||
request.setAttribute((QNetworkRequest::Attribute)(QNetworkRequest::User + 100), variant);
|
||||
/*
|
||||
if (lastRequestUrl_ == request.url()) {
|
||||
request.setAttribute((QNetworkRequest::Attribute)(QNetworkRequest::User + 101), lastRequestType_);
|
||||
if (lastRequestType_ == NavigationTypeLinkClicked) {
|
||||
request.setRawHeader("X-QuiteRSS-UserLoadAction", QByteArray("1"));
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
void WebPage::handleUnsupportedContent(QNetworkReply *reply) {
|
||||
if (!reply) {
|
||||
return;
|
||||
@ -78,6 +213,9 @@ bool WebPage::acceptNavigationRequest(QWebFrame *frame,
|
||||
return false;
|
||||
}
|
||||
|
||||
lastRequestType_ = type;
|
||||
lastRequestUrl_ = request.url();
|
||||
|
||||
if (type == QWebPage::NavigationTypeLinkClicked &&
|
||||
frame == mainFrame()) {
|
||||
// Make sure that appropriate signal is emitted even if
|
||||
|
37
src/network-web/webpage.h
Normal file → Executable file
37
src/network-web/webpage.h
Normal file → Executable file
@ -19,12 +19,25 @@
|
||||
#define WEBPAGE_H
|
||||
|
||||
#include <QWebPage>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QSslCertificate>
|
||||
|
||||
|
||||
class AdBlockRule;
|
||||
|
||||
class WebPage : public QWebPage {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
struct AdBlockedEntry {
|
||||
const AdBlockRule* rule;
|
||||
QUrl url;
|
||||
|
||||
bool operator==(const AdBlockedEntry &other) const {
|
||||
return (this->rule == other.rule && this->url == other.url);
|
||||
}
|
||||
};
|
||||
|
||||
// Constructors and destructors.
|
||||
explicit WebPage(QObject *parent = 0);
|
||||
virtual ~WebPage();
|
||||
@ -32,11 +45,35 @@ class WebPage : public QWebPage {
|
||||
QString toHtml() const;
|
||||
QString toPlainText() const;
|
||||
|
||||
void populateNetworkRequest(QNetworkRequest &request);
|
||||
|
||||
bool isLoading() const;
|
||||
|
||||
static bool isPointerSafeToUse(WebPage* page);
|
||||
void addAdBlockRule(const AdBlockRule* rule, const QUrl &url);
|
||||
QVector<AdBlockedEntry> adBlockedEntries() const;
|
||||
|
||||
|
||||
private slots:
|
||||
void progress(int prog);
|
||||
void finished();
|
||||
void cleanBlockedObjects();
|
||||
void urlChanged(const QUrl &url);
|
||||
|
||||
void handleUnsupportedContent(QNetworkReply *reply);
|
||||
|
||||
protected:
|
||||
bool acceptNavigationRequest(QWebFrame *frame, const QNetworkRequest &request, NavigationType type);
|
||||
|
||||
private:
|
||||
QWebPage::NavigationType lastRequestType_;
|
||||
QUrl lastRequestUrl_;
|
||||
|
||||
bool adjustingScheduled_;
|
||||
static QList<WebPage*> livingPages_;
|
||||
QVector<AdBlockedEntry> adBlockedEntries_;
|
||||
|
||||
int loadProgress_;
|
||||
};
|
||||
|
||||
#endif // BASEWEBPAGE_H
|
||||
|
Loading…
x
Reference in New Issue
Block a user