geoipcache.cpp

Go to the documentation of this file.
00001 /****************************************************************
00002  *  Vidalia is distributed under the following license:
00003  *
00004  *  Copyright (C) 2006,  Matt Edman, Justin Hipple
00005  *
00006  *  This program is free software; you can redistribute it and/or
00007  *  modify it under the terms of the GNU General Public License
00008  *  as published by the Free Software Foundation; either version 2
00009  *  of the License, or (at your option) any later version.
00010  *
00011  *  This program is distributed in the hope that it will be useful,
00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *  GNU General Public License for more details.
00015  *
00016  *  You should have received a copy of the GNU General Public License
00017  *  along with this program; if not, write to the Free Software
00018  *  Foundation, Inc., 51 Franklin Street, Fifth Floor,
00019  *  Boston, MA  02110-1301, USA.
00020  ****************************************************************/
00021 
00022 /**
00023  * \file geoipcache.cpp
00024  * \version $Id: geoipcache.cpp 1563 2006-12-26 06:06:04Z edmanm $
00025  * \brief Caches the results of previous GeoIP requests
00026  */
00027 
00028 #include <QFile>
00029 #include <QDir>
00030 #include <QTextStream>
00031 #include <util/string.h>
00032 #include <util/file.h>
00033 #include <vidalia.h>
00034 
00035 #include "geoipcache.h"
00036 
00037 /* Location of Vidalia's geoip cache file. Qt docs claims that QFile will
00038  * translate the "/" correctly on Windows. Hopefully they didn't lie. */
00039 #define CACHE_FILENAME  (Vidalia::dataDirectory() + "/geoip-cache")
00040 
00041 
00042 /** Constructor. */
00043 GeoIpCache::GeoIpCache()
00044 {
00045   loadFromDisk();
00046 }
00047 
00048 /** Returns the location currently used for the cache file. */
00049 QString
00050 GeoIpCache::cacheFilename()
00051 {
00052   return CACHE_FILENAME;
00053 }
00054 
00055 /** Writes the current cache to disk. */
00056 bool
00057 GeoIpCache::saveToDisk(QString *errmsg)
00058 {
00059   /* Make sure we have a data directory. */
00060   if (!create_path(Vidalia::dataDirectory())) {
00061     return false;
00062   }
00063   
00064   /* Try to open a temporary cache file for writing */
00065   QFile tmpCacheFile(CACHE_FILENAME + ".tmp");
00066   if (!tmpCacheFile.open(QIODevice::WriteOnly | QIODevice::Text)) {
00067     return err(errmsg, tmpCacheFile.errorString());
00068   }
00069   
00070   /* Write the cache entries to the file. */
00071   QTextStream cache(&tmpCacheFile);
00072   foreach (GeoIpCacheItem cacheItem, _cache.values()) {
00073     /* Save the cache item if it's not too old. */
00074     if (!cacheItem.isExpired()) {
00075       cache << cacheItem.toString() << endl;
00076     }
00077   }
00078   
00079   QFile cacheFile(CACHE_FILENAME);
00080   /* Check if an previous cache file exists. */
00081   if (cacheFile.exists()) {
00082     /* A previous cache file exists, so try to remove it */
00083     if (!cacheFile.remove()) {
00084       return err(errmsg, cacheFile.errorString());
00085     }
00086   }
00087   /* Rename the temporary file into place. */
00088   if (tmpCacheFile.rename(cacheFile.fileName())) {
00089     return err(errmsg, tmpCacheFile.errorString());
00090   }
00091   return true;
00092 }
00093 
00094 /** Reads the cache contents in from disk. This function returns true if no
00095  * cache file exists, since it's possible nothing has been cached yet. */
00096 bool
00097 GeoIpCache::loadFromDisk(QString *errmsg)
00098 {
00099   QFile cacheFile(CACHE_FILENAME);
00100   
00101   if (cacheFile.exists()) {
00102     /* Try to open the cache file */
00103     if (!cacheFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
00104       return err(errmsg, cacheFile.errorString());
00105     }
00106     
00107     /* Read the cached items from the cache file */
00108     QTextStream cache(&cacheFile);
00109     QString line = cache.readLine();
00110     while (!line.isNull()) {
00111       /* Create a GeoIpCacheItem from the line and save it */
00112       GeoIpCacheItem item = GeoIpCacheItem::fromString(line);
00113       if (!item.isEmpty() && !item.isExpired()) {
00114         /* Only load non-stale cache items. */
00115         _cache.insert(item.ip().toIPv4Address(), item);
00116       }
00117       line = cache.readLine();
00118     }
00119   }
00120   return true;
00121 }
00122 
00123 /** Caches the given IP and geographic information to disk. Call saveToDisk()
00124  * when you want to write the cache to disk. */
00125 void
00126 GeoIpCache::cache(GeoIp geoip)
00127 {
00128   /* Store the entry in our in-memory cache */
00129   _cache.insert(geoip.ip().toIPv4Address(), 
00130                 GeoIpCacheItem(geoip,QDateTime::currentDateTime()));
00131 }
00132 
00133 /** Returns a GeoIp object for the given IP from cache. */
00134 GeoIp
00135 GeoIpCache::geoip(QHostAddress ip)
00136 {
00137   if (this->contains(ip)) {
00138     return _cache.value(ip.toIPv4Address()).geoip();
00139   }
00140   return GeoIp();
00141 }
00142 
00143 /** Returns true if the given IP address is cached and the cached information
00144  * is not stale. */
00145 bool
00146 GeoIpCache::contains(QHostAddress ip)
00147 {
00148   quint32 ipv4 = ip.toIPv4Address();
00149   if (_cache.contains(ipv4)) {
00150     GeoIpCacheItem cacheItem = _cache.value(ipv4);
00151     return !cacheItem.isExpired();
00152   }
00153   return false;
00154 }
00155 

Generated on Wed Sep 5 15:49:27 2007 for Vidalia by  doxygen 1.5.3