mirror of
https://github.com/d47081/qBittorrent.git
synced 2025-01-28 23:44:32 +00:00
Merge pull request #9125 from glassez/downloader
Implement "Sequential downloading" feature. Closes #6835
This commit is contained in:
commit
b0afa33e22
@ -1844,11 +1844,10 @@ void Session::handleRedirectedToMagnet(const QString &url, const QString &magnet
|
||||
}
|
||||
|
||||
// Add to BitTorrent session the downloaded torrent file
|
||||
void Session::handleDownloadFinished(const QString &url, const QString &filePath)
|
||||
void Session::handleDownloadFinished(const QString &url, const QByteArray &data)
|
||||
{
|
||||
emit downloadFromUrlFinished(url);
|
||||
addTorrent_impl(m_downloadedTorrents.take(url), MagnetUri(), TorrentInfo::loadFromFile(filePath));
|
||||
Utils::Fs::forceRemove(filePath); // remove temporary file
|
||||
addTorrent_impl(m_downloadedTorrents.take(url), MagnetUri(), TorrentInfo::load(data));
|
||||
}
|
||||
|
||||
// Return the torrent handle, given its hash
|
||||
@ -2077,10 +2076,11 @@ bool Session::addTorrent(QString source, const AddTorrentParams ¶ms)
|
||||
return addTorrent_impl(params, magnetUri);
|
||||
}
|
||||
else if (Utils::Misc::isUrl(source)) {
|
||||
Logger::instance()->addMessage(tr("Downloading '%1', please wait...", "e.g: Downloading 'xxx.torrent', please wait...").arg(source));
|
||||
LogMsg(tr("Downloading '%1', please wait...", "e.g: Downloading 'xxx.torrent', please wait...").arg(source));
|
||||
// Launch downloader
|
||||
Net::DownloadHandler *handler = Net::DownloadManager::instance()->downloadUrl(source, true, 10485760 /* 10MB */, true);
|
||||
connect(handler, static_cast<void (Net::DownloadHandler::*)(const QString &, const QString &)>(&Net::DownloadHandler::downloadFinished)
|
||||
Net::DownloadHandler *handler =
|
||||
Net::DownloadManager::instance()->download(Net::DownloadRequest(source).limit(10485760 /* 10MB */).handleRedirectToMagnet(true));
|
||||
connect(handler, static_cast<void (Net::DownloadHandler::*)(const QString &, const QByteArray &)>(&Net::DownloadHandler::downloadFinished)
|
||||
, this, &Session::handleDownloadFinished);
|
||||
connect(handler, &Net::DownloadHandler::downloadFailed, this, &Session::handleDownloadFailed);
|
||||
connect(handler, &Net::DownloadHandler::redirectedToMagnet, this, &Session::handleRedirectedToMagnet);
|
||||
|
@ -547,7 +547,7 @@ namespace BitTorrent
|
||||
void generateResumeData(bool final = false);
|
||||
void handleIPFilterParsed(int ruleCount);
|
||||
void handleIPFilterError();
|
||||
void handleDownloadFinished(const QString &url, const QString &filePath);
|
||||
void handleDownloadFinished(const QString &url, const QByteArray &data);
|
||||
void handleDownloadFailed(const QString &url, const QString &reason);
|
||||
void handleRedirectedToMagnet(const QString &url, const QString &magnetUri);
|
||||
|
||||
|
@ -62,13 +62,32 @@ TorrentInfo &TorrentInfo::operator=(const TorrentInfo &other)
|
||||
|
||||
TorrentInfo TorrentInfo::load(const QByteArray &data, QString *error) noexcept
|
||||
{
|
||||
// 2-step construction to overcome default limits of `depth_limit` & `token_limit` which are
|
||||
// used in `torrent_info()` constructor
|
||||
const int depthLimit = 100;
|
||||
const int tokenLimit = 10000000;
|
||||
libt::error_code ec;
|
||||
TorrentInfo info(NativePtr(new libt::torrent_info(data.constData(), data.size(), ec)));
|
||||
if (error) {
|
||||
if (ec)
|
||||
|
||||
#if LIBTORRENT_VERSION_NUM < 10100
|
||||
libt::lazy_entry node;
|
||||
libt::lazy_bdecode(data.constData(), (data.constData() + data.size()), node, ec
|
||||
, nullptr, depthLimit, tokenLimit);
|
||||
#else
|
||||
libt::bdecode_node node;
|
||||
bdecode(data.constData(), (data.constData() + data.size()), node, ec
|
||||
, nullptr, depthLimit, tokenLimit);
|
||||
#endif
|
||||
if (ec) {
|
||||
if (error)
|
||||
*error = QString::fromStdString(ec.message());
|
||||
else
|
||||
error->clear();
|
||||
return TorrentInfo();
|
||||
}
|
||||
|
||||
TorrentInfo info {NativePtr(new libt::torrent_info(node, ec))};
|
||||
if (ec) {
|
||||
if (error)
|
||||
*error = QString::fromStdString(ec.message());
|
||||
return TorrentInfo();
|
||||
}
|
||||
|
||||
return info;
|
||||
@ -102,35 +121,7 @@ TorrentInfo TorrentInfo::loadFromFile(const QString &path, QString *error) noexc
|
||||
|
||||
file.close();
|
||||
|
||||
// 2-step construction to overcome default limits of `depth_limit` & `token_limit` which are
|
||||
// used in `torrent_info()` constructor
|
||||
const int depthLimit = 100;
|
||||
const int tokenLimit = 10000000;
|
||||
libt::error_code ec;
|
||||
|
||||
#if LIBTORRENT_VERSION_NUM < 10100
|
||||
libt::lazy_entry node;
|
||||
libt::lazy_bdecode(data.constData(), (data.constData() + data.size()), node, ec
|
||||
, nullptr, depthLimit, tokenLimit);
|
||||
#else
|
||||
libt::bdecode_node node;
|
||||
bdecode(data.constData(), (data.constData() + data.size()), node, ec
|
||||
, nullptr, depthLimit, tokenLimit);
|
||||
#endif
|
||||
if (ec) {
|
||||
if (error)
|
||||
*error = QString::fromStdString(ec.message());
|
||||
return TorrentInfo();
|
||||
}
|
||||
|
||||
TorrentInfo info {NativePtr(new libt::torrent_info(node, ec))};
|
||||
if (ec) {
|
||||
if (error)
|
||||
*error = QString::fromStdString(ec.message());
|
||||
return TorrentInfo();
|
||||
}
|
||||
|
||||
return info;
|
||||
return load(data, error);
|
||||
}
|
||||
|
||||
bool TorrentInfo::isValid() const
|
||||
|
@ -75,9 +75,8 @@ void DNSUpdater::checkPublicIP()
|
||||
{
|
||||
Q_ASSERT(m_state == OK);
|
||||
|
||||
DownloadHandler *handler = DownloadManager::instance()->downloadUrl(
|
||||
"http://checkip.dyndns.org", false, 0, false,
|
||||
"qBittorrent/" QBT_VERSION_2);
|
||||
DownloadHandler *handler = DownloadManager::instance()->download(
|
||||
DownloadRequest("http://checkip.dyndns.org").userAgent("qBittorrent/" QBT_VERSION_2));
|
||||
connect(handler, static_cast<void (Net::DownloadHandler::*)(const QString &, const QByteArray &)>(&Net::DownloadHandler::downloadFinished)
|
||||
, this, &DNSUpdater::ipRequestFinished);
|
||||
connect(handler, &Net::DownloadHandler::downloadFailed, this, &DNSUpdater::ipRequestFailed);
|
||||
@ -123,9 +122,8 @@ void DNSUpdater::updateDNSService()
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
|
||||
m_lastIPCheckTime = QDateTime::currentDateTime();
|
||||
DownloadHandler *handler = DownloadManager::instance()->downloadUrl(
|
||||
getUpdateUrl(), false, 0, false,
|
||||
"qBittorrent/" QBT_VERSION_2);
|
||||
DownloadHandler *handler = DownloadManager::instance()->download(
|
||||
DownloadRequest(getUpdateUrl()).userAgent("qBittorrent/" QBT_VERSION_2));
|
||||
connect(handler, static_cast<void (Net::DownloadHandler::*)(const QString &, const QByteArray &)>(&Net::DownloadHandler::downloadFinished)
|
||||
, this, &DNSUpdater::ipUpdateFinished);
|
||||
connect(handler, &Net::DownloadHandler::downloadFailed, this, &DNSUpdater::ipUpdateFailed);
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* 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>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
@ -29,6 +29,7 @@
|
||||
|
||||
#include "downloadhandler.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QDebug>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QNetworkCookie>
|
||||
@ -43,35 +44,46 @@
|
||||
#include "base/utils/misc.h"
|
||||
#include "downloadmanager.h"
|
||||
|
||||
static QString errorCodeToString(QNetworkReply::NetworkError status);
|
||||
namespace
|
||||
{
|
||||
QString tr(const char *message);
|
||||
QString errorCodeToString(QNetworkReply::NetworkError status);
|
||||
}
|
||||
|
||||
using namespace Net;
|
||||
|
||||
DownloadHandler::DownloadHandler(QNetworkReply *reply, DownloadManager *manager, bool saveToFile, qint64 limit, bool handleRedirectToMagnet)
|
||||
Net::DownloadHandler::DownloadHandler(QNetworkReply *reply, DownloadManager *manager, const DownloadRequest &downloadRequest)
|
||||
: QObject(manager)
|
||||
, m_reply(reply)
|
||||
, m_manager(manager)
|
||||
, m_saveToFile(saveToFile)
|
||||
, m_sizeLimit(limit)
|
||||
, m_handleRedirectToMagnet(handleRedirectToMagnet)
|
||||
, m_url(reply->url().toString())
|
||||
, m_downloadRequest(downloadRequest)
|
||||
{
|
||||
init();
|
||||
if (reply)
|
||||
assignNetworkReply(reply);
|
||||
}
|
||||
|
||||
DownloadHandler::~DownloadHandler()
|
||||
Net::DownloadHandler::~DownloadHandler()
|
||||
{
|
||||
if (m_reply)
|
||||
delete m_reply;
|
||||
}
|
||||
|
||||
// Returns original url
|
||||
QString DownloadHandler::url() const
|
||||
void Net::DownloadHandler::assignNetworkReply(QNetworkReply *reply)
|
||||
{
|
||||
return m_url;
|
||||
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);
|
||||
}
|
||||
|
||||
void DownloadHandler::processFinishedDownload()
|
||||
// Returns original url
|
||||
QString Net::DownloadHandler::url() const
|
||||
{
|
||||
return m_downloadRequest.url();
|
||||
}
|
||||
|
||||
void Net::DownloadHandler::processFinishedDownload()
|
||||
{
|
||||
QString url = m_reply->url().toString();
|
||||
qDebug("Download finished: %s", qUtf8Printable(url));
|
||||
@ -79,7 +91,7 @@ void DownloadHandler::processFinishedDownload()
|
||||
if (m_reply->error() != QNetworkReply::NoError) {
|
||||
// Failure
|
||||
qDebug("Download failure (%s), reason: %s", qUtf8Printable(url), qUtf8Printable(errorCodeToString(m_reply->error())));
|
||||
emit downloadFailed(m_url, errorCodeToString(m_reply->error()));
|
||||
emit downloadFailed(m_downloadRequest.url(), errorCodeToString(m_reply->error()));
|
||||
this->deleteLater();
|
||||
}
|
||||
else {
|
||||
@ -97,15 +109,15 @@ void DownloadHandler::processFinishedDownload()
|
||||
replyData = Utils::Gzip::decompress(replyData);
|
||||
}
|
||||
|
||||
if (m_saveToFile) {
|
||||
if (m_downloadRequest.saveToFile()) {
|
||||
QString filePath;
|
||||
if (saveToFile(replyData, filePath))
|
||||
emit downloadFinished(m_url, filePath);
|
||||
emit downloadFinished(m_downloadRequest.url(), filePath);
|
||||
else
|
||||
emit downloadFailed(m_url, tr("I/O Error"));
|
||||
}
|
||||
emit downloadFailed(m_downloadRequest.url(), tr("I/O Error"));
|
||||
}
|
||||
else {
|
||||
emit downloadFinished(m_url, replyData);
|
||||
emit downloadFinished(m_downloadRequest.url(), replyData);
|
||||
}
|
||||
|
||||
this->deleteLater();
|
||||
@ -113,35 +125,27 @@ 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.");
|
||||
|
||||
if (bytesTotal > 0) {
|
||||
// Total number of bytes is available
|
||||
if (bytesTotal > m_sizeLimit) {
|
||||
if (bytesTotal > m_downloadRequest.limit()) {
|
||||
m_reply->abort();
|
||||
emit downloadFailed(m_url, msg.arg(Utils::Misc::friendlyUnit(bytesTotal), Utils::Misc::friendlyUnit(m_sizeLimit)));
|
||||
emit downloadFailed(m_downloadRequest.url(), msg.arg(Utils::Misc::friendlyUnit(bytesTotal), Utils::Misc::friendlyUnit(m_downloadRequest.limit())));
|
||||
}
|
||||
else {
|
||||
disconnect(m_reply, &QNetworkReply::downloadProgress, this, &Net::DownloadHandler::checkDownloadSize);
|
||||
}
|
||||
}
|
||||
else if (bytesReceived > m_sizeLimit) {
|
||||
else if (bytesReceived > m_downloadRequest.limit()) {
|
||||
m_reply->abort();
|
||||
emit downloadFailed(m_url, msg.arg(Utils::Misc::friendlyUnit(bytesReceived), Utils::Misc::friendlyUnit(m_sizeLimit)));
|
||||
emit downloadFailed(m_downloadRequest.url(), msg.arg(Utils::Misc::friendlyUnit(bytesReceived), Utils::Misc::friendlyUnit(m_downloadRequest.limit())));
|
||||
}
|
||||
}
|
||||
|
||||
void DownloadHandler::init()
|
||||
{
|
||||
m_reply->setParent(this);
|
||||
if (m_sizeLimit > 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)
|
||||
bool Net::DownloadHandler::saveToFile(const QByteArray &replyData, QString &filePath)
|
||||
{
|
||||
QTemporaryFile *tmpfile = new QTemporaryFile(Utils::Fs::tempPath() + "XXXXXX");
|
||||
if (!tmpfile->open()) {
|
||||
@ -168,82 +172,104 @@ bool DownloadHandler::saveToFile(const QByteArray &replyData, QString &filePath)
|
||||
return false;
|
||||
}
|
||||
|
||||
void DownloadHandler::handleRedirection(QUrl newUrl)
|
||||
void Net::DownloadHandler::handleRedirection(QUrl newUrl)
|
||||
{
|
||||
// Resolve relative urls
|
||||
if (newUrl.isRelative())
|
||||
newUrl = m_reply->url().resolved(newUrl);
|
||||
|
||||
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
|
||||
if (newUrlString.startsWith("magnet:", Qt::CaseInsensitive)) {
|
||||
qDebug("Magnet redirect detected.");
|
||||
m_reply->abort();
|
||||
if (m_handleRedirectToMagnet)
|
||||
emit redirectedToMagnet(m_url, newUrlString);
|
||||
if (m_downloadRequest.handleRedirectToMagnet())
|
||||
emit redirectedToMagnet(m_downloadRequest.url(), newUrlString);
|
||||
else
|
||||
emit downloadFailed(m_url, tr("Unexpected redirect to magnet URI."));
|
||||
emit downloadFailed(m_downloadRequest.url(), tr("Unexpected redirect to magnet URI."));
|
||||
|
||||
this->deleteLater();
|
||||
}
|
||||
else {
|
||||
DownloadHandler *tmp = m_manager->downloadUrl(newUrlString, m_saveToFile, m_sizeLimit, m_handleRedirectToMagnet);
|
||||
m_reply->deleteLater();
|
||||
m_reply = tmp->m_reply;
|
||||
init();
|
||||
tmp->m_reply = nullptr;
|
||||
delete tmp;
|
||||
DownloadHandler *redirected = m_manager->download(DownloadRequest(m_downloadRequest).url(newUrlString));
|
||||
connect(redirected, &DownloadHandler::destroyed, this, &DownloadHandler::deleteLater);
|
||||
connect(redirected, &DownloadHandler::downloadFailed, this, [this](const QString &, const QString &reason)
|
||||
{
|
||||
emit downloadFailed(url(), reason);
|
||||
});
|
||||
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) {
|
||||
case QNetworkReply::HostNotFoundError:
|
||||
return QObject::tr("The remote host name was not found (invalid hostname)");
|
||||
case QNetworkReply::OperationCanceledError:
|
||||
return QObject::tr("The operation was canceled");
|
||||
case QNetworkReply::RemoteHostClosedError:
|
||||
return QObject::tr("The remote server closed the connection prematurely, before the entire reply was received and processed");
|
||||
case QNetworkReply::TimeoutError:
|
||||
return QObject::tr("The connection to the remote server timed out");
|
||||
case QNetworkReply::SslHandshakeFailedError:
|
||||
return QObject::tr("SSL/TLS handshake failed");
|
||||
case QNetworkReply::ConnectionRefusedError:
|
||||
return QObject::tr("The remote server refused the connection");
|
||||
case QNetworkReply::ProxyConnectionRefusedError:
|
||||
return QObject::tr("The connection to the proxy server was refused");
|
||||
case QNetworkReply::ProxyConnectionClosedError:
|
||||
return QObject::tr("The proxy server closed the connection prematurely");
|
||||
case QNetworkReply::ProxyNotFoundError:
|
||||
return QObject::tr("The proxy host name was not found");
|
||||
case QNetworkReply::ProxyTimeoutError:
|
||||
return QObject::tr("The connection to the proxy timed out or the proxy did not reply in time to the request sent");
|
||||
case QNetworkReply::ProxyAuthenticationRequiredError:
|
||||
return QObject::tr("The proxy requires authentication in order to honor the request but did not accept any credentials offered");
|
||||
case QNetworkReply::ContentAccessDenied:
|
||||
return QObject::tr("The access to the remote content was denied (401)");
|
||||
case QNetworkReply::ContentOperationNotPermittedError:
|
||||
return QObject::tr("The operation requested on the remote content is not permitted");
|
||||
case QNetworkReply::ContentNotFoundError:
|
||||
return QObject::tr("The remote content was not found at the server (404)");
|
||||
case QNetworkReply::AuthenticationRequiredError:
|
||||
return QObject::tr("The remote server requires authentication to serve the content but the credentials provided were not accepted");
|
||||
case QNetworkReply::ProtocolUnknownError:
|
||||
return QObject::tr("The Network Access API cannot honor the request because the protocol is not known");
|
||||
case QNetworkReply::ProtocolInvalidOperationError:
|
||||
return QObject::tr("The requested operation is invalid for this protocol");
|
||||
case QNetworkReply::UnknownNetworkError:
|
||||
return QObject::tr("An unknown network-related error was detected");
|
||||
case QNetworkReply::UnknownProxyError:
|
||||
return QObject::tr("An unknown proxy-related error was detected");
|
||||
case QNetworkReply::UnknownContentError:
|
||||
return QObject::tr("An unknown error related to the remote content was detected");
|
||||
case QNetworkReply::ProtocolFailure:
|
||||
return QObject::tr("A breakdown in protocol was detected");
|
||||
default:
|
||||
return QObject::tr("Unknown error");
|
||||
QString tr(const char *message)
|
||||
{
|
||||
return QCoreApplication::translate("DownloadHandler", message);
|
||||
}
|
||||
|
||||
QString errorCodeToString(QNetworkReply::NetworkError status)
|
||||
{
|
||||
switch (status) {
|
||||
case QNetworkReply::HostNotFoundError:
|
||||
return tr("The remote host name was not found (invalid hostname)");
|
||||
case QNetworkReply::OperationCanceledError:
|
||||
return tr("The operation was canceled");
|
||||
case QNetworkReply::RemoteHostClosedError:
|
||||
return tr("The remote server closed the connection prematurely, before the entire reply was received and processed");
|
||||
case QNetworkReply::TimeoutError:
|
||||
return tr("The connection to the remote server timed out");
|
||||
case QNetworkReply::SslHandshakeFailedError:
|
||||
return tr("SSL/TLS handshake failed");
|
||||
case QNetworkReply::ConnectionRefusedError:
|
||||
return tr("The remote server refused the connection");
|
||||
case QNetworkReply::ProxyConnectionRefusedError:
|
||||
return tr("The connection to the proxy server was refused");
|
||||
case QNetworkReply::ProxyConnectionClosedError:
|
||||
return tr("The proxy server closed the connection prematurely");
|
||||
case QNetworkReply::ProxyNotFoundError:
|
||||
return tr("The proxy host name was not found");
|
||||
case QNetworkReply::ProxyTimeoutError:
|
||||
return tr("The connection to the proxy timed out or the proxy did not reply in time to the request sent");
|
||||
case QNetworkReply::ProxyAuthenticationRequiredError:
|
||||
return tr("The proxy requires authentication in order to honor the request but did not accept any credentials offered");
|
||||
case QNetworkReply::ContentAccessDenied:
|
||||
return tr("The access to the remote content was denied (401)");
|
||||
case QNetworkReply::ContentOperationNotPermittedError:
|
||||
return tr("The operation requested on the remote content is not permitted");
|
||||
case QNetworkReply::ContentNotFoundError:
|
||||
return tr("The remote content was not found at the server (404)");
|
||||
case QNetworkReply::AuthenticationRequiredError:
|
||||
return tr("The remote server requires authentication to serve the content but the credentials provided were not accepted");
|
||||
case QNetworkReply::ProtocolUnknownError:
|
||||
return tr("The Network Access API cannot honor the request because the protocol is not known");
|
||||
case QNetworkReply::ProtocolInvalidOperationError:
|
||||
return tr("The requested operation is invalid for this protocol");
|
||||
case QNetworkReply::UnknownNetworkError:
|
||||
return tr("An unknown network-related error was detected");
|
||||
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.
|
||||
* 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>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
@ -31,8 +31,8 @@
|
||||
#define NET_DOWNLOADHANDLER_H
|
||||
|
||||
#include <QObject>
|
||||
#include "downloadmanager.h"
|
||||
|
||||
class QNetworkAccessManager;
|
||||
class QNetworkReply;
|
||||
class QUrl;
|
||||
|
||||
@ -43,10 +43,14 @@ namespace Net
|
||||
class DownloadHandler : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_DISABLE_COPY(DownloadHandler)
|
||||
|
||||
friend class DownloadManager;
|
||||
|
||||
DownloadHandler(QNetworkReply *reply, DownloadManager *manager, const DownloadRequest &downloadRequest);
|
||||
|
||||
public:
|
||||
DownloadHandler(QNetworkReply *reply, DownloadManager *manager, bool saveToFile = false, qint64 limit = 0, bool handleRedirectToMagnet = false);
|
||||
~DownloadHandler();
|
||||
~DownloadHandler() override;
|
||||
|
||||
QString url() const;
|
||||
|
||||
@ -61,16 +65,13 @@ namespace Net
|
||||
void checkDownloadSize(qint64 bytesReceived, qint64 bytesTotal);
|
||||
|
||||
private:
|
||||
void init();
|
||||
void assignNetworkReply(QNetworkReply *reply);
|
||||
bool saveToFile(const QByteArray &replyData, QString &filePath);
|
||||
void handleRedirection(QUrl newUrl);
|
||||
|
||||
QNetworkReply *m_reply;
|
||||
DownloadManager *m_manager;
|
||||
bool m_saveToFile;
|
||||
qint64 m_sizeLimit;
|
||||
bool m_handleRedirectToMagnet;
|
||||
QString m_url;
|
||||
const DownloadRequest m_downloadRequest;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* 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>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
@ -103,28 +103,46 @@ namespace
|
||||
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;
|
||||
|
||||
DownloadManager::DownloadManager(QObject *parent)
|
||||
Net::DownloadManager::DownloadManager(QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
#ifndef QT_NO_OPENSSL
|
||||
connect(&m_networkManager, &QNetworkAccessManager::sslErrors, this, &Net::DownloadManager::ignoreSslErrors);
|
||||
#endif
|
||||
connect(&m_networkManager, &QNetworkAccessManager::finished, this, &DownloadManager::handleReplyFinished);
|
||||
connect(ProxyConfigurationManager::instance(), &ProxyConfigurationManager::proxyConfigurationChanged
|
||||
, this, &DownloadManager::applyProxySettings);
|
||||
m_networkManager.setCookieJar(new NetworkCookieJar(this));
|
||||
}
|
||||
|
||||
void DownloadManager::initInstance()
|
||||
void Net::DownloadManager::initInstance()
|
||||
{
|
||||
if (!m_instance)
|
||||
m_instance = new DownloadManager;
|
||||
}
|
||||
|
||||
void DownloadManager::freeInstance()
|
||||
void Net::DownloadManager::freeInstance()
|
||||
{
|
||||
if (m_instance) {
|
||||
delete m_instance;
|
||||
@ -132,62 +150,65 @@ void DownloadManager::freeInstance()
|
||||
}
|
||||
}
|
||||
|
||||
DownloadManager *DownloadManager::instance()
|
||||
Net::DownloadManager *Net::DownloadManager::instance()
|
||||
{
|
||||
return m_instance;
|
||||
}
|
||||
|
||||
DownloadHandler *DownloadManager::downloadUrl(const QString &url, bool saveToFile, qint64 limit, bool handleRedirectToMagnet, const QString &userAgent)
|
||||
Net::DownloadHandler *Net::DownloadManager::download(const DownloadRequest &downloadRequest)
|
||||
{
|
||||
// Update proxy settings
|
||||
applyProxySettings();
|
||||
|
||||
// Process download request
|
||||
qDebug("url is %s", qUtf8Printable(url));
|
||||
const QUrl qurl = QUrl(url);
|
||||
QNetworkRequest request(qurl);
|
||||
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 (userAgent.isEmpty())
|
||||
request.setRawHeader("User-Agent", DEFAULT_USER_AGENT);
|
||||
else
|
||||
request.setRawHeader("User-Agent", userAgent.toUtf8());
|
||||
|
||||
// Spoof HTTP Referer to allow adding torrent link from Torcache/KickAssTorrents
|
||||
request.setRawHeader("Referer", request.url().toEncoded().data());
|
||||
|
||||
qDebug("Downloading %s...", request.url().toEncoded().data());
|
||||
qDebug() << "Cookies:" << m_networkManager.cookieJar()->cookiesForUrl(request.url());
|
||||
// accept gzip
|
||||
request.setRawHeader("Accept-Encoding", "gzip");
|
||||
return new DownloadHandler(m_networkManager.get(request), this, saveToFile, limit, handleRedirectToMagnet);
|
||||
auto *downloadHandler = new DownloadHandler {nullptr, this, downloadRequest};
|
||||
connect(downloadHandler, &DownloadHandler::destroyed, this, [this, id, downloadHandler]()
|
||||
{
|
||||
m_waitingJobs[id].removeOne(downloadHandler);
|
||||
});
|
||||
m_waitingJobs[id].enqueue(downloadHandler);
|
||||
return downloadHandler;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
QList<QNetworkCookie> DownloadManager::allCookies() const
|
||||
QList<QNetworkCookie> Net::DownloadManager::allCookies() const
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
bool DownloadManager::deleteCookie(const QNetworkCookie &cookie)
|
||||
bool Net::DownloadManager::deleteCookie(const QNetworkCookie &cookie)
|
||||
{
|
||||
return static_cast<NetworkCookieJar *>(m_networkManager.cookieJar())->deleteCookie(cookie);
|
||||
}
|
||||
|
||||
void DownloadManager::applyProxySettings()
|
||||
void Net::DownloadManager::applyProxySettings()
|
||||
{
|
||||
auto proxyManager = ProxyConfigurationManager::instance();
|
||||
ProxyConfiguration proxyConfig = proxyManager->proxyConfiguration();
|
||||
@ -208,7 +229,7 @@ void DownloadManager::applyProxySettings()
|
||||
}
|
||||
// Authentication?
|
||||
if (proxyManager->isAuthenticationRequired()) {
|
||||
qDebug("Proxy requires authentication, authenticating");
|
||||
qDebug("Proxy requires authentication, authenticating...");
|
||||
proxy.setUser(proxyConfig.username);
|
||||
proxy.setPassword(proxyConfig.password);
|
||||
}
|
||||
@ -220,11 +241,101 @@ void DownloadManager::applyProxySettings()
|
||||
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
|
||||
void DownloadManager::ignoreSslErrors(QNetworkReply *reply, const QList<QSslError> &errors)
|
||||
void Net::DownloadManager::ignoreSslErrors(QNetworkReply *reply, const QList<QSslError> &errors)
|
||||
{
|
||||
Q_UNUSED(errors)
|
||||
// Ignore all SSL errors
|
||||
reply->ignoreSslErrors();
|
||||
}
|
||||
#endif
|
||||
|
||||
Net::DownloadRequest::DownloadRequest(const QString &url)
|
||||
: m_url {url}
|
||||
{
|
||||
}
|
||||
|
||||
QString Net::DownloadRequest::url() const
|
||||
{
|
||||
return m_url;
|
||||
}
|
||||
|
||||
Net::DownloadRequest &Net::DownloadRequest::url(const QString &value)
|
||||
{
|
||||
m_url = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
QString Net::DownloadRequest::userAgent() const
|
||||
{
|
||||
return m_userAgent;
|
||||
}
|
||||
|
||||
Net::DownloadRequest &Net::DownloadRequest::userAgent(const QString &value)
|
||||
{
|
||||
m_userAgent = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
qint64 Net::DownloadRequest::limit() const
|
||||
{
|
||||
return m_limit;
|
||||
}
|
||||
|
||||
Net::DownloadRequest &Net::DownloadRequest::limit(qint64 value)
|
||||
{
|
||||
m_limit = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool Net::DownloadRequest::saveToFile() const
|
||||
{
|
||||
return m_saveToFile;
|
||||
}
|
||||
|
||||
Net::DownloadRequest &Net::DownloadRequest::saveToFile(bool value)
|
||||
{
|
||||
m_saveToFile = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool Net::DownloadRequest::handleRedirectToMagnet() const
|
||||
{
|
||||
return m_handleRedirectToMagnet;
|
||||
}
|
||||
|
||||
Net::DownloadRequest &Net::DownloadRequest::handleRedirectToMagnet(bool value)
|
||||
{
|
||||
m_handleRedirectToMagnet = value;
|
||||
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.
|
||||
* 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>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
@ -30,8 +30,12 @@
|
||||
#ifndef NET_DOWNLOADMANAGER_H
|
||||
#define NET_DOWNLOADMANAGER_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QHash>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QNetworkRequest>
|
||||
#include <QObject>
|
||||
#include <QQueue>
|
||||
#include <QSet>
|
||||
|
||||
class QNetworkReply;
|
||||
class QNetworkCookie;
|
||||
@ -42,16 +46,57 @@ namespace Net
|
||||
{
|
||||
class DownloadHandler;
|
||||
|
||||
class DownloadRequest
|
||||
{
|
||||
public:
|
||||
DownloadRequest(const QString &url);
|
||||
DownloadRequest(const DownloadRequest &other) = default;
|
||||
|
||||
QString url() const;
|
||||
DownloadRequest &url(const QString &value);
|
||||
|
||||
QString userAgent() const;
|
||||
DownloadRequest &userAgent(const QString &value);
|
||||
|
||||
qint64 limit() const;
|
||||
DownloadRequest &limit(qint64 value);
|
||||
|
||||
bool saveToFile() const;
|
||||
DownloadRequest &saveToFile(bool value);
|
||||
|
||||
bool handleRedirectToMagnet() const;
|
||||
DownloadRequest &handleRedirectToMagnet(bool value);
|
||||
|
||||
private:
|
||||
QString m_url;
|
||||
QString m_userAgent;
|
||||
qint64 m_limit = 0;
|
||||
bool m_saveToFile = false;
|
||||
bool m_handleRedirectToMagnet = false;
|
||||
};
|
||||
|
||||
struct ServiceID
|
||||
{
|
||||
QString hostName;
|
||||
int port;
|
||||
|
||||
static ServiceID fromURL(const QUrl &url);
|
||||
};
|
||||
|
||||
class DownloadManager : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_DISABLE_COPY(DownloadManager)
|
||||
|
||||
public:
|
||||
static void initInstance();
|
||||
static void freeInstance();
|
||||
static DownloadManager *instance();
|
||||
|
||||
DownloadHandler *downloadUrl(const QString &url, bool saveToFile = false, qint64 limit = 0, bool handleRedirectToMagnet = false, const QString &userAgent = "");
|
||||
DownloadHandler *download(const DownloadRequest &downloadRequest);
|
||||
|
||||
void registerSequentialService(const ServiceID &serviceID);
|
||||
|
||||
QList<QNetworkCookie> cookiesForUrl(const QUrl &url) const;
|
||||
bool setCookiesFromUrl(const QList<QNetworkCookie> &cookieList, const QUrl &url);
|
||||
QList<QNetworkCookie> allCookies() const;
|
||||
@ -60,17 +105,25 @@ namespace Net
|
||||
|
||||
private slots:
|
||||
#ifndef QT_NO_OPENSSL
|
||||
void ignoreSslErrors(QNetworkReply *,const QList<QSslError> &);
|
||||
void ignoreSslErrors(QNetworkReply *, const QList<QSslError> &);
|
||||
#endif
|
||||
|
||||
private:
|
||||
explicit DownloadManager(QObject *parent = nullptr);
|
||||
|
||||
void applyProxySettings();
|
||||
void handleReplyFinished(QNetworkReply *reply);
|
||||
|
||||
static DownloadManager *m_instance;
|
||||
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
|
||||
|
@ -118,7 +118,7 @@ void GeoIPManager::manageDatabaseUpdate()
|
||||
|
||||
void GeoIPManager::downloadDatabaseFile()
|
||||
{
|
||||
DownloadHandler *handler = DownloadManager::instance()->downloadUrl(DATABASE_URL);
|
||||
DownloadHandler *handler = DownloadManager::instance()->download({DATABASE_URL});
|
||||
connect(handler, static_cast<void (Net::DownloadHandler::*)(const QString &, const QByteArray &)>(&Net::DownloadHandler::downloadFinished)
|
||||
, this, &GeoIPManager::downloadFinished);
|
||||
connect(handler, &Net::DownloadHandler::downloadFailed, this, &GeoIPManager::downloadFailed);
|
||||
|
@ -88,6 +88,8 @@ Feed::Feed(const QUuid &uid, const QString &url, const QString &path, Session *s
|
||||
else
|
||||
connect(m_session, &Session::processingStateChanged, this, &Feed::handleSessionProcessingEnabledChanged);
|
||||
|
||||
Net::DownloadManager::instance()->registerSequentialService(Net::ServiceID::fromURL(m_url));
|
||||
|
||||
load();
|
||||
}
|
||||
|
||||
@ -127,7 +129,7 @@ void Feed::refresh()
|
||||
|
||||
// NOTE: Should we allow manually refreshing for disabled session?
|
||||
|
||||
Net::DownloadHandler *handler = Net::DownloadManager::instance()->downloadUrl(m_url);
|
||||
Net::DownloadHandler *handler = Net::DownloadManager::instance()->download({m_url});
|
||||
connect(handler
|
||||
, static_cast<void (Net::DownloadHandler::*)(const QString &, const QByteArray &)>(&Net::DownloadHandler::downloadFinished)
|
||||
, this, &Feed::handleDownloadFinished);
|
||||
@ -416,7 +418,8 @@ void Feed::downloadIcon()
|
||||
// XXX: This works for most sites but it is not perfect
|
||||
const QUrl url(m_url);
|
||||
auto iconUrl = QString("%1://%2/favicon.ico").arg(url.scheme(), url.host());
|
||||
Net::DownloadHandler *handler = Net::DownloadManager::instance()->downloadUrl(iconUrl, true);
|
||||
Net::DownloadHandler *handler = Net::DownloadManager::instance()->download(
|
||||
Net::DownloadRequest(iconUrl).saveToFile(true));
|
||||
connect(handler
|
||||
, static_cast<void (Net::DownloadHandler::*)(const QString &, const QString &)>(&Net::DownloadHandler::downloadFinished)
|
||||
, this, &Feed::handleIconDownloadFinished);
|
||||
|
@ -171,7 +171,7 @@ void SearchPluginManager::installPlugin(const QString &source)
|
||||
|
||||
if (Utils::Misc::isUrl(source)) {
|
||||
using namespace Net;
|
||||
DownloadHandler *handler = DownloadManager::instance()->downloadUrl(source, true);
|
||||
DownloadHandler *handler = DownloadManager::instance()->download(DownloadRequest(source).saveToFile(true));
|
||||
connect(handler, static_cast<void (DownloadHandler::*)(const QString &, const QString &)>(&DownloadHandler::downloadFinished)
|
||||
, this, &SearchPluginManager::pluginDownloaded);
|
||||
connect(handler, &DownloadHandler::downloadFailed, this, &SearchPluginManager::pluginDownloadFailed);
|
||||
@ -275,7 +275,7 @@ void SearchPluginManager::checkForUpdates()
|
||||
{
|
||||
// Download version file from update server
|
||||
using namespace Net;
|
||||
DownloadHandler *handler = DownloadManager::instance()->downloadUrl(m_updateUrl + "versions.txt");
|
||||
DownloadHandler *handler = DownloadManager::instance()->download({m_updateUrl + "versions.txt"});
|
||||
connect(handler, static_cast<void (DownloadHandler::*)(const QString &, const QByteArray &)>(&DownloadHandler::downloadFinished)
|
||||
, this, &SearchPluginManager::versionInfoDownloaded);
|
||||
connect(handler, &DownloadHandler::downloadFailed, this, &SearchPluginManager::versionInfoDownloadFailed);
|
||||
|
@ -230,7 +230,9 @@ void AddNewTorrentDialog::show(QString source, const BitTorrent::AddTorrentParam
|
||||
|
||||
if (Utils::Misc::isUrl(source)) {
|
||||
// Launch downloader
|
||||
Net::DownloadHandler *handler = Net::DownloadManager::instance()->downloadUrl(source, true, 10485760 /* 10MB */, true);
|
||||
// TODO: Don't save loaded torrent to file, just use downloaded data!
|
||||
Net::DownloadHandler *handler = Net::DownloadManager::instance()->download(
|
||||
Net::DownloadRequest(source).limit(10485760 /* 10MB */).handleRedirectToMagnet(true).saveToFile(true));
|
||||
connect(handler, static_cast<void (Net::DownloadHandler::*)(const QString &, const QString &)>(&Net::DownloadHandler::downloadFinished)
|
||||
, dlg, &AddNewTorrentDialog::handleDownloadFinished);
|
||||
connect(handler, &Net::DownloadHandler::downloadFailed, dlg, &AddNewTorrentDialog::handleDownloadFailed);
|
||||
|
@ -2041,11 +2041,11 @@ void MainWindow::installPython()
|
||||
{
|
||||
setCursor(QCursor(Qt::WaitCursor));
|
||||
// Download python
|
||||
Net::DownloadHandler *handler = nullptr;
|
||||
if (QSysInfo::windowsVersion() >= QSysInfo::WV_VISTA)
|
||||
handler = Net::DownloadManager::instance()->downloadUrl("https://www.python.org/ftp/python/3.5.2/python-3.5.2.exe", true);
|
||||
else
|
||||
handler = Net::DownloadManager::instance()->downloadUrl("https://www.python.org/ftp/python/3.4.4/python-3.4.4.msi", true);
|
||||
const QString installerURL = ((QSysInfo::windowsVersion() >= QSysInfo::WV_VISTA)
|
||||
? "https://www.python.org/ftp/python/3.5.2/python-3.5.2.exe"
|
||||
: "https://www.python.org/ftp/python/3.4.4/python-3.4.4.msi");
|
||||
Net::DownloadHandler *handler = Net::DownloadManager::instance()->download(
|
||||
Net::DownloadRequest(installerURL).saveToFile(true));
|
||||
|
||||
using Func = void (Net::DownloadHandler::*)(const QString &, const QString &);
|
||||
connect(handler, static_cast<Func>(&Net::DownloadHandler::downloadFinished), this, &MainWindow::pythonDownloadSuccess);
|
||||
|
@ -61,11 +61,10 @@ ProgramUpdater::ProgramUpdater(QObject *parent, bool invokedByUser)
|
||||
|
||||
void ProgramUpdater::checkForUpdates()
|
||||
{
|
||||
Net::DownloadHandler *handler = Net::DownloadManager::instance()->downloadUrl(
|
||||
RSS_URL, false, 0, false,
|
||||
// Don't change this User-Agent. In case our updater goes haywire,
|
||||
// the filehost can identify it and contact us.
|
||||
"qBittorrent/" QBT_VERSION_2 " ProgramUpdater (www.qbittorrent.org)");
|
||||
// Don't change this User-Agent. In case our updater goes haywire,
|
||||
// the filehost can identify it and contact us.
|
||||
Net::DownloadHandler *handler = Net::DownloadManager::instance()->download(
|
||||
Net::DownloadRequest(RSS_URL).userAgent("qBittorrent/" QBT_VERSION_2 " ProgramUpdater (www.qbittorrent.org)"));
|
||||
connect(handler, static_cast<void (Net::DownloadHandler::*)(const QString &, const QByteArray &)>(&Net::DownloadHandler::downloadFinished)
|
||||
, this, &ProgramUpdater::rssDownloadFinished);
|
||||
connect(handler, &Net::DownloadHandler::downloadFailed, this, &ProgramUpdater::rssDownloadFailed);
|
||||
|
@ -25,9 +25,10 @@
|
||||
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||
* exception statement from your version.
|
||||
*/
|
||||
|
||||
#include "trackersadditiondialog.h"
|
||||
|
||||
#include <QFile>
|
||||
#include <QBuffer>
|
||||
#include <QMessageBox>
|
||||
#include <QStringList>
|
||||
#include <QUrl>
|
||||
@ -70,25 +71,16 @@ QStringList TrackersAdditionDialog::newTrackers() const
|
||||
void TrackersAdditionDialog::on_uTorrentListButton_clicked()
|
||||
{
|
||||
m_ui->uTorrentListButton->setEnabled(false);
|
||||
Net::DownloadHandler *handler = Net::DownloadManager::instance()->downloadUrl(m_ui->list_url->text(), true);
|
||||
connect(handler, static_cast<void (Net::DownloadHandler::*)(const QString &, const QString &)>(&Net::DownloadHandler::downloadFinished)
|
||||
Net::DownloadHandler *handler = Net::DownloadManager::instance()->download({m_ui->list_url->text()});
|
||||
connect(handler, static_cast<void (Net::DownloadHandler::*)(const QString &, const QByteArray &)>(&Net::DownloadHandler::downloadFinished)
|
||||
, this, &TrackersAdditionDialog::parseUTorrentList);
|
||||
connect(handler, &Net::DownloadHandler::downloadFailed, this, &TrackersAdditionDialog::getTrackerError);
|
||||
// Just to show that it takes times
|
||||
setCursor(Qt::WaitCursor);
|
||||
}
|
||||
|
||||
void TrackersAdditionDialog::parseUTorrentList(const QString &, const QString &path)
|
||||
void TrackersAdditionDialog::parseUTorrentList(const QString &, const QByteArray &data)
|
||||
{
|
||||
QFile listFile(path);
|
||||
if (!listFile.open(QFile::ReadOnly)) {
|
||||
QMessageBox::warning(this, tr("I/O Error"), tr("Error while trying to open the downloaded file."), QMessageBox::Ok);
|
||||
setCursor(Qt::ArrowCursor);
|
||||
m_ui->uTorrentListButton->setEnabled(true);
|
||||
Utils::Fs::forceRemove(path);
|
||||
return;
|
||||
}
|
||||
|
||||
// Load from torrent handle
|
||||
QList<BitTorrent::TrackerEntry> existingTrackers = m_torrent->trackers();
|
||||
// Load from current user list
|
||||
@ -103,19 +95,21 @@ void TrackersAdditionDialog::parseUTorrentList(const QString &, const QString &p
|
||||
if (!m_ui->trackers_list->toPlainText().isEmpty() && !m_ui->trackers_list->toPlainText().endsWith('\n'))
|
||||
m_ui->trackers_list->insertPlainText("\n");
|
||||
int nb = 0;
|
||||
while (!listFile.atEnd()) {
|
||||
const QString line = listFile.readLine().trimmed();
|
||||
QBuffer buffer;
|
||||
buffer.setData(data);
|
||||
buffer.open(QBuffer::ReadOnly);
|
||||
while (!buffer.atEnd()) {
|
||||
const QString line = buffer.readLine().trimmed();
|
||||
if (line.isEmpty()) continue;
|
||||
|
||||
BitTorrent::TrackerEntry newTracker(line);
|
||||
if (!existingTrackers.contains(newTracker)) {
|
||||
m_ui->trackers_list->insertPlainText(line + '\n');
|
||||
++nb;
|
||||
}
|
||||
}
|
||||
// Clean up
|
||||
listFile.close();
|
||||
Utils::Fs::forceRemove(path);
|
||||
//To restore the cursor ...
|
||||
|
||||
// To restore the cursor ...
|
||||
setCursor(Qt::ArrowCursor);
|
||||
m_ui->uTorrentListButton->setEnabled(true);
|
||||
// Display information message if necessary
|
||||
|
@ -57,7 +57,7 @@ public:
|
||||
|
||||
public slots:
|
||||
void on_uTorrentListButton_clicked();
|
||||
void parseUTorrentList(const QString &, const QString &path);
|
||||
void parseUTorrentList(const QString &, const QByteArray &data);
|
||||
void getTrackerError(const QString &, const QString &error);
|
||||
|
||||
private:
|
||||
|
@ -292,7 +292,8 @@ void PluginSelectDialog::addNewPlugin(QString pluginName)
|
||||
else {
|
||||
// Icon is missing, we must download it
|
||||
using namespace Net;
|
||||
DownloadHandler *handler = DownloadManager::instance()->downloadUrl(plugin->url + "/favicon.ico", true);
|
||||
DownloadHandler *handler = DownloadManager::instance()->download(
|
||||
DownloadRequest(plugin->url + "/favicon.ico").saveToFile(true));
|
||||
connect(handler, static_cast<void (DownloadHandler::*)(const QString &, const QString &)>(&DownloadHandler::downloadFinished)
|
||||
, this, &PluginSelectDialog::iconDownloaded);
|
||||
connect(handler, &DownloadHandler::downloadFailed, this, &PluginSelectDialog::iconDownloadFailed);
|
||||
|
@ -404,7 +404,8 @@ void TrackerFiltersList::trackerWarning(const QString &hash, const QString &trac
|
||||
void TrackerFiltersList::downloadFavicon(const QString& url)
|
||||
{
|
||||
if (!m_downloadTrackerFavicon) return;
|
||||
Net::DownloadHandler *h = Net::DownloadManager::instance()->downloadUrl(url, true);
|
||||
Net::DownloadHandler *h = Net::DownloadManager::instance()->download(
|
||||
Net::DownloadRequest(url).saveToFile(true));
|
||||
using Func = void (Net::DownloadHandler::*)(const QString &, const QString &);
|
||||
connect(h, static_cast<Func>(&Net::DownloadHandler::downloadFinished), this
|
||||
, &TrackerFiltersList::handleFavicoDownload);
|
||||
|
Loading…
x
Reference in New Issue
Block a user