mirror of
https://github.com/qbittorrent/qBittorrent.git
synced 2024-11-29 05:48:47 +03:00
commit
5b7ea0e611
41 changed files with 1476 additions and 548 deletions
32
configure
vendored
32
configure
vendored
|
@ -716,7 +716,6 @@ enable_dependency_tracking
|
|||
enable_silent_rules
|
||||
with_qt5
|
||||
with_libtorrent_rasterbar0_16
|
||||
with_geoip_database_embedded
|
||||
with_qtsingleapplication
|
||||
with_qjson
|
||||
enable_debug
|
||||
|
@ -1387,10 +1386,6 @@ Optional Packages:
|
|||
--with-libtorrent-rasterbar0.16
|
||||
Compile using libtorrent-rasterbar 0.16.x series
|
||||
(default=no)
|
||||
--with-geoip-database-embedded
|
||||
Embed the GeoIP database in the qBittorrent
|
||||
executable (please follow instructions in
|
||||
src/gui/geoip/README) (default=no)
|
||||
--with-qtsingleapplication=[system|shipped]
|
||||
Use the shipped qtsingleapplication library or the
|
||||
system one (default=shipped)
|
||||
|
@ -4194,15 +4189,6 @@ fi
|
|||
|
||||
|
||||
|
||||
# Check whether --with-geoip-database-embedded was given.
|
||||
if test "${with_geoip_database_embedded+set}" = set; then :
|
||||
withval=$with_geoip_database_embedded;
|
||||
else
|
||||
with_geoip_database_embedded=no
|
||||
fi
|
||||
|
||||
|
||||
|
||||
# Check whether --with-qtsingleapplication was given.
|
||||
if test "${with_qtsingleapplication+set}" = set; then :
|
||||
withval=$with_qtsingleapplication;
|
||||
|
@ -4429,7 +4415,6 @@ $as_echo "yes" >&6; }
|
|||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
enable_qt_dbus=no
|
||||
enable_geoip_database=no
|
||||
QBT_ADD_CONFIG="$QBT_ADD_CONFIG nogui" ;; #(
|
||||
*) :
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_gui" >&5
|
||||
|
@ -5493,23 +5478,6 @@ $as_echo "$with_libtorrent_rasterbar0_16" >&6; }
|
|||
as_fn_error $? "Unknown option \"$with_libtorrent_rasterbar0_16\". Use either \"yes\" or \"no\"." "$LINENO" 5 ;;
|
||||
esac
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to embed the GeoIP database" >&5
|
||||
$as_echo_n "checking whether to embed the GeoIP database... " >&6; }
|
||||
case "x$with_geoip_database_embedded" in #(
|
||||
"xno") :
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
QBT_REMOVE_DEFINES="$QBT_REMOVE_DEFINES WITH_GEOIP_EMBEDDED" ;; #(
|
||||
"xyes") :
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
$as_echo "yes" >&6; }
|
||||
QBT_ADD_DEFINES="$QBT_ADD_DEFINES WITH_GEOIP_EMBEDDED" ;; #(
|
||||
*) :
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_geoip_database_embedded" >&5
|
||||
$as_echo "$with_geoip_database_embedded" >&6; }
|
||||
as_fn_error $? "Unknown option \"$with_geoip_database_embedded\". Use either \"yes\" or \"no\"." "$LINENO" 5 ;;
|
||||
esac
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking which qtsingleapplication to use" >&5
|
||||
$as_echo_n "checking which qtsingleapplication to use... " >&6; }
|
||||
case "x$with_qtsingleapplication" in #(
|
||||
|
|
17
configure.ac
17
configure.ac
|
@ -24,12 +24,6 @@ AC_ARG_WITH(libtorrent-rasterbar0.16,
|
|||
[],
|
||||
[with_libtorrent_rasterbar0_16=no])
|
||||
|
||||
AC_ARG_WITH(geoip-database-embedded,
|
||||
[AS_HELP_STRING([--with-geoip-database-embedded],
|
||||
[Embed the GeoIP database in the qBittorrent executable (please follow instructions in src/gui/geoip/README) (default=no)])],
|
||||
[],
|
||||
[with_geoip_database_embedded=no])
|
||||
|
||||
AC_ARG_WITH(qtsingleapplication,
|
||||
[AS_HELP_STRING([--with-qtsingleapplication=@<:@system|shipped@:>@],
|
||||
[Use the shipped qtsingleapplication library or the system one (default=shipped)])],
|
||||
|
@ -198,17 +192,6 @@ AS_CASE(["x$with_libtorrent_rasterbar0_16"],
|
|||
[AC_MSG_RESULT([$with_libtorrent_rasterbar0_16])
|
||||
AC_MSG_ERROR([Unknown option "$with_libtorrent_rasterbar0_16". Use either "yes" or "no".])])
|
||||
|
||||
AC_MSG_CHECKING([whether to embed the GeoIP database])
|
||||
AS_CASE(["x$with_geoip_database_embedded"],
|
||||
["xno"],
|
||||
[AC_MSG_RESULT([no])
|
||||
QBT_REMOVE_DEFINES="$QBT_REMOVE_DEFINES WITH_GEOIP_EMBEDDED"],
|
||||
["xyes"],
|
||||
[AC_MSG_RESULT([yes])
|
||||
QBT_ADD_DEFINES="$QBT_ADD_DEFINES WITH_GEOIP_EMBEDDED"],
|
||||
[AC_MSG_RESULT([$with_geoip_database_embedded])
|
||||
AC_MSG_ERROR([Unknown option "$with_geoip_database_embedded". Use either "yes" or "no".])])
|
||||
|
||||
AC_MSG_CHECKING([which qtsingleapplication to use])
|
||||
AS_CASE(["x$with_qtsingleapplication"],
|
||||
["xshipped"],
|
||||
|
|
|
@ -56,6 +56,3 @@ QMAKE_BUNDLE_DATA += qt_translations
|
|||
|
||||
ICON = $$DIST_PATH/qbittorrent_mac.icns
|
||||
QMAKE_INFO_PLIST = $$DIST_PATH/Info.plist
|
||||
|
||||
DEFINES += WITH_GEOIP_EMBEDDED
|
||||
message("On Mac OS X, GeoIP database must be embedded.")
|
||||
|
|
|
@ -13,8 +13,4 @@ LIBS += \
|
|||
RC_FILE = qbittorrent_os2.rc
|
||||
|
||||
# LIBTORRENT DEFINES
|
||||
DEFINES += WITH_SHIPPED_GEOIP_H
|
||||
DEFINES += BOOST_ASIO_DYN_LINK
|
||||
|
||||
DEFINES += WITH_GEOIP_EMBEDDED
|
||||
message("On eCS(OS/2), GeoIP database must be embedded.")
|
||||
|
|
|
@ -65,6 +65,7 @@
|
|||
#include "core/scanfoldersmodel.h"
|
||||
#include "core/net/smtp.h"
|
||||
#include "core/net/downloadmanager.h"
|
||||
#include "core/net/geoipmanager.h"
|
||||
#include "core/bittorrent/session.h"
|
||||
#include "core/bittorrent/torrenthandle.h"
|
||||
|
||||
|
@ -232,10 +233,14 @@ int Application::exec(const QStringList ¶ms)
|
|||
#else
|
||||
GuiIconProvider::initInstance();
|
||||
#endif
|
||||
|
||||
BitTorrent::Session::initInstance();
|
||||
connect(BitTorrent::Session::instance(), SIGNAL(torrentFinished(BitTorrent::TorrentHandle *const)), SLOT(torrentFinished(BitTorrent::TorrentHandle *const)));
|
||||
connect(BitTorrent::Session::instance(), SIGNAL(allTorrentsFinished()), SLOT(allTorrentsFinished()));
|
||||
|
||||
#ifndef DISABLE_COUNTRIES_RESOLUTION
|
||||
Net::GeoIPManager::initInstance();
|
||||
#endif
|
||||
ScanFoldersModel::initInstance(this);
|
||||
|
||||
#ifndef DISABLE_WEBUI
|
||||
|
@ -446,6 +451,9 @@ void Application::cleanup()
|
|||
|
||||
ScanFoldersModel::freeInstance();
|
||||
BitTorrent::Session::freeInstance();
|
||||
#ifndef DISABLE_COUNTRIES_RESOLUTION
|
||||
Net::GeoIPManager::freeInstance();
|
||||
#endif
|
||||
Preferences::freeInstance();
|
||||
Logger::freeInstance();
|
||||
IconProvider::freeInstance();
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
|
||||
#include <libtorrent/version.hpp>
|
||||
|
||||
#include "core/net/geoipmanager.h"
|
||||
#include "core/utils/string.h"
|
||||
#include "peerinfo.h"
|
||||
|
||||
|
@ -69,11 +70,12 @@ bool PeerInfo::fromLSD() const
|
|||
return (m_nativeInfo.source & libt::peer_info::lsd);
|
||||
}
|
||||
|
||||
#ifndef DISABLE_COUNTRIES_RESOLUTION
|
||||
QString PeerInfo::country() const
|
||||
{
|
||||
return QString(QByteArray(m_nativeInfo.country, 2));
|
||||
return Net::GeoIPManager::instance()->lookup(address().ip);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
bool PeerInfo::isInteresting() const
|
||||
{
|
||||
|
|
|
@ -89,7 +89,9 @@ namespace BitTorrent
|
|||
qlonglong totalDownload() const;
|
||||
QBitArray pieces() const;
|
||||
QString connectionType() const;
|
||||
#ifndef DISABLE_COUNTRIES_RESOLUTION
|
||||
QString country() const;
|
||||
#endif
|
||||
|
||||
private:
|
||||
libtorrent::peer_info m_nativeInfo;
|
||||
|
|
|
@ -50,9 +50,6 @@ struct SessionPrivate
|
|||
virtual bool isTempPathEnabled() const = 0;
|
||||
virtual bool isAppendExtensionEnabled() const = 0;
|
||||
virtual bool useAppendLabelToSavePath() const = 0;
|
||||
#ifndef DISABLE_COUNTRIES_RESOLUTION
|
||||
virtual bool isResolveCountriesEnabled() const = 0;
|
||||
#endif
|
||||
virtual QString defaultSavePath() const = 0;
|
||||
virtual QString tempPath() const = 0;
|
||||
virtual qreal globalMaxRatio() const = 0;
|
||||
|
|
|
@ -42,9 +42,6 @@ struct TorrentHandlePrivate
|
|||
virtual void handleDefaultSavePathChanged() = 0;
|
||||
virtual void handleTempPathChanged() = 0;
|
||||
virtual void handleAppendExtensionToggled() = 0;
|
||||
#ifndef DISABLE_COUNTRIES_RESOLUTION
|
||||
virtual void handleResolveCountriesToggled() = 0;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
~TorrentHandlePrivate() {}
|
||||
|
|
|
@ -63,7 +63,7 @@ using namespace BitTorrent;
|
|||
//#include <libtorrent/extensions/metadata_transfer.hpp>
|
||||
|
||||
#ifndef DISABLE_COUNTRIES_RESOLUTION
|
||||
#include "geoipmanager.h"
|
||||
#include "core/net/geoipmanager.h"
|
||||
#endif
|
||||
|
||||
#include "core/utils/misc.h"
|
||||
|
@ -141,10 +141,6 @@ Session::Session(QObject *parent)
|
|||
, m_globalMaxRatio(-1)
|
||||
, m_numResumeData(0)
|
||||
, m_extraLimit(0)
|
||||
#ifndef DISABLE_COUNTRIES_RESOLUTION
|
||||
, m_geoipDBLoaded(false)
|
||||
, m_resolveCountries(false)
|
||||
#endif
|
||||
, m_appendLabelToSavePath(false)
|
||||
, m_appendExtension(false)
|
||||
, m_refreshInterval(0)
|
||||
|
@ -252,13 +248,6 @@ bool Session::useAppendLabelToSavePath() const
|
|||
return m_appendLabelToSavePath;
|
||||
}
|
||||
|
||||
#ifndef DISABLE_COUNTRIES_RESOLUTION
|
||||
bool Session::isResolveCountriesEnabled() const
|
||||
{
|
||||
return m_resolveCountries;
|
||||
}
|
||||
#endif
|
||||
|
||||
QString Session::defaultSavePath() const
|
||||
{
|
||||
return m_defaultSavePath;
|
||||
|
@ -577,25 +566,6 @@ void Session::configure()
|
|||
delete m_bwScheduler;
|
||||
}
|
||||
|
||||
#ifndef DISABLE_COUNTRIES_RESOLUTION
|
||||
// Resolve countries
|
||||
qDebug("Loading country resolution settings");
|
||||
const bool new_resolv_countries = pref->resolvePeerCountries();
|
||||
if (m_resolveCountries != new_resolv_countries) {
|
||||
qDebug("in country resolution settings");
|
||||
m_resolveCountries = new_resolv_countries;
|
||||
if (m_resolveCountries && !m_geoipDBLoaded) {
|
||||
qDebug("Loading geoip database");
|
||||
GeoIPManager::loadDatabase(m_nativeSession);
|
||||
m_geoipDBLoaded = true;
|
||||
}
|
||||
|
||||
// Update torrent handles
|
||||
foreach (TorrentHandlePrivate *const torrent, m_torrents)
|
||||
torrent->handleResolveCountriesToggled();
|
||||
}
|
||||
#endif
|
||||
|
||||
Logger* const logger = Logger::instance();
|
||||
|
||||
// * Session settings
|
||||
|
@ -1049,7 +1019,7 @@ bool Session::addTorrent(QString source, const AddTorrentParams ¶ms)
|
|||
if (Utils::Misc::isUrl(source)) {
|
||||
Logger::instance()->addMessage(tr("Downloading '%1', please wait...", "e.g: Downloading 'xxx.torrent', please wait...").arg(source));
|
||||
// Launch downloader
|
||||
Net::DownloadHandler *handler = Net::DownloadManager::instance()->downloadUrl(source, 10485760 /* 10MB */);
|
||||
Net::DownloadHandler *handler = Net::DownloadManager::instance()->downloadUrl(source, true, 10485760 /* 10MB */, true);
|
||||
connect(handler, SIGNAL(downloadFinished(QString, QString)), this, SLOT(handleDownloadFinished(QString, QString)));
|
||||
connect(handler, SIGNAL(downloadFailed(QString, QString)), this, SLOT(handleDownloadFailed(QString, QString)));
|
||||
connect(handler, SIGNAL(redirectedToMagnet(QString, QString)), this, SLOT(handleRedirectedToMagnet(QString, QString)));
|
||||
|
|
|
@ -283,9 +283,6 @@ namespace BitTorrent
|
|||
bool isTempPathEnabled() const;
|
||||
bool isAppendExtensionEnabled() const;
|
||||
bool useAppendLabelToSavePath() const;
|
||||
#ifndef DISABLE_COUNTRIES_RESOLUTION
|
||||
bool isResolveCountriesEnabled() const;
|
||||
#endif
|
||||
QString defaultSavePath() const;
|
||||
QString tempPath() const;
|
||||
void handleTorrentRatioLimitChanged(TorrentHandle *const torrent);
|
||||
|
@ -327,10 +324,6 @@ namespace BitTorrent
|
|||
qreal m_globalMaxRatio;
|
||||
int m_numResumeData;
|
||||
int m_extraLimit;
|
||||
#ifndef DISABLE_COUNTRIES_RESOLUTION
|
||||
bool m_geoipDBLoaded;
|
||||
bool m_resolveCountries;
|
||||
#endif
|
||||
bool m_appendLabelToSavePath;
|
||||
bool m_appendExtension;
|
||||
uint m_refreshInterval;
|
||||
|
|
|
@ -205,10 +205,6 @@ TorrentHandle::TorrentHandle(Session *session, const libtorrent::torrent_handle
|
|||
{
|
||||
initialize();
|
||||
|
||||
#ifndef DISABLE_COUNTRIES_RESOLUTION
|
||||
resolveCountries(m_session->isResolveCountriesEnabled());
|
||||
#endif
|
||||
|
||||
if (!data.resumed) {
|
||||
setSequentialDownload(data.sequential);
|
||||
if (hasMetadata()) {
|
||||
|
@ -1644,13 +1640,6 @@ void TorrentHandle::handleAppendExtensionToggled()
|
|||
removeExtensionsFromIncompleteFiles();
|
||||
}
|
||||
|
||||
#ifndef DISABLE_COUNTRIES_RESOLUTION
|
||||
void TorrentHandle::handleResolveCountriesToggled()
|
||||
{
|
||||
resolveCountries(m_session->isResolveCountriesEnabled());
|
||||
}
|
||||
#endif
|
||||
|
||||
void TorrentHandle::handleAlert(libtorrent::alert *a)
|
||||
{
|
||||
switch (a->type()) {
|
||||
|
@ -1865,11 +1854,6 @@ QString TorrentHandle::toMagnetUri() const
|
|||
return Utils::String::fromStdString(libt::make_magnet_uri(m_nativeHandle));
|
||||
}
|
||||
|
||||
void TorrentHandle::resolveCountries(bool b)
|
||||
{
|
||||
SAFE_CALL(resolve_countries, b);
|
||||
}
|
||||
|
||||
void TorrentHandle::prioritizeFiles(const QVector<int> &priorities)
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
|
|
|
@ -316,9 +316,6 @@ namespace BitTorrent
|
|||
void handleDefaultSavePathChanged();
|
||||
void handleTempPathChanged();
|
||||
void handleAppendExtensionToggled();
|
||||
#ifndef DISABLE_COUNTRIES_RESOLUTION
|
||||
void handleResolveCountriesToggled();
|
||||
#endif
|
||||
|
||||
void handleStorageMovedAlert(libtorrent::storage_moved_alert *p);
|
||||
void handleStorageMovedFailedAlert(libtorrent::storage_moved_failed_alert *p);
|
||||
|
@ -341,7 +338,6 @@ namespace BitTorrent
|
|||
bool useTempPath() const;
|
||||
QString nativeActualSavePath() const;
|
||||
|
||||
void resolveCountries(bool b);
|
||||
void adjustSavePath();
|
||||
void adjustActualSavePath();
|
||||
void adjustActualSavePath_impl();
|
||||
|
|
|
@ -16,9 +16,11 @@ HEADERS += \
|
|||
$$PWD/net/dnsupdater.h \
|
||||
$$PWD/net/downloadmanager.h \
|
||||
$$PWD/net/downloadhandler.h \
|
||||
$$PWD/net/geoipmanager.h \
|
||||
$$PWD/net/portforwarder.h \
|
||||
$$PWD/net/reverseresolution.h \
|
||||
$$PWD/net/smtp.h \
|
||||
$$PWD/net/private/geoipdatabase.h \
|
||||
$$PWD/bittorrent/infohash.h \
|
||||
$$PWD/bittorrent/session.h \
|
||||
$$PWD/bittorrent/sessionstatus.h \
|
||||
|
@ -37,6 +39,7 @@ HEADERS += \
|
|||
$$PWD/bittorrent/private/filterparserthread.h \
|
||||
$$PWD/bittorrent/private/statistics.h \
|
||||
$$PWD/utils/fs.h \
|
||||
$$PWD/utils/gzip.h \
|
||||
$$PWD/utils/misc.h \
|
||||
$$PWD/utils/string.h \
|
||||
$$PWD/unicodestrings.h \
|
||||
|
@ -57,9 +60,11 @@ SOURCES += \
|
|||
$$PWD/net/dnsupdater.cpp \
|
||||
$$PWD/net/downloadmanager.cpp \
|
||||
$$PWD/net/downloadhandler.cpp \
|
||||
$$PWD/net/geoipmanager.cpp \
|
||||
$$PWD/net/portforwarder.cpp \
|
||||
$$PWD/net/reverseresolution.cpp \
|
||||
$$PWD/net/smtp.cpp \
|
||||
$$PWD/net/private/geoipdatabase.cpp \
|
||||
$$PWD/bittorrent/infohash.cpp \
|
||||
$$PWD/bittorrent/session.cpp \
|
||||
$$PWD/bittorrent/sessionstatus.cpp \
|
||||
|
@ -76,6 +81,7 @@ SOURCES += \
|
|||
$$PWD/bittorrent/private/filterparserthread.cpp \
|
||||
$$PWD/bittorrent/private/statistics.cpp \
|
||||
$$PWD/utils/fs.cpp \
|
||||
$$PWD/utils/gzip.cpp \
|
||||
$$PWD/utils/misc.cpp \
|
||||
$$PWD/utils/string.cpp \
|
||||
$$PWD/torrentfilter.cpp \
|
||||
|
|
|
@ -29,11 +29,9 @@
|
|||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
#include <zlib.h>
|
||||
#include "core/utils/gzip.h"
|
||||
#include "responsegenerator.h"
|
||||
|
||||
bool gCompress(QByteArray data, QByteArray& dest_buffer);
|
||||
|
||||
using namespace Http;
|
||||
|
||||
QByteArray ResponseGenerator::generate(Response response)
|
||||
|
@ -44,7 +42,7 @@ QByteArray ResponseGenerator::generate(Response response)
|
|||
// So we only benefit from gzip if the message is bigger than 23+26 = 49
|
||||
// If the message is smaller than 49 bytes we actually send MORE data if we gzip
|
||||
QByteArray dest_buf;
|
||||
if ((response.content.size() > 49) && (gCompress(response.content, dest_buf)))
|
||||
if ((response.content.size() > 49) && (Utils::Gzip::compress(response.content, dest_buf)))
|
||||
response.content = dest_buf;
|
||||
else
|
||||
response.headers.remove(HEADER_CONTENT_ENCODING);
|
||||
|
@ -67,58 +65,3 @@ QByteArray ResponseGenerator::generate(Response response)
|
|||
|
||||
return ret.toUtf8() + response.content;
|
||||
}
|
||||
|
||||
bool gCompress(QByteArray data, QByteArray& dest_buffer)
|
||||
{
|
||||
static const int BUFSIZE = 128 * 1024;
|
||||
char tmp_buf[BUFSIZE];
|
||||
int ret;
|
||||
|
||||
z_stream strm;
|
||||
strm.zalloc = Z_NULL;
|
||||
strm.zfree = Z_NULL;
|
||||
strm.opaque = Z_NULL;
|
||||
strm.next_in = reinterpret_cast<unsigned char*>(data.data());
|
||||
strm.avail_in = data.length();
|
||||
strm.next_out = reinterpret_cast<unsigned char*>(tmp_buf);
|
||||
strm.avail_out = BUFSIZE;
|
||||
|
||||
//windowBits = 15+16 to enable gzip
|
||||
//From the zlib manual: windowBits can also be greater than 15 for optional gzip encoding. Add 16 to windowBits
|
||||
//to write a simple gzip header and trailer around the compressed data instead of a zlib wrapper.
|
||||
ret = deflateInit2(&strm, Z_BEST_COMPRESSION, Z_DEFLATED, 15 + 16, 8, Z_DEFAULT_STRATEGY);
|
||||
|
||||
if (ret != Z_OK)
|
||||
return false;
|
||||
|
||||
while (strm.avail_in != 0) {
|
||||
ret = deflate(&strm, Z_NO_FLUSH);
|
||||
if (ret != Z_OK)
|
||||
return false;
|
||||
|
||||
if (strm.avail_out == 0) {
|
||||
dest_buffer.append(tmp_buf, BUFSIZE);
|
||||
strm.next_out = reinterpret_cast<unsigned char*>(tmp_buf);
|
||||
strm.avail_out = BUFSIZE;
|
||||
}
|
||||
}
|
||||
|
||||
int deflate_res = Z_OK;
|
||||
while (deflate_res == Z_OK) {
|
||||
if (strm.avail_out == 0) {
|
||||
dest_buffer.append(tmp_buf, BUFSIZE);
|
||||
strm.next_out = reinterpret_cast<unsigned char*>(tmp_buf);
|
||||
strm.avail_out = BUFSIZE;
|
||||
}
|
||||
|
||||
deflate_res = deflate(&strm, Z_FINISH);
|
||||
}
|
||||
|
||||
if (deflate_res != Z_STREAM_END)
|
||||
return false;
|
||||
|
||||
dest_buffer.append(tmp_buf, BUFSIZE - strm.avail_out);
|
||||
deflateEnd(&strm);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -36,23 +36,23 @@
|
|||
#include <QUrl>
|
||||
#include <QDebug>
|
||||
|
||||
#include <zlib.h>
|
||||
|
||||
#include "core/utils/fs.h"
|
||||
#include "core/utils/gzip.h"
|
||||
#include "core/utils/misc.h"
|
||||
#include "downloadmanager.h"
|
||||
#include "downloadhandler.h"
|
||||
|
||||
static QString errorCodeToString(QNetworkReply::NetworkError status);
|
||||
static QByteArray gUncompress(Bytef *inData, uInt len);
|
||||
|
||||
using namespace Net;
|
||||
|
||||
DownloadHandler::DownloadHandler(QNetworkReply *reply, DownloadManager *manager, qint64 limit)
|
||||
DownloadHandler::DownloadHandler(QNetworkReply *reply, DownloadManager *manager, bool saveToFile, qint64 limit, bool handleRedirectToMagnet)
|
||||
: QObject(manager)
|
||||
, m_reply(reply)
|
||||
, m_manager(manager)
|
||||
, m_saveToFile(saveToFile)
|
||||
, m_sizeLimit(limit)
|
||||
, m_handleRedirectToMagnet(handleRedirectToMagnet)
|
||||
, m_url(reply->url().toString())
|
||||
{
|
||||
init();
|
||||
|
@ -90,11 +90,23 @@ void DownloadHandler::processFinishedDownload()
|
|||
}
|
||||
else {
|
||||
// Success
|
||||
QString filePath;
|
||||
if (saveToFile(filePath))
|
||||
emit downloadFinished(m_url, filePath);
|
||||
else
|
||||
emit downloadFailed(m_url, tr("I/O Error"));
|
||||
QByteArray replyData = m_reply->readAll();
|
||||
if (m_reply->rawHeader("Content-Encoding") == "gzip") {
|
||||
// uncompress gzip reply
|
||||
Utils::Gzip::uncompress(replyData, replyData);
|
||||
}
|
||||
|
||||
if (m_saveToFile) {
|
||||
QString filePath;
|
||||
if (saveToFile(replyData, filePath))
|
||||
emit downloadFinished(m_url, filePath);
|
||||
else
|
||||
emit downloadFailed(m_url, tr("I/O Error"));
|
||||
}
|
||||
else {
|
||||
emit downloadFinished(m_url, replyData);
|
||||
}
|
||||
|
||||
this->deleteLater();
|
||||
}
|
||||
}
|
||||
|
@ -128,7 +140,7 @@ void DownloadHandler::init()
|
|||
connect(m_reply, SIGNAL(finished()), this, SLOT(processFinishedDownload()));
|
||||
}
|
||||
|
||||
bool DownloadHandler::saveToFile(QString &filePath)
|
||||
bool DownloadHandler::saveToFile(const QByteArray &replyData, QString &filePath)
|
||||
{
|
||||
QTemporaryFile *tmpfile = new QTemporaryFile;
|
||||
if (!tmpfile->open()) {
|
||||
|
@ -140,11 +152,6 @@ bool DownloadHandler::saveToFile(QString &filePath)
|
|||
filePath = tmpfile->fileName();
|
||||
qDebug("Temporary filename is: %s", qPrintable(filePath));
|
||||
if (m_reply->isOpen() || m_reply->open(QIODevice::ReadOnly)) {
|
||||
QByteArray replyData = m_reply->readAll();
|
||||
if (m_reply->rawHeader("Content-Encoding") == "gzip") {
|
||||
// uncompress gzip reply
|
||||
replyData = gUncompress(reinterpret_cast<unsigned char*>(replyData.data()), static_cast<uInt>(replyData.length()));
|
||||
}
|
||||
tmpfile->write(replyData);
|
||||
tmpfile->close();
|
||||
// XXX: tmpfile needs to be deleted on Windows before using the file
|
||||
|
@ -173,14 +180,20 @@ void DownloadHandler::handleRedirection(QUrl newUrl)
|
|||
if (newUrlString.startsWith("magnet:", Qt::CaseInsensitive)) {
|
||||
qDebug("Magnet redirect detected.");
|
||||
m_reply->abort();
|
||||
emit redirectedToMagnet(m_url, newUrlString);
|
||||
if (m_handleRedirectToMagnet)
|
||||
emit redirectedToMagnet(m_url, newUrlString);
|
||||
else
|
||||
emit downloadFailed(m_url, tr("Unexpected redirect to magnet URI."));
|
||||
|
||||
this->deleteLater();
|
||||
}
|
||||
else {
|
||||
DownloadHandler *tmp = m_manager->downloadUrl(newUrlString, m_sizeLimit);
|
||||
m_reply->deleteLater();
|
||||
m_reply = tmp->m_reply;
|
||||
m_saveToFile = tmp->m_saveToFile;
|
||||
m_sizeLimit = tmp->m_sizeLimit;
|
||||
m_handleRedirectToMagnet = tmp->m_handleRedirectToMagnet;
|
||||
init();
|
||||
tmp->m_reply = 0;
|
||||
delete tmp;
|
||||
|
@ -236,55 +249,3 @@ QString errorCodeToString(QNetworkReply::NetworkError status)
|
|||
return QObject::tr("Unknown error");
|
||||
}
|
||||
}
|
||||
|
||||
QByteArray gUncompress(Bytef *inData, uInt len)
|
||||
{
|
||||
if (len <= 4) {
|
||||
qWarning("gUncompress: Input data is truncated");
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
QByteArray result;
|
||||
|
||||
z_stream strm;
|
||||
static const int CHUNK_SIZE = 1024;
|
||||
char out[CHUNK_SIZE];
|
||||
|
||||
/* allocate inflate state */
|
||||
strm.zalloc = Z_NULL;
|
||||
strm.zfree = Z_NULL;
|
||||
strm.opaque = Z_NULL;
|
||||
strm.avail_in = len;
|
||||
strm.next_in = inData;
|
||||
|
||||
const int windowBits = 15;
|
||||
const int ENABLE_ZLIB_GZIP = 32;
|
||||
|
||||
int ret = inflateInit2(&strm, windowBits | ENABLE_ZLIB_GZIP); // gzip decoding
|
||||
if (ret != Z_OK)
|
||||
return QByteArray();
|
||||
|
||||
// run inflate()
|
||||
do {
|
||||
strm.avail_out = CHUNK_SIZE;
|
||||
strm.next_out = reinterpret_cast<unsigned char*>(out);
|
||||
|
||||
ret = inflate(&strm, Z_NO_FLUSH);
|
||||
Q_ASSERT(ret != Z_STREAM_ERROR); // state not clobbered
|
||||
|
||||
switch (ret) {
|
||||
case Z_NEED_DICT:
|
||||
case Z_DATA_ERROR:
|
||||
case Z_MEM_ERROR:
|
||||
(void) inflateEnd(&strm);
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
result.append(out, CHUNK_SIZE - strm.avail_out);
|
||||
}
|
||||
while (!strm.avail_out);
|
||||
|
||||
// clean up and return
|
||||
inflateEnd(&strm);
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -47,12 +47,13 @@ namespace Net
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
DownloadHandler(QNetworkReply *reply, DownloadManager *manager, qint64 limit = 0);
|
||||
DownloadHandler(QNetworkReply *reply, DownloadManager *manager, bool saveToFile = false, qint64 limit = 0, bool handleRedirectToMagnet = false);
|
||||
~DownloadHandler();
|
||||
|
||||
QString url() const;
|
||||
|
||||
signals:
|
||||
void downloadFinished(const QString &url, const QByteArray &data);
|
||||
void downloadFinished(const QString &url, const QString &filePath);
|
||||
void downloadFailed(const QString &url, const QString &reason);
|
||||
void redirectedToMagnet(const QString &url, const QString &magnetUri);
|
||||
|
@ -63,12 +64,14 @@ namespace Net
|
|||
|
||||
private:
|
||||
void init();
|
||||
bool saveToFile(QString &filePath);
|
||||
bool saveToFile(const QByteArray &replyData, QString &filePath);
|
||||
void handleRedirection(QUrl newUrl);
|
||||
|
||||
QNetworkReply *m_reply;
|
||||
DownloadManager *m_manager;
|
||||
bool m_saveToFile;
|
||||
qint64 m_sizeLimit;
|
||||
bool m_handleRedirectToMagnet;
|
||||
QString m_url;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -75,7 +75,7 @@ DownloadManager *DownloadManager::instance()
|
|||
return m_instance;
|
||||
}
|
||||
|
||||
DownloadHandler *DownloadManager::downloadUrl(const QString &url, qint64 limit)
|
||||
DownloadHandler *DownloadManager::downloadUrl(const QString &url, bool saveToFile, qint64 limit, bool handleRedirectToMagnet)
|
||||
{
|
||||
// Update proxy settings
|
||||
applyProxySettings();
|
||||
|
@ -91,7 +91,7 @@ DownloadHandler *DownloadManager::downloadUrl(const QString &url, qint64 limit)
|
|||
qDebug("Downloading %s...", request.url().toEncoded().data());
|
||||
// accept gzip
|
||||
request.setRawHeader("Accept-Encoding", "gzip");
|
||||
return new DownloadHandler(m_networkManager.get(request), this, limit);
|
||||
return new DownloadHandler(m_networkManager.get(request), this, saveToFile, limit, handleRedirectToMagnet);
|
||||
}
|
||||
|
||||
QList<QNetworkCookie> DownloadManager::cookiesForUrl(const QString &url) const
|
||||
|
|
|
@ -53,7 +53,7 @@ namespace Net
|
|||
static void freeInstance();
|
||||
static DownloadManager *instance();
|
||||
|
||||
DownloadHandler *downloadUrl(const QString &url, qint64 limit = 0);
|
||||
DownloadHandler *downloadUrl(const QString &url, bool saveToFile = false, qint64 limit = 0, bool handleRedirectToMagnet = false);
|
||||
QList<QNetworkCookie> cookiesForUrl(const QString &url) const;
|
||||
bool setCookiesFromUrl(const QList<QNetworkCookie> &cookieList, const QUrl &url);
|
||||
|
||||
|
|
464
src/core/net/geoipmanager.cpp
Normal file
464
src/core/net/geoipmanager.cpp
Normal file
|
@ -0,0 +1,464 @@
|
|||
/*
|
||||
* 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 <QDebug>
|
||||
#include <QFile>
|
||||
#include <QDir>
|
||||
#include <QHostAddress>
|
||||
#include <QDateTime>
|
||||
|
||||
#include "core/logger.h"
|
||||
#include "core/preferences.h"
|
||||
#include "core/utils/fs.h"
|
||||
#include "core/utils/gzip.h"
|
||||
#include "downloadmanager.h"
|
||||
#include "downloadhandler.h"
|
||||
#include "private/geoipdatabase.h"
|
||||
#include "geoipmanager.h"
|
||||
|
||||
static const char DATABASE_URL[] = "http://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 CACHE_SIZE = 1000;
|
||||
static const int UPDATE_INTERVAL = 30; // Days between database updates
|
||||
|
||||
using namespace Net;
|
||||
|
||||
// GeoIPManager
|
||||
|
||||
GeoIPManager *GeoIPManager::m_instance = 0;
|
||||
|
||||
GeoIPManager::GeoIPManager()
|
||||
: m_enabled(false)
|
||||
, m_geoIPDatabase(0)
|
||||
, m_cache(CACHE_SIZE)
|
||||
{
|
||||
configure();
|
||||
connect(Preferences::instance(), SIGNAL(changed()), SLOT(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 = 0;
|
||||
}
|
||||
}
|
||||
|
||||
GeoIPManager *GeoIPManager::instance()
|
||||
{
|
||||
return m_instance;
|
||||
}
|
||||
|
||||
void GeoIPManager::loadDatabase()
|
||||
{
|
||||
if (m_geoIPDatabase) {
|
||||
delete m_geoIPDatabase;
|
||||
m_geoIPDatabase = 0;
|
||||
}
|
||||
|
||||
QString filepath = Utils::Fs::expandPathAbs(
|
||||
QString("%1%2/%3").arg(Utils::Fs::QDesktopServicesDataLocation())
|
||||
.arg(GEOIP_FOLDER).arg(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()).arg(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()
|
||||
{
|
||||
DownloadHandler *handler = DownloadManager::instance()->downloadUrl(DATABASE_URL);
|
||||
connect(handler, SIGNAL(downloadFinished(QString, QByteArray)), SLOT(downloadFinished(QString, QByteArray)));
|
||||
connect(handler, SIGNAL(downloadFailed(QString, QString)), SLOT(downloadFailed(QString, QString)));
|
||||
}
|
||||
|
||||
QString GeoIPManager::lookup(const QHostAddress &hostAddr) const
|
||||
{
|
||||
if (m_enabled && m_geoIPDatabase) {
|
||||
QString *country = m_cache.object(hostAddr);
|
||||
if (country)
|
||||
return *country;
|
||||
|
||||
QString code = m_geoIPDatabase->lookup(hostAddr);
|
||||
m_cache.insert(hostAddr, new QString(code));
|
||||
return code;
|
||||
}
|
||||
|
||||
return QString();
|
||||
}
|
||||
|
||||
// http://www.iso.org/iso/country_codes/iso_3166_code_lists/english_country_names_and_code_elements.htm
|
||||
QString GeoIPManager::CountryName(const QString &countryISOCode)
|
||||
{
|
||||
static QHash<QString, QString> countries;
|
||||
static bool initialized = false;
|
||||
|
||||
if (!initialized) {
|
||||
countries[QString()] = "N/A";
|
||||
countries["AP"] = "Asia/Pacific Region";
|
||||
countries["EU"] = "Europe";
|
||||
countries["AD"] = "Andorra";
|
||||
countries["AE"] = "United Arab Emirates";
|
||||
countries["AF"] = "Afghanistan";
|
||||
countries["AG"] = "Antigua and Barbuda";
|
||||
countries["AI"] = "Anguilla";
|
||||
countries["AL"] = "Albania";
|
||||
countries["AM"] = "Armenia";
|
||||
countries["AN"] = "Netherlands Antilles";
|
||||
countries["AO"] = "Angola";
|
||||
countries["AQ"] = "Antarctica";
|
||||
countries["AR"] = "Argentina";
|
||||
countries["AS"] = "American Samoa";
|
||||
countries["AT"] = "Austria";
|
||||
countries["AU"] = "Australia";
|
||||
countries["AW"] = "Aruba";
|
||||
countries["AZ"] = "Azerbaijan";
|
||||
countries["BA"] = "Bosnia and Herzegovina";
|
||||
countries["BB"] = "Barbados";
|
||||
countries["BD"] = "Bangladesh";
|
||||
countries["BE"] = "Belgium";
|
||||
countries["BF"] = "Burkina Faso";
|
||||
countries["BG"] = "Bulgaria";
|
||||
countries["BH"] = "Bahrain";
|
||||
countries["BI"] = "Burundi";
|
||||
countries["BJ"] = "Benin";
|
||||
countries["BM"] = "Bermuda";
|
||||
countries["BN"] = "Brunei Darussalam";
|
||||
countries["BO"] = "Bolivia";
|
||||
countries["BR"] = "Brazil";
|
||||
countries["BS"] = "Bahamas";
|
||||
countries["BT"] = "Bhutan";
|
||||
countries["BV"] = "Bouvet Island";
|
||||
countries["BW"] = "Botswana";
|
||||
countries["BY"] = "Belarus";
|
||||
countries["BZ"] = "Belize";
|
||||
countries["CA"] = "Canada";
|
||||
countries["CC"] = "Cocos (Keeling) Islands";
|
||||
countries["CD"] = "Congo, The Democratic Republic of the";
|
||||
countries["CF"] = "Central African Republic";
|
||||
countries["CG"] = "Congo";
|
||||
countries["CH"] = "Switzerland";
|
||||
countries["CI"] = "Cote D'Ivoire";
|
||||
countries["CK"] = "Cook Islands";
|
||||
countries["CL"] = "Chile";
|
||||
countries["CM"] = "Cameroon";
|
||||
countries["CN"] = "China";
|
||||
countries["CO"] = "Colombia";
|
||||
countries["CR"] = "Costa Rica";
|
||||
countries["CU"] = "Cuba";
|
||||
countries["CV"] = "Cape Verde";
|
||||
countries["CX"] = "Christmas Island";
|
||||
countries["CY"] = "Cyprus";
|
||||
countries["CZ"] = "Czech Republic";
|
||||
countries["DE"] = "Germany";
|
||||
countries["DJ"] = "Djibouti";
|
||||
countries["DK"] = "Denmark";
|
||||
countries["DM"] = "Dominica";
|
||||
countries["DO"] = "Dominican Republic";
|
||||
countries["DZ"] = "Algeria";
|
||||
countries["EC"] = "Ecuador";
|
||||
countries["EE"] = "Estonia";
|
||||
countries["EG"] = "Egypt";
|
||||
countries["EH"] = "Western Sahara";
|
||||
countries["ER"] = "Eritrea";
|
||||
countries["ES"] = "Spain";
|
||||
countries["ET"] = "Ethiopia";
|
||||
countries["FI"] = "Finland";
|
||||
countries["FJ"] = "Fiji";
|
||||
countries["FK"] = "Falkland Islands (Malvinas)";
|
||||
countries["FM"] = "Micronesia, Federated States of";
|
||||
countries["FO"] = "Faroe Islands";
|
||||
countries["FR"] = "France";
|
||||
countries["FX"] = "France, Metropolitan";
|
||||
countries["GA"] = "Gabon";
|
||||
countries["GB"] = "United Kingdom";
|
||||
countries["GD"] = "Grenada";
|
||||
countries["GE"] = "Georgia";
|
||||
countries["GF"] = "French Guiana";
|
||||
countries["GH"] = "Ghana";
|
||||
countries["GI"] = "Gibraltar";
|
||||
countries["GL"] = "Greenland";
|
||||
countries["GM"] = "Gambia";
|
||||
countries["GN"] = "Guinea";
|
||||
countries["GP"] = "Guadeloupe";
|
||||
countries["GQ"] = "Equatorial Guinea";
|
||||
countries["GR"] = "Greece";
|
||||
countries["GS"] = "South Georgia and the South Sandwich Islands";
|
||||
countries["GT"] = "Guatemala";
|
||||
countries["GU"] = "Guam";
|
||||
countries["GW"] = "Guinea-Bissau";
|
||||
countries["GY"] = "Guyana";
|
||||
countries["HK"] = "Hong Kong";
|
||||
countries["HM"] = "Heard Island and McDonald Islands";
|
||||
countries["HN"] = "Honduras";
|
||||
countries["HR"] = "Croatia";
|
||||
countries["HT"] = "Haiti";
|
||||
countries["HU"] = "Hungary";
|
||||
countries["ID"] = "Indonesia";
|
||||
countries["IE"] = "Ireland";
|
||||
countries["IL"] = "Israel";
|
||||
countries["IN"] = "India";
|
||||
countries["IO"] = "British Indian Ocean Territory";
|
||||
countries["IQ"] = "Iraq";
|
||||
countries["IR"] = "Iran, Islamic Republic of";
|
||||
countries["IS"] = "Iceland";
|
||||
countries["IT"] = "Italy";
|
||||
countries["JM"] = "Jamaica";
|
||||
countries["JO"] = "Jordan";
|
||||
countries["JP"] = "Japan";
|
||||
countries["KE"] = "Kenya";
|
||||
countries["KG"] = "Kyrgyzstan";
|
||||
countries["KH"] = "Cambodia";
|
||||
countries["KI"] = "Kiribati";
|
||||
countries["KM"] = "Comoros";
|
||||
countries["KN"] = "Saint Kitts and Nevis";
|
||||
countries["KP"] = "Korea, Democratic People's Republic of";
|
||||
countries["KR"] = "Korea, Republic of";
|
||||
countries["KW"] = "Kuwait";
|
||||
countries["KY"] = "Cayman Islands";
|
||||
countries["KZ"] = "Kazakhstan";
|
||||
countries["LA"] = "Lao People's Democratic Republic";
|
||||
countries["LB"] = "Lebanon";
|
||||
countries["LC"] = "Saint Lucia";
|
||||
countries["LI"] = "Liechtenstein";
|
||||
countries["LK"] = "Sri Lanka";
|
||||
countries["LR"] = "Liberia";
|
||||
countries["LS"] = "Lesotho";
|
||||
countries["LT"] = "Lithuania";
|
||||
countries["LU"] = "Luxembourg";
|
||||
countries["LV"] = "Latvia";
|
||||
countries["LY"] = "Libyan Arab Jamahiriya";
|
||||
countries["MA"] = "Morocco";
|
||||
countries["MC"] = "Monaco";
|
||||
countries["MD"] = "Moldova, Republic of";
|
||||
countries["MG"] = "Madagascar";
|
||||
countries["MH"] = "Marshall Islands";
|
||||
countries["MK"] = "Macedonia";
|
||||
countries["ML"] = "Mali";
|
||||
countries["MM"] = "Myanmar";
|
||||
countries["MN"] = "Mongolia";
|
||||
countries["MO"] = "Macau";
|
||||
countries["MP"] = "Northern Mariana Islands";
|
||||
countries["MQ"] = "Martinique";
|
||||
countries["MR"] = "Mauritania";
|
||||
countries["MS"] = "Montserrat";
|
||||
countries["MT"] = "Malta";
|
||||
countries["MU"] = "Mauritius";
|
||||
countries["MV"] = "Maldives";
|
||||
countries["MW"] = "Malawi";
|
||||
countries["MX"] = "Mexico";
|
||||
countries["MY"] = "Malaysia";
|
||||
countries["MZ"] = "Mozambique";
|
||||
countries["NA"] = "Namibia";
|
||||
countries["NC"] = "New Caledonia";
|
||||
countries["NE"] = "Niger";
|
||||
countries["NF"] = "Norfolk Island";
|
||||
countries["NG"] = "Nigeria";
|
||||
countries["NI"] = "Nicaragua";
|
||||
countries["NL"] = "Netherlands";
|
||||
countries["NO"] = "Norway";
|
||||
countries["NP"] = "Nepal";
|
||||
countries["NR"] = "Nauru";
|
||||
countries["NU"] = "Niue";
|
||||
countries["NZ"] = "New Zealand";
|
||||
countries["OM"] = "Oman";
|
||||
countries["PA"] = "Panama";
|
||||
countries["PE"] = "Peru";
|
||||
countries["PF"] = "French Polynesia";
|
||||
countries["PG"] = "Papua New Guinea";
|
||||
countries["PH"] = "Philippines";
|
||||
countries["PK"] = "Pakistan";
|
||||
countries["PL"] = "Poland";
|
||||
countries["PM"] = "Saint Pierre and Miquelon";
|
||||
countries["PN"] = "Pitcairn Islands";
|
||||
countries["PR"] = "Puerto Rico";
|
||||
countries["PS"] = "Palestinian Territory";
|
||||
countries["PT"] = "Portugal";
|
||||
countries["PW"] = "Palau";
|
||||
countries["PY"] = "Paraguay";
|
||||
countries["QA"] = "Qatar";
|
||||
countries["RE"] = "Reunion";
|
||||
countries["RO"] = "Romania";
|
||||
countries["RU"] = "Russian Federation";
|
||||
countries["RW"] = "Rwanda";
|
||||
countries["SA"] = "Saudi Arabia";
|
||||
countries["SB"] = "Solomon Islands";
|
||||
countries["SC"] = "Seychelles";
|
||||
countries["SD"] = "Sudan";
|
||||
countries["SE"] = "Sweden";
|
||||
countries["SG"] = "Singapore";
|
||||
countries["SH"] = "Saint Helena";
|
||||
countries["SI"] = "Slovenia";
|
||||
countries["SJ"] = "Svalbard and Jan Mayen";
|
||||
countries["SK"] = "Slovakia";
|
||||
countries["SL"] = "Sierra Leone";
|
||||
countries["SM"] = "San Marino";
|
||||
countries["SN"] = "Senegal";
|
||||
countries["SO"] = "Somalia";
|
||||
countries["SR"] = "Suriname";
|
||||
countries["ST"] = "Sao Tome and Principe";
|
||||
countries["SV"] = "El Salvador";
|
||||
countries["SY"] = "Syrian Arab Republic";
|
||||
countries["SZ"] = "Swaziland";
|
||||
countries["TC"] = "Turks and Caicos Islands";
|
||||
countries["TD"] = "Chad";
|
||||
countries["TF"] = "French Southern Territories";
|
||||
countries["TG"] = "Togo";
|
||||
countries["TH"] = "Thailand";
|
||||
countries["TJ"] = "Tajikistan";
|
||||
countries["TK"] = "Tokelau";
|
||||
countries["TM"] = "Turkmenistan";
|
||||
countries["TN"] = "Tunisia";
|
||||
countries["TO"] = "Tonga";
|
||||
countries["TL"] = "Timor-Leste";
|
||||
countries["TR"] = "Turkey";
|
||||
countries["TT"] = "Trinidad and Tobago";
|
||||
countries["TV"] = "Tuvalu";
|
||||
countries["TW"] = "Taiwan";
|
||||
countries["TZ"] = "Tanzania, United Republic of";
|
||||
countries["UA"] = "Ukraine";
|
||||
countries["UG"] = "Uganda";
|
||||
countries["UM"] = "United States Minor Outlying Islands";
|
||||
countries["US"] = "United States";
|
||||
countries["UY"] = "Uruguay";
|
||||
countries["UZ"] = "Uzbekistan";
|
||||
countries["VA"] = "Holy See (Vatican City State)";
|
||||
countries["VC"] = "Saint Vincent and the Grenadines";
|
||||
countries["VE"] = "Venezuela";
|
||||
countries["VG"] = "Virgin Islands, British";
|
||||
countries["VI"] = "Virgin Islands, U.S.";
|
||||
countries["VN"] = "Vietnam";
|
||||
countries["VU"] = "Vanuatu";
|
||||
countries["WF"] = "Wallis and Futuna";
|
||||
countries["WS"] = "Samoa";
|
||||
countries["YE"] = "Yemen";
|
||||
countries["YT"] = "Mayotte";
|
||||
countries["RS"] = "Serbia";
|
||||
countries["ZA"] = "South Africa";
|
||||
countries["ZM"] = "Zambia";
|
||||
countries["ME"] = "Montenegro";
|
||||
countries["ZW"] = "Zimbabwe";
|
||||
countries["A1"] = "Anonymous Proxy";
|
||||
countries["A2"] = "Satellite Provider";
|
||||
countries["O1"] = "Other";
|
||||
countries["AX"] = "Aland Islands";
|
||||
countries["GG"] = "Guernsey";
|
||||
countries["IM"] = "Isle of Man";
|
||||
countries["JE"] = "Jersey";
|
||||
countries["BL"] = "Saint Barthelemy";
|
||||
countries["MF"] = "Saint Martin";
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
return countries.value(countryISOCode, "N/A");
|
||||
}
|
||||
|
||||
void GeoIPManager::configure()
|
||||
{
|
||||
const bool enabled = Preferences::instance()->resolvePeerCountries();
|
||||
if (m_enabled != enabled) {
|
||||
m_enabled = enabled;
|
||||
if (m_enabled && !m_geoIPDatabase)
|
||||
loadDatabase();
|
||||
}
|
||||
}
|
||||
|
||||
void GeoIPManager::downloadFinished(const QString &url, QByteArray data)
|
||||
{
|
||||
Q_UNUSED(url);
|
||||
|
||||
if (!Utils::Gzip::uncompress(data, data)) {
|
||||
Logger::instance()->addMessage(tr("Could not uncompress 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;
|
||||
Logger::instance()->addMessage(tr("GeoIP database loaded. Type: %1. Build time: %2.")
|
||||
.arg(m_geoIPDatabase->type()).arg(m_geoIPDatabase->buildEpoch().toString()),
|
||||
Log::INFO);
|
||||
QString targetPath = Utils::Fs::expandPathAbs(
|
||||
Utils::Fs::QDesktopServicesDataLocation() + GEOIP_FOLDER);
|
||||
if (!QDir(targetPath).exists())
|
||||
QDir().mkpath(targetPath);
|
||||
QFile targetFile(QString("%1/%2").arg(targetPath).arg(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);
|
||||
}
|
||||
}
|
||||
else {
|
||||
delete geoIPDatabase;
|
||||
}
|
||||
}
|
||||
else {
|
||||
Logger::instance()->addMessage(tr("Couldn't load GeoIP database. Reason: %1").arg(error), Log::WARNING);
|
||||
}
|
||||
}
|
||||
|
||||
void GeoIPManager::downloadFailed(const QString &url, const QString &reason)
|
||||
{
|
||||
Q_UNUSED(url);
|
||||
Logger::instance()->addMessage(tr("Couldn't download GeoIP database file. Reason: %1").arg(reason), Log::WARNING);
|
||||
}
|
77
src/core/net/geoipmanager.h
Normal file
77
src/core/net/geoipmanager.h
Normal file
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef NET_GEOIPMANAGER_H
|
||||
#define NET_GEOIPMANAGER_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QCache>
|
||||
|
||||
class QHostAddress;
|
||||
class QString;
|
||||
|
||||
class GeoIPDatabase;
|
||||
|
||||
namespace Net
|
||||
{
|
||||
class GeoIPManager : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
static void initInstance();
|
||||
static void freeInstance();
|
||||
static GeoIPManager *instance();
|
||||
|
||||
QString lookup(const QHostAddress &hostAddr) const;
|
||||
|
||||
static QString CountryName(const QString &countryISOCode);
|
||||
|
||||
private slots:
|
||||
void configure();
|
||||
void downloadFinished(const QString &url, QByteArray data);
|
||||
void downloadFailed(const QString &url, const QString &reason);
|
||||
|
||||
private:
|
||||
GeoIPManager();
|
||||
~GeoIPManager();
|
||||
|
||||
void loadDatabase();
|
||||
void manageDatabaseUpdate();
|
||||
void downloadDatabaseFile();
|
||||
|
||||
bool m_enabled;
|
||||
GeoIPDatabase *m_geoIPDatabase;
|
||||
mutable QCache<QHostAddress, QString> m_cache;
|
||||
|
||||
static GeoIPManager *m_instance;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // NET_GEOIPMANAGER_H
|
631
src/core/net/private/geoipdatabase.cpp
Normal file
631
src/core/net/private/geoipdatabase.cpp
Normal file
|
@ -0,0 +1,631 @@
|
|||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2015 Vladimir Golovnev <glassez@yandex.ru>
|
||||
*
|
||||
* 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 <QDebug>
|
||||
#include <QCoreApplication>
|
||||
#include <QVariant>
|
||||
#include <QHash>
|
||||
#include <QList>
|
||||
#include <QScopedArrayPointer>
|
||||
#include <QScopedPointer>
|
||||
#include <QHostAddress>
|
||||
#include <QDateTime>
|
||||
#include <QFile>
|
||||
|
||||
#include "core/types.h"
|
||||
#include "geoipdatabase.h"
|
||||
|
||||
struct Node
|
||||
{
|
||||
quint32 left;
|
||||
quint32 right;
|
||||
};
|
||||
|
||||
struct GeoIPData
|
||||
{
|
||||
// Metadata
|
||||
quint16 ipVersion;
|
||||
quint16 recordSize;
|
||||
quint32 nodeCount;
|
||||
QDateTime buildEpoch;
|
||||
// Search data
|
||||
QList<Node> index;
|
||||
QHash<quint32, QString> countries;
|
||||
};
|
||||
|
||||
namespace
|
||||
{
|
||||
const quint32 __ENDIAN_TEST__ = 0x00000001;
|
||||
const bool __IS_LITTLE_ENDIAN__ = (reinterpret_cast<const uchar *>(&__ENDIAN_TEST__)[0] == 0x01);
|
||||
|
||||
BEGIN_SCOPED_ENUM(DataType)
|
||||
{
|
||||
Unknown = 0,
|
||||
Pointer = 1,
|
||||
String = 2,
|
||||
Double = 3,
|
||||
Bytes = 4,
|
||||
Integer16 = 5,
|
||||
Integer32 = 6,
|
||||
Map = 7,
|
||||
SignedInteger32 = 8,
|
||||
Integer64 = 9,
|
||||
Integer128 = 10,
|
||||
Array = 11,
|
||||
DataCacheContainer = 12,
|
||||
EndMarker = 13,
|
||||
Boolean = 14,
|
||||
Float = 15
|
||||
}
|
||||
END_SCOPED_ENUM
|
||||
|
||||
struct DataFieldDescriptor
|
||||
{
|
||||
DataType fieldType;
|
||||
union
|
||||
{
|
||||
quint32 fieldSize;
|
||||
quint32 offset; // Pointer
|
||||
};
|
||||
};
|
||||
|
||||
const int MAX_FILE_SIZE = 10485760; // 10MB
|
||||
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 };
|
||||
|
||||
#if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0))
|
||||
Q_IPV6ADDR createMappedAddress(quint32 ip4);
|
||||
#endif
|
||||
|
||||
class Loader
|
||||
{
|
||||
Q_DECLARE_TR_FUNCTIONS(GeoIPDatabase)
|
||||
|
||||
public:
|
||||
GeoIPData *load(const QString &filename);
|
||||
GeoIPData *load(const QByteArray &data);
|
||||
QString error() const;
|
||||
|
||||
private:
|
||||
bool parseMetadata(const QVariantHash &metadata);
|
||||
bool loadDB();
|
||||
QVariantHash readMetadata();
|
||||
QVariant readDataField(quint32 &offset);
|
||||
bool readDataFieldDescriptor(quint32 &offset, DataFieldDescriptor &out);
|
||||
void fromBigEndian(uchar *buf, quint32 len);
|
||||
QVariant readMapValue(quint32 &offset, quint32 count);
|
||||
QVariant readArrayValue(quint32 &offset, quint32 count);
|
||||
|
||||
template<typename T>
|
||||
QVariant readPlainValue(quint32 &offset, quint8 len)
|
||||
{
|
||||
T value = 0;
|
||||
const uchar *const data = m_data + offset;
|
||||
const quint32 availSize = m_size - offset;
|
||||
|
||||
if ((len > 0) && (len <= sizeof(T) && (availSize >= len))) {
|
||||
// copy input data to last 'len' bytes of 'value'
|
||||
uchar *dst = reinterpret_cast<uchar *>(&value) + (sizeof(T) - len);
|
||||
memcpy(dst, data, len);
|
||||
fromBigEndian(reinterpret_cast<uchar *>(&value), sizeof(T));
|
||||
offset += len;
|
||||
}
|
||||
|
||||
return QVariant::fromValue(value);
|
||||
}
|
||||
|
||||
private:
|
||||
const uchar *m_data;
|
||||
quint32 m_size;
|
||||
QString m_error;
|
||||
GeoIPData *m_geoIPData;
|
||||
};
|
||||
}
|
||||
|
||||
// GeoIPDatabase
|
||||
|
||||
GeoIPDatabase::GeoIPDatabase(GeoIPData *geoIPData)
|
||||
: m_geoIPData(geoIPData)
|
||||
{
|
||||
}
|
||||
|
||||
GeoIPDatabase *GeoIPDatabase::load(const QString &filename, QString &error)
|
||||
{
|
||||
GeoIPDatabase *db = 0;
|
||||
|
||||
Loader loader;
|
||||
GeoIPData *geoIPData = loader.load(filename);
|
||||
if (!geoIPData)
|
||||
error = loader.error();
|
||||
else
|
||||
db = new GeoIPDatabase(geoIPData);
|
||||
|
||||
return db;
|
||||
}
|
||||
|
||||
GeoIPDatabase *GeoIPDatabase::load(const QByteArray &data, QString &error)
|
||||
{
|
||||
GeoIPDatabase *db = 0;
|
||||
|
||||
Loader loader;
|
||||
GeoIPData *geoIPData = loader.load(data);
|
||||
if (!geoIPData)
|
||||
error = loader.error();
|
||||
else
|
||||
db = new GeoIPDatabase(geoIPData);
|
||||
|
||||
return db;
|
||||
}
|
||||
|
||||
GeoIPDatabase::~GeoIPDatabase()
|
||||
{
|
||||
delete m_geoIPData;
|
||||
}
|
||||
|
||||
QString GeoIPDatabase::type() const
|
||||
{
|
||||
return DB_TYPE;
|
||||
}
|
||||
|
||||
quint16 GeoIPDatabase::ipVersion() const
|
||||
{
|
||||
return m_geoIPData->ipVersion;
|
||||
}
|
||||
|
||||
QDateTime GeoIPDatabase::buildEpoch() const
|
||||
{
|
||||
return m_geoIPData->buildEpoch;
|
||||
}
|
||||
|
||||
QString GeoIPDatabase::lookup(const QHostAddress &hostAddr) const
|
||||
{
|
||||
#if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0))
|
||||
Q_IPV6ADDR addr = hostAddr.protocol() == QAbstractSocket::IPv4Protocol
|
||||
? createMappedAddress(hostAddr.toIPv4Address())
|
||||
: hostAddr.toIPv6Address();
|
||||
#else
|
||||
Q_IPV6ADDR addr = hostAddr.toIPv6Address();
|
||||
#endif
|
||||
const quint32 nodeCount = static_cast<quint32>(m_geoIPData->index.size());
|
||||
Node node = m_geoIPData->index[0];
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
for (int j = 0; j < 8; ++j) {
|
||||
bool right = static_cast<bool>((addr[i] >> (7 - j)) & 1);
|
||||
quint32 id = (right ? node.right : node.left);
|
||||
if (id == nodeCount)
|
||||
return QString();
|
||||
else if (id > nodeCount)
|
||||
return m_geoIPData->countries[id];
|
||||
else
|
||||
node = m_geoIPData->index[id];
|
||||
}
|
||||
}
|
||||
|
||||
return QString();
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
// Loader
|
||||
|
||||
GeoIPData *Loader::load(const QString &filename)
|
||||
{
|
||||
QFile file(filename);
|
||||
if (file.size() > MAX_FILE_SIZE) {
|
||||
m_error = tr("Unsupported database file size.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!file.open(QFile::ReadOnly)) {
|
||||
m_error = file.errorString();
|
||||
return 0;
|
||||
}
|
||||
|
||||
m_size = file.size();
|
||||
QScopedArrayPointer<uchar> data(new uchar[m_size]);
|
||||
m_data = data.data();
|
||||
if (file.read((char *)m_data, m_size) != m_size) {
|
||||
m_error = file.errorString();
|
||||
return 0;
|
||||
}
|
||||
|
||||
QScopedPointer<GeoIPData> geoIPData(new GeoIPData);
|
||||
m_geoIPData = geoIPData.data();
|
||||
if (!parseMetadata(readMetadata()) || !loadDB())
|
||||
return 0;
|
||||
|
||||
return geoIPData.take();
|
||||
}
|
||||
|
||||
GeoIPData *Loader::load(const QByteArray &data)
|
||||
{
|
||||
if (data.size() > MAX_FILE_SIZE) {
|
||||
m_error = tr("Unsupported database file size.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
m_size = data.size();
|
||||
m_data = reinterpret_cast<const uchar *>(data.constData());
|
||||
|
||||
QScopedPointer<GeoIPData> geoIPData(new GeoIPData);
|
||||
m_geoIPData = geoIPData.data();
|
||||
if (!parseMetadata(readMetadata()) || !loadDB())
|
||||
return 0;
|
||||
|
||||
return geoIPData.take();
|
||||
}
|
||||
|
||||
QString Loader::error() const
|
||||
{
|
||||
return m_error;
|
||||
}
|
||||
|
||||
#define CHECK_METADATA_REQ(key, type) \
|
||||
if (!metadata.contains(#key)) { \
|
||||
m_error = errMsgNotFound.arg(#key); \
|
||||
return false; \
|
||||
} \
|
||||
else if (metadata.value(#key).userType() != QMetaType::type) { \
|
||||
m_error = errMsgInvalid.arg(#key); \
|
||||
return false; \
|
||||
}
|
||||
|
||||
#define CHECK_METADATA_OPT(key, type) \
|
||||
if (metadata.contains(#key)) { \
|
||||
if (metadata.value(#key).userType() != QMetaType::type) { \
|
||||
m_error = errMsgInvalid.arg(#key); \
|
||||
return false; \
|
||||
} \
|
||||
}
|
||||
|
||||
bool Loader::parseMetadata(const QVariantHash &metadata)
|
||||
{
|
||||
const QString errMsgNotFound = tr("Metadata error: '%1' entry not found.");
|
||||
const QString errMsgInvalid = tr("Metadata error: '%1' entry has invalid type.");
|
||||
|
||||
qDebug() << "Parsing MaxMindDB metadata...";
|
||||
|
||||
CHECK_METADATA_REQ(binary_format_major_version, UShort);
|
||||
CHECK_METADATA_REQ(binary_format_minor_version, UShort);
|
||||
uint versionMajor = metadata.value("binary_format_major_version").toUInt();
|
||||
uint versionMinor = metadata.value("binary_format_minor_version").toUInt();
|
||||
if (versionMajor != 2) {
|
||||
m_error = tr("Unsupported database version: %1.%2").arg(versionMajor).arg(versionMinor);
|
||||
return false;
|
||||
}
|
||||
|
||||
CHECK_METADATA_REQ(ip_version, UShort);
|
||||
m_geoIPData->ipVersion = metadata.value("ip_version").value<quint16>();
|
||||
if (m_geoIPData->ipVersion != 6) {
|
||||
m_error = tr("Unsupported IP version: %1").arg(m_geoIPData->ipVersion);
|
||||
return false;
|
||||
}
|
||||
|
||||
CHECK_METADATA_REQ(record_size, UShort);
|
||||
m_geoIPData->recordSize = metadata.value("record_size").value<quint16>();
|
||||
if (m_geoIPData->recordSize != 24) {
|
||||
m_error = tr("Unsupported record size: %1").arg(m_geoIPData->recordSize);
|
||||
return false;
|
||||
}
|
||||
|
||||
CHECK_METADATA_REQ(node_count, UInt);
|
||||
m_geoIPData->nodeCount = metadata.value("node_count").value<quint32>();
|
||||
|
||||
CHECK_METADATA_REQ(database_type, QString);
|
||||
QString dbType = metadata.value("database_type").toString();
|
||||
if (dbType != DB_TYPE) {
|
||||
m_error = tr("Invalid database type: %1").arg(dbType);
|
||||
return false;
|
||||
}
|
||||
|
||||
CHECK_METADATA_REQ(build_epoch, ULongLong);
|
||||
m_geoIPData->buildEpoch = QDateTime::fromTime_t(metadata.value("build_epoch").toULongLong());
|
||||
|
||||
CHECK_METADATA_OPT(languages, QVariantList);
|
||||
CHECK_METADATA_OPT(description, QVariantHash);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Loader::loadDB()
|
||||
{
|
||||
qDebug() << "Parsing MaxMindDB index tree...";
|
||||
|
||||
const int nodeSize = m_geoIPData->recordSize / 4; // in bytes
|
||||
const int indexSize = m_geoIPData->nodeCount * nodeSize;
|
||||
if ((m_size < (indexSize + sizeof(DATA_SECTION_SEPARATOR)))
|
||||
|| (memcmp(m_data + indexSize, DATA_SECTION_SEPARATOR, sizeof(DATA_SECTION_SEPARATOR)) != 0)) {
|
||||
m_error = tr("Database corrupted: no data section found.");
|
||||
return false;
|
||||
}
|
||||
|
||||
m_geoIPData->index.reserve(m_geoIPData->nodeCount);
|
||||
|
||||
const int recordBytes = nodeSize / 2;
|
||||
const uchar *ptr = m_data;
|
||||
bool left = true;
|
||||
Node node;
|
||||
for (quint32 i = 0; i < (2 * m_geoIPData->nodeCount); ++i) {
|
||||
uchar buf[4] = { 0 };
|
||||
|
||||
memcpy(&buf[4 - recordBytes], ptr, recordBytes);
|
||||
fromBigEndian(buf, 4);
|
||||
quint32 id = *(reinterpret_cast<quint32 *>(buf));
|
||||
|
||||
if ((id > m_geoIPData->nodeCount) && !m_geoIPData->countries.contains(id)) {
|
||||
const quint32 offset = id - m_geoIPData->nodeCount - sizeof(DATA_SECTION_SEPARATOR);
|
||||
quint32 tmp = offset + indexSize + sizeof(DATA_SECTION_SEPARATOR);
|
||||
QVariant val = readDataField(tmp);
|
||||
if (val.userType() == QMetaType::QVariantHash) {
|
||||
m_geoIPData->countries[id] = val.toHash()["country"].toHash()["iso_code"].toString();
|
||||
}
|
||||
else if (val.userType() == QVariant::Invalid) {
|
||||
m_error = tr("Database corrupted: invalid data type at DATA@%1").arg(offset, 8, 16, QLatin1Char('0'));
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
m_error = tr("Invalid database: unsupported data type at DATA@%1").arg(offset, 8, 16, QLatin1Char('0'));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (left) {
|
||||
node.left = id;
|
||||
}
|
||||
else {
|
||||
node.right = id;
|
||||
m_geoIPData->index << node;
|
||||
}
|
||||
|
||||
left = !left;
|
||||
ptr += recordBytes;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QVariantHash Loader::readMetadata()
|
||||
{
|
||||
const char *ptr = reinterpret_cast<const char *>(m_data);
|
||||
quint32 size = m_size;
|
||||
if (m_size > MAX_METADATA_SIZE) {
|
||||
ptr += m_size - MAX_METADATA_SIZE;
|
||||
size = MAX_METADATA_SIZE;
|
||||
}
|
||||
|
||||
const QByteArray data = QByteArray::fromRawData(ptr, size);
|
||||
int index = data.lastIndexOf(METADATA_BEGIN_MARK);
|
||||
if (index >= 0) {
|
||||
if (m_size > MAX_METADATA_SIZE)
|
||||
index += (m_size - MAX_METADATA_SIZE); // from begin of all data
|
||||
quint32 offset = static_cast<quint32>(index + strlen(METADATA_BEGIN_MARK));
|
||||
QVariant metadata = readDataField(offset);
|
||||
m_size = index; // truncate m_size to not contain metadata section
|
||||
if (metadata.userType() == QMetaType::QVariantHash)
|
||||
return metadata.toHash();
|
||||
}
|
||||
|
||||
return QVariantHash();
|
||||
}
|
||||
|
||||
QVariant Loader::readDataField(quint32 &offset)
|
||||
{
|
||||
DataFieldDescriptor descr;
|
||||
if (!readDataFieldDescriptor(offset, descr))
|
||||
return QVariant();
|
||||
|
||||
quint32 locOffset = offset;
|
||||
bool usePointer = false;
|
||||
if (descr.fieldType == DataType::Pointer) {
|
||||
usePointer = true;
|
||||
// convert offset from data section to global
|
||||
locOffset = descr.offset + (m_geoIPData->nodeCount * m_geoIPData->recordSize / 4) + sizeof(DATA_SECTION_SEPARATOR);
|
||||
if (!readDataFieldDescriptor(locOffset, descr))
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QVariant fieldValue;
|
||||
switch (descr.fieldType) {
|
||||
case DataType::Pointer:
|
||||
qDebug() << "* Illegal Pointer using";
|
||||
break;
|
||||
case DataType::String:
|
||||
fieldValue = QString::fromUtf8(reinterpret_cast<const char *>(m_data + locOffset), descr.fieldSize);
|
||||
locOffset += descr.fieldSize;
|
||||
break;
|
||||
case DataType::Double:
|
||||
if (descr.fieldSize == 8)
|
||||
fieldValue = readPlainValue<double>(locOffset, descr.fieldSize);
|
||||
else
|
||||
qDebug() << "* Invalid field size for type: Double";
|
||||
break;
|
||||
case DataType::Bytes:
|
||||
fieldValue = QByteArray(reinterpret_cast<const char *>(m_data + locOffset), descr.fieldSize);
|
||||
locOffset += descr.fieldSize;
|
||||
break;
|
||||
case DataType::Integer16:
|
||||
fieldValue = readPlainValue<quint16>(locOffset, descr.fieldSize);
|
||||
break;
|
||||
case DataType::Integer32:
|
||||
fieldValue = readPlainValue<quint32>(locOffset, descr.fieldSize);
|
||||
break;
|
||||
case DataType::Map:
|
||||
fieldValue = readMapValue(locOffset, descr.fieldSize);
|
||||
break;
|
||||
case DataType::SignedInteger32:
|
||||
fieldValue = readPlainValue<qint32>(locOffset, descr.fieldSize);
|
||||
break;
|
||||
case DataType::Integer64:
|
||||
fieldValue = readPlainValue<quint64>(locOffset, descr.fieldSize);
|
||||
break;
|
||||
case DataType::Integer128:
|
||||
qDebug() << "* Unsupported data type: Integer128";
|
||||
break;
|
||||
case DataType::Array:
|
||||
fieldValue = readArrayValue(locOffset, descr.fieldSize);
|
||||
break;
|
||||
case DataType::DataCacheContainer:
|
||||
qDebug() << "* Unsupported data type: DataCacheContainer";
|
||||
break;
|
||||
case DataType::EndMarker:
|
||||
qDebug() << "* Unsupported data type: EndMarker";
|
||||
break;
|
||||
case DataType::Boolean:
|
||||
fieldValue = QVariant::fromValue(static_cast<bool>(descr.fieldSize));
|
||||
break;
|
||||
case DataType::Float:
|
||||
if (descr.fieldSize == 4)
|
||||
fieldValue = readPlainValue<float>(locOffset, descr.fieldSize);
|
||||
else
|
||||
qDebug() << "* Invalid field size for type: Float";
|
||||
break;
|
||||
}
|
||||
|
||||
if (!usePointer)
|
||||
offset = locOffset;
|
||||
return fieldValue;
|
||||
}
|
||||
|
||||
bool Loader::readDataFieldDescriptor(quint32 &offset, DataFieldDescriptor &out)
|
||||
{
|
||||
const uchar *dataPtr = m_data + offset;
|
||||
int availSize = m_size - offset;
|
||||
if (availSize < 1) return false;
|
||||
|
||||
out.fieldType = static_cast<DataType>((dataPtr[0] & 0xE0) >> 5);
|
||||
if (out.fieldType == DataType::Pointer) {
|
||||
int size = ((dataPtr[0] & 0x18) >> 3);
|
||||
if (availSize < (size + 2)) return false;
|
||||
|
||||
if (size == 0)
|
||||
out.offset = ((dataPtr[0] & 0x07) << 8) + dataPtr[1];
|
||||
else if (size == 1)
|
||||
out.offset = ((dataPtr[0] & 0x07) << 16) + (dataPtr[1] << 8) + dataPtr[2] + 2048;
|
||||
else if (size == 2)
|
||||
out.offset = ((dataPtr[0] & 0x07) << 24) + (dataPtr[1] << 16) + (dataPtr[2] << 8) + dataPtr[3] + 526336;
|
||||
else if (size == 3)
|
||||
out.offset = (dataPtr[1] << 24) + (dataPtr[2] << 16) + (dataPtr[3] << 8) + dataPtr[4];
|
||||
|
||||
offset += size + 2;
|
||||
return true;
|
||||
}
|
||||
|
||||
out.fieldSize = dataPtr[0] & 0x1F;
|
||||
if (out.fieldSize <= 28) {
|
||||
if (out.fieldType == DataType::Unknown) {
|
||||
out.fieldType = static_cast<DataType>(dataPtr[1] + 7);
|
||||
if ((out.fieldType <= DataType::Map) || (out.fieldType > DataType::Float) || (availSize < 3))
|
||||
return false;
|
||||
offset += 2;
|
||||
}
|
||||
else {
|
||||
offset += 1;
|
||||
}
|
||||
}
|
||||
else if (out.fieldSize == 29) {
|
||||
if (availSize < 2) return false;
|
||||
out.fieldSize = dataPtr[1] + 29;
|
||||
offset += 2;
|
||||
}
|
||||
else if (out.fieldSize == 30) {
|
||||
if (availSize < 3) return false;
|
||||
out.fieldSize = (dataPtr[1] << 8) + dataPtr[2] + 285;
|
||||
offset += 3;
|
||||
}
|
||||
else if (out.fieldSize == 31) {
|
||||
if (availSize < 4) return false;
|
||||
out.fieldSize = (dataPtr[1] << 16) + (dataPtr[2] << 8) + dataPtr[3] + 65821;
|
||||
offset += 4;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Loader::fromBigEndian(uchar *buf, quint32 len)
|
||||
{
|
||||
if (__IS_LITTLE_ENDIAN__)
|
||||
std::reverse(buf, buf + len);
|
||||
}
|
||||
|
||||
QVariant Loader::readMapValue(quint32 &offset, quint32 count)
|
||||
{
|
||||
QVariantHash map;
|
||||
|
||||
for (quint32 i = 0; i < count; ++i) {
|
||||
QVariant field = readDataField(offset);
|
||||
if (field.userType() != QMetaType::QString)
|
||||
return QVariant();
|
||||
|
||||
QString key = field.toString();
|
||||
field = readDataField(offset);
|
||||
if (field.userType() == QVariant::Invalid)
|
||||
return QVariant();
|
||||
|
||||
map[key] = field;
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
QVariant Loader::readArrayValue(quint32 &offset, quint32 count)
|
||||
{
|
||||
QVariantList array;
|
||||
|
||||
for (quint32 i = 0; i < count; ++i) {
|
||||
QVariant field = readDataField(offset);
|
||||
if (field.userType() == QVariant::Invalid)
|
||||
return QVariant();
|
||||
|
||||
array.append(field);
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
#if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0))
|
||||
Q_IPV6ADDR createMappedAddress(quint32 ip4)
|
||||
{
|
||||
Q_IPV6ADDR ip6;
|
||||
memset(&ip6, 0, sizeof(ip6));
|
||||
|
||||
int i;
|
||||
for (i = 15; ip4 != 0; i--) {
|
||||
ip6[i] = ip4 & 0xFF;
|
||||
ip4 >>= 8;
|
||||
}
|
||||
|
||||
ip6[11] = 0xFF;
|
||||
ip6[10] = 0xFF;
|
||||
|
||||
return ip6;
|
||||
}
|
||||
#endif
|
||||
}
|
60
src/core/net/private/geoipdatabase.h
Normal file
60
src/core/net/private/geoipdatabase.h
Normal file
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2015 Vladimir Golovnev <glassez@yandex.ru>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef GEOIPDATABASE_H
|
||||
#define GEOIPDATABASE_H
|
||||
|
||||
#include <QtGlobal>
|
||||
|
||||
class QHostAddress;
|
||||
class QString;
|
||||
class QByteArray;
|
||||
class QDateTime;
|
||||
|
||||
struct GeoIPData;
|
||||
|
||||
class GeoIPDatabase
|
||||
{
|
||||
public:
|
||||
static GeoIPDatabase *load(const QString &filename, QString &error);
|
||||
static GeoIPDatabase *load(const QByteArray &data, QString &error);
|
||||
|
||||
~GeoIPDatabase();
|
||||
|
||||
QString type() const;
|
||||
quint16 ipVersion() const;
|
||||
QDateTime buildEpoch() const;
|
||||
QString lookup(const QHostAddress &hostAddr) const;
|
||||
|
||||
private:
|
||||
GeoIPDatabase(GeoIPData *geoIPData);
|
||||
|
||||
GeoIPData *m_geoIPData;
|
||||
};
|
||||
|
||||
#endif // GEOIPDATABASE_H
|
142
src/core/utils/gzip.cpp
Normal file
142
src/core/utils/gzip.cpp
Normal file
|
@ -0,0 +1,142 @@
|
|||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2015 Vladimir Golovnev <glassez@yandex.ru>
|
||||
* Copyright (C) 2006 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 <QByteArray>
|
||||
#include <zlib.h>
|
||||
|
||||
#include "gzip.h"
|
||||
|
||||
bool Utils::Gzip::compress(QByteArray src, QByteArray &dest)
|
||||
{
|
||||
static const int BUFSIZE = 128 * 1024;
|
||||
char tmpBuf[BUFSIZE];
|
||||
int ret;
|
||||
|
||||
dest.clear();
|
||||
|
||||
z_stream strm;
|
||||
strm.zalloc = Z_NULL;
|
||||
strm.zfree = Z_NULL;
|
||||
strm.opaque = Z_NULL;
|
||||
strm.next_in = reinterpret_cast<uchar *>(src.data());
|
||||
strm.avail_in = src.length();
|
||||
strm.next_out = reinterpret_cast<uchar *>(tmpBuf);
|
||||
strm.avail_out = BUFSIZE;
|
||||
|
||||
// windowBits = 15 + 16 to enable gzip
|
||||
// From the zlib manual: windowBits can also be greater than 15 for optional gzip encoding. Add 16 to windowBits
|
||||
// to write a simple gzip header and trailer around the compressed data instead of a zlib wrapper.
|
||||
ret = deflateInit2(&strm, Z_BEST_COMPRESSION, Z_DEFLATED, 15 + 16, 8, Z_DEFAULT_STRATEGY);
|
||||
|
||||
if (ret != Z_OK)
|
||||
return false;
|
||||
|
||||
while (strm.avail_in != 0) {
|
||||
ret = deflate(&strm, Z_NO_FLUSH);
|
||||
if (ret != Z_OK)
|
||||
return false;
|
||||
|
||||
if (strm.avail_out == 0) {
|
||||
dest.append(tmpBuf, BUFSIZE);
|
||||
strm.next_out = reinterpret_cast<uchar *>(tmpBuf);
|
||||
strm.avail_out = BUFSIZE;
|
||||
}
|
||||
}
|
||||
|
||||
int deflateRes = Z_OK;
|
||||
while (deflateRes == Z_OK) {
|
||||
if (strm.avail_out == 0) {
|
||||
dest.append(tmpBuf, BUFSIZE);
|
||||
strm.next_out = reinterpret_cast<uchar *>(tmpBuf);
|
||||
strm.avail_out = BUFSIZE;
|
||||
}
|
||||
|
||||
deflateRes = deflate(&strm, Z_FINISH);
|
||||
}
|
||||
|
||||
if (deflateRes != Z_STREAM_END)
|
||||
return false;
|
||||
|
||||
dest.append(tmpBuf, BUFSIZE - strm.avail_out);
|
||||
deflateEnd(&strm);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Utils::Gzip::uncompress(QByteArray src, QByteArray &dest)
|
||||
{
|
||||
dest.clear();
|
||||
|
||||
if (src.size() <= 4) {
|
||||
qWarning("uncompress: Input data is truncated");
|
||||
return false;
|
||||
}
|
||||
|
||||
z_stream strm;
|
||||
static const int CHUNK_SIZE = 1024;
|
||||
char out[CHUNK_SIZE];
|
||||
|
||||
/* allocate inflate state */
|
||||
strm.zalloc = Z_NULL;
|
||||
strm.zfree = Z_NULL;
|
||||
strm.opaque = Z_NULL;
|
||||
strm.avail_in = static_cast<uint>(src.size());
|
||||
strm.next_in = reinterpret_cast<uchar *>(src.data());
|
||||
|
||||
const int windowBits = 15;
|
||||
const int ENABLE_ZLIB_GZIP = 32;
|
||||
|
||||
int ret = inflateInit2(&strm, windowBits | ENABLE_ZLIB_GZIP); // gzip decoding
|
||||
if (ret != Z_OK)
|
||||
return false;
|
||||
|
||||
// run inflate()
|
||||
do {
|
||||
strm.avail_out = CHUNK_SIZE;
|
||||
strm.next_out = reinterpret_cast<uchar *>(out);
|
||||
|
||||
ret = inflate(&strm, Z_NO_FLUSH);
|
||||
Q_ASSERT(ret != Z_STREAM_ERROR); // state not clobbered
|
||||
|
||||
switch (ret) {
|
||||
case Z_NEED_DICT:
|
||||
case Z_DATA_ERROR:
|
||||
case Z_MEM_ERROR:
|
||||
inflateEnd(&strm);
|
||||
return false;
|
||||
}
|
||||
|
||||
dest.append(out, CHUNK_SIZE - strm.avail_out);
|
||||
}
|
||||
while (!strm.avail_out);
|
||||
|
||||
// clean up and return
|
||||
inflateEnd(&strm);
|
||||
return true;
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
/*
|
||||
* Bittorrent Client using Qt4 and libtorrent.
|
||||
* Copyright (C) 2010 Christophe Dumez
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2015 Vladimir Golovnev <glassez@yandex.ru>
|
||||
* Copyright (C) 2006 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
|
||||
|
@ -24,35 +25,20 @@
|
|||
* 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.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
#ifndef GEOIPMANAGER_H
|
||||
#define GEOIPMANAGER_H
|
||||
#ifndef UTILS_GZIP_H
|
||||
#define UTILS_GZIP_H
|
||||
|
||||
#include <QString>
|
||||
#include <QIcon>
|
||||
class QByteArray;
|
||||
|
||||
namespace libtorrent {
|
||||
class session;
|
||||
namespace Utils
|
||||
{
|
||||
namespace Gzip
|
||||
{
|
||||
bool compress(QByteArray src, QByteArray &dest);
|
||||
bool uncompress(QByteArray src, QByteArray &dest);
|
||||
}
|
||||
}
|
||||
|
||||
class GeoIPManager : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
static void loadDatabase(libtorrent::session *s);
|
||||
static QIcon CountryISOCodeToIcon(const QString &iso);
|
||||
static QString CountryISOCodeToName(const QString &iso);
|
||||
|
||||
private:
|
||||
static QString geoipFolder(bool embedded=false);
|
||||
static QString geoipDBpath(bool embedded=false);
|
||||
#ifdef WITH_GEOIP_EMBEDDED
|
||||
static void exportEmbeddedDb();
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
#endif // GEOIP_H
|
||||
#endif // UTILS_GZIP_H
|
|
@ -135,7 +135,7 @@ void AddNewTorrentDialog::show(QString source, QWidget *parent)
|
|||
|
||||
if (Utils::Misc::isUrl(source)) {
|
||||
// Launch downloader
|
||||
Net::DownloadHandler *handler = Net::DownloadManager::instance()->downloadUrl(source, 10485760 /* 10MB */);
|
||||
Net::DownloadHandler *handler = Net::DownloadManager::instance()->downloadUrl(source, true, 10485760 /* 10MB */, true);
|
||||
connect(handler, SIGNAL(downloadFinished(QString, QString)), dlg, SLOT(handleDownloadFinished(QString, QString)));
|
||||
connect(handler, SIGNAL(downloadFailed(QString, QString)), dlg, SLOT(handleDownloadFailed(QString, QString)));
|
||||
connect(handler, SIGNAL(redirectedToMagnet(QString, QString)), dlg, SLOT(handleRedirectedToMagnet(QString, QString)));
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
If you wish to embed GeoIP database into qBittorrent executable, please download put GeoIP.dat in this folder.
|
||||
|
||||
GeoIP Database can be downloaded from here:
|
||||
* http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz
|
||||
Note that the database should be uncompressed.
|
||||
|
||||
Embedding GeoIP database into qBittorrent executable is advised for:
|
||||
* Windows
|
||||
* Mac OS X
|
||||
* Linux distributions that don't provide GeoIP database in a separate package
|
||||
|
||||
On Linux operating system, since this is not the default behavior, you also need to pass --with-geoip-database-embedded parameter to the configure file.
|
|
@ -1,19 +0,0 @@
|
|||
INCLUDEPATH += $$PWD
|
||||
|
||||
HEADERS += $$PWD/geoipmanager.h
|
||||
|
||||
SOURCES += $$PWD/geoipmanager.cpp
|
||||
|
||||
# Add GeoIP resource file if the GeoIP database
|
||||
# should be embedded in qBittorrent executable
|
||||
contains(DEFINES, WITH_GEOIP_EMBEDDED) {
|
||||
exists("GeoIP.dat") {
|
||||
message("GeoIP.dat was found in src/gui/geoip/.")
|
||||
RESOURCES += $$PWD/geoip.qrc
|
||||
} else {
|
||||
DEFINES -= WITH_GEOIP_EMBEDDED
|
||||
error("GeoIP.dat was not found in src/gui/geoip/ folder, please follow instructions in src/gui/geoip/README.")
|
||||
}
|
||||
} else {
|
||||
message("GeoIP database will not be embedded in qBittorrent executable.")
|
||||
}
|
|
@ -1,5 +0,0 @@
|
|||
<RCC>
|
||||
<qresource prefix="/geoip">
|
||||
<file>GeoIP.dat</file>
|
||||
</qresource>
|
||||
</RCC>
|
|
@ -1,203 +0,0 @@
|
|||
/*
|
||||
* Bittorrent Client using Qt4 and libtorrent.
|
||||
* 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.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
#include "geoipmanager.h"
|
||||
|
||||
/*
|
||||
* Bittorrent Client using Qt4 and libtorrent.
|
||||
* 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.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QChar>
|
||||
|
||||
#include "core/utils/fs.h"
|
||||
#include <libtorrent/session.hpp>
|
||||
|
||||
using namespace libtorrent;
|
||||
|
||||
QString GeoIPManager::geoipFolder(bool embedded) {
|
||||
#ifdef WITH_GEOIP_EMBEDDED
|
||||
if (embedded)
|
||||
return ":/geoip/";
|
||||
return Utils::Fs::QDesktopServicesDataLocation()+"geoip"+"/";
|
||||
#else
|
||||
Q_UNUSED(embedded);
|
||||
if (QFile::exists("/usr/local/share/GeoIP/GeoIP.dat"))
|
||||
return "/usr/local/share/GeoIP/";
|
||||
if (QFile::exists("/var/lib/GeoIP/GeoIP.dat"))
|
||||
return "/var/lib/GeoIP/";
|
||||
return "/usr/share/GeoIP/";
|
||||
#endif
|
||||
}
|
||||
|
||||
QString GeoIPManager::geoipDBpath(bool embedded) {
|
||||
return geoipFolder(embedded)+"GeoIP.dat";
|
||||
}
|
||||
|
||||
#ifdef WITH_GEOIP_EMBEDDED
|
||||
void GeoIPManager::exportEmbeddedDb() {
|
||||
if (!QFile::exists(geoipDBpath(false)) || QFile(geoipDBpath(false)).size() != QFile(geoipDBpath(true)).size()) { // Export is required
|
||||
qDebug("A local Geoip database update is required, proceeding...");
|
||||
// Create geoip folder is necessary
|
||||
QDir gfolder(geoipFolder(false));
|
||||
if (!gfolder.exists()) {
|
||||
if (!gfolder.mkpath(geoipFolder(false))) {
|
||||
std::cerr << "Failed to create geoip folder at " << qPrintable(geoipFolder(false)) << std::endl;
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Remove destination files
|
||||
if (QFile::exists(geoipDBpath(false)))
|
||||
Utils::Fs::forceRemove(geoipDBpath(false));
|
||||
// Copy from executable to hard disk
|
||||
qDebug("%s -> %s", qPrintable(geoipDBpath(true)), qPrintable(geoipDBpath(false)));
|
||||
if (!QFile::copy(geoipDBpath(true), geoipDBpath(false))) {
|
||||
std::cerr << "ERROR: Failed to copy geoip.dat from executable to hard disk" << std::endl;
|
||||
}
|
||||
qDebug("Local Geoip database was updated");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void GeoIPManager::loadDatabase(session *s) {
|
||||
#ifdef WITH_GEOIP_EMBEDDED
|
||||
exportEmbeddedDb();
|
||||
#endif
|
||||
if (QFile::exists(geoipDBpath(false))) {
|
||||
qDebug("Loading GeoIP database from %s...", qPrintable(geoipDBpath(false)));
|
||||
s->load_country_db(geoipDBpath(false).toLocal8Bit().constData());
|
||||
} else {
|
||||
qDebug("ERROR: Impossible to find local Geoip Database");
|
||||
}
|
||||
}
|
||||
|
||||
const char country_code[253][3] =
|
||||
{ "--","AP","EU","AD","AE","AF","AG","AI","AL","AM","AN",
|
||||
"AO","AQ","AR","AS","AT","AU","AW","AZ","BA","BB",
|
||||
"BD","BE","BF","BG","BH","BI","BJ","BM","BN","BO",
|
||||
"BR","BS","BT","BV","BW","BY","BZ","CA","CC","CD",
|
||||
"CF","CG","CH","CI","CK","CL","CM","CN","CO","CR",
|
||||
"CU","CV","CX","CY","CZ","DE","DJ","DK","DM","DO",
|
||||
"DZ","EC","EE","EG","EH","ER","ES","ET","FI","FJ",
|
||||
"FK","FM","FO","FR","FX","GA","GB","GD","GE","GF",
|
||||
"GH","GI","GL","GM","GN","GP","GQ","GR","GS","GT",
|
||||
"GU","GW","GY","HK","HM","HN","HR","HT","HU","ID",
|
||||
"IE","IL","IN","IO","IQ","IR","IS","IT","JM","JO",
|
||||
"JP","KE","KG","KH","KI","KM","KN","KP","KR","KW",
|
||||
"KY","KZ","LA","LB","LC","LI","LK","LR","LS","LT",
|
||||
"LU","LV","LY","MA","MC","MD","MG","MH","MK","ML",
|
||||
"MM","MN","MO","MP","MQ","MR","MS","MT","MU","MV",
|
||||
"MW","MX","MY","MZ","NA","NC","NE","NF","NG","NI",
|
||||
"NL","NO","NP","NR","NU","NZ","OM","PA","PE","PF",
|
||||
"PG","PH","PK","PL","PM","PN","PR","PS","PT","PW",
|
||||
"PY","QA","RE","RO","RU","RW","SA","SB","SC","SD",
|
||||
"SE","SG","SH","SI","SJ","SK","SL","SM","SN","SO",
|
||||
"SR","ST","SV","SY","SZ","TC","TD","TF","TG","TH",
|
||||
"TJ","TK","TM","TN","TO","TL","TR","TT","TV","TW",
|
||||
"TZ","UA","UG","UM","US","UY","UZ","VA","VC","VE",
|
||||
"VG","VI","VN","VU","WF","WS","YE","YT","RS","ZA",
|
||||
"ZM","ME","ZW","A1","A2","O1","AX","GG","IM","JE",
|
||||
"BL","MF"};
|
||||
|
||||
static const uint num_countries = (unsigned)(sizeof(country_code)/sizeof(country_code[0]));
|
||||
|
||||
const char * country_name[253] =
|
||||
{"N/A","Asia/Pacific Region","Europe","Andorra","United Arab Emirates","Afghanistan","Antigua and Barbuda","Anguilla","Albania","Armenia","Netherlands Antilles",
|
||||
"Angola","Antarctica","Argentina","American Samoa","Austria","Australia","Aruba","Azerbaijan","Bosnia and Herzegovina","Barbados",
|
||||
"Bangladesh","Belgium","Burkina Faso","Bulgaria","Bahrain","Burundi","Benin","Bermuda","Brunei Darussalam","Bolivia",
|
||||
"Brazil","Bahamas","Bhutan","Bouvet Island","Botswana","Belarus","Belize","Canada","Cocos (Keeling) Islands","Congo, The Democratic Republic of the",
|
||||
"Central African Republic","Congo","Switzerland","Cote D'Ivoire","Cook Islands","Chile","Cameroon","China","Colombia","Costa Rica",
|
||||
"Cuba","Cape Verde","Christmas Island","Cyprus","Czech Republic","Germany","Djibouti","Denmark","Dominica","Dominican Republic",
|
||||
"Algeria","Ecuador","Estonia","Egypt","Western Sahara","Eritrea","Spain","Ethiopia","Finland","Fiji",
|
||||
"Falkland Islands (Malvinas)","Micronesia, Federated States of","Faroe Islands","France","France, Metropolitan","Gabon","United Kingdom","Grenada","Georgia","French Guiana",
|
||||
"Ghana","Gibraltar","Greenland","Gambia","Guinea","Guadeloupe","Equatorial Guinea","Greece","South Georgia and the South Sandwich Islands","Guatemala",
|
||||
"Guam","Guinea-Bissau","Guyana","Hong Kong","Heard Island and McDonald Islands","Honduras","Croatia","Haiti","Hungary","Indonesia",
|
||||
"Ireland","Israel","India","British Indian Ocean Territory","Iraq","Iran, Islamic Republic of","Iceland","Italy","Jamaica","Jordan",
|
||||
"Japan","Kenya","Kyrgyzstan","Cambodia","Kiribati","Comoros","Saint Kitts and Nevis","Korea, Democratic People's Republic of","Korea, Republic of","Kuwait",
|
||||
"Cayman Islands","Kazakhstan","Lao People's Democratic Republic","Lebanon","Saint Lucia","Liechtenstein","Sri Lanka","Liberia","Lesotho","Lithuania",
|
||||
"Luxembourg","Latvia","Libyan Arab Jamahiriya","Morocco","Monaco","Moldova, Republic of","Madagascar","Marshall Islands","Macedonia","Mali",
|
||||
"Myanmar","Mongolia","Macau","Northern Mariana Islands","Martinique","Mauritania","Montserrat","Malta","Mauritius","Maldives",
|
||||
"Malawi","Mexico","Malaysia","Mozambique","Namibia","New Caledonia","Niger","Norfolk Island","Nigeria","Nicaragua",
|
||||
"Netherlands","Norway","Nepal","Nauru","Niue","New Zealand","Oman","Panama","Peru","French Polynesia",
|
||||
"Papua New Guinea","Philippines","Pakistan","Poland","Saint Pierre and Miquelon","Pitcairn Islands","Puerto Rico","Palestinian Territory","Portugal","Palau",
|
||||
"Paraguay","Qatar","Reunion","Romania","Russian Federation","Rwanda","Saudi Arabia","Solomon Islands","Seychelles","Sudan",
|
||||
"Sweden","Singapore","Saint Helena","Slovenia","Svalbard and Jan Mayen","Slovakia","Sierra Leone","San Marino","Senegal","Somalia","Suriname",
|
||||
"Sao Tome and Principe","El Salvador","Syrian Arab Republic","Swaziland","Turks and Caicos Islands","Chad","French Southern Territories","Togo","Thailand",
|
||||
"Tajikistan","Tokelau","Turkmenistan","Tunisia","Tonga","Timor-Leste","Turkey","Trinidad and Tobago","Tuvalu","Taiwan",
|
||||
"Tanzania, United Republic of","Ukraine","Uganda","United States Minor Outlying Islands","United States","Uruguay","Uzbekistan","Holy See (Vatican City State)","Saint Vincent and the Grenadines","Venezuela",
|
||||
"Virgin Islands, British","Virgin Islands, U.S.","Vietnam","Vanuatu","Wallis and Futuna","Samoa","Yemen","Mayotte","Serbia","South Africa",
|
||||
"Zambia","Montenegro","Zimbabwe","Anonymous Proxy","Satellite Provider","Other","Aland Islands","Guernsey","Isle of Man","Jersey",
|
||||
"Saint Barthelemy","Saint Martin"};
|
||||
|
||||
QString GeoIPManager::CountryISOCodeToName(const QString &iso) {
|
||||
if (iso.isEmpty()) return "N/A";
|
||||
|
||||
for (uint i = 0; i < num_countries; ++i) {
|
||||
if (iso == country_code[i]) {
|
||||
return QLatin1String(country_name[i]);
|
||||
}
|
||||
}
|
||||
qDebug("GeoIPManager: Country name resolution failed for: %s", qPrintable(iso));
|
||||
return "N/A";
|
||||
}
|
||||
|
||||
// http://www.iso.org/iso/country_codes/iso_3166_code_lists/english_country_names_and_code_elements.htm
|
||||
QIcon GeoIPManager::CountryISOCodeToIcon(const QString &iso) {
|
||||
if (iso.isEmpty() || (iso[0] == '!')) return QIcon();
|
||||
return QIcon(":/icons/flags/" + iso.toLower() + ".png");
|
||||
}
|
||||
|
|
@ -3,7 +3,6 @@ INCLUDEPATH += $$PWD
|
|||
include(lineedit/lineedit.pri)
|
||||
include(properties/properties.pri)
|
||||
include(rss/rss.pri)
|
||||
include(geoip/geoip.pri)
|
||||
include(powermanagement/powermanagement.pri)
|
||||
unix:!macx:dbus: include(qtnotify/qtnotify.pri)
|
||||
|
||||
|
|
|
@ -68,6 +68,12 @@ QIcon GuiIconProvider::getIcon(const QString &iconId)
|
|||
return QIcon(IconProvider::getIconPath(iconId));
|
||||
}
|
||||
|
||||
QIcon GuiIconProvider::getFlagIcon(const QString &countryIsoCode)
|
||||
{
|
||||
if (countryIsoCode.isEmpty()) return QIcon();
|
||||
return QIcon(":/icons/flags/" + countryIsoCode.toLower() + ".png");
|
||||
}
|
||||
|
||||
// Makes sure the icon is at least available in 16px and 24px size
|
||||
// It scales the icon from the theme if necessary
|
||||
// Otherwise, the UI looks broken if the icon is not available
|
||||
|
|
|
@ -44,6 +44,7 @@ public:
|
|||
static GuiIconProvider *instance();
|
||||
|
||||
QIcon getIcon(const QString &iconId);
|
||||
QIcon getFlagIcon(const QString &countryIsoCode);
|
||||
QString getIconPath(const QString &iconId);
|
||||
|
||||
private slots:
|
||||
|
|
|
@ -1626,7 +1626,7 @@ void MainWindow::installPython()
|
|||
{
|
||||
setCursor(QCursor(Qt::WaitCursor));
|
||||
// Download python
|
||||
Net::DownloadHandler *handler = Net::DownloadManager::instance()->downloadUrl("https://www.python.org/ftp/python/3.4.3/python-3.4.3.msi");
|
||||
Net::DownloadHandler *handler = Net::DownloadManager::instance()->downloadUrl("https://www.python.org/ftp/python/3.4.3/python-3.4.3.msi", true);
|
||||
connect(handler, SIGNAL(downloadFinished(QString, QString)), this, SLOT(pythonDownloadSuccess(QString, QString)));
|
||||
connect(handler, SIGNAL(downloadFailed(QString, QString)), this, SLOT(pythonDownloadFailure(QString, QString)));
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
#include "core/preferences.h"
|
||||
#include "core/logger.h"
|
||||
#include "propertieswidget.h"
|
||||
#include "geoipmanager.h"
|
||||
#include "core/net/geoipmanager.h"
|
||||
#include "peersadditiondlg.h"
|
||||
#include "speedlimitdlg.h"
|
||||
#include "guiiconprovider.h"
|
||||
|
@ -141,8 +141,14 @@ void PeerListWidget::updatePeerCountryResolutionState()
|
|||
{
|
||||
if (Preferences::instance()->resolvePeerCountries() != m_displayFlags) {
|
||||
m_displayFlags = !m_displayFlags;
|
||||
if (m_displayFlags)
|
||||
if (m_displayFlags) {
|
||||
loadPeers(m_properties->getCurrentTorrent());
|
||||
showColumn(PeerListDelegate::COUNTRY);
|
||||
resizeColumnToContents(PeerListDelegate::COUNTRY);
|
||||
}
|
||||
else {
|
||||
hideColumn(PeerListDelegate::COUNTRY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -303,10 +309,10 @@ QStandardItem* PeerListWidget::addPeer(const QString& ip, BitTorrent::TorrentHan
|
|||
m_listModel->setData(m_listModel->index(row, PeerListDelegate::PORT), peer.address().port);
|
||||
m_listModel->setData(m_listModel->index(row, PeerListDelegate::IP_HIDDEN), ip);
|
||||
if (m_displayFlags) {
|
||||
const QIcon ico = GeoIPManager::CountryISOCodeToIcon(peer.country());
|
||||
const QIcon ico = GuiIconProvider::instance()->getFlagIcon(peer.country());
|
||||
if (!ico.isNull()) {
|
||||
m_listModel->setData(m_listModel->index(row, PeerListDelegate::COUNTRY), ico, Qt::DecorationRole);
|
||||
const QString country_name = GeoIPManager::CountryISOCodeToName(peer.country());
|
||||
const QString country_name = Net::GeoIPManager::CountryName(peer.country());
|
||||
m_listModel->setData(m_listModel->index(row, PeerListDelegate::COUNTRY), country_name, Qt::ToolTipRole);
|
||||
} else {
|
||||
m_missingFlags.insert(ip);
|
||||
|
@ -331,10 +337,10 @@ void PeerListWidget::updatePeer(const QString &ip, BitTorrent::TorrentHandle *co
|
|||
QStandardItem *item = m_peerItems.value(ip);
|
||||
int row = item->row();
|
||||
if (m_displayFlags) {
|
||||
const QIcon ico = GeoIPManager::CountryISOCodeToIcon(peer.country());
|
||||
const QIcon ico = GuiIconProvider::instance()->getFlagIcon(peer.country());
|
||||
if (!ico.isNull()) {
|
||||
m_listModel->setData(m_listModel->index(row, PeerListDelegate::COUNTRY), ico, Qt::DecorationRole);
|
||||
const QString country_name = GeoIPManager::CountryISOCodeToName(peer.country());
|
||||
const QString country_name = Net::GeoIPManager::CountryName(peer.country());
|
||||
m_listModel->setData(m_listModel->index(row, PeerListDelegate::COUNTRY), country_name, Qt::ToolTipRole);
|
||||
m_missingFlags.remove(ip);
|
||||
}
|
||||
|
|
|
@ -59,7 +59,7 @@ QStringList TrackersAdditionDlg::newTrackers() const
|
|||
void TrackersAdditionDlg::on_uTorrentListButton_clicked()
|
||||
{
|
||||
uTorrentListButton->setEnabled(false);
|
||||
Net::DownloadHandler *handler = Net::DownloadManager::instance()->downloadUrl(QString("http://www.torrentz.com/announce_%1").arg(m_torrent->hash()));
|
||||
Net::DownloadHandler *handler = Net::DownloadManager::instance()->downloadUrl(QString("http://www.torrentz.com/announce_%1").arg(m_torrent->hash()), true);
|
||||
connect(handler, SIGNAL(downloadFinished(QString, QString)), this, SLOT(parseUTorrentList(QString, QString)));
|
||||
connect(handler, SIGNAL(downloadFailed(QString, QString)), this, SLOT(getTrackerError(QString, QString)));
|
||||
//Just to show that it takes times
|
||||
|
|
|
@ -66,7 +66,7 @@ RssFeed::RssFeed(RssManager* manager, RssFolder* parent, const QString& url):
|
|||
connect(manager->rssParser(), SIGNAL(feedParsingFinished(QString,QString)), SLOT(handleFeedParsingFinished(QString,QString)));
|
||||
|
||||
// Download the RSS Feed icon
|
||||
Net::DownloadHandler *handler = Net::DownloadManager::instance()->downloadUrl(iconUrl());
|
||||
Net::DownloadHandler *handler = Net::DownloadManager::instance()->downloadUrl(iconUrl(), true);
|
||||
connect(handler, SIGNAL(downloadFinished(QString, QString)), this, SLOT(handleFinishedDownload(QString, QString)));
|
||||
connect(handler, SIGNAL(downloadFailed(QString, QString)), this, SLOT(handleDownloadFailure(QString, QString)));
|
||||
m_iconUrl = handler->url();
|
||||
|
@ -167,7 +167,7 @@ bool RssFeed::refresh()
|
|||
}
|
||||
m_loading = true;
|
||||
// Download the RSS again
|
||||
Net::DownloadHandler *handler = Net::DownloadManager::instance()->downloadUrl(m_url);
|
||||
Net::DownloadHandler *handler = Net::DownloadManager::instance()->downloadUrl(m_url, true);
|
||||
connect(handler, SIGNAL(downloadFinished(QString, QString)), this, SLOT(handleFinishedDownload(QString, QString)));
|
||||
connect(handler, SIGNAL(downloadFailed(QString, QString)), this, SLOT(handleDownloadFailure(QString, QString)));
|
||||
m_url = handler->url(); // sync URL encoding
|
||||
|
|
|
@ -474,7 +474,7 @@ void TrackerFiltersList::addItem(const QString &tracker, const QString &hash)
|
|||
trackerItem = new QListWidgetItem();
|
||||
trackerItem->setData(Qt::DecorationRole, GuiIconProvider::instance()->getIcon("network-server"));
|
||||
|
||||
Net::DownloadHandler *h = Net::DownloadManager::instance()->downloadUrl(QString("http://%1/favicon.ico").arg(host));
|
||||
Net::DownloadHandler *h = Net::DownloadManager::instance()->downloadUrl(QString("http://%1/favicon.ico").arg(host), true);
|
||||
connect(h, SIGNAL(downloadFinished(QString, QString)), this, SLOT(handleFavicoDownload(QString, QString)));
|
||||
connect(h, SIGNAL(downloadFailed(QString, QString)), this, SLOT(handleFavicoFailure(QString, QString)));
|
||||
}
|
||||
|
@ -634,7 +634,7 @@ void TrackerFiltersList::handleFavicoDownload(const QString& url, const QString&
|
|||
if (url.endsWith(".ico", Qt::CaseInsensitive)) {
|
||||
Logger::instance()->addMessage(tr("Couldn't decode favicon for URL `%1`. Trying to download favicon in PNG format.").arg(url),
|
||||
Log::WARNING);
|
||||
Net::DownloadHandler *h = Net::DownloadManager::instance()->downloadUrl(url.left(url.size() - 4) + ".png");
|
||||
Net::DownloadHandler *h = Net::DownloadManager::instance()->downloadUrl(url.left(url.size() - 4) + ".png", true);
|
||||
connect(h, SIGNAL(downloadFinished(QString, QString)), this, SLOT(handleFavicoDownload(QString, QString)));
|
||||
connect(h, SIGNAL(downloadFailed(QString, QString)), this, SLOT(handleFavicoFailure(QString, QString)));
|
||||
}
|
||||
|
|
|
@ -429,7 +429,7 @@ bool engineSelectDlg::parseVersionsFile(QString versions_file) {
|
|||
|
||||
void engineSelectDlg::downloadFromUrl(const QString &url)
|
||||
{
|
||||
Net::DownloadHandler *handler = Net::DownloadManager::instance()->downloadUrl(url);
|
||||
Net::DownloadHandler *handler = Net::DownloadManager::instance()->downloadUrl(url, true);
|
||||
connect(handler, SIGNAL(downloadFinished(QString, QString)), this, SLOT(processDownloadedFile(QString, QString)));
|
||||
connect(handler, SIGNAL(downloadFailed(QString, QString)), this, SLOT(handleDownloadFailure(QString, QString)));
|
||||
}
|
||||
|
|
|
@ -91,10 +91,3 @@ nogui:systemd {
|
|||
# INSTALL
|
||||
target.path = $$PREFIX/bin/
|
||||
INSTALLS += target
|
||||
|
||||
!nogui {
|
||||
# DEFINE added by configure
|
||||
contains(DEFINES, WITH_GEOIP_EMBEDDED) {
|
||||
message("You chose to embed GeoIP database in qBittorrent executable.")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,7 +32,6 @@ DEFINES += _CRT_SECURE_NO_DEPRECATE
|
|||
DEFINES += _SCL_SECURE_NO_DEPRECATE
|
||||
DEFINES += __USE_W32_SOCKETS
|
||||
DEFINES += _FILE_OFFSET_BITS=64
|
||||
DEFINES += WITH_SHIPPED_GEOIP_H
|
||||
|
||||
CONFIG(debug, debug|release) {
|
||||
DEFINES += TORRENT_DEBUG
|
||||
|
@ -49,6 +48,3 @@ win32-g++ {
|
|||
else {
|
||||
include(winconf-msvc.pri)
|
||||
}
|
||||
|
||||
DEFINES += WITH_GEOIP_EMBEDDED
|
||||
message("On Windows, GeoIP database must be embedded.")
|
||||
|
|
Loading…
Reference in a new issue