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

[vidalia-svn] r2143: Move the GeoIP stuff out of util, so it can live as its own (in trunk: . src src/geoip src/gui/network src/util)



Author: edmanm
Date: 2007-11-30 11:28:52 -0500 (Fri, 30 Nov 2007)
New Revision: 2143

Added:
   trunk/src/geoip/
   trunk/src/geoip/geoip.cpp
   trunk/src/geoip/geoip.h
   trunk/src/geoip/geoip.pri
   trunk/src/geoip/geoipcache.cpp
   trunk/src/geoip/geoipcache.h
   trunk/src/geoip/geoipcacheitem.cpp
   trunk/src/geoip/geoipcacheitem.h
   trunk/src/geoip/geoiprequest.cpp
   trunk/src/geoip/geoiprequest.h
   trunk/src/geoip/geoipresolver.cpp
   trunk/src/geoip/geoipresolver.h
   trunk/src/geoip/geoipresponse.cpp
   trunk/src/geoip/geoipresponse.h
Removed:
   trunk/src/util/geoip/
Modified:
   trunk/
   trunk/src/gui/network/netviewer.h
   trunk/src/gui/network/routerlistitem.h
   trunk/src/src.pri
   trunk/src/util/util.pri
Log:
 r2166@lysithea:  edmanm | 2007-11-30 11:28:25 -0500
 Move the GeoIP stuff out of util, so it can live as its own little module.



Property changes on: trunk
___________________________________________________________________
 svk:merge ticket from /local/vidalia/trunk [r2166] on 0108964c-5b0b-4c9e-969f-e2288315d100

Added: trunk/src/geoip/geoip.cpp
===================================================================
--- trunk/src/geoip/geoip.cpp	                        (rev 0)
+++ trunk/src/geoip/geoip.cpp	2007-11-30 16:28:52 UTC (rev 2143)
@@ -0,0 +1,150 @@
+/****************************************************************
+ *  Vidalia is distributed under the following license:
+ *
+ *  Copyright (C) 2006,  Matt Edman, Justin Hipple
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  as published by the Free Software Foundation; either version 2
+ *  of the License, or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA  02110-1301, USA.
+ ****************************************************************/
+
+/**
+ * \file geoip.cpp
+ * \version $Id$
+ * \brief Associates an IP with a geographic location
+ */
+
+#include <QStringList>
+
+#include "geoip.h"
+
+/** Verifies a latitude is between -90.0 and 90.0 degrees. */
+#define IS_VALID_LATITUDE(x)    (((x) >= -90.0) && ((x) <= 90.0))
+/** Verifies a longitude is between -180.0 and 180.0 degrees. */
+#define IS_VALID_LONGITUDE(x)   (((x) >= -180.0) && ((x) <= 180.0))
+
+
+/** Constructor */
+GeoIp::GeoIp(QHostAddress ip)
+{
+  _ip = ip;
+  _latitude = _longitude = 0xFFFF;
+}
+
+/** Constructor. */
+GeoIp::GeoIp(QHostAddress ip, float latitude, float longitude, 
+             QString city, QString state, QString country)
+{
+  _ip        = ip;
+  _latitude  = latitude;
+  _longitude = longitude;
+  _city      = city;
+  _state     = state;
+  _country   = country;
+}
+
+/** Parses the GeoIp information from a comma-delimited string. The format of
+ * the string is as in the following example:
+ *
+ *      128.213.48.13,Troy,NY,US,42.7495,-73.5951,1138402852
+ */
+GeoIp
+GeoIp::fromString(QString geoip)
+{
+  /* Split comma-delimited data fields */
+  QStringList data = geoip.split(",");
+  
+  if (data.size() == 2 && data.at(1).toLower() == "unknown") {
+    return GeoIp(QHostAddress(data.at(0)));
+  } else if (data.size() < 6) {
+    return GeoIp();
+  }
+  
+  /* Parse the data from the string */
+  QHostAddress   ip(data.at(0));
+  QString city    = data.at(1);
+  QString state   = data.at(2);
+  QString country = data.at(3);
+  float latitude  = data.at(4).toFloat();
+  float longitude = data.at(5).toFloat();
+ 
+  /* Create a new GeoIp object with the parsed data. */
+  return GeoIp(ip, latitude, longitude, city, state, country);
+}
+
+/** Formats the GeoIp information as a comma-delimited string. */
+QString
+GeoIp::toString() const
+{
+  QString s;
+  /* Assemble and comma-delimit the data fields */
+  s.append(_ip.toString());
+  s.append("," + _city);
+  s.append("," + _state);
+  s.append("," + _country);
+  s.append("," + QString::number(_latitude,  'f', 4));
+  s.append("," + QString::number(_longitude, 'f', 4));
+  return s;
+}
+
+/** Returns true if the GeoIp object is invalid. */
+bool
+GeoIp::isEmpty() const
+{
+  return (_ip.isNull() && 
+          !IS_VALID_LATITUDE(_latitude) && 
+          !IS_VALID_LONGITUDE(_longitude));
+}
+
+/** Returns true if the GeoIp object is valid, but no location information
+ * is known for the associated IP address. */
+bool
+GeoIp::isUnknown() const
+{
+  return (!_ip.isNull() && 
+          !IS_VALID_LATITUDE(_latitude) && 
+          !IS_VALID_LONGITUDE(_longitude));
+}
+
+/** Returns a human-readable string of GeoIp location information. */
+QString
+GeoIp::toLocation() const
+{
+  QStringList location;
+  
+  /* Add the city name (if present) */
+  if (!_city.isEmpty()) {
+    location << _city;
+  }
+  /* Add the state or region name (if present) */
+  if (!_state.isEmpty()) {
+    /* Only display non-numeric region codes. */
+    bool valid = true;
+    for (int i = 0; i < _state.length(); i++) {
+      if (_state[i].isDigit()) {
+        valid = false;
+        break;
+      }
+    }
+    if (valid) {
+      location << _state;
+    }
+  }
+  /* Add the country code (if present) */
+  if (!_country.isEmpty()) {
+    location << _country;
+  }
+  return location.join(", ");
+}
+


