diff --git a/src/base/net/downloadhandlerimpl.cpp b/src/base/net/downloadhandlerimpl.cpp index 370347946c1f..61a516088473 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 8f74c2f9d135..a13768e9d534 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/optionsdialog.cpp b/src/gui/optionsdialog.cpp index ba4ee232c8a3..a8416c21e7d0 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" @@ -1229,8 +1230,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 c1e29c1d6c3c..1e7afa4c8985 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; @@ -137,9 +138,12 @@ private slots: void loadRSSTabOptions(); void saveRSSTabOptions() const; + void onAddTrackersDownload(const Net::DownloadResult &result); + void loadSearchTabOptions(); void saveSearchTabOptions() const; + #ifndef DISABLE_WEBUI void loadWebUITabOptions(); void saveWebUITabOptions() const; diff --git a/src/gui/trackersadditiondialog.cpp b/src/gui/trackersadditiondialog.cpp index 0014d5a5521b..9403edf3b535 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); } @@ -116,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 0dc658cffef7..893379f684f8 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;