From 06d7b809a35c4463cf4591bd4dc078a1009a0516 Mon Sep 17 00:00:00 2001 From: coolsnowwolf Date: Sat, 7 Dec 2019 12:23:49 +0800 Subject: [PATCH] "qBittorrent: rollback to v4.1.9" This reverts commit 5eaee721bc26ae9eeffb95b69ab9662c17339c65. --- package/lean/qBittorrent/Makefile | 6 +- .../001-remove-ico-not-for-webui.patch | 126 +++ .../patches/002-add-autoban-function.patch | 807 ++++++++++++++++++ 3 files changed, 936 insertions(+), 3 deletions(-) create mode 100644 package/lean/qBittorrent/patches/001-remove-ico-not-for-webui.patch create mode 100644 package/lean/qBittorrent/patches/002-add-autoban-function.patch diff --git a/package/lean/qBittorrent/Makefile b/package/lean/qBittorrent/Makefile index 7ef3b1d22..3bd02e265 100644 --- a/package/lean/qBittorrent/Makefile +++ b/package/lean/qBittorrent/Makefile @@ -1,12 +1,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=qbittorrent -PKG_VERSION:=4.2.0 -PKG_RELEASE=1 +PKG_VERSION:=4.1.9 +PKG_RELEASE=5 PKG_SOURCE:=$(PKG_NAME)-release-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://codeload.github.com/qbittorrent/qBittorrent/tar.gz/release-$(PKG_VERSION)? -PKG_HASH:=2f367b89d7049c09e808fc5f7c338ce1820d91bcaecddcad681e9ba18b13206d +PKG_HASH:=620127f73f88ed3f2b2e4195cbc641f7c27f967d3b045e45f7916c0995fd61fe PKG_BUILD_DIR:=$(BUILD_DIR)/qBittorrent-release-$(PKG_VERSION) diff --git a/package/lean/qBittorrent/patches/001-remove-ico-not-for-webui.patch b/package/lean/qBittorrent/patches/001-remove-ico-not-for-webui.patch new file mode 100644 index 000000000..ee27bbaca --- /dev/null +++ b/package/lean/qBittorrent/patches/001-remove-ico-not-for-webui.patch @@ -0,0 +1,126 @@ +--- a/src/icons/icons.qrc ++++ b/src/icons/icons.qrc +@@ -250,38 +250,16 @@ + flags/zm.svg + flags/zw.svg + L.gif +- loading.png + qbt-theme/application-exit.svg +- qbt-theme/application-rss+xml.svg +- qbt-theme/application-x-mswinurl.svg + qbt-theme/checked.svg + qbt-theme/configure.svg +- qbt-theme/dialog-cancel.svg +- qbt-theme/dialog-information.svg +- qbt-theme/dialog-warning.svg + qbt-theme/document-edit-verify.svg + qbt-theme/document-edit.svg +- qbt-theme/document-encrypt.svg +- qbt-theme/document-import.svg +- qbt-theme/document-new.svg +- qbt-theme/document-properties.svg +- qbt-theme/document-save.svg +- qbt-theme/download.svg +- qbt-theme/edit-clear-history.svg + qbt-theme/edit-clear.svg + qbt-theme/edit-copy.svg +- qbt-theme/edit-cut.svg + qbt-theme/edit-delete.svg +- qbt-theme/edit-find-user.svg + qbt-theme/edit-find.svg +- qbt-theme/edit-paste.svg + qbt-theme/edit-rename.svg +- qbt-theme/folder-documents.svg +- qbt-theme/folder-download.svg +- qbt-theme/folder-new.svg +- qbt-theme/folder-remote.svg +- qbt-theme/gear.svg +- qbt-theme/gear32.svg + qbt-theme/go-bottom.svg + qbt-theme/go-down.svg + qbt-theme/go-top.svg +@@ -295,43 +273,15 @@ + qbt-theme/kt-set-max-upload-speed.png + qbt-theme/list-add.svg + qbt-theme/list-remove.svg +- qbt-theme/mail-folder-inbox.svg +- qbt-theme/mail-mark-read.svg + qbt-theme/media-playback-pause.svg + qbt-theme/media-playback-start.svg + qbt-theme/media-seek-forward.svg +- qbt-theme/network-server.svg +- qbt-theme/network-wired.svg +- qbt-theme/object-locked.svg +- qbt-theme/office-chart-line.svg +- qbt-theme/preferences-desktop.svg +- qbt-theme/preferences-other.svg +- qbt-theme/preferences-system-network.svg +- qbt-theme/preferences-web-browser-cookies.svg +- qbt-theme/rss-config.png + qbt-theme/security-high.svg + qbt-theme/security-low.svg +- qbt-theme/services.svg +- qbt-theme/speedometer.svg + qbt-theme/system-log-out.svg +- qbt-theme/tab-close.svg +- qbt-theme/task-attention.svg +- qbt-theme/task-complete.png +- qbt-theme/task-ongoing.png +- qbt-theme/task-reject.png +- qbt-theme/text-plain.svg +- qbt-theme/tools-report-bug.svg +- qbt-theme/unavailable.svg +- qbt-theme/user-group-delete.svg +- qbt-theme/user-group-new.svg +- qbt-theme/view-calendar-journal.svg + qbt-theme/view-categories.svg +- qbt-theme/view-filter.svg +- qbt-theme/view-preview.svg +- qbt-theme/view-refresh.svg + qbt-theme/view-statistics.svg + qbt-theme/wallet-open.svg +- qbt-theme/webui.svg + skin/arrow-right.gif + skin/bg-dropdown.gif + skin/bg-handle-horizontal.gif +@@ -342,7 +292,6 @@ + skin/completed.svg + skin/connected.svg + skin/disconnected.svg +- skin/dock-tabs.gif + skin/download.svg + skin/downloading.svg + skin/error.svg +@@ -353,14 +302,11 @@ + skin/handle-icon-horizontal.gif + skin/handle-icon.gif + skin/knob.gif +- skin/logo-blank.gif + skin/logo.gif + skin/logo2.gif + skin/mascot.png + skin/paused.svg + skin/qbittorrent-tray.svg +- skin/qbittorrent-tray-dark.svg +- skin/qbittorrent-tray-light.svg + skin/qbittorrent32.png + skin/queued.svg + skin/ratio.svg +@@ -370,17 +316,12 @@ + skin/spacer.gif + skin/spinner-placeholder.gif + skin/spinner.gif +- skin/splash.png + skin/stalledDL.svg + skin/stalledUP.svg + skin/tabs.gif + skin/toolbox-divider.gif +- skin/toolbox-divider2.gif + skin/uploading.svg + slow.png + slow_off.png +- sphere.png +- sphere2.png +- url.png + + diff --git a/package/lean/qBittorrent/patches/002-add-autoban-function.patch b/package/lean/qBittorrent/patches/002-add-autoban-function.patch new file mode 100644 index 000000000..8de0f1e47 --- /dev/null +++ b/package/lean/qBittorrent/patches/002-add-autoban-function.patch @@ -0,0 +1,807 @@ +--- a/src/base/bittorrent/peerinfo.cpp ++++ b/src/base/bittorrent/peerinfo.cpp +@@ -186,11 +186,26 @@ PeerAddress PeerInfo::address() const + m_nativeInfo.ip.port()); + } + ++int PeerInfo::port() const ++{ ++ return m_nativeInfo.ip.port(); ++} ++ + QString PeerInfo::client() const + { + return QString::fromStdString(m_nativeInfo.client); + } + ++QString PeerInfo::pid() const ++{ ++ return QString::fromStdString(m_nativeInfo.pid.to_string()); ++} ++ ++QString PeerInfo::pidtoclient() const ++{ ++ return QString::fromStdString(libt::identify_client(m_nativeInfo.pid)); ++} ++ + qreal PeerInfo::progress() const + { + return m_nativeInfo.progress; +--- a/src/base/bittorrent/peerinfo.h ++++ b/src/base/bittorrent/peerinfo.h +@@ -34,6 +34,7 @@ + #include + + #include ++#include + + namespace BitTorrent + { +@@ -85,7 +86,10 @@ namespace BitTorrent + bool isPlaintextEncrypted() const; + + PeerAddress address() const; ++ int port() const; + QString client() const; ++ QString pid() const; ++ QString pidtoclient() const; + qreal progress() const; + int payloadUpSpeed() const; + int payloadDownSpeed() const; +--- a/src/base/bittorrent/session.cpp ++++ b/src/base/bittorrent/session.cpp +@@ -69,6 +69,7 @@ + #endif + + #include "base/algorithm.h" ++#include "base/bittorrent/peerinfo.h" + #include "base/exceptions.h" + #include "base/global.h" + #include "base/logger.h" +@@ -335,6 +336,8 @@ Session::Session(QObject *parent) + , m_isAltGlobalSpeedLimitEnabled(BITTORRENT_SESSION_KEY("UseAlternativeGlobalSpeedLimit"), false) + , m_isBandwidthSchedulerEnabled(BITTORRENT_SESSION_KEY("BandwidthSchedulerEnabled"), false) + , m_saveResumeDataInterval(BITTORRENT_SESSION_KEY("SaveResumeDataInterval"), 60) ++ , m_autoBanUnknownPeer(BITTORRENT_SESSION_KEY("AutoBanUnknownPeer"), true) ++ , m_showTrackerAuthWindow(BITTORRENT_SESSION_KEY("ShowTrackerAuthWindow"), true) + , m_port(BITTORRENT_SESSION_KEY("Port"), 8999) + , m_useRandomPort(BITTORRENT_SESSION_KEY("UseRandomPort"), false) + , m_networkInterface(BITTORRENT_SESSION_KEY("Interface")) +@@ -502,6 +505,7 @@ Session::Session(QObject *parent) + libt::ip_filter filter; + processBannedIPs(filter); + m_nativeSession->set_ip_filter(filter); ++ loadOfflineFilter(); + } + + m_categories = map_cast(m_storedCategories); +@@ -518,6 +522,17 @@ Session::Session(QObject *parent) + connect(m_refreshTimer, &QTimer::timeout, this, &Session::refresh); + m_refreshTimer->start(); + ++ // Unban Timer ++ m_unbanTimer = new QTimer(this); ++ m_unbanTimer->setInterval(500); ++ connect(m_unbanTimer, &QTimer::timeout, this, &Session::processUnbanRequest); ++ ++ // Ban Timer ++ m_banTimer = new QTimer(this); ++ m_banTimer->setInterval(500); ++ connect(m_banTimer, &QTimer::timeout, this, &Session::autoBanBadClient); ++ m_banTimer->start(); ++ + m_statistics = new Statistics(this); + + updateSeedingLimitTimer(); +@@ -1077,6 +1092,7 @@ void Session::configure() + enableIPFilter(); + else + disableIPFilter(); ++ loadOfflineFilter(); + m_IPFilteringChanged = false; + } + +@@ -1905,6 +1921,95 @@ void Session::banIP(const QString &ip) + } + } + ++bool Session::checkAccessFlags(const QString &ip) ++{ ++ libt::ip_filter filter = m_nativeSession->get_ip_filter(); ++ boost::system::error_code ec; ++ libt::address addr = libt::address::from_string(ip.toLatin1().constData(), ec); ++ Q_ASSERT(!ec); ++ if (ec) return false; ++ return filter.access(addr); ++} ++ ++void Session::tempblockIP(const QString &ip) ++{ ++ libt::ip_filter filter = m_nativeSession->get_ip_filter(); ++ boost::system::error_code ec; ++ libt::address addr = libt::address::from_string(ip.toLatin1().constData(), ec); ++ Q_ASSERT(!ec); ++ if (ec) return; ++ filter.add_rule(addr, addr, libt::ip_filter::blocked); ++ m_nativeSession->set_ip_filter(filter); ++ insertQueue(ip); ++} ++ ++void Session::removeBlockedIP(const QString &ip) ++{ ++ libt::ip_filter filter = m_nativeSession->get_ip_filter(); ++ boost::system::error_code ec; ++ libt::address addr = libt::address::from_string(ip.toLatin1().constData(), ec); ++ Q_ASSERT(!ec); ++ if (ec) return; ++ filter.add_rule(addr, addr, 0); ++ m_nativeSession->set_ip_filter(filter); ++} ++ ++void Session::eraseIPFilter() ++{ ++ q_bannedIPs.clear(); ++ q_unbanTime.clear(); ++ if (isIPFilteringEnabled()) { ++ enableIPFilter(); ++ } else { ++ disableIPFilter(); ++ loadOfflineFilter(); ++ } ++} ++ ++void Session::autoBanBadClient() ++{ ++ const BitTorrent::SessionStatus tStatus = BitTorrent::Session::instance()->status(); ++ if (tStatus.peersCount > 0) { ++ bool m_AutoBan = BitTorrent::Session::instance()->isAutoBanUnknownPeerEnabled(); ++ foreach (BitTorrent::TorrentHandle *const torrent, BitTorrent::Session::instance()->torrents()) { ++ QList peers = torrent->peers(); ++ foreach (const BitTorrent::PeerInfo &peer, peers) { ++ BitTorrent::PeerAddress addr = peer.address(); ++ if (addr.ip.isNull()) continue; ++ QString ip = addr.ip.toString(); ++ int port = peer.port(); ++ QString client = peer.client(); ++ QString ptoc = peer.pidtoclient(); ++ QString pid = peer.pid().left(8); ++ QString country = peer.country(); ++ ++ QRegExp IDFilter("-(XL|SD|XF|QD|BN|DL)(\\d+)-"); ++ QRegExp UAFilter("\\d+.\\d+.\\d+.\\d+"); ++ if (IDFilter.exactMatch(pid) || UAFilter.exactMatch(client)) { ++ qDebug("Auto Banning bad Peer %s...", ip.toLocal8Bit().data()); ++ Logger::instance()->addMessage(tr("Auto banning bad Peer '%1'...'%2'...'%3'...'%4'").arg(ip).arg(pid).arg(ptoc).arg(country)); ++ tempblockIP(ip); ++ continue; ++ } ++ ++ if(m_AutoBan) { ++ if (client.contains("Unknown") && country == "CN") { ++ qDebug("Auto Banning Unknown Peer %s...", ip.toLocal8Bit().data()); ++ Logger::instance()->addMessage(tr("Auto banning Unknown Peer '%1'...'%2'...'%3'...'%4'").arg(ip).arg(pid).arg(ptoc).arg(country)); ++ tempblockIP(ip); ++ continue; ++ } ++ if (port >= 65000 && country == "CN" && client.contains("Transmission")) { ++ qDebug("Auto Banning Offline Downloader %s...", ip.toLocal8Bit().data()); ++ Logger::instance()->addMessage(tr("Auto banning Offline Downloader '%1:%2'...'%3'...'%4'...'%5'").arg(ip).arg(port).arg(pid).arg(ptoc).arg(country)); ++ tempblockIP(ip); ++ } ++ } ++ } ++ } ++ } ++} ++ + // Delete a torrent from the session, given its hash + // deleteLocalFiles = true means that the torrent will be removed from the hard-drive too + bool Session::deleteTorrent(const QString &hash, bool deleteLocalFiles) +@@ -2787,6 +2892,30 @@ void Session::setSaveResumeDataInterval( + } + } + ++bool Session::isAutoBanUnknownPeerEnabled() const ++{ ++ return m_autoBanUnknownPeer; ++} ++ ++void Session::setAutoBanUnknownPeer(bool value) ++{ ++ if (value != isAutoBanUnknownPeerEnabled()) { ++ m_autoBanUnknownPeer = value; ++ } ++} ++ ++bool Session::isShowTrackerAuthWindow() const ++{ ++ return m_showTrackerAuthWindow; ++} ++ ++void Session::setShowTrackerAuthWindow(bool value) ++{ ++ if (value != isShowTrackerAuthWindow()) { ++ m_showTrackerAuthWindow = value; ++ } ++} ++ + int Session::port() const + { + static int randomPort = Utils::Random::rand(1024, 65535); +@@ -3877,6 +4006,220 @@ void Session::disableIPFilter() + m_nativeSession->set_ip_filter(filter); + } + ++// Insert banned IP to Queue ++void Session::insertQueue(QString ip) ++{ ++ q_bannedIPs.enqueue(ip); ++ q_unbanTime.enqueue(QDateTime::currentMSecsSinceEpoch() + 60 * 60 * 1000); ++ ++ if (!m_unbanTimer->isActive()) { ++ m_unbanTimer->start(); ++ } ++} ++ ++// Process Unban Queue ++void Session::processUnbanRequest() ++{ ++ if (q_bannedIPs.isEmpty() && q_unbanTime.isEmpty()) { ++ m_unbanTimer->stop(); ++ } ++ else if (m_isActive) { ++ return; ++ } ++ else { ++ m_isActive = true; ++ int64_t currentTime = QDateTime::currentMSecsSinceEpoch(); ++ int64_t nextTime = q_unbanTime.dequeue(); ++ int delayTime = int(nextTime - currentTime); ++ QString nextIP = q_bannedIPs.dequeue(); ++ if (delayTime < 0) { ++ QTimer::singleShot(0, [=] { BitTorrent::Session::instance()->removeBlockedIP(nextIP); m_isActive = false; }); ++ } ++ else { ++ QTimer::singleShot(delayTime, [=] { BitTorrent::Session::instance()->removeBlockedIP(nextIP); m_isActive = false; }); ++ } ++ } ++} ++ ++// Handle ipfilter.dat ++int trim(char* const data, int start, int end) ++{ ++ if (start >= end) return start; ++ int newStart = start; ++ ++ for (int i = start; i <= end; ++i) { ++ if (isspace(data[i]) != 0) { ++ data[i] = '\0'; ++ } ++ else { ++ newStart = i; ++ break; ++ } ++ } ++ ++ for (int i = end; i >= start; --i) { ++ if (isspace(data[i]) != 0) ++ data[i] = '\0'; ++ else ++ break; ++ } ++ ++ return newStart; ++} ++ ++int findAndNullDelimiter(char *const data, char delimiter, int start, int end) ++{ ++ for (int i = start; i <= end; ++i) { ++ if (data[i] == delimiter) { ++ data[i] = '\0'; ++ return i; ++ } ++ } ++ ++ return -1; ++} ++ ++int Session::parseOfflineFilterFile(QString ipDat, libt::ip_filter &filter) ++{ ++ int ruleCount = 0; ++ QFile file(ipDat); ++ if (!file.exists()) return ruleCount; ++ ++ if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { ++ LogMsg(tr("I/O Error: Could not open IP filter file in read mode."), Log::CRITICAL); ++ return ruleCount; ++ } ++ ++ std::vector buffer(2 * 1024 * 1024, 0); // seems a bit faster than QVector ++ qint64 bytesRead = 0; ++ int offset = 0; ++ int start = 0; ++ int endOfLine = -1; ++ int nbLine = 0; ++ ++ while (true) { ++ bytesRead = file.read(buffer.data() + offset, 2 * 1024 * 1024 - offset - 1); ++ if (bytesRead < 0) ++ break; ++ int dataSize = bytesRead + offset; ++ if (bytesRead == 0 && dataSize == 0) ++ break; ++ ++ for (start = 0; start < dataSize; ++start) { ++ endOfLine = -1; ++ // The file might have ended without the last line having a newline ++ if (!(bytesRead == 0 && dataSize > 0)) { ++ for (int i = start; i < dataSize; ++i) { ++ if (buffer[i] == '\n') { ++ endOfLine = i; ++ // We need to NULL the newline in case the line has only an IP range. ++ // In that case the parser won't work for the end IP, because it ends ++ // with the newline and not with a number. ++ buffer[i] = '\0'; ++ break; ++ } ++ } ++ } ++ else { ++ endOfLine = dataSize; ++ buffer[dataSize] = '\0'; ++ } ++ ++ if (endOfLine == -1) { ++ // read the next chunk from file ++ // but first move(copy) the leftover data to the front of the buffer ++ offset = dataSize - start; ++ memmove(buffer.data(), buffer.data() + start, offset); ++ break; ++ } ++ else { ++ ++nbLine; ++ } ++ ++ if ((buffer[start] == '#') ++ || ((buffer[start] == '/') && ((start + 1 < dataSize) && (buffer[start + 1] == '/')))) { ++ start = endOfLine; ++ continue; ++ } ++ ++ // Each line should follow this format: ++ // 001.009.096.105 - 001.009.096.105 , 000 , Some organization ++ // The 3rd entry is access level and if above 127 the IP range isn't blocked. ++ int firstComma = findAndNullDelimiter(buffer.data(), ',', start, endOfLine); ++ if (firstComma != -1) ++ findAndNullDelimiter(buffer.data(), ',', firstComma + 1, endOfLine); ++ ++ // Check if there is an access value (apparently not mandatory) ++ if (firstComma != -1) { ++ // There is possibly one ++ const long int nbAccess = strtol(buffer.data() + firstComma + 1, nullptr, 10); ++ // Ignoring this rule because access value is too high ++ if (nbAccess > 127L) { ++ start = endOfLine; ++ continue; ++ } ++ } ++ ++ // IP Range should be split by a dash ++ int endOfIPRange = ((firstComma == -1) ? (endOfLine - 1) : (firstComma - 1)); ++ int delimIP = findAndNullDelimiter(buffer.data(), '-', start, endOfIPRange); ++ if (delimIP == -1) { ++ start = endOfLine; ++ continue; ++ } ++ ++ boost::system::error_code ec; ++ int newStart = trim(buffer.data(), start, delimIP - 1); ++ libt::address startAddr = libt::address::from_string(buffer.data() + newStart, ec); ++ Q_ASSERT(!ec); ++ if (ec) { ++ start = endOfLine; ++ continue; ++ } ++ ++ newStart = trim(buffer.data(), delimIP + 1, endOfIPRange); ++ libt::address endAddr = libt::address::from_string(buffer.data() + newStart, ec); ++ Q_ASSERT(!ec); ++ if (ec) { ++ start = endOfLine; ++ continue; ++ } ++ ++ if ((startAddr.is_v4() != endAddr.is_v4()) ++ || (startAddr.is_v6() != endAddr.is_v6())) { ++ start = endOfLine; ++ continue; ++ } ++ ++ start = endOfLine; ++ ++ filter.add_rule(startAddr, endAddr, libt::ip_filter::blocked); ++ ++ruleCount; ++ } ++ ++ if (start >= dataSize) ++ offset = 0; ++ } ++ ++ return ruleCount; ++} ++ ++void Session::loadOfflineFilter() { ++ int Count = 0; ++ libt::ip_filter offlineFilter = m_nativeSession->get_ip_filter(); ++ ++#if defined(Q_OS_WIN) ++ Count = parseOfflineFilterFile("./ipfilter.dat", offlineFilter); ++#endif ++ ++#if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC)) ++ Count = parseOfflineFilterFile(QDir::home().absoluteFilePath(".config")+"/qBittorrent/ipfilter.dat", offlineFilter); ++#endif ++ ++ m_nativeSession->set_ip_filter(offlineFilter); ++ Logger::instance()->addMessage(tr("Successfully parsed the offline downloader IP filter: %1 rules were applied.", "%1 is a number").arg(Count)); ++} ++ + void Session::recursiveTorrentDownload(const InfoHash &hash) + { + TorrentHandle *const torrent = m_torrents.value(hash); +@@ -4063,6 +4406,7 @@ void Session::handleIPFilterParsed(int r + } + Logger::instance()->addMessage(tr("Successfully parsed the provided IP filter: %1 rules were applied.", "%1 is a number").arg(ruleCount)); + emit IPFilterParsed(false, ruleCount); ++ loadOfflineFilter(); + } + + void Session::handleIPFilterError() +--- a/src/base/bittorrent/session.h ++++ b/src/base/bittorrent/session.h +@@ -40,8 +40,10 @@ + #include + #include + #include ++#include + #include + #include ++#include + #include + #include + +@@ -341,6 +343,10 @@ namespace BitTorrent + + uint saveResumeDataInterval() const; + void setSaveResumeDataInterval(uint value); ++ bool isAutoBanUnknownPeerEnabled() const; ++ void setAutoBanUnknownPeer(bool value); ++ bool isShowTrackerAuthWindow() const; ++ void setShowTrackerAuthWindow(bool value); + int port() const; + void setPort(int port); + bool useRandomPort() const; +@@ -467,6 +473,19 @@ namespace BitTorrent + void setMaxRatioAction(MaxRatioAction act); + + void banIP(const QString &ip); ++ bool checkAccessFlags(const QString &ip); ++ void tempblockIP(const QString &ip); ++ void removeBlockedIP(const QString &ip); ++ void eraseIPFilter(); ++ void autoBanBadClient(); ++ ++ // Unban Timer ++ bool m_isActive = false; ++ QQueue q_bannedIPs; ++ QQueue q_unbanTime; ++ QTimer *m_unbanTimer; ++ QTimer *m_banTimer; ++ void insertQueue(QString ip); + + bool isKnownTorrent(const InfoHash &hash) const; + bool addTorrent(QString source, const AddTorrentParams ¶ms = AddTorrentParams()); +@@ -546,6 +565,9 @@ namespace BitTorrent + void tagAdded(const QString &tag); + void tagRemoved(const QString &tag); + ++ public slots: ++ void processUnbanRequest(); ++ + private slots: + void configureDeferred(); + void readAlerts(); +@@ -601,6 +623,8 @@ namespace BitTorrent + void populateAdditionalTrackers(); + void enableIPFilter(); + void disableIPFilter(); ++ int parseOfflineFilterFile(QString ipDat, libtorrent::ip_filter &filter); ++ void loadOfflineFilter(); + + bool addTorrent_impl(CreateTorrentParams params, const MagnetUri &magnetUri, + TorrentInfo torrentInfo = TorrentInfo(), +@@ -713,6 +737,8 @@ namespace BitTorrent + CachedSettingValue m_isAltGlobalSpeedLimitEnabled; + CachedSettingValue m_isBandwidthSchedulerEnabled; + CachedSettingValue m_saveResumeDataInterval; ++ CachedSettingValue m_autoBanUnknownPeer; ++ CachedSettingValue m_showTrackerAuthWindow; + CachedSettingValue m_port; + CachedSettingValue m_useRandomPort; + CachedSettingValue m_networkInterface; +--- a/src/base/bittorrent/torrenthandle.cpp ++++ b/src/base/bittorrent/torrenthandle.cpp +@@ -1561,7 +1561,8 @@ void TorrentHandle::handleTrackerErrorAl + m_trackerInfos[trackerUrl].lastMessage = message; + + if (p->status_code == 401) +- m_session->handleTorrentTrackerAuthenticationRequired(this, trackerUrl); ++ if (Preferences::instance()->getShowTrackerAuthWindow()) ++ m_session->handleTorrentTrackerAuthenticationRequired(this, trackerUrl); + + m_session->handleTorrentTrackerError(this, trackerUrl); + } +--- a/src/base/preferences.cpp ++++ b/src/base/preferences.cpp +@@ -1090,6 +1090,26 @@ void Preferences::setTrayIconStyle(TrayI + } + #endif + ++bool Preferences::getAutoBanUnknownPeer() const ++{ ++ return value("Preferences/Advanced/AutoBanUnknownPeer", false).toBool(); ++} ++ ++void Preferences::setAutoBanUnknownPeer(const bool checked) ++{ ++ setValue("Preferences/Advanced/AutoBanUnknownPeer", checked); ++} ++ ++bool Preferences::getShowTrackerAuthWindow() const ++{ ++ return value("Preferences/Advanced/ShowTrackerAuthWindow", true).toBool(); ++} ++ ++void Preferences::setShowTrackerAuthWindow(const bool checked) ++{ ++ setValue("Preferences/Advanced/ShowTrackerAuthWindow", checked); ++} ++ + // Stuff that don't appear in the Options GUI but are saved + // in the same file. + +--- a/src/base/preferences.h ++++ b/src/base/preferences.h +@@ -300,6 +300,10 @@ public: + TrayIcon::Style trayIconStyle() const; + void setTrayIconStyle(TrayIcon::Style style); + #endif // Q_OS_MAC ++ bool getAutoBanUnknownPeer() const; ++ void setAutoBanUnknownPeer(const bool checked); ++ bool getShowTrackerAuthWindow() const; ++ void setShowTrackerAuthWindow(const bool checked); + + // Stuff that don't appear in the Options GUI but are saved + // in the same file. +--- a/src/base/settingsstorage.cpp ++++ b/src/base/settingsstorage.cpp +@@ -91,6 +91,8 @@ namespace + {"BitTorrent/Session/InterfaceName", "Preferences/Connection/InterfaceName"}, + {"BitTorrent/Session/InterfaceAddress", "Preferences/Connection/InterfaceAddress"}, + {"BitTorrent/Session/SaveResumeDataInterval", "Preferences/Downloads/SaveResumeDataInterval"}, ++ {"BitTorrent/Session/AutoBanUnknownPeer", "Preferences/Advanced/AutoBanUnknownPeer"}, ++ {"BitTorrent/Session/ShowTrackerAuthWindow", "Preferences/Advanced/ShowTrackerAuthWindow"}, + {"BitTorrent/Session/Encryption", "Preferences/Bittorrent/Encryption"}, + {"BitTorrent/Session/ForceProxy", "Preferences/Connection/ProxyForce"}, + {"BitTorrent/Session/ProxyPeerConnections", "Preferences/Connection/ProxyPeerConnections"}, +--- a/src/gui/advancedsettings.cpp ++++ b/src/gui/advancedsettings.cpp +@@ -60,6 +60,8 @@ enum AdvSettingsRows + NETWORK_LISTEN_IPV6, + // behavior + SAVE_RESUME_DATA_INTERVAL, ++ CONFIRM_AUTO_BAN, ++ SHOW_TRACKER_AUTH_WINDOW, + CONFIRM_RECHECK_TORRENT, + RECHECK_COMPLETED, + #if defined(Q_OS_WIN) || defined(Q_OS_MAC) +@@ -215,6 +217,10 @@ void AdvancedSettings::saveAdvancedSetti + // Announce IP + QHostAddress addr(lineEditAnnounceIP.text().trimmed()); + session->setAnnounceIP(addr.isNull() ? "" : addr.toString()); ++ // Auto ban Unknown Peer ++ session->setAutoBanUnknownPeer(cb_auto_ban_unknown_peer.isChecked()); ++ // Show Tracker Authenticaion Window ++ session->setShowTrackerAuthWindow(cb_show_tracker_auth_window.isChecked()); + + // Program notification + MainWindow *const mainWindow = static_cast(QCoreApplication::instance())->mainWindow(); +@@ -465,6 +471,12 @@ void AdvancedSettings::loadAdvancedSetti + // Announce IP + lineEditAnnounceIP.setText(session->announceIP()); + addRow(ANNOUNCE_IP, tr("IP Address to report to trackers (requires restart)"), &lineEditAnnounceIP); ++ // Auto Ban Unknown Peer from China ++ cb_auto_ban_unknown_peer.setChecked(session->isAutoBanUnknownPeerEnabled()); ++ addRow(CONFIRM_AUTO_BAN, tr("Auto Ban Unknown Peer from China"), &cb_auto_ban_unknown_peer); ++ // Show Tracker Authenticaion Window ++ cb_show_tracker_auth_window.setChecked(session->isShowTrackerAuthWindow()); ++ addRow(SHOW_TRACKER_AUTH_WINDOW, tr("Show Tracker Authenticaion Window"), &cb_show_tracker_auth_window); + + // Program notifications + const MainWindow *const mainWindow = static_cast(QCoreApplication::instance())->mainWindow(); +--- a/src/gui/advancedsettings.h ++++ b/src/gui/advancedsettings.h +@@ -65,7 +65,8 @@ private: + QCheckBox checkBoxOsCache, checkBoxRecheckCompleted, checkBoxResolveCountries, checkBoxResolveHosts, checkBoxSuperSeeding, + checkBoxProgramNotifications, checkBoxTorrentAddedNotifications, checkBoxTrackerFavicon, checkBoxTrackerStatus, + checkBoxConfirmTorrentRecheck, checkBoxConfirmRemoveAllTags, checkBoxListenIPv6, checkBoxAnnounceAllTrackers, checkBoxAnnounceAllTiers, +- checkBoxGuidedReadCache, checkBoxMultiConnectionsPerIp, checkBoxSuggestMode, checkBoxCoalesceRW, checkBoxSpeedWidgetEnabled; ++ checkBoxGuidedReadCache, checkBoxMultiConnectionsPerIp, checkBoxSuggestMode, checkBoxCoalesceRW, checkBoxSpeedWidgetEnabled, ++ cb_auto_ban_unknown_peer, cb_show_tracker_auth_window; + QComboBox comboBoxInterface, comboBoxInterfaceAddress, comboBoxUtpMixedMode, comboBoxChokingAlgorithm, comboBoxSeedChokingAlgorithm; + QLineEdit lineEditAnnounceIP; + +--- a/src/gui/mainwindow.cpp ++++ b/src/gui/mainwindow.cpp +@@ -73,6 +73,7 @@ + #include "addnewtorrentdialog.h" + #include "application.h" + #include "autoexpandabledialog.h" ++#include "base/bittorrent/peerinfo.h" + #include "cookiesdialog.h" + #include "downloadfromurldialog.h" + #include "executionlogwidget.h" +--- a/src/gui/properties/peerlistdelegate.h ++++ b/src/gui/properties/peerlistdelegate.h +@@ -49,6 +49,7 @@ public: + CONNECTION, + FLAGS, + CLIENT, ++ PEERID, + PROGRESS, + DOWN_SPEED, + UP_SPEED, +--- a/src/gui/properties/peerlistwidget.cpp ++++ b/src/gui/properties/peerlistwidget.cpp +@@ -75,6 +75,7 @@ PeerListWidget::PeerListWidget(Propertie + m_listModel->setHeaderData(PeerListDelegate::FLAGS, Qt::Horizontal, tr("Flags")); + m_listModel->setHeaderData(PeerListDelegate::CONNECTION, Qt::Horizontal, tr("Connection")); + m_listModel->setHeaderData(PeerListDelegate::CLIENT, Qt::Horizontal, tr("Client", "i.e.: Client application")); ++ m_listModel->setHeaderData(PeerListDelegate::PEERID, Qt::Horizontal, tr("Peer ID", "i.e.: Client Peer ID")); + m_listModel->setHeaderData(PeerListDelegate::PROGRESS, Qt::Horizontal, tr("Progress", "i.e: % downloaded")); + m_listModel->setHeaderData(PeerListDelegate::DOWN_SPEED, Qt::Horizontal, tr("Down Speed", "i.e: Download speed")); + m_listModel->setHeaderData(PeerListDelegate::UP_SPEED, Qt::Horizontal, tr("Up Speed", "i.e: Upload speed")); +@@ -288,8 +289,13 @@ void PeerListWidget::banSelectedPeers() + for (const QModelIndex &index : selectedIndexes) { + int row = m_proxyModel->mapToSource(index).row(); + QString ip = m_listModel->data(m_listModel->index(row, PeerListDelegate::IP_HIDDEN)).toString(); ++ QString client = m_listModel->data(m_listModel->index(row, PeerListDelegate::CLIENT)).toString(); ++ QString peerid = m_listModel->data(m_listModel->index(row, PeerListDelegate::PEERID)).toString(); ++ QHostAddress host; ++ host.setAddress(ip); ++ const QString countryName = Net::GeoIPManager::CountryName(Net::GeoIPManager::instance()->lookup(host)); + qDebug("Banning peer %s...", ip.toLocal8Bit().data()); +- Logger::instance()->addMessage(tr("Manually banning peer '%1'...").arg(ip)); ++ Logger::instance()->addMessage(tr("Manually banning peer '%1'...'%2'...'%3'...'%4'").arg(ip).arg(peerid).arg(client).arg(countryName)); + BitTorrent::Session::instance()->banIP(ip); + } + // Refresh list +@@ -398,6 +404,7 @@ QStandardItem *PeerListWidget::addPeer(c + m_listModel->setData(m_listModel->index(row, PeerListDelegate::FLAGS), peer.flags()); + m_listModel->setData(m_listModel->index(row, PeerListDelegate::FLAGS), peer.flagsDescription(), Qt::ToolTipRole); + m_listModel->setData(m_listModel->index(row, PeerListDelegate::CLIENT), peer.client().toHtmlEscaped()); ++ m_listModel->setData(m_listModel->index(row, PeerListDelegate::PEERID), peer.pid().left(8).toHtmlEscaped()); + m_listModel->setData(m_listModel->index(row, PeerListDelegate::PROGRESS), peer.progress()); + m_listModel->setData(m_listModel->index(row, PeerListDelegate::DOWN_SPEED), peer.payloadDownSpeed()); + m_listModel->setData(m_listModel->index(row, PeerListDelegate::UP_SPEED), peer.payloadUpSpeed()); +@@ -429,6 +436,7 @@ void PeerListWidget::updatePeer(const QS + m_listModel->setData(m_listModel->index(row, PeerListDelegate::FLAGS), peer.flags()); + m_listModel->setData(m_listModel->index(row, PeerListDelegate::FLAGS), peer.flagsDescription(), Qt::ToolTipRole); + m_listModel->setData(m_listModel->index(row, PeerListDelegate::CLIENT), peer.client().toHtmlEscaped()); ++ m_listModel->setData(m_listModel->index(row, PeerListDelegate::PEERID), peer.pid().left(8).toHtmlEscaped()); + m_listModel->setData(m_listModel->index(row, PeerListDelegate::PROGRESS), peer.progress()); + m_listModel->setData(m_listModel->index(row, PeerListDelegate::DOWN_SPEED), peer.payloadDownSpeed()); + m_listModel->setData(m_listModel->index(row, PeerListDelegate::UP_SPEED), peer.payloadUpSpeed()); +--- a/src/webui/api/appcontroller.cpp ++++ b/src/webui/api/appcontroller.cpp +@@ -153,6 +153,7 @@ void AppController::preferencesAction() + data["ip_filter_path"] = Utils::Fs::toNativePath(session->IPFilterFile()); + data["ip_filter_trackers"] = session->isTrackerFilteringEnabled(); + data["banned_IPs"] = session->bannedIPs().join("\n"); ++ data["auto_ban_unknown_peer"] = session->isAutoBanUnknownPeerEnabled(); + + // Speed + // Global Rate Limits +@@ -401,6 +402,8 @@ void AppController::setPreferencesAction + session->setTrackerFilteringEnabled(m["ip_filter_trackers"].toBool()); + if (m.contains("banned_IPs")) + session->setBannedIPs(m["banned_IPs"].toString().split('\n')); ++ if (m.contains("auto_ban_unknown_peer")) ++ session->setAutoBanUnknownPeer(m["auto_ban_unknown_peer"].toBool()); + + // Speed + // Global Rate Limits +--- a/src/webui/api/transfercontroller.cpp ++++ b/src/webui/api/transfercontroller.cpp +@@ -30,6 +30,7 @@ + + #include + ++#include "base/logger.h" + #include "base/bittorrent/session.h" + + const char KEY_TRANSFER_DLSPEED[] = "dl_info_speed"; +@@ -111,3 +112,37 @@ void TransferController::speedLimitsMode + { + setResult(QString::number(BitTorrent::Session::instance()->isAltGlobalSpeedLimitEnabled())); + } ++ ++void TransferController::tempblockPeerAction() ++{ ++ checkParams({"ip"}); ++ QString ip = params()["ip"]; ++ boost::system::error_code ec; ++ boost::asio::ip::address addr = boost::asio::ip::address::from_string(ip.toStdString(), ec); ++ bool isBanned = BitTorrent::Session::instance()->checkAccessFlags(QString::fromStdString(addr.to_string())); ++ ++ if (ip.isEmpty()) { ++ setResult(QLatin1String("IP field should not be empty.")); ++ return; ++ } ++ ++ if (ec) { ++ setResult(QLatin1String("The given IP address is not valid.")); ++ return; ++ } ++ ++ if (isBanned) { ++ setResult(QLatin1String("The given IP address already exists.")); ++ return; ++ } ++ ++ BitTorrent::Session::instance()->tempblockIP(ip); ++ Logger::instance()->addMessage(tr("Peer '%1' banned via Web API.").arg(ip)); ++ setResult(QLatin1String("Done.")); ++} ++ ++void TransferController::resetIPFilterAction() ++{ ++ BitTorrent::Session::instance()->eraseIPFilter(); ++ setResult(QLatin1String("Erased.")); ++} +--- a/src/webui/api/transfercontroller.h ++++ b/src/webui/api/transfercontroller.h +@@ -46,4 +46,6 @@ private slots: + void downloadLimitAction(); + void setUploadLimitAction(); + void setDownloadLimitAction(); ++ void tempblockPeerAction(); ++ void resetIPFilterAction(); + }; +--- a/src/webui/www/private/preferences_content.html ++++ b/src/webui/www/private/preferences_content.html +@@ -377,6 +377,8 @@ + + + ++ ++ + + + +@@ -1252,6 +1254,7 @@ + $('ipfilter_text').setProperty('value', pref.ip_filter_path); + $('ipfilter_trackers_checkbox').setProperty('checked', pref.ip_filter_trackers); + $('banned_IPs_textarea').setProperty('value', pref.banned_IPs); ++ $('auto_ban_unknown_peer_checkbox').setProperty('checked', pref.auto_ban_unknown_peer); + updateFilterSettings(); + + // Speed tab +@@ -1502,6 +1505,7 @@ + settings.set('ip_filter_path', $('ipfilter_text').getProperty('value')); + settings.set('ip_filter_trackers', $('ipfilter_trackers_checkbox').getProperty('checked')); + settings.set('banned_IPs', $('banned_IPs_textarea').getProperty('value')); ++ settings.set('auto_ban_unknown_peer', $('auto_ban_unknown_peer_checkbox').getProperty('checked')); + + // Speed tab + // Global Rate Limits