QtNetwork: handle raw deflate compressed data in Http.
authorMartin Petersson <Martin.Petersson@nokia.com>
Thu, 31 May 2012 12:42:32 +0000 (14:42 +0200)
committerQt by Nokia <qt-info@nokia.com>
Fri, 1 Jun 2012 13:57:18 +0000 (15:57 +0200)
For raw deflate compressed data with no zlib or gzip header
we need to call initInflate2 with -MAX_WBITS.

The first call to inflate will asume that the data has a header,
but if that call fails with a Z_DATA_ERROR we can try once more
with changed windowBits incase the data was raw compressed data
without a header.

Task-number: QTBUG-25513
Change-Id: Ib37c286c6da6d5395581717d0e76a0dbd5df289c
Reviewed-by: Shane Kearns <shane.kearns@accenture.com>
src/network/access/qhttpnetworkreply.cpp

index b95a227..8c8c834 100644 (file)
@@ -685,6 +685,7 @@ qint64 QHttpNetworkReplyPrivate::readBody(QAbstractSocket *socket, QByteDataBuff
 #ifndef QT_NO_COMPRESS
 qint64 QHttpNetworkReplyPrivate::uncompressBodyData(QByteDataBuffer *in, QByteDataBuffer *out)
 {
+    bool triedRawDeflate = false;
     for (int i = 0; i < in->bufferCount(); i++) {
         QByteArray &bIn = (*in)[i];
 
@@ -700,8 +701,26 @@ qint64 QHttpNetworkReplyPrivate::uncompressBodyData(QByteDataBuffer *in, QByteDa
 
             int ret = inflate(&inflateStrm, Z_NO_FLUSH);
             //All negative return codes are errors, in the context of HTTP compression, Z_NEED_DICT is also an error.
-            if (ret < 0 || ret == Z_NEED_DICT)
+            // in the case where we get Z_DATA_ERROR this could be because we recieved raw deflate compressed data.
+            if (ret == Z_DATA_ERROR && !triedRawDeflate) {
+                inflateEnd(&inflateStrm);
+                triedRawDeflate = true;
+                inflateStrm.zalloc = Z_NULL;
+                inflateStrm.zfree = Z_NULL;
+                inflateStrm.opaque = Z_NULL;
+                inflateStrm.avail_in = 0;
+                inflateStrm.next_in = Z_NULL;
+                int ret = inflateInit2(&inflateStrm, -MAX_WBITS);
+                if (ret != Z_OK) {
+                    return -1;
+                } else {
+                    inflateStrm.avail_in = bIn.size();
+                    inflateStrm.next_in = reinterpret_cast<Bytef*>(bIn.data());
+                    continue;
+                }
+            } else if (ret < 0 || ret == Z_NEED_DICT) {
                 return -1;
+            }
             bOut.resize(bOut.capacity() - inflateStrm.avail_out);
             out->append(bOut);
             if (ret == Z_STREAM_END)