Skip to content

Commit

Permalink
fix #1490 - add option to set per-feed HTTP headers
Browse files Browse the repository at this point in the history
  • Loading branch information
martinrotter committed Oct 16, 2024
1 parent 56d8144 commit f1d5c7d
Show file tree
Hide file tree
Showing 14 changed files with 211 additions and 20 deletions.
25 changes: 19 additions & 6 deletions src/librssguard-standard/src/gui/formstandardfeeddetails.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <librssguard/network-web/webfactory.h>
#include <librssguard/services/abstract/category.h>
#include <librssguard/services/abstract/gui/authenticationdetails.h>
#include <librssguard/services/abstract/gui/httpheadersdetails.h>
#include <librssguard/services/abstract/serviceroot.h>

#include <QComboBox>
Expand All @@ -27,9 +28,10 @@ FormStandardFeedDetails::FormStandardFeedDetails(ServiceRoot* service_root,
QWidget* parent)
: FormFeedDetails(service_root, parent), m_standardFeedDetails(new StandardFeedDetails(this)),
m_standardFeedExpDetails(new StandardFeedExpDetails(this)), m_authDetails(new AuthenticationDetails(false, this)),
m_parentToSelect(parent_to_select), m_urlToProcess(url) {
m_headersDetails(new HttpHeadersDetails(this)), m_parentToSelect(parent_to_select), m_urlToProcess(url) {
insertCustomTab(m_standardFeedDetails, tr("General"), 0);
insertCustomTab(m_authDetails, tr("Network"), 2);
insertCustomTab(m_headersDetails, tr("HTTP headers"), 2);
insertCustomTab(m_authDetails, tr("Auth"), 2);
insertCustomTab(m_standardFeedExpDetails, tr("Experimental"));
activateTab(0);

Expand All @@ -53,6 +55,7 @@ void FormStandardFeedDetails::guessFeed() {
m_authDetails->authenticationType(),
m_authDetails->username(),
m_authDetails->password(),
StandardFeed::httpHeadersToList(m_headersDetails->httpHeaders()),
m_serviceRoot->networkProxy());
}

Expand All @@ -63,6 +66,7 @@ void FormStandardFeedDetails::guessIconOnly() {
m_authDetails->authenticationType(),
m_authDetails->username(),
m_authDetails->password(),
StandardFeed::httpHeadersToList(m_headersDetails->httpHeaders()),
m_serviceRoot->networkProxy());
}

Expand Down Expand Up @@ -120,15 +124,19 @@ void FormStandardFeedDetails::apply() {
std_feed->setProtection(m_authDetails->authenticationType());
}

if (isChangeAllowed(m_standardFeedExpDetails->m_ui.m_mcbDontUseRawXml)) {
std_feed->setDontUseRawXmlSaving(m_standardFeedExpDetails->m_ui.m_cbDontUseRawXml->isChecked());
}

if (isChangeAllowed(m_authDetails->findChild<MultiFeedEditCheckBox*>(QSL("m_mcbAuthentication")))) {
std_feed->setUsername(m_authDetails->username());
std_feed->setPassword(m_authDetails->password());
}

if (isChangeAllowed(m_headersDetails->findChild<MultiFeedEditCheckBox*>(QSL("m_mcbHttpHeaders")))) {
std_feed->setHttpHeaders(m_headersDetails->httpHeaders());
}

if (isChangeAllowed(m_standardFeedExpDetails->m_ui.m_mcbDontUseRawXml)) {
std_feed->setDontUseRawXmlSaving(m_standardFeedExpDetails->m_ui.m_cbDontUseRawXml->isChecked());
}

std_feed->setCreationDate(QDateTime::currentDateTime());
std_feed->setLastEtag({});