Property changes on: trunk/src/geoip/geoip.cpp
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: trunk/src/geoip/geoip.h
===================================================================
--- trunk/src/geoip/geoip.h	                        (rev 0)
+++ trunk/src/geoip/geoip.h	2007-11-30 16:28:52 UTC (rev 2143)
@@ -0,0 +1,83 @@
+/****************************************************************
+ *  Vidalia is distributed under the following license:
+ *
+ *  Copyright (C) 2006,  Matt Edman, Justin Hipple
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  as published by the Free Software Foundation; either version 2
+ *  of the License, or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA  02110-1301, USA.
+ ****************************************************************/
+
+/**
+ * \file geoip.h
+ * \version $Id$
+ * \brief Associates an IP with a geographic location
+ */
+
+#ifndef _GEOIP_H
+#define _GEOIP_H
+
+#include <QString>
+#include <QHostAddress>
+
+
+class GeoIp
+{
+public:
+  /** Default constructor */
+  GeoIp() : _latitude(0xFFFF), _longitude(0xFFFF) {}
+  /** Constructor. */
+  GeoIp(QHostAddress ip);
+
+  /** Constructor */
+  GeoIp(QHostAddress ip, float latitude, float longitude, 
+        QString city, QString state, QString country);
+  
+  /** Creates a GeoIp object from a string. */
+  static GeoIp fromString(QString geoip);
+  /** Builds a comma-delimited string of GeoIp fields. */
+  QString toString() const;
+
+  /** Returns the IP address for this object. */
+  QHostAddress ip() const { return _ip; }
+  /** Returns the latitude coordinate for this IP. */
+  float latitude() const { return _latitude; }
+  /** Returns the longitude coordinate for this IP. */
+  float longitude() const { return _longitude; }
+  /** Returns the city in which this IP lives. */
+  QString city() const { return _city; }
+  /** Returns the state or district in which this IP lives. */
+  QString state() const { return _state; }
+  /** Returns the country in which this IP lives. */
+  QString country() const { return _country; }
+  /** Returns a human-readable string of city, region(state), and country. */
+  QString toLocation() const;
+
+  /** Returns true if the GeoIp object is invalid. */
+  bool isEmpty() const;
+  /** Returns true if the GeoIp object is valid, but no location information
+   * is known for the associated IP address. */
+   bool isUnknown() const;
+
+private:
+  QHostAddress _ip; /**< IP address for this location. */
+  float _latitude;  /**< Latitudinal coordinate for this IP's location. */
+  float _longitude; /**< Longitudinal coordinate for this IP's location. */
+  QString _city;    /**< City in which this IP lives. */
+  QString _state;   /**< State or district in which this IP lives. */
+  QString _country; /**< Country in which this IP lives. */
+};
+
+#endif
+


Property changes on: trunk/src/geoip/geoip.h
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: trunk/src/geoip/geoip.pri
===================================================================
--- trunk/src/geoip/geoip.pri	                        (rev 0)
+++ trunk/src/geoip/geoip.pri	2007-11-30 16:28:52 UTC (rev 2143)
@@ -0,0 +1,39 @@
+#################################################################
+#  $Id$
+#
+#  Vidalia is distributed under the following license:
+#
+#  Copyright (C) 2006,  Matt Edman, Justin Hipple
+#
+#  This program is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU General Public License
+#  as published by the Free Software Foundation; either version 2
+#  of the License, or (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software
+#  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  
+#  02110-1301, USA.
+#################################################################
+
+INCLUDEPATH += $$PWD
+
+HEADERS += $$PWD/geoip.h \
+           $$PWD/geoipcache.h \
+           $$PWD/geoipcacheitem.h \
+           $$PWD/geoipresolver.h \
+           $$PWD/geoiprequest.h \
+           $$PWD/geoipresponse.h
+           
+SOURCES += $$PWD/geoip.cpp \
+           $$PWD/geoipcache.cpp \
+           $$PWD/geoipcacheitem.cpp \
+           $$PWD/geoipresolver.cpp \
+           $$PWD/geoiprequest.cpp \
+           $$PWD/geoipresponse.cpp
+


