diff --git a/src/downloadthread.cpp b/src/downloadthread.cpp index 6a765f85a..78c989431 100644 --- a/src/downloadthread.cpp +++ b/src/downloadthread.cpp @@ -40,6 +40,7 @@ #include "rsssettings.h" #endif #include "qinisettings.h" +#include /** Download Thread **/ @@ -50,6 +51,56 @@ DownloadThread::DownloadThread(QObject* parent) : QObject(parent) { #endif } +QByteArray DownloadThread::gUncompress(Bytef *inData, size_t len) { + if (len <= 4) { + qWarning("gUncompress: Input data is truncated"); + return QByteArray(); + } + + QByteArray result; + + z_stream strm; + static const int CHUNK_SIZE = 1024; + char out[CHUNK_SIZE]; + + /* allocate inflate state */ + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + strm.opaque = Z_NULL; + strm.avail_in = len; + strm.next_in = inData; + + #define windowBits 15 + #define ENABLE_ZLIB_GZIP 32 + + int ret = inflateInit2(&strm, windowBits|ENABLE_ZLIB_GZIP ); // gzip decoding + if (ret != Z_OK) + return QByteArray(); + + // run inflate() + do { + strm.avail_out = CHUNK_SIZE; + strm.next_out = reinterpret_cast(out); + + ret = inflate(&strm, Z_NO_FLUSH); + Q_ASSERT(ret != Z_STREAM_ERROR); // state not clobbered + + switch (ret) { + case Z_NEED_DICT: + case Z_DATA_ERROR: + case Z_MEM_ERROR: + (void) inflateEnd(&strm); + return QByteArray(); + } + + result.append(out, CHUNK_SIZE - strm.avail_out); + } while (!strm.avail_out); + + // clean up and return + inflateEnd(&strm); + return result; +} + void DownloadThread::processDlFinished(QNetworkReply* reply) { QString url = reply->url().toString(); qDebug("Download finished: %s", qPrintable(url)); @@ -72,7 +123,8 @@ void DownloadThread::processDlFinished(QNetworkReply* reply) { const QString newUrlString = newUrl.toString(); qDebug("Redirecting from %s to %s", qPrintable(url), qPrintable(newUrlString)); m_redirectMapping.insert(newUrlString, url); - downloadUrl(newUrlString); + // redirecting with first cookies + downloadUrl(newUrlString, m_networkManager.cookieJar()->cookiesForUrl(url)); reply->deleteLater(); return; } @@ -87,8 +139,12 @@ void DownloadThread::processDlFinished(QNetworkReply* reply) { QString filePath = tmpfile->fileName(); qDebug("Temporary filename is: %s", qPrintable(filePath)); if (reply->isOpen() || reply->open(QIODevice::ReadOnly)) { - // TODO: Support GZIP compression - tmpfile->write(reply->readAll()); + QByteArray replyData = reply->readAll(); + if (reply->rawHeader("Content-Encoding") == "gzip") { + // uncompress gzip reply + replyData = gUncompress(reinterpret_cast(replyData.data()), replyData.length()); + } + tmpfile->write(replyData); tmpfile->close(); // XXX: tmpfile needs to be deleted on Windows before using the file // or it will complain that the file is used by another process. @@ -136,6 +192,8 @@ QNetworkReply* DownloadThread::downloadUrl(const QString &url, const QListcookiesForUrl(url).at(i).name().data(), m_networkManager.cookieJar()->cookiesForUrl(url).at(i).value().data()); qDebug("Domain: %s, Path: %s", qPrintable(m_networkManager.cookieJar()->cookiesForUrl(url).at(i).domain()), qPrintable(m_networkManager.cookieJar()->cookiesForUrl(url).at(i).path())); } + // accept gzip + request.setRawHeader("Accept-Encoding", "gzip"); return m_networkManager.get(request); } diff --git a/src/downloadthread.h b/src/downloadthread.h index 6bdc6a7a3..be4360306 100644 --- a/src/downloadthread.h +++ b/src/downloadthread.h @@ -36,6 +36,7 @@ #include #include #include +#include QT_BEGIN_NAMESPACE class QNetworkAccessManager; @@ -62,6 +63,7 @@ private slots: #endif private: + static QByteArray gUncompress(Bytef *inData, size_t len); QString errorCodeToString(QNetworkReply::NetworkError status); void applyProxySettings(); diff --git a/src/qtlibtorrent/qbtsession.cpp b/src/qtlibtorrent/qbtsession.cpp index 260670e2b..2249f61a4 100755 --- a/src/qtlibtorrent/qbtsession.cpp +++ b/src/qtlibtorrent/qbtsession.cpp @@ -2675,14 +2675,14 @@ void QBtSession::addMagnetSkipAddDlg(const QString& uri, const QString& save_pat addMagnetUri(uri, false); } -void QBtSession::downloadUrlAndSkipDialog(QString url, QString save_path, QString label) { +void QBtSession::downloadUrlAndSkipDialog(QString url, QString save_path, QString label, const QList& cookies) { //emit aboutToDownloadFromUrl(url); const QUrl qurl = QUrl::fromEncoded(url.toUtf8()); if (!save_path.isEmpty() || !label.isEmpty()) savepathLabel_fromurl[qurl] = qMakePair(save_path, label); url_skippingDlg << qurl; // Launch downloader thread - downloader->downloadTorrentUrl(url); + downloader->downloadTorrentUrl(url, cookies); } // Add to Bittorrent session the downloaded torrent file diff --git a/src/qtlibtorrent/qbtsession.h b/src/qtlibtorrent/qbtsession.h index 02df04358..7a20ab7c8 100755 --- a/src/qtlibtorrent/qbtsession.h +++ b/src/qtlibtorrent/qbtsession.h @@ -131,7 +131,7 @@ public slots: void disableIPFilter(); void setQueueingEnabled(bool enable); void handleDownloadFailure(QString url, QString reason); - void downloadUrlAndSkipDialog(QString url, QString save_path=QString(), QString label=QString()); + void downloadUrlAndSkipDialog(QString url, QString save_path=QString(), QString label=QString(), const QList& cookies = QList()); // Session configuration - Setters void setListeningPort(int port); void setMaxConnections(int maxConnec); diff --git a/src/rss/rssfeed.cpp b/src/rss/rssfeed.cpp index f39939702..2b92c3bfa 100644 --- a/src/rss/rssfeed.cpp +++ b/src/rss/rssfeed.cpp @@ -339,7 +339,7 @@ void RssFeed::downloadArticleTorrentIfMatching(RssDownloadRuleList* rules, const if (torrent_url.startsWith("magnet:", Qt::CaseInsensitive)) QBtSession::instance()->addMagnetSkipAddDlg(torrent_url, matching_rule->savePath(), matching_rule->label()); else - QBtSession::instance()->downloadUrlAndSkipDialog(torrent_url, matching_rule->savePath(), matching_rule->label()); + QBtSession::instance()->downloadUrlAndSkipDialog(torrent_url, matching_rule->savePath(), matching_rule->label(), feedCookies()); } void RssFeed::recheckRssItemsForDownload()