GeoIpCacheItem.cpp

Go to the documentation of this file.
00001 /*
00002 **  This file is part of Vidalia, and is subject to the license terms in the
00003 **  LICENSE file, found in the top level directory of this distribution. If you
00004 **  did not receive the LICENSE file with this file, you may obtain it from the
00005 **  Vidalia source package distributed by the Vidalia Project at
00006 **  http://www.vidalia-project.net/. No part of Vidalia, including this file,
00007 **  may be copied, modified, propagated, or distributed except according to the
00008 **  terms described in the LICENSE file.
00009 */
00010 
00011 /*
00012 ** \file GeoIpCacheItem.cpp
00013 ** \version $Id: GeoIpCacheItem.cpp 3768 2009-05-13 19:07:26Z edmanm $
00014 ** \brief Cached result of a single IP-to-geolocation result
00015 */
00016 
00017 #include "GeoIpCacheItem.h"
00018 #include "GeoIp.h"
00019 
00020 #include "stringutil.h"
00021 
00022 #include <QString>
00023 #include <QDateTime>
00024 #include <QStringList>
00025 
00026 #define CACHE_KEY_FROM_IP       "FROM"
00027 #define CACHE_KEY_TO_IP         "TO"
00028 #define CACHE_KEY_EXPIRES       "EXPIRES"
00029 #define CACHE_KEY_LATITUDE      "LAT"
00030 #define CACHE_KEY_LONGITUDE     "LON"
00031 #define CACHE_KEY_CITY          "CITY"
00032 #define CACHE_KEY_REGION        "REGION"
00033 #define CACHE_KEY_COUNTRY       "COUNTRY"
00034 #define CACHE_KEY_COUNTRY_CODE  "CC"
00035 
00036 
00037 GeoIpCacheItem::GeoIpCacheItem()
00038 {
00039   _fromIp = 0;
00040   _toIp = 0;
00041 }
00042 
00043 GeoIpCacheItem::GeoIpCacheItem(const QHostAddress &from, const QHostAddress &to,
00044                                const GeoIp &geoip, const QDateTime &expires)
00045 {
00046   _fromIp = from.toIPv4Address();
00047   _toIp = to.toIPv4Address();
00048   _expires = expires;
00049 
00050   _fields.insert(CACHE_KEY_LATITUDE, geoip.latitude());
00051   _fields.insert(CACHE_KEY_LONGITUDE, geoip.longitude());
00052   if (! geoip.city().isEmpty())
00053     _fields.insert(CACHE_KEY_CITY, geoip.city());
00054   if (! geoip.region().isEmpty())
00055     _fields.insert(CACHE_KEY_REGION, geoip.region());
00056   if (! geoip.country().isEmpty())
00057     _fields.insert(CACHE_KEY_COUNTRY, geoip.country());
00058   if (! geoip.countryCode().isEmpty())
00059     _fields.insert(CACHE_KEY_COUNTRY_CODE, geoip.countryCode());
00060 }
00061 
00062 QHostAddress
00063 GeoIpCacheItem::ipRangeStart() const
00064 {
00065   return QHostAddress(_fromIp);
00066 }
00067 
00068 QHostAddress
00069 GeoIpCacheItem::ipRangeEnd() const
00070 {
00071   return QHostAddress(_toIp);
00072 }
00073 
00074 bool
00075 GeoIpCacheItem::contains(const QHostAddress &ip) const
00076 {
00077   quint32 ipv4 = ip.toIPv4Address();
00078 
00079   return (ipv4 >= _fromIp && ipv4 <= _toIp);
00080 }
00081 
00082 bool
00083 GeoIpCacheItem::isValid() const
00084 {
00085   return (_expires.isValid()
00086             && ! QHostAddress(_fromIp).isNull()
00087             && ! QHostAddress(_toIp).isNull()
00088             && _fromIp <= _toIp
00089             && _fields.contains(CACHE_KEY_LATITUDE)
00090             && _fields.contains(CACHE_KEY_LONGITUDE));
00091 }
00092 
00093 bool
00094 GeoIpCacheItem::isExpired() const
00095 {
00096   return (_expires < QDateTime::currentDateTime().toUTC());
00097 }
00098 
00099 GeoIp
00100 GeoIpCacheItem::toGeoIp(const QHostAddress &ip) const
00101 {
00102   if (this->contains(ip))
00103     return GeoIp(ip,
00104                  _fields.value(CACHE_KEY_LATITUDE).toDouble(),
00105                  _fields.value(CACHE_KEY_LONGITUDE).toDouble(),
00106                  _fields.value(CACHE_KEY_CITY).toString(),
00107                  _fields.value(CACHE_KEY_REGION).toString(),
00108                  _fields.value(CACHE_KEY_COUNTRY).toString(),
00109                  _fields.value(CACHE_KEY_COUNTRY_CODE).toString());
00110   return GeoIp();
00111 }
00112 
00113 QString
00114 GeoIpCacheItem::toCacheString() const
00115 {
00116   QStringList keyvals;
00117 
00118   keyvals << QString(CACHE_KEY_FROM_IP"=%1").arg(QHostAddress(_fromIp).toString());
00119   keyvals << QString(CACHE_KEY_TO_IP"=%1").arg(QHostAddress(_toIp).toString());
00120   keyvals << QString(CACHE_KEY_EXPIRES"=\"%1\"").arg(_expires.toString(Qt::ISODate));
00121 
00122   foreach (QString key, _fields.keys()) {
00123     QString value = _fields.value(key).toString();
00124     if (value.contains(" ")) {
00125       value.replace("\\", "\\\\");
00126       value.replace("\"", "\\\"");
00127       value = "\"" + value + "\"";
00128     }
00129     keyvals << key + "=" + value;
00130   }
00131   return keyvals.join(" ");
00132 }
00133 
00134 GeoIpCacheItem
00135 GeoIpCacheItem::fromCacheString(const QString &line)
00136 {
00137   GeoIpCacheItem ci;
00138   bool ok;
00139 
00140   QHash<QString,QString> keyvals = string_parse_keyvals(line, &ok);
00141   if (! ok)
00142     return GeoIpCacheItem();
00143   
00144   /* Get the range of IP addresses associated with this cache entry */
00145   QHostAddress fromIp(keyvals.value(CACHE_KEY_FROM_IP));
00146   QHostAddress toIp(keyvals.value(CACHE_KEY_TO_IP));
00147   if (fromIp.isNull() || toIp.isNull())
00148     return GeoIpCacheItem();
00149   ci._fromIp = fromIp.toIPv4Address();
00150   ci._toIp = toIp.toIPv4Address();
00151 
00152   /* Extract the expiration timestamp of this entry */
00153   ci._expires = QDateTime::fromString(keyvals.value(CACHE_KEY_EXPIRES),
00154                                    Qt::ISODate);
00155   if (! ci._expires.isValid())
00156     ci._expires = QDateTime::currentDateTime().toUTC().addDays(30);
00157   
00158   
00159   /* Make sure we have valid geographic coordinates */
00160   float latitude = keyvals.value(CACHE_KEY_LATITUDE).toFloat(&ok);
00161   if (! ok)
00162     return GeoIpCacheItem();
00163   ci._fields.insert(CACHE_KEY_LATITUDE, latitude);
00164 
00165   float longitude = keyvals.value(CACHE_KEY_LONGITUDE).toFloat(&ok);
00166   if (! ok)
00167     return GeoIpCacheItem();
00168   ci._fields.insert(CACHE_KEY_LONGITUDE, longitude);
00169   
00170   /* Each of these fields is optional */
00171   if (keyvals.contains(CACHE_KEY_CITY))
00172     ci._fields.insert(CACHE_KEY_CITY, keyvals.value(CACHE_KEY_CITY));
00173   if (keyvals.contains(CACHE_KEY_REGION))
00174     ci._fields.insert(CACHE_KEY_REGION, keyvals.value(CACHE_KEY_REGION));
00175   if (keyvals.contains(CACHE_KEY_COUNTRY))
00176     ci._fields.insert(CACHE_KEY_COUNTRY, keyvals.value(CACHE_KEY_COUNTRY));
00177   if (keyvals.contains(CACHE_KEY_COUNTRY_CODE))
00178     ci._fields.insert(CACHE_KEY_COUNTRY_CODE,
00179                       keyvals.value(CACHE_KEY_COUNTRY_CODE));
00180 
00181   return ci;
00182 }
00183 

Generated on Mon Aug 30 19:14:02 2010 for Vidalia by  doxygen 1.5.9