mirror of
https://github.com/d47081/qBittorrent.git
synced 2025-01-11 23:37:59 +00:00
Merge pull request #12579 from Chocobo1/headers
Add ability to send custom HTTP headers
This commit is contained in:
commit
708b9b9c1b
@ -743,6 +743,26 @@ void Preferences::setWebUiRootFolder(const QString &path)
|
|||||||
setValue("Preferences/WebUI/RootFolder", path);
|
setValue("Preferences/WebUI/RootFolder", path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Preferences::isWebUICustomHTTPHeadersEnabled() const
|
||||||
|
{
|
||||||
|
return value("Preferences/WebUI/CustomHTTPHeadersEnabled", false).toBool();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Preferences::setWebUICustomHTTPHeadersEnabled(const bool enabled)
|
||||||
|
{
|
||||||
|
setValue("Preferences/WebUI/CustomHTTPHeadersEnabled", enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Preferences::getWebUICustomHTTPHeaders() const
|
||||||
|
{
|
||||||
|
return value("Preferences/WebUI/CustomHTTPHeaders").toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Preferences::setWebUICustomHTTPHeaders(const QString &headers)
|
||||||
|
{
|
||||||
|
setValue("Preferences/WebUI/CustomHTTPHeaders", headers);
|
||||||
|
}
|
||||||
|
|
||||||
bool Preferences::isDynDNSEnabled() const
|
bool Preferences::isDynDNSEnabled() const
|
||||||
{
|
{
|
||||||
return value("Preferences/DynDNS/Enabled", false).toBool();
|
return value("Preferences/DynDNS/Enabled", false).toBool();
|
||||||
|
@ -223,6 +223,12 @@ public:
|
|||||||
QString getWebUiRootFolder() const;
|
QString getWebUiRootFolder() const;
|
||||||
void setWebUiRootFolder(const QString &path);
|
void setWebUiRootFolder(const QString &path);
|
||||||
|
|
||||||
|
// WebUI custom HTTP headers
|
||||||
|
bool isWebUICustomHTTPHeadersEnabled() const;
|
||||||
|
void setWebUICustomHTTPHeadersEnabled(bool enabled);
|
||||||
|
QString getWebUICustomHTTPHeaders() const;
|
||||||
|
void setWebUICustomHTTPHeaders(const QString &headers);
|
||||||
|
|
||||||
// Dynamic DNS
|
// Dynamic DNS
|
||||||
bool isDynDNSEnabled() const;
|
bool isDynDNSEnabled() const;
|
||||||
void setDynDNSEnabled(bool enabled);
|
void setDynDNSEnabled(bool enabled);
|
||||||
|
@ -503,6 +503,8 @@ OptionsDialog::OptionsDialog(QWidget *parent)
|
|||||||
connect(m_ui->DNSPasswordTxt, &QLineEdit::textChanged, this, &ThisType::enableApplyButton);
|
connect(m_ui->DNSPasswordTxt, &QLineEdit::textChanged, this, &ThisType::enableApplyButton);
|
||||||
connect(m_ui->groupAltWebUI, &QGroupBox::toggled, this, &ThisType::enableApplyButton);
|
connect(m_ui->groupAltWebUI, &QGroupBox::toggled, this, &ThisType::enableApplyButton);
|
||||||
connect(m_ui->textWebUIRootFolder, &FileSystemPathLineEdit::selectedPathChanged, this, &ThisType::enableApplyButton);
|
connect(m_ui->textWebUIRootFolder, &FileSystemPathLineEdit::selectedPathChanged, this, &ThisType::enableApplyButton);
|
||||||
|
connect(m_ui->groupWebUIAddCustomHTTPHeaders, &QGroupBox::toggled, this, &ThisType::enableApplyButton);
|
||||||
|
connect(m_ui->textWebUICustomHTTPHeaders, &QPlainTextEdit::textChanged, this, &OptionsDialog::enableApplyButton);
|
||||||
#endif // DISABLE_WEBUI
|
#endif // DISABLE_WEBUI
|
||||||
|
|
||||||
// RSS tab
|
// RSS tab
|
||||||
@ -862,6 +864,9 @@ void OptionsDialog::saveOptions()
|
|||||||
// Alternative UI
|
// Alternative UI
|
||||||
pref->setAltWebUiEnabled(m_ui->groupAltWebUI->isChecked());
|
pref->setAltWebUiEnabled(m_ui->groupAltWebUI->isChecked());
|
||||||
pref->setWebUiRootFolder(m_ui->textWebUIRootFolder->selectedPath());
|
pref->setWebUiRootFolder(m_ui->textWebUIRootFolder->selectedPath());
|
||||||
|
// Custom HTTP headers
|
||||||
|
pref->setWebUICustomHTTPHeadersEnabled(m_ui->groupWebUIAddCustomHTTPHeaders->isChecked());
|
||||||
|
pref->setWebUICustomHTTPHeaders(m_ui->textWebUICustomHTTPHeaders->toPlainText());
|
||||||
}
|
}
|
||||||
// End Web UI
|
// End Web UI
|
||||||
// End preferences
|
// End preferences
|
||||||
@ -1242,6 +1247,9 @@ void OptionsDialog::loadOptions()
|
|||||||
|
|
||||||
m_ui->groupAltWebUI->setChecked(pref->isAltWebUiEnabled());
|
m_ui->groupAltWebUI->setChecked(pref->isAltWebUiEnabled());
|
||||||
m_ui->textWebUIRootFolder->setSelectedPath(pref->getWebUiRootFolder());
|
m_ui->textWebUIRootFolder->setSelectedPath(pref->getWebUiRootFolder());
|
||||||
|
// Custom HTTP headers
|
||||||
|
m_ui->groupWebUIAddCustomHTTPHeaders->setChecked(pref->isWebUICustomHTTPHeadersEnabled());
|
||||||
|
m_ui->textWebUICustomHTTPHeaders->setPlainText(pref->getWebUICustomHTTPHeaders());
|
||||||
// End Web UI preferences
|
// End Web UI preferences
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3220,6 +3220,28 @@ Use ';' to split multiple entries. Can use wildcard '*'.</string>
|
|||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="groupWebUIAddCustomHTTPHeaders">
|
||||||
|
<property name="title">
|
||||||
|
<string>Add custom HTTP headers</string>
|
||||||
|
</property>
|
||||||
|
<property name="checkable">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_8">
|
||||||
|
<item>
|
||||||
|
<widget class="QPlainTextEdit" name="textWebUICustomHTTPHeaders">
|
||||||
|
<property name="lineWrapMode">
|
||||||
|
<enum>QPlainTextEdit::NoWrap</enum>
|
||||||
|
</property>
|
||||||
|
<property name="placeholderText">
|
||||||
|
<string>Header: value pairs, one per line</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QGroupBox" name="checkDynDNS">
|
<widget class="QGroupBox" name="checkDynDNS">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
|
@ -243,6 +243,9 @@ void AppController::preferencesAction()
|
|||||||
data["web_ui_csrf_protection_enabled"] = pref->isWebUiCSRFProtectionEnabled();
|
data["web_ui_csrf_protection_enabled"] = pref->isWebUiCSRFProtectionEnabled();
|
||||||
data["web_ui_secure_cookie_enabled"] = pref->isWebUiSecureCookieEnabled();
|
data["web_ui_secure_cookie_enabled"] = pref->isWebUiSecureCookieEnabled();
|
||||||
data["web_ui_host_header_validation_enabled"] = pref->isWebUIHostHeaderValidationEnabled();
|
data["web_ui_host_header_validation_enabled"] = pref->isWebUIHostHeaderValidationEnabled();
|
||||||
|
// Custom HTTP headers
|
||||||
|
data["web_ui_use_custom_http_headers_enabled"] = pref->isWebUICustomHTTPHeadersEnabled();
|
||||||
|
data["web_ui_custom_http_headers"] = pref->getWebUICustomHTTPHeaders();
|
||||||
// Update my dynamic domain name
|
// Update my dynamic domain name
|
||||||
data["dyndns_enabled"] = pref->isDynDNSEnabled();
|
data["dyndns_enabled"] = pref->isDynDNSEnabled();
|
||||||
data["dyndns_service"] = pref->getDynDNSService();
|
data["dyndns_service"] = pref->getDynDNSService();
|
||||||
@ -480,7 +483,7 @@ void AppController::setPreferencesAction()
|
|||||||
if (hasKey("ip_filter_trackers"))
|
if (hasKey("ip_filter_trackers"))
|
||||||
session->setTrackerFilteringEnabled(it.value().toBool());
|
session->setTrackerFilteringEnabled(it.value().toBool());
|
||||||
if (hasKey("banned_IPs"))
|
if (hasKey("banned_IPs"))
|
||||||
session->setBannedIPs(it.value().toString().split('\n'));
|
session->setBannedIPs(it.value().toString().split('\n', QString::SkipEmptyParts));
|
||||||
|
|
||||||
// Speed
|
// Speed
|
||||||
// Global Rate Limits
|
// Global Rate Limits
|
||||||
@ -623,6 +626,11 @@ void AppController::setPreferencesAction()
|
|||||||
pref->setWebUiSecureCookieEnabled(it.value().toBool());
|
pref->setWebUiSecureCookieEnabled(it.value().toBool());
|
||||||
if (hasKey("web_ui_host_header_validation_enabled"))
|
if (hasKey("web_ui_host_header_validation_enabled"))
|
||||||
pref->setWebUIHostHeaderValidationEnabled(it.value().toBool());
|
pref->setWebUIHostHeaderValidationEnabled(it.value().toBool());
|
||||||
|
// Custom HTTP headers
|
||||||
|
if (hasKey("web_ui_use_custom_http_headers_enabled"))
|
||||||
|
pref->setWebUICustomHTTPHeadersEnabled(it.value().toBool());
|
||||||
|
if (hasKey("web_ui_custom_http_headers"))
|
||||||
|
pref->setWebUICustomHTTPHeaders(it.value().toString());
|
||||||
// Update my dynamic domain name
|
// Update my dynamic domain name
|
||||||
if (hasKey("dyndns_enabled"))
|
if (hasKey("dyndns_enabled"))
|
||||||
pref->setDynDNSEnabled(it.value().toBool());
|
pref->setDynDNSEnabled(it.value().toBool());
|
||||||
|
@ -347,6 +347,27 @@ void WebApplication::configure()
|
|||||||
: QLatin1String("default-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; script-src 'self' 'unsafe-inline'; object-src 'none'; form-action 'self';"))
|
: QLatin1String("default-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; script-src 'self' 'unsafe-inline'; object-src 'none'; form-action 'self';"))
|
||||||
+ (m_isClickjackingProtectionEnabled ? QLatin1String(" frame-ancestors 'self';") : QLatin1String(""))
|
+ (m_isClickjackingProtectionEnabled ? QLatin1String(" frame-ancestors 'self';") : QLatin1String(""))
|
||||||
+ (m_isHttpsEnabled ? QLatin1String(" upgrade-insecure-requests;") : QLatin1String(""));
|
+ (m_isHttpsEnabled ? QLatin1String(" upgrade-insecure-requests;") : QLatin1String(""));
|
||||||
|
|
||||||
|
m_useCustomHTTPHeaders = pref->isWebUICustomHTTPHeadersEnabled();
|
||||||
|
m_customHTTPHeaders.clear();
|
||||||
|
if (m_useCustomHTTPHeaders) {
|
||||||
|
const QString customHeaders = pref->getWebUICustomHTTPHeaders().trimmed();
|
||||||
|
const QVector<QStringRef> customHeaderLines = customHeaders.splitRef('\n', QString::SkipEmptyParts);
|
||||||
|
m_customHTTPHeaders.reserve(customHeaderLines.size());
|
||||||
|
|
||||||
|
for (const QStringRef &line : customHeaderLines) {
|
||||||
|
const int idx = line.indexOf(':');
|
||||||
|
if (idx < 0) {
|
||||||
|
// require separator `:` to be present even if `value` field can be empty
|
||||||
|
LogMsg(tr("Missing ':' separator in WebUI custom HTTP header: \"%1\"").arg(line.toString()), Log::WARNING);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString header = line.left(idx).trimmed().toString();
|
||||||
|
const QString value = line.mid(idx + 1).trimmed().toString();
|
||||||
|
m_customHTTPHeaders.push_back({header, value});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebApplication::registerAPIController(const QString &scope, APIController *controller)
|
void WebApplication::registerAPIController(const QString &scope, APIController *controller)
|
||||||
@ -451,6 +472,11 @@ Http::Response WebApplication::processRequest(const Http::Request &request, cons
|
|||||||
if (!m_contentSecurityPolicy.isEmpty())
|
if (!m_contentSecurityPolicy.isEmpty())
|
||||||
header(QLatin1String(Http::HEADER_CONTENT_SECURITY_POLICY), m_contentSecurityPolicy);
|
header(QLatin1String(Http::HEADER_CONTENT_SECURITY_POLICY), m_contentSecurityPolicy);
|
||||||
|
|
||||||
|
if (m_useCustomHTTPHeaders) {
|
||||||
|
for (const CustomHTTPHeader &customHeader : asConst(m_customHTTPHeaders))
|
||||||
|
header(customHeader.name, customHeader.value);
|
||||||
|
}
|
||||||
|
|
||||||
return response();
|
return response();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -157,4 +157,13 @@ private:
|
|||||||
bool m_isHostHeaderValidationEnabled;
|
bool m_isHostHeaderValidationEnabled;
|
||||||
bool m_isHttpsEnabled;
|
bool m_isHttpsEnabled;
|
||||||
QString m_contentSecurityPolicy;
|
QString m_contentSecurityPolicy;
|
||||||
|
|
||||||
|
// Custom HTTP headers
|
||||||
|
struct CustomHTTPHeader
|
||||||
|
{
|
||||||
|
QString name;
|
||||||
|
QString value;
|
||||||
|
};
|
||||||
|
bool m_useCustomHTTPHeaders;
|
||||||
|
QVector<CustomHTTPHeader> m_customHTTPHeaders;
|
||||||
};
|
};
|
||||||
|
@ -787,6 +787,14 @@
|
|||||||
</table>
|
</table>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
|
<fieldset class="settings">
|
||||||
|
<legend>
|
||||||
|
<input type="checkbox" id="webUIUseCustomHTTPHeadersCheckbox" onclick="qBittorrent.Preferences.updateWebUICustomHTTPHeadersSettings();" />
|
||||||
|
<label for="webUIUseCustomHTTPHeadersCheckbox">QBT_TR(Add custom HTTP headers)QBT_TR[CONTEXT=OptionsDialog]</label>
|
||||||
|
</legend>
|
||||||
|
<textarea id="webUICustomHTTPHeadersTextarea" placeholder="QBT_TR(Header: value pairs, one per line)QBT_TR[CONTEXT=OptionsDialog]" style="width: 90%;"></textarea>
|
||||||
|
</fieldset>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
<fieldset class="settings">
|
<fieldset class="settings">
|
||||||
@ -1139,6 +1147,7 @@
|
|||||||
updateBypasssAuthSettings: updateBypasssAuthSettings,
|
updateBypasssAuthSettings: updateBypasssAuthSettings,
|
||||||
updateAlternativeWebUISettings: updateAlternativeWebUISettings,
|
updateAlternativeWebUISettings: updateAlternativeWebUISettings,
|
||||||
updateHostHeaderValidationSettings: updateHostHeaderValidationSettings,
|
updateHostHeaderValidationSettings: updateHostHeaderValidationSettings,
|
||||||
|
updateWebUICustomHTTPHeadersSettings: updateWebUICustomHTTPHeadersSettings,
|
||||||
updateDynDnsSettings: updateDynDnsSettings,
|
updateDynDnsSettings: updateDynDnsSettings,
|
||||||
registerDynDns: registerDynDns,
|
registerDynDns: registerDynDns,
|
||||||
applyPreferences: applyPreferences
|
applyPreferences: applyPreferences
|
||||||
@ -1381,6 +1390,11 @@
|
|||||||
$('webui_domain_textarea').setProperty('disabled', !isHostHeaderValidationEnabled);
|
$('webui_domain_textarea').setProperty('disabled', !isHostHeaderValidationEnabled);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const updateWebUICustomHTTPHeadersSettings = function() {
|
||||||
|
const isEnabled = $('webUIUseCustomHTTPHeadersCheckbox').getProperty('checked');
|
||||||
|
$('webUICustomHTTPHeadersTextarea').setProperty('disabled', !isEnabled);
|
||||||
|
};
|
||||||
|
|
||||||
const updateDynDnsSettings = function() {
|
const updateDynDnsSettings = function() {
|
||||||
const isDynDnsEnabled = $('use_dyndns_checkbox').getProperty('checked');
|
const isDynDnsEnabled = $('use_dyndns_checkbox').getProperty('checked');
|
||||||
$('dyndns_select').setProperty('disabled', !isDynDnsEnabled);
|
$('dyndns_select').setProperty('disabled', !isDynDnsEnabled);
|
||||||
@ -1737,6 +1751,11 @@
|
|||||||
$('host_header_validation_checkbox').setProperty('checked', pref.web_ui_host_header_validation_enabled);
|
$('host_header_validation_checkbox').setProperty('checked', pref.web_ui_host_header_validation_enabled);
|
||||||
updateHostHeaderValidationSettings();
|
updateHostHeaderValidationSettings();
|
||||||
|
|
||||||
|
// Custom HTTP headers
|
||||||
|
$('webUIUseCustomHTTPHeadersCheckbox').setProperty('checked', pref.web_ui_use_custom_http_headers_enabled);
|
||||||
|
$('webUICustomHTTPHeadersTextarea').setProperty('value', pref.web_ui_custom_http_headers);
|
||||||
|
updateWebUICustomHTTPHeadersSettings();
|
||||||
|
|
||||||
// Update my dynamic domain name
|
// Update my dynamic domain name
|
||||||
$('use_dyndns_checkbox').setProperty('checked', pref.dyndns_enabled);
|
$('use_dyndns_checkbox').setProperty('checked', pref.dyndns_enabled);
|
||||||
$('dyndns_select').setProperty('value', pref.dyndns_service);
|
$('dyndns_select').setProperty('value', pref.dyndns_service);
|
||||||
@ -2100,11 +2119,16 @@
|
|||||||
settings.set('alternative_webui_enabled', alternative_webui_enabled);
|
settings.set('alternative_webui_enabled', alternative_webui_enabled);
|
||||||
settings.set('alternative_webui_path', webui_files_location_textarea);
|
settings.set('alternative_webui_path', webui_files_location_textarea);
|
||||||
|
|
||||||
|
// Security
|
||||||
settings.set('web_ui_clickjacking_protection_enabled', $('clickjacking_protection_checkbox').getProperty('checked'));
|
settings.set('web_ui_clickjacking_protection_enabled', $('clickjacking_protection_checkbox').getProperty('checked'));
|
||||||
settings.set('web_ui_csrf_protection_enabled', $('csrf_protection_checkbox').getProperty('checked'));
|
settings.set('web_ui_csrf_protection_enabled', $('csrf_protection_checkbox').getProperty('checked'));
|
||||||
settings.set('web_ui_secure_cookie_enabled', $('secureCookieCheckbox').getProperty('checked'));
|
settings.set('web_ui_secure_cookie_enabled', $('secureCookieCheckbox').getProperty('checked'));
|
||||||
settings.set('web_ui_host_header_validation_enabled', $('host_header_validation_checkbox').getProperty('checked'));
|
settings.set('web_ui_host_header_validation_enabled', $('host_header_validation_checkbox').getProperty('checked'));
|
||||||
|
|
||||||
|
// Custom HTTP headers
|
||||||
|
settings.set('web_ui_use_custom_http_headers_enabled', $('webUIUseCustomHTTPHeadersCheckbox').getProperty('checked'));
|
||||||
|
settings.set('web_ui_custom_http_headers', $('webUICustomHTTPHeadersTextarea').getProperty('value'));
|
||||||
|
|
||||||
// Update my dynamic domain name
|
// Update my dynamic domain name
|
||||||
settings.set('dyndns_enabled', $('use_dyndns_checkbox').getProperty('checked'));
|
settings.set('dyndns_enabled', $('use_dyndns_checkbox').getProperty('checked'));
|
||||||
settings.set('dyndns_service', $('dyndns_select').getProperty('value'));
|
settings.set('dyndns_service', $('dyndns_select').getProperty('value'));
|
||||||
|
Loading…
Reference in New Issue
Block a user