geoipcache.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 geoipcache.cpp
00013 ** \version $Id: geoipcache.cpp 2362 2008-02-29 04:30:11Z edmanm $
00014 ** \brief Caches the results of previous GeoIP requests
00015 */
00016 
00017 #include <QFile>
00018 #include <QDir>
00019 #include <QTextStream>
00020 #include <stringutil.h>
00021 #include <file.h>
00022 #include <vidalia.h>
00023 
00024 #include "geoipcache.h"
00025 
00026 /* Location of Vidalia's geoip cache file. Qt docs claims that QFile will
00027  * translate the "/" correctly on Windows. Hopefully they didn't lie. */
00028 #define CACHE_FILENAME  (Vidalia::dataDirectory() + "/geoip-cache")
00029 
00030 
00031 /** Constructor. */
00032 GeoIpCache::GeoIpCache()
00033 {
00034   loadFromDisk();
00035 }
00036 
00037 /** Returns the location currently used for the cache file. */
00038 QString
00039 GeoIpCache::cacheFilename()
00040 {
00041   return CACHE_FILENAME;
00042 }
00043 
00044 /** Writes the current cache to disk. */
00045 bool
00046 GeoIpCache::saveToDisk(QString *errmsg)
00047 {
00048   /* Make sure we have a data directory. */
00049   if (!create_path(Vidalia::dataDirectory())) {
00050     return false;
00051   }
00052   
00053   /* Try to open a temporary cache file for writing */
00054   QFile tmpCacheFile(CACHE_FILENAME + ".tmp");
00055   if (!tmpCacheFile.open(QIODevice::WriteOnly | QIODevice::Text)) {
00056     return err(errmsg, tmpCacheFile.errorString());
00057   }
00058   
00059   /* Write the cache entries to the file. */
00060   QTextStream cache(&tmpCacheFile);
00061   foreach (GeoIpCacheItem cacheItem, _cache.values()) {
00062     /* Save the cache item if it's not too old. */
00063     if (!cacheItem.isExpired()) {
00064       cache << cacheItem.toString() << endl;
00065     }
00066   }
00067   
00068   QFile cacheFile(CACHE_FILENAME);
00069   /* Check if an previous cache file exists. */
00070   if (cacheFile.exists()) {
00071     /* A previous cache file exists, so try to remove it */
00072     if (!cacheFile.remove()) {
00073       return err(errmsg, cacheFile.errorString());
00074     }
00075   }
00076   /* Rename the temporary file into place. */
00077   if (tmpCacheFile.rename(cacheFile.fileName())) {
00078     return err(errmsg, tmpCacheFile.errorString());
00079   }
00080   return true;
00081 }
00082 
00083 /** Reads the cache contents in from disk. This function returns true if no
00084  * cache file exists, since it's possible nothing has been cached yet. */
00085 bool
00086 GeoIpCache::loadFromDisk(QString *errmsg)
00087 {
00088   QFile cacheFile(CACHE_FILENAME);
00089   
00090   if (cacheFile.exists()) {
00091     /* Try to open the cache file */
00092     if (!cacheFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
00093       return err(errmsg, cacheFile.errorString());
00094     }
00095     
00096     /* Read the cached items from the cache file */
00097     QTextStream cache(&cacheFile);
00098     QString line = cache.readLine();
00099     while (!line.isNull()) {
00100       /* Create a GeoIpCacheItem from the line and save it */
00101       GeoIpCacheItem item = GeoIpCacheItem::fromString(line);
00102       if (!item.isEmpty() && !item.isExpired()) {
00103         /* Only load non-stale cache items. */
00104         _cache.insert(item.ip().toIPv4Address(), item);
00105       }
00106       line = cache.readLine();
00107     }
00108   }
00109   return true;
00110 }
00111 
00112 /** Caches the given IP and geographic information to disk. Call saveToDisk()
00113  * when you want to write the cache to disk. */
00114 void
00115 GeoIpCache::cache(GeoIp geoip)
00116 {
00117   /* Store the entry in our in-memory cache */
00118   _cache.insert(geoip.ip().toIPv4Address(), 
00119                 GeoIpCacheItem(geoip,QDateTime::currentDateTime()));
00120 }
00121 
00122 /** Returns a GeoIp object for the given IP from cache. */
00123 GeoIp
00124 GeoIpCache::geoip(QHostAddress ip)
00125 {
00126   if (this->contains(ip)) {
00127     return _cache.value(ip.toIPv4Address()).geoip();
00128   }
00129   return GeoIp();
00130 }
00131 
00132 /** Returns true if the given IP address is cached and the cached information
00133  * is not stale. */
00134 bool
00135 GeoIpCache::contains(QHostAddress ip)
00136 {
00137   quint32 ipv4 = ip.toIPv4Address();
00138   if (_cache.contains(ipv4)) {
00139     GeoIpCacheItem cacheItem = _cache.value(ipv4);
00140     return !cacheItem.isExpired();
00141   }
00142   return false;
00143 }
00144 

Generated on Wed Dec 23 21:11:08 2009 for Vidalia by  doxygen 1.6.1