From 59de1af31bcdcb3c6d0390ef59391d07c8616fd9 Mon Sep 17 00:00:00 2001 From: dzmat Date: Mon, 6 Mar 2017 19:40:34 +0700 Subject: [PATCH] implemented UI for managment of locally banned IP list (Closes #1837 ) --- src/base/base.pri | 2 + src/base/bittorrent/session.cpp | 59 ++++++++- src/base/bittorrent/session.h | 2 + src/base/utils/net.cpp | 42 +++++++ src/base/utils/net.h | 41 +++++++ src/gui/banlistoptions.cpp | 99 +++++++++++++++ src/gui/banlistoptions.h | 58 +++++++++ src/gui/banlistoptions.ui | 115 ++++++++++++++++++ src/gui/gui.pri | 9 +- src/gui/optionsdlg.cpp | 8 ++ src/gui/optionsdlg.h | 1 + src/gui/optionsdlg.ui | 13 ++ src/webui/prefjson.cpp | 3 + src/webui/www/public/preferences_content.html | 10 ++ 14 files changed, 456 insertions(+), 6 deletions(-) create mode 100644 src/base/utils/net.cpp create mode 100644 src/base/utils/net.h create mode 100644 src/gui/banlistoptions.cpp create mode 100644 src/gui/banlistoptions.h create mode 100644 src/gui/banlistoptions.ui diff --git a/src/base/base.pri b/src/base/base.pri index 6de6d98a5..14ee8fe1c 100644 --- a/src/base/base.pri +++ b/src/base/base.pri @@ -52,6 +52,7 @@ HEADERS += \ $$PWD/utils/fs.h \ $$PWD/utils/gzip.h \ $$PWD/utils/misc.h \ + $$PWD/utils/net.h \ $$PWD/utils/random.h \ $$PWD/utils/string.h \ $$PWD/unicodestrings.h \ @@ -108,6 +109,7 @@ SOURCES += \ $$PWD/utils/fs.cpp \ $$PWD/utils/gzip.cpp \ $$PWD/utils/misc.cpp \ + $$PWD/utils/net.cpp \ $$PWD/utils/random.cpp \ $$PWD/utils/string.cpp \ $$PWD/torrentfileguard.cpp \ diff --git a/src/base/bittorrent/session.cpp b/src/base/bittorrent/session.cpp index e6b6fcd37..5669ba629 100644 --- a/src/base/bittorrent/session.cpp +++ b/src/base/bittorrent/session.cpp @@ -1,4 +1,3 @@ - /* * Bittorrent Client using Qt and libtorrent. * Copyright (C) 2015 Vladimir Golovnev @@ -74,6 +73,7 @@ #include "base/torrentfileguard.h" #include "base/torrentfilter.h" #include "base/unicodestrings.h" +#include "base/utils/net.h" #include "base/utils/misc.h" #include "base/utils/fs.h" #include "base/utils/random.h" @@ -275,7 +275,15 @@ Session::Session(QObject *parent) , m_isDisableAutoTMMWhenDefaultSavePathChanged(BITTORRENT_SESSION_KEY("DisableAutoTMMTriggers/DefaultSavePathChanged"), true) , m_isDisableAutoTMMWhenCategorySavePathChanged(BITTORRENT_SESSION_KEY("DisableAutoTMMTriggers/CategorySavePathChanged"), true) , m_isTrackerEnabled(BITTORRENT_KEY("TrackerEnabled"), false) - , m_bannedIPs("State/BannedIPs") + , m_bannedIPs("State/BannedIPs" + , QStringList() + , [](const QStringList &value) + { + QStringList tmp = value; + tmp.sort(); + return tmp; + } + ) , m_wasPexEnabled(m_isPeXEnabled) , m_numResumeData(0) , m_extraLimit(0) @@ -1376,6 +1384,7 @@ void Session::banIP(const QString &ip) m_nativeSession->set_ip_filter(filter); bannedIPs << ip; + bannedIPs.sort(); m_bannedIPs = bannedIPs; } } @@ -2379,6 +2388,45 @@ void Session::setIPFilterFile(QString path) } } +void Session::setBannedIPs(const QStringList &newList) +{ + if (newList == m_bannedIPs) + return; // do nothing + // here filter out incorrect IP + QStringList filteredList; + for (const QString &ip : newList) { + if (Utils::Net::isValidIP(ip)) { + // the same IPv6 addresses could be written in different forms; + // QHostAddress::toString() result format follows RFC5952; + // thus we avoid duplicate entries pointing to the same address + filteredList << QHostAddress(ip).toString(); + } + else { + Logger::instance()->addMessage( + tr("%1 is not a valid IP address and was rejected while applying the list of banned addresses.") + .arg(ip) + , Log::WARNING); + } + } + // now we have to sort IPs and make them unique + filteredList.sort(); + filteredList.removeDuplicates(); + // Again ensure that the new list is different from the stored one. + if (filteredList == m_bannedIPs) + return; // do nothing + // store to session settings + // also here we have to recreate filter list including 3rd party ban file + // and install it again into m_session + m_bannedIPs = filteredList; + m_IPFilteringChanged = true; + configureDeferred(); +} + +QStringList Session::bannedIPs() const +{ + return m_bannedIPs; +} + int Session::maxConnectionsPerTorrent() const { return m_maxConnectionsPerTorrent; @@ -2976,15 +3024,20 @@ void Session::configureDeferred() } // Enable IP Filtering +// this method creates ban list from scratch combining user ban list and 3rd party ban list file void Session::enableIPFilter() { qDebug("Enabling IPFilter"); + // 1. Clear existing ban list + // 2. Add manual ban list + // 3. Add 3rd party ban list + m_nativeSession->set_ip_filter(libt::ip_filter()); + processBannedIPs(); if (!m_filterParser) { m_filterParser = new FilterParserThread(m_nativeSession, this); connect(m_filterParser.data(), SIGNAL(IPFilterParsed(int)), SLOT(handleIPFilterParsed(int))); connect(m_filterParser.data(), SIGNAL(IPFilterError()), SLOT(handleIPFilterError())); } - m_filterParser->processFilterFile(IPFilterFile()); } diff --git a/src/base/bittorrent/session.h b/src/base/bittorrent/session.h index e91d20c77..f5be62299 100644 --- a/src/base/bittorrent/session.h +++ b/src/base/bittorrent/session.h @@ -326,6 +326,8 @@ namespace BitTorrent void setUTPRateLimited(bool limited); bool isTrackerFilteringEnabled() const; void setTrackerFilteringEnabled(bool enabled); + QStringList bannedIPs() const; + void setBannedIPs(const QStringList &list); TorrentHandle *findTorrent(const InfoHash &hash) const; QHash torrents() const; diff --git a/src/base/utils/net.cpp b/src/base/utils/net.cpp new file mode 100644 index 000000000..564c4d29c --- /dev/null +++ b/src/base/utils/net.cpp @@ -0,0 +1,42 @@ +/* + * Bittorrent Client using Qt and libtorrent. + * Copyright (C) 2016 Alexandr Milovantsev + * + * 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 "net.h" +#include +#include + +namespace Utils +{ + namespace Net + { + bool isValidIP(const QString &ip) + { + return !QHostAddress(ip).isNull(); + } + } +} diff --git a/src/base/utils/net.h b/src/base/utils/net.h new file mode 100644 index 000000000..65b17b0e7 --- /dev/null +++ b/src/base/utils/net.h @@ -0,0 +1,41 @@ +/* + * Bittorrent Client using Qt and libtorrent. + * Copyright (C) 2016 Alexandr Milovantsev + * + * 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 BASE_UTILS_NET_H +#define BASE_UTILS_NET_H +class QString; + +namespace Utils +{ + namespace Net + { + bool isValidIP(const QString &ip); + } +} + +#endif // BASE_UTILS_NET_H diff --git a/src/gui/banlistoptions.cpp b/src/gui/banlistoptions.cpp new file mode 100644 index 000000000..d7159601c --- /dev/null +++ b/src/gui/banlistoptions.cpp @@ -0,0 +1,99 @@ +/* + * Bittorrent Client using Qt and libtorrent. + * Copyright (C) 2016 Alexandr Milovantsev + * + * 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 "banlistoptions.h" +#include "ui_banlistoptions.h" + +#include +#include + +#include "base/bittorrent/session.h" +#include "base/utils/net.h" + +BanListOptions::BanListOptions(QWidget *parent) + : QDialog(parent) + , m_ui(new Ui::BanListOptions) + , m_modified(false) +{ + m_ui->setupUi(this); + m_ui->bannedIPList->addItems(BitTorrent::Session::instance()->bannedIPs()); + m_ui->buttonBanIP->setEnabled(false); +} + +BanListOptions::~BanListOptions() +{ + delete m_ui; +} + +void BanListOptions::on_buttonBox_accepted() +{ + if (m_modified) { + // save to session + QStringList IPList; + for (int i = 0; i < m_ui->bannedIPList->count(); ++i) + IPList << m_ui->bannedIPList->item(i)->text(); + BitTorrent::Session::instance()->setBannedIPs(IPList); + } + QDialog::accept(); +} + +void BanListOptions::on_buttonBanIP_clicked() +{ + QString ip=m_ui->txtIP->text(); + if (!Utils::Net::isValidIP(ip)) { + QMessageBox::warning(this, tr("Warning"), tr("The entered IP address is invalid.")); + return; + } + // the same IPv6 addresses could be written in different forms; + // QHostAddress::toString() result format follows RFC5952; + // thus we avoid duplicate entries pointing to the same address + ip = QHostAddress(ip).toString(); + QList findres = m_ui->bannedIPList->findItems(ip, Qt::MatchExactly); + if (!findres.isEmpty()) { + QMessageBox::warning(this, tr("Warning"), tr("The entered IP is already banned.")); + return; + } + m_ui->bannedIPList->addItem(ip); + m_ui->txtIP->clear(); + m_modified = true; +} + +void BanListOptions::on_buttonDeleteIP_clicked() +{ + QList selection = m_ui->bannedIPList->selectedItems(); + for (auto &i : selection) { + m_ui->bannedIPList->removeItemWidget(i); + delete i; + } + m_modified = true; +} + +void BanListOptions::on_txtIP_textChanged(const QString &ip) +{ + m_ui->buttonBanIP->setEnabled(Utils::Net::isValidIP(ip)); +} diff --git a/src/gui/banlistoptions.h b/src/gui/banlistoptions.h new file mode 100644 index 000000000..37285d540 --- /dev/null +++ b/src/gui/banlistoptions.h @@ -0,0 +1,58 @@ +/* + * Bittorrent Client using Qt and libtorrent. + * Copyright (C) 2016 Alexandr Milovantsev + * + * 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 OPTIONS_BANLIST_H +#define OPTIONS_BANLIST_H + +#include + +namespace Ui +{ + class BanListOptions; +} + +class BanListOptions: public QDialog +{ + Q_OBJECT + +public: + explicit BanListOptions(QWidget *parent = 0); + ~BanListOptions(); + +private slots: + void on_buttonBox_accepted(); + void on_buttonBanIP_clicked(); + void on_buttonDeleteIP_clicked(); + void on_txtIP_textChanged(const QString &ip); + +private: + Ui::BanListOptions *m_ui; + bool m_modified; +}; + +#endif // OPTIONS_BANLIST_H diff --git a/src/gui/banlistoptions.ui b/src/gui/banlistoptions.ui new file mode 100644 index 000000000..79ac4ed5c --- /dev/null +++ b/src/gui/banlistoptions.ui @@ -0,0 +1,115 @@ + + + BanListOptions + + + + 0 + 0 + 360 + 450 + + + + List of banned IP addresses + + + + + + true + + + + 0 + 0 + + + + true + + + QFrame::Panel + + + QFrame::Raised + + + 1 + + + 0 + + + + + + + 0 + 0 + + + + true + + + + + + + + + + + + Ban IP + + + + + + + Delete + + + + + + + + + + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + bannedIPList + txtIP + buttonBanIP + buttonDeleteIP + + + + + buttonBox + rejected() + BanListOptions + reject() + + + 179 + 427 + + + 179 + 224 + + + + + diff --git a/src/gui/gui.pri b/src/gui/gui.pri index 62ad185eb..b41408df6 100644 --- a/src/gui/gui.pri +++ b/src/gui/gui.pri @@ -51,7 +51,8 @@ HEADERS += \ $$PWD/cookiesmodel.h \ $$PWD/cookiesdialog.h \ $$PWD/categoryfiltermodel.h \ - $$PWD/categoryfilterwidget.h + $$PWD/categoryfilterwidget.h \ + $$PWD/banlistoptions.h SOURCES += \ $$PWD/mainwindow.cpp \ @@ -93,7 +94,8 @@ SOURCES += \ $$PWD/cookiesmodel.cpp \ $$PWD/cookiesdialog.cpp \ $$PWD/categoryfiltermodel.cpp \ - $$PWD/categoryfilterwidget.cpp + $$PWD/categoryfilterwidget.cpp \ + $$PWD/banlistoptions.cpp win32|macx { HEADERS += $$PWD/programupdater.h @@ -120,6 +122,7 @@ FORMS += \ $$PWD/search/pluginselectdlg.ui \ $$PWD/search/pluginsourcedlg.ui \ $$PWD/search/searchtab.ui \ - $$PWD/cookiesdialog.ui + $$PWD/cookiesdialog.ui \ + $$PWD/banlistoptions.ui RESOURCES += $$PWD/about.qrc diff --git a/src/gui/optionsdlg.cpp b/src/gui/optionsdlg.cpp index 6c2f873ef..4af9d3a3a 100644 --- a/src/gui/optionsdlg.cpp +++ b/src/gui/optionsdlg.cpp @@ -61,6 +61,7 @@ #include "base/utils/random.h" #include "addnewtorrentdialog.h" #include "advancedsettings.h" +#include "banlistoptions.h" #include "guiiconprovider.h" #include "scanfoldersdelegate.h" @@ -1701,3 +1702,10 @@ bool OptionsDialog::webUIAuthenticationOk() } return true; } + +void OptionsDialog::on_banListButton_clicked() +{ + //have to call dialog window + BanListOptions bl(this); + bl.exec(); +} diff --git a/src/gui/optionsdlg.h b/src/gui/optionsdlg.h index 01fb0fab5..744aa9896 100644 --- a/src/gui/optionsdlg.h +++ b/src/gui/optionsdlg.h @@ -93,6 +93,7 @@ private slots: void handleScanFolderViewSelectionChanged(); void on_IpFilterRefreshBtn_clicked(); void handleIPFilterParsed(bool error, int ruleCount); + void on_banListButton_clicked(); void on_browseFileLogDir_clicked(); void on_browseExportDirButton_clicked(); void on_browseExportDirFinButton_clicked(); diff --git a/src/gui/optionsdlg.ui b/src/gui/optionsdlg.ui index 191ea6392..c367879f0 100644 --- a/src/gui/optionsdlg.ui +++ b/src/gui/optionsdlg.ui @@ -1768,6 +1768,19 @@ + + + + + 0 + 0 + + + + Manually banned IP addresses... + + + diff --git a/src/webui/prefjson.cpp b/src/webui/prefjson.cpp index ee26028b3..1d02bbdae 100644 --- a/src/webui/prefjson.cpp +++ b/src/webui/prefjson.cpp @@ -114,6 +114,7 @@ QByteArray prefjson::getPreferences() data["ip_filter_enabled"] = session->isIPFilteringEnabled(); data["ip_filter_path"] = Utils::Fs::toNativePath(session->IPFilterFile()); data["ip_filter_trackers"] = session->isTrackerFilteringEnabled(); + data["banned_IPs"] = session->bannedIPs().join("\n"); // Speed // Global Rate Limits @@ -309,6 +310,8 @@ void prefjson::setPreferences(const QString& json) session->setIPFilterFile(m["ip_filter_path"].toString()); if (m.contains("ip_filter_trackers")) session->setTrackerFilteringEnabled(m["ip_filter_trackers"].toBool()); + if (m.contains("banned_IPs")) + session->setBannedIPs(m["banned_IPs"].toString().split('\n')); // Speed // Global Rate Limits diff --git a/src/webui/www/public/preferences_content.html b/src/webui/www/public/preferences_content.html index e14f445d8..705ce1e90 100644 --- a/src/webui/www/public/preferences_content.html +++ b/src/webui/www/public/preferences_content.html @@ -180,6 +180,12 @@
+
+
+ QBT_TR(Manually banned IP addresses...)QBT_TR + +
+
@@ -637,9 +643,11 @@ updateFilterSettings = function() { if($('ipfilter_enabled_checkbox').getProperty('checked')) { $('ipfilter_text').setProperty('disabled', false); $('ipfilter_trackers_checkbox').setProperty('disabled', false); + $('banned_IPs_textarea').setProperty('disabled', false); } else { $('ipfilter_text').setProperty('disabled', true); $('ipfilter_trackers_checkbox').setProperty('disabled', true); + $('banned_IPs_textarea').setProperty('disabled', true); } } @@ -913,6 +921,7 @@ loadPreferences = function() { $('ipfilter_enabled_checkbox').setProperty('checked', pref.ip_filter_enabled); $('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); updateFilterSettings(); // Speed tab @@ -1146,6 +1155,7 @@ applyPreferences = function() { settings.set('ip_filter_enabled', $('ipfilter_enabled_checkbox').getProperty('checked')); 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')); // Speed tab // Global Rate Limits