Browse Source

Merge pull request #471 from daimor/master

Correctly handle HTTP responses with gzipped encoded content.
adaptive-webui-19844
Christophe Dumez 12 years ago
parent
commit
13e57fb9dd
  1. 64
      src/downloadthread.cpp
  2. 2
      src/downloadthread.h
  3. 4
      src/qtlibtorrent/qbtsession.cpp
  4. 2
      src/qtlibtorrent/qbtsession.h
  5. 2
      src/rss/rssfeed.cpp

64
src/downloadthread.cpp

@ -40,6 +40,7 @@
#include "rsssettings.h" #include "rsssettings.h"
#endif #endif
#include "qinisettings.h" #include "qinisettings.h"
#include <zlib.h>
/** Download Thread **/ /** Download Thread **/
@ -50,6 +51,56 @@ DownloadThread::DownloadThread(QObject* parent) : QObject(parent) {
#endif #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<unsigned char*>(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) { void DownloadThread::processDlFinished(QNetworkReply* reply) {
QString url = reply->url().toString(); QString url = reply->url().toString();
qDebug("Download finished: %s", qPrintable(url)); qDebug("Download finished: %s", qPrintable(url));
@ -72,7 +123,8 @@ void DownloadThread::processDlFinished(QNetworkReply* reply) {
const QString newUrlString = newUrl.toString(); const QString newUrlString = newUrl.toString();
qDebug("Redirecting from %s to %s", qPrintable(url), qPrintable(newUrlString)); qDebug("Redirecting from %s to %s", qPrintable(url), qPrintable(newUrlString));
m_redirectMapping.insert(newUrlString, url); m_redirectMapping.insert(newUrlString, url);
downloadUrl(newUrlString); // redirecting with first cookies
downloadUrl(newUrlString, m_networkManager.cookieJar()->cookiesForUrl(url));
reply->deleteLater(); reply->deleteLater();
return; return;
} }
@ -87,8 +139,12 @@ void DownloadThread::processDlFinished(QNetworkReply* reply) {
QString filePath = tmpfile->fileName(); QString filePath = tmpfile->fileName();
qDebug("Temporary filename is: %s", qPrintable(filePath)); qDebug("Temporary filename is: %s", qPrintable(filePath));
if (reply->isOpen() || reply->open(QIODevice::ReadOnly)) { if (reply->isOpen() || reply->open(QIODevice::ReadOnly)) {
// TODO: Support GZIP compression QByteArray replyData = reply->readAll();
tmpfile->write(reply->readAll()); if (reply->rawHeader("Content-Encoding") == "gzip") {
// uncompress gzip reply
replyData = gUncompress(reinterpret_cast<unsigned char*>(replyData.data()), replyData.length());
}
tmpfile->write(replyData);
tmpfile->close(); tmpfile->close();
// XXX: tmpfile needs to be deleted on Windows before using the file // XXX: tmpfile needs to be deleted on Windows before using the file
// or it will complain that the file is used by another process. // or it will complain that the file is used by another process.
@ -136,6 +192,8 @@ QNetworkReply* DownloadThread::downloadUrl(const QString &url, const QList<QNetw
qDebug("%s=%s", m_networkManager.cookieJar()->cookiesForUrl(url).at(i).name().data(), m_networkManager.cookieJar()->cookiesForUrl(url).at(i).value().data()); qDebug("%s=%s", m_networkManager.cookieJar()->cookiesForUrl(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())); 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); return m_networkManager.get(request);
} }

2
src/downloadthread.h

@ -36,6 +36,7 @@
#include <QObject> #include <QObject>
#include <QHash> #include <QHash>
#include <QSslError> #include <QSslError>
#include <zlib.h>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class QNetworkAccessManager; class QNetworkAccessManager;
@ -62,6 +63,7 @@ private slots:
#endif #endif
private: private:
static QByteArray gUncompress(Bytef *inData, size_t len);
QString errorCodeToString(QNetworkReply::NetworkError status); QString errorCodeToString(QNetworkReply::NetworkError status);
void applyProxySettings(); void applyProxySettings();

4
src/qtlibtorrent/qbtsession.cpp

@ -2675,14 +2675,14 @@ void QBtSession::addMagnetSkipAddDlg(const QString& uri, const QString& save_pat
addMagnetUri(uri, false); 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<QNetworkCookie>& cookies) {
//emit aboutToDownloadFromUrl(url); //emit aboutToDownloadFromUrl(url);
const QUrl qurl = QUrl::fromEncoded(url.toUtf8()); const QUrl qurl = QUrl::fromEncoded(url.toUtf8());
if (!save_path.isEmpty() || !label.isEmpty()) if (!save_path.isEmpty() || !label.isEmpty())
savepathLabel_fromurl[qurl] = qMakePair(save_path, label); savepathLabel_fromurl[qurl] = qMakePair(save_path, label);
url_skippingDlg << qurl; url_skippingDlg << qurl;
// Launch downloader thread // Launch downloader thread
downloader->downloadTorrentUrl(url); downloader->downloadTorrentUrl(url, cookies);
} }
// Add to Bittorrent session the downloaded torrent file // Add to Bittorrent session the downloaded torrent file

2
src/qtlibtorrent/qbtsession.h

@ -131,7 +131,7 @@ public slots:
void disableIPFilter(); void disableIPFilter();
void setQueueingEnabled(bool enable); void setQueueingEnabled(bool enable);
void handleDownloadFailure(QString url, QString reason); 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<QNetworkCookie>& cookies = QList<QNetworkCookie>());
// Session configuration - Setters // Session configuration - Setters
void setListeningPort(int port); void setListeningPort(int port);
void setMaxConnections(int maxConnec); void setMaxConnections(int maxConnec);

2
src/rss/rssfeed.cpp

@ -339,7 +339,7 @@ void RssFeed::downloadArticleTorrentIfMatching(RssDownloadRuleList* rules, const
if (torrent_url.startsWith("magnet:", Qt::CaseInsensitive)) if (torrent_url.startsWith("magnet:", Qt::CaseInsensitive))
QBtSession::instance()->addMagnetSkipAddDlg(torrent_url, matching_rule->savePath(), matching_rule->label()); QBtSession::instance()->addMagnetSkipAddDlg(torrent_url, matching_rule->savePath(), matching_rule->label());
else 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() void RssFeed::recheckRssItemsForDownload()

Loading…
Cancel
Save