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 = nullptr;
37 
38 IP2C *IP2C::instance()
39 {
40  if (staticInstance == nullptr)
41  {
42  QMutexLocker locker(&instanceMutex);
43  if (staticInstance == nullptr)
44  staticInstance = new IP2C();
45  }
46  return staticInstance;
47 }
48 
49 void IP2C::deinstantiate()
50 {
51  if (staticInstance != nullptr)
52  {
53  delete staticInstance;
54  staticInstance = nullptr;
55  }
56 }
57 
58 IP2C::IP2C()
59  : flagLan(":flags/lan-small"), flagLocalhost(":flags/localhost-small"),
60  flagUnknown(":flags/unknown-small")
61 {
62 }
63 
64 IP2C::~IP2C()
65 {
66 }
67 
69 {
70  QMutexLocker dataAccessMutexLocker(&dataAccessMutex);
71 
72  if (database.isEmpty() || entry.ipStart > database.back().ipStart)
73  database << entry;
74  else if (entry.ipStart < database.first().ipStart)
75  database.insert(0, entry);
76  else
77  {
78  QList<IP2CData>::iterator it;
79  for (it = database.begin(); it != database.end(); ++it)
80  {
81  if (entry.ipStart < it->ipStart)
82  {
83  database.insert(it, entry);
84  break;
85  }
86  }
87  }
88 }
89 
90 const QPixmap &IP2C::flag(const QString &countryShortName)
91 {
92  if (flags.contains(countryShortName))
93  return flags[countryShortName];
94 
95  QString resName = ":flags/" + countryShortName;
96  QResource res(resName);
97 
98  if (!res.isValid())
99  {
100  gLog << tr("No flag for country: %1").arg(countryShortName);
101  flags[countryShortName] = flagUnknown;
102  return flagUnknown;
103  }
104 
105  flags[countryShortName] = QPixmap(resName);
106  return flags[countryShortName];
107 }
108 
109 bool IP2C::hasData() const
110 {
111  return !database.empty();
112 }
113 
114 const IP2C::IP2CData &IP2C::lookupIP(unsigned int ipaddress)
115 {
116  QMutexLocker dataAccessMutexLocker(&dataAccessMutex);
117 
118  if (database.empty())
119  return invalidData;
120 
121  unsigned int upper = database.size() - 1;
122  unsigned int lower = 0;
123  unsigned int index = database.size() / 2;
124  unsigned int lastIndex = 0xFFFFFFFF;
125  while (index != lastIndex) // Infinite loop protection.
126  {
127  lastIndex = index;
128 
129  if (ipaddress < database[index].ipStart)
130  {
131  upper = index;
132  index -= (index - lower) >> 1; // If we're concerning ourselves with speed >>1 is the same as /2, but should be faster.
133  continue;
134  }
135  else if (ipaddress > database[index].ipEnd)
136  {
137  lower = index;
138  index += (upper - index) >> 1;
139  continue;
140  }
141  return database[index];
142  }
143 
144  return invalidData;
145 }
146 
148 {
149  if (isLocalhostAddress(ipaddress))
150  return IP2CCountryInfo(&flagLocalhost, tr("Localhost"));
151 
152  if (isLANAddress(ipaddress))
153  return IP2CCountryInfo(&flagLan, tr("LAN"));
154 
155  if (!hasData())
156  return IP2CCountryInfo();
157 
158  const IP2CData &data = lookupIP(ipaddress);
159 
160  if (!data.isCountryKnown())
161  return IP2CCountryInfo(&flagUnknown, tr("Unknown"));
162 
163  if (!data.isValid())
164  return IP2CCountryInfo();
165 
166  const QPixmap *pFlag = &flag(data.country);
167  return IP2CCountryInfo(pFlag, data.countryFullName);
168 }
169 
170 bool IP2C::IP2CData::isCountryKnown() const
171 {
172  return !country.isEmpty() && country != "ZZZ";
173 }
IP2CCountryInfo obtainCountryInfo(unsigned int ipaddress)
Definition: ip2c.cpp:147
void appendEntryToDatabase(const IP2CData &entry)
Adds new country entry to the database.
Definition: ip2c.cpp:68
const IP2CData & lookupIP(unsigned int ipaddress)
Definition: ip2c.cpp:114
IP to Country database handler.
Definition: ip2c.h:48
Flag and name of the country.
bool isValid() const
Definition: ip2c.h:72