mirror of
https://github.com/qbittorrent/qBittorrent.git
synced 2025-12-22 16:37:21 -06:00
Merge pull request #18528 from glassez/proxy
Allow to use proxy per subsystem
This commit is contained in:
@@ -262,8 +262,6 @@ namespace BitTorrent
|
||||
virtual void setMaxActiveCheckingTorrents(int val) = 0;
|
||||
virtual bool isProxyPeerConnectionsEnabled() const = 0;
|
||||
virtual void setProxyPeerConnectionsEnabled(bool enabled) = 0;
|
||||
virtual bool isProxyHostnameLookupEnabled() const = 0;
|
||||
virtual void setProxyHostnameLookupEnabled(bool enabled) = 0;
|
||||
virtual ChokingAlgorithm chokingAlgorithm() const = 0;
|
||||
virtual void setChokingAlgorithm(ChokingAlgorithm mode) = 0;
|
||||
virtual SeedChokingAlgorithm seedChokingAlgorithm() const = 0;
|
||||
|
||||
@@ -42,7 +42,10 @@
|
||||
#include <iphlpapi.h>
|
||||
#endif
|
||||
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
|
||||
#include <libtorrent/add_torrent_params.hpp>
|
||||
#include <libtorrent/address.hpp>
|
||||
#include <libtorrent/alert_types.hpp>
|
||||
#include <libtorrent/error_code.hpp>
|
||||
#include <libtorrent/extensions/smart_ban.hpp>
|
||||
@@ -495,7 +498,6 @@ SessionImpl::SessionImpl(QObject *parent)
|
||||
, m_encryption(BITTORRENT_SESSION_KEY(u"Encryption"_qs), 0)
|
||||
, m_maxActiveCheckingTorrents(BITTORRENT_SESSION_KEY(u"MaxActiveCheckingTorrents"_qs), 1)
|
||||
, m_isProxyPeerConnectionsEnabled(BITTORRENT_SESSION_KEY(u"ProxyPeerConnections"_qs), false)
|
||||
, m_isProxyHostnameLookupEnabled(BITTORRENT_SESSION_KEY(u"ProxyHostnameLookup"_qs), true)
|
||||
, m_chokingAlgorithm(BITTORRENT_SESSION_KEY(u"ChokingAlgorithm"_qs), ChokingAlgorithm::FixedSlots
|
||||
, clampValue(ChokingAlgorithm::FixedSlots, ChokingAlgorithm::RateBased))
|
||||
, m_seedChokingAlgorithm(BITTORRENT_SESSION_KEY(u"SeedChokingAlgorithm"_qs), SeedChokingAlgorithm::FastestUpload
|
||||
@@ -1629,44 +1631,47 @@ lt::settings_pack SessionImpl::loadLTSettings() const
|
||||
settingsPack.set_int(lt::settings_pack::active_checking, maxActiveCheckingTorrents());
|
||||
|
||||
// proxy
|
||||
const auto proxyManager = Net::ProxyConfigurationManager::instance();
|
||||
const Net::ProxyConfiguration proxyConfig = proxyManager->proxyConfiguration();
|
||||
|
||||
switch (proxyConfig.type)
|
||||
settingsPack.set_int(lt::settings_pack::proxy_type, lt::settings_pack::none);
|
||||
if (Preferences::instance()->useProxyForBT())
|
||||
{
|
||||
case Net::ProxyType::HTTP:
|
||||
settingsPack.set_int(lt::settings_pack::proxy_type, lt::settings_pack::http);
|
||||
break;
|
||||
case Net::ProxyType::HTTP_PW:
|
||||
settingsPack.set_int(lt::settings_pack::proxy_type, lt::settings_pack::http_pw);
|
||||
break;
|
||||
case Net::ProxyType::SOCKS4:
|
||||
settingsPack.set_int(lt::settings_pack::proxy_type, lt::settings_pack::socks4);
|
||||
break;
|
||||
case Net::ProxyType::SOCKS5:
|
||||
settingsPack.set_int(lt::settings_pack::proxy_type, lt::settings_pack::socks5);
|
||||
break;
|
||||
case Net::ProxyType::SOCKS5_PW:
|
||||
settingsPack.set_int(lt::settings_pack::proxy_type, lt::settings_pack::socks5_pw);
|
||||
break;
|
||||
case Net::ProxyType::None:
|
||||
default:
|
||||
settingsPack.set_int(lt::settings_pack::proxy_type, lt::settings_pack::none);
|
||||
}
|
||||
const auto proxyManager = Net::ProxyConfigurationManager::instance();
|
||||
const Net::ProxyConfiguration proxyConfig = proxyManager->proxyConfiguration();
|
||||
|
||||
switch (proxyConfig.type)
|
||||
{
|
||||
case Net::ProxyType::SOCKS4:
|
||||
settingsPack.set_int(lt::settings_pack::proxy_type, lt::settings_pack::socks4);
|
||||
break;
|
||||
|
||||
case Net::ProxyType::HTTP:
|
||||
if (proxyConfig.authEnabled)
|
||||
settingsPack.set_int(lt::settings_pack::proxy_type, lt::settings_pack::http_pw);
|
||||
else
|
||||
settingsPack.set_int(lt::settings_pack::proxy_type, lt::settings_pack::http);
|
||||
break;
|
||||
|
||||
case Net::ProxyType::SOCKS5:
|
||||
if (proxyConfig.authEnabled)
|
||||
settingsPack.set_int(lt::settings_pack::proxy_type, lt::settings_pack::socks5_pw);
|
||||
else
|
||||
settingsPack.set_int(lt::settings_pack::proxy_type, lt::settings_pack::socks5);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (proxyConfig.type != Net::ProxyType::None)
|
||||
{
|
||||
settingsPack.set_str(lt::settings_pack::proxy_hostname, proxyConfig.ip.toStdString());
|
||||
settingsPack.set_int(lt::settings_pack::proxy_port, proxyConfig.port);
|
||||
|
||||
if (proxyManager->isAuthenticationRequired())
|
||||
if (proxyConfig.authEnabled)
|
||||
{
|
||||
settingsPack.set_str(lt::settings_pack::proxy_username, proxyConfig.username.toStdString());
|
||||
settingsPack.set_str(lt::settings_pack::proxy_password, proxyConfig.password.toStdString());
|
||||
}
|
||||
|
||||
settingsPack.set_bool(lt::settings_pack::proxy_peer_connections, isProxyPeerConnectionsEnabled());
|
||||
settingsPack.set_bool(lt::settings_pack::proxy_hostnames, isProxyHostnameLookupEnabled());
|
||||
settingsPack.set_bool(lt::settings_pack::proxy_hostnames, proxyConfig.hostnameLookupEnabled);
|
||||
}
|
||||
|
||||
settingsPack.set_bool(lt::settings_pack::announce_to_all_trackers, announceToAllTrackers());
|
||||
@@ -2493,7 +2498,7 @@ bool SessionImpl::addTorrent(const QString &source, const AddTorrentParams ¶
|
||||
LogMsg(tr("Downloading torrent, please wait... Source: \"%1\"").arg(source));
|
||||
// Launch downloader
|
||||
Net::DownloadManager::instance()->download(Net::DownloadRequest(source).limit(MAX_TORRENT_SIZE)
|
||||
, this, &SessionImpl::handleDownloadFinished);
|
||||
, Preferences::instance()->useProxyForGeneralPurposes(), this, &SessionImpl::handleDownloadFinished);
|
||||
m_downloadedTorrents[source] = params;
|
||||
return true;
|
||||
}
|
||||
@@ -3542,20 +3547,6 @@ void SessionImpl::setProxyPeerConnectionsEnabled(const bool enabled)
|
||||
}
|
||||
}
|
||||
|
||||
bool SessionImpl::isProxyHostnameLookupEnabled() const
|
||||
{
|
||||
return m_isProxyHostnameLookupEnabled;
|
||||
}
|
||||
|
||||
void SessionImpl::setProxyHostnameLookupEnabled(const bool enabled)
|
||||
{
|
||||
if (enabled != isProxyHostnameLookupEnabled())
|
||||
{
|
||||
m_isProxyHostnameLookupEnabled = enabled;
|
||||
configureDeferred();
|
||||
}
|
||||
}
|
||||
|
||||
ChokingAlgorithm SessionImpl::chokingAlgorithm() const
|
||||
{
|
||||
return m_chokingAlgorithm;
|
||||
@@ -5791,8 +5782,12 @@ void SessionImpl::handleSocks5Alert(const lt::socks5_alert *p) const
|
||||
{
|
||||
if (p->error)
|
||||
{
|
||||
LogMsg(tr("SOCKS5 proxy error. Message: \"%1\"").arg(QString::fromStdString(p->message()))
|
||||
, Log::WARNING);
|
||||
const auto addr = p->ip.address();
|
||||
const QString endpoint = (addr.is_v6() ? u"[%1]:%2"_qs : u"%1:%2"_qs)
|
||||
.arg(QString::fromStdString(addr.to_string()), QString::number(p->ip.port()));
|
||||
LogMsg(tr("SOCKS5 proxy error. Address: %1. Message: \"%2\".")
|
||||
.arg(endpoint, QString::fromLocal8Bit(p->error.message().c_str()))
|
||||
, Log::WARNING);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -239,8 +239,6 @@ namespace BitTorrent
|
||||
void setMaxActiveCheckingTorrents(int val) override;
|
||||
bool isProxyPeerConnectionsEnabled() const override;
|
||||
void setProxyPeerConnectionsEnabled(bool enabled) override;
|
||||
bool isProxyHostnameLookupEnabled() const override;
|
||||
void setProxyHostnameLookupEnabled(bool enabled) override;
|
||||
ChokingAlgorithm chokingAlgorithm() const override;
|
||||
void setChokingAlgorithm(ChokingAlgorithm mode) override;
|
||||
SeedChokingAlgorithm seedChokingAlgorithm() const override;
|
||||
@@ -655,7 +653,6 @@ namespace BitTorrent
|
||||
CachedSettingValue<int> m_encryption;
|
||||
CachedSettingValue<int> m_maxActiveCheckingTorrents;
|
||||
CachedSettingValue<bool> m_isProxyPeerConnectionsEnabled;
|
||||
CachedSettingValue<bool> m_isProxyHostnameLookupEnabled;
|
||||
CachedSettingValue<ChokingAlgorithm> m_chokingAlgorithm;
|
||||
CachedSettingValue<SeedChokingAlgorithm> m_seedChokingAlgorithm;
|
||||
CachedSettingValue<QStringList> m_storedTags;
|
||||
|
||||
@@ -80,8 +80,8 @@ void DNSUpdater::checkPublicIP()
|
||||
Q_ASSERT(m_state == OK);
|
||||
|
||||
DownloadManager::instance()->download(
|
||||
DownloadRequest(u"http://checkip.dyndns.org"_qs).userAgent(QStringLiteral("qBittorrent/" QBT_VERSION_2))
|
||||
, this, &DNSUpdater::ipRequestFinished);
|
||||
DownloadRequest(u"http://checkip.dyndns.org"_qs).userAgent(QStringLiteral("qBittorrent/" QBT_VERSION_2))
|
||||
, Preferences::instance()->useProxyForGeneralPurposes(), this, &DNSUpdater::ipRequestFinished);
|
||||
|
||||
m_lastIPCheckTime = QDateTime::currentDateTime();
|
||||
}
|
||||
@@ -128,8 +128,8 @@ void DNSUpdater::updateDNSService()
|
||||
|
||||
m_lastIPCheckTime = QDateTime::currentDateTime();
|
||||
DownloadManager::instance()->download(
|
||||
DownloadRequest(getUpdateUrl()).userAgent(QStringLiteral("qBittorrent/" QBT_VERSION_2))
|
||||
, this, &DNSUpdater::ipUpdateFinished);
|
||||
DownloadRequest(getUpdateUrl()).userAgent(QStringLiteral("qBittorrent/" QBT_VERSION_2))
|
||||
, Preferences::instance()->useProxyForGeneralPurposes(), this, &DNSUpdater::ipUpdateFinished);
|
||||
}
|
||||
|
||||
QString DNSUpdater::getUpdateUrl() const
|
||||
|
||||
@@ -56,16 +56,18 @@ namespace
|
||||
}
|
||||
}
|
||||
|
||||
DownloadHandlerImpl::DownloadHandlerImpl(Net::DownloadManager *manager, const Net::DownloadRequest &downloadRequest)
|
||||
Net::DownloadHandlerImpl::DownloadHandlerImpl(DownloadManager *manager
|
||||
, const DownloadRequest &downloadRequest, const bool useProxy)
|
||||
: DownloadHandler {manager}
|
||||
, m_manager {manager}
|
||||
, m_downloadRequest {downloadRequest}
|
||||
, m_useProxy {useProxy}
|
||||
{
|
||||
m_result.url = url();
|
||||
m_result.status = Net::DownloadStatus::Success;
|
||||
m_result.status = DownloadStatus::Success;
|
||||
}
|
||||
|
||||
void DownloadHandlerImpl::cancel()
|
||||
void Net::DownloadHandlerImpl::cancel()
|
||||
{
|
||||
if (m_reply)
|
||||
{
|
||||
@@ -78,7 +80,7 @@ void DownloadHandlerImpl::cancel()
|
||||
}
|
||||
}
|
||||
|
||||
void DownloadHandlerImpl::assignNetworkReply(QNetworkReply *reply)
|
||||
void Net::DownloadHandlerImpl::assignNetworkReply(QNetworkReply *reply)
|
||||
{
|
||||
Q_ASSERT(reply);
|
||||
Q_ASSERT(!m_reply);
|
||||
@@ -91,17 +93,22 @@ void DownloadHandlerImpl::assignNetworkReply(QNetworkReply *reply)
|
||||
}
|
||||
|
||||
// Returns original url
|
||||
QString DownloadHandlerImpl::url() const
|
||||
QString Net::DownloadHandlerImpl::url() const
|
||||
{
|
||||
return m_downloadRequest.url();
|
||||
}
|
||||
|
||||
const Net::DownloadRequest DownloadHandlerImpl::downloadRequest() const
|
||||
Net::DownloadRequest Net::DownloadHandlerImpl::downloadRequest() const
|
||||
{
|
||||
return m_downloadRequest;
|
||||
}
|
||||
|
||||
void DownloadHandlerImpl::processFinishedDownload()
|
||||
bool Net::DownloadHandlerImpl::useProxy() const
|
||||
{
|
||||
return m_useProxy;
|
||||
}
|
||||
|
||||
void Net::DownloadHandlerImpl::processFinishedDownload()
|
||||
{
|
||||
qDebug("Download finished: %s", qUtf8Printable(url()));
|
||||
|
||||
@@ -156,7 +163,7 @@ void DownloadHandlerImpl::processFinishedDownload()
|
||||
finish();
|
||||
}
|
||||
|
||||
void DownloadHandlerImpl::checkDownloadSize(const qint64 bytesReceived, const qint64 bytesTotal)
|
||||
void Net::DownloadHandlerImpl::checkDownloadSize(const qint64 bytesReceived, const qint64 bytesTotal)
|
||||
{
|
||||
if ((bytesTotal > 0) && (bytesTotal <= m_downloadRequest.limit()))
|
||||
{
|
||||
@@ -175,7 +182,7 @@ void DownloadHandlerImpl::checkDownloadSize(const qint64 bytesReceived, const qi
|
||||
}
|
||||
}
|
||||
|
||||
void DownloadHandlerImpl::handleRedirection(const QUrl &newUrl)
|
||||
void Net::DownloadHandlerImpl::handleRedirection(const QUrl &newUrl)
|
||||
{
|
||||
if (m_redirectionCount >= MAX_REDIRECTIONS)
|
||||
{
|
||||
@@ -202,9 +209,9 @@ void DownloadHandlerImpl::handleRedirection(const QUrl &newUrl)
|
||||
}
|
||||
|
||||
auto redirected = static_cast<DownloadHandlerImpl *>(
|
||||
m_manager->download(Net::DownloadRequest(m_downloadRequest).url(newUrlString)));
|
||||
m_manager->download(DownloadRequest(m_downloadRequest).url(newUrlString), useProxy()));
|
||||
redirected->m_redirectionCount = m_redirectionCount + 1;
|
||||
connect(redirected, &DownloadHandlerImpl::finished, this, [this](const Net::DownloadResult &result)
|
||||
connect(redirected, &DownloadHandlerImpl::finished, this, [this](const DownloadResult &result)
|
||||
{
|
||||
m_result = result;
|
||||
m_result.url = url();
|
||||
@@ -212,18 +219,18 @@ void DownloadHandlerImpl::handleRedirection(const QUrl &newUrl)
|
||||
});
|
||||
}
|
||||
|
||||
void DownloadHandlerImpl::setError(const QString &error)
|
||||
void Net::DownloadHandlerImpl::setError(const QString &error)
|
||||
{
|
||||
m_result.errorString = error;
|
||||
m_result.status = Net::DownloadStatus::Failed;
|
||||
m_result.status = DownloadStatus::Failed;
|
||||
}
|
||||
|
||||
void DownloadHandlerImpl::finish()
|
||||
void Net::DownloadHandlerImpl::finish()
|
||||
{
|
||||
emit finished(m_result);
|
||||
}
|
||||
|
||||
QString DownloadHandlerImpl::errorCodeToString(const QNetworkReply::NetworkError status)
|
||||
QString Net::DownloadHandlerImpl::errorCodeToString(const QNetworkReply::NetworkError status)
|
||||
{
|
||||
switch (status)
|
||||
{
|
||||
|
||||
@@ -36,33 +36,38 @@
|
||||
class QObject;
|
||||
class QUrl;
|
||||
|
||||
class DownloadHandlerImpl final : public Net::DownloadHandler
|
||||
namespace Net
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_DISABLE_COPY_MOVE(DownloadHandlerImpl)
|
||||
class DownloadHandlerImpl final : public DownloadHandler
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_DISABLE_COPY_MOVE(DownloadHandlerImpl)
|
||||
|
||||
public:
|
||||
DownloadHandlerImpl(Net::DownloadManager *manager, const Net::DownloadRequest &downloadRequest);
|
||||
public:
|
||||
DownloadHandlerImpl(DownloadManager *manager, const DownloadRequest &downloadRequest, bool useProxy);
|
||||
|
||||
void cancel() override;
|
||||
void cancel() override;
|
||||
|
||||
QString url() const;
|
||||
const Net::DownloadRequest downloadRequest() const;
|
||||
QString url() const;
|
||||
DownloadRequest downloadRequest() const;
|
||||
bool useProxy() const;
|
||||
|
||||
void assignNetworkReply(QNetworkReply *reply);
|
||||
void assignNetworkReply(QNetworkReply *reply);
|
||||
|
||||
private:
|
||||
void processFinishedDownload();
|
||||
void checkDownloadSize(qint64 bytesReceived, qint64 bytesTotal);
|
||||
void handleRedirection(const QUrl &newUrl);
|
||||
void setError(const QString &error);
|
||||
void finish();
|
||||
private:
|
||||
void processFinishedDownload();
|
||||
void checkDownloadSize(qint64 bytesReceived, qint64 bytesTotal);
|
||||
void handleRedirection(const QUrl &newUrl);
|
||||
void setError(const QString &error);
|
||||
void finish();
|
||||
|
||||
static QString errorCodeToString(QNetworkReply::NetworkError status);
|
||||
static QString errorCodeToString(QNetworkReply::NetworkError status);
|
||||
|
||||
Net::DownloadManager *m_manager = nullptr;
|
||||
QNetworkReply *m_reply = nullptr;
|
||||
const Net::DownloadRequest m_downloadRequest;
|
||||
short m_redirectionCount = 0;
|
||||
Net::DownloadResult m_result;
|
||||
};
|
||||
DownloadManager *m_manager = nullptr;
|
||||
QNetworkReply *m_reply = nullptr;
|
||||
const DownloadRequest m_downloadRequest;
|
||||
const bool m_useProxy = false;
|
||||
short m_redirectionCount = 0;
|
||||
DownloadResult m_result;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QDebug>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QNetworkCookie>
|
||||
#include <QNetworkCookieJar>
|
||||
#include <QNetworkProxy>
|
||||
@@ -51,101 +52,81 @@ namespace
|
||||
{
|
||||
// Disguise as Firefox to avoid web server banning
|
||||
const char DEFAULT_USER_AGENT[] = "Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0";
|
||||
|
||||
class NetworkCookieJar final : public QNetworkCookieJar
|
||||
{
|
||||
public:
|
||||
explicit NetworkCookieJar(QObject *parent = nullptr)
|
||||
: QNetworkCookieJar(parent)
|
||||
{
|
||||
const QDateTime now = QDateTime::currentDateTime();
|
||||
QList<QNetworkCookie> cookies = Preferences::instance()->getNetworkCookies();
|
||||
for (const QNetworkCookie &cookie : asConst(Preferences::instance()->getNetworkCookies()))
|
||||
{
|
||||
if (cookie.isSessionCookie() || (cookie.expirationDate() <= now))
|
||||
cookies.removeAll(cookie);
|
||||
}
|
||||
|
||||
setAllCookies(cookies);
|
||||
}
|
||||
|
||||
~NetworkCookieJar() override
|
||||
{
|
||||
const QDateTime now = QDateTime::currentDateTime();
|
||||
QList<QNetworkCookie> cookies = allCookies();
|
||||
for (const QNetworkCookie &cookie : asConst(allCookies()))
|
||||
{
|
||||
if (cookie.isSessionCookie() || (cookie.expirationDate() <= now))
|
||||
cookies.removeAll(cookie);
|
||||
}
|
||||
|
||||
Preferences::instance()->setNetworkCookies(cookies);
|
||||
}
|
||||
|
||||
using QNetworkCookieJar::allCookies;
|
||||
using QNetworkCookieJar::setAllCookies;
|
||||
|
||||
QList<QNetworkCookie> cookiesForUrl(const QUrl &url) const override
|
||||
{
|
||||
const QDateTime now = QDateTime::currentDateTime();
|
||||
QList<QNetworkCookie> cookies = QNetworkCookieJar::cookiesForUrl(url);
|
||||
for (const QNetworkCookie &cookie : asConst(QNetworkCookieJar::cookiesForUrl(url)))
|
||||
{
|
||||
if (!cookie.isSessionCookie() && (cookie.expirationDate() <= now))
|
||||
cookies.removeAll(cookie);
|
||||
}
|
||||
|
||||
return cookies;
|
||||
}
|
||||
|
||||
bool setCookiesFromUrl(const QList<QNetworkCookie> &cookieList, const QUrl &url) override
|
||||
{
|
||||
const QDateTime now = QDateTime::currentDateTime();
|
||||
QList<QNetworkCookie> cookies = cookieList;
|
||||
for (const QNetworkCookie &cookie : cookieList)
|
||||
{
|
||||
if (!cookie.isSessionCookie() && (cookie.expirationDate() <= now))
|
||||
cookies.removeAll(cookie);
|
||||
}
|
||||
|
||||
return QNetworkCookieJar::setCookiesFromUrl(cookies, url);
|
||||
}
|
||||
};
|
||||
|
||||
QNetworkRequest createNetworkRequest(const Net::DownloadRequest &downloadRequest)
|
||||
{
|
||||
QNetworkRequest request {downloadRequest.url()};
|
||||
|
||||
if (downloadRequest.userAgent().isEmpty())
|
||||
request.setRawHeader("User-Agent", DEFAULT_USER_AGENT);
|
||||
else
|
||||
request.setRawHeader("User-Agent", downloadRequest.userAgent().toUtf8());
|
||||
|
||||
// Spoof HTTP Referer to allow adding torrent link from Torcache/KickAssTorrents
|
||||
request.setRawHeader("Referer", request.url().toEncoded().data());
|
||||
#ifdef QT_NO_COMPRESS
|
||||
// The macro "QT_NO_COMPRESS" defined in QT will disable the zlib related features
|
||||
// and reply data auto-decompression in QT will also be disabled. But we can support
|
||||
// gzip encoding and manually decompress the reply data.
|
||||
request.setRawHeader("Accept-Encoding", "gzip");
|
||||
#endif
|
||||
// Qt doesn't support Magnet protocol so we need to handle redirections manually
|
||||
request.setAttribute(QNetworkRequest::RedirectPolicyAttribute, QNetworkRequest::ManualRedirectPolicy);
|
||||
|
||||
return request;
|
||||
}
|
||||
}
|
||||
|
||||
class Net::DownloadManager::NetworkCookieJar final : public QNetworkCookieJar
|
||||
{
|
||||
public:
|
||||
explicit NetworkCookieJar(QObject *parent = nullptr)
|
||||
: QNetworkCookieJar(parent)
|
||||
{
|
||||
const QDateTime now = QDateTime::currentDateTime();
|
||||
QList<QNetworkCookie> cookies = Preferences::instance()->getNetworkCookies();
|
||||
for (const QNetworkCookie &cookie : asConst(Preferences::instance()->getNetworkCookies()))
|
||||
{
|
||||
if (cookie.isSessionCookie() || (cookie.expirationDate() <= now))
|
||||
cookies.removeAll(cookie);
|
||||
}
|
||||
|
||||
setAllCookies(cookies);
|
||||
}
|
||||
|
||||
~NetworkCookieJar() override
|
||||
{
|
||||
const QDateTime now = QDateTime::currentDateTime();
|
||||
QList<QNetworkCookie> cookies = allCookies();
|
||||
for (const QNetworkCookie &cookie : asConst(allCookies()))
|
||||
{
|
||||
if (cookie.isSessionCookie() || (cookie.expirationDate() <= now))
|
||||
cookies.removeAll(cookie);
|
||||
}
|
||||
|
||||
Preferences::instance()->setNetworkCookies(cookies);
|
||||
}
|
||||
|
||||
using QNetworkCookieJar::allCookies;
|
||||
using QNetworkCookieJar::setAllCookies;
|
||||
|
||||
QList<QNetworkCookie> cookiesForUrl(const QUrl &url) const override
|
||||
{
|
||||
const QDateTime now = QDateTime::currentDateTime();
|
||||
QList<QNetworkCookie> cookies = QNetworkCookieJar::cookiesForUrl(url);
|
||||
for (const QNetworkCookie &cookie : asConst(QNetworkCookieJar::cookiesForUrl(url)))
|
||||
{
|
||||
if (!cookie.isSessionCookie() && (cookie.expirationDate() <= now))
|
||||
cookies.removeAll(cookie);
|
||||
}
|
||||
|
||||
return cookies;
|
||||
}
|
||||
|
||||
bool setCookiesFromUrl(const QList<QNetworkCookie> &cookieList, const QUrl &url) override
|
||||
{
|
||||
const QDateTime now = QDateTime::currentDateTime();
|
||||
QList<QNetworkCookie> cookies = cookieList;
|
||||
for (const QNetworkCookie &cookie : cookieList)
|
||||
{
|
||||
if (!cookie.isSessionCookie() && (cookie.expirationDate() <= now))
|
||||
cookies.removeAll(cookie);
|
||||
}
|
||||
|
||||
return QNetworkCookieJar::setCookiesFromUrl(cookies, url);
|
||||
}
|
||||
};
|
||||
|
||||
Net::DownloadManager *Net::DownloadManager::m_instance = nullptr;
|
||||
|
||||
Net::DownloadManager::DownloadManager(QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_networkCookieJar {new NetworkCookieJar(this)}
|
||||
, m_networkManager {new QNetworkAccessManager(this)}
|
||||
{
|
||||
connect(&m_networkManager, &QNetworkAccessManager::sslErrors, this, &Net::DownloadManager::ignoreSslErrors);
|
||||
connect(&m_networkManager, &QNetworkAccessManager::finished, this, &DownloadManager::handleReplyFinished);
|
||||
m_networkManager->setCookieJar(m_networkCookieJar);
|
||||
connect(m_networkManager, &QNetworkAccessManager::sslErrors, this, &Net::DownloadManager::ignoreSslErrors);
|
||||
|
||||
connect(ProxyConfigurationManager::instance(), &ProxyConfigurationManager::proxyConfigurationChanged
|
||||
, this, &DownloadManager::applyProxySettings);
|
||||
m_networkManager.setCookieJar(new NetworkCookieJar(this));
|
||||
connect(Preferences::instance(), &Preferences::changed, this, &DownloadManager::applyProxySettings);
|
||||
applyProxySettings();
|
||||
}
|
||||
|
||||
@@ -166,14 +147,18 @@ Net::DownloadManager *Net::DownloadManager::instance()
|
||||
return m_instance;
|
||||
}
|
||||
|
||||
Net::DownloadHandler *Net::DownloadManager::download(const DownloadRequest &downloadRequest)
|
||||
Net::DownloadHandler *Net::DownloadManager::download(const DownloadRequest &downloadRequest, const bool useProxy)
|
||||
{
|
||||
// Process download request
|
||||
const QNetworkRequest request = createNetworkRequest(downloadRequest);
|
||||
const ServiceID id = ServiceID::fromURL(request.url());
|
||||
const ServiceID id = ServiceID::fromURL(downloadRequest.url());
|
||||
const bool isSequentialService = m_sequentialServices.contains(id);
|
||||
|
||||
auto downloadHandler = new DownloadHandlerImpl {this, downloadRequest};
|
||||
auto downloadHandler = new DownloadHandlerImpl(this, downloadRequest, useProxy);
|
||||
connect(downloadHandler, &DownloadHandler::finished, this
|
||||
, [this, downloadHandler]
|
||||
{
|
||||
handleDownloadFinished(downloadHandler);
|
||||
});
|
||||
connect(downloadHandler, &DownloadHandler::finished, downloadHandler, &QObject::deleteLater);
|
||||
connect(downloadHandler, &QObject::destroyed, this, [this, id, downloadHandler]()
|
||||
{
|
||||
@@ -189,7 +174,7 @@ Net::DownloadHandler *Net::DownloadManager::download(const DownloadRequest &down
|
||||
qDebug("Downloading %s...", qUtf8Printable(downloadRequest.url()));
|
||||
if (isSequentialService)
|
||||
m_busyServices.insert(id);
|
||||
downloadHandler->assignNetworkReply(m_networkManager.get(request));
|
||||
processRequest(downloadHandler);
|
||||
}
|
||||
|
||||
return downloadHandler;
|
||||
@@ -202,32 +187,32 @@ void Net::DownloadManager::registerSequentialService(const Net::ServiceID &servi
|
||||
|
||||
QList<QNetworkCookie> Net::DownloadManager::cookiesForUrl(const QUrl &url) const
|
||||
{
|
||||
return m_networkManager.cookieJar()->cookiesForUrl(url);
|
||||
return m_networkCookieJar->cookiesForUrl(url);
|
||||
}
|
||||
|
||||
bool Net::DownloadManager::setCookiesFromUrl(const QList<QNetworkCookie> &cookieList, const QUrl &url)
|
||||
{
|
||||
return m_networkManager.cookieJar()->setCookiesFromUrl(cookieList, url);
|
||||
return m_networkCookieJar->setCookiesFromUrl(cookieList, url);
|
||||
}
|
||||
|
||||
QList<QNetworkCookie> Net::DownloadManager::allCookies() const
|
||||
{
|
||||
return static_cast<NetworkCookieJar *>(m_networkManager.cookieJar())->allCookies();
|
||||
return m_networkCookieJar->allCookies();
|
||||
}
|
||||
|
||||
void Net::DownloadManager::setAllCookies(const QList<QNetworkCookie> &cookieList)
|
||||
{
|
||||
static_cast<NetworkCookieJar *>(m_networkManager.cookieJar())->setAllCookies(cookieList);
|
||||
m_networkCookieJar->setAllCookies(cookieList);
|
||||
}
|
||||
|
||||
bool Net::DownloadManager::deleteCookie(const QNetworkCookie &cookie)
|
||||
{
|
||||
return static_cast<NetworkCookieJar *>(m_networkManager.cookieJar())->deleteCookie(cookie);
|
||||
return m_networkCookieJar->deleteCookie(cookie);
|
||||
}
|
||||
|
||||
bool Net::DownloadManager::hasSupportedScheme(const QString &url)
|
||||
{
|
||||
const QStringList schemes = instance()->m_networkManager.supportedSchemes();
|
||||
const QStringList schemes = QNetworkAccessManager().supportedSchemes();
|
||||
return std::any_of(schemes.cbegin(), schemes.cend(), [&url](const QString &scheme)
|
||||
{
|
||||
return url.startsWith((scheme + u':'), Qt::CaseInsensitive);
|
||||
@@ -238,46 +223,47 @@ void Net::DownloadManager::applyProxySettings()
|
||||
{
|
||||
const auto *proxyManager = ProxyConfigurationManager::instance();
|
||||
const ProxyConfiguration proxyConfig = proxyManager->proxyConfiguration();
|
||||
QNetworkProxy proxy;
|
||||
|
||||
if (!proxyManager->isProxyOnlyForTorrents() && (proxyConfig.type != ProxyType::None))
|
||||
m_proxy = QNetworkProxy(QNetworkProxy::NoProxy);
|
||||
|
||||
if (proxyConfig.type != ProxyType::SOCKS4)
|
||||
{
|
||||
// Proxy enabled
|
||||
proxy.setHostName(proxyConfig.ip);
|
||||
proxy.setPort(proxyConfig.port);
|
||||
// Default proxy type is HTTP, we must change if it is SOCKS5
|
||||
if ((proxyConfig.type == ProxyType::SOCKS5) || (proxyConfig.type == ProxyType::SOCKS5_PW))
|
||||
if (proxyConfig.type == ProxyType::SOCKS5)
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << "using SOCKS proxy";
|
||||
proxy.setType(QNetworkProxy::Socks5Proxy);
|
||||
m_proxy.setType(QNetworkProxy::Socks5Proxy);
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << "using HTTP proxy";
|
||||
proxy.setType(QNetworkProxy::HttpProxy);
|
||||
m_proxy.setType(QNetworkProxy::HttpProxy);
|
||||
}
|
||||
|
||||
m_proxy.setHostName(proxyConfig.ip);
|
||||
m_proxy.setPort(proxyConfig.port);
|
||||
|
||||
// Authentication?
|
||||
if (proxyManager->isAuthenticationRequired())
|
||||
if (proxyConfig.authEnabled)
|
||||
{
|
||||
qDebug("Proxy requires authentication, authenticating...");
|
||||
proxy.setUser(proxyConfig.username);
|
||||
proxy.setPassword(proxyConfig.password);
|
||||
m_proxy.setUser(proxyConfig.username);
|
||||
m_proxy.setPassword(proxyConfig.password);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
proxy.setType(QNetworkProxy::NoProxy);
|
||||
}
|
||||
|
||||
m_networkManager.setProxy(proxy);
|
||||
if (proxyConfig.hostnameLookupEnabled)
|
||||
m_proxy.setCapabilities(m_proxy.capabilities() | QNetworkProxy::HostNameLookupCapability);
|
||||
else
|
||||
m_proxy.setCapabilities(m_proxy.capabilities() & ~QNetworkProxy::HostNameLookupCapability);
|
||||
}
|
||||
}
|
||||
|
||||
void Net::DownloadManager::handleReplyFinished(const QNetworkReply *reply)
|
||||
void Net::DownloadManager::handleDownloadFinished(DownloadHandlerImpl *finishedHandler)
|
||||
{
|
||||
// QNetworkReply::url() may be different from that of the original request
|
||||
// so we need QNetworkRequest::url() to properly process Sequential Services
|
||||
// in the case when the redirection occurred.
|
||||
const ServiceID id = ServiceID::fromURL(reply->request().url());
|
||||
const ServiceID id = ServiceID::fromURL(finishedHandler->url());
|
||||
const auto waitingJobsIter = m_waitingJobs.find(id);
|
||||
if ((waitingJobsIter == m_waitingJobs.end()) || waitingJobsIter.value().isEmpty())
|
||||
{
|
||||
@@ -286,12 +272,38 @@ void Net::DownloadManager::handleReplyFinished(const QNetworkReply *reply)
|
||||
return;
|
||||
}
|
||||
|
||||
auto handler = static_cast<DownloadHandlerImpl *>(waitingJobsIter.value().dequeue());
|
||||
auto handler = waitingJobsIter.value().dequeue();
|
||||
qDebug("Downloading %s...", qUtf8Printable(handler->url()));
|
||||
handler->assignNetworkReply(m_networkManager.get(createNetworkRequest(handler->downloadRequest())));
|
||||
processRequest(handler);
|
||||
handler->disconnect(this);
|
||||
}
|
||||
|
||||
void Net::DownloadManager::processRequest(DownloadHandlerImpl *downloadHandler)
|
||||
{
|
||||
m_networkManager->setProxy((downloadHandler->useProxy() == true) ? m_proxy : QNetworkProxy(QNetworkProxy::NoProxy));
|
||||
|
||||
const DownloadRequest downloadRequest = downloadHandler->downloadRequest();
|
||||
QNetworkRequest request {downloadRequest.url()};
|
||||
|
||||
if (downloadRequest.userAgent().isEmpty())
|
||||
request.setRawHeader("User-Agent", DEFAULT_USER_AGENT);
|
||||
else
|
||||
request.setRawHeader("User-Agent", downloadRequest.userAgent().toUtf8());
|
||||
|
||||
// Spoof HTTP Referer to allow adding torrent link from Torcache/KickAssTorrents
|
||||
request.setRawHeader("Referer", request.url().toEncoded().data());
|
||||
#ifdef QT_NO_COMPRESS
|
||||
// The macro "QT_NO_COMPRESS" defined in QT will disable the zlib related features
|
||||
// and reply data auto-decompression in QT will also be disabled. But we can support
|
||||
// gzip encoding and manually decompress the reply data.
|
||||
request.setRawHeader("Accept-Encoding", "gzip");
|
||||
#endif
|
||||
// Qt doesn't support Magnet protocol so we need to handle redirections manually
|
||||
request.setAttribute(QNetworkRequest::RedirectPolicyAttribute, QNetworkRequest::ManualRedirectPolicy);
|
||||
|
||||
downloadHandler->assignNetworkReply(m_networkManager->get(request));
|
||||
}
|
||||
|
||||
void Net::DownloadManager::ignoreSslErrors(QNetworkReply *reply, const QList<QSslError> &errors)
|
||||
{
|
||||
QStringList errorList;
|
||||
|
||||
@@ -31,13 +31,14 @@
|
||||
|
||||
#include <QtGlobal>
|
||||
#include <QHash>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QNetworkProxy>
|
||||
#include <QObject>
|
||||
#include <QQueue>
|
||||
#include <QSet>
|
||||
|
||||
#include "base/path.h"
|
||||
|
||||
class QNetworkAccessManager;
|
||||
class QNetworkCookie;
|
||||
class QNetworkReply;
|
||||
class QSslError;
|
||||
@@ -123,6 +124,8 @@ namespace Net
|
||||
void finished(const DownloadResult &result);
|
||||
};
|
||||
|
||||
class DownloadHandlerImpl;
|
||||
|
||||
class DownloadManager : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
@@ -133,10 +136,10 @@ namespace Net
|
||||
static void freeInstance();
|
||||
static DownloadManager *instance();
|
||||
|
||||
DownloadHandler *download(const DownloadRequest &downloadRequest);
|
||||
DownloadHandler *download(const DownloadRequest &downloadRequest, bool useProxy);
|
||||
|
||||
template <typename Context, typename Func>
|
||||
void download(const DownloadRequest &downloadRequest, Context context, Func &&slot);
|
||||
void download(const DownloadRequest &downloadRequest, bool useProxy, Context context, Func &&slot);
|
||||
|
||||
void registerSequentialService(const ServiceID &serviceID);
|
||||
|
||||
@@ -152,23 +155,28 @@ namespace Net
|
||||
void ignoreSslErrors(QNetworkReply *, const QList<QSslError> &);
|
||||
|
||||
private:
|
||||
class NetworkCookieJar;
|
||||
|
||||
explicit DownloadManager(QObject *parent = nullptr);
|
||||
|
||||
void applyProxySettings();
|
||||
void handleReplyFinished(const QNetworkReply *reply);
|
||||
void handleDownloadFinished(DownloadHandlerImpl *finishedHandler);
|
||||
void processRequest(DownloadHandlerImpl *downloadHandler);
|
||||
|
||||
static DownloadManager *m_instance;
|
||||
QNetworkAccessManager m_networkManager;
|
||||
NetworkCookieJar *m_networkCookieJar = nullptr;
|
||||
QNetworkAccessManager *m_networkManager = nullptr;
|
||||
QNetworkProxy m_proxy;
|
||||
|
||||
QSet<ServiceID> m_sequentialServices;
|
||||
QSet<ServiceID> m_busyServices;
|
||||
QHash<ServiceID, QQueue<DownloadHandler *>> m_waitingJobs;
|
||||
QHash<ServiceID, QQueue<DownloadHandlerImpl *>> m_waitingJobs;
|
||||
};
|
||||
|
||||
template <typename Context, typename Func>
|
||||
void DownloadManager::download(const DownloadRequest &downloadRequest, Context context, Func &&slot)
|
||||
void DownloadManager::download(const DownloadRequest &downloadRequest, bool useProxy, Context context, Func &&slot)
|
||||
{
|
||||
const DownloadHandler *handler = download(downloadRequest);
|
||||
const DownloadHandler *handler = download(downloadRequest, useProxy);
|
||||
connect(handler, &DownloadHandler::finished, context, slot);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,7 +129,9 @@ void GeoIPManager::downloadDatabaseFile()
|
||||
{
|
||||
const QDateTime curDatetime = QDateTime::currentDateTimeUtc();
|
||||
const QString curUrl = DATABASE_URL.arg(QLocale::c().toString(curDatetime, u"yyyy-MM"));
|
||||
DownloadManager::instance()->download({curUrl}, this, &GeoIPManager::downloadFinished);
|
||||
DownloadManager::instance()->download(
|
||||
{curUrl}, Preferences::instance()->useProxyForGeneralPurposes()
|
||||
, this, &GeoIPManager::downloadFinished);
|
||||
}
|
||||
|
||||
QString GeoIPManager::lookup(const QHostAddress &hostAddr) const
|
||||
|
||||
@@ -35,8 +35,10 @@ bool Net::operator==(const ProxyConfiguration &left, const ProxyConfiguration &r
|
||||
return (left.type == right.type)
|
||||
&& (left.ip == right.ip)
|
||||
&& (left.port == right.port)
|
||||
&& (left.authEnabled == right.authEnabled)
|
||||
&& (left.username == right.username)
|
||||
&& (left.password == right.password);
|
||||
&& (left.password == right.password)
|
||||
&& (left.hostnameLookupEnabled == right.hostnameLookupEnabled);
|
||||
}
|
||||
|
||||
bool Net::operator!=(const ProxyConfiguration &left, const ProxyConfiguration &right)
|
||||
@@ -49,22 +51,24 @@ using namespace Net;
|
||||
ProxyConfigurationManager *ProxyConfigurationManager::m_instance = nullptr;
|
||||
|
||||
ProxyConfigurationManager::ProxyConfigurationManager(QObject *parent)
|
||||
: QObject {parent}
|
||||
, m_storeProxyOnlyForTorrents {SETTINGS_KEY(u"OnlyForTorrents"_qs)}
|
||||
: QObject(parent)
|
||||
, m_storeProxyType {SETTINGS_KEY(u"Type"_qs)}
|
||||
, m_storeProxyIP {SETTINGS_KEY(u"IP"_qs)}
|
||||
, m_storeProxyPort {SETTINGS_KEY(u"Port"_qs)}
|
||||
, m_storeProxyAuthEnabled {SETTINGS_KEY(u"AuthEnabled"_qs)}
|
||||
, m_storeProxyUsername {SETTINGS_KEY(u"Username"_qs)}
|
||||
, m_storeProxyPassword {SETTINGS_KEY(u"Password"_qs)}
|
||||
, m_storeProxyHostnameLookupEnabled {SETTINGS_KEY(u"HostnameLookupEnabled"_qs)}
|
||||
{
|
||||
m_config.type = m_storeProxyType.get(ProxyType::None);
|
||||
if ((m_config.type < ProxyType::None) || (m_config.type > ProxyType::SOCKS4))
|
||||
m_config.type = ProxyType::None;
|
||||
m_config.type = m_storeProxyType.get(ProxyType::HTTP);
|
||||
if ((m_config.type < ProxyType::HTTP) || (m_config.type > ProxyType::SOCKS4))
|
||||
m_config.type = ProxyType::HTTP;
|
||||
m_config.ip = m_storeProxyIP.get(u"0.0.0.0"_qs);
|
||||
m_config.port = m_storeProxyPort.get(8080);
|
||||
m_config.authEnabled = m_storeProxyAuthEnabled;
|
||||
m_config.username = m_storeProxyUsername;
|
||||
m_config.password = m_storeProxyPassword;
|
||||
configureProxy();
|
||||
m_config.hostnameLookupEnabled = m_storeProxyHostnameLookupEnabled.get(true);
|
||||
}
|
||||
|
||||
void ProxyConfigurationManager::initInstance()
|
||||
@@ -97,62 +101,11 @@ void ProxyConfigurationManager::setProxyConfiguration(const ProxyConfiguration &
|
||||
m_storeProxyType = config.type;
|
||||
m_storeProxyIP = config.ip;
|
||||
m_storeProxyPort = config.port;
|
||||
m_storeProxyAuthEnabled = config.authEnabled;
|
||||
m_storeProxyUsername = config.username;
|
||||
m_storeProxyPassword = config.password;
|
||||
configureProxy();
|
||||
m_storeProxyHostnameLookupEnabled = config.hostnameLookupEnabled;
|
||||
|
||||
emit proxyConfigurationChanged();
|
||||
}
|
||||
}
|
||||
|
||||
bool ProxyConfigurationManager::isProxyOnlyForTorrents() const
|
||||
{
|
||||
return m_storeProxyOnlyForTorrents || (m_config.type == ProxyType::SOCKS4);
|
||||
}
|
||||
|
||||
void ProxyConfigurationManager::setProxyOnlyForTorrents(const bool onlyForTorrents)
|
||||
{
|
||||
m_storeProxyOnlyForTorrents = onlyForTorrents;
|
||||
}
|
||||
|
||||
bool ProxyConfigurationManager::isAuthenticationRequired() const
|
||||
{
|
||||
return m_config.type == ProxyType::SOCKS5_PW
|
||||
|| m_config.type == ProxyType::HTTP_PW;
|
||||
}
|
||||
|
||||
void ProxyConfigurationManager::configureProxy()
|
||||
{
|
||||
// Define environment variables for urllib in search engine plugins
|
||||
QString proxyStrHTTP, proxyStrSOCK;
|
||||
if (!isProxyOnlyForTorrents())
|
||||
{
|
||||
switch (m_config.type)
|
||||
{
|
||||
case ProxyType::HTTP_PW:
|
||||
proxyStrHTTP = u"http://%1:%2@%3:%4"_qs.arg(m_config.username
|
||||
, m_config.password, m_config.ip, QString::number(m_config.port));
|
||||
break;
|
||||
case ProxyType::HTTP:
|
||||
proxyStrHTTP = u"http://%1:%2"_qs.arg(m_config.ip, QString::number(m_config.port));
|
||||
break;
|
||||
case ProxyType::SOCKS5:
|
||||
proxyStrSOCK = u"%1:%2"_qs.arg(m_config.ip, QString::number(m_config.port));
|
||||
break;
|
||||
case ProxyType::SOCKS5_PW:
|
||||
proxyStrSOCK = u"%1:%2@%3:%4"_qs.arg(m_config.username
|
||||
, m_config.password, m_config.ip, QString::number(m_config.port));
|
||||
break;
|
||||
default:
|
||||
qDebug("Disabling HTTP communications proxy");
|
||||
}
|
||||
|
||||
qDebug("HTTP communications proxy string: %s"
|
||||
, qUtf8Printable((m_config.type == ProxyType::SOCKS5) || (m_config.type == ProxyType::SOCKS5_PW)
|
||||
? proxyStrSOCK : proxyStrHTTP));
|
||||
}
|
||||
|
||||
qputenv("http_proxy", proxyStrHTTP.toLocal8Bit());
|
||||
qputenv("https_proxy", proxyStrHTTP.toLocal8Bit());
|
||||
qputenv("sock_proxy", proxyStrSOCK.toLocal8Bit());
|
||||
}
|
||||
|
||||
@@ -39,22 +39,21 @@ namespace Net
|
||||
|
||||
enum class ProxyType
|
||||
{
|
||||
None = 0,
|
||||
HTTP = 1,
|
||||
SOCKS5 = 2,
|
||||
HTTP_PW = 3,
|
||||
SOCKS5_PW = 4,
|
||||
SOCKS4 = 5
|
||||
};
|
||||
Q_ENUM_NS(ProxyType)
|
||||
|
||||
struct ProxyConfiguration
|
||||
{
|
||||
ProxyType type = ProxyType::None;
|
||||
ProxyType type = ProxyType::HTTP;
|
||||
QString ip = u"0.0.0.0"_qs;
|
||||
ushort port = 8080;
|
||||
bool authEnabled = false;
|
||||
QString username;
|
||||
QString password;
|
||||
bool hostnameLookupEnabled = true;
|
||||
};
|
||||
bool operator==(const ProxyConfiguration &left, const ProxyConfiguration &right);
|
||||
bool operator!=(const ProxyConfiguration &left, const ProxyConfiguration &right);
|
||||
@@ -74,24 +73,19 @@ namespace Net
|
||||
|
||||
ProxyConfiguration proxyConfiguration() const;
|
||||
void setProxyConfiguration(const ProxyConfiguration &config);
|
||||
bool isProxyOnlyForTorrents() const;
|
||||
void setProxyOnlyForTorrents(bool onlyForTorrents);
|
||||
|
||||
bool isAuthenticationRequired() const;
|
||||
|
||||
signals:
|
||||
void proxyConfigurationChanged();
|
||||
|
||||
private:
|
||||
void configureProxy();
|
||||
|
||||
static ProxyConfigurationManager *m_instance;
|
||||
ProxyConfiguration m_config;
|
||||
SettingValue<bool> m_storeProxyOnlyForTorrents;
|
||||
SettingValue<ProxyType> m_storeProxyType;
|
||||
SettingValue<QString> m_storeProxyIP;
|
||||
SettingValue<ushort> m_storeProxyPort;
|
||||
SettingValue<bool> m_storeProxyAuthEnabled;
|
||||
SettingValue<QString> m_storeProxyUsername;
|
||||
SettingValue<QString> m_storeProxyPassword;
|
||||
SettingValue<bool> m_storeProxyHostnameLookupEnabled;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1619,6 +1619,37 @@ void Preferences::setNetworkCookies(const QList<QNetworkCookie> &cookies)
|
||||
setValue(u"Network/Cookies"_qs, rawCookies);
|
||||
}
|
||||
|
||||
bool Preferences::useProxyForBT() const
|
||||
{
|
||||
return value<bool>(u"Network/Proxy/Profiles/BitTorrent"_qs);
|
||||
}
|
||||
|
||||
void Preferences::setUseProxyForBT(const bool value)
|
||||
{
|
||||
setValue(u"Network/Proxy/Profiles/BitTorrent"_qs, value);
|
||||
}
|
||||
|
||||
bool Preferences::useProxyForRSS() const
|
||||
{
|
||||
return value<bool>(u"Network/Proxy/Profiles/RSS"_qs);
|
||||
}
|
||||
|
||||
void Preferences::setUseProxyForRSS(const bool value)
|
||||
{
|
||||
setValue(u"Network/Proxy/Profiles/RSS"_qs, value);
|
||||
}
|
||||
|
||||
bool Preferences::useProxyForGeneralPurposes() const
|
||||
{
|
||||
return value<bool>(u"Network/Proxy/Profiles/Misc"_qs);
|
||||
}
|
||||
|
||||
|
||||
void Preferences::setUseProxyForGeneralPurposes(const bool value)
|
||||
{
|
||||
setValue(u"Network/Proxy/Profiles/Misc"_qs, value);
|
||||
}
|
||||
|
||||
bool Preferences::isSpeedWidgetEnabled() const
|
||||
{
|
||||
return value(u"SpeedWidget/Enabled"_qs, true);
|
||||
|
||||
@@ -397,6 +397,13 @@ public:
|
||||
QList<QNetworkCookie> getNetworkCookies() const;
|
||||
void setNetworkCookies(const QList<QNetworkCookie> &cookies);
|
||||
|
||||
bool useProxyForBT() const;
|
||||
void setUseProxyForBT(bool value);
|
||||
bool useProxyForRSS() const;
|
||||
void setUseProxyForRSS(bool value);
|
||||
bool useProxyForGeneralPurposes() const;
|
||||
void setUseProxyForGeneralPurposes(bool value);
|
||||
|
||||
// SpeedWidget
|
||||
bool isSpeedWidgetEnabled() const;
|
||||
void setSpeedWidgetEnabled(bool enabled);
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
#include "base/global.h"
|
||||
#include "base/logger.h"
|
||||
#include "base/net/downloadmanager.h"
|
||||
#include "base/preferences.h"
|
||||
#include "base/profile.h"
|
||||
#include "base/utils/fs.h"
|
||||
#include "feed_serializer.h"
|
||||
@@ -148,7 +149,7 @@ void Feed::refresh()
|
||||
|
||||
// NOTE: Should we allow manually refreshing for disabled session?
|
||||
|
||||
m_downloadHandler = Net::DownloadManager::instance()->download(m_url);
|
||||
m_downloadHandler = Net::DownloadManager::instance()->download(m_url, Preferences::instance()->useProxyForRSS());
|
||||
connect(m_downloadHandler, &Net::DownloadHandler::finished, this, &Feed::handleDownloadFinished);
|
||||
|
||||
if (!m_iconPath.exists())
|
||||
@@ -378,7 +379,7 @@ void Feed::downloadIcon()
|
||||
const auto iconUrl = u"%1://%2/favicon.ico"_qs.arg(url.scheme(), url.host());
|
||||
Net::DownloadManager::instance()->download(
|
||||
Net::DownloadRequest(iconUrl).saveToFile(true).destFileName(m_iconPath)
|
||||
, this, &Feed::handleIconDownloadFinished);
|
||||
, Preferences::instance()->useProxyForRSS(), this, &Feed::handleIconDownloadFinished);
|
||||
}
|
||||
|
||||
int Feed::updateArticles(const QList<QVariantHash> &loadedArticles)
|
||||
|
||||
@@ -38,10 +38,12 @@
|
||||
#include <QDomNode>
|
||||
#include <QPointer>
|
||||
#include <QProcess>
|
||||
#include <QUrl>
|
||||
|
||||
#include "base/global.h"
|
||||
#include "base/logger.h"
|
||||
#include "base/net/downloadmanager.h"
|
||||
#include "base/net/proxyconfigurationmanager.h"
|
||||
#include "base/preferences.h"
|
||||
#include "base/profile.h"
|
||||
#include "base/utils/bytearray.h"
|
||||
@@ -90,6 +92,12 @@ SearchPluginManager::SearchPluginManager()
|
||||
Q_ASSERT(!m_instance); // only one instance is allowed
|
||||
m_instance = this;
|
||||
|
||||
connect(Net::ProxyConfigurationManager::instance(), &Net::ProxyConfigurationManager::proxyConfigurationChanged
|
||||
, this, &SearchPluginManager::applyProxySettings);
|
||||
connect(Preferences::instance(), &Preferences::changed
|
||||
, this, &SearchPluginManager::applyProxySettings);
|
||||
applyProxySettings();
|
||||
|
||||
updateNova();
|
||||
update();
|
||||
}
|
||||
@@ -207,7 +215,8 @@ void SearchPluginManager::installPlugin(const QString &source)
|
||||
{
|
||||
using namespace Net;
|
||||
DownloadManager::instance()->download(DownloadRequest(source).saveToFile(true)
|
||||
, this, &SearchPluginManager::pluginDownloadFinished);
|
||||
, Preferences::instance()->useProxyForGeneralPurposes()
|
||||
, this, &SearchPluginManager::pluginDownloadFinished);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -323,7 +332,8 @@ void SearchPluginManager::checkForUpdates()
|
||||
// Download version file from update server
|
||||
using namespace Net;
|
||||
DownloadManager::instance()->download({m_updateUrl + u"versions.txt"}
|
||||
, this, &SearchPluginManager::versionInfoDownloadFinished);
|
||||
, Preferences::instance()->useProxyForGeneralPurposes()
|
||||
, this, &SearchPluginManager::versionInfoDownloadFinished);
|
||||
}
|
||||
|
||||
SearchDownloadHandler *SearchPluginManager::downloadTorrent(const QString &siteUrl, const QString &url)
|
||||
@@ -378,6 +388,54 @@ Path SearchPluginManager::engineLocation()
|
||||
return location;
|
||||
}
|
||||
|
||||
void SearchPluginManager::applyProxySettings()
|
||||
{
|
||||
const auto *proxyManager = Net::ProxyConfigurationManager::instance();
|
||||
const Net::ProxyConfiguration proxyConfig = proxyManager->proxyConfiguration();
|
||||
|
||||
// Define environment variables for urllib in search engine plugins
|
||||
QString proxyStrHTTP, proxyStrSOCK;
|
||||
if (Preferences::instance()->useProxyForGeneralPurposes())
|
||||
{
|
||||
switch (proxyConfig.type)
|
||||
{
|
||||
case Net::ProxyType::HTTP:
|
||||
if (proxyConfig.authEnabled)
|
||||
{
|
||||
proxyStrHTTP = u"http://%1:%2@%3:%4"_qs.arg(proxyConfig.username
|
||||
, proxyConfig.password, proxyConfig.ip, QString::number(proxyConfig.port));
|
||||
}
|
||||
else
|
||||
{
|
||||
proxyStrHTTP = u"http://%1:%2"_qs.arg(proxyConfig.ip, QString::number(proxyConfig.port));
|
||||
}
|
||||
break;
|
||||
|
||||
case Net::ProxyType::SOCKS5:
|
||||
if (proxyConfig.authEnabled)
|
||||
{
|
||||
proxyStrSOCK = u"%1:%2@%3:%4"_qs.arg(proxyConfig.username
|
||||
, proxyConfig.password, proxyConfig.ip, QString::number(proxyConfig.port));
|
||||
}
|
||||
else
|
||||
{
|
||||
proxyStrSOCK = u"%1:%2"_qs.arg(proxyConfig.ip, QString::number(proxyConfig.port));
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
qDebug("Disabling HTTP communications proxy");
|
||||
}
|
||||
|
||||
qDebug("HTTP communications proxy string: %s"
|
||||
, qUtf8Printable((proxyConfig.type == Net::ProxyType::SOCKS5) ? proxyStrSOCK : proxyStrHTTP));
|
||||
}
|
||||
|
||||
qputenv("http_proxy", proxyStrHTTP.toLocal8Bit());
|
||||
qputenv("https_proxy", proxyStrHTTP.toLocal8Bit());
|
||||
qputenv("sock_proxy", proxyStrSOCK.toLocal8Bit());
|
||||
}
|
||||
|
||||
void SearchPluginManager::versionInfoDownloadFinished(const Net::DownloadResult &result)
|
||||
{
|
||||
if (result.status == Net::DownloadStatus::Success)
|
||||
|
||||
@@ -104,6 +104,7 @@ signals:
|
||||
void checkForUpdatesFailed(const QString &reason);
|
||||
|
||||
private:
|
||||
void applyProxySettings();
|
||||
void update();
|
||||
void updateNova();
|
||||
void parseVersionInfo(const QByteArray &info);
|
||||
|
||||
Reference in New Issue
Block a user