/* * Bittorrent Client using Qt and libtorrent. * Copyright (C) 2015 Vladimir Golovnev * Copyright (C) 2010 Christophe Dumez * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * In addition, as a special exception, the copyright holders give permission to * link this program with the OpenSSL project's "OpenSSL" library (or with * modified versions of it that use the same license as the "OpenSSL" library), * and distribute the linked executables. You must obey the GNU General Public * License in all respects for all of the code used other than "OpenSSL". If you * modify file(s), you may extend this exception to your version of the file(s), * but you are not obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ #include "geoipmanager.h" #include #include #include #include #include "base/logger.h" #include "base/preferences.h" #include "base/profile.h" #include "base/utils/fs.h" #include "base/utils/gzip.h" #include "downloadmanager.h" #include "private/geoipdatabase.h" static const char DATABASE_URL[] = "https://geolite.maxmind.com/download/geoip/database/GeoLite2-Country.mmdb.gz"; static const char GEOIP_FOLDER[] = "GeoIP"; static const char GEOIP_FILENAME[] = "GeoLite2-Country.mmdb"; static const int UPDATE_INTERVAL = 30; // Days between database updates using namespace Net; // GeoIPManager GeoIPManager *GeoIPManager::m_instance = nullptr; GeoIPManager::GeoIPManager() : m_enabled(false) , m_geoIPDatabase(nullptr) { configure(); connect(Preferences::instance(), &Preferences::changed, this, &GeoIPManager::configure); } GeoIPManager::~GeoIPManager() { if (m_geoIPDatabase) delete m_geoIPDatabase; } void GeoIPManager::initInstance() { if (!m_instance) m_instance = new GeoIPManager; } void GeoIPManager::freeInstance() { if (m_instance) { delete m_instance; m_instance = nullptr; } } GeoIPManager *GeoIPManager::instance() { return m_instance; } void GeoIPManager::loadDatabase() { if (m_geoIPDatabase) { delete m_geoIPDatabase; m_geoIPDatabase = nullptr; } const QString filepath = Utils::Fs::expandPathAbs( QString("%1%2/%3").arg(specialFolderLocation(SpecialFolder::Data), GEOIP_FOLDER, GEOIP_FILENAME)); QString error; m_geoIPDatabase = GeoIPDatabase::load(filepath, error); if (m_geoIPDatabase) Logger::instance()->addMessage(tr("GeoIP database loaded. Type: %1. Build time: %2.") .arg(m_geoIPDatabase->type(), m_geoIPDatabase->buildEpoch().toString()), Log::INFO); else Logger::instance()->addMessage(tr("Couldn't load GeoIP database. Reason: %1").arg(error), Log::WARNING); manageDatabaseUpdate(); } void GeoIPManager::manageDatabaseUpdate() { if (!m_geoIPDatabase || (m_geoIPDatabase->buildEpoch().daysTo(QDateTime::currentDateTimeUtc()) >= UPDATE_INTERVAL)) downloadDatabaseFile(); } void GeoIPManager::downloadDatabaseFile() { DownloadManager::instance()->download({DATABASE_URL}, this, &GeoIPManager::downloadFinished); } QString GeoIPManager::lookup(const QHostAddress &hostAddr) const { if (m_enabled && m_geoIPDatabase) return m_geoIPDatabase->lookup(hostAddr); return {}; } QString GeoIPManager::CountryName(const QString &countryISOCode) { static const QHash countries = { // ISO 3166-1 alpha-2 codes // http://www.iso.org/iso/home/standards/country_codes/country_names_and_code_elements_txt-temp.htm // Officially assigned {"AD", tr("Andorra")}, {"AE", tr("United Arab Emirates")}, {"AF", tr("Afghanistan")}, {"AG", tr("Antigua and Barbuda")}, {"AI", tr("Anguilla")}, {"AL", tr("Albania")}, {"AM", tr("Armenia")}, {"AO", tr("Angola")}, {"AQ", tr("Antarctica")}, {"AR", tr("Argentina")}, {"AS", tr("American Samoa")}, {"AT", tr("Austria")}, {"AU", tr("Australia")}, {"AW", tr("Aruba")}, {"AX", tr("Aland Islands")}, {"AZ", tr("Azerbaijan")}, {"BA", tr("Bosnia and Herzegovina")}, {"BB", tr("Barbados")}, {"BD", tr("Bangladesh")}, {"BE", tr("Belgium")}, {"BF", tr("Burkina Faso")}, {"BG", tr("Bulgaria")}, {"BH", tr("Bahrain")}, {"BI", tr("Burundi")}, {"BJ", tr("Benin")}, {"BL", tr("Saint Barthelemy")}, {"BM", tr("Bermuda")}, {"BN", tr("Brunei Darussalam")}, {"BO", tr("Bolivia, Plurinational State of")}, {"BQ", tr("Bonaire, Sint Eustatius and Saba")}, {"BR", tr("Brazil")}, {"BS", tr("Bahamas")}, {"BT", tr("Bhutan")}, {"BV", tr("Bouvet Island")}, {"BW", tr("Botswana")}, {"BY", tr("Belarus")}, {"BZ", tr("Belize")}, {"CA", tr("Canada")}, {"CC", tr("Cocos (Keeling) Islands")}, {"CD", tr("Congo, The Democratic Republic of the")}, {"CF", tr("Central African Republic")}, {"CG", tr("Congo")}, {"CH", tr("Switzerland")}, {"CI", tr("Cote d'Ivoire")}, {"CK", tr("Cook Islands")}, {"CL", tr("Chile")}, {"CM", tr("Cameroon")}, {"CN", tr("China")}, {"CO", tr("Colombia")}, {"CR", tr("Costa Rica")}, {"CU", tr("Cuba")}, {"CV", tr("Cape Verde")}, {"CW", tr("Curacao")}, {"CX", tr("Christmas Island")}, {"CY", tr("Cyprus")}, {"CZ", tr("Czech Republic")}, {"DE", tr("Germany")}, {"DJ", tr("Djibouti")}, {"DK", tr("Denmark")}, {"DM", tr("Dominica")}, {"DO", tr("Dominican Republic")}, {"DZ", tr("Algeria")}, {"EC", tr("Ecuador")}, {"EE", tr("Estonia")}, {"EG", tr("Egypt")}, {"EH", tr("Western Sahara")}, {"ER", tr("Eritrea")}, {"ES", tr("Spain")}, {"ET", tr("Ethiopia")}, {"FI", tr("Finland")}, {"FJ", tr("Fiji")}, {"FK", tr("Falkland Islands (Malvinas)")}, {"FM", tr("Micronesia, Federated States of")}, {"FO", tr("Faroe Islands")}, {"FR", tr("France")}, {"GA", tr("Gabon")}, {"GB", tr("United Kingdom")}, {"GD", tr("Grenada")}, {"GE", tr("Georgia")}, {"GF", tr("French Guiana")}, {"GG", tr("Guernsey")}, {"GH", tr("Ghana")}, {"GI", tr("Gibraltar")}, {"GL", tr("Greenland")}, {"GM", tr("Gambia")}, {"GN", tr("Guinea")}, {"GP", tr("Guadeloupe")}, {"GQ", tr("Equatorial Guinea")}, {"GR", tr("Greece")}, {"GS", tr("South Georgia and the South Sandwich Islands")}, {"GT", tr("Guatemala")}, {"GU", tr("Guam")}, {"GW", tr("Guinea-Bissau")}, {"GY", tr("Guyana")}, {"HK", tr("Hong Kong")}, {"HM", tr("Heard Island and McDonald Islands")}, {"HN", tr("Honduras")}, {"HR", tr("Croatia")}, {"HT", tr("Haiti")}, {"HU", tr("Hungary")}, {"ID", tr("Indonesia")}, {"IE", tr("Ireland")}, {"IL", tr("Israel")}, {"IM", tr("Isle of Man")}, {"IN", tr("India")}, {"IO", tr("British Indian Ocean Territory")}, {"IQ", tr("Iraq")}, {"IR", tr("Iran, Islamic Republic of")}, {"IS", tr("Iceland")}, {"IT", tr("Italy")}, {"JE", tr("Jersey")}, {"JM", tr("Jamaica")}, {"JO", tr("Jordan")}, {"JP", tr("Japan")}, {"KE", tr("Kenya")}, {"KG", tr("Kyrgyzstan")}, {"KH", tr("Cambodia")}, {"KI", tr("Kiribati")}, {"KM", tr("Comoros")}, {"KN", tr("Saint Kitts and Nevis")}, {"KP", tr("Korea, Democratic People's Republic of")}, {"KR", tr("Korea, Republic of")}, {"KW", tr("Kuwait")}, {"KY", tr("Cayman Islands")}, {"KZ", tr("Kazakhstan")}, {"LA", tr("Lao People's Democratic Republic")}, {"LB", tr("Lebanon")}, {"LC", tr("Saint Lucia")}, {"LI", tr("Liechtenstein")}, {"LK", tr("Sri Lanka")}, {"LR", tr("Liberia")}, {"LS", tr("Lesotho")}, {"LT", tr("Lithuania")}, {"LU", tr("Luxembourg")}, {"LV", tr("Latvia")}, {"LY", tr("Libya")}, {"MA", tr("Morocco")}, {"MC", tr("Monaco")}, {"MD", tr("Moldova, Republic of")}, {"ME", tr("Montenegro")}, {"MF", tr("Saint Martin (French part)")}, {"MG", tr("Madagascar")}, {"MH", tr("Marshall Islands")}, {"MK", tr("Macedonia, The Former Yugoslav Republic of")}, {"ML", tr("Mali")}, {"MM", tr("Myanmar")}, {"MN", tr("Mongolia")}, {"MO", tr("Macao")}, {"MP", tr("Northern Mariana Islands")}, {"MQ", tr("Martinique")}, {"MR", tr("Mauritania")}, {"MS", tr("Montserrat")}, {"MT", tr("Malta")}, {"MU", tr("Mauritius")}, {"MV", tr("Maldives")}, {"MW", tr("Malawi")}, {"MX", tr("Mexico")}, {"MY", tr("Malaysia")}, {"MZ", tr("Mozambique")}, {"NA", tr("Namibia")}, {"NC", tr("New Caledonia")}, {"NE", tr("Niger")}, {"NF", tr("Norfolk Island")}, {"NG", tr("Nigeria")}, {"NI", tr("Nicaragua")}, {"NL", tr("Netherlands")}, {"NO", tr("Norway")}, {"NP", tr("Nepal")}, {"NR", tr("Nauru")}, {"NU", tr("Niue")}, {"NZ", tr("New Zealand")}, {"OM", tr("Oman")}, {"PA", tr("Panama")}, {"PE", tr("Peru")}, {"PF", tr("French Polynesia")}, {"PG", tr("Papua New Guinea")}, {"PH", tr("Philippines")}, {"PK", tr("Pakistan")}, {"PL", tr("Poland")}, {"PM", tr("Saint Pierre and Miquelon")}, {"PN", tr("Pitcairn")}, {"PR", tr("Puerto Rico")}, {"PS", tr("Palestine, State of")}, {"PT", tr("Portugal")}, {"PW", tr("Palau")}, {"PY", tr("Paraguay")}, {"QA", tr("Qatar")}, {"RE", tr("Reunion")}, {"RO", tr("Romania")}, {"RS", tr("Serbia")}, {"RU", tr("Russian Federation")}, {"RW", tr("Rwanda")}, {"SA", tr("Saudi Arabia")}, {"SB", tr("Solomon Islands")}, {"SC", tr("Seychelles")}, {"SD", tr("Sudan")}, {"SE", tr("Sweden")}, {"SG", tr("Singapore")}, {"SH", tr("Saint Helena, Ascension and Tristan da Cunha")}, {"SI", tr("Slovenia")}, {"SJ", tr("Svalbard and Jan Mayen")}, {"SK", tr("Slovakia")}, {"SL", tr("Sierra Leone")}, {"SM", tr("San Marino")}, {"SN", tr("Senegal")}, {"SO", tr("Somalia")}, {"SR", tr("Suriname")}, {"SS", tr("South Sudan")}, {"ST", tr("Sao Tome and Principe")}, {"SV", tr("El Salvador")}, {"SX", tr("Sint Maarten (Dutch part)")}, {"SY", tr("Syrian Arab Republic")}, {"SZ", tr("Swaziland")}, {"TC", tr("Turks and Caicos Islands")}, {"TD", tr("Chad")}, {"TF", tr("French Southern Territories")}, {"TG", tr("Togo")}, {"TH", tr("Thailand")}, {"TJ", tr("Tajikistan")}, {"TK", tr("Tokelau")}, {"TL", tr("Timor-Leste")}, {"TM", tr("Turkmenistan")}, {"TN", tr("Tunisia")}, {"TO", tr("Tonga")}, {"TR", tr("Turkey")}, {"TT", tr("Trinidad and Tobago")}, {"TV", tr("Tuvalu")}, {"TW", tr("Taiwan")}, {"TZ", tr("Tanzania, United Republic of")}, {"UA", tr("Ukraine")}, {"UG", tr("Uganda")}, {"UM", tr("United States Minor Outlying Islands")}, {"US", tr("United States")}, {"UY", tr("Uruguay")}, {"UZ", tr("Uzbekistan")}, {"VA", tr("Holy See (Vatican City State)")}, {"VC", tr("Saint Vincent and the Grenadines")}, {"VE", tr("Venezuela, Bolivarian Republic of")}, {"VG", tr("Virgin Islands, British")}, {"VI", tr("Virgin Islands, U.S.")}, {"VN", tr("Viet Nam")}, {"VU", tr("Vanuatu")}, {"WF", tr("Wallis and Futuna")}, {"WS", tr("Samoa")}, {"YE", tr("Yemen")}, {"YT", tr("Mayotte")}, {"ZA", tr("South Africa")}, {"ZM", tr("Zambia")}, {"ZW", tr("Zimbabwe")}, {{}, tr("N/A")} }; return countries.value(countryISOCode, tr("N/A")); } void GeoIPManager::configure() { const bool enabled = Preferences::instance()->resolvePeerCountries(); if (m_enabled != enabled) { m_enabled = enabled; if (m_enabled && !m_geoIPDatabase) { loadDatabase(); } else if (!m_enabled && m_geoIPDatabase) { delete m_geoIPDatabase; m_geoIPDatabase = nullptr; } } } void GeoIPManager::downloadFinished(const DownloadResult &result) { if (result.status != DownloadStatus::Success) { LogMsg(tr("Couldn't download GeoIP database file. Reason: %1").arg(result.errorString), Log::WARNING); return; } bool ok = false; const QByteArray data = Utils::Gzip::decompress(result.data, &ok); if (!ok) { LogMsg(tr("Could not decompress GeoIP database file."), Log::WARNING); return; } QString error; GeoIPDatabase *geoIPDatabase = GeoIPDatabase::load(data, error); if (geoIPDatabase) { if (!m_geoIPDatabase || (geoIPDatabase->buildEpoch() > m_geoIPDatabase->buildEpoch())) { if (m_geoIPDatabase) delete m_geoIPDatabase; m_geoIPDatabase = geoIPDatabase; LogMsg(tr("GeoIP database loaded. Type: %1. Build time: %2.") .arg(m_geoIPDatabase->type(), m_geoIPDatabase->buildEpoch().toString()), Log::INFO); const QString targetPath = Utils::Fs::expandPathAbs( specialFolderLocation(SpecialFolder::Data) + GEOIP_FOLDER); if (!QDir(targetPath).exists()) QDir().mkpath(targetPath); QFile targetFile(QString("%1/%2").arg(targetPath, GEOIP_FILENAME)); if (!targetFile.open(QFile::WriteOnly) || (targetFile.write(data) == -1)) LogMsg(tr("Couldn't save downloaded GeoIP database file."), Log::WARNING); else LogMsg(tr("Successfully updated GeoIP database."), Log::INFO); } else { delete geoIPDatabase; } } else { LogMsg(tr("Couldn't load GeoIP database. Reason: %1").arg(error), Log::WARNING); } }