From 7c8455115008fd65283e6c4b4f17490105a04f42 Mon Sep 17 00:00:00 2001 From: Christophe Dumez Date: Tue, 17 Nov 2009 16:02:35 +0000 Subject: [PATCH] - Support peer manual ban (from peer list) --- Changelog | 1 + src/Icons/oxygen/add_peer.png | Bin 644 -> 0 bytes src/Icons/oxygen/user-group-delete.png | Bin 0 -> 1365 bytes src/Icons/oxygen/user-group-new.png | Bin 0 -> 1274 bytes src/bittorrent.cpp | 6 +++++ src/bittorrent.h | 1 + src/filterParserThread.h | 13 +++++++++ src/icons.qrc | 3 ++- src/peerlistdelegate.h | 2 +- src/peerlistwidget.cpp | 35 ++++++++++++++++++++++--- src/peerlistwidget.h | 1 + src/preferences.h | 15 +++++++++++ src/propertieswidget.cpp | 4 +++ src/propertieswidget.h | 1 + 14 files changed, 77 insertions(+), 5 deletions(-) delete mode 100644 src/Icons/oxygen/add_peer.png create mode 100644 src/Icons/oxygen/user-group-delete.png create mode 100644 src/Icons/oxygen/user-group-new.png diff --git a/Changelog b/Changelog index 77a9a97ee..1153b3ebd 100644 --- a/Changelog +++ b/Changelog @@ -24,6 +24,7 @@ - FEATURE: Torrents can be rechecked from Web UI (Stephanos Antaris) - FEATURE: New peers can manually be added to the torrents - FEATURE: Support per-peer rate limiting + - FEATURE: Support peer manual ban - COSMETIC: Merged download / upload lists - COSMETIC: Torrents can be filtered based on their status - COSMETIC: Torrent properties are now displayed in main window diff --git a/src/Icons/oxygen/add_peer.png b/src/Icons/oxygen/add_peer.png deleted file mode 100644 index a28a8a2e9b15d06117662dab7e428a05e5af59fe..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 644 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 if(isRunning()) { // Already parsing a filter, abort first abort = true; @@ -400,6 +402,17 @@ class FilterParserThread : public QThread { start(); } + static void processFilterList(session *s, QStringList IPs) { + // First, import current filter + ip_filter filter = s->get_ip_filter(); + foreach(const QString &ip, IPs) { + qDebug("Manual ban of peer %s", ip.toLocal8Bit().data()); + address_v4 addr = address_v4::from_string(ip.toLocal8Bit().data()); + filter.add_rule(addr, addr, ip_filter::blocked); + } + s->set_ip_filter(filter); + } + }; #endif diff --git a/src/icons.qrc b/src/icons.qrc index 7214c0166..239136387 100644 --- a/src/icons.qrc +++ b/src/icons.qrc @@ -105,6 +105,8 @@ Icons/oxygen/edit-paste.png Icons/oxygen/run-build.png Icons/oxygen/proxy.png + Icons/oxygen/user-group-delete.png + Icons/oxygen/user-group-new.png Icons/oxygen/log.png Icons/oxygen/unavailable.png Icons/oxygen/button_ok.png @@ -142,6 +144,5 @@ Icons/oxygen/unsubscribe.png Icons/oxygen/draw-rectangle.png Icons/oxygen/subscribe16.png - Icons/oxygen/add_peer.png \ No newline at end of file diff --git a/src/peerlistdelegate.h b/src/peerlistdelegate.h index 9652b8fcd..7408a6de4 100644 --- a/src/peerlistdelegate.h +++ b/src/peerlistdelegate.h @@ -34,7 +34,7 @@ #include #include "misc.h" -enum PeerListColumns {IP, CLIENT, PROGRESS, DOWN_SPEED, UP_SPEED, TOT_DOWN, TOT_UP}; +enum PeerListColumns {IP, CLIENT, PROGRESS, DOWN_SPEED, UP_SPEED, TOT_DOWN, TOT_UP, IP_HIDDEN}; class PeerListDelegate: public QItemDelegate { Q_OBJECT diff --git a/src/peerlistwidget.cpp b/src/peerlistwidget.cpp index b7729c8ef..74e62e83e 100644 --- a/src/peerlistwidget.cpp +++ b/src/peerlistwidget.cpp @@ -48,8 +48,9 @@ PeerListWidget::PeerListWidget(PropertiesWidget *parent): properties(parent), di setRootIsDecorated(false); setItemsExpandable(false); setAllColumnsShowFocus(true); + setSelectionMode(QAbstractItemView::ExtendedSelection); // List Model - listModel = new QStandardItemModel(0, 7); + listModel = new QStandardItemModel(0, 8); listModel->setHeaderData(IP, Qt::Horizontal, tr("IP")); listModel->setHeaderData(CLIENT, Qt::Horizontal, tr("Client", "i.e.: Client application")); listModel->setHeaderData(PROGRESS, Qt::Horizontal, tr("Progress", "i.e: % downloaded")); @@ -62,6 +63,7 @@ PeerListWidget::PeerListWidget(PropertiesWidget *parent): properties(parent), di proxyModel->setDynamicSortFilter(true); proxyModel->setSourceModel(listModel); setModel(proxyModel); + hideColumn(IP_HIDDEN); // Context menu setContextMenuPolicy(Qt::CustomContextMenu); connect(this, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showPeerListMenu(QPoint))); @@ -112,26 +114,33 @@ void PeerListWidget::updatePeerCountryResolutionState() { void PeerListWidget::showPeerListMenu(QPoint) { QMenu menu; + bool empty_menu = true; QTorrentHandle h = properties->getCurrentTorrent(); if(!h.is_valid()) return; QModelIndexList selectedIndexes = selectionModel()->selectedRows(); QStringList selectedPeerIPs; foreach(const QModelIndex &index, selectedIndexes) { - QString IP = proxyModel->data(index).toString(); + int row = proxyModel->mapToSource(index).row(); + QString IP = listModel->data(listModel->index(row, IP_HIDDEN)).toString(); selectedPeerIPs << IP; } // Add Peer Action QAction *addPeerAct = 0; if(!h.is_queued() && !h.is_checking()) { - addPeerAct = menu.addAction(QIcon(":/Icons/oxygen/add_peer.png"), tr("Add a new peer")); + addPeerAct = menu.addAction(QIcon(":/Icons/oxygen/user-group-new.png"), tr("Add a new peer")); + empty_menu = false; } // Per Peer Speed limiting actions QAction *upLimitAct = 0; QAction *dlLimitAct = 0; + QAction *banAct = 0; if(!selectedPeerIPs.isEmpty()) { upLimitAct = menu.addAction(QIcon(":/Icons/skin/seeding.png"), tr("Limit upload rate")); dlLimitAct = menu.addAction(QIcon(":/Icons/skin/downloading.png"), tr("Limit download rate")); + banAct = menu.addAction(QIcon(":/Icons/oxygen/user-group-delete.png"), tr("Ban peer permanently")); + empty_menu = false; } + if(empty_menu) return; QAction *act = menu.exec(QCursor::pos()); if(act == addPeerAct) { boost::asio::ip::tcp::endpoint ep = PeerAdditionDlg::askForPeerEndpoint(); @@ -155,6 +164,25 @@ void PeerListWidget::showPeerListMenu(QPoint) { limitDlRateSelectedPeers(selectedPeerIPs); return; } + if(act == banAct) { + banSelectedPeers(selectedPeerIPs); + return; + } +} + +void PeerListWidget::banSelectedPeers(QStringList peer_ips) { + // Confirm first + int ret = QMessageBox::question(this, tr("Are you sure? -- qBittorrent"), tr("Are you sure you want to ban permanently the selected peers?"), + tr("&Yes"), tr("&No"), + QString(), 0, 1); + if(ret) return; + foreach(const QString &ip, peer_ips) { + qDebug("Banning peer %s...", ip.toLocal8Bit().data()); + properties->getBTSession()->addConsoleMessage(tr("Manually banning peer %1...").arg(ip)); + properties->getBTSession()->banIP(ip); + } + // Refresh list + loadPeers(properties->getCurrentTorrent()); } void PeerListWidget::limitUpRateSelectedPeers(QStringList peer_ips) { @@ -270,6 +298,7 @@ QStandardItem* PeerListWidget::addPeer(QString ip, peer_info peer) { // Adding Peer to peer list listModel->insertRow(row); listModel->setData(listModel->index(row, IP), ip); + listModel->setData(listModel->index(row, IP_HIDDEN), ip); // Resolve peer host name is asked if(resolver) resolver->resolve(peer.ip); diff --git a/src/peerlistwidget.h b/src/peerlistwidget.h index 35b9a0049..ee15cd7bb 100644 --- a/src/peerlistwidget.h +++ b/src/peerlistwidget.h @@ -78,6 +78,7 @@ protected slots: void showPeerListMenu(QPoint); void limitUpRateSelectedPeers(QStringList peer_ips); void limitDlRateSelectedPeers(QStringList peer_ips); + void banSelectedPeers(QStringList peer_ips); }; #endif // PEERLISTWIDGET_H diff --git a/src/preferences.h b/src/preferences.h index 6bf7df93c..cf02933e2 100644 --- a/src/preferences.h +++ b/src/preferences.h @@ -367,6 +367,20 @@ public: return settings.value(QString::fromUtf8("Preferences/IPFilter/File"), QString()).toString(); } + static void banIP(QString ip) { + QSettings settings("qBittorrent", "qBittorrent"); + QStringList banned_ips = settings.value(QString::fromUtf8("Preferences/IPFilter/BannedIPs"), QStringList()).toStringList(); + if(!banned_ips.contains(ip)) { + banned_ips << ip; + settings.setValue("Preferences/IPFilter/BannedIPs", banned_ips); + } + } + + static QStringList bannedIPs() { + QSettings settings("qBittorrent", "qBittorrent"); + return settings.value(QString::fromUtf8("Preferences/IPFilter/BannedIPs"), QStringList()).toStringList(); + } + // RSS static bool isRSSEnabled() { QSettings settings("qBittorrent", "qBittorrent"); @@ -423,6 +437,7 @@ public: QSettings settings("qBittorrent", "qBittorrent"); return settings.value("Preferences/WebUI/Password", "").toString(); } + }; #endif // PREFERENCES_H diff --git a/src/propertieswidget.cpp b/src/propertieswidget.cpp index a05a59fe3..ff1413f7b 100644 --- a/src/propertieswidget.cpp +++ b/src/propertieswidget.cpp @@ -186,6 +186,10 @@ const QTorrentHandle& PropertiesWidget::getCurrentTorrent() const { return h; } +bittorrent* PropertiesWidget::getBTSession() const { + return BTSession; +} + void PropertiesWidget::loadTorrentInfos(QTorrentHandle &_h) { h = _h; if(!h.is_valid()) { diff --git a/src/propertieswidget.h b/src/propertieswidget.h index cefce5e4b..896174705 100644 --- a/src/propertieswidget.h +++ b/src/propertieswidget.h @@ -113,6 +113,7 @@ public: PropertiesWidget(QWidget *parent, TransferListWidget *transferList, bittorrent* BTSession); ~PropertiesWidget(); const QTorrentHandle& getCurrentTorrent() const; + bittorrent* getBTSession() const; }; #endif // PROPERTIESWIDGET_H