ip2c.cpp
1 //------------------------------------------------------------------------------
2 // ip2c.cpp
3 //------------------------------------------------------------------------------
4 //
5 // This library is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU Lesser General Public
7 // License as published by the Free Software Foundation; either
8 // version 2.1 of the License, or (at your option) any later version.
9 //
10 // This library 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 GNU
13 // Lesser General Public License for more details.
14 //
15 // You should have received a copy of the GNU Lesser General Public
16 // License along with this library; 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 Braden "Blzut3" Obrzut <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 bool IP2C::hasData() const
118 {
119  return !database.empty();
120 }
121 
122 const IP2C::IP2CData& IP2C::lookupIP(unsigned int ipaddress)
123 {
124  QMutexLocker dataAccessMutexLocker(&dataAccessMutex);
125 
126  if(database.empty())
127  {
128  return invalidData;
129  }
130 
131  unsigned int upper = database.size()-1;
132  unsigned int lower = 0;
133  unsigned int index = database.size()/2;
134  unsigned int lastIndex = 0xFFFFFFFF;
135  while(index != lastIndex) // Infinite loop protection.
136  {
137  lastIndex = index;
138 
139  if(ipaddress < database[index].ipStart)
140  {
141  upper = index;
142  index -= (index-lower)>>1; // If we're concerning ourselves with speed >>1 is the same as /2, but should be faster.
143  continue;
144  }
145  else if(ipaddress > database[index].ipEnd)
146  {
147  lower = index;
148  index += (upper-index)>>1;
149  continue;
150  }
151  return database[index];
152  }
153 
154  return invalidData;
155 }
156 
158 {
159  if (isLocalhostAddress(ipaddress))
160  {
161  return IP2CCountryInfo(&flagLocalhost, tr("Localhost"));
162  }
163 
164  if (isLANAddress(ipaddress))
165  {
166  return IP2CCountryInfo(&flagLan, tr("LAN"));
167  }
168 
169  if (!hasData())
170  return IP2CCountryInfo();
171 
172  const IP2CData& data = lookupIP(ipaddress);
173 
174  if (!data.isCountryKnown())
175  {
176  return IP2CCountryInfo(&flagUnknown, tr("Unknown"));
177  }
178 
179  if (!data.isValid())
180  {
181  return IP2CCountryInfo();
182  }
183 
184  const QPixmap* pFlag = &flag(data.country);
185  return IP2CCountryInfo(pFlag, data.countryFullName);
186 }
187 
188 bool IP2C::IP2CData::isCountryKnown() const
189 {
190  return !country.isEmpty() && country != "ZZZ";
191 }
IP2CCountryInfo obtainCountryInfo(unsigned int ipaddress)
Definition: ip2c.cpp:157
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:122
IP to Country database handler.
Definition: ip2c.h:48
Flag and name of the country.
bool isValid() const
Definition: ip2c.h:72