From c702a7e426ffb3cc6ed30ea901706b3b9f765c00 Mon Sep 17 00:00:00 2001 From: "Vladimir Golovnev (Glassez)" Date: Wed, 3 Jun 2015 11:49:39 +0300 Subject: [PATCH] Improve DownloadManager. Now we can use downloaded data directly without saving to file. We also can disable redirection to Magnet URI handling (useful for non-torrent files downloading). --- src/core/bittorrent/session.cpp | 2 +- src/core/net/downloadhandler.cpp | 41 +++++++++++++++------- src/core/net/downloadhandler.h | 7 ++-- src/core/net/downloadmanager.cpp | 4 +-- src/core/net/downloadmanager.h | 2 +- src/gui/addnewtorrentdialog.cpp | 2 +- src/gui/mainwindow.cpp | 2 +- src/gui/properties/trackersadditiondlg.cpp | 2 +- src/gui/rss/rssfeed.cpp | 4 +-- src/gui/transferlistfilterswidget.cpp | 4 +-- src/searchengine/engineselectdlg.cpp | 2 +- 11 files changed, 45 insertions(+), 27 deletions(-) diff --git a/src/core/bittorrent/session.cpp b/src/core/bittorrent/session.cpp index 207112fa3..390cf6c55 100644 --- a/src/core/bittorrent/session.cpp +++ b/src/core/bittorrent/session.cpp @@ -1049,7 +1049,7 @@ bool Session::addTorrent(QString source, const AddTorrentParams ¶ms) if (Utils::Misc::isUrl(source)) { Logger::instance()->addMessage(tr("Downloading '%1', please wait...", "e.g: Downloading 'xxx.torrent', please wait...").arg(source)); // Launch downloader - Net::DownloadHandler *handler = Net::DownloadManager::instance()->downloadUrl(source, 10485760 /* 10MB */); + Net::DownloadHandler *handler = Net::DownloadManager::instance()->downloadUrl(source, true, 10485760 /* 10MB */, true); connect(handler, SIGNAL(downloadFinished(QString, QString)), this, SLOT(handleDownloadFinished(QString, QString))); connect(handler, SIGNAL(downloadFailed(QString, QString)), this, SLOT(handleDownloadFailed(QString, QString))); connect(handler, SIGNAL(redirectedToMagnet(QString, QString)), this, SLOT(handleRedirectedToMagnet(QString, QString))); diff --git a/src/core/net/downloadhandler.cpp b/src/core/net/downloadhandler.cpp index 4a91af4c8..9b86dc54b 100644 --- a/src/core/net/downloadhandler.cpp +++ b/src/core/net/downloadhandler.cpp @@ -46,11 +46,13 @@ static QString errorCodeToString(QNetworkReply::NetworkError status); using namespace Net; -DownloadHandler::DownloadHandler(QNetworkReply *reply, DownloadManager *manager, qint64 limit) +DownloadHandler::DownloadHandler(QNetworkReply *reply, DownloadManager *manager, bool saveToFile, qint64 limit, bool handleRedirectToMagnet) : QObject(manager) , m_reply(reply) , m_manager(manager) + , m_saveToFile(saveToFile) , m_sizeLimit(limit) + , m_handleRedirectToMagnet(handleRedirectToMagnet) , m_url(reply->url().toString()) { init(); @@ -88,11 +90,23 @@ void DownloadHandler::processFinishedDownload() } else { // Success - QString filePath; - if (saveToFile(filePath)) - emit downloadFinished(m_url, filePath); - else - emit downloadFailed(m_url, tr("I/O Error")); + QByteArray replyData = m_reply->readAll(); + if (m_reply->rawHeader("Content-Encoding") == "gzip") { + // uncompress gzip reply + Utils::Gzip::uncompress(replyData, replyData); + } + + if (m_saveToFile) { + QString filePath; + if (saveToFile(replyData, filePath)) + emit downloadFinished(m_url, filePath); + else + emit downloadFailed(m_url, tr("I/O Error")); + } + else { + emit downloadFinished(m_url, replyData); + } + this->deleteLater(); } } @@ -126,7 +140,7 @@ void DownloadHandler::init() connect(m_reply, SIGNAL(finished()), this, SLOT(processFinishedDownload())); } -bool DownloadHandler::saveToFile(QString &filePath) +bool DownloadHandler::saveToFile(const QByteArray &replyData, QString &filePath) { QTemporaryFile *tmpfile = new QTemporaryFile; if (!tmpfile->open()) { @@ -138,11 +152,6 @@ bool DownloadHandler::saveToFile(QString &filePath) filePath = tmpfile->fileName(); qDebug("Temporary filename is: %s", qPrintable(filePath)); if (m_reply->isOpen() || m_reply->open(QIODevice::ReadOnly)) { - QByteArray replyData = m_reply->readAll(); - if (m_reply->rawHeader("Content-Encoding") == "gzip") { - // uncompress gzip reply - Utils::Gzip::uncompress(replyData, replyData); - } tmpfile->write(replyData); tmpfile->close(); // XXX: tmpfile needs to be deleted on Windows before using the file @@ -171,14 +180,20 @@ void DownloadHandler::handleRedirection(QUrl newUrl) if (newUrlString.startsWith("magnet:", Qt::CaseInsensitive)) { qDebug("Magnet redirect detected."); m_reply->abort(); - emit redirectedToMagnet(m_url, newUrlString); + if (m_handleRedirectToMagnet) + emit redirectedToMagnet(m_url, newUrlString); + else + emit downloadFailed(m_url, tr("Unexpected redirect to magnet URI.")); + this->deleteLater(); } else { DownloadHandler *tmp = m_manager->downloadUrl(newUrlString, m_sizeLimit); m_reply->deleteLater(); m_reply = tmp->m_reply; + m_saveToFile = tmp->m_saveToFile; m_sizeLimit = tmp->m_sizeLimit; + m_handleRedirectToMagnet = tmp->m_handleRedirectToMagnet; init(); tmp->m_reply = 0; delete tmp; diff --git a/src/core/net/downloadhandler.h b/src/core/net/downloadhandler.h index 3de172b81..f4afa7491 100644 --- a/src/core/net/downloadhandler.h +++ b/src/core/net/downloadhandler.h @@ -47,12 +47,13 @@ namespace Net Q_OBJECT public: - DownloadHandler(QNetworkReply *reply, DownloadManager *manager, qint64 limit = 0); + DownloadHandler(QNetworkReply *reply, DownloadManager *manager, bool saveToFile = false, qint64 limit = 0, bool handleRedirectToMagnet = false); ~DownloadHandler(); QString url() const; signals: + void downloadFinished(const QString &url, const QByteArray &data); void downloadFinished(const QString &url, const QString &filePath); void downloadFailed(const QString &url, const QString &reason); void redirectedToMagnet(const QString &url, const QString &magnetUri); @@ -63,12 +64,14 @@ namespace Net private: void init(); - bool saveToFile(QString &filePath); + 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; }; } diff --git a/src/core/net/downloadmanager.cpp b/src/core/net/downloadmanager.cpp index 4000410bc..4e1ff2047 100644 --- a/src/core/net/downloadmanager.cpp +++ b/src/core/net/downloadmanager.cpp @@ -75,7 +75,7 @@ DownloadManager *DownloadManager::instance() return m_instance; } -DownloadHandler *DownloadManager::downloadUrl(const QString &url, qint64 limit) +DownloadHandler *DownloadManager::downloadUrl(const QString &url, bool saveToFile, qint64 limit, bool handleRedirectToMagnet) { // Update proxy settings applyProxySettings(); @@ -91,7 +91,7 @@ DownloadHandler *DownloadManager::downloadUrl(const QString &url, qint64 limit) qDebug("Downloading %s...", request.url().toEncoded().data()); // accept gzip request.setRawHeader("Accept-Encoding", "gzip"); - return new DownloadHandler(m_networkManager.get(request), this, limit); + return new DownloadHandler(m_networkManager.get(request), this, saveToFile, limit, handleRedirectToMagnet); } QList DownloadManager::cookiesForUrl(const QString &url) const diff --git a/src/core/net/downloadmanager.h b/src/core/net/downloadmanager.h index ab3556acc..d5fe6b367 100644 --- a/src/core/net/downloadmanager.h +++ b/src/core/net/downloadmanager.h @@ -53,7 +53,7 @@ namespace Net static void freeInstance(); static DownloadManager *instance(); - DownloadHandler *downloadUrl(const QString &url, qint64 limit = 0); + DownloadHandler *downloadUrl(const QString &url, bool saveToFile = false, qint64 limit = 0, bool handleRedirectToMagnet = false); QList cookiesForUrl(const QString &url) const; bool setCookiesFromUrl(const QList &cookieList, const QUrl &url); diff --git a/src/gui/addnewtorrentdialog.cpp b/src/gui/addnewtorrentdialog.cpp index f43e2f414..3597ed503 100644 --- a/src/gui/addnewtorrentdialog.cpp +++ b/src/gui/addnewtorrentdialog.cpp @@ -135,7 +135,7 @@ void AddNewTorrentDialog::show(QString source, QWidget *parent) if (Utils::Misc::isUrl(source)) { // Launch downloader - Net::DownloadHandler *handler = Net::DownloadManager::instance()->downloadUrl(source, 10485760 /* 10MB */); + Net::DownloadHandler *handler = Net::DownloadManager::instance()->downloadUrl(source, true, 10485760 /* 10MB */, true); connect(handler, SIGNAL(downloadFinished(QString, QString)), dlg, SLOT(handleDownloadFinished(QString, QString))); connect(handler, SIGNAL(downloadFailed(QString, QString)), dlg, SLOT(handleDownloadFailed(QString, QString))); connect(handler, SIGNAL(redirectedToMagnet(QString, QString)), dlg, SLOT(handleRedirectedToMagnet(QString, QString))); diff --git a/src/gui/mainwindow.cpp b/src/gui/mainwindow.cpp index db6328e41..4ada3cb3d 100644 --- a/src/gui/mainwindow.cpp +++ b/src/gui/mainwindow.cpp @@ -1570,7 +1570,7 @@ void MainWindow::installPython() { setCursor(QCursor(Qt::WaitCursor)); // Download python - Net::DownloadHandler *handler = Net::DownloadManager::instance()->downloadUrl("https://www.python.org/ftp/python/3.4.3/python-3.4.3.msi"); + Net::DownloadHandler *handler = Net::DownloadManager::instance()->downloadUrl("https://www.python.org/ftp/python/3.4.3/python-3.4.3.msi", true); connect(handler, SIGNAL(downloadFinished(QString, QString)), this, SLOT(pythonDownloadSuccess(QString, QString))); connect(handler, SIGNAL(downloadFailed(QString, QString)), this, SLOT(pythonDownloadFailure(QString, QString))); } diff --git a/src/gui/properties/trackersadditiondlg.cpp b/src/gui/properties/trackersadditiondlg.cpp index e04a53839..f170639ae 100644 --- a/src/gui/properties/trackersadditiondlg.cpp +++ b/src/gui/properties/trackersadditiondlg.cpp @@ -59,7 +59,7 @@ QStringList TrackersAdditionDlg::newTrackers() const void TrackersAdditionDlg::on_uTorrentListButton_clicked() { uTorrentListButton->setEnabled(false); - Net::DownloadHandler *handler = Net::DownloadManager::instance()->downloadUrl(QString("http://www.torrentz.com/announce_%1").arg(m_torrent->hash())); + Net::DownloadHandler *handler = Net::DownloadManager::instance()->downloadUrl(QString("http://www.torrentz.com/announce_%1").arg(m_torrent->hash()), true); connect(handler, SIGNAL(downloadFinished(QString, QString)), this, SLOT(parseUTorrentList(QString, QString))); connect(handler, SIGNAL(downloadFailed(QString, QString)), this, SLOT(getTrackerError(QString, QString))); //Just to show that it takes times diff --git a/src/gui/rss/rssfeed.cpp b/src/gui/rss/rssfeed.cpp index 8651f830b..837f5470b 100644 --- a/src/gui/rss/rssfeed.cpp +++ b/src/gui/rss/rssfeed.cpp @@ -66,7 +66,7 @@ RssFeed::RssFeed(RssManager* manager, RssFolder* parent, const QString& url): connect(manager->rssParser(), SIGNAL(feedParsingFinished(QString,QString)), SLOT(handleFeedParsingFinished(QString,QString))); // Download the RSS Feed icon - Net::DownloadHandler *handler = Net::DownloadManager::instance()->downloadUrl(iconUrl()); + Net::DownloadHandler *handler = Net::DownloadManager::instance()->downloadUrl(iconUrl(), true); connect(handler, SIGNAL(downloadFinished(QString, QString)), this, SLOT(handleFinishedDownload(QString, QString))); connect(handler, SIGNAL(downloadFailed(QString, QString)), this, SLOT(handleDownloadFailure(QString, QString))); m_iconUrl = handler->url(); @@ -167,7 +167,7 @@ bool RssFeed::refresh() } m_loading = true; // Download the RSS again - Net::DownloadHandler *handler = Net::DownloadManager::instance()->downloadUrl(m_url); + Net::DownloadHandler *handler = Net::DownloadManager::instance()->downloadUrl(m_url, true); connect(handler, SIGNAL(downloadFinished(QString, QString)), this, SLOT(handleFinishedDownload(QString, QString))); connect(handler, SIGNAL(downloadFailed(QString, QString)), this, SLOT(handleDownloadFailure(QString, QString))); m_url = handler->url(); // sync URL encoding diff --git a/src/gui/transferlistfilterswidget.cpp b/src/gui/transferlistfilterswidget.cpp index c25163a77..40216ed6d 100644 --- a/src/gui/transferlistfilterswidget.cpp +++ b/src/gui/transferlistfilterswidget.cpp @@ -474,7 +474,7 @@ void TrackerFiltersList::addItem(const QString &tracker, const QString &hash) trackerItem = new QListWidgetItem(); trackerItem->setData(Qt::DecorationRole, GuiIconProvider::instance()->getIcon("network-server")); - Net::DownloadHandler *h = Net::DownloadManager::instance()->downloadUrl(QString("http://%1/favicon.ico").arg(host)); + Net::DownloadHandler *h = Net::DownloadManager::instance()->downloadUrl(QString("http://%1/favicon.ico").arg(host), true); connect(h, SIGNAL(downloadFinished(QString, QString)), this, SLOT(handleFavicoDownload(QString, QString))); connect(h, SIGNAL(downloadFailed(QString, QString)), this, SLOT(handleFavicoFailure(QString, QString))); } @@ -634,7 +634,7 @@ void TrackerFiltersList::handleFavicoDownload(const QString& url, const QString& if (url.endsWith(".ico", Qt::CaseInsensitive)) { Logger::instance()->addMessage(tr("Couldn't decode favicon for URL `%1`. Trying to download favicon in PNG format.").arg(url), Log::WARNING); - Net::DownloadHandler *h = Net::DownloadManager::instance()->downloadUrl(url.left(url.size() - 4) + ".png"); + Net::DownloadHandler *h = Net::DownloadManager::instance()->downloadUrl(url.left(url.size() - 4) + ".png", true); connect(h, SIGNAL(downloadFinished(QString, QString)), this, SLOT(handleFavicoDownload(QString, QString))); connect(h, SIGNAL(downloadFailed(QString, QString)), this, SLOT(handleFavicoFailure(QString, QString))); } diff --git a/src/searchengine/engineselectdlg.cpp b/src/searchengine/engineselectdlg.cpp index bb1147609..844298ed0 100644 --- a/src/searchengine/engineselectdlg.cpp +++ b/src/searchengine/engineselectdlg.cpp @@ -413,7 +413,7 @@ bool engineSelectDlg::parseVersionsFile(QString versions_file) { void engineSelectDlg::downloadFromUrl(const QString &url) { - Net::DownloadHandler *handler = Net::DownloadManager::instance()->downloadUrl(url); + Net::DownloadHandler *handler = Net::DownloadManager::instance()->downloadUrl(url, true); connect(handler, SIGNAL(downloadFinished(QString, QString)), this, SLOT(processDownloadedFile(QString, QString))); connect(handler, SIGNAL(downloadFailed(QString, QString)), this, SLOT(handleDownloadFailure(QString, QString))); }