diff --git a/src/librssguard/CMakeLists.txt b/src/librssguard/CMakeLists.txt index 848442237..b5fafe424 100644 --- a/src/librssguard/CMakeLists.txt +++ b/src/librssguard/CMakeLists.txt @@ -261,6 +261,8 @@ set(SOURCES network-web/downloadmanager.h network-web/googlesuggest.cpp network-web/googlesuggest.h + network-web/apiserver.cpp + network-web/apiserver.h network-web/httpresponse.cpp network-web/httpresponse.h network-web/httpserver.cpp diff --git a/src/librssguard/gui/settings/settingsbrowsermail.cpp b/src/librssguard/gui/settings/settingsbrowsermail.cpp index 1088465a5..8b799219f 100644 --- a/src/librssguard/gui/settings/settingsbrowsermail.cpp +++ b/src/librssguard/gui/settings/settingsbrowsermail.cpp @@ -41,6 +41,7 @@ SettingsBrowserMail::SettingsBrowserMail(Settings* settings, QWidget* parent) m_ui->m_listTools->header()->setSectionResizeMode(0, QHeaderView::ResizeMode::ResizeToContents); connect(m_ui->m_cbEnableHttp2, &QCheckBox::stateChanged, this, &SettingsBrowserMail::dirtifySettings); + connect(m_ui->m_cbEnableApiServer, &QCheckBox::stateChanged, this, &SettingsBrowserMail::dirtifySettings); connect(m_ui->m_cbIgnoreAllCookies, &QCheckBox::stateChanged, this, &SettingsBrowserMail::dirtifySettings); connect(m_ui->m_checkOpenLinksInExternal, &QCheckBox::stateChanged, this, &SettingsBrowserMail::dirtifySettings); connect(m_proxyDetails, &NetworkProxyDetails::changed, this, &SettingsBrowserMail::dirtifySettings); @@ -172,6 +173,7 @@ void SettingsBrowserMail::loadSettings() { m_ui->m_cbDisableCache->setChecked(settings()->value(GROUP(Browser), SETTING(Browser::DisableCache)).toBool()); m_ui->m_cbEnableHttp2->setChecked(settings()->value(GROUP(Network), SETTING(Network::EnableHttp2)).toBool()); + m_ui->m_cbEnableApiServer->setChecked(settings()->value(GROUP(Network), SETTING(Network::EnableApiServer)).toBool()); m_ui->m_cbIgnoreAllCookies ->setChecked(settings()->value(GROUP(Network), SETTING(Network::IgnoreAllCookies)).toBool()); m_ui->m_checkOpenLinksInExternal @@ -218,8 +220,15 @@ void SettingsBrowserMail::saveSettings() { settings()->setValue(GROUP(Browser), Browser::DisableCache, m_ui->m_cbDisableCache->isChecked()); settings()->setValue(GROUP(Network), Network::EnableHttp2, m_ui->m_cbEnableHttp2->isChecked()); + settings()->setValue(GROUP(Network), Network::EnableApiServer, m_ui->m_cbEnableApiServer->isChecked()); settings()->setValue(GROUP(Network), Network::IgnoreAllCookies, m_ui->m_cbIgnoreAllCookies->isChecked()); + qApp->web()->stopApiServer(); + + if (m_ui->m_cbEnableApiServer->isChecked()) { + qApp->web()->startApiServer(); + } + settings()->setValue(GROUP(Browser), Browser::OpenLinksInExternalBrowserRightAway, m_ui->m_checkOpenLinksInExternal->isChecked()); diff --git a/src/librssguard/gui/settings/settingsbrowsermail.ui b/src/librssguard/gui/settings/settingsbrowsermail.ui index f44a57ff3..a7862e0a4 100644 --- a/src/librssguard/gui/settings/settingsbrowsermail.ui +++ b/src/librssguard/gui/settings/settingsbrowsermail.ui @@ -35,6 +35,13 @@ + + + + Enable API server + + + diff --git a/src/librssguard/miscellaneous/settings.cpp b/src/librssguard/miscellaneous/settings.cpp index 84384867a..ef9dc8525 100644 --- a/src/librssguard/miscellaneous/settings.cpp +++ b/src/librssguard/miscellaneous/settings.cpp @@ -57,6 +57,9 @@ DKEY Network::ID = "network"; DKEY Network::SendDNT = "send_dnt"; VALUE(bool) Network::SendDNTDef = false; +DKEY Network::EnableApiServer = "api_server"; +VALUE(bool) Network::EnableApiServerDef = false; + DKEY Network::EnableHttp2 = "http2_enabled"; DVALUE(bool) Network::EnableHttp2Def = false; diff --git a/src/librssguard/miscellaneous/settings.h b/src/librssguard/miscellaneous/settings.h index 2f16321c5..23a774ebb 100644 --- a/src/librssguard/miscellaneous/settings.h +++ b/src/librssguard/miscellaneous/settings.h @@ -372,6 +372,9 @@ namespace Network { KEY SendDNT; VALUE(bool) SendDNTDef; + KEY EnableApiServer; + VALUE(bool) EnableApiServerDef; + KEY EnableHttp2; VALUE(bool) EnableHttp2Def; diff --git a/src/librssguard/network-web/apiserver.cpp b/src/librssguard/network-web/apiserver.cpp new file mode 100644 index 000000000..27e408317 --- /dev/null +++ b/src/librssguard/network-web/apiserver.cpp @@ -0,0 +1,23 @@ +// For license of this file, see /LICENSE.md. + +#include "network-web/apiserver.h" + +#include "definitions/definitions.h" + +ApiServer::ApiServer(QObject* parent) : HttpServer(parent) {} + +void ApiServer::answerClient(QTcpSocket* socket, const QHttpRequest& request) { + QByteArray incoming_data = socket->readAll(); + + const QByteArray output_data = incoming_data; + const QByteArray reply_message = QSL("HTTP/1.0 200 OK \r\n" + "Content-Type: application/json; charset=\"utf-8\"\r\n" + "Content-Length: %1" + "\r\n\r\n" + "%2") + .arg(QString::number(output_data.size()), output_data) + .toLocal8Bit(); + + socket->write(reply_message); + socket->disconnectFromHost(); +} diff --git a/src/librssguard/network-web/apiserver.h b/src/librssguard/network-web/apiserver.h new file mode 100644 index 000000000..e9bff3716 --- /dev/null +++ b/src/librssguard/network-web/apiserver.h @@ -0,0 +1,16 @@ +// For license of this file, see /LICENSE.md. + +#ifndef APISERVER_H +#define APISERVER_H + +#include "network-web/httpserver.h" + +class ApiServer : public HttpServer { + public: + explicit ApiServer(QObject* parent = nullptr); + + protected: + virtual void answerClient(QTcpSocket* socket, const QHttpRequest& request); +}; + +#endif // APISERVER_H diff --git a/src/librssguard/network-web/oauthhttphandler.cpp b/src/librssguard/network-web/oauthhttphandler.cpp index 0f7d15ebd..d5c42062f 100644 --- a/src/librssguard/network-web/oauthhttphandler.cpp +++ b/src/librssguard/network-web/oauthhttphandler.cpp @@ -62,11 +62,13 @@ void OAuthHttpHandler::answerClient(QTcpSocket* socket, const QHttpRequest& requ const QString html = QSL("") + qApp->applicationName() + QSL("") + m_successText + QSL(""); const QByteArray html_utf = html.toUtf8(); - const QByteArray html_size = QString::number(html_utf.size()).toLocal8Bit(); - const QByteArray reply_message = QByteArrayLiteral("HTTP/1.0 200 OK \r\n" - "Content-Type: text/html; charset=\"utf-8\"\r\n" - "Content-Length: ") + - html_size + QByteArrayLiteral("\r\n\r\n") + html_utf; + const QByteArray reply_message = QSL("HTTP/1.0 200 OK \r\n" + "Content-Type: text/html; charset=\"utf-8\"\r\n" + "Content-Length: %1" + "\r\n\r\n" + "%2") + .arg(QString::number(html_utf.size()), html_utf) + .toLocal8Bit(); socket->write(reply_message); } diff --git a/src/librssguard/network-web/webfactory.cpp b/src/librssguard/network-web/webfactory.cpp index 21ceb1ea9..b6e842147 100644 --- a/src/librssguard/network-web/webfactory.cpp +++ b/src/librssguard/network-web/webfactory.cpp @@ -7,6 +7,7 @@ #include "miscellaneous/iconfactory.h" #include "miscellaneous/settings.h" #include "network-web/adblock/adblockmanager.h" +#include "network-web/apiserver.h" #include "network-web/cookiejar.h" #include "network-web/readability.h" @@ -28,9 +29,13 @@ #include #endif -WebFactory::WebFactory(QObject* parent) : QObject(parent), m_customUserAgent(QString()) { +WebFactory::WebFactory(QObject* parent) : QObject(parent), m_apiServer(nullptr), m_customUserAgent(QString()) { m_adBlock = new AdBlockManager(this); + if (qApp->settings()->value(GROUP(Network), SETTING(Network::EnableApiServer)).toBool()) { + startApiServer(); + } + #if defined(NO_LITE) if (qApp->settings()->value(GROUP(Browser), SETTING(Browser::DisableCache)).toBool()) { qWarningNN << LOGSEC_NETWORK << "Using off-the-record WebEngine profile."; @@ -58,6 +63,8 @@ WebFactory::WebFactory(QObject* parent) : QObject(parent), m_customUserAgent(QSt } WebFactory::~WebFactory() { + stopApiServer(); + #if defined(NO_LITE) if (m_engineSettings != nullptr && m_engineSettings->menu() != nullptr) { m_engineSettings->menu()->deleteLater(); @@ -558,6 +565,22 @@ Readability* WebFactory::readability() const { return m_readability; } +void WebFactory::startApiServer() { + m_apiServer = new ApiServer(this); + m_apiServer->setListenAddressPort(QSL("http://localhost:54123"), true); + + qDebugNN << LOGSEC_NETWORK << "Started API server:" << QUOTE_W_SPACE_DOT(m_apiServer->listenAddressPort()); +} + +void WebFactory::stopApiServer() { + if (m_apiServer != nullptr) { + delete m_apiServer; + m_apiServer = nullptr; + + qDebugNN << LOGSEC_NETWORK << "Stopped API server:" << QUOTE_W_SPACE_DOT(m_apiServer->listenAddressPort()); + } +} + void WebFactory::generateUnescapes() { m_htmlNamedEntities[QSL("AElig")] = 0x00c6; m_htmlNamedEntities[QSL("AMP")] = 38; diff --git a/src/librssguard/network-web/webfactory.h b/src/librssguard/network-web/webfactory.h index eaa344b0d..d68f1bd57 100644 --- a/src/librssguard/network-web/webfactory.h +++ b/src/librssguard/network-web/webfactory.h @@ -20,6 +20,7 @@ class NetworkUrlInterceptor; class QMenu; class AdBlockManager; class CookieJar; +class ApiServer; class Readability; class WebFactory : public QObject { @@ -52,6 +53,9 @@ class WebFactory : public QObject { CookieJar* cookieJar() const; Readability* readability() const; + void startApiServer(); + void stopApiServer(); + void updateProxy(); bool sendMessageViaEmail(const Message& message); @@ -90,6 +94,7 @@ class WebFactory : public QObject { QAction* m_engineSettings; #endif + ApiServer* m_apiServer; CookieJar* m_cookieJar; Readability* m_readability; QMap m_htmlNamedEntities;