mirror of
https://github.com/qbittorrent/qBittorrent.git
synced 2025-01-09 16:47:27 +03:00
6748e8d787
Attempting to delete a null pointer is a noop in C++. Closes #2864. [1] https://isocpp.org/wiki/faq/freestore-mgmt#delete-handles-null
443 lines
15 KiB
C++
443 lines
15 KiB
C++
/*
|
|
* Bittorrent Client using Qt and libtorrent.
|
|
* Copyright (C) 2015 Vladimir Golovnev <glassez@yandex.ru>
|
|
* Copyright (C) 2010 Christophe Dumez <chris@qbittorrent.org>
|
|
*
|
|
* 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 <QDateTime>
|
|
#include <QDir>
|
|
#include <QFile>
|
|
#include <QHostAddress>
|
|
|
|
#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()
|
|
{
|
|
delete m_geoIPDatabase;
|
|
}
|
|
|
|
void GeoIPManager::initInstance()
|
|
{
|
|
if (!m_instance)
|
|
m_instance = new GeoIPManager;
|
|
}
|
|
|
|
void GeoIPManager::freeInstance()
|
|
{
|
|
delete m_instance;
|
|
m_instance = nullptr;
|
|
}
|
|
|
|
GeoIPManager *GeoIPManager::instance()
|
|
{
|
|
return m_instance;
|
|
}
|
|
|
|
void GeoIPManager::loadDatabase()
|
|
{
|
|
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<QString, QString> 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("Vietnam")},
|
|
{"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) {
|
|
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())) {
|
|
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);
|
|
}
|
|
}
|