From 304e831b0c84a531387a95dc690f11769f4b5d5c Mon Sep 17 00:00:00 2001 From: sledgehammer999 Date: Fri, 14 Feb 2020 22:07:19 +0200 Subject: [PATCH] Use IP geolocation database by DB-IP instead of MaxMind --- README.md | 3 +- src/base/net/geoipmanager.cpp | 56 ++++++++++++++++---------- src/base/net/private/geoipdatabase.cpp | 11 ++--- src/base/net/private/geoipdatabase.h | 1 + src/gui/aboutdialog.h | 8 ++++ src/gui/aboutdialog.ui | 22 ++++++++-- src/gui/advancedsettings.cpp | 2 +- 7 files changed, 67 insertions(+), 36 deletions(-) diff --git a/README.md b/README.md index a2c75ef52..8c0d32e72 100644 --- a/README.md +++ b/README.md @@ -13,8 +13,7 @@ It aims to be a good alternative to all other bittorrent clients out there. qBittorrent is fast, stable and provides unicode support as well as many features. -This product includes GeoLite data created by MaxMind, available from -https://www.maxmind.com/ +The free [IP to Country Lite database](https://db-ip.com/db/download/ip-to-country-lite) by [DB-IP](https://db-ip.com/) is used for resolving the countries of peers. The database is licensed under the [Creative Commons Attribution 4.0 International License](https://creativecommons.org/licenses/by/4.0/). ### Installation: For installation, follow the instructions from INSTALL file, but simple: diff --git a/src/base/net/geoipmanager.cpp b/src/base/net/geoipmanager.cpp index ace840e98..f330713c7 100644 --- a/src/base/net/geoipmanager.cpp +++ b/src/base/net/geoipmanager.cpp @@ -44,10 +44,9 @@ #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 +static const QString DATABASE_URL = QStringLiteral("https://download.db-ip.com/free/dbip-country-lite-%1.mmdb.gz"); +static const char GEODB_FOLDER[] = "GeoDB"; +static const char GEODB_FILENAME[] = "dbip-country-lite.mmdb"; using namespace Net; @@ -96,29 +95,45 @@ void GeoIPManager::loadDatabase() } QString filepath = Utils::Fs::expandPathAbs( - QString("%1%2/%3").arg(specialFolderLocation(SpecialFolder::Data), GEOIP_FOLDER, GEOIP_FILENAME)); + QString("%1%2/%3").arg(specialFolderLocation(SpecialFolder::Data), GEODB_FOLDER, GEODB_FILENAME)); QString error; m_geoIPDatabase = GeoIPDatabase::load(filepath, error); if (m_geoIPDatabase) - Logger::instance()->addMessage(tr("GeoIP database loaded. Type: %1. Build time: %2.") + Logger::instance()->addMessage(tr("IP geolocation 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); + Logger::instance()->addMessage(tr("Couldn't load IP geolocation database. Reason: %1").arg(error), Log::WARNING); manageDatabaseUpdate(); } void GeoIPManager::manageDatabaseUpdate() { - if (!m_geoIPDatabase || (m_geoIPDatabase->buildEpoch().daysTo(QDateTime::currentDateTimeUtc()) >= UPDATE_INTERVAL)) + const auto expired = [](const QDateTime &testDateTime) + { + const QDate testDate = testDateTime.date(); + const QDate curDate = QDateTime::currentDateTimeUtc().date(); + + if ((testDate.year() < curDate.year()) && (curDate.day() > 1)) + return true; + + if ((testDate.month() < curDate.month()) && (curDate.day() > 1)) + return true; + + return false; + }; + + if (!m_geoIPDatabase || expired(m_geoIPDatabase->buildEpoch())) downloadDatabaseFile(); } void GeoIPManager::downloadDatabaseFile() { - DownloadHandler *handler = DownloadManager::instance()->download({DATABASE_URL}); + const QDate curDate = QDateTime::currentDateTimeUtc().date(); + const QString curUrl = DATABASE_URL.arg(curDate.toString("yyyy-MM")); + DownloadHandler *handler = DownloadManager::instance()->download({curUrl}); connect(handler, static_cast(&Net::DownloadHandler::downloadFinished) , this, &GeoIPManager::downloadFinished); connect(handler, &Net::DownloadHandler::downloadFailed, this, &GeoIPManager::downloadFailed); @@ -420,7 +435,7 @@ void GeoIPManager::downloadFinished(const QString &url, QByteArray data) bool ok = false; data = Utils::Gzip::decompress(data, &ok); if (!ok) { - Logger::instance()->addMessage(tr("Could not decompress GeoIP database file."), Log::WARNING); + LogMsg(tr("Could not decompress IP geolocation database file."), Log::WARNING); return; } @@ -431,28 +446,25 @@ void GeoIPManager::downloadFinished(const QString &url, QByteArray data) if (m_geoIPDatabase) delete m_geoIPDatabase; m_geoIPDatabase = geoIPDatabase; - Logger::instance()->addMessage(tr("GeoIP database loaded. Type: %1. Build time: %2.") + LogMsg(tr("IP geolocation database loaded. Type: %1. Build time: %2.") .arg(m_geoIPDatabase->type(), m_geoIPDatabase->buildEpoch().toString()), Log::INFO); - QString targetPath = Utils::Fs::expandPathAbs( - specialFolderLocation(SpecialFolder::Data) + GEOIP_FOLDER); + const QString targetPath = Utils::Fs::expandPathAbs( + specialFolderLocation(SpecialFolder::Data) + GEODB_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)) { - Logger::instance()->addMessage( - tr("Couldn't save downloaded GeoIP database file."), Log::WARNING); - } - else { - Logger::instance()->addMessage(tr("Successfully updated GeoIP database."), Log::INFO); - } + QFile targetFile(QString("%1/%2").arg(targetPath, GEODB_FILENAME)); + if (!targetFile.open(QFile::WriteOnly) || (targetFile.write(data) == -1)) + LogMsg(tr("Couldn't save downloaded IP geolocation database file."), Log::WARNING); + else + LogMsg(tr("Successfully updated IP geolocation database."), Log::INFO); } else { delete geoIPDatabase; } } else { - Logger::instance()->addMessage(tr("Couldn't load GeoIP database. Reason: %1").arg(error), Log::WARNING); + LogMsg(tr("Couldn't load IP geolocation database. Reason: %1").arg(error), Log::WARNING); } } diff --git a/src/base/net/private/geoipdatabase.cpp b/src/base/net/private/geoipdatabase.cpp index 3319c911c..07b317b84 100644 --- a/src/base/net/private/geoipdatabase.cpp +++ b/src/base/net/private/geoipdatabase.cpp @@ -38,7 +38,6 @@ namespace { const qint32 MAX_FILE_SIZE = 67108864; // 64MB - const char DB_TYPE[] = "GeoLite2-Country"; const quint32 MAX_METADATA_SIZE = 131072; // 128KB const char METADATA_BEGIN_MARK[] = "\xab\xcd\xefMaxMind.com"; const char DATA_SECTION_SEPARATOR[16] = {0}; @@ -144,7 +143,7 @@ GeoIPDatabase::~GeoIPDatabase() QString GeoIPDatabase::type() const { - return DB_TYPE; + return m_dbType; } quint16 GeoIPDatabase::ipVersion() const @@ -255,11 +254,7 @@ bool GeoIPDatabase::parseMetadata(const QVariantHash &metadata, QString &error) m_indexSize = m_nodeCount * m_nodeSize; CHECK_METADATA_REQ(database_type, QString); - QString dbType = metadata.value("database_type").toString(); - if (dbType != DB_TYPE) { - error = tr("Invalid database type: %1").arg(dbType); - return false; - } + m_dbType = metadata.value("database_type").toString(); CHECK_METADATA_REQ(build_epoch, ULongLong); m_buildEpoch = QDateTime::fromTime_t(metadata.value("build_epoch").toULongLong()); @@ -272,7 +267,7 @@ bool GeoIPDatabase::parseMetadata(const QVariantHash &metadata, QString &error) bool GeoIPDatabase::loadDB(QString &error) const { - qDebug() << "Parsing MaxMindDB index tree..."; + qDebug() << "Parsing IP geolocation database index tree..."; const int nodeSize = m_recordSize / 4; // in bytes const int indexSize = m_nodeCount * nodeSize; diff --git a/src/base/net/private/geoipdatabase.h b/src/base/net/private/geoipdatabase.h index dc702d4df..d5e17bf88 100644 --- a/src/base/net/private/geoipdatabase.h +++ b/src/base/net/private/geoipdatabase.h @@ -93,6 +93,7 @@ private: int m_indexSize; int m_recordBytes; QDateTime m_buildEpoch; + QString m_dbType; // Search data mutable QHash m_countries; quint32 m_size; diff --git a/src/gui/aboutdialog.h b/src/gui/aboutdialog.h index 8b001830f..87b3a7df8 100644 --- a/src/gui/aboutdialog.h +++ b/src/gui/aboutdialog.h @@ -102,6 +102,14 @@ public: labelLibtVer->setText(Utils::Misc::libtorrentVersionString()); labelBoostVer->setText(Utils::Misc::boostVersionString()); + const QString DBIPText = QString( + "

