ip2c.cpp
1 //------------------------------------------------------------------------------
2 // ip2c.cpp
3 //------------------------------------------------------------------------------
4 //
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License
7 // as published by the Free Software Foundation; either version 2
8 // of the License, or (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 // 02110-1301, USA.
19 //
20 //------------------------------------------------------------------------------
21 // Copyright (C) 2009 "Blzut3" <admin@maniacsvault.net>
22 //------------------------------------------------------------------------------
23 #include "ip2c.h"
24 
25 #include <QBuffer>
26 #include <QFile>
27 #include <QFileInfo>
28 #include <QHash>
29 #include <QResource>
30 #include <QTime>
31 #include <QTimeLine>
32 
33 #include "log.h"
34 
35 QMutex IP2C::instanceMutex;
36 IP2C *IP2C::staticInstance = NULL;
37 
38 IP2C *IP2C::instance()
39 {
40  if (staticInstance == NULL)
41  {
42  QMutexLocker locker(&instanceMutex);
43  if (staticInstance == NULL)
44  {
45  staticInstance = new IP2C();
46  }
47  }
48  return staticInstance;
49 }
50 
51 void IP2C::deinstantiate()
52 {
53  if (staticInstance != NULL)
54  {
55  delete staticInstance;
56  staticInstance = NULL;
57  }
58 }
59 
60 IP2C::IP2C()
61 : flagLan(":flags/lan-small"), flagLocalhost(":flags/localhost-small"),
62  flagUnknown(":flags/unknown-small")
63 {
64 }
65 
66 IP2C::~IP2C()
67 {
68 }
69 
71 {
72  QMutexLocker dataAccessMutexLocker(&dataAccessMutex);
73 
74  if (database.isEmpty() || entry.ipStart > database.back().ipStart)
75  {
76  database << entry;
77  }
78  else if (entry.ipStart < database.first().ipStart)
79  {
80  database.insert(0, entry);
81  }
82  else
83  {
84  QList<IP2CData>::iterator it;
85  for (it = database.begin(); it != database.end(); ++it)
86  {
87  if (entry.ipStart < it->ipStart)
88  {
89  database.insert(it, entry);
90  break;
91  }
92  }
93  }
94 }
95 
96 const QPixmap &IP2C::flag(const QString& countryShortName)
97 {
98  if (flags.contains(countryShortName))
99  {
100  return flags[countryShortName];
101  }
102 
103  QString resName = ":flags/" + countryShortName;
104  QResource res(resName);
105 
106  if (!res.isValid())
107  {
108  gLog << tr("No flag for country: %1").arg(countryShortName);
109  flags[countryShortName] = flagUnknown;
110  return flagUnknown;
111  }
112 
113  flags[countryShortName] = QPixmap(resName);
114  return flags[countryShortName];
115 }
116 
117 const IP2C::IP2CData& IP2C::lookupIP(unsigned int ipaddress)
118 {
119  QMutexLocker dataAccessMutexLocker(&dataAccessMutex);
120 
121  if(database.empty())
122  {
123  return invalidData;
124  }
125 
126  unsigned int upper = database.size()-1;
127  unsigned int lower = 0;
128  unsigned int index = database.size()/2;
129  unsigned int lastIndex = 0xFFFFFFFF;
130  while(index != lastIndex) // Infinite loop protection.
131  {
132  lastIndex = index;
133 
134  if(ipaddress < database[index].ipStart)
135  {
136  upper = index;
137  index -= (index-lower)>>1; // If we're concerning ourselves with speed >>1 is the same as /2, but should be faster.
138  continue;
139  }
140  else if(ipaddress > database[index].ipEnd)
141  {
142  lower = index;
143  index += (upper-index)>>1;
144  continue;
145  }
146  return database[index];
147  }
148 
149  return invalidData;
150 }
151 
153 {
154  if (isLocalhostAddress(ipaddress))
155  {
156  return IP2CCountryInfo(&flagLocalhost, tr("Localhost"));
157  }
158 
159  if (isLANAddress(ipaddress))
160  {
161  return IP2CCountryInfo(&flagLan, tr("LAN"));
162  }
163 
164  const IP2CData& data = lookupIP(ipaddress);
165 
166  if (!data.isCountryKnown())
167  {
168  return IP2CCountryInfo(&flagUnknown, tr("Unknown"));
169  }
170 
171  if (!data.isValid())
172  {
173  return IP2CCountryInfo();
174  }
175 
176  const QPixmap* pFlag = &flag(data.country);
177  return IP2CCountryInfo(pFlag, data.countryFullName);
178 }
179 
180 bool IP2C::IP2CData::isCountryKnown() const
181 {
182  return !country.isEmpty() && country != "ZZZ";
183 }
IP2CCountryInfo obtainCountryInfo(unsigned int ipaddress)
Definition: ip2c.cpp:152
void appendEntryToDatabase(const IP2CData &entry)
Adds new country entry to the database.
Definition: ip2c.cpp:70
const IP2CData & lookupIP(unsigned int ipaddress)
Definition: ip2c.cpp:117
IP to Country database handler.
Definition: ip2c.h:48
Flag and name of the country.
bool isValid() const
Definition: ip2c.h:72