Expand Down Expand Up @@ -177,6 +185,9 @@ void FormStandardFeedDetails::loadFeedData() {
m_authDetails->findChild<MultiFeedEditCheckBox*>(QSL("m_mcbAuthentication"))
->addActionWidget(m_authDetails->findChild<QGroupBox*>(QSL("m_gbAuthentication")));

m_headersDetails->findChild<MultiFeedEditCheckBox*>(QSL("m_mcbHttpHeaders"))
->addActionWidget(m_headersDetails->findChild<QPlainTextEdit*>(QSL("m_txtHttpHeaders")));

m_standardFeedDetails->m_ui.m_btnFetchMetadata->setEnabled(false);

m_standardFeedExpDetails->m_ui.m_mcbDontUseRawXml
Expand All @@ -198,6 +209,8 @@ void FormStandardFeedDetails::loadFeedData() {
m_authDetails->setUsername(std_feed->username());
m_authDetails->setPassword(std_feed->password());

m_headersDetails->loadHttpHeaders(std_feed->httpHeaders());

if (m_creatingNew) {
// auto processed_url = qApp->web()->processFeedUriScheme(m_urlToProcess);

Expand Down
2 changes: 2 additions & 0 deletions src/librssguard-standard/src/gui/formstandardfeeddetails.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

class StandardFeedDetails;
class StandardFeedExpDetails;
class HttpHeadersDetails;
class StandardServiceRoot;
class AuthenticationDetails;
class StandardFeed;
Expand Down Expand Up @@ -34,6 +35,7 @@ class FormStandardFeedDetails : public FormFeedDetails {
StandardFeedDetails* m_standardFeedDetails;
StandardFeedExpDetails* m_standardFeedExpDetails;
AuthenticationDetails* m_authDetails;
HttpHeadersDetails* m_headersDetails;
RootItem* m_parentToSelect;
QString m_urlToProcess;
};
Expand Down
4 changes: 4 additions & 0 deletions src/librssguard-standard/src/gui/standardfeeddetails.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ void StandardFeedDetails::guessIconOnly(StandardFeed::SourceType source_type,
NetworkFactory::NetworkAuthentication protection,
const QString& username,
const QString& password,
const QList<QPair<QByteArray, QByteArray>>& headers,
const QNetworkProxy& custom_proxy) {
try {
StandardFeed* metadata = StandardFeed::guessFeed(source_type,
Expand All @@ -152,6 +153,7 @@ void StandardFeedDetails::guessIconOnly(StandardFeed::SourceType source_type,
true,
username,
password,
{},
custom_proxy);

// Icon or whole feed was guessed.
Expand Down Expand Up @@ -186,6 +188,7 @@ void StandardFeedDetails::guessFeed(StandardFeed::SourceType source_type,
NetworkFactory::NetworkAuthentication protection,
const QString& username,
const QString& password,
const QList<QPair<QByteArray, QByteArray>>& headers,
const QNetworkProxy& custom_proxy) {
try {
StandardFeed* metadata = StandardFeed::guessFeed(source_type,
Expand All @@ -195,6 +198,7 @@ void StandardFeedDetails::guessFeed(StandardFeed::SourceType source_type,
true,
username,
password,
headers,
custom_proxy);

// Icon or whole feed was guessed.
Expand Down
3 changes: 3 additions & 0 deletions src/librssguard-standard/src/gui/standardfeeddetails.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,16 @@ class StandardFeedDetails : public QWidget {
NetworkFactory::NetworkAuthentication protection,
const QString& username,
const QString& password,
const QList<QPair<QByteArray, QByteArray>>& headers = {},
const QNetworkProxy& custom_proxy = QNetworkProxy::ProxyType::DefaultProxy);

void guessFeed(StandardFeed::SourceType source_type,
const QString& source,
const QString& post_process_script,
NetworkFactory::NetworkAuthentication protection,
const QString& username,
const QString& password,
const QList<QPair<QByteArray, QByteArray>>& headers = {},
const QNetworkProxy& custom_proxy = QNetworkProxy::ProxyType::DefaultProxy);

void onTitleChanged(const QString& new_title);
Expand Down
36 changes: 32 additions & 4 deletions src/librssguard-standard/src/standardfeed.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ StandardFeed::StandardFeed(RootItem* parent_item) : Feed(parent_item) {
m_protection = NetworkFactory::NetworkAuthentication::NoAuthentication;
m_username = QString();
m_password = QString();
m_httpHeaders = {};
m_dontUseRawXmlSaving = false;
}

Expand All @@ -64,6 +65,7 @@ StandardFeed::StandardFeed(const StandardFeed& other) : Feed(other) {
m_username = other.username();
m_password = other.password();
m_dontUseRawXmlSaving = other.dontUseRawXmlSaving();
m_httpHeaders = other.httpHeaders();
}

QList<QAction*> StandardFeed::contextMenuFeedsList() {
Expand Down Expand Up @@ -164,6 +166,7 @@ QVariantHash StandardFeed::customDatabaseData() const {
data[QSL("username")] = username();
data[QSL("password")] = TextFactory::encrypt(password());
data[QSL("dont_use_raw_xml_saving")] = dontUseRawXmlSaving();
data[QSL("http_headers")] = httpHeaders();

return data;
}
Expand All @@ -177,6 +180,7 @@ void StandardFeed::setCustomDatabaseData(const QVariantHash& data) {
setUsername(data[QSL("username")].toString());
setPassword(TextFactory::decrypt(data[QSL("password")].toString()));
setDontUseRawXmlSaving(data[QSL("dont_use_raw_xml_saving")].toBool());
setHttpHeaders(data[QSL("http_headers")].toHash());
}

QString StandardFeed::typeToString(StandardFeed::Type type) {
Expand Down Expand Up @@ -233,6 +237,7 @@ void StandardFeed::fetchMetadataForItself() {
true,
username(),
password(),
{},
getParentServiceRoot()->networkProxy());

// Copy metadata to our object.
Expand Down Expand Up @@ -281,14 +286,16 @@ StandardFeed* StandardFeed::guessFeed(StandardFeed::SourceType source_type,
bool fetch_icons,
const QString& username,
const QString& password,
const QList<QPair<QByteArray, QByteArray>>& http_headers,
const QNetworkProxy& custom_proxy) {
auto timeout = qApp->settings()->value(GROUP(Feeds), SETTING(Feeds::UpdateTimeout)).toInt();
QByteArray feed_contents;
QString content_type;

if (source_type == StandardFeed::SourceType::Url) {
QList<QPair<QByteArray, QByteArray>> headers = {
NetworkFactory::generateBasicAuthHeader(protection, username, password)};
QList<QPair<QByteArray, QByteArray>> headers = http_headers;
headers << NetworkFactory::generateBasicAuthHeader(protection, username, password);

NetworkResult network_result =
NetworkFactory::performNetworkOperation(source,
timeout,
Expand Down Expand Up @@ -392,8 +399,11 @@ StandardFeed* StandardFeed::guessFeed(StandardFeed::SourceType source_type,
// Try to obtain icon.
QPixmap icon_data;

if (NetworkFactory::downloadIcon(icon_possible_locations, DOWNLOAD_TIMEOUT, icon_data, {}, custom_proxy) ==
QNetworkReply::NetworkError::NoError) {
if (NetworkFactory::downloadIcon(icon_possible_locations,
DOWNLOAD_TIMEOUT,
icon_data,
http_headers,
custom_proxy) == QNetworkReply::NetworkError::NoError) {
// Icon for feed was downloaded and is stored now in icon_data.
feed->setIcon(icon_data);
}
Expand Down Expand Up @@ -433,6 +443,14 @@ bool StandardFeed::removeItself() {
return DatabaseQueries::deleteFeed(database, this, getParentServiceRoot()->accountId());
}

QVariantHash StandardFeed::httpHeaders() const {
return m_httpHeaders;
}

void StandardFeed::setHttpHeaders(const QVariantHash& http_headers) {
m_httpHeaders = http_headers;
}

bool StandardFeed::dontUseRawXmlSaving() const {
return m_dontUseRawXmlSaving;
}
Expand Down Expand Up @@ -547,6 +565,16 @@ QByteArray StandardFeed::runScriptProcess(const QStringList& cmd_args,
}
}

QList<QPair<QByteArray, QByteArray>> StandardFeed::httpHeadersToList(const QVariantHash& headers) {
QList<QPair<QByteArray, QByteArray>> hdrs_list;

for (auto i = headers.cbegin(), end = headers.cend(); i != end; i++) {
hdrs_list.append({i.key().toLocal8Bit(), i.value().toString().toLocal8Bit()});
}

return hdrs_list;
}

QByteArray StandardFeed::generateFeedFileWithScript(const QString& execution_line, int run_timeout) {
auto prepared_query = prepareExecutionLine(execution_line);

Expand Down
8 changes: 8 additions & 0 deletions src/librssguard-standard/src/standardfeed.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ class StandardFeed : public Feed {
bool fetch_icons = true,
const QString& username = {},
const QString& password = {},
const QList<QPair<QByteArray, QByteArray>>& http_headers = {},
const QNetworkProxy& custom_proxy = QNetworkProxy::ProxyType::DefaultProxy);

// Converts particular feed type to string.
Expand All @@ -104,6 +105,8 @@ class StandardFeed : public Feed {
bool provide_input,
const QString& input = {});

static QList<QPair<QByteArray, QByteArray>> httpHeadersToList(const QVariantHash& headers);

QString lastEtag() const;
void setLastEtag(const QString& etag);

Expand All @@ -113,6 +116,10 @@ class StandardFeed : public Feed {
bool dontUseRawXmlSaving() const;
void setDontUseRawXmlSaving(bool no_raw_xml_saving);

// NOTE: Contains hash table where key is name of HTTP header.
QVariantHash httpHeaders() const;
void setHttpHeaders(const QVariantHash& http_headers);

public slots:
void fetchMetadataForItself();

Expand All @@ -131,6 +138,7 @@ class StandardFeed : public Feed {
QString m_password;
QString m_lastEtag;
bool m_dontUseRawXmlSaving;
QVariantHash m_httpHeaders;
};

Q_DECLARE_METATYPE(StandardFeed::SourceType)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ bool FeedsImportExportModel::produceFeed(const FeedLookup& feed_lookup) {
!feed_lookup.do_not_fetch_icons,
{},
{},
{},
feed_lookup.custom_proxy);

new_feed->setSourceType(source_type);
Expand Down
2 changes: 1 addition & 1 deletion src/librssguard-standard/src/standardserviceroot.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ QList<Message> StandardServiceRoot::obtainNewMessages(Feed* feed,
if (f->sourceType() == StandardFeed::SourceType::Url) {
qDebugNN << LOGSEC_CORE << "Downloading URL" << QUOTE_W_SPACE(feed->source()) << "to obtain feed data.";

QList<QPair<QByteArray, QByteArray>> headers;
QList<QPair<QByteArray, QByteArray>> headers = StandardFeed::httpHeadersToList(f->httpHeaders());

headers << NetworkFactory::generateBasicAuthHeader(f->protection(), f->username(), f->password());

Expand Down
2 changes: 1 addition & 1 deletion src/librssguard-ttrss/src/gui/formttrssfeeddetails.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ void FormTtRssFeedDetails::loadFeedData() {

if (m_creatingNew) {
insertCustomTab(m_feedDetails, tr("General"), 0);
insertCustomTab(m_authDetails, tr("Network"), 1);
insertCustomTab(m_authDetails, tr("Auth"), 1);
activateTab(0);

m_feedDetails->loadCategories(m_serviceRoot->getSubTreeCategories(), m_serviceRoot, m_parentToSelect);
Expand Down
3 changes: 3 additions & 0 deletions src/librssguard/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,8 @@ set(SOURCES
services/abstract/gui/formcategorydetails.h
services/abstract/gui/formfeeddetails.cpp
services/abstract/gui/formfeeddetails.h
services/abstract/gui/httpheadersdetails.cpp
services/abstract/gui/httpheadersdetails.h
services/abstract/gui/multifeededitcheckbox.cpp
services/abstract/gui/multifeededitcheckbox.h
services/abstract/importantnode.cpp
Expand Down Expand Up @@ -371,6 +373,7 @@ set(UI_FILES
services/abstract/gui/formaddeditprobe.ui
services/abstract/gui/formcategorydetails.ui
services/abstract/gui/formfeeddetails.ui
services/abstract/gui/httpheadersdetails.ui
)

if(ENABLE_MEDIAPLAYER)
Expand Down
16 changes: 8 additions & 8 deletions src/librssguard/network-web/basenetworkaccessmanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,20 +73,20 @@ QNetworkReply* BaseNetworkAccessManager::createRequest(QNetworkAccessManager::Op
new_request.setRawHeader(HTTP_HEADERS_COOKIE, QSL("JSESSIONID= ").toLocal8Bit());

auto custom_ua = qApp->web()->customUserAgent();
auto existing_ua = new_request.rawHeader(QSL(HTTP_HEADERS_USER_AGENT));

if (custom_ua.isEmpty()) {
new_request.setRawHeader(HTTP_HEADERS_USER_AGENT, HTTP_COMPLETE_USERAGENT);
}
else {
new_request.setRawHeader(HTTP_HEADERS_USER_AGENT, custom_ua.toLocal8Bit());
if (existing_ua.isEmpty()) {
if (custom_ua.isEmpty()) {
new_request.setRawHeader(HTTP_HEADERS_USER_AGENT, HTTP_COMPLETE_USERAGENT);
}
else {
new_request.setRawHeader(HTTP_HEADERS_USER_AGENT, custom_ua.toLocal8Bit());
}
}

auto reply = QNetworkAccessManager::createRequest(op, new_request, outgoingData);

auto ssl_conf = reply->sslConfiguration();

auto aa = ssl_conf.backendConfiguration();

ssl_conf.setPeerVerifyMode(QSslSocket::PeerVerifyMode::VerifyNone);
ssl_conf.setSslOption(QSsl::SslOption::SslOptionDisableLegacyRenegotiation, false);

Expand Down
Loading

0 comments on commit f1d5c7d

Please sign in to comment.