Property changes on: trunk/src/geoip/geoip.pri
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: trunk/src/geoip/geoipcache.cpp
===================================================================
--- trunk/src/geoip/geoipcache.cpp	                        (rev 0)
+++ trunk/src/geoip/geoipcache.cpp	2007-11-30 16:28:52 UTC (rev 2143)
@@ -0,0 +1,155 @@
+/****************************************************************
+ *  Vidalia is distributed under the following license:
+ *
+ *  Copyright (C) 2006,  Matt Edman, Justin Hipple
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  as published by the Free Software Foundation; either version 2
+ *  of the License, or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA  02110-1301, USA.
+ ****************************************************************/
+
+/**
+ * \file geoipcache.cpp
+ * \version $Id$
+ * \brief Caches the results of previous GeoIP requests
+ */
+
+#include <QFile>
+#include <QDir>
+#include <QTextStream>
+#include <util/string.h>
+#include <util/file.h>
+#include <vidalia.h>
+
+#include "geoipcache.h"
+
+/* Location of Vidalia's geoip cache file. Qt docs claims that QFile will
+ * translate the "/" correctly on Windows. Hopefully they didn't lie. */
+#define CACHE_FILENAME  (Vidalia::dataDirectory() + "/geoip-cache")
+
+
+/** Constructor. */
+GeoIpCache::GeoIpCache()
+{
+  loadFromDisk();
+}
+
+/** Returns the location currently used for the cache file. */
+QString
+GeoIpCache::cacheFilename()
+{
+  return CACHE_FILENAME;
+}
+
+/** Writes the current cache to disk. */
+bool
+GeoIpCache::saveToDisk(QString *errmsg)
+{
+  /* Make sure we have a data directory. */
+  if (!create_path(Vidalia::dataDirectory())) {
+    return false;
+  }
+  
+  /* Try to open a temporary cache file for writing */
+  QFile tmpCacheFile(CACHE_FILENAME + ".tmp");
+  if (!tmpCacheFile.open(QIODevice::WriteOnly | QIODevice::Text)) {
+    return err(errmsg, tmpCacheFile.errorString());
+  }
+  
+  /* Write the cache entries to the file. */
+  QTextStream cache(&tmpCacheFile);
+  foreach (GeoIpCacheItem cacheItem, _cache.values()) {
+    /* Save the cache item if it's not too old. */
+    if (!cacheItem.isExpired()) {
+      cache << cacheItem.toString() << endl;
+    }
+  }
+  
+  QFile cacheFile(CACHE_FILENAME);
+  /* Check if an previous cache file exists. */
+  if (cacheFile.exists()) {
+    /* A previous cache file exists, so try to remove it */
+    if (!cacheFile.remove()) {
+      return err(errmsg, cacheFile.errorString());
+    }
+  }
+  /* Rename the temporary file into place. */
+  if (tmpCacheFile.rename(cacheFile.fileName())) {
+    return err(errmsg, tmpCacheFile.errorString());
+  }
+  return true;
+}
+
+/** Reads the cache contents in from disk. This function returns true if no
+ * cache file exists, since it's possible nothing has been cached yet. */
+bool
+GeoIpCache::loadFromDisk(QString *errmsg)
+{
+  QFile cacheFile(CACHE_FILENAME);
+  
+  if (cacheFile.exists()) {
+    /* Try to open the cache file */
+    if (!cacheFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
+      return err(errmsg, cacheFile.errorString());
+    }
+    
+    /* Read the cached items from the cache file */
+    QTextStream cache(&cacheFile);
+    QString line = cache.readLine();
+    while (!line.isNull()) {
+      /* Create a GeoIpCacheItem from the line and save it */
+      GeoIpCacheItem item = GeoIpCacheItem::fromString(line);
+      if (!item.isEmpty() && !item.isExpired()) {
+        /* Only load non-stale cache items. */
+        _cache.insert(item.ip().toIPv4Address(), item);
+      }
+      line = cache.readLine();
+    }
+  }
+  return true;
+}
+
+/** Caches the given IP and geographic information to disk. Call saveToDisk()
+ * when you want to write the cache to disk. */
+void
+GeoIpCache::cache(GeoIp geoip)
+{
+  /* Store the entry in our in-memory cache */
+  _cache.insert(geoip.ip().toIPv4Address(), 
+                GeoIpCacheItem(geoip,QDateTime::currentDateTime()));
+}
+
+/** Returns a GeoIp object for the given IP from cache. */
+GeoIp
+GeoIpCache::geoip(QHostAddress ip)
+{
+  if (this->contains(ip)) {
+    return _cache.value(ip.toIPv4Address()).geoip();
+  }
+  return GeoIp();
+}
+
+/** Returns true if the given IP address is cached and the cached information
+ * is not stale. */
+bool
+GeoIpCache::contains(QHostAddress ip)
+{
+  quint32 ipv4 = ip.toIPv4Address();
+  if (_cache.contains(ipv4)) {
+    GeoIpCacheItem cacheItem = _cache.value(ipv4);
+    return !cacheItem.isExpired();
+  }
+  return false;
+}
+


Property changes on: trunk/src/geoip/geoipcache.cpp
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: trunk/src/geoip/geoipcache.h
===================================================================
--- trunk/src/geoip/geoipcache.h	                        (rev 0)
+++ trunk/src/geoip/geoipcache.h	2007-11-30 16:28:52 UTC (rev 2143)
@@ -0,0 +1,63 @@
+/****************************************************************
+ *  Vidalia is distributed under the following license:
+ *
+ *  Copyright (C) 2006,  Matt Edman, Justin Hipple
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  as published by the Free Software Foundation; either version 2
+ *  of the License, or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA  02110-1301, USA.
+ ****************************************************************/
+
+/**
+ * \file geoipcache.h
+ * \version $Id$
+ * \brief Caches the results of previous GeoIP requests
+ */
+
+#ifndef _GEOIPCACHE_H
+#define _GEOIPCACHE_H
+
+#include <QString>
+#include <QHash>
+#include <QHostAddress>
+
+#include "geoipcacheitem.h"
+
+
+class GeoIpCache
+{
+public:
+  /** Default constructor. */
+  GeoIpCache();
+  
+  /** Writes the current cache to disk. */
+  bool saveToDisk(QString *errmsg = 0);
+  /** Reads the cache in from disk. */
+  bool loadFromDisk(QString *errmsg = 0);
+  
+  /** Returns the location currently used for the cache file. */
+  QString cacheFilename();
+  /** Caches the given IP and geographic information to disk. */
+  void cache(GeoIp geoip);
+  /** Returns a GeoIp object for the given IP from cache. */
+  GeoIp geoip(QHostAddress ip);
+  /** Returns true if the given IP address is cached. */
+  bool contains(QHostAddress ip);
+  
+private:
+  QHash<quint32, GeoIpCacheItem> _cache;  /**< List of cached GeoIp objects. */  
+};
+
+#endif
+


