[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. */
};