From 2aec131158da9908dad0e56986f5366dd3de700e Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Wed, 13 Mar 2019 17:46:29 +0100 Subject: Add black/whitelisting of URLs --- src/slxbrowser.cpp | 149 +++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 110 insertions(+), 39 deletions(-) (limited to 'src/slxbrowser.cpp') diff --git a/src/slxbrowser.cpp b/src/slxbrowser.cpp index 0690102..5ffe281 100644 --- a/src/slxbrowser.cpp +++ b/src/slxbrowser.cpp @@ -1,19 +1,24 @@ #include "slxbrowser.h" #include "webview.h" +#include "nam.h" #include #include #include #include #include +#include -SLXbrowser::SLXbrowser(QString url, bool fullscreen, bool ignoreSslErrors, int reloadIntervalSeconds) +static QRegularExpression urlListToRegExp(const QStringList &list); + +SLXbrowser::SLXbrowser(BrowserSettings settings) : QMainWindow(nullptr), - _url(url), - _ignoreSslErrors(ignoreSslErrors), + _settings(settings), _unsupportedUri(false), - _reloadIntervalMs(reloadIntervalSeconds * 1000) + _blockedSite(false), + _lastPageLoad(0) { - if (fullscreen) { + _settings.reloadInterval *= 1000; + if (_settings.fullscreen) { this->showFullScreen(); this->setWindowFlags(windowFlags() | Qt::WindowStaysOnTopHint); } @@ -40,12 +45,21 @@ SLXbrowser::SLXbrowser(QString url, bool fullscreen, bool ignoreSslErrors, int r connect(_browser, SIGNAL(loadProgress(int)), this, SLOT(loadProgress(int))); // QWebPage *page = _browser->page(); - QNetworkAccessManager *nam = new QNetworkAccessManager(this); + QNetworkAccessManager *nam; + if (_settings.urlList.isEmpty()) { + nam = new QNetworkAccessManager(this); + } else { + if (_settings.isWhitelist) { + // Just to be safe + _settings.urlList << _settings.url; + } + nam = new SlxNetworkAccessManager(urlListToRegExp(_settings.urlList), _settings.isWhitelist); + } connect(nam, SIGNAL(sslErrors(QNetworkReply*, const QList&)), this, SLOT(sslErrors(QNetworkReply*, const QList&))); connect(nam, SIGNAL(finished(QNetworkReply*)), this, SLOT(requestFinished(QNetworkReply*))); page->setNetworkAccessManager(nam); - page->mainFrame()->load(url); + page->mainFrame()->load(_settings.url); // _browser->show(); } @@ -57,8 +71,8 @@ SLXbrowser::~SLXbrowser() void SLXbrowser::loadStarted() { _reset.stop(); - if (_reloadIntervalMs > 0) { - _reset.start(_reloadIntervalMs + 10000); + if (_settings.reloadInterval > 0) { + _reset.start(_settings.reloadInterval + 10000); } _normalError.clear(); _sslErrors.clear(); @@ -69,37 +83,63 @@ void SLXbrowser::loadStarted() void SLXbrowser::loadFinished(bool ok) { _progress->hide(); - if (!_browser->wasAbortedDownload() && !_unsupportedUri && !ok) { - _browser->page()->mainFrame()->setHtml("

Page Load Error

");
-		QWebElement el = _browser->page()->mainFrame()->documentElement().findFirst("#content");
-		QString str;
-		if (!_sslErrors.empty()) {
-			str.append("SSL Errors:\n");
-			for (QSslError err : _sslErrors) {
-				str.append(err.errorString());
-				str.append('\n');
+	qint64 now = QDateTime::currentMSecsSinceEpoch();
+	if (!_browser->wasAbortedDownload() && !ok) {
+
+		if (_unsupportedUri) {
+			QMessageBox::warning(this, QString::fromUtf8("Denied"),
+					QString::fromUtf8("This URL type is not supported.\n\n"
+							"Diese Art Link wird nicht unterstützt.\n\n"
+							"(z.B. Mail)"));
+		} else if (_blockedSite) {
+			int numElems = _browser->page()->mainFrame()->documentElement().findAll("*").count();
+			if (now - _lastPageLoad < 500 && numElems < 15) {
+				// Was probably a JS redirect, go back before displaying the error
+				_browser->page()->triggerAction(QWebPage::Back);
 			}
-		} else if (_normalError.length() != 0) {
-			str.append("Load Error:\n");
-			str.append(_normalError);
+			QTimer::singleShot(5, [=]() {
+				QMessageBox::warning(this, QString::fromUtf8("Denied"),
+						QString::fromUtf8("Target URL not allowed.\n\n"
+								"Dieser Link führt auf eine nicht erlaubte Seite."));
+			});
+			/*
+			_browser->page()->mainFrame()->setHtml("

" + "

Zugriff verweigert

" + "

Diese URL wurde gefiltert.
" + "Zurück

" + ""); + */ } else { - str.append("Unknown Error"); + _browser->page()->mainFrame()->setHtml("

" + "

Page Load Error

" + ""); + QWebElement el = _browser->page()->mainFrame()->documentElement().findFirst("#content"); + QString str; + if (!_sslErrors.empty()) { + str.append("SSL Errors:\n"); + for (QSslError err : _sslErrors) { + str.append(err.errorString()); + str.append('\n'); + } + } else if (_normalError.length() != 0) { + str.append("Load Error:\n"); + str.append(_normalError); + } else { + str.append("Unknown Error"); + } + str.append("\n\n\n\n" + QDateTime::currentDateTime().toString()); + el.setPlainText(str); } - str.append("\n\n\n\n" + QDateTime::currentDateTime().toString()); - el.setPlainText(str); _sslErrors.clear(); _normalError.clear(); - _reset.start(30000); - } else if (_reloadIntervalMs > 0) { - _reset.start(_reloadIntervalMs); + _reset.start(qMin(30000, _settings.reloadInterval > 0 ? _settings.reloadInterval : 30000)); + } else if (_settings.reloadInterval > 0) { + _reset.start(_settings.reloadInterval); } - if (_unsupportedUri && !ok) { - QMessageBox::warning(this, QString::fromUtf8("Denied"), - QString::fromUtf8("This URL type is not supported.\n\n" - "Diese Art Link wird nicht unterstützt.\n\n" - "(z.B. Mail)")); - } + _unsupportedUri = false; + _blockedSite = false; + _lastPageLoad = now; } void SLXbrowser::loadProgress(int progress) @@ -109,7 +149,7 @@ void SLXbrowser::loadProgress(int progress) void SLXbrowser::sslErrors(QNetworkReply* reply, const QList& errors) { - if (_ignoreSslErrors) { + if (_settings.ignoreSslErrors) { reply->ignoreSslErrors(); return; } @@ -118,17 +158,48 @@ void SLXbrowser::sslErrors(QNetworkReply* reply, const QList& errors) void SLXbrowser::requestFinished(QNetworkReply *reply) { - if (reply->error() == QNetworkReply::NoError) { - _unsupportedUri = false; - } else if (reply->error() == QNetworkReply::ProtocolUnknownError) { + if (reply->error() == QNetworkReply::ProtocolUnknownError) { _unsupportedUri = true; + } else if (reply->error() == QNetworkReply::UnknownNetworkError) { + _blockedSite = true; } else { - qDebug() << reply->error(); + //qDebug() << reply->error(); _normalError = reply->errorString(); } } void SLXbrowser::reloadInitial() { - _browser->page()->mainFrame()->load(_url); + _browser->page()->mainFrame()->load(_settings.url); +} + +static QRegularExpression urlListToRegExp(const QStringList &list) +{ + // We search in the escaped string, so actually look for \*\* and \* + // Capture char before that because it must not be another backslash, as that + // means the star was already escaped in the list. + // Since these are C strings there are some additional backslashes here. + static const QRegularExpression STARSTAR("(^|[^\\\\])\\\\\\*\\\\\\*"); + static const QRegularExpression STAR("(^|[^\\\\])\\\\\\*"); + static const QRegularExpression QUEST("(^|[^\\\\])\\\\\\?"); + static const QString STARSTAR_REP("\\1.*"); + static const QString STAR_REP("\\1[^/]*"); + static const QString QUEST_REP("\\1.?"); + QStringList regexes; // All my regex's live in Regtexas + for (const QString &str : list) { + QString mangled; + if (str.contains(QLatin1String("//"))) { + mangled = str; + } else if (str.contains(QLatin1Char('/')) || str.contains(QLatin1String("**"))) { + mangled = "*//" + str; + } else { + mangled = "*//" + str + "/**"; + } + mangled = QRegularExpression::escape(mangled); + mangled = mangled.replace(STARSTAR, STARSTAR_REP).replace(STAR, STAR_REP) + .replace(QUEST, QUEST_REP); + regexes << mangled; + } + qDebug() << regexes; + return QRegularExpression("^(" + regexes.join('|') + ")$"); } -- cgit v1.2.3-55-g7522