Property changes on: trunk/src/geoip/geoipcache.h
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: trunk/src/geoip/geoipcacheitem.cpp
===================================================================
--- trunk/src/geoip/geoipcacheitem.cpp	                        (rev 0)
+++ trunk/src/geoip/geoipcacheitem.cpp	2007-11-30 16:28:52 UTC (rev 2143)
@@ -0,0 +1,95 @@
+/****************************************************************
+ *  Vidalia is distributed under the following license:
+ *
+ *  Copyright (C) 2006,  Matt Edman, Justin Hipple
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  as published by the Free Software Foundation; either version 2
+ *  of the License, or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA  02110-1301, USA.
+ ****************************************************************/
+
+/**
+ * \file geoipcacheitem.cpp
+ * \version $Id$
+ * \brief Cached result of a single IP-to-geolocation result
+ */
+
+#include <QStringList>
+
+#include "geoipcacheitem.h"
+
+
+/** Constructor */
+GeoIpCacheItem::GeoIpCacheItem(GeoIp geoip, QDateTime timestamp)
+{
+  _geoip = geoip;
+  _timestamp = timestamp;
+}
+
+/** Returns true if this cache item is empty and invalid. A valid cache item
+ * must have a valid GeoIp object and timestamp. */
+bool
+GeoIpCacheItem::isEmpty() const
+{
+  return (_geoip.isEmpty() || _timestamp.isNull());
+}
+
+/** Returns a string representing the contents of this cache item, suitable
+ * for writing to disk. The format is as in the following example:
+ *                     <Geo IP Data>:<Timestamp>
+ */
+QString
+GeoIpCacheItem::toString() const
+{
+  return _geoip.toString() + ":" + QString::number(_timestamp.toTime_t());
+}
+
+/** Returns a GeoIpCacheItem from a string as read from the cache that was
+ * written to disk. The format is:
+ *                     <Geo IP Data>[:<Timestamp>]
+ *
+ * If no value for Timestamp is given, the current date and time will be used.
+ * If the string cannot be parsed for valid cached GeoIP data, then an empty
+ * GeoIpCacheItem object is returned. The calling method should call isEmpty()
+ * on the returned GeoIpCacheItem object to ensure it got a valid object.
+ */
+GeoIpCacheItem
+GeoIpCacheItem::fromString(QString cacheString)
+{
+  QDateTime timestamp;
+  QStringList cacheData = cacheString.split(":");
+
+  if (cacheData.size() >= 1) {
+    GeoIp geoip = GeoIp::fromString(cacheData.at(0));
+    if (cacheData.size() >= 2)
+      timestamp.setTime_t(cacheData.at(1).toUInt());
+    else
+      timestamp = QDateTime::currentDateTime();
+    return GeoIpCacheItem(geoip, timestamp);
+  }
+  return GeoIpCacheItem();
+}
+
+/** Returns true if the cache item is too old to be considered valid. Normal
+ * cached responses are valid for one month. Cached UNKNOWN responses are
+ * considered valid for one week. */
+bool
+GeoIpCacheItem::isExpired() const
+{
+  if (_geoip.isUnknown()) {
+    return (_timestamp.addDays(7) < QDateTime::currentDateTime());
+  }
+  return (_timestamp.addMonths(1) < QDateTime::currentDateTime()); 
+}
+


Property changes on: trunk/src/geoip/geoipcacheitem.cpp
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: trunk/src/geoip/geoipcacheitem.h
===================================================================
--- trunk/src/geoip/geoipcacheitem.h	                        (rev 0)
+++ trunk/src/geoip/geoipcacheitem.h	2007-11-30 16:28:52 UTC (rev 2143)
@@ -0,0 +1,66 @@
+/****************************************************************
+ *  Vidalia is distributed under the following license:
+ *
+ *  Copyright (C) 2006,  Matt Edman, Justin Hipple
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  as published by the Free Software Foundation; either version 2
+ *  of the License, or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA  02110-1301, USA.
+ ****************************************************************/
+
+/**
+ * \file geoipcacheitem.h
+ * \version $Id$
+ * \brief Cached result of a single IP-to-geolocation result
+ */
+
+#ifndef _GEOIPCACHEITEM_H
+#define _GEOIPCACHEITEM_H
+
+#include <QDateTime>
+
+#include "geoip.h"
+
+
+class GeoIpCacheItem
+{
+public:
+  /** Default constructor */
+  GeoIpCacheItem() {};
+  /** Constructor. */
+  GeoIpCacheItem(GeoIp geoip, QDateTime timestamp);
+
+  /** Returns the IP of this cache item. */
+  QHostAddress ip() const { return _geoip.ip(); }
+  /** Returns the cached GeoIp object. */
+  GeoIp geoip() const { return _geoip; }
+  /** Returns true if this cache item is expired. */
+  bool isExpired() const;
+  /** Returns true if this cache item is empty and invalid. */
+  bool isEmpty() const;
+
+  /** Returns a string representing the contents of this cache item, suitable
+   * for writing to disk. */
+  QString toString() const;
+  /** Returns a GeoIpCacheItem from a string as read from the cache that was
+   * written to disk. */
+  static GeoIpCacheItem fromString(QString cacheString);
+
+private:
+  GeoIp     _geoip;      /**< Cached GeoIp item. */
+  QDateTime _timestamp;  /**< Time this item was cached. */
+};
+
+#endif
+


