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