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