Property changes on: trunk/src/geoip/geoipcacheitem.h
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: trunk/src/geoip/geoiprequest.cpp
===================================================================
--- trunk/src/geoip/geoiprequest.cpp	                        (rev 0)
+++ trunk/src/geoip/geoiprequest.cpp	2007-11-30 16:28:52 UTC (rev 2143)
@@ -0,0 +1,88 @@
+/****************************************************************
+ *  Vidalia is distributed under the following license:
+ *
+ *  Copyright (C) 2006-2007,  Matt Edman, Justin Hipple
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  as published by the Free Software Foundation; either version 2
+ *  of the License, or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA  02110-1301, USA.
+ ***************************************************************/
+
+/**
+ * \file geoiprequest.cpp
+ * \version $Id$
+ * \brief A formatted request for GeoIP information for one or more IPs
+ */
+
+#include <util/zlibbytearray.h>
+
+#include "geoiprequest.h"
+
+
+/** Creates an HTTP POST header for this request, based on the 
+ * Host, Page, and content-length values. */
+QHttpRequestHeader
+GeoIpRequest::createHeader()
+{
+  QHttpRequestHeader header("POST", _page, 1, 1);
+  
+  if (!_host.isEmpty())
+    header.setValue("Host", _host);
+  header.setContentType("application/x-www-form-urlencoded");
+  header.setContentLength(_request.length());
+  header.setValue("Connection", "close");
+
+  if (ZlibByteArray::isZlibAvailable()) {
+    QString acceptEncodings = "deflate, x-deflate";
+    if (ZlibByteArray::isGzipSupported())
+      acceptEncodings += ", gzip, x-gzip";
+    header.setValue("Accept-Encoding", acceptEncodings);
+  }
+
+  return header;
+}
+
+/** Sets the list of IPs whose geo information we want to request. */
+void
+GeoIpRequest::setRequest(QList<QHostAddress> ips)
+{
+  _request = "ip=";
+  int ipcount = ips.size();
+
+  /* Add each IP to a comma-delimited list. */
+  for (int i = 0; i < ipcount; i++) {
+    _request.append(ips.at(i).toString());
+    if (i < ipcount-1) {
+      _request.append(",");
+    }
+  }
+  _ips = ips;
+}
+
+/** Formats the request as an HTTP POST request. */
+QByteArray
+GeoIpRequest::request()
+{
+  /* Create the header and append the request content. */
+  QString request = createHeader().toString() + _request;
+  return request.toAscii();
+}
+
+/** Returns true if this request contains <b>ip</b>. */
+bool
+GeoIpRequest::contains(QHostAddress ip)
+{
+  return _ips.contains(ip);
+}
+


Property changes on: trunk/src/geoip/geoiprequest.cpp
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: trunk/src/geoip/geoiprequest.h
===================================================================
--- trunk/src/geoip/geoiprequest.h	                        (rev 0)
+++ trunk/src/geoip/geoiprequest.h	2007-11-30 16:28:52 UTC (rev 2143)
@@ -0,0 +1,70 @@
+/****************************************************************
+ *  Vidalia is distributed under the following license:
+ *
+ *  Copyright (C) 2006,  Matt Edman, Justin Hipple
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  as published by the Free Software Foundation; either version 2
+ *  of the License, or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA  02110-1301, USA.
+ ****************************************************************/
+
+/**
+ * \file geoiprequest.h
+ * \version $Id$
+ * \brief A formatted request for GeoIP information for one or more IPs
+ */
+
+#ifndef _GEOIPREQUEST_H
+#define _GEOIPREQUEST_H
+
+#include <QList>
+#include <QString>
+#include <QByteArray>
+#include <QHostAddress>
+#include <QHttpRequestHeader>
+
+
+class GeoIpRequest
+{
+public:
+  /** Constructor */
+  GeoIpRequest(int id) : _id(id) {}
+  
+  /** Sets the Host: field in this request's header. */
+  void setHost(QString host) { _host = host; }
+  /** Sets the page path in this request's header. */
+  void setPage(QString page) { _page = page; }
+  /** Sets the list of IPs whose geo information we want to request. */
+  void setRequest(QList<QHostAddress> ips);
+  /** Returns true if this request contains <b>ip</b>. */
+  bool contains(QHostAddress ip);
+
+  /** Returns the request's identifier. */
+  int id() { return _id; }
+  /** Formats the request as an HTTP POST request */
+  QByteArray request();
+  
+private:
+  /** Creates an HTTP header for this request. */
+  QHttpRequestHeader createHeader();
+  
+  int _id;          /**< Request identifier */
+  QString _host;    /**< Host: field value. */
+  QString _page;    /**< Page giving us the geo ip information. */
+  QString _request; /**< Formatted Geo IP request string. */
+  QList<QHostAddress> _ips; /**< List of IP addresses in this request. */
+};
+
+#endif
+


