mirror of
https://github.com/qbittorrent/qBittorrent.git
synced 2024-11-28 21:38:51 +03:00
parent
322ae3e0bc
commit
ea1481beef
10 changed files with 73 additions and 38 deletions
|
@ -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
|
out there. qBittorrent is fast, stable and provides unicode
|
||||||
support as well as many features.
|
support as well as many features.
|
||||||
|
|
||||||
This product includes GeoLite data created by MaxMind, available from
|
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/).
|
||||||
https://www.maxmind.com/
|
|
||||||
|
|
||||||
### Installation:
|
### Installation:
|
||||||
For installation, follow the instructions from INSTALL file, but simple:
|
For installation, follow the instructions from INSTALL file, but simple:
|
||||||
|
|
|
@ -42,10 +42,9 @@
|
||||||
#include "downloadmanager.h"
|
#include "downloadmanager.h"
|
||||||
#include "private/geoipdatabase.h"
|
#include "private/geoipdatabase.h"
|
||||||
|
|
||||||
static const char DATABASE_URL[] = "https://geolite.maxmind.com/download/geoip/database/GeoLite2-Country.mmdb.gz";
|
static const QString DATABASE_URL = QStringLiteral("https://download.db-ip.com/free/dbip-country-lite-%1.mmdb.gz");
|
||||||
static const char GEOIP_FOLDER[] = "GeoIP";
|
static const char GEODB_FOLDER[] = "GeoDB";
|
||||||
static const char GEOIP_FILENAME[] = "GeoLite2-Country.mmdb";
|
static const char GEODB_FILENAME[] = "dbip-country-lite.mmdb";
|
||||||
static const int UPDATE_INTERVAL = 30; // Days between database updates
|
|
||||||
|
|
||||||
using namespace Net;
|
using namespace Net;
|
||||||
|
|
||||||
|
@ -89,29 +88,45 @@ void GeoIPManager::loadDatabase()
|
||||||
m_geoIPDatabase = nullptr;
|
m_geoIPDatabase = nullptr;
|
||||||
|
|
||||||
const QString filepath = Utils::Fs::expandPathAbs(
|
const 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;
|
QString error;
|
||||||
m_geoIPDatabase = GeoIPDatabase::load(filepath, error);
|
m_geoIPDatabase = GeoIPDatabase::load(filepath, error);
|
||||||
if (m_geoIPDatabase)
|
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()),
|
.arg(m_geoIPDatabase->type(), m_geoIPDatabase->buildEpoch().toString()),
|
||||||
Log::INFO);
|
Log::INFO);
|
||||||
else
|
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();
|
manageDatabaseUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GeoIPManager::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();
|
downloadDatabaseFile();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GeoIPManager::downloadDatabaseFile()
|
void GeoIPManager::downloadDatabaseFile()
|
||||||
{
|
{
|
||||||
DownloadManager::instance()->download({DATABASE_URL}, this, &GeoIPManager::downloadFinished);
|
const QDate curDate = QDateTime::currentDateTimeUtc().date();
|
||||||
|
const QString curUrl = DATABASE_URL.arg(curDate.toString("yyyy-MM"));
|
||||||
|
DownloadManager::instance()->download({curUrl}, this, &GeoIPManager::downloadFinished);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString GeoIPManager::lookup(const QHostAddress &hostAddr) const
|
QString GeoIPManager::lookup(const QHostAddress &hostAddr) const
|
||||||
|
@ -403,14 +418,14 @@ void GeoIPManager::configure()
|
||||||
void GeoIPManager::downloadFinished(const DownloadResult &result)
|
void GeoIPManager::downloadFinished(const DownloadResult &result)
|
||||||
{
|
{
|
||||||
if (result.status != DownloadStatus::Success) {
|
if (result.status != DownloadStatus::Success) {
|
||||||
LogMsg(tr("Couldn't download GeoIP database file. Reason: %1").arg(result.errorString), Log::WARNING);
|
LogMsg(tr("Couldn't download IP geolocation database file. Reason: %1").arg(result.errorString), Log::WARNING);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ok = false;
|
bool ok = false;
|
||||||
const QByteArray data = Utils::Gzip::decompress(result.data, &ok);
|
const QByteArray data = Utils::Gzip::decompress(result.data, &ok);
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
LogMsg(tr("Could not decompress GeoIP database file."), Log::WARNING);
|
LogMsg(tr("Could not decompress IP geolocation database file."), Log::WARNING);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -420,24 +435,24 @@ void GeoIPManager::downloadFinished(const DownloadResult &result)
|
||||||
if (!m_geoIPDatabase || (geoIPDatabase->buildEpoch() > m_geoIPDatabase->buildEpoch())) {
|
if (!m_geoIPDatabase || (geoIPDatabase->buildEpoch() > m_geoIPDatabase->buildEpoch())) {
|
||||||
delete m_geoIPDatabase;
|
delete m_geoIPDatabase;
|
||||||
m_geoIPDatabase = geoIPDatabase;
|
m_geoIPDatabase = geoIPDatabase;
|
||||||
LogMsg(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()),
|
.arg(m_geoIPDatabase->type(), m_geoIPDatabase->buildEpoch().toString()),
|
||||||
Log::INFO);
|
Log::INFO);
|
||||||
const QString targetPath = Utils::Fs::expandPathAbs(
|
const QString targetPath = Utils::Fs::expandPathAbs(
|
||||||
specialFolderLocation(SpecialFolder::Data) + GEOIP_FOLDER);
|
specialFolderLocation(SpecialFolder::Data) + GEODB_FOLDER);
|
||||||
if (!QDir(targetPath).exists())
|
if (!QDir(targetPath).exists())
|
||||||
QDir().mkpath(targetPath);
|
QDir().mkpath(targetPath);
|
||||||
QFile targetFile(QString("%1/%2").arg(targetPath, GEOIP_FILENAME));
|
QFile targetFile(QString("%1/%2").arg(targetPath, GEODB_FILENAME));
|
||||||
if (!targetFile.open(QFile::WriteOnly) || (targetFile.write(data) == -1))
|
if (!targetFile.open(QFile::WriteOnly) || (targetFile.write(data) == -1))
|
||||||
LogMsg(tr("Couldn't save downloaded GeoIP database file."), Log::WARNING);
|
LogMsg(tr("Couldn't save downloaded IP geolocation database file."), Log::WARNING);
|
||||||
else
|
else
|
||||||
LogMsg(tr("Successfully updated GeoIP database."), Log::INFO);
|
LogMsg(tr("Successfully updated IP geolocation database."), Log::INFO);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
delete geoIPDatabase;
|
delete geoIPDatabase;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
LogMsg(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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,6 @@
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
const qint32 MAX_FILE_SIZE = 67108864; // 64MB
|
const qint32 MAX_FILE_SIZE = 67108864; // 64MB
|
||||||
const char DB_TYPE[] = "GeoLite2-Country";
|
|
||||||
const quint32 MAX_METADATA_SIZE = 131072; // 128KB
|
const quint32 MAX_METADATA_SIZE = 131072; // 128KB
|
||||||
const char METADATA_BEGIN_MARK[] = "\xab\xcd\xefMaxMind.com";
|
const char METADATA_BEGIN_MARK[] = "\xab\xcd\xefMaxMind.com";
|
||||||
const char DATA_SECTION_SEPARATOR[16] = {0};
|
const char DATA_SECTION_SEPARATOR[16] = {0};
|
||||||
|
@ -143,7 +142,7 @@ GeoIPDatabase::~GeoIPDatabase()
|
||||||
|
|
||||||
QString GeoIPDatabase::type() const
|
QString GeoIPDatabase::type() const
|
||||||
{
|
{
|
||||||
return DB_TYPE;
|
return m_dbType;
|
||||||
}
|
}
|
||||||
|
|
||||||
quint16 GeoIPDatabase::ipVersion() const
|
quint16 GeoIPDatabase::ipVersion() const
|
||||||
|
@ -253,11 +252,7 @@ bool GeoIPDatabase::parseMetadata(const QVariantHash &metadata, QString &error)
|
||||||
m_indexSize = m_nodeCount * m_nodeSize;
|
m_indexSize = m_nodeCount * m_nodeSize;
|
||||||
|
|
||||||
CHECK_METADATA_REQ(database_type, QString);
|
CHECK_METADATA_REQ(database_type, QString);
|
||||||
const QString dbType = metadata.value("database_type").toString();
|
m_dbType = metadata.value("database_type").toString();
|
||||||
if (dbType != DB_TYPE) {
|
|
||||||
error = tr("Invalid database type: %1").arg(dbType);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
CHECK_METADATA_REQ(build_epoch, ULongLong);
|
CHECK_METADATA_REQ(build_epoch, ULongLong);
|
||||||
m_buildEpoch = QDateTime::fromSecsSinceEpoch(metadata.value("build_epoch").toULongLong());
|
m_buildEpoch = QDateTime::fromSecsSinceEpoch(metadata.value("build_epoch").toULongLong());
|
||||||
|
@ -270,7 +265,7 @@ bool GeoIPDatabase::parseMetadata(const QVariantHash &metadata, QString &error)
|
||||||
|
|
||||||
bool GeoIPDatabase::loadDB(QString &error) const
|
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 nodeSize = m_recordSize / 4; // in bytes
|
||||||
const int indexSize = m_nodeCount * nodeSize;
|
const int indexSize = m_nodeCount * nodeSize;
|
||||||
|
|
|
@ -93,6 +93,7 @@ private:
|
||||||
int m_indexSize;
|
int m_indexSize;
|
||||||
int m_recordBytes;
|
int m_recordBytes;
|
||||||
QDateTime m_buildEpoch;
|
QDateTime m_buildEpoch;
|
||||||
|
QString m_dbType;
|
||||||
// Search data
|
// Search data
|
||||||
mutable QHash<quint32, QString> m_countries;
|
mutable QHash<quint32, QString> m_countries;
|
||||||
quint32 m_size;
|
quint32 m_size;
|
||||||
|
|
|
@ -48,7 +48,7 @@ AboutDialog::AboutDialog(QWidget *parent)
|
||||||
m_ui->logo->setPixmap(Utils::Gui::scaledPixmapSvg(":/icons/skin/qbittorrent-tray.svg", this, 32));
|
m_ui->logo->setPixmap(Utils::Gui::scaledPixmapSvg(":/icons/skin/qbittorrent-tray.svg", this, 32));
|
||||||
|
|
||||||
// About
|
// About
|
||||||
QString aboutText = QString(
|
const QString aboutText = QString(
|
||||||
"<p style=\"white-space: pre-wrap;\">"
|
"<p style=\"white-space: pre-wrap;\">"
|
||||||
"%1\n\n"
|
"%1\n\n"
|
||||||
"%2\n\n"
|
"%2\n\n"
|
||||||
|
@ -88,13 +88,21 @@ AboutDialog::AboutDialog(QWidget *parent)
|
||||||
licensefile.close();
|
licensefile.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Libraries
|
// Software Used
|
||||||
m_ui->labelQtVer->setText(QT_VERSION_STR);
|
m_ui->labelQtVer->setText(QT_VERSION_STR);
|
||||||
m_ui->labelLibtVer->setText(Utils::Misc::libtorrentVersionString());
|
m_ui->labelLibtVer->setText(Utils::Misc::libtorrentVersionString());
|
||||||
m_ui->labelBoostVer->setText(Utils::Misc::boostVersionString());
|
m_ui->labelBoostVer->setText(Utils::Misc::boostVersionString());
|
||||||
m_ui->labelOpensslVer->setText(Utils::Misc::opensslVersionString());
|
m_ui->labelOpensslVer->setText(Utils::Misc::opensslVersionString());
|
||||||
m_ui->labelZlibVer->setText(Utils::Misc::zlibVersionString());
|
m_ui->labelZlibVer->setText(Utils::Misc::zlibVersionString());
|
||||||
|
|
||||||
|
const QString DBIPText = QString(
|
||||||
|
"<html><head/><body><p>"
|
||||||
|
"%1"
|
||||||
|
" (<a href=\"https://db-ip.com/\">https://db-ip.com/</a>)</p></body></html>")
|
||||||
|
.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"));
|
||||||
|
m_ui->labelDBIP->setText(DBIPText);
|
||||||
|
|
||||||
Utils::Gui::resize(this);
|
Utils::Gui::resize(this);
|
||||||
show();
|
show();
|
||||||
}
|
}
|
||||||
|
|
|
@ -314,11 +314,11 @@
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QWidget" name="librariesTab">
|
<widget class="QWidget" name="SoftwareUsedTab">
|
||||||
<attribute name="title">
|
<attribute name="title">
|
||||||
<string>Libraries</string>
|
<string>Software Used</string>
|
||||||
</attribute>
|
</attribute>
|
||||||
<layout class="QVBoxLayout" name="librariesTabLayout">
|
<layout class="QVBoxLayout" name="SoftwareUsedTabLayout">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="label">
|
<widget class="QLabel" name="label">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
|
@ -470,6 +470,22 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="labelDBIP">
|
||||||
|
<property name="text">
|
||||||
|
<string notr="true">DB-IP license text</string>
|
||||||
|
</property>
|
||||||
|
<property name="wordWrap">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="openExternalLinks">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="textInteractionFlags">
|
||||||
|
<set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<spacer name="verticalSpacer_2">
|
<spacer name="verticalSpacer_2">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
|
|
|
@ -496,7 +496,7 @@ void AdvancedSettings::loadAdvancedSettings()
|
||||||
addRow(LIST_REFRESH, tr("Transfer list refresh interval"), &m_spinBoxListRefresh);
|
addRow(LIST_REFRESH, tr("Transfer list refresh interval"), &m_spinBoxListRefresh);
|
||||||
// Resolve Peer countries
|
// Resolve Peer countries
|
||||||
m_checkBoxResolveCountries.setChecked(pref->resolvePeerCountries());
|
m_checkBoxResolveCountries.setChecked(pref->resolvePeerCountries());
|
||||||
addRow(RESOLVE_COUNTRIES, tr("Resolve peer countries (GeoIP)"), &m_checkBoxResolveCountries);
|
addRow(RESOLVE_COUNTRIES, tr("Resolve peer countries"), &m_checkBoxResolveCountries);
|
||||||
// Resolve peer hosts
|
// Resolve peer hosts
|
||||||
m_checkBoxResolveHosts.setChecked(pref->resolvePeerHostNames());
|
m_checkBoxResolveHosts.setChecked(pref->resolvePeerHostNames());
|
||||||
addRow(RESOLVE_HOSTS, tr("Resolve peer host names"), &m_checkBoxResolveHosts);
|
addRow(RESOLVE_HOSTS, tr("Resolve peer host names"), &m_checkBoxResolveHosts);
|
||||||
|
|
|
@ -652,7 +652,7 @@
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="aboutLibrariesContent" class="aboutTabContent invisible">
|
<div id="aboutSoftwareUsedContent" class="aboutTabContent invisible">
|
||||||
<p>QBT_TR(qBittorrent was built with the following libraries:)QBT_TR[CONTEXT=AboutDialog]</p>
|
<p>QBT_TR(qBittorrent was built with the following libraries:)QBT_TR[CONTEXT=AboutDialog]</p>
|
||||||
<table style="margin-left: 20px;">
|
<table style="margin-left: 20px;">
|
||||||
<tr>
|
<tr>
|
||||||
|
@ -676,6 +676,7 @@
|
||||||
<td><span id="zlibVersion"></span></td>
|
<td><span id="zlibVersion"></span></td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
<p>QBT_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)QBT_TR[CONTEXT=AboutDialog] (<a href="https://db-ip.com/" target="_blank" rel="noopener ">https://db-ip.com/</a>)</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<li id="aboutSpecialThanksLink"><a>QBT_TR(Special Thanks)QBT_TR[CONTEXT=AboutDialog]</a></li>
|
<li id="aboutSpecialThanksLink"><a>QBT_TR(Special Thanks)QBT_TR[CONTEXT=AboutDialog]</a></li>
|
||||||
<li id="aboutTranslatorsLink"><a>QBT_TR(Translators)QBT_TR[CONTEXT=AboutDialog]</a></li>
|
<li id="aboutTranslatorsLink"><a>QBT_TR(Translators)QBT_TR[CONTEXT=AboutDialog]</a></li>
|
||||||
<li id="aboutLicenseLink"><a>QBT_TR(License)QBT_TR[CONTEXT=AboutDialog]</a></li>
|
<li id="aboutLicenseLink"><a>QBT_TR(License)QBT_TR[CONTEXT=AboutDialog]</a></li>
|
||||||
<li id="aboutLibrariesLink"><a>QBT_TR(Libraries)QBT_TR[CONTEXT=AboutDialog]</a></li>
|
<li id="aboutSoftwareUsedLink"><a>QBT_TR(Software Used)QBT_TR[CONTEXT=AboutDialog]</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
<div class="clear"></div>
|
<div class="clear"></div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -41,9 +41,9 @@
|
||||||
$('aboutLicenseContent').removeClass('invisible');
|
$('aboutLicenseContent').removeClass('invisible');
|
||||||
});
|
});
|
||||||
|
|
||||||
$('aboutLibrariesLink').addEvent('click', function() {
|
$('aboutSoftwareUsedLink').addEvent('click', function() {
|
||||||
$$('.aboutTabContent').addClass('invisible');
|
$$('.aboutTabContent').addClass('invisible');
|
||||||
$('aboutLibrariesContent').removeClass('invisible');
|
$('aboutSoftwareUsedContent').removeClass('invisible');
|
||||||
});
|
});
|
||||||
})();
|
})();
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -868,7 +868,7 @@
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<label for="resolvePeerCountries">QBT_TR(Resolve peer countries (GeoIP):)QBT_TR[CONTEXT=OptionsDialog]</label>
|
<label for="resolvePeerCountries">QBT_TR(Resolve peer countries:)QBT_TR[CONTEXT=OptionsDialog]</label>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<input type="checkbox" id="resolvePeerCountries">
|
<input type="checkbox" id="resolvePeerCountries">
|
||||||
|
|
Loading…
Reference in a new issue