1// 2// This file is part of the aMule Project. 3// 4// Copyright (c) 2004-2011 Marcelo Roberto Jimenez ( phoenix@amule.org ) 5// Copyright (c) 2006-2011 aMule Team ( admin@amule.org / http://www.amule.org ) 6// 7// Any parts of this program derived from the xMule, lMule or eMule project, 8// or contributed by third-party developers are copyrighted by their 9// respective authors. 10// 11// This program is free software; you can redistribute it and/or modify 12// it under the terms of the GNU General Public License as published by 13// the Free Software Foundation; either version 2 of the License, or 14// (at your option) any later version. 15// 16// This program is distributed in the hope that it will be useful, 17// but WITHOUT ANY WARRANTY; without even the implied warranty of 18// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19// GNU General Public License for more details. 20// 21// You should have received a copy of the GNU General Public License 22// along with this program; if not, write to the Free Software 23// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 24// 25 26 27// 28// Country flags are from FAMFAMFAM (http://www.famfamfam.com) 29// 30// Flag icons - http://www.famfamfam.com 31// 32// These icons are public domain, and as such are free for any use (attribution appreciated but not required). 33// 34// Note that these flags are named using the ISO3166-1 alpha-2 country codes where appropriate. 35// A list of codes can be found at http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2 36// 37// If you find these icons useful, please donate via paypal to mjames@gmail.com 38// (or click the donate button available at http://www.famfamfam.com/lab/icons/silk) 39// 40// Contact: mjames@gmail.com 41// 42 43#ifdef HAVE_CONFIG_H 44# include "config.h" // Needed for ENABLE_IP2COUNTRY 45#endif 46 47#ifdef _MSC_VER 48// For MSVC we need to check here if geoip is available at all. MinGW needs the include below however. 49 50// Block unnecessary includes from GeoIP.h 51#define _WINDOWS_ 52#define _WINSOCK2API_ 53#define _WS2TCPIP_H_ 54#define _WSPIAPI_H_ 55#include <GeoIP.h> 56#endif 57 58#ifdef ENABLE_IP2COUNTRY 59 60#include "Preferences.h" // For thePrefs 61#include "CFile.h" // For CPath 62#include "HTTPDownload.h" 63#include "Logger.h" // For AddLogLineM() 64#include <common/Format.h> // For CFormat() 65#include "common/FileFunctions.h" // For UnpackArchive 66#include <common/StringFunctions.h> // For unicode2char() 67#include "pixmaps/flags_xpm/CountryFlags.h" 68 69#include <wx/intl.h> 70#include <wx/image.h> 71 72#include <GeoIP.h> 73#include "IP2Country.h" 74 75CIP2Country::CIP2Country(const wxString& configDir) 76{ 77 m_geoip = NULL; 78 m_DataBaseName = wxT("GeoIP.dat"); 79 m_DataBasePath = configDir + m_DataBaseName; 80} 81 82void CIP2Country::Enable() 83{ 84 Disable(); 85 86 if (m_CountryDataMap.empty()) { 87 LoadFlags(); 88 } 89 90 if (!CPath::FileExists(m_DataBasePath)) { 91 Update(); 92 return; 93 } 94 95 m_geoip = GeoIP_open(unicode2char(m_DataBasePath), GEOIP_STANDARD); 96} 97 98void CIP2Country::Update() 99{ 100 AddLogLineN(CFormat(_("Download new GeoIP.dat from %s")) % thePrefs::GetGeoIPUpdateUrl()); 101 CHTTPDownloadThread *downloader = new CHTTPDownloadThread(thePrefs::GetGeoIPUpdateUrl(), m_DataBasePath + wxT(".download"), m_DataBasePath, HTTP_GeoIP, true, true); 102 downloader->Create(); 103 downloader->Run(); 104} 105 106void CIP2Country::Disable() 107{ 108 if (m_geoip) { 109 GeoIP_delete(m_geoip); 110 m_geoip = NULL; 111 } 112} 113 114void CIP2Country::DownloadFinished(uint32 result) 115{ 116 if (result == HTTP_Success) { 117 Disable(); 118 // download succeeded. Switch over to new database. 119 wxString newDat = m_DataBasePath + wxT(".download"); 120 121 // Try to unpack the file, might be an archive 122 const wxChar* geoip_files[] = { 123 m_DataBaseName, 124 NULL 125 }; 126 127 if (UnpackArchive(CPath(newDat), geoip_files).second == EFT_Error) { 128 AddLogLineC(_("Download of GeoIP.dat file failed, aborting update.")); 129 return; 130 } 131 132 if (wxFileExists(m_DataBasePath)) { 133 if (!wxRemoveFile(m_DataBasePath)) { 134 AddLogLineC(CFormat(_("Failed to remove %s file, aborting update.")) % m_DataBaseName); 135 return; 136 } 137 } 138 139 if (!wxRenameFile(newDat, m_DataBasePath)) { 140 AddLogLineC(CFormat(_("Failed to rename %s file, aborting update.")) % m_DataBaseName); 141 return; 142 } 143 144 Enable(); 145 if (m_geoip) { 146 AddLogLineN(CFormat(_("Successfully updated %s")) % m_DataBaseName); 147 } else { 148 AddLogLineC(_("Error updating GeoIP.dat")); 149 } 150 } else if (result == HTTP_Skipped) { 151 AddLogLineN(CFormat(_("Skipped download of %s, because requested file is not newer.")) % m_DataBaseName); 152 } else { 153 AddLogLineC(CFormat(_("Failed to download %s from %s")) % m_DataBaseName % thePrefs::GetGeoIPUpdateUrl()); 154 // if it failed and there is no database, turn it off 155 if (!wxFileExists(m_DataBasePath)) { 156 thePrefs::SetGeoIPEnabled(false); 157 } 158 } 159} 160 161void CIP2Country::LoadFlags() 162{ 163 // Load data from xpm files 164 for (int i = 0; i < flags::FLAGS_XPM_SIZE; ++i) { 165 CountryData countrydata; 166 countrydata.Name = char2unicode(flags::flagXPMCodeVector[i].code); 167 countrydata.Flag = wxImage(flags::flagXPMCodeVector[i].xpm); 168 169 if (countrydata.Flag.IsOk()) { 170 m_CountryDataMap[countrydata.Name] = countrydata; 171 } else { 172 AddLogLineC(CFormat(_("Failed to load country data for '%s'.")) % countrydata.Name); 173 continue; 174 } 175 } 176 177 AddDebugLogLineN(logGeneral, CFormat(wxT("Loaded %d flag bitmaps.")) % m_CountryDataMap.size()); // there's never just one - no plural needed 178} 179 180 181CIP2Country::~CIP2Country() 182{ 183 Disable(); 184} 185 186 187const CountryData& CIP2Country::GetCountryData(const wxString &ip) 188{ 189 // Should prevent the crash if the GeoIP database does not exists 190 if (m_geoip == NULL) { 191 CountryDataMap::iterator it = m_CountryDataMap.find(wxString(wxT("unknown"))); 192 it->second.Name = wxT("?"); 193 return it->second; 194 } 195 196 const wxString CCode = wxString(char2unicode(GeoIP_country_code_by_addr(m_geoip, unicode2char(ip)))).MakeLower(); 197 198 CountryDataMap::iterator it = m_CountryDataMap.find(CCode); 199 if (it == m_CountryDataMap.end()) { 200 // Show the code and ?? flag 201 it = m_CountryDataMap.find(wxString(wxT("unknown"))); 202 wxASSERT(it != m_CountryDataMap.end()); 203 if (CCode.IsEmpty()) { 204 it->second.Name = wxT("?"); 205 } else{ 206 it->second.Name = CCode; 207 } 208 } 209 210 return it->second; 211} 212 213#else 214 215#include "IP2Country.h" 216 217CIP2Country::CIP2Country(const wxString&) 218{ 219 m_geoip = NULL; 220} 221 222CIP2Country::~CIP2Country() {} 223void CIP2Country::Enable() {} 224void CIP2Country::DownloadFinished(uint32) {} 225 226const CountryData& CIP2Country::GetCountryData(const wxString &) 227{ 228 static CountryData dummy; 229 return dummy; 230} 231 232#endif // ENABLE_IP2COUNTRY 233