Fine tune translations loading for Chinese locales
[qBittorrent.git] / src / base / net / geoipmanager.cpp
blob5bd235d0ca85fdca0a6ec1b265593f3b3e102485
1 /*
2 * Bittorrent Client using Qt and libtorrent.
3 * Copyright (C) 2015 Vladimir Golovnev <glassez@yandex.ru>
4 * Copyright (C) 2010 Christophe Dumez <chris@qbittorrent.org>
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 * In addition, as a special exception, the copyright holders give permission to
21 * link this program with the OpenSSL project's "OpenSSL" library (or with
22 * modified versions of it that use the same license as the "OpenSSL" library),
23 * and distribute the linked executables. You must obey the GNU General Public
24 * License in all respects for all of the code used other than "OpenSSL". If you
25 * modify file(s), you may extend this exception to your version of the file(s),
26 * but you are not obligated to do so. If you do not wish to do so, delete this
27 * exception statement from your version.
30 #include "geoipmanager.h"
32 #include <QDateTime>
33 #include <QHostAddress>
34 #include <QLocale>
36 #include "base/global.h"
37 #include "base/logger.h"
38 #include "base/preferences.h"
39 #include "base/profile.h"
40 #include "base/utils/fs.h"
41 #include "base/utils/gzip.h"
42 #include "base/utils/io.h"
43 #include "downloadmanager.h"
44 #include "geoipdatabase.h"
46 const QString DATABASE_URL = u"https://download.db-ip.com/free/dbip-country-lite-%1.mmdb.gz"_qs;
47 const QString GEODB_FOLDER = u"GeoDB"_qs;
48 const QString GEODB_FILENAME = u"dbip-country-lite.mmdb"_qs;
50 using namespace Net;
52 // GeoIPManager
54 GeoIPManager *GeoIPManager::m_instance = nullptr;
56 GeoIPManager::GeoIPManager()
58 configure();
59 connect(Preferences::instance(), &Preferences::changed, this, &GeoIPManager::configure);
62 GeoIPManager::~GeoIPManager()
64 delete m_geoIPDatabase;
67 void GeoIPManager::initInstance()
69 if (!m_instance)
70 m_instance = new GeoIPManager;
73 void GeoIPManager::freeInstance()
75 delete m_instance;
76 m_instance = nullptr;
79 GeoIPManager *GeoIPManager::instance()
81 return m_instance;
84 void GeoIPManager::loadDatabase()
86 delete m_geoIPDatabase;
87 m_geoIPDatabase = nullptr;
89 const Path filepath = specialFolderLocation(SpecialFolder::Data)
90 / Path(GEODB_FOLDER) / Path(GEODB_FILENAME);
92 QString error;
93 m_geoIPDatabase = GeoIPDatabase::load(filepath, error);
94 if (m_geoIPDatabase)
96 LogMsg(tr("IP geolocation database loaded. Type: %1. Build time: %2.")
97 .arg(m_geoIPDatabase->type(), m_geoIPDatabase->buildEpoch().toString()),
98 Log::INFO);
100 else
102 LogMsg(tr("Couldn't load IP geolocation database. Reason: %1").arg(error), Log::WARNING);
105 manageDatabaseUpdate();
108 void GeoIPManager::manageDatabaseUpdate()
110 const auto expired = [](const QDateTime &testDateTime)
112 const QDate testDate = testDateTime.date();
113 const QDate curDate = QDateTime::currentDateTimeUtc().date();
115 if ((testDate.year() < curDate.year()) && (curDate.day() > 1))
116 return true;
118 if ((testDate.month() < curDate.month()) && (curDate.day() > 1))
119 return true;
121 return false;
124 if (!m_geoIPDatabase || expired(m_geoIPDatabase->buildEpoch()))
125 downloadDatabaseFile();
128 void GeoIPManager::downloadDatabaseFile()
130 const QDateTime curDatetime = QDateTime::currentDateTimeUtc();
131 const QString curUrl = DATABASE_URL.arg(QLocale::c().toString(curDatetime, u"yyyy-MM"));
132 DownloadManager::instance()->download({curUrl}, this, &GeoIPManager::downloadFinished);
135 QString GeoIPManager::lookup(const QHostAddress &hostAddr) const
137 if (m_enabled && m_geoIPDatabase)
138 return m_geoIPDatabase->lookup(hostAddr);
140 return {};
143 QString GeoIPManager::CountryName(const QString &countryISOCode)
145 static const QHash<QString, QString> countries =
147 // ISO 3166-1 alpha-2 codes
148 // http://www.iso.org/iso/home/standards/country_codes/country_names_and_code_elements_txt-temp.htm
150 // Officially assigned
151 {u"AD"_qs, tr("Andorra")},
152 {u"AE"_qs, tr("United Arab Emirates")},
153 {u"AF"_qs, tr("Afghanistan")},
154 {u"AG"_qs, tr("Antigua and Barbuda")},
155 {u"AI"_qs, tr("Anguilla")},
156 {u"AL"_qs, tr("Albania")},
157 {u"AM"_qs, tr("Armenia")},
158 {u"AO"_qs, tr("Angola")},
159 {u"AQ"_qs, tr("Antarctica")},
160 {u"AR"_qs, tr("Argentina")},
161 {u"AS"_qs, tr("American Samoa")},
162 {u"AT"_qs, tr("Austria")},
163 {u"AU"_qs, tr("Australia")},
164 {u"AW"_qs, tr("Aruba")},
165 {u"AX"_qs, tr("Aland Islands")},
166 {u"AZ"_qs, tr("Azerbaijan")},
167 {u"BA"_qs, tr("Bosnia and Herzegovina")},
168 {u"BB"_qs, tr("Barbados")},
169 {u"BD"_qs, tr("Bangladesh")},
170 {u"BE"_qs, tr("Belgium")},
171 {u"BF"_qs, tr("Burkina Faso")},
172 {u"BG"_qs, tr("Bulgaria")},
173 {u"BH"_qs, tr("Bahrain")},
174 {u"BI"_qs, tr("Burundi")},
175 {u"BJ"_qs, tr("Benin")},
176 {u"BL"_qs, tr("Saint Barthelemy")},
177 {u"BM"_qs, tr("Bermuda")},
178 {u"BN"_qs, tr("Brunei Darussalam")},
179 {u"BO"_qs, tr("Bolivia, Plurinational State of")},
180 {u"BQ"_qs, tr("Bonaire, Sint Eustatius and Saba")},
181 {u"BR"_qs, tr("Brazil")},
182 {u"BS"_qs, tr("Bahamas")},
183 {u"BT"_qs, tr("Bhutan")},
184 {u"BV"_qs, tr("Bouvet Island")},
185 {u"BW"_qs, tr("Botswana")},
186 {u"BY"_qs, tr("Belarus")},
187 {u"BZ"_qs, tr("Belize")},
188 {u"CA"_qs, tr("Canada")},
189 {u"CC"_qs, tr("Cocos (Keeling) Islands")},
190 {u"CD"_qs, tr("Congo, The Democratic Republic of the")},
191 {u"CF"_qs, tr("Central African Republic")},
192 {u"CG"_qs, tr("Congo")},
193 {u"CH"_qs, tr("Switzerland")},
194 {u"CI"_qs, tr("Cote d'Ivoire")},
195 {u"CK"_qs, tr("Cook Islands")},
196 {u"CL"_qs, tr("Chile")},
197 {u"CM"_qs, tr("Cameroon")},
198 {u"CN"_qs, tr("China")},
199 {u"CO"_qs, tr("Colombia")},
200 {u"CR"_qs, tr("Costa Rica")},
201 {u"CU"_qs, tr("Cuba")},
202 {u"CV"_qs, tr("Cape Verde")},
203 {u"CW"_qs, tr("Curacao")},
204 {u"CX"_qs, tr("Christmas Island")},
205 {u"CY"_qs, tr("Cyprus")},
206 {u"CZ"_qs, tr("Czech Republic")},
207 {u"DE"_qs, tr("Germany")},
208 {u"DJ"_qs, tr("Djibouti")},
209 {u"DK"_qs, tr("Denmark")},
210 {u"DM"_qs, tr("Dominica")},
211 {u"DO"_qs, tr("Dominican Republic")},
212 {u"DZ"_qs, tr("Algeria")},
213 {u"EC"_qs, tr("Ecuador")},
214 {u"EE"_qs, tr("Estonia")},
215 {u"EG"_qs, tr("Egypt")},
216 {u"EH"_qs, tr("Western Sahara")},
217 {u"ER"_qs, tr("Eritrea")},
218 {u"ES"_qs, tr("Spain")},
219 {u"ET"_qs, tr("Ethiopia")},
220 {u"FI"_qs, tr("Finland")},
221 {u"FJ"_qs, tr("Fiji")},
222 {u"FK"_qs, tr("Falkland Islands (Malvinas)")},
223 {u"FM"_qs, tr("Micronesia, Federated States of")},
224 {u"FO"_qs, tr("Faroe Islands")},
225 {u"FR"_qs, tr("France")},
226 {u"GA"_qs, tr("Gabon")},
227 {u"GB"_qs, tr("United Kingdom")},
228 {u"GD"_qs, tr("Grenada")},
229 {u"GE"_qs, tr("Georgia")},
230 {u"GF"_qs, tr("French Guiana")},
231 {u"GG"_qs, tr("Guernsey")},
232 {u"GH"_qs, tr("Ghana")},
233 {u"GI"_qs, tr("Gibraltar")},
234 {u"GL"_qs, tr("Greenland")},
235 {u"GM"_qs, tr("Gambia")},
236 {u"GN"_qs, tr("Guinea")},
237 {u"GP"_qs, tr("Guadeloupe")},
238 {u"GQ"_qs, tr("Equatorial Guinea")},
239 {u"GR"_qs, tr("Greece")},
240 {u"GS"_qs, tr("South Georgia and the South Sandwich Islands")},
241 {u"GT"_qs, tr("Guatemala")},
242 {u"GU"_qs, tr("Guam")},
243 {u"GW"_qs, tr("Guinea-Bissau")},
244 {u"GY"_qs, tr("Guyana")},
245 {u"HK"_qs, tr("Hong Kong")},
246 {u"HM"_qs, tr("Heard Island and McDonald Islands")},
247 {u"HN"_qs, tr("Honduras")},
248 {u"HR"_qs, tr("Croatia")},
249 {u"HT"_qs, tr("Haiti")},
250 {u"HU"_qs, tr("Hungary")},
251 {u"ID"_qs, tr("Indonesia")},
252 {u"IE"_qs, tr("Ireland")},
253 {u"IL"_qs, tr("Israel")},
254 {u"IM"_qs, tr("Isle of Man")},
255 {u"IN"_qs, tr("India")},
256 {u"IO"_qs, tr("British Indian Ocean Territory")},
257 {u"IQ"_qs, tr("Iraq")},
258 {u"IR"_qs, tr("Iran, Islamic Republic of")},
259 {u"IS"_qs, tr("Iceland")},
260 {u"IT"_qs, tr("Italy")},
261 {u"JE"_qs, tr("Jersey")},
262 {u"JM"_qs, tr("Jamaica")},
263 {u"JO"_qs, tr("Jordan")},
264 {u"JP"_qs, tr("Japan")},
265 {u"KE"_qs, tr("Kenya")},
266 {u"KG"_qs, tr("Kyrgyzstan")},
267 {u"KH"_qs, tr("Cambodia")},
268 {u"KI"_qs, tr("Kiribati")},
269 {u"KM"_qs, tr("Comoros")},
270 {u"KN"_qs, tr("Saint Kitts and Nevis")},
271 {u"KP"_qs, tr("Korea, Democratic People's Republic of")},
272 {u"KR"_qs, tr("Korea, Republic of")},
273 {u"KW"_qs, tr("Kuwait")},
274 {u"KY"_qs, tr("Cayman Islands")},
275 {u"KZ"_qs, tr("Kazakhstan")},
276 {u"LA"_qs, tr("Lao People's Democratic Republic")},
277 {u"LB"_qs, tr("Lebanon")},
278 {u"LC"_qs, tr("Saint Lucia")},
279 {u"LI"_qs, tr("Liechtenstein")},
280 {u"LK"_qs, tr("Sri Lanka")},
281 {u"LR"_qs, tr("Liberia")},
282 {u"LS"_qs, tr("Lesotho")},
283 {u"LT"_qs, tr("Lithuania")},
284 {u"LU"_qs, tr("Luxembourg")},
285 {u"LV"_qs, tr("Latvia")},
286 {u"LY"_qs, tr("Libya")},
287 {u"MA"_qs, tr("Morocco")},
288 {u"MC"_qs, tr("Monaco")},
289 {u"MD"_qs, tr("Moldova, Republic of")},
290 {u"ME"_qs, tr("Montenegro")},
291 {u"MF"_qs, tr("Saint Martin (French part)")},
292 {u"MG"_qs, tr("Madagascar")},
293 {u"MH"_qs, tr("Marshall Islands")},
294 {u"MK"_qs, tr("Macedonia, The Former Yugoslav Republic of")},
295 {u"ML"_qs, tr("Mali")},
296 {u"MM"_qs, tr("Myanmar")},
297 {u"MN"_qs, tr("Mongolia")},
298 {u"MO"_qs, tr("Macao")},
299 {u"MP"_qs, tr("Northern Mariana Islands")},
300 {u"MQ"_qs, tr("Martinique")},
301 {u"MR"_qs, tr("Mauritania")},
302 {u"MS"_qs, tr("Montserrat")},
303 {u"MT"_qs, tr("Malta")},
304 {u"MU"_qs, tr("Mauritius")},
305 {u"MV"_qs, tr("Maldives")},
306 {u"MW"_qs, tr("Malawi")},
307 {u"MX"_qs, tr("Mexico")},
308 {u"MY"_qs, tr("Malaysia")},
309 {u"MZ"_qs, tr("Mozambique")},
310 {u"NA"_qs, tr("Namibia")},
311 {u"NC"_qs, tr("New Caledonia")},
312 {u"NE"_qs, tr("Niger")},
313 {u"NF"_qs, tr("Norfolk Island")},
314 {u"NG"_qs, tr("Nigeria")},
315 {u"NI"_qs, tr("Nicaragua")},
316 {u"NL"_qs, tr("Netherlands")},
317 {u"NO"_qs, tr("Norway")},
318 {u"NP"_qs, tr("Nepal")},
319 {u"NR"_qs, tr("Nauru")},
320 {u"NU"_qs, tr("Niue")},
321 {u"NZ"_qs, tr("New Zealand")},
322 {u"OM"_qs, tr("Oman")},
323 {u"PA"_qs, tr("Panama")},
324 {u"PE"_qs, tr("Peru")},
325 {u"PF"_qs, tr("French Polynesia")},
326 {u"PG"_qs, tr("Papua New Guinea")},
327 {u"PH"_qs, tr("Philippines")},
328 {u"PK"_qs, tr("Pakistan")},
329 {u"PL"_qs, tr("Poland")},
330 {u"PM"_qs, tr("Saint Pierre and Miquelon")},
331 {u"PN"_qs, tr("Pitcairn")},
332 {u"PR"_qs, tr("Puerto Rico")},
333 {u"PS"_qs, tr("Palestine, State of")},
334 {u"PT"_qs, tr("Portugal")},
335 {u"PW"_qs, tr("Palau")},
336 {u"PY"_qs, tr("Paraguay")},
337 {u"QA"_qs, tr("Qatar")},
338 {u"RE"_qs, tr("Reunion")},
339 {u"RO"_qs, tr("Romania")},
340 {u"RS"_qs, tr("Serbia")},
341 {u"RU"_qs, tr("Russian Federation")},
342 {u"RW"_qs, tr("Rwanda")},
343 {u"SA"_qs, tr("Saudi Arabia")},
344 {u"SB"_qs, tr("Solomon Islands")},
345 {u"SC"_qs, tr("Seychelles")},
346 {u"SD"_qs, tr("Sudan")},
347 {u"SE"_qs, tr("Sweden")},
348 {u"SG"_qs, tr("Singapore")},
349 {u"SH"_qs, tr("Saint Helena, Ascension and Tristan da Cunha")},
350 {u"SI"_qs, tr("Slovenia")},
351 {u"SJ"_qs, tr("Svalbard and Jan Mayen")},
352 {u"SK"_qs, tr("Slovakia")},
353 {u"SL"_qs, tr("Sierra Leone")},
354 {u"SM"_qs, tr("San Marino")},
355 {u"SN"_qs, tr("Senegal")},
356 {u"SO"_qs, tr("Somalia")},
357 {u"SR"_qs, tr("Suriname")},
358 {u"SS"_qs, tr("South Sudan")},
359 {u"ST"_qs, tr("Sao Tome and Principe")},
360 {u"SV"_qs, tr("El Salvador")},
361 {u"SX"_qs, tr("Sint Maarten (Dutch part)")},
362 {u"SY"_qs, tr("Syrian Arab Republic")},
363 {u"SZ"_qs, tr("Swaziland")},
364 {u"TC"_qs, tr("Turks and Caicos Islands")},
365 {u"TD"_qs, tr("Chad")},
366 {u"TF"_qs, tr("French Southern Territories")},
367 {u"TG"_qs, tr("Togo")},
368 {u"TH"_qs, tr("Thailand")},
369 {u"TJ"_qs, tr("Tajikistan")},
370 {u"TK"_qs, tr("Tokelau")},
371 {u"TL"_qs, tr("Timor-Leste")},
372 {u"TM"_qs, tr("Turkmenistan")},
373 {u"TN"_qs, tr("Tunisia")},
374 {u"TO"_qs, tr("Tonga")},
375 {u"TR"_qs, tr("Turkey")},
376 {u"TT"_qs, tr("Trinidad and Tobago")},
377 {u"TV"_qs, tr("Tuvalu")},
378 {u"TW"_qs, tr("Taiwan")},
379 {u"TZ"_qs, tr("Tanzania, United Republic of")},
380 {u"UA"_qs, tr("Ukraine")},
381 {u"UG"_qs, tr("Uganda")},
382 {u"UM"_qs, tr("United States Minor Outlying Islands")},
383 {u"US"_qs, tr("United States")},
384 {u"UY"_qs, tr("Uruguay")},
385 {u"UZ"_qs, tr("Uzbekistan")},
386 {u"VA"_qs, tr("Holy See (Vatican City State)")},
387 {u"VC"_qs, tr("Saint Vincent and the Grenadines")},
388 {u"VE"_qs, tr("Venezuela, Bolivarian Republic of")},
389 {u"VG"_qs, tr("Virgin Islands, British")},
390 {u"VI"_qs, tr("Virgin Islands, U.S.")},
391 {u"VN"_qs, tr("Vietnam")},
392 {u"VU"_qs, tr("Vanuatu")},
393 {u"WF"_qs, tr("Wallis and Futuna")},
394 {u"WS"_qs, tr("Samoa")},
395 {u"YE"_qs, tr("Yemen")},
396 {u"YT"_qs, tr("Mayotte")},
397 {u"ZA"_qs, tr("South Africa")},
398 {u"ZM"_qs, tr("Zambia")},
399 {u"ZW"_qs, tr("Zimbabwe")},
401 {{}, tr("N/A")}
404 return countries.value(countryISOCode, tr("N/A"));
407 void GeoIPManager::configure()
409 const bool enabled = Preferences::instance()->resolvePeerCountries();
410 if (m_enabled != enabled)
412 m_enabled = enabled;
413 if (m_enabled && !m_geoIPDatabase)
415 loadDatabase();
417 else if (!m_enabled)
419 delete m_geoIPDatabase;
420 m_geoIPDatabase = nullptr;
425 void GeoIPManager::downloadFinished(const DownloadResult &result)
427 if (result.status != DownloadStatus::Success)
429 LogMsg(tr("Couldn't download IP geolocation database file. Reason: %1").arg(result.errorString), Log::WARNING);
430 return;
433 bool ok = false;
434 const QByteArray data = Utils::Gzip::decompress(result.data, &ok);
435 if (!ok)
437 LogMsg(tr("Could not decompress IP geolocation database file."), Log::WARNING);
438 return;
441 QString error;
442 GeoIPDatabase *geoIPDatabase = GeoIPDatabase::load(data, error);
443 if (geoIPDatabase)
445 if (!m_geoIPDatabase || (geoIPDatabase->buildEpoch() > m_geoIPDatabase->buildEpoch()))
447 delete m_geoIPDatabase;
448 m_geoIPDatabase = geoIPDatabase;
449 LogMsg(tr("IP geolocation database loaded. Type: %1. Build time: %2.")
450 .arg(m_geoIPDatabase->type(), m_geoIPDatabase->buildEpoch().toString())
451 , Log::INFO);
452 const Path targetPath = specialFolderLocation(SpecialFolder::Data) / Path(GEODB_FOLDER);
453 if (!targetPath.exists())
454 Utils::Fs::mkpath(targetPath);
456 const auto path = targetPath / Path(GEODB_FILENAME);
457 const nonstd::expected<void, QString> result = Utils::IO::saveToFile(path, data);
458 if (result)
460 LogMsg(tr("Successfully updated IP geolocation database."), Log::INFO);
462 else
464 LogMsg(tr("Couldn't save downloaded IP geolocation database file. Reason: %1")
465 .arg(result.error()), Log::WARNING);
468 else
470 delete geoIPDatabase;
473 else
475 LogMsg(tr("Couldn't load IP geolocation database. Reason: %1").arg(error), Log::WARNING);