diff --git a/src/base/bittorrent/peerinfo.cpp b/src/base/bittorrent/peerinfo.cpp index c3e66d7c8..45b8a158a 100644 --- a/src/base/bittorrent/peerinfo.cpp +++ b/src/base/bittorrent/peerinfo.cpp @@ -181,6 +181,31 @@ QString PeerInfo::client() const return QString::fromStdString(m_nativeInfo.client); } +QString PeerInfo::peerIdClient() const +{ + // when peer ID is not known yet it contains only zero bytes, + // do not create string in such case, return empty string instead + if (m_nativeInfo.pid.is_all_zeros()) + return {}; + + QString result; + + // interesting part of a typical peer ID is first 8 chars + for (int i = 0; i < 8; ++i) + { + const std::uint8_t c = m_nativeInfo.pid[i]; + + // ensure that the peer ID slice consists only of printable ASCII characters, + // this should filter out most of the improper IDs + if ((c < 32) || (c > 126)) + return tr("Unknown"); + + result += QChar::fromLatin1(c); + } + + return result; +} + qreal PeerInfo::progress() const { return m_nativeInfo.progress; diff --git a/src/base/bittorrent/peerinfo.h b/src/base/bittorrent/peerinfo.h index f7f51d177..6c7cb7b1c 100644 --- a/src/base/bittorrent/peerinfo.h +++ b/src/base/bittorrent/peerinfo.h @@ -78,6 +78,7 @@ namespace BitTorrent PeerAddress address() const; QString client() const; + QString peerIdClient() const; qreal progress() const; int payloadUpSpeed() const; int payloadDownSpeed() const; diff --git a/src/gui/properties/peerlistwidget.cpp b/src/gui/properties/peerlistwidget.cpp index e4ed8a75a..5b490df9e 100644 --- a/src/gui/properties/peerlistwidget.cpp +++ b/src/gui/properties/peerlistwidget.cpp @@ -89,7 +89,7 @@ PeerListWidget::PeerListWidget(PropertiesWidget *parent) , m_properties(parent) { // Load settings - loadSettings(); + const bool columnLoaded = loadSettings(); // Visual settings setUniformRowHeights(true); setRootIsDecorated(false); @@ -109,6 +109,7 @@ PeerListWidget::PeerListWidget(PropertiesWidget *parent) m_listModel->setHeaderData(PeerListColumns::FLAGS, Qt::Horizontal, tr("Flags")); m_listModel->setHeaderData(PeerListColumns::CONNECTION, Qt::Horizontal, tr("Connection")); m_listModel->setHeaderData(PeerListColumns::CLIENT, Qt::Horizontal, tr("Client", "i.e.: Client application")); + m_listModel->setHeaderData(PeerListColumns::PEERID_CLIENT, Qt::Horizontal, tr("Peer ID Client", "i.e.: Client resolved from Peer ID")); m_listModel->setHeaderData(PeerListColumns::PROGRESS, Qt::Horizontal, tr("Progress", "i.e: % downloaded")); m_listModel->setHeaderData(PeerListColumns::DOWN_SPEED, Qt::Horizontal, tr("Down Speed", "i.e: Download speed")); m_listModel->setHeaderData(PeerListColumns::UP_SPEED, Qt::Horizontal, tr("Up Speed", "i.e: Upload speed")); @@ -130,8 +131,16 @@ PeerListWidget::PeerListWidget(PropertiesWidget *parent) m_proxyModel->setSourceModel(m_listModel); m_proxyModel->setSortCaseSensitivity(Qt::CaseInsensitive); setModel(m_proxyModel); + hideColumn(PeerListColumns::IP_HIDDEN); hideColumn(PeerListColumns::COL_COUNT); + + // Default hidden columns + if (!columnLoaded) + { + hideColumn(PeerListColumns::PEERID_CLIENT); + } + m_resolveCountries = Preferences::instance()->resolvePeerCountries(); if (!m_resolveCountries) hideColumn(PeerListColumns::COUNTRY); @@ -371,9 +380,9 @@ void PeerListWidget::clear() m_listModel->removeRows(0, nbrows); } -void PeerListWidget::loadSettings() +bool PeerListWidget::loadSettings() { - header()->restoreState(Preferences::instance()->getPeerListState()); + return header()->restoreState(Preferences::instance()->getPeerListState()); } void PeerListWidget::saveSettings() const @@ -461,6 +470,8 @@ void PeerListWidget::updatePeer(const BitTorrent::Torrent *torrent, const BitTor setModelData(row, PeerListColumns::FLAGS, peer.flags(), peer.flags(), {}, peer.flagsDescription()); const QString client = peer.client().toHtmlEscaped(); setModelData(row, PeerListColumns::CLIENT, client, client, {}, client); + const QString peerIdClient = peer.peerIdClient().toHtmlEscaped(); + setModelData(row, PeerListColumns::PEERID_CLIENT, peerIdClient, peerIdClient); setModelData(row, PeerListColumns::PROGRESS, (Utils::String::fromDouble(peer.progress() * 100, 1) + u'%'), peer.progress(), intDataTextAlignment); const QString downSpeed = (hideValues && (peer.payloadDownSpeed() <= 0)) ? QString {} : Utils::Misc::friendlyUnit(peer.payloadDownSpeed(), true); setModelData(row, PeerListColumns::DOWN_SPEED, downSpeed, peer.payloadDownSpeed(), intDataTextAlignment); diff --git a/src/gui/properties/peerlistwidget.h b/src/gui/properties/peerlistwidget.h index a3e9e0d94..2276437c1 100644 --- a/src/gui/properties/peerlistwidget.h +++ b/src/gui/properties/peerlistwidget.h @@ -66,6 +66,7 @@ public: CONNECTION, FLAGS, CLIENT, + PEERID_CLIENT, PROGRESS, DOWN_SPEED, UP_SPEED, @@ -87,7 +88,7 @@ public: void clear(); private slots: - void loadSettings(); + bool loadSettings(); void saveSettings() const; void displayColumnHeaderMenu(); void showPeerListMenu(); diff --git a/src/webui/api/synccontroller.cpp b/src/webui/api/synccontroller.cpp index 173280c6e..f7770aeb5 100644 --- a/src/webui/api/synccontroller.cpp +++ b/src/webui/api/synccontroller.cpp @@ -66,6 +66,7 @@ namespace // Peer keys const QString KEY_PEER_CLIENT = u"client"_qs; + const QString KEY_PEER_ID_CLIENT = u"peer_id_client"_qs; const QString KEY_PEER_CONNECTION_TYPE = u"connection"_qs; const QString KEY_PEER_COUNTRY = u"country"_qs; const QString KEY_PEER_COUNTRY_CODE = u"country_code"_qs; @@ -561,6 +562,7 @@ void SyncController::torrentPeersAction() {KEY_PEER_IP, pi.address().ip.toString()}, {KEY_PEER_PORT, pi.address().port}, {KEY_PEER_CLIENT, pi.client()}, + {KEY_PEER_ID_CLIENT, pi.peerIdClient()}, {KEY_PEER_PROGRESS, pi.progress()}, {KEY_PEER_DOWN_SPEED, pi.payloadDownSpeed()}, {KEY_PEER_UP_SPEED, pi.payloadUpSpeed()}, diff --git a/src/webui/webapplication.h b/src/webui/webapplication.h index 79b5f9c69..df58992ba 100644 --- a/src/webui/webapplication.h +++ b/src/webui/webapplication.h @@ -52,7 +52,7 @@ #include "base/utils/version.h" #include "api/isessionmanager.h" -inline const Utils::Version<3, 2> API_VERSION {2, 8, 16}; +inline const Utils::Version<3, 2> API_VERSION {2, 8, 17}; class APIController; class AuthController; diff --git a/src/webui/www/private/scripts/dynamicTable.js b/src/webui/www/private/scripts/dynamicTable.js index 6a35ae5ec..6f72009ab 100644 --- a/src/webui/www/private/scripts/dynamicTable.js +++ b/src/webui/www/private/scripts/dynamicTable.js @@ -1498,6 +1498,7 @@ window.qBittorrent.DynamicTable = (function() { this.newColumn('connection', '', 'QBT_TR(Connection)QBT_TR[CONTEXT=PeerListWidget]', 50, true); this.newColumn('flags', '', 'QBT_TR(Flags)QBT_TR[CONTEXT=PeerListWidget]', 50, true); this.newColumn('client', '', 'QBT_TR(Client)QBT_TR[CONTEXT=PeerListWidget]', 140, true); + this.newColumn('peer_id_client', '', 'QBT_TR(Peer ID Client)QBT_TR[CONTEXT=PeerListWidget]', 60, false); this.newColumn('progress', '', 'QBT_TR(Progress)QBT_TR[CONTEXT=PeerListWidget]', 50, true); this.newColumn('dl_speed', '', 'QBT_TR(Down Speed)QBT_TR[CONTEXT=PeerListWidget]', 50, true); this.newColumn('up_speed', '', 'QBT_TR(Up Speed)QBT_TR[CONTEXT=PeerListWidget]', 50, true);