Add manual proxy configuration
This implementation is based on the one from neochat and tokodon, but it fixes the "system default" option and adds a "no proxy" option. Most of these settings now also cover streaming audio through the different backends. FEATURE: 467490
This commit is contained in:
parent
014cf66898
commit
755014f570
@ -15,6 +15,7 @@
|
||||
#include <QFile>
|
||||
#include <QFileInfo>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QNetworkProxy>
|
||||
#include <QNetworkProxyFactory>
|
||||
#include <QNetworkReply>
|
||||
#include <QTime>
|
||||
@ -43,7 +44,14 @@ Fetcher::Fetcher()
|
||||
manager->setStrictTransportSecurityEnabled(true);
|
||||
manager->enableStrictTransportSecurityStore(true);
|
||||
|
||||
QNetworkProxyFactory::setUseSystemConfiguration(true);
|
||||
// First save the original system proxy settings
|
||||
m_systemHttpProxy = qgetenv("http_proxy");
|
||||
m_systemHttpsProxy = qgetenv("https_proxy");
|
||||
m_isSystemProxyDefined = (QNetworkProxy::applicationProxy().type() != QNetworkProxy::ProxyType::NoProxy);
|
||||
qCDebug(kastsFetcher) << "saved system proxy:" << m_systemHttpProxy << m_systemHttpsProxy << m_isSystemProxyDefined;
|
||||
|
||||
// Set network proxy based on saved settings
|
||||
setNetworkProxy();
|
||||
|
||||
// setup update timer if required
|
||||
initializeUpdateTimer();
|
||||
@ -286,3 +294,84 @@ void Fetcher::checkUpdateTimer()
|
||||
qCDebug(kastsFetcher) << "new auto feed update trigger set to" << m_updateTriggerTime;
|
||||
}
|
||||
}
|
||||
|
||||
void Fetcher::setNetworkProxy()
|
||||
{
|
||||
SettingsManager *settings = SettingsManager::self();
|
||||
QNetworkProxy proxy;
|
||||
|
||||
// define network proxy environment variable
|
||||
// this is needed for the audio backends which don't obey qt's settings
|
||||
QByteArray appProxy;
|
||||
if (!settings->proxyUser().isEmpty()) {
|
||||
appProxy += QUrl::toPercentEncoding(settings->proxyUser());
|
||||
if (!settings->proxyPassword().isEmpty()) {
|
||||
appProxy += ":" + QUrl::toPercentEncoding(settings->proxyPassword());
|
||||
}
|
||||
appProxy += "@";
|
||||
}
|
||||
appProxy += settings->proxyHost().toLocal8Bit() + ":" + QByteArray::number(settings->proxyPort());
|
||||
|
||||
// type match to ProxyType from config.ksettings
|
||||
switch (settings->proxyType()) {
|
||||
case 1: // No Proxy
|
||||
proxy.setType(QNetworkProxy::NoProxy);
|
||||
QNetworkProxy::setApplicationProxy(proxy);
|
||||
|
||||
// also reset environment variables if they have been set
|
||||
qunsetenv("http_proxy");
|
||||
qunsetenv("https_proxy");
|
||||
break;
|
||||
case 2: // HTTP
|
||||
proxy.setType(QNetworkProxy::HttpProxy);
|
||||
proxy.setHostName(settings->proxyHost());
|
||||
proxy.setPort(settings->proxyPort());
|
||||
proxy.setUser(settings->proxyUser());
|
||||
proxy.setPassword(settings->proxyPassword());
|
||||
QNetworkProxy::setApplicationProxy(proxy);
|
||||
|
||||
// also set it through environment variables for the audio backends
|
||||
appProxy.prepend("http://");
|
||||
qputenv("http_proxy", appProxy);
|
||||
qputenv("https_proxy", appProxy);
|
||||
qCDebug(kastsFetcher) << "appProxy environment variable" << appProxy;
|
||||
break;
|
||||
case 3: // SOCKS 5
|
||||
proxy.setType(QNetworkProxy::Socks5Proxy);
|
||||
proxy.setHostName(settings->proxyHost());
|
||||
proxy.setPort(settings->proxyPort());
|
||||
proxy.setUser(settings->proxyUser());
|
||||
proxy.setPassword(settings->proxyPassword());
|
||||
QNetworkProxy::setApplicationProxy(proxy);
|
||||
|
||||
// also set it through environment variables for the audio backends
|
||||
appProxy.prepend("socks5://");
|
||||
qputenv("http_proxy", appProxy);
|
||||
qputenv("https_proxy", appProxy);
|
||||
qCDebug(kastsFetcher) << "appProxy environment variable" << appProxy;
|
||||
break;
|
||||
case 0: // System Default
|
||||
default:
|
||||
QNetworkProxyFactory::setUseSystemConfiguration(true);
|
||||
|
||||
// also reset env variables that might have been overridden
|
||||
if (!m_systemHttpProxy.isEmpty()) {
|
||||
qputenv("http_proxy", m_systemHttpProxy);
|
||||
} else {
|
||||
qunsetenv("http_proxy");
|
||||
}
|
||||
if (!m_systemHttpProxy.isEmpty()) {
|
||||
qputenv("https_proxy", m_systemHttpsProxy);
|
||||
} else {
|
||||
qunsetenv("https_proxy");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
qCDebug(kastsFetcher) << "Network proxy set to:" << QNetworkProxy::applicationProxy();
|
||||
}
|
||||
|
||||
bool Fetcher::isSystemProxyDefined()
|
||||
{
|
||||
return m_isSystemProxyDefined;
|
||||
}
|
||||
|
@ -55,6 +55,9 @@ public:
|
||||
void initializeUpdateTimer();
|
||||
void checkUpdateTimer();
|
||||
|
||||
Q_INVOKABLE void setNetworkProxy();
|
||||
Q_INVOKABLE bool isSystemProxyDefined();
|
||||
|
||||
Q_SIGNALS:
|
||||
void entryAdded(const QString &feedurl, const QString &id);
|
||||
void entryUpdated(const QString &feedurl, const QString &id);
|
||||
@ -93,4 +96,8 @@ private:
|
||||
const qint64 m_checkInterval = 10 * 60 * 1000; // trigger timer every 10 minutes
|
||||
QTimer *m_updateTimer;
|
||||
QDateTime m_updateTriggerTime;
|
||||
|
||||
QByteArray m_systemHttpProxy;
|
||||
QByteArray m_systemHttpsProxy;
|
||||
bool m_isSystemProxyDefined;
|
||||
};
|
||||
|
@ -1,6 +1,7 @@
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2020 Tobias Fella <tobias.fella@kde.org>
|
||||
* SPDX-FileCopyrightText: 2021 Bart De Vries <bart@mogwai.be>
|
||||
* SPDX-FileCopyrightText: 2022 Gary Wang <wzc782970009@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
*/
|
||||
@ -11,6 +12,7 @@ import QtQuick.Layouts
|
||||
|
||||
import org.kde.kirigami as Kirigami
|
||||
import org.kde.kirigamiaddons.formcard as FormCard
|
||||
import org.kde.kirigamiaddons.labs.components as Addons
|
||||
|
||||
import org.kde.kasts
|
||||
import org.kde.kasts.settings
|
||||
@ -18,6 +20,9 @@ import org.kde.kasts.settings
|
||||
FormCard.FormCardPage {
|
||||
id: root
|
||||
|
||||
property int currentType: SettingsManager.proxyType
|
||||
property bool proxyConfigChanged: false
|
||||
|
||||
FormCard.FormHeader {
|
||||
Layout.fillWidth: true
|
||||
title: i18nc("@title Form header for settings related to network connections", "Network")
|
||||
@ -89,4 +94,130 @@ FormCard.FormCardPage {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FormCard.FormHeader {
|
||||
title: i18nc("@title Form header for settings related to network proxies", "Network Proxy")
|
||||
}
|
||||
|
||||
FormCard.FormCard {
|
||||
FormCard.FormRadioDelegate {
|
||||
text: i18nc("@option:radio Network proxy selection", "System Default")
|
||||
checked: currentType === 0
|
||||
enabled: !SettingsManager.isProxyTypeImmutable
|
||||
onToggled: {
|
||||
currentType = 0;
|
||||
}
|
||||
}
|
||||
|
||||
FormCard.FormRadioDelegate {
|
||||
text: i18nc("@option:radio Network proxy selection", "No Proxy")
|
||||
checked: currentType === 1
|
||||
enabled: !SettingsManager.isProxyTypeImmutable
|
||||
onToggled: {
|
||||
currentType = 1;
|
||||
}
|
||||
}
|
||||
|
||||
FormCard.FormRadioDelegate {
|
||||
text: i18nc("@option:radio Network proxy selection", "HTTP")
|
||||
checked: currentType === 2
|
||||
enabled: !SettingsManager.isProxyTypeImmutable
|
||||
onToggled: {
|
||||
currentType = 2;
|
||||
}
|
||||
}
|
||||
|
||||
FormCard.FormRadioDelegate {
|
||||
text: i18nc("@option:radio Network proxy selection", "Socks5")
|
||||
checked: currentType === 3
|
||||
enabled: !SettingsManager.isProxyTypeImmutable
|
||||
onToggled: {
|
||||
currentType = 3;
|
||||
}
|
||||
}
|
||||
|
||||
FormCard.FormDelegateSeparator {
|
||||
visible: currentType > 1
|
||||
}
|
||||
|
||||
FormCard.FormTextFieldDelegate {
|
||||
id: hostField
|
||||
visible: currentType > 1
|
||||
label: i18nc("@label:textbox Hostname for proxy config", "Host")
|
||||
text: SettingsManager.proxyHost
|
||||
inputMethodHints: Qt.ImhUrlCharactersOnly
|
||||
onEditingFinished: {
|
||||
proxyConfigChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
FormCard.FormSpinBoxDelegate {
|
||||
id: portField
|
||||
visible: currentType > 1
|
||||
label: i18nc("@label:spinbox Port for proxy config", "Port")
|
||||
value: SettingsManager.proxyPort
|
||||
from: 0
|
||||
to: 65536
|
||||
textFromValue: (value, locale) => {
|
||||
return value; // it will add a thousands separator if we don't do this, not sure why
|
||||
}
|
||||
onValueChanged: {
|
||||
proxyConfigChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
FormCard.FormTextFieldDelegate {
|
||||
id: userField
|
||||
visible: currentType > 1
|
||||
label: i18nc("@label:textbox Username for proxy config", "User")
|
||||
text: SettingsManager.proxyUser
|
||||
inputMethodHints: Qt.ImhUrlCharactersOnly
|
||||
onEditingFinished: {
|
||||
proxyConfigChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
FormCard.FormTextFieldDelegate {
|
||||
id: passwordField
|
||||
visible: currentType > 1
|
||||
label: i18nc("@label:textbox Password for proxy config", "Password")
|
||||
text: SettingsManager.proxyPassword
|
||||
echoMode: TextInput.Password
|
||||
inputMethodHints: Qt.ImhUrlCharactersOnly
|
||||
onEditingFinished: {
|
||||
proxyConfigChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
FormCard.FormDelegateSeparator {}
|
||||
|
||||
FormCard.FormTextDelegate {
|
||||
trailing: Controls.Button {
|
||||
icon.name: "dialog-ok"
|
||||
text: i18nc("@action:button", "Apply")
|
||||
enabled: currentType !== SettingsManager.proxyType || proxyConfigChanged
|
||||
onClicked: {
|
||||
SettingsManager.proxyType = currentType;
|
||||
SettingsManager.proxyHost = hostField.text;
|
||||
SettingsManager.proxyPort = portField.value;
|
||||
SettingsManager.proxyUser = userField.text;
|
||||
SettingsManager.proxyPassword = passwordField.text;
|
||||
SettingsManager.save();
|
||||
proxyConfigChanged = false;
|
||||
Fetcher.setNetworkProxy();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
footer: Addons.Banner {
|
||||
Layout.fillWidth: true
|
||||
type: Kirigami.MessageType.Warning
|
||||
visible: currentType < 2 && Fetcher.isSystemProxyDefined()
|
||||
text: i18nc("@info:status Warning message related to app proxy settings", "Your system level or app level proxy settings might be ignored by the audio backend when streaming audio. The settings should still be honored by all other network related actions, including downloading episodes.")
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
proxyConfigChanged = false;
|
||||
}
|
||||
}
|
||||
|
@ -237,4 +237,37 @@
|
||||
<default></default>
|
||||
</entry>
|
||||
</group>
|
||||
<group name="NetworkProxy">
|
||||
<entry name="ProxyType" type="Enum">
|
||||
<label>The type of proxy used by the application</label>
|
||||
<choices>
|
||||
<choice name="System">
|
||||
<label>System Default</label>
|
||||
</choice>
|
||||
<choice name="HTTP">
|
||||
<label>HTTP</label>
|
||||
</choice>
|
||||
<choice name="Socks5">
|
||||
<label>Socks5</label>
|
||||
</choice>
|
||||
<default>System</default>
|
||||
</choices>
|
||||
</entry>
|
||||
<entry name="ProxyHost" type="String">
|
||||
<label>IP or hostname of the proxy</label>
|
||||
<default>127.0.0.1</default>
|
||||
</entry>
|
||||
<entry name="ProxyPort" type="int">
|
||||
<label>The port number of the proxy</label>
|
||||
<default>1080</default>
|
||||
</entry>
|
||||
<entry name="ProxyUser" type="String">
|
||||
<label>The user of the proxy</label>
|
||||
<default></default>
|
||||
</entry>
|
||||
<entry name="ProxyPassword" type="Password">
|
||||
<label>The password of the proxy</label>
|
||||
<default></default>
|
||||
</entry>
|
||||
</group>
|
||||
</kcfg>
|
||||
|
Loading…
x
Reference in New Issue
Block a user