Property changes on: trunk/src/geoip/geoiprequest.h
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: trunk/src/geoip/geoipresolver.cpp
===================================================================
--- trunk/src/geoip/geoipresolver.cpp	                        (rev 0)
+++ trunk/src/geoip/geoipresolver.cpp	2007-11-30 16:28:52 UTC (rev 2143)
@@ -0,0 +1,229 @@
+/****************************************************************
+ *  Vidalia is distributed under the following license:
+ *
+ *  Copyright (C) 2006,  Matt Edman, Justin Hipple
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  as published by the Free Software Foundation; either version 2
+ *  of the License, or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA  02110-1301, USA.
+ ****************************************************************/
+
+/**
+ * \file geoipresolver.cpp
+ * \version $Id$
+ * \brief Requests GeoIP information and caches the result
+ */
+
+#include "geoipresolver.h"
+
+/** Host for the geo ip information. This hostname round-robins between
+ * pasiphae.vidalia-project.net, thebe.vidalia-project.net, and
+ * cups.cs.cmu.edu. */ 
+#define GEOIP_HOST    "geoip.vidalia-project.net"
+/** Page that we request the geo ip information from. */
+#define GEOIP_PAGE    "/cgi-bin/geoip"
+
+
+/** Sets the address and port of Tor, through which GeoIP requests will be
+ * made. */
+void
+GeoIpResolver::setSocksHost(QHostAddress addr, quint16 port)
+{
+  _socksAddr = addr;
+  _socksPort = port;
+}
+
+/** Resolves <b>ip</b> to geographic information if it is cached. A resolved()
+ * signal will be emitted and true returned if we have cached geographic
+ * information for <b>ip</b>. Otherwise, this returns false. */
+bool
+GeoIpResolver::resolveFromCache(QHostAddress ip)
+{
+  if (_cache.contains(ip)) {
+    emit resolved(-1, QList<GeoIp>() << _cache.geoip(ip));
+    return true;
+  }
+  return false;
+}
+
+/** Resolves a list of IPs to a geographic location, but only those which are
+ * cached. Returns a list of IPs that were not in the cache. */
+QList<QHostAddress>
+GeoIpResolver::resolveFromCache(QList<QHostAddress> ips)
+{
+  QList<GeoIp> cached;
+
+  /* Build a list of which IPs have cached GeoIp information */
+  foreach (QHostAddress ip, ips) {
+    if (_cache.contains(ip)) {
+      ips.removeAt(ips.indexOf(ip));
+      cached << _cache.geoip(ip);
+    }
+  }
+
+  /* If any were cached, emit their results now */
+  if (cached.size() > 0) {
+    emit resolved(-1, cached);
+  }
+  return ips;
+}
+
+/** Resolves a single IP to a geographic location. */
+int
+GeoIpResolver::resolve(QHostAddress ip)
+{
+  return resolve(QList<QHostAddress>() << ip);
+}
+
+/** Called when the socket has connected to the Geo IP host. */
+void
+GeoIpResolver::connected()
+{
+  /* Find the socket and request for whoever called this slot */ 
+  TorSocket *socket = (TorSocket *)sender();
+  if (!_requestList.contains(socket)) {
+    return;
+  }
+  GeoIpRequest *req = (GeoIpRequest *)_requestList.value(socket);
+  
+  /* Send the request */
+  socket->write(req->request());
+}
+
+/** Called when the socket has disconnected from the Geo IP host. */
+void
+GeoIpResolver::disconnected()
+{
+  /* Find the socket and request for whoever called this slot */ 
+  TorSocket *socket = (TorSocket *)sender();
+  if (!_requestList.contains(socket)) {
+    return;
+  }
+  GeoIpRequest *request = (GeoIpRequest *)_requestList.take(socket);
+
+  /* Read and parse the response */
+  GeoIpResponse response = GeoIpResponse(socket->readAll());
+
+  /* Check the response code and see what we got */
+  if (response.statusCode() == 200) {
+    /* We got a 200 OK, so get the Geo IP information and cache the results */
+    int numCached = 0, i = 0;
+    QList<GeoIp> geoips = response.geoIps();
+    foreach (GeoIp geoip, geoips) {
+      QHostAddress ip = geoip.ip();
+      
+      if (request->contains(ip)) {
+        /* This is a requested geoip item, so if it wasn't cached, then 
+         * cache it now. */
+        if (!_cache.contains(ip)) {
+          _cache.cache(geoip);
+          numCached++;
+        }
+        i++;
+      } else {
+        /* This item wasn't requested, so remove it. According to the Qt docs,
+         * this is safe to do inside the foreach() loop because, "Qt
+         * automatically takes a copy of the container when it enters a
+         * foreach loop. If you modify the container as you are iterating,
+         * that won't affect the loop." */
+        geoips.removeAt(i);
+      }
+    }
+    /* If new results were cached, save them to disk */
+    if (numCached > 0) {
+      _cache.saveToDisk();
+    }
+    /* Emit the results */
+    emit resolved(request->id(), geoips);
+  } else {
+    /* We failed to get the Geo IP information, so emit resolveFailed and
+     * include the HTTP status message. */
+    emit resolveFailed(request->id(), response.statusMessage());
+  }
+  /* Close the socket and clean up */
+  socket->close();
+  delete socket;
+  delete request;
+}
+
+/** Called when an error has occurred requesting Geo IP information. */
+void
+GeoIpResolver::socketError(QString errorString)
+{
+  /* Find the socket and request for whoever called this slot */ 
+  TorSocket *socket = (TorSocket *)sender();
+  if (!_requestList.contains(socket)) {
+    return;
+  }
+  
+  /* We expect a remote host to close the socket, because that's how the HTTP
+   * server tells us he's done talkig to us. */
+  if (socket->error() != QAbstractSocket::RemoteHostClosedError) {
+    /* Emit the failure and clean up */
+    GeoIpRequest *request = (GeoIpRequest *)_requestList.take(socket);
+    emit resolveFailed(request->id(), errorString);
+    socket->abort();
+    delete socket;
+    delete request;
+  }
+}
+
+/** Creates an HTTP request for Geo IP information. */
+GeoIpRequest*
+GeoIpResolver::createRequest(QList<QHostAddress> ips)
+{
+  static int id = -1;
+  GeoIpRequest *request = new GeoIpRequest(++id);
+  request->setHost(GEOIP_HOST);
+  request->setPage(GEOIP_PAGE);
+  request->setRequest(ips);
+  return request;
+}
+
+/** Creates a TorSocket used to connect to the Geo IP host. */
+TorSocket*
+GeoIpResolver::createRequestSocket()
+{
+  TorSocket *socket = new TorSocket(_socksAddr, _socksPort);
+  connect(socket, SIGNAL(connectedToHost()), this, SLOT(connected()),
+          Qt::QueuedConnection);
+  connect(socket, SIGNAL(socketError(QString)), 
+            this,   SLOT(socketError(QString)),
+          Qt::QueuedConnection);
+  connect(socket, SIGNAL(disconnected()), this, SLOT(disconnected()),
+          Qt::QueuedConnection);
+  return socket;
+}
+
+/** Resolves a list of IPs to a geographic location. */
+int
+GeoIpResolver::resolve(QList<QHostAddress> ips)
+{
+  /* Resolve the cached IPs and get a list of IPs that still need to be
+   * resolved to a lat and long. */
+  QList<QHostAddress> uncached = resolveFromCache(ips);
+  if (!uncached.size()) {
+    return -1;
+  }
+
+  /* Create a socket used ot request the geo ip information. */
+  TorSocket *socket = createRequestSocket();
+  GeoIpRequest *request = createRequest(ips);
+  _requestList.insert(socket, request);
+  
+  /* Connect so we can send our request and return the request ID. */
+  socket->connectToHost(GEOIP_HOST, 80);
+  return request->id();
+}
+


