[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[vidalia-svn] r1593: Handle chunked transfer encodings properly. (trunk/src/util/geoip)



Author: edmanm
Date: 2007-01-15 22:52:47 -0500 (Mon, 15 Jan 2007)
New Revision: 1593

Modified:
   trunk/src/util/geoip/geoipresponse.cpp
   trunk/src/util/geoip/geoipresponse.h
Log:
Handle chunked transfer encodings properly.


Modified: trunk/src/util/geoip/geoipresponse.cpp
===================================================================
--- trunk/src/util/geoip/geoipresponse.cpp	2007-01-16 00:21:44 UTC (rev 1592)
+++ trunk/src/util/geoip/geoipresponse.cpp	2007-01-16 03:52:47 UTC (rev 1593)
@@ -34,6 +34,8 @@
 #define STATUS_HTTP_OK                 200
 /** Status code for content encoding errors. */
 #define STATUS_CONTENT_ENCODING_ERR    601
+/** Status code for transfer encoding errors. */
+#define STATUS_TRANSFER_ENCODING_ERR   602
 
 
 /** Constructor. Parses the response data for an HTTP header and Geo IP
@@ -50,6 +52,22 @@
   if (headerPos > 0 && _header.statusCode() == STATUS_HTTP_OK) {
     QByteArray content = response.mid(headerPos+4);
  
+    if (_header.hasKey("Transfer-Encoding")) {
+      QString encoding = _header.value("Transfer-Encoding");
+      if (encoding == "chunked") {
+        content = decodeChunked(content);
+        if (content.isEmpty()) {
+          _header.setStatusLine(STATUS_TRANSFER_ENCODING_ERR,
+            QString("Failed to decode chunked response"));
+          return;
+        }
+      } else {
+        _header.setStatusLine(STATUS_TRANSFER_ENCODING_ERR,
+          QString("Unknown transfer encoding '%1'").arg(encoding));
+        return;
+      }
+    }
+ 
     if (_header.hasKey("Content-Encoding")) {
       ZlibByteArray::CompressionMethod method;
       QString encoding = _header.value("Content-Encoding");
@@ -64,7 +82,7 @@
           QString("Unknown content encoding '%1'").arg(encoding));
         return;
       }
-      
+ 
       content = ZlibByteArray::uncompress(content, method, &errmsg);
       if (content.isEmpty()) {
         _header.setStatusLine(STATUS_CONTENT_ENCODING_ERR,
@@ -84,3 +102,36 @@
   }
 }
 
+/** Decodes a <b>chunked</b> transfer encoding. Returns the unchunked 
+ * result on success, or an empty QByteArray if decoding fails. */
+QByteArray
+GeoIpResponse::decodeChunked(QByteArray chunked)
+{
+  QByteArray unchunked;
+  QString sizeString;
+  int eol, chunkedlen, chunksize, offset = 0;
+  bool ok;
+ 
+  chunkedlen = chunked.length();
+  while (offset < chunkedlen) {
+    eol = chunked.indexOf("\r\n", offset);
+    if (eol < 0)
+      return QByteArray();
+    sizeString = QString::fromAscii(chunked.mid(offset, eol-offset));
+    offset = eol + 2; /* Skip past the CRLF */
+    
+    if (sizeString.indexOf(";") >= 0)
+      sizeString.truncate(sizeString.indexOf(";")); 
+    chunksize = sizeString.toInt(&ok, 16);
+    if (!ok || chunksize > chunkedlen - offset)
+      return QByteArray();
+    if (!chunksize)
+      break; /* Last chunk. Ignore the trailer. */
+    
+    unchunked.append(chunked.mid(offset, chunksize));
+    offset += chunksize;
+    offset += 2; /* CRLF after each chunk */
+  }
+  return unchunked;
+}
+

Modified: trunk/src/util/geoip/geoipresponse.h
===================================================================
--- trunk/src/util/geoip/geoipresponse.h	2007-01-16 00:21:44 UTC (rev 1592)
+++ trunk/src/util/geoip/geoipresponse.h	2007-01-16 03:52:47 UTC (rev 1593)
@@ -50,6 +50,10 @@
   QList<GeoIp> geoIps() { return _geoips; }
   
 private:
+  /** Decodes a <b>chunked</b> transfer encoding. Returns the unchunked 
+   * result on success, or an empty QByteArray if decoding fails. */
+  QByteArray decodeChunked(QByteArray chunked);
+  
   QHttpResponseHeader _header; /**< HTTP response header. */
   QList<GeoIp> _geoips;        /**< Geo IP information in this response. */
 };