" + "%1" + " (https://db-ip.com/)

") + .arg(tr("The free IP to Country Lite database by DB-IP is used for resolving the countries of peers. " + "The database is licensed under the Creative Commons Attribution 4.0 International License")); + labelDBIP->setText(DBIPText); + Utils::Gui::resize(this); show(); } diff --git a/src/gui/aboutdialog.ui b/src/gui/aboutdialog.ui index a21b35394..09ef076f5 100644 --- a/src/gui/aboutdialog.ui +++ b/src/gui/aboutdialog.ui @@ -314,11 +314,11 @@ - + - Libraries + Software Used - + @@ -430,6 +430,22 @@ + + + + DB-IP license text + + + true + + + true + + + Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse + + + diff --git a/src/gui/advancedsettings.cpp b/src/gui/advancedsettings.cpp index d1329e02c..185ebd367 100644 --- a/src/gui/advancedsettings.cpp +++ b/src/gui/advancedsettings.cpp @@ -419,7 +419,7 @@ void AdvancedSettings::loadAdvancedSettings() addRow(LIST_REFRESH, tr("Transfer list refresh interval"), &spinBoxListRefresh); // Resolve Peer countries checkBoxResolveCountries.setChecked(pref->resolvePeerCountries()); - addRow(RESOLVE_COUNTRIES, tr("Resolve peer countries (GeoIP)"), &checkBoxResolveCountries); + addRow(RESOLVE_COUNTRIES, tr("Resolve peer countries"), &checkBoxResolveCountries); // Resolve peer hosts checkBoxResolveHosts.setChecked(pref->resolvePeerHostNames()); addRow(RESOLVE_HOSTS, tr("Resolve peer host names"), &checkBoxResolveHosts);