Property changes on: trunk/src/geoip/geoipresolver.cpp
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: trunk/src/geoip/geoipresolver.h
===================================================================
--- trunk/src/geoip/geoipresolver.h	                        (rev 0)
+++ trunk/src/geoip/geoipresolver.h	2007-11-30 16:28:52 UTC (rev 2143)
@@ -0,0 +1,97 @@
+/****************************************************************
+ *  Vidalia is distributed under the following license:
+ *
+ *  Copyright (C) 2006,  Matt Edman, Justin Hipple
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  as published by the Free Software Foundation; either version 2
+ *  of the License, or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA  02110-1301, USA.
+ ****************************************************************/
+
+/**
+ * \file geoipresolver.h
+ * \version $Id$
+ * \brief Requests GeoIP information and caches the result
+ */
+
+#ifndef _GEOIPRESOLVER_H
+#define _GEOIPRESOLVER_H
+
+#include <QObject>
+#include <QList>
+#include <QHash>
+#include <QString>
+#include <QHostAddress>
+#include <util/torsocket.h>
+
+#include "geoip.h"
+#include "geoipcache.h"
+#include "geoiprequest.h"
+#include "geoipresponse.h"
+
+
+class GeoIpResolver : public QObject
+{
+  Q_OBJECT
+
+public:
+  /** Default constructor. */
+  GeoIpResolver() 
+  { _socksAddr = QHostAddress::LocalHost; _socksPort = 9050; }
+  
+  /** Sets the address and port of Tor, through which GeoIP requests will be
+   * made. */
+  void setSocksHost(QHostAddress addr, quint16 port);
+  /** Resolves a single IP to a geographic location. */
+  int resolve(QHostAddress ip);
+  /** Resolves a list of IPs to a geographic location. */
+  int resolve(QList<QHostAddress> ips);
+  /** Resolves <b>ip</b> to geographic information only if it is cached. */
+  bool resolveFromCache(QHostAddress ip);
+  /** Resolves a list of IPs to a geographic location, but only those which
+   * are cached. Returns a list of which IPs were not cached. */
+  QList<QHostAddress> resolveFromCache(QList<QHostAddress> ips);
+
+signals:
+  /** Emitted when a list of IPs have been resolved to lat/long. */
+  void resolved(int id, QList<GeoIp> geoips);
+  /** Emitted when a resolve has failed. */
+  void resolveFailed(int id, QString errorString);
+
+private slots:
+  /** Called when the socket has connected to the Geo IP host. */
+  void connected();
+  /** Called when the socket has disconnected from the Geo IP host. */
+  void disconnected();
+  /** Called when an error has occurred getting the Geo IP information. */
+  void socketError(QString errorString);
+
+private:
+  /** Creates an HTTP request for Geo IP information. */
+  GeoIpRequest* createRequest(QList<QHostAddress> ips);
+  /** Creates a socket used to request Geo IP information over Tor. */
+  TorSocket* createRequestSocket();
+  
+  /**< Cached GeoIp objects. */
+  GeoIpCache  _cache;
+  /**< List of sockets used for requests. */
+  QHash<TorSocket *,GeoIpRequest*> _requestList;
+  /** Tor's SocksListenAddress. */
+  QHostAddress _socksAddr;
+  /** Tor's SocksPort. */
+  quint16 _socksPort;
+};
+
+#endif
+


Property changes on: trunk/src/geoip/geoipresolver.h
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: trunk/src/geoip/geoipresponse.cpp
===================================================================
--- trunk/src/geoip/geoipresponse.cpp	                        (rev 0)
+++ trunk/src/geoip/geoipresponse.cpp	2007-11-30 16:28:52 UTC (rev 2143)
@@ -0,0 +1,137 @@
+/****************************************************************
+ *  Vidalia is distributed under the following license:
+ *
+ *  Copyright (C) 2006-2007,  Matt Edman, Justin Hipple
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  as published by the Free Software Foundation; either version 2
+ *  of the License, or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA  02110-1301, USA.
+ ****************************************************************/
+
+/**
+ * \file geoipresponse.cpp
+ * \version $Id$
+ * \brief Parses a response to a previous GeoIP request
+ */
+
+#include <QStringList>
+#include <util/zlibbytearray.h>
+
+#include "geoipresponse.h"
+
+/** Status code for a successful HTTP request. */
+#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
+ * information. */
+GeoIpResponse::GeoIpResponse(QByteArray response)
+{
+  QString errmsg;
+  
+  /* Parse out the header */
+  int headerPos = response.indexOf("\r\n\r\n");
+  _header = QHttpResponseHeader(QString(response.mid(0, headerPos)));
+
+  /* Parse out the Geo IP information, if any was included. */
+  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");
+      if (encoding == "gzip" || encoding == "x-gzip") {
+        method = ZlibByteArray::Gzip;
+      } else if (encoding == "deflate" || encoding == "x-deflate") {
+        method = ZlibByteArray::Zlib;
+      } else if (encoding == "text/plain") {
+        method = ZlibByteArray::None;
+      } else {
+        _header.setStatusLine(STATUS_CONTENT_ENCODING_ERR,
+          QString("Unknown content encoding '%1'").arg(encoding));
+        return;
+      }
+ 
+      content = ZlibByteArray::uncompress(content, method, &errmsg);
+      if (content.isEmpty()) {
+        _header.setStatusLine(STATUS_CONTENT_ENCODING_ERR,
+          QString("Content decoding using method '%1' failed: %2")
+                                       .arg(encoding).arg(errmsg));
+        return;
+      }
+    }
+
+    /* Parse the Geo IP information in each line */
+    QStringList lines = QString(content).split("\n");
+    foreach (QString line, lines) {
+      GeoIp geoip = GeoIp::fromString(line);
+      if (!geoip.isEmpty())
+        _geoips << geoip;
+    }
+  }
+}
+
+/** 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;
+}
+


Property changes on: trunk/src/geoip/geoipresponse.cpp
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: trunk/src/geoip/geoipresponse.h
===================================================================
--- trunk/src/geoip/geoipresponse.h	                        (rev 0)
+++ trunk/src/geoip/geoipresponse.h	2007-11-30 16:28:52 UTC (rev 2143)
@@ -0,0 +1,62 @@
+/****************************************************************
+ *  Vidalia is distributed under the following license:
+ *
+ *  Copyright (C) 2006,  Matt Edman, Justin Hipple
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  as published by the Free Software Foundation; either version 2
+ *  of the License, or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA  02110-1301, USA.
+ ****************************************************************/
+
+/**
+ * \file geoipresponse.h
+ * \version $Id$
+ * \brief Parses a response to a previous GeoIP request
+ */
+
+#ifndef _GEOIPRESPONSE_H
+#define _GEOIPRESPONSE_H
+
+#include <QList>
+#include <QByteArray>
+#include <QHttpResponseHeader>
+
+#include "geoip.h"
+
+
+class GeoIpResponse
+{
+public:
+  /** Constructor. Parses the response data for an HTTP header and Geo IP
+   * information.  */
+  GeoIpResponse(QByteArray response);
+
+  /** Returns the HTTP status code for this response. */
+  int statusCode() { return _header.statusCode(); }
+  /** Returns the HTTP status message for this response. */
+  QString statusMessage() { return _header.reasonPhrase(); }
+  /** Returns the Geo IP information contained in this response. */
+  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. */
+};
+
+#endif
+


Property changes on: trunk/src/geoip/geoipresponse.h
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Modified: trunk/src/gui/network/netviewer.h
===================================================================
--- trunk/src/gui/network/netviewer.h	2007-11-30 16:28:34 UTC (rev 2142)
+++ trunk/src/gui/network/netviewer.h	2007-11-30 16:28:52 UTC (rev 2143)
@@ -34,7 +34,7 @@
 #include <QTimer>
 #include <QHash>
 #include <torcontrol.h>
-#include <util/geoip/geoipresolver.h>
+#include <geoipresolver.h>
 #include <vidaliawindow.h>
 
 #include "tormapwidget.h"

Modified: trunk/src/gui/network/routerlistitem.h
===================================================================
--- trunk/src/gui/network/routerlistitem.h	2007-11-30 16:28:34 UTC (rev 2142)
+++ trunk/src/gui/network/routerlistitem.h	2007-11-30 16:28:52 UTC (rev 2143)
@@ -32,7 +32,7 @@
 #include <QTreeWidgetItem>
 #include <QString>
 #include <control/routerdescriptor.h>
-#include <util/geoip/geoip.h>
+#include <geoip.h>
 
 #include "routerlistwidget.h"
 

Modified: trunk/src/src.pri
===================================================================
--- trunk/src/src.pri	2007-11-30 16:28:34 UTC (rev 2142)
+++ trunk/src/src.pri	2007-11-30 16:28:52 UTC (rev 2143)
@@ -34,4 +34,5 @@
 include($$PWD/config/config.pri)
 include($$PWD/control/control.pri)
 include($$PWD/util/util.pri)
+include($$PWD/geoip/geoip.pri)
 

Modified: trunk/src/util/util.pri
===================================================================
--- trunk/src/util/util.pri	2007-11-30 16:28:34 UTC (rev 2142)
+++ trunk/src/util/util.pri	2007-11-30 16:28:52 UTC (rev 2143)
@@ -46,5 +46,3 @@
     SOURCES += $$PWD/win32.cpp
 }
 
-include($$PWD/geoip/geoip.pri)
-