// This file is part of RSS Guard. // // Copyright (C) 2011-2017 by Martin Rotter // // RSS Guard 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. // // RSS Guard 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 RSS Guard. If not, see . #include "network-web/webfactory.h" #include "miscellaneous/application.h" #include "miscellaneous/iconfactory.h" #include #include #include #include #if defined (USE_WEBENGINE) #include #endif WebFactory::WebFactory(QObject* parent) : QObject(parent), m_escapes(QMap()), m_deEscapes(QMap()) { #if defined (USE_WEBENGINE) m_engineSettings = nullptr; #endif } WebFactory::~WebFactory() { #if defined (USE_WEBENGINE) if (m_engineSettings != nullptr && m_engineSettings->menu() != nullptr) { m_engineSettings->menu()->deleteLater(); } #endif } bool WebFactory::sendMessageViaEmail(const Message& message) { if (qApp->settings()->value(GROUP(Browser), SETTING(Browser::CustomExternalEmailEnabled)).toBool()) { const QString browser = qApp->settings()->value(GROUP(Browser), SETTING(Browser::CustomExternalEmailExecutable)).toString(); const QString arguments = qApp->settings()->value(GROUP(Browser), SETTING(Browser::CustomExternalEmailArguments)).toString(); return QProcess::startDetached(QString("\"") + browser + QSL("\" ") + arguments.arg(message.m_title, stripTags(message.m_contents))); } else { // Send it via mailto protocol. // NOTE: http://en.wikipedia.org/wiki/Mailto return QDesktopServices::openUrl(QString("mailto:?subject=%1&body=%2").arg(QString(QUrl::toPercentEncoding(message.m_title)), QString(QUrl::toPercentEncoding(stripTags(message.m_contents))))); } } bool WebFactory::openUrlInExternalBrowser(const QString& url) { if (qApp->settings()->value(GROUP(Browser), SETTING(Browser::CustomExternalBrowserEnabled)).toBool()) { const QString browser = qApp->settings()->value(GROUP(Browser), SETTING(Browser::CustomExternalBrowserExecutable)).toString(); const QString arguments = qApp->settings()->value(GROUP(Browser), SETTING(Browser::CustomExternalBrowserArguments)).toString(); const QString call_line = "\"" + browser + "\" \"" + arguments.arg(url) + "\""; qDebug("Running command '%s'.", qPrintable(call_line)); const bool result = QProcess::startDetached(call_line); if (!result) { qDebug("External web browser call failed."); } return result; } else { return QDesktopServices::openUrl(url); } } QString WebFactory::stripTags(QString text) { return text.remove(QRegExp(QSL("<[^>]*>"))); } QString WebFactory::escapeHtml(const QString& html) { if (m_escapes.isEmpty()) { genereteEscapes(); } QString output = html; QMapIterator i(m_escapes); while (i.hasNext()) { i.next(); output = output.replace(i.key(), i.value()); } return output; } QString WebFactory::deEscapeHtml(const QString& text) { if (m_deEscapes.isEmpty()) { generateDeescapes(); } QString output = text; QMapIterator i(m_deEscapes); while (i.hasNext()) { i.next(); output = output.replace(i.key(), i.value()); } return output; } QString WebFactory::toSecondLevelDomain(const QUrl& url) { const QString top_level_domain = url.topLevelDomain(); const QString url_host = url.host(); if (top_level_domain.isEmpty() || url_host.isEmpty()) { return QString(); } QString domain = url_host.left(url_host.size() - top_level_domain.size()); if (domain.count(QL1C('.')) == 0) { return url_host; } while (domain.count(QL1C('.')) != 0) { domain = domain.mid(domain.indexOf(QL1C('.')) + 1); } return domain + top_level_domain; } #if defined (USE_WEBENGINE) QAction* WebFactory::engineSettingsAction() { if (m_engineSettings == nullptr) { m_engineSettings = new QAction(qApp->icons()->fromTheme(QSL("applications-internet")), tr("Web engine settings"), this); m_engineSettings->setMenu(new QMenu()); createMenu(m_engineSettings->menu()); connect(m_engineSettings->menu(), SIGNAL(aboutToShow()), this, SLOT(createMenu())); } return m_engineSettings; } void WebFactory::createMenu(QMenu* menu) { if (menu == nullptr) { menu = qobject_cast(sender()); if (menu == nullptr) { return; } } menu->clear(); QList actions; actions << createEngineSettingsAction(tr("Auto-load images"), QWebEngineSettings::AutoLoadImages); actions << createEngineSettingsAction(tr("JS enabled"), QWebEngineSettings::JavascriptEnabled); actions << createEngineSettingsAction(tr("JS can open popup windows"), QWebEngineSettings::JavascriptCanOpenWindows); actions << createEngineSettingsAction(tr("JS can access clipboard"), QWebEngineSettings::JavascriptCanAccessClipboard); actions << createEngineSettingsAction(tr("Hyperlinks can get focus"), QWebEngineSettings::LinksIncludedInFocusChain); actions << createEngineSettingsAction(tr("Local storage enabled"), QWebEngineSettings::LocalStorageEnabled); actions << createEngineSettingsAction(tr("Local content can access remote URLs"), QWebEngineSettings::LocalContentCanAccessRemoteUrls); actions << createEngineSettingsAction(tr("XSS auditing enabled"), QWebEngineSettings::XSSAuditingEnabled); actions << createEngineSettingsAction(tr("Spatial navigation enabled"), QWebEngineSettings::SpatialNavigationEnabled); actions << createEngineSettingsAction(tr("Local content can access local files"), QWebEngineSettings::LocalContentCanAccessFileUrls); actions << createEngineSettingsAction(tr("Hyperlink auditing enabled"), QWebEngineSettings::HyperlinkAuditingEnabled); actions << createEngineSettingsAction(tr("Animate scrolling"), QWebEngineSettings::ScrollAnimatorEnabled); actions << createEngineSettingsAction(tr("Error pages enabled"), QWebEngineSettings::ErrorPageEnabled); actions << createEngineSettingsAction(tr("Plugins enabled"), QWebEngineSettings::PluginsEnabled); actions << createEngineSettingsAction(tr("Fullscreen enabled"), QWebEngineSettings::FullScreenSupportEnabled); actions << createEngineSettingsAction(tr("Screen capture enabled"), QWebEngineSettings::ScreenCaptureEnabled); actions << createEngineSettingsAction(tr("WebGL enabled"), QWebEngineSettings::WebGLEnabled); actions << createEngineSettingsAction(tr("Accelerate 2D canvas"), QWebEngineSettings::Accelerated2dCanvasEnabled); actions << createEngineSettingsAction(tr("Print element backgrounds"), QWebEngineSettings::PrintElementBackgrounds); actions << createEngineSettingsAction(tr("Allow running insecure content"), QWebEngineSettings::AllowRunningInsecureContent); #if !defined(Q_OS_LINUX) actions << createEngineSettingsAction(tr("Allow geolocation on insecure origins"), QWebEngineSettings::AllowGeolocationOnInsecureOrigins); #endif menu->addActions(actions); } void WebFactory::webEngineSettingChanged(bool enabled) { const QAction* const act = qobject_cast(sender()); QWebEngineSettings::WebAttribute attribute = static_cast(act->data().toInt()); qApp->settings()->setValue(WebEngineAttributes::ID, QString::number(static_cast(attribute)), enabled); QWebEngineProfile::defaultProfile()->settings()->setAttribute(attribute, act->isChecked()); } QAction* WebFactory::createEngineSettingsAction(const QString& title, QWebEngineSettings::WebAttribute attribute) { QAction* act = new QAction(title, m_engineSettings->menu()); act->setData(attribute); act->setCheckable(true); act->setChecked(qApp->settings()->value(WebEngineAttributes::ID, QString::number(static_cast(attribute)), true).toBool()); QWebEngineProfile::defaultProfile()->settings()->setAttribute(attribute, act->isChecked()); connect(act, &QAction::toggled, this, &WebFactory::webEngineSettingChanged); return act; } #endif void WebFactory::genereteEscapes() { m_escapes[QSL("<")] = QL1C('<'); m_escapes[QSL(">")] = QL1C('>'); m_escapes[QSL("&")] = QL1C('&'); m_escapes[QSL(""")] = QL1C('\"'); m_escapes[QSL(" ")] = QL1C(' '); m_escapes[QSL("±")] = QSL("±"); m_escapes[QSL("×")] = QSL("×"); m_escapes[QSL("'")] = QL1C('\''); } void WebFactory::generateDeescapes() { m_deEscapes[QSL("<")] = QSL("<"); m_deEscapes[QSL(">")] = QSL(">"); m_deEscapes[QSL("&")] = QSL("&"); m_deEscapes[QSL("\"")] = QSL("""); m_deEscapes[QSL("±")] = QSL("±"); m_deEscapes[QSL("×")] = QSL("×"); m_deEscapes[QSL("\'")] = QSL("'"); }