GeoIpResponse.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "GeoIpResponse.h"
00018 #include "GeoIp.h"
00019 #include "Vidalia.h"
00020
00021 #include "ZlibByteArray.h"
00022
00023 #include <QByteArray>
00024 #include <QStringList>
00025 #include <QHttpResponseHeader>
00026
00027
00028 #define STATUS_HTTP_OK 200
00029
00030 #define STATUS_CONTENT_ENCODING_ERR 601
00031
00032 #define STATUS_TRANSFER_ENCODING_ERR 602
00033
00034
00035 GeoIpResponse::GeoIpResponse(const QByteArray &response)
00036 {
00037 QString errmsg;
00038
00039
00040 int headerPos = response.indexOf("\r\n\r\n");
00041 _header = QHttpResponseHeader(QString(response.mid(0, headerPos)));
00042
00043
00044 if (headerPos > 0 && _header.statusCode() == STATUS_HTTP_OK) {
00045 _content = response.mid(headerPos+4);
00046
00047 if (_header.hasKey("Transfer-Encoding")) {
00048 QString encoding = _header.value("Transfer-Encoding");
00049 if (encoding == "chunked") {
00050 _content = decodeChunked(_content);
00051 if (_content.isEmpty()) {
00052 _header.setStatusLine(STATUS_TRANSFER_ENCODING_ERR,
00053 QString("Failed to decode chunked response"));
00054 return;
00055 }
00056 } else {
00057 _header.setStatusLine(STATUS_TRANSFER_ENCODING_ERR,
00058 QString("Unknown transfer encoding '%1'").arg(encoding));
00059 return;
00060 }
00061 }
00062
00063 if (_header.hasKey("Content-Encoding")) {
00064 ZlibByteArray::CompressionMethod method;
00065 QString encoding = _header.value("Content-Encoding");
00066 if (encoding == "gzip" || encoding == "x-gzip") {
00067 method = ZlibByteArray::Gzip;
00068 } else if (encoding == "deflate" || encoding == "x-deflate") {
00069 method = ZlibByteArray::Zlib;
00070 } else if (encoding == "text/plain") {
00071 method = ZlibByteArray::None;
00072 } else {
00073 _header.setStatusLine(STATUS_CONTENT_ENCODING_ERR,
00074 QString("Unknown content encoding '%1'").arg(encoding));
00075 return;
00076 }
00077
00078 _content = ZlibByteArray::uncompress(_content, method, &errmsg);
00079 if (_content.isEmpty()) {
00080 _header.setStatusLine(STATUS_CONTENT_ENCODING_ERR,
00081 QString("Content decoding using method '%1' failed: %2")
00082 .arg(encoding).arg(errmsg));
00083 return;
00084 }
00085 }
00086 }
00087 }
00088
00089 QByteArray
00090 GeoIpResponse::decodeChunked(const QByteArray &chunked)
00091 {
00092 QByteArray unchunked;
00093 QString sizeString;
00094 int eol, chunkedlen, chunksize, offset = 0;
00095 bool ok;
00096
00097 chunkedlen = chunked.length();
00098 while (offset < chunkedlen) {
00099 eol = chunked.indexOf("\r\n", offset);
00100 if (eol < 0)
00101 return QByteArray();
00102 sizeString = QString::fromAscii(chunked.mid(offset, eol-offset));
00103 offset = eol + 2;
00104
00105 if (sizeString.indexOf(";") >= 0)
00106 sizeString.truncate(sizeString.indexOf(";"));
00107 chunksize = sizeString.toInt(&ok, 16);
00108 if (!ok || chunksize > chunkedlen - offset)
00109 return QByteArray();
00110 if (!chunksize)
00111 break;
00112
00113 unchunked.append(chunked.mid(offset, chunksize));
00114 offset += chunksize;
00115 offset += 2;
00116 }
00117 return unchunked;
00118 }
00119
00120 int
00121 GeoIpResponse::statusCode() const
00122 {
00123 return _header.statusCode();
00124 }
00125
00126 QString
00127 GeoIpResponse::statusMessage() const
00128 {
00129 return _header.reasonPhrase();
00130 }
00131
00132 QByteArray
00133 GeoIpResponse::content() const
00134 {
00135 return _content;
00136 }
00137