mirror of
https://github.com/d47081/qBittorrent.git
synced 2025-01-23 21:14:33 +00:00
parent
a9a6b74416
commit
8d438e159c
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Bittorrent Client using Qt and libtorrent.
|
* Bittorrent Client using Qt and libtorrent.
|
||||||
* Copyright (C) 2015 Vladimir Golovnev <glassez@yandex.ru>
|
* Copyright (C) 2015, 2018 Vladimir Golovnev <glassez@yandex.ru>
|
||||||
* Copyright (C) 2006 Christophe Dumez <chris@qbittorrent.org>
|
* Copyright (C) 2006 Christophe Dumez <chris@qbittorrent.org>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
@ -29,6 +29,7 @@
|
|||||||
|
|
||||||
#include "downloadhandler.h"
|
#include "downloadhandler.h"
|
||||||
|
|
||||||
|
#include <QCoreApplication>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QNetworkAccessManager>
|
#include <QNetworkAccessManager>
|
||||||
#include <QNetworkCookie>
|
#include <QNetworkCookie>
|
||||||
@ -43,32 +44,46 @@
|
|||||||
#include "base/utils/misc.h"
|
#include "base/utils/misc.h"
|
||||||
#include "downloadmanager.h"
|
#include "downloadmanager.h"
|
||||||
|
|
||||||
static QString errorCodeToString(QNetworkReply::NetworkError status);
|
namespace
|
||||||
|
{
|
||||||
|
QString tr(const char *message);
|
||||||
|
QString errorCodeToString(QNetworkReply::NetworkError status);
|
||||||
|
}
|
||||||
|
|
||||||
using namespace Net;
|
Net::DownloadHandler::DownloadHandler(QNetworkReply *reply, DownloadManager *manager, const DownloadRequest &downloadRequest)
|
||||||
|
|
||||||
DownloadHandler::DownloadHandler(QNetworkReply *reply, DownloadManager *manager, const DownloadRequest &downloadRequest)
|
|
||||||
: QObject(manager)
|
: QObject(manager)
|
||||||
, m_reply(reply)
|
, m_reply(reply)
|
||||||
, m_manager(manager)
|
, m_manager(manager)
|
||||||
, m_downloadRequest(downloadRequest)
|
, m_downloadRequest(downloadRequest)
|
||||||
{
|
{
|
||||||
init();
|
if (reply)
|
||||||
|
assignNetworkReply(reply);
|
||||||
}
|
}
|
||||||
|
|
||||||
DownloadHandler::~DownloadHandler()
|
Net::DownloadHandler::~DownloadHandler()
|
||||||
{
|
{
|
||||||
if (m_reply)
|
if (m_reply)
|
||||||
delete m_reply;
|
delete m_reply;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Net::DownloadHandler::assignNetworkReply(QNetworkReply *reply)
|
||||||
|
{
|
||||||
|
Q_ASSERT(reply);
|
||||||
|
|
||||||
|
m_reply = reply;
|
||||||
|
m_reply->setParent(this);
|
||||||
|
if (m_downloadRequest.limit() > 0)
|
||||||
|
connect(m_reply, &QNetworkReply::downloadProgress, this, &Net::DownloadHandler::checkDownloadSize);
|
||||||
|
connect(m_reply, &QNetworkReply::finished, this, &Net::DownloadHandler::processFinishedDownload);
|
||||||
|
}
|
||||||
|
|
||||||
// Returns original url
|
// Returns original url
|
||||||
QString DownloadHandler::url() const
|
QString Net::DownloadHandler::url() const
|
||||||
{
|
{
|
||||||
return m_downloadRequest.url();
|
return m_downloadRequest.url();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DownloadHandler::processFinishedDownload()
|
void Net::DownloadHandler::processFinishedDownload()
|
||||||
{
|
{
|
||||||
QString url = m_reply->url().toString();
|
QString url = m_reply->url().toString();
|
||||||
qDebug("Download finished: %s", qUtf8Printable(url));
|
qDebug("Download finished: %s", qUtf8Printable(url));
|
||||||
@ -110,7 +125,7 @@ void DownloadHandler::processFinishedDownload()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DownloadHandler::checkDownloadSize(qint64 bytesReceived, qint64 bytesTotal)
|
void Net::DownloadHandler::checkDownloadSize(qint64 bytesReceived, qint64 bytesTotal)
|
||||||
{
|
{
|
||||||
QString msg = tr("The file size is %1. It exceeds the download limit of %2.");
|
QString msg = tr("The file size is %1. It exceeds the download limit of %2.");
|
||||||
|
|
||||||
@ -130,15 +145,7 @@ void DownloadHandler::checkDownloadSize(qint64 bytesReceived, qint64 bytesTotal)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DownloadHandler::init()
|
bool Net::DownloadHandler::saveToFile(const QByteArray &replyData, QString &filePath)
|
||||||
{
|
|
||||||
m_reply->setParent(this);
|
|
||||||
if (m_downloadRequest.limit() > 0)
|
|
||||||
connect(m_reply, &QNetworkReply::downloadProgress, this, &Net::DownloadHandler::checkDownloadSize);
|
|
||||||
connect(m_reply, &QNetworkReply::finished, this, &Net::DownloadHandler::processFinishedDownload);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DownloadHandler::saveToFile(const QByteArray &replyData, QString &filePath)
|
|
||||||
{
|
{
|
||||||
QTemporaryFile *tmpfile = new QTemporaryFile(Utils::Fs::tempPath() + "XXXXXX");
|
QTemporaryFile *tmpfile = new QTemporaryFile(Utils::Fs::tempPath() + "XXXXXX");
|
||||||
if (!tmpfile->open()) {
|
if (!tmpfile->open()) {
|
||||||
@ -165,14 +172,14 @@ bool DownloadHandler::saveToFile(const QByteArray &replyData, QString &filePath)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DownloadHandler::handleRedirection(QUrl newUrl)
|
void Net::DownloadHandler::handleRedirection(QUrl newUrl)
|
||||||
{
|
{
|
||||||
// Resolve relative urls
|
// Resolve relative urls
|
||||||
if (newUrl.isRelative())
|
if (newUrl.isRelative())
|
||||||
newUrl = m_reply->url().resolved(newUrl);
|
newUrl = m_reply->url().resolved(newUrl);
|
||||||
|
|
||||||
const QString newUrlString = newUrl.toString();
|
const QString newUrlString = newUrl.toString();
|
||||||
qDebug("Redirecting from %s to %s", qUtf8Printable(m_reply->url().toString()), qUtf8Printable(newUrlString));
|
qDebug("Redirecting from %s to %s...", qUtf8Printable(m_reply->url().toString()), qUtf8Printable(newUrlString));
|
||||||
|
|
||||||
// Redirect to magnet workaround
|
// Redirect to magnet workaround
|
||||||
if (newUrlString.startsWith("magnet:", Qt::CaseInsensitive)) {
|
if (newUrlString.startsWith("magnet:", Qt::CaseInsensitive)) {
|
||||||
@ -186,61 +193,83 @@ void DownloadHandler::handleRedirection(QUrl newUrl)
|
|||||||
this->deleteLater();
|
this->deleteLater();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
DownloadHandler *tmp = m_manager->download(DownloadRequest(m_downloadRequest).url(newUrlString));
|
DownloadHandler *redirected = m_manager->download(DownloadRequest(m_downloadRequest).url(newUrlString));
|
||||||
m_reply->deleteLater();
|
connect(redirected, &DownloadHandler::destroyed, this, &DownloadHandler::deleteLater);
|
||||||
m_reply = tmp->m_reply;
|
connect(redirected, &DownloadHandler::downloadFailed, this, [this](const QString &, const QString &reason)
|
||||||
init();
|
{
|
||||||
tmp->m_reply = nullptr;
|
emit downloadFailed(url(), reason);
|
||||||
delete tmp;
|
});
|
||||||
|
connect(redirected, &DownloadHandler::redirectedToMagnet, this, [this](const QString &, const QString &magnetUri)
|
||||||
|
{
|
||||||
|
emit redirectedToMagnet(url(), magnetUri);
|
||||||
|
});
|
||||||
|
connect(redirected, static_cast<void (DownloadHandler::*)(const QString &, const QString &)>(&DownloadHandler::downloadFinished)
|
||||||
|
, this, [this](const QString &, const QString &fileName)
|
||||||
|
{
|
||||||
|
emit downloadFinished(url(), fileName);
|
||||||
|
});
|
||||||
|
connect(redirected, static_cast<void (DownloadHandler::*)(const QString &, const QByteArray &)>(&DownloadHandler::downloadFinished)
|
||||||
|
, this, [this](const QString &, const QByteArray &data)
|
||||||
|
{
|
||||||
|
emit downloadFinished(url(), data);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QString errorCodeToString(QNetworkReply::NetworkError status)
|
namespace
|
||||||
{
|
{
|
||||||
switch (status) {
|
QString tr(const char *message)
|
||||||
case QNetworkReply::HostNotFoundError:
|
{
|
||||||
return QObject::tr("The remote host name was not found (invalid hostname)");
|
return QCoreApplication::translate("DownloadHandler", message);
|
||||||
case QNetworkReply::OperationCanceledError:
|
}
|
||||||
return QObject::tr("The operation was canceled");
|
|
||||||
case QNetworkReply::RemoteHostClosedError:
|
QString errorCodeToString(QNetworkReply::NetworkError status)
|
||||||
return QObject::tr("The remote server closed the connection prematurely, before the entire reply was received and processed");
|
{
|
||||||
case QNetworkReply::TimeoutError:
|
switch (status) {
|
||||||
return QObject::tr("The connection to the remote server timed out");
|
case QNetworkReply::HostNotFoundError:
|
||||||
case QNetworkReply::SslHandshakeFailedError:
|
return tr("The remote host name was not found (invalid hostname)");
|
||||||
return QObject::tr("SSL/TLS handshake failed");
|
case QNetworkReply::OperationCanceledError:
|
||||||
case QNetworkReply::ConnectionRefusedError:
|
return tr("The operation was canceled");
|
||||||
return QObject::tr("The remote server refused the connection");
|
case QNetworkReply::RemoteHostClosedError:
|
||||||
case QNetworkReply::ProxyConnectionRefusedError:
|
return tr("The remote server closed the connection prematurely, before the entire reply was received and processed");
|
||||||
return QObject::tr("The connection to the proxy server was refused");
|
case QNetworkReply::TimeoutError:
|
||||||
case QNetworkReply::ProxyConnectionClosedError:
|
return tr("The connection to the remote server timed out");
|
||||||
return QObject::tr("The proxy server closed the connection prematurely");
|
case QNetworkReply::SslHandshakeFailedError:
|
||||||
case QNetworkReply::ProxyNotFoundError:
|
return tr("SSL/TLS handshake failed");
|
||||||
return QObject::tr("The proxy host name was not found");
|
case QNetworkReply::ConnectionRefusedError:
|
||||||
case QNetworkReply::ProxyTimeoutError:
|
return tr("The remote server refused the connection");
|
||||||
return QObject::tr("The connection to the proxy timed out or the proxy did not reply in time to the request sent");
|
case QNetworkReply::ProxyConnectionRefusedError:
|
||||||
case QNetworkReply::ProxyAuthenticationRequiredError:
|
return tr("The connection to the proxy server was refused");
|
||||||
return QObject::tr("The proxy requires authentication in order to honor the request but did not accept any credentials offered");
|
case QNetworkReply::ProxyConnectionClosedError:
|
||||||
case QNetworkReply::ContentAccessDenied:
|
return tr("The proxy server closed the connection prematurely");
|
||||||
return QObject::tr("The access to the remote content was denied (401)");
|
case QNetworkReply::ProxyNotFoundError:
|
||||||
case QNetworkReply::ContentOperationNotPermittedError:
|
return tr("The proxy host name was not found");
|
||||||
return QObject::tr("The operation requested on the remote content is not permitted");
|
case QNetworkReply::ProxyTimeoutError:
|
||||||
case QNetworkReply::ContentNotFoundError:
|
return tr("The connection to the proxy timed out or the proxy did not reply in time to the request sent");
|
||||||
return QObject::tr("The remote content was not found at the server (404)");
|
case QNetworkReply::ProxyAuthenticationRequiredError:
|
||||||
case QNetworkReply::AuthenticationRequiredError:
|
return tr("The proxy requires authentication in order to honor the request but did not accept any credentials offered");
|
||||||
return QObject::tr("The remote server requires authentication to serve the content but the credentials provided were not accepted");
|
case QNetworkReply::ContentAccessDenied:
|
||||||
case QNetworkReply::ProtocolUnknownError:
|
return tr("The access to the remote content was denied (401)");
|
||||||
return QObject::tr("The Network Access API cannot honor the request because the protocol is not known");
|
case QNetworkReply::ContentOperationNotPermittedError:
|
||||||
case QNetworkReply::ProtocolInvalidOperationError:
|
return tr("The operation requested on the remote content is not permitted");
|
||||||
return QObject::tr("The requested operation is invalid for this protocol");
|
case QNetworkReply::ContentNotFoundError:
|
||||||
case QNetworkReply::UnknownNetworkError:
|
return tr("The remote content was not found at the server (404)");
|
||||||
return QObject::tr("An unknown network-related error was detected");
|
case QNetworkReply::AuthenticationRequiredError:
|
||||||
case QNetworkReply::UnknownProxyError:
|
return tr("The remote server requires authentication to serve the content but the credentials provided were not accepted");
|
||||||
return QObject::tr("An unknown proxy-related error was detected");
|
case QNetworkReply::ProtocolUnknownError:
|
||||||
case QNetworkReply::UnknownContentError:
|
return tr("The Network Access API cannot honor the request because the protocol is not known");
|
||||||
return QObject::tr("An unknown error related to the remote content was detected");
|
case QNetworkReply::ProtocolInvalidOperationError:
|
||||||
case QNetworkReply::ProtocolFailure:
|
return tr("The requested operation is invalid for this protocol");
|
||||||
return QObject::tr("A breakdown in protocol was detected");
|
case QNetworkReply::UnknownNetworkError:
|
||||||
default:
|
return tr("An unknown network-related error was detected");
|
||||||
return QObject::tr("Unknown error");
|
case QNetworkReply::UnknownProxyError:
|
||||||
|
return tr("An unknown proxy-related error was detected");
|
||||||
|
case QNetworkReply::UnknownContentError:
|
||||||
|
return tr("An unknown error related to the remote content was detected");
|
||||||
|
case QNetworkReply::ProtocolFailure:
|
||||||
|
return tr("A breakdown in protocol was detected");
|
||||||
|
default:
|
||||||
|
return tr("Unknown error");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Bittorrent Client using Qt and libtorrent.
|
* Bittorrent Client using Qt and libtorrent.
|
||||||
* Copyright (C) 2015 Vladimir Golovnev <glassez@yandex.ru>
|
* Copyright (C) 2015, 2018 Vladimir Golovnev <glassez@yandex.ru>
|
||||||
* Copyright (C) 2006 Christophe Dumez <chris@qbittorrent.org>
|
* Copyright (C) 2006 Christophe Dumez <chris@qbittorrent.org>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
@ -33,7 +33,6 @@
|
|||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include "downloadmanager.h"
|
#include "downloadmanager.h"
|
||||||
|
|
||||||
class QNetworkAccessManager;
|
|
||||||
class QNetworkReply;
|
class QNetworkReply;
|
||||||
class QUrl;
|
class QUrl;
|
||||||
|
|
||||||
@ -44,10 +43,14 @@ namespace Net
|
|||||||
class DownloadHandler : public QObject
|
class DownloadHandler : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
Q_DISABLE_COPY(DownloadHandler)
|
||||||
|
|
||||||
|
friend class DownloadManager;
|
||||||
|
|
||||||
|
DownloadHandler(QNetworkReply *reply, DownloadManager *manager, const DownloadRequest &downloadRequest);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DownloadHandler(QNetworkReply *reply, DownloadManager *manager, const DownloadRequest &downloadRequest);
|
~DownloadHandler() override;
|
||||||
~DownloadHandler();
|
|
||||||
|
|
||||||
QString url() const;
|
QString url() const;
|
||||||
|
|
||||||
@ -62,7 +65,7 @@ namespace Net
|
|||||||
void checkDownloadSize(qint64 bytesReceived, qint64 bytesTotal);
|
void checkDownloadSize(qint64 bytesReceived, qint64 bytesTotal);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void init();
|
void assignNetworkReply(QNetworkReply *reply);
|
||||||
bool saveToFile(const QByteArray &replyData, QString &filePath);
|
bool saveToFile(const QByteArray &replyData, QString &filePath);
|
||||||
void handleRedirection(QUrl newUrl);
|
void handleRedirection(QUrl newUrl);
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Bittorrent Client using Qt and libtorrent.
|
* Bittorrent Client using Qt and libtorrent.
|
||||||
* Copyright (C) 2015 Vladimir Golovnev <glassez@yandex.ru>
|
* Copyright (C) 2015, 2018 Vladimir Golovnev <glassez@yandex.ru>
|
||||||
* Copyright (C) 2006 Christophe Dumez <chris@qbittorrent.org>
|
* Copyright (C) 2006 Christophe Dumez <chris@qbittorrent.org>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
@ -103,28 +103,46 @@ namespace
|
|||||||
return QNetworkCookieJar::setCookiesFromUrl(cookies, url);
|
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());
|
||||||
|
// Accept gzip
|
||||||
|
request.setRawHeader("Accept-Encoding", "gzip");
|
||||||
|
|
||||||
|
return request;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
using namespace Net;
|
Net::DownloadManager *Net::DownloadManager::m_instance = nullptr;
|
||||||
|
|
||||||
DownloadManager *DownloadManager::m_instance = nullptr;
|
Net::DownloadManager::DownloadManager(QObject *parent)
|
||||||
|
|
||||||
DownloadManager::DownloadManager(QObject *parent)
|
|
||||||
: QObject(parent)
|
: QObject(parent)
|
||||||
{
|
{
|
||||||
#ifndef QT_NO_OPENSSL
|
#ifndef QT_NO_OPENSSL
|
||||||
connect(&m_networkManager, &QNetworkAccessManager::sslErrors, this, &Net::DownloadManager::ignoreSslErrors);
|
connect(&m_networkManager, &QNetworkAccessManager::sslErrors, this, &Net::DownloadManager::ignoreSslErrors);
|
||||||
#endif
|
#endif
|
||||||
|
connect(&m_networkManager, &QNetworkAccessManager::finished, this, &DownloadManager::handleReplyFinished);
|
||||||
|
connect(ProxyConfigurationManager::instance(), &ProxyConfigurationManager::proxyConfigurationChanged
|
||||||
|
, this, &DownloadManager::applyProxySettings);
|
||||||
m_networkManager.setCookieJar(new NetworkCookieJar(this));
|
m_networkManager.setCookieJar(new NetworkCookieJar(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
void DownloadManager::initInstance()
|
void Net::DownloadManager::initInstance()
|
||||||
{
|
{
|
||||||
if (!m_instance)
|
if (!m_instance)
|
||||||
m_instance = new DownloadManager;
|
m_instance = new DownloadManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DownloadManager::freeInstance()
|
void Net::DownloadManager::freeInstance()
|
||||||
{
|
{
|
||||||
if (m_instance) {
|
if (m_instance) {
|
||||||
delete m_instance;
|
delete m_instance;
|
||||||
@ -132,64 +150,70 @@ void DownloadManager::freeInstance()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DownloadManager *DownloadManager::instance()
|
Net::DownloadManager *Net::DownloadManager::instance()
|
||||||
{
|
{
|
||||||
return m_instance;
|
return m_instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
DownloadHandler *DownloadManager::downloadUrl(const QString &url, bool saveToFile, qint64 limit, bool handleRedirectToMagnet, const QString &userAgent)
|
Net::DownloadHandler *Net::DownloadManager::downloadUrl(const QString &url, bool saveToFile, qint64 limit, bool handleRedirectToMagnet, const QString &userAgent)
|
||||||
{
|
{
|
||||||
return download(DownloadRequest(url).saveToFile(saveToFile).limit(limit).handleRedirectToMagnet(handleRedirectToMagnet).userAgent(userAgent));
|
return download(DownloadRequest(url).saveToFile(saveToFile).limit(limit).handleRedirectToMagnet(handleRedirectToMagnet).userAgent(userAgent));
|
||||||
}
|
}
|
||||||
|
|
||||||
DownloadHandler *DownloadManager::download(const DownloadRequest &downloadRequest)
|
Net::DownloadHandler *Net::DownloadManager::download(const DownloadRequest &downloadRequest)
|
||||||
{
|
{
|
||||||
// Update proxy settings
|
|
||||||
applyProxySettings();
|
|
||||||
|
|
||||||
// Process download request
|
// Process download request
|
||||||
QNetworkRequest request(downloadRequest.url());
|
const QNetworkRequest request = createNetworkRequest(downloadRequest);
|
||||||
|
const ServiceID id = ServiceID::fromURL(request.url());
|
||||||
|
const bool isSequentialService = m_sequentialServices.contains(id);
|
||||||
|
if (!isSequentialService || !m_busyServices.contains(id)) {
|
||||||
|
qDebug("Downloading %s...", qUtf8Printable(downloadRequest.url()));
|
||||||
|
if (isSequentialService)
|
||||||
|
m_busyServices.insert(id);
|
||||||
|
return new DownloadHandler {
|
||||||
|
m_networkManager.get(request), this, downloadRequest};
|
||||||
|
}
|
||||||
|
|
||||||
if (downloadRequest.userAgent().isEmpty())
|
auto *downloadHandler = new DownloadHandler {nullptr, this, downloadRequest};
|
||||||
request.setRawHeader("User-Agent", DEFAULT_USER_AGENT);
|
connect(downloadHandler, &DownloadHandler::destroyed, this, [this, id, downloadHandler]()
|
||||||
else
|
{
|
||||||
request.setRawHeader("User-Agent", downloadRequest.userAgent().toUtf8());
|
m_waitingJobs[id].removeOne(downloadHandler);
|
||||||
|
});
|
||||||
// Spoof HTTP Referer to allow adding torrent link from Torcache/KickAssTorrents
|
m_waitingJobs[id].enqueue(downloadHandler);
|
||||||
request.setRawHeader("Referer", request.url().toEncoded().data());
|
return downloadHandler;
|
||||||
|
|
||||||
qDebug("Downloading %s...", request.url().toEncoded().data());
|
|
||||||
// accept gzip
|
|
||||||
request.setRawHeader("Accept-Encoding", "gzip");
|
|
||||||
return new DownloadHandler(m_networkManager.get(request), this, downloadRequest);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<QNetworkCookie> DownloadManager::cookiesForUrl(const QUrl &url) const
|
void Net::DownloadManager::registerSequentialService(const Net::ServiceID &serviceID)
|
||||||
|
{
|
||||||
|
m_sequentialServices.insert(serviceID);
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<QNetworkCookie> Net::DownloadManager::cookiesForUrl(const QUrl &url) const
|
||||||
{
|
{
|
||||||
return m_networkManager.cookieJar()->cookiesForUrl(url);
|
return m_networkManager.cookieJar()->cookiesForUrl(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DownloadManager::setCookiesFromUrl(const QList<QNetworkCookie> &cookieList, const QUrl &url)
|
bool Net::DownloadManager::setCookiesFromUrl(const QList<QNetworkCookie> &cookieList, const QUrl &url)
|
||||||
{
|
{
|
||||||
return m_networkManager.cookieJar()->setCookiesFromUrl(cookieList, url);
|
return m_networkManager.cookieJar()->setCookiesFromUrl(cookieList, url);
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<QNetworkCookie> DownloadManager::allCookies() const
|
QList<QNetworkCookie> Net::DownloadManager::allCookies() const
|
||||||
{
|
{
|
||||||
return static_cast<NetworkCookieJar *>(m_networkManager.cookieJar())->allCookies();
|
return static_cast<NetworkCookieJar *>(m_networkManager.cookieJar())->allCookies();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DownloadManager::setAllCookies(const QList<QNetworkCookie> &cookieList)
|
void Net::DownloadManager::setAllCookies(const QList<QNetworkCookie> &cookieList)
|
||||||
{
|
{
|
||||||
static_cast<NetworkCookieJar *>(m_networkManager.cookieJar())->setAllCookies(cookieList);
|
static_cast<NetworkCookieJar *>(m_networkManager.cookieJar())->setAllCookies(cookieList);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DownloadManager::deleteCookie(const QNetworkCookie &cookie)
|
bool Net::DownloadManager::deleteCookie(const QNetworkCookie &cookie)
|
||||||
{
|
{
|
||||||
return static_cast<NetworkCookieJar *>(m_networkManager.cookieJar())->deleteCookie(cookie);
|
return static_cast<NetworkCookieJar *>(m_networkManager.cookieJar())->deleteCookie(cookie);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DownloadManager::applyProxySettings()
|
void Net::DownloadManager::applyProxySettings()
|
||||||
{
|
{
|
||||||
auto proxyManager = ProxyConfigurationManager::instance();
|
auto proxyManager = ProxyConfigurationManager::instance();
|
||||||
ProxyConfiguration proxyConfig = proxyManager->proxyConfiguration();
|
ProxyConfiguration proxyConfig = proxyManager->proxyConfiguration();
|
||||||
@ -210,7 +234,7 @@ void DownloadManager::applyProxySettings()
|
|||||||
}
|
}
|
||||||
// Authentication?
|
// Authentication?
|
||||||
if (proxyManager->isAuthenticationRequired()) {
|
if (proxyManager->isAuthenticationRequired()) {
|
||||||
qDebug("Proxy requires authentication, authenticating");
|
qDebug("Proxy requires authentication, authenticating...");
|
||||||
proxy.setUser(proxyConfig.username);
|
proxy.setUser(proxyConfig.username);
|
||||||
proxy.setPassword(proxyConfig.password);
|
proxy.setPassword(proxyConfig.password);
|
||||||
}
|
}
|
||||||
@ -222,8 +246,23 @@ void DownloadManager::applyProxySettings()
|
|||||||
m_networkManager.setProxy(proxy);
|
m_networkManager.setProxy(proxy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Net::DownloadManager::handleReplyFinished(QNetworkReply *reply)
|
||||||
|
{
|
||||||
|
const ServiceID id = ServiceID::fromURL(reply->url());
|
||||||
|
auto waitingJobsIter = m_waitingJobs.find(id);
|
||||||
|
if ((waitingJobsIter == m_waitingJobs.end()) || waitingJobsIter.value().isEmpty()) {
|
||||||
|
m_busyServices.remove(id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DownloadHandler *handler = waitingJobsIter.value().dequeue();
|
||||||
|
qDebug("Downloading %s...", qUtf8Printable(handler->m_downloadRequest.url()));
|
||||||
|
handler->assignNetworkReply(m_networkManager.get(createNetworkRequest(handler->m_downloadRequest)));
|
||||||
|
handler->disconnect(this);
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef QT_NO_OPENSSL
|
#ifndef QT_NO_OPENSSL
|
||||||
void DownloadManager::ignoreSslErrors(QNetworkReply *reply, const QList<QSslError> &errors)
|
void Net::DownloadManager::ignoreSslErrors(QNetworkReply *reply, const QList<QSslError> &errors)
|
||||||
{
|
{
|
||||||
Q_UNUSED(errors)
|
Q_UNUSED(errors)
|
||||||
// Ignore all SSL errors
|
// Ignore all SSL errors
|
||||||
@ -290,3 +329,18 @@ Net::DownloadRequest &Net::DownloadRequest::handleRedirectToMagnet(bool value)
|
|||||||
m_handleRedirectToMagnet = value;
|
m_handleRedirectToMagnet = value;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Net::ServiceID Net::ServiceID::fromURL(const QUrl &url)
|
||||||
|
{
|
||||||
|
return {url.host(), url.port(80)};
|
||||||
|
}
|
||||||
|
|
||||||
|
uint Net::qHash(const ServiceID &serviceID, uint seed)
|
||||||
|
{
|
||||||
|
return ::qHash(serviceID.hostName, seed) ^ serviceID.port;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Net::operator==(const ServiceID &lhs, const ServiceID &rhs)
|
||||||
|
{
|
||||||
|
return ((lhs.hostName == rhs.hostName) && (lhs.port == rhs.port));
|
||||||
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Bittorrent Client using Qt and libtorrent.
|
* Bittorrent Client using Qt and libtorrent.
|
||||||
* Copyright (C) 2015 Vladimir Golovnev <glassez@yandex.ru>
|
* Copyright (C) 2015, 2018 Vladimir Golovnev <glassez@yandex.ru>
|
||||||
* Copyright (C) 2006 Christophe Dumez <chris@qbittorrent.org>
|
* Copyright (C) 2006 Christophe Dumez <chris@qbittorrent.org>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
@ -30,8 +30,12 @@
|
|||||||
#ifndef NET_DOWNLOADMANAGER_H
|
#ifndef NET_DOWNLOADMANAGER_H
|
||||||
#define NET_DOWNLOADMANAGER_H
|
#define NET_DOWNLOADMANAGER_H
|
||||||
|
|
||||||
#include <QObject>
|
#include <QHash>
|
||||||
#include <QNetworkAccessManager>
|
#include <QNetworkAccessManager>
|
||||||
|
#include <QNetworkRequest>
|
||||||
|
#include <QObject>
|
||||||
|
#include <QQueue>
|
||||||
|
#include <QSet>
|
||||||
|
|
||||||
class QNetworkReply;
|
class QNetworkReply;
|
||||||
class QNetworkCookie;
|
class QNetworkCookie;
|
||||||
@ -71,6 +75,14 @@ namespace Net
|
|||||||
bool m_handleRedirectToMagnet = false;
|
bool m_handleRedirectToMagnet = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ServiceID
|
||||||
|
{
|
||||||
|
QString hostName;
|
||||||
|
int port;
|
||||||
|
|
||||||
|
static ServiceID fromURL(const QUrl &url);
|
||||||
|
};
|
||||||
|
|
||||||
class DownloadManager : public QObject
|
class DownloadManager : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@ -83,6 +95,9 @@ namespace Net
|
|||||||
|
|
||||||
DownloadHandler *downloadUrl(const QString &url, bool saveToFile = false, qint64 limit = 0, bool handleRedirectToMagnet = false, const QString &userAgent = "");
|
DownloadHandler *downloadUrl(const QString &url, bool saveToFile = false, qint64 limit = 0, bool handleRedirectToMagnet = false, const QString &userAgent = "");
|
||||||
DownloadHandler *download(const DownloadRequest &downloadRequest);
|
DownloadHandler *download(const DownloadRequest &downloadRequest);
|
||||||
|
|
||||||
|
void registerSequentialService(const ServiceID &serviceID);
|
||||||
|
|
||||||
QList<QNetworkCookie> cookiesForUrl(const QUrl &url) const;
|
QList<QNetworkCookie> cookiesForUrl(const QUrl &url) const;
|
||||||
bool setCookiesFromUrl(const QList<QNetworkCookie> &cookieList, const QUrl &url);
|
bool setCookiesFromUrl(const QList<QNetworkCookie> &cookieList, const QUrl &url);
|
||||||
QList<QNetworkCookie> allCookies() const;
|
QList<QNetworkCookie> allCookies() const;
|
||||||
@ -91,17 +106,25 @@ namespace Net
|
|||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
#ifndef QT_NO_OPENSSL
|
#ifndef QT_NO_OPENSSL
|
||||||
void ignoreSslErrors(QNetworkReply *,const QList<QSslError> &);
|
void ignoreSslErrors(QNetworkReply *, const QList<QSslError> &);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
explicit DownloadManager(QObject *parent = nullptr);
|
explicit DownloadManager(QObject *parent = nullptr);
|
||||||
|
|
||||||
void applyProxySettings();
|
void applyProxySettings();
|
||||||
|
void handleReplyFinished(QNetworkReply *reply);
|
||||||
|
|
||||||
static DownloadManager *m_instance;
|
static DownloadManager *m_instance;
|
||||||
QNetworkAccessManager m_networkManager;
|
QNetworkAccessManager m_networkManager;
|
||||||
|
|
||||||
|
QSet<ServiceID> m_sequentialServices;
|
||||||
|
QSet<ServiceID> m_busyServices;
|
||||||
|
QHash<ServiceID, QQueue<DownloadHandler *>> m_waitingJobs;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
uint qHash(const ServiceID &serviceID, uint seed);
|
||||||
|
bool operator==(const ServiceID &lhs, const ServiceID &rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // NET_DOWNLOADMANAGER_H
|
#endif // NET_DOWNLOADMANAGER_H
|
||||||
|
@ -88,6 +88,8 @@ Feed::Feed(const QUuid &uid, const QString &url, const QString &path, Session *s
|
|||||||
else
|
else
|
||||||
connect(m_session, &Session::processingStateChanged, this, &Feed::handleSessionProcessingEnabledChanged);
|
connect(m_session, &Session::processingStateChanged, this, &Feed::handleSessionProcessingEnabledChanged);
|
||||||
|
|
||||||
|
Net::DownloadManager::instance()->registerSequentialService(Net::ServiceID::fromURL(m_url));
|
||||||
|
|
||||||
load();
|
load();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user