/*******************************************************************************
**
** smolbote: yet another qute browser
** Copyright (C) 2017 Xian Nox
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see .
**
******************************************************************************/
#include "blockersubscription.h"
#include "ui_subscriptionform.h"
#include "browser.h"
#include
#include
BlockerSubscription::BlockerSubscription(const QUrl url, QWidget *parent) :
QWidget(parent),
ui(new Ui::SubscriptionForm)
{
ui->setupUi(this);
m_name = url.fileName();
m_url = url;
QString subPath = sSettings->value("blocker.path").toString() + m_name;
qDebug("Adding subscription [%s]", qUtf8Printable(subPath));
QFile *sub = new QFile(subPath);
if(sub->exists()) {
sub->open(QIODevice::ReadOnly);
load(sub);
} else {
if(!url.scheme().startsWith("http")) {
qWarning("Invalid url, subscription cannot be updated");
sub->deleteLater();
return;
}
qDebug("Subscription doesn't exist, updating...");
sub->open(QIODevice::ReadWrite);
update(sub);
}
}
BlockerSubscription::~BlockerSubscription()
{
delete ui;
}
QString BlockerSubscription::name() const
{
return m_name;
}
/**
* Check if a URL request should be blocked or not
* @param info
* @return true if it should be blocked; false otherwise
*/
BlockerSubscription::MatchResult BlockerSubscription::match(QWebEngineUrlRequestInfo &info)
{
MatchResult result;
for(BlockerRule* rule : m_urlWhitelist) {
if(rule->match(info)) {
// this request is whitelisted
result.match = true;
result.block = false;
result.pattern = rule->filter();
return result;
}
}
// request is not in the whitelist
for(BlockerRule* rule : m_urlBlacklist) {
if(rule->match(info)) {
// this request is blacklisted
result.match = true;
result.block = true;
result.pattern = rule->filter();
return result;
}
}
// request matches neither whitelist nor blacklist
result.match = false;
result.block = false;
return result;
}
void BlockerSubscription::update(QFile *cache)
{
// no cache path specified - pull the subscription
QNetworkRequest request;
request.setUrl(m_url);
QNetworkReply *reply = sNetwork->get(request);
connect(reply, &QNetworkReply::readyRead, [this, reply, cache]() {
cache->write(reply->readAll());
});
connect(reply, &QNetworkReply::finished, [this, reply, cache]() {
cache->write(reply->readAll());
cache->flush();
cache->seek(0);
reply->deleteLater();
qDebug("Subscription updated: [%s]", qUtf8Printable(this->m_name));
this->load(cache);
});
}
void BlockerSubscription::load(QIODevice *dev)
{
QTextStream subscription(dev);
QString header = subscription.readLine();
if(!header.startsWith("[Adblock Plus")) {
qWarning("Invalid format of subscription: %s", qUtf8Printable(m_name));
}
// clear all lists
m_urlBlacklist.clear();
m_urlWhitelist.clear();
int rules = 0;
while(!subscription.atEnd()) {
QString line = subscription.readLine();
if(!line.isEmpty()) {
if(line.startsWith('!')) {
parseComment(line);
} else {
// The line is not empty or a comment
rules++;
BlockerRule *rule = new BlockerRule(line, this);
if(rule->isValid()) {
if(rule->isException()) {
m_urlWhitelist.append(rule);
ui->whitelist_listWidget->addItem(rule->filter());
} else {
ui->blacklist_listWidget->addItem(rule->filter());
m_urlBlacklist.append(rule);
}
}
}
} // line.isEmpty
} // subscription.atEnd()
qDebug("Loaded %i/%i rules from subscription %s", m_urlBlacklist.count() + m_urlWhitelist.count(), rules, qUtf8Printable(m_name));
dev->deleteLater();
}
void BlockerSubscription::parseComment(const QString &line)
{
if(line.startsWith("! Title: ")) {
ui->title->setText(line.right(line.length() - 9));
return;
}
if(line.startsWith("! Homepage: ")) {
ui->homepage->setText(line.right(line.length() - 12));
return;
}
if(line.startsWith("! Licence: ")) {
ui->license->setText(line.right(line.length() - 11));
return;
}
if(line.startsWith("! Version: ")) {
ui->version->setText(line.right(line.length() - 11));
return;
}
if(line.startsWith("! Last modified: ")) {
ui->lastModified->setText(line.right(line.length() - 17));
return;
}
if(line.startsWith("! Expires: ")) {
ui->expires->setText(line.right(line.length() - 11).left(2));
return;
}
}