From 67db0c03d72557db0b0ab994534c585a6d54a9ad Mon Sep 17 00:00:00 2001 From: "Stiliyan Tonev (Bark)" Date: Fri, 10 Jan 2025 09:56:21 +0200 Subject: [PATCH 1/7] fix: Add check for Content-Type when downloading tracker list. Check if the URL from where we are downloading the trackers returns `Content-Type` as `text`. Otherwise consider it might be a non-usable format for this functionality (html,xml,etc.ect.) --- src/base/net/downloadhandlerimpl.cpp | 1 + src/base/net/downloadmanager.h | 1 + src/gui/trackersadditiondialog.cpp | 7 +++++++ 3 files changed, 9 insertions(+) diff --git a/src/base/net/downloadhandlerimpl.cpp b/src/base/net/downloadhandlerimpl.cpp index 370347946..61a516088 100644 --- a/src/base/net/downloadhandlerimpl.cpp +++ b/src/base/net/downloadhandlerimpl.cpp @@ -143,6 +143,7 @@ void Net::DownloadHandlerImpl::processFinishedDownload() #else m_result.data = m_reply->readAll(); #endif + m_result.contentType = m_reply->header(QNetworkRequest::ContentTypeHeader).toString(); if (m_downloadRequest.saveToFile()) { diff --git a/src/base/net/downloadmanager.h b/src/base/net/downloadmanager.h index 8f74c2f9d..a13768e9d 100644 --- a/src/base/net/downloadmanager.h +++ b/src/base/net/downloadmanager.h @@ -107,6 +107,7 @@ namespace Net QByteArray data; Path filePath; QString magnetURI; + QString contentType; }; class DownloadHandler : public QObject diff --git a/src/gui/trackersadditiondialog.cpp b/src/gui/trackersadditiondialog.cpp index 0014d5a55..4c93aacbc 100644 --- a/src/gui/trackersadditiondialog.cpp +++ b/src/gui/trackersadditiondialog.cpp @@ -109,6 +109,13 @@ void TrackersAdditionDialog::onTorrentListDownloadFinished(const Net::DownloadRe m_ui->downloadButton->setEnabled(true); setCursor(Qt::ArrowCursor); + if (!result.contentType.contains(u"text/plain"_s, Qt::CaseInsensitive)) + { + QMessageBox::warning(this, tr("Download trackers list error") + , tr("The content type of the downloaded file is not plain text. Content-Type: \"%1\"").arg(result.contentType)); + return; + } + if (result.status != Net::DownloadStatus::Success) { QMessageBox::warning(this, tr("Download trackers list error") From db41945db796c82960350fc0ec730c3c8df2370e Mon Sep 17 00:00:00 2001 From: "Stiliyan Tonev (Bark)" Date: Fri, 10 Jan 2025 13:58:14 +0200 Subject: [PATCH 2/7] Check header after request succeeds, check if added trackers are valid URL\'s --- src/gui/trackersadditiondialog.cpp | 37 +++++++++++++++++++++++------- src/gui/trackersadditiondialog.h | 1 + 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/src/gui/trackersadditiondialog.cpp b/src/gui/trackersadditiondialog.cpp index 4c93aacbc..9403edf3b 100644 --- a/src/gui/trackersadditiondialog.cpp +++ b/src/gui/trackersadditiondialog.cpp @@ -74,14 +74,35 @@ TrackersAdditionDialog::~TrackersAdditionDialog() delete m_ui; } +int TrackersAdditionDialog::isValidEndpoint(const QStringView &endpoint) const +{ + if (endpoint.isEmpty()) + return 0; + QUrl url(endpoint.toString()); + if (!url.isValid()) + return 0; + if (url.scheme().isEmpty()) + return 0; + if (url.host().isEmpty()) + return 0; + return 1; +} + void TrackersAdditionDialog::onAccepted() const { const QList currentTrackers = m_torrent->trackers(); const int baseTier = !currentTrackers.isEmpty() ? (currentTrackers.last().tier + 1) : 0; QList entries = BitTorrent::parseTrackerEntries(m_ui->textEditTrackersList->toPlainText()); - for (BitTorrent::TrackerEntry &entry : entries) + for (BitTorrent::TrackerEntry &entry : entries) { + auto isValid = isValidEndpoint(entry.url); + if (!isValid) + { + QMessageBox::warning(const_cast(this), tr("Invalid tracker URL"), tr("The tracker URL \"%1\" is invalid").arg(entry.url)); + return; + } entry.tier = Utils::Number::clampingAdd(entry.tier, baseTier); + } m_torrent->addTrackers(entries); } @@ -109,13 +130,6 @@ void TrackersAdditionDialog::onTorrentListDownloadFinished(const Net::DownloadRe m_ui->downloadButton->setEnabled(true); setCursor(Qt::ArrowCursor); - if (!result.contentType.contains(u"text/plain"_s, Qt::CaseInsensitive)) - { - QMessageBox::warning(this, tr("Download trackers list error") - , tr("The content type of the downloaded file is not plain text. Content-Type: \"%1\"").arg(result.contentType)); - return; - } - if (result.status != Net::DownloadStatus::Success) { QMessageBox::warning(this, tr("Download trackers list error") @@ -123,6 +137,13 @@ void TrackersAdditionDialog::onTorrentListDownloadFinished(const Net::DownloadRe return; } + if (!result.contentType.contains(u"text/plain"_s, Qt::CaseInsensitive)) + { + QMessageBox::warning(this, tr("Download trackers list error") + , tr("The content type of the downloaded file is not plain text. Content-Type: \"%1\"").arg(result.contentType)); + return; + } + // Add fetched trackers to the list const QString existingText = m_ui->textEditTrackersList->toPlainText(); if (!existingText.isEmpty() && !existingText.endsWith(u'\n')) diff --git a/src/gui/trackersadditiondialog.h b/src/gui/trackersadditiondialog.h index 0dc658cff..893379f68 100644 --- a/src/gui/trackersadditiondialog.h +++ b/src/gui/trackersadditiondialog.h @@ -65,6 +65,7 @@ private slots: private: void saveSettings(); void loadSettings(); + int isValidEndpoint(const QStringView &endpoint) const; Ui::TrackersAdditionDialog *m_ui = nullptr; BitTorrent::Torrent *const m_torrent = nullptr; From db5fc72950043afaafde411182558b68302f0d6e Mon Sep 17 00:00:00 2001 From: "Stiliyan Tonev (Bark)" Date: Mon, 13 Jan 2025 16:12:42 +0200 Subject: [PATCH 3/7] Add check to Bittorrent tab in preferences too. --- src/gui/optionsdialog.cpp | 35 +++++++++++++++++++++++++++++++++++ src/gui/optionsdialog.h | 1 + 2 files changed, 36 insertions(+) diff --git a/src/gui/optionsdialog.cpp b/src/gui/optionsdialog.cpp index 114f3004f..d62a16f72 100644 --- a/src/gui/optionsdialog.cpp +++ b/src/gui/optionsdialog.cpp @@ -83,6 +83,7 @@ #include "watchedfolderoptionsdialog.h" #include "watchedfoldersmodel.h" #include "webui/webui.h" +#include "base/net/downloadmanager.h" #ifndef DISABLE_WEBUI #include "base/net/dnsupdater.h" @@ -1232,8 +1233,42 @@ void OptionsDialog::saveBittorrentTabOptions() const session->setAddTrackersEnabled(m_ui->checkEnableAddTrackers->isChecked()); session->setAdditionalTrackers(m_ui->textTrackers->toPlainText()); + auto enabledAddTrackers = m_ui->checkAddTrackersFromURL->isChecked(); + auto url = m_ui->textTrackersURL->text(); + if (!url.isEmpty() && enabledAddTrackers) + { + Net::DownloadManager::instance()->download(url, Preferences::instance()->useProxyForGeneralPurposes() + , this, &OptionsDialog::onAddTrackersDownload); + } + else + { + session->setAddTrackersFromURLEnabled(enabledAddTrackers); + session->setAdditionalTrackersURL(url); + } +} + +void OptionsDialog::onAddTrackersDownload(const Net::DownloadResult &result) +{ + if (result.status != Net::DownloadStatus::Success) + { + QMessageBox::warning(this, tr("Download trackers list error") + , tr("Error occurred when downloading the trackers list. Reason: \"%1\"").arg(result.errorString)); + return; + } + + if (!result.contentType.contains(u"text/plain"_s, Qt::CaseInsensitive)) + { + QMessageBox::warning(this, tr("Download trackers list error") + , tr("The content type of the downloaded file is not plain text. Content-Type: \"%1\"").arg(result.contentType)); + return; + } + + auto *session = BitTorrent::Session::instance(); + session->setAddTrackersFromURLEnabled(m_ui->checkAddTrackersFromURL->isChecked()); session->setAdditionalTrackersURL(m_ui->textTrackersURL->text()); + + return; } void OptionsDialog::loadRSSTabOptions() diff --git a/src/gui/optionsdialog.h b/src/gui/optionsdialog.h index c1e29c1d6..d6d7d1a6d 100644 --- a/src/gui/optionsdialog.h +++ b/src/gui/optionsdialog.h @@ -34,6 +34,7 @@ #include "base/pathfwd.h" #include "base/settingvalue.h" #include "guiapplicationcomponent.h" +#include "base/net/downloadmanager.h" class QListWidgetItem; From c194b4512d2a9d02f0448c14e1ad85c14d824c77 Mon Sep 17 00:00:00 2001 From: "Stiliyan Tonev (Bark)" Date: Mon, 31 Mar 2025 14:07:01 +0300 Subject: [PATCH 4/7] Address PR comments. --- src/base/net/downloadmanager.h | 2 +- src/gui/optionsdialog.cpp | 15 ++++++--------- src/gui/optionsdialog.h | 4 +++- src/gui/trackersadditiondialog.cpp | 24 ++++++++++++------------ src/gui/trackersadditiondialog.h | 3 +-- 5 files changed, 23 insertions(+), 25 deletions(-) diff --git a/src/base/net/downloadmanager.h b/src/base/net/downloadmanager.h index a13768e9d..b1cf32425 100644 --- a/src/base/net/downloadmanager.h +++ b/src/base/net/downloadmanager.h @@ -104,10 +104,10 @@ namespace Net QString url; DownloadStatus status = DownloadStatus::Failed; QString errorString; + QString contentType; QByteArray data; Path filePath; QString magnetURI; - QString contentType; }; class DownloadHandler : public QObject diff --git a/src/gui/optionsdialog.cpp b/src/gui/optionsdialog.cpp index d62a16f72..517173cf8 100644 --- a/src/gui/optionsdialog.cpp +++ b/src/gui/optionsdialog.cpp @@ -53,7 +53,6 @@ #include "base/bittorrent/sharelimitaction.h" #include "base/exceptions.h" #include "base/global.h" -#include "base/net/downloadmanager.h" #include "base/net/portforwarder.h" #include "base/net/proxyconfigurationmanager.h" #include "base/path.h" @@ -1233,21 +1232,21 @@ void OptionsDialog::saveBittorrentTabOptions() const session->setAddTrackersEnabled(m_ui->checkEnableAddTrackers->isChecked()); session->setAdditionalTrackers(m_ui->textTrackers->toPlainText()); - auto enabledAddTrackers = m_ui->checkAddTrackersFromURL->isChecked(); - auto url = m_ui->textTrackersURL->text(); - if (!url.isEmpty() && enabledAddTrackers) + const bool isAddTrackersEnabled = m_ui->checkAddTrackersFromURL->isChecked(); + const QString url = m_ui->textTrackersURL->text(); + if (isAddTrackersEnabled && !url.isEmpty()) { Net::DownloadManager::instance()->download(url, Preferences::instance()->useProxyForGeneralPurposes() - , this, &OptionsDialog::onAddTrackersDownload); + , this, &OptionsDialog::onAdditionalTrackersDownload); } else { - session->setAddTrackersFromURLEnabled(enabledAddTrackers); + session->setAddTrackersFromURLEnabled(isAddTrackersEnabled); session->setAdditionalTrackersURL(url); } } -void OptionsDialog::onAddTrackersDownload(const Net::DownloadResult &result) +void OptionsDialog::onAdditionalTrackersDownload(const Net::DownloadResult &result) { if (result.status != Net::DownloadStatus::Success) { @@ -1267,8 +1266,6 @@ void OptionsDialog::onAddTrackersDownload(const Net::DownloadResult &result) session->setAddTrackersFromURLEnabled(m_ui->checkAddTrackersFromURL->isChecked()); session->setAdditionalTrackersURL(m_ui->textTrackersURL->text()); - - return; } void OptionsDialog::loadRSSTabOptions() diff --git a/src/gui/optionsdialog.h b/src/gui/optionsdialog.h index d6d7d1a6d..6828c2ce4 100644 --- a/src/gui/optionsdialog.h +++ b/src/gui/optionsdialog.h @@ -31,10 +31,10 @@ #include +#include "base/net/downloadmanager.h" #include "base/pathfwd.h" #include "base/settingvalue.h" #include "guiapplicationcomponent.h" -#include "base/net/downloadmanager.h" class QListWidgetItem; @@ -138,6 +138,8 @@ private: void loadRSSTabOptions(); void saveRSSTabOptions() const; + void onAdditionalTrackersDownload(const Net::DownloadResult &result); + void loadSearchTabOptions(); void saveSearchTabOptions() const; diff --git a/src/gui/trackersadditiondialog.cpp b/src/gui/trackersadditiondialog.cpp index 9403edf3b..2ae916370 100644 --- a/src/gui/trackersadditiondialog.cpp +++ b/src/gui/trackersadditiondialog.cpp @@ -74,31 +74,31 @@ TrackersAdditionDialog::~TrackersAdditionDialog() delete m_ui; } -int TrackersAdditionDialog::isValidEndpoint(const QStringView &endpoint) const +bool isValidEndpoint(const QStringView endpoint) { if (endpoint.isEmpty()) - return 0; - QUrl url(endpoint.toString()); + return false; + const QUrl url {endpoint.toString()}; if (!url.isValid()) - return 0; + return false; if (url.scheme().isEmpty()) - return 0; + return false; if (url.host().isEmpty()) - return 0; - return 1; + return false; + return true; } -void TrackersAdditionDialog::onAccepted() const +void TrackersAdditionDialog::onAccepted() { const QList currentTrackers = m_torrent->trackers(); const int baseTier = !currentTrackers.isEmpty() ? (currentTrackers.last().tier + 1) : 0; QList entries = BitTorrent::parseTrackerEntries(m_ui->textEditTrackersList->toPlainText()); - for (BitTorrent::TrackerEntry &entry : entries) { - auto isValid = isValidEndpoint(entry.url); - if (!isValid) + for (BitTorrent::TrackerEntry &entry : entries) + { + if (!isValidEndpoint(entry.url)) { - QMessageBox::warning(const_cast(this), tr("Invalid tracker URL"), tr("The tracker URL \"%1\" is invalid").arg(entry.url)); + QMessageBox::warning(this, tr("Invalid tracker URL"), tr("The tracker URL \"%1\" is invalid").arg(entry.url)); return; } entry.tier = Utils::Number::clampingAdd(entry.tier, baseTier); diff --git a/src/gui/trackersadditiondialog.h b/src/gui/trackersadditiondialog.h index 893379f68..ebb214050 100644 --- a/src/gui/trackersadditiondialog.h +++ b/src/gui/trackersadditiondialog.h @@ -58,14 +58,13 @@ public: ~TrackersAdditionDialog(); private slots: - void onAccepted() const; + void onAccepted(); void onDownloadButtonClicked(); void onTorrentListDownloadFinished(const Net::DownloadResult &result); private: void saveSettings(); void loadSettings(); - int isValidEndpoint(const QStringView &endpoint) const; Ui::TrackersAdditionDialog *m_ui = nullptr; BitTorrent::Torrent *const m_torrent = nullptr; From 156f6cf3a319fe0d414660dc40638a3856adb55b Mon Sep 17 00:00:00 2001 From: "Stiliyan Tonev (Bark)" Date: Mon, 31 Mar 2025 16:04:03 +0300 Subject: [PATCH 5/7] Remove redundant include. --- src/gui/optionsdialog.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/gui/optionsdialog.cpp b/src/gui/optionsdialog.cpp index 517173cf8..44e3f4c3e 100644 --- a/src/gui/optionsdialog.cpp +++ b/src/gui/optionsdialog.cpp @@ -82,7 +82,6 @@ #include "watchedfolderoptionsdialog.h" #include "watchedfoldersmodel.h" #include "webui/webui.h" -#include "base/net/downloadmanager.h" #ifndef DISABLE_WEBUI #include "base/net/dnsupdater.h" From 5567d029cf03f6ccaa25dd162cb8966daf9b634c Mon Sep 17 00:00:00 2001 From: "Stiliyan Tonev (Bark)" Date: Mon, 12 May 2025 12:59:48 +0300 Subject: [PATCH 6/7] fix: As advised, move logic away from the settings window into session. --- src/base/bittorrent/sessionimpl.cpp | 5 +++++ src/gui/optionsdialog.cpp | 34 +---------------------------- src/gui/optionsdialog.h | 3 --- 3 files changed, 6 insertions(+), 36 deletions(-) diff --git a/src/base/bittorrent/sessionimpl.cpp b/src/base/bittorrent/sessionimpl.cpp index 1cbd1b3c6..b3887047a 100644 --- a/src/base/bittorrent/sessionimpl.cpp +++ b/src/base/bittorrent/sessionimpl.cpp @@ -4105,6 +4105,11 @@ void SessionImpl::updateTrackersFromURL() { if (result.status == Net::DownloadStatus::Success) { + if (!result.contentType.contains(u"text/plain"_s, Qt::CaseInsensitive)) + { + LogMsg(tr("Cannot add trackers from URL, expected Content-Type is \'text/plain\' received \"%1\"").arg(result.contentType), Log::WARNING); + return; + } setAdditionalTrackersFromURL(QString::fromUtf8(result.data)); LogMsg(tr("Tracker list updated"), Log::INFO); return; diff --git a/src/gui/optionsdialog.cpp b/src/gui/optionsdialog.cpp index 44e3f4c3e..7cb9be963 100644 --- a/src/gui/optionsdialog.cpp +++ b/src/gui/optionsdialog.cpp @@ -53,6 +53,7 @@ #include "base/bittorrent/sharelimitaction.h" #include "base/exceptions.h" #include "base/global.h" +#include "base/net/downloadmanager.h" #include "base/net/portforwarder.h" #include "base/net/proxyconfigurationmanager.h" #include "base/path.h" @@ -1227,42 +1228,9 @@ void OptionsDialog::saveBittorrentTabOptions() const BitTorrent::ShareLimitAction::EnableSuperSeeding }; session->setShareLimitAction(actIndex.value(m_ui->comboRatioLimitAct->currentIndex())); - session->setAddTrackersEnabled(m_ui->checkEnableAddTrackers->isChecked()); session->setAdditionalTrackers(m_ui->textTrackers->toPlainText()); - const bool isAddTrackersEnabled = m_ui->checkAddTrackersFromURL->isChecked(); - const QString url = m_ui->textTrackersURL->text(); - if (isAddTrackersEnabled && !url.isEmpty()) - { - Net::DownloadManager::instance()->download(url, Preferences::instance()->useProxyForGeneralPurposes() - , this, &OptionsDialog::onAdditionalTrackersDownload); - } - else - { - session->setAddTrackersFromURLEnabled(isAddTrackersEnabled); - session->setAdditionalTrackersURL(url); - } -} - -void OptionsDialog::onAdditionalTrackersDownload(const Net::DownloadResult &result) -{ - if (result.status != Net::DownloadStatus::Success) - { - QMessageBox::warning(this, tr("Download trackers list error") - , tr("Error occurred when downloading the trackers list. Reason: \"%1\"").arg(result.errorString)); - return; - } - - if (!result.contentType.contains(u"text/plain"_s, Qt::CaseInsensitive)) - { - QMessageBox::warning(this, tr("Download trackers list error") - , tr("The content type of the downloaded file is not plain text. Content-Type: \"%1\"").arg(result.contentType)); - return; - } - - auto *session = BitTorrent::Session::instance(); - session->setAddTrackersFromURLEnabled(m_ui->checkAddTrackersFromURL->isChecked()); session->setAdditionalTrackersURL(m_ui->textTrackersURL->text()); } diff --git a/src/gui/optionsdialog.h b/src/gui/optionsdialog.h index 6828c2ce4..c1e29c1d6 100644 --- a/src/gui/optionsdialog.h +++ b/src/gui/optionsdialog.h @@ -31,7 +31,6 @@ #include -#include "base/net/downloadmanager.h" #include "base/pathfwd.h" #include "base/settingvalue.h" #include "guiapplicationcomponent.h" @@ -138,8 +137,6 @@ private: void loadRSSTabOptions(); void saveRSSTabOptions() const; - void onAdditionalTrackersDownload(const Net::DownloadResult &result); - void loadSearchTabOptions(); void saveSearchTabOptions() const; From 669f8cd06d43aae48ed3f615cade11a4df7465b9 Mon Sep 17 00:00:00 2001 From: "Stiliyan Tonev (Bark)" Date: Mon, 12 May 2025 13:18:36 +0300 Subject: [PATCH 7/7] return removed empty line --- src/gui/optionsdialog.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/gui/optionsdialog.cpp b/src/gui/optionsdialog.cpp index 7cb9be963..114f3004f 100644 --- a/src/gui/optionsdialog.cpp +++ b/src/gui/optionsdialog.cpp @@ -1228,6 +1228,7 @@ void OptionsDialog::saveBittorrentTabOptions() const BitTorrent::ShareLimitAction::EnableSuperSeeding }; session->setShareLimitAction(actIndex.value(m_ui->comboRatioLimitAct->currentIndex())); + session->setAddTrackersEnabled(m_ui->checkEnableAddTrackers->isChecked()); session->setAdditionalTrackers(m_ui->textTrackers->toPlainText());