diff --git a/src/gui/rss/rsswidget.cpp b/src/gui/rss/rsswidget.cpp index b2fc2454f..fb711b0ac 100644 --- a/src/gui/rss/rsswidget.cpp +++ b/src/gui/rss/rsswidget.cpp @@ -40,6 +40,7 @@ #include #include "base/global.h" +#include "base/logger.h" #include "base/net/downloadmanager.h" #include "base/preferences.h" #include "base/rss/rss_article.h" @@ -433,16 +434,52 @@ void RSSWidget::downloadSelectedTorrents() // open the url of the selected RSS articles in the Web browser void RSSWidget::openSelectedArticlesUrls() { + qsizetype emptyLinkCount = 0; + qsizetype badLinkCount = 0; + QString articleTitle; for (QListWidgetItem *item : asConst(m_ui->articleListWidget->selectedItems())) { auto *article = item->data(Qt::UserRole).value(); Q_ASSERT(article); - // Mark as read article->markAsRead(); - if (const QUrl articleLink {article->link()}; !articleLink.isEmpty() && !articleLink.isLocalFile()) - QDesktopServices::openUrl(articleLink); + const QString articleLink = article->link(); + const QUrl articleLinkURL {articleLink}; + if (articleLinkURL.isEmpty()) [[unlikely]] + { + if (articleTitle.isEmpty()) + articleTitle = article->title(); + ++emptyLinkCount; + } + else if (articleLinkURL.isLocalFile()) [[unlikely]] + { + if (badLinkCount == 0) + articleTitle = article->title(); + ++badLinkCount; + + LogMsg(tr("Blocked opening RSS article URL. URL pointing to local file might be malicious behaviour. Article: \"%1\". URL: \"%2\".") + .arg(article->title(), articleLink), Log::WARNING); + } + else [[likely]] + { + QDesktopServices::openUrl(articleLinkURL); + } + } + + if (badLinkCount > 0) + { + QString message = tr("Blocked opening RSS article URL. The following article URL is pointing to local file and it may be malicious behaviour:\n%1").arg(articleTitle); + if (badLinkCount > 1) + message.append(u"\n" + tr("There are %1 more articles with the same issue.").arg(badLinkCount - 1)); + QMessageBox::warning(this, u"qBittorrent"_s, message, QMessageBox::Ok); + } + else if (emptyLinkCount > 0) + { + QString message = tr("The following article has no news URL provided:\n%1").arg(articleTitle); + if (emptyLinkCount > 1) + message.append(u"\n" + tr("There are %1 more articles with the same issue.").arg(emptyLinkCount - 1)); + QMessageBox::warning(this, u"qBittorrent"_s, message, QMessageBox::Ok); } } diff --git a/src/gui/search/searchjobwidget.cpp b/src/gui/search/searchjobwidget.cpp index 01e83eec0..5544ea150 100644 --- a/src/gui/search/searchjobwidget.cpp +++ b/src/gui/search/searchjobwidget.cpp @@ -35,10 +35,12 @@ #include #include #include +#include #include #include #include +#include "base/logger.h" #include "base/preferences.h" #include "base/search/searchdownloadhandler.h" #include "base/search/searchhandler.h" @@ -319,15 +321,52 @@ void SearchJobWidget::downloadTorrents(const AddTorrentOption option) downloadTorrent(rowIndex, option); } -void SearchJobWidget::openTorrentPages() const +void SearchJobWidget::openTorrentPages() { const QModelIndexList rows = m_ui->resultsBrowser->selectionModel()->selectedRows(); + qsizetype emptyLinkCount = 0; + qsizetype badLinkCount = 0; + QString warningEntryName; for (const QModelIndex &rowIndex : rows) { - const QString descrLink = m_proxyModel->data( - m_proxyModel->index(rowIndex.row(), SearchSortModel::DESC_LINK)).toString(); - if (const QUrl descrLinkURL {descrLink}; !descrLinkURL.isEmpty() && !descrLinkURL.isLocalFile()) + const QString entryName = m_proxyModel->index(rowIndex.row(), SearchSortModel::NAME).data().toString(); + const QString descrLink = m_proxyModel->index(rowIndex.row(), SearchSortModel::DESC_LINK).data().toString(); + + const QUrl descrLinkURL {descrLink}; + if (descrLinkURL.isEmpty()) [[unlikely]] + { + if (warningEntryName.isEmpty()) + warningEntryName = entryName; + ++emptyLinkCount; + } + else if (descrLinkURL.isLocalFile()) [[unlikely]] + { + if (badLinkCount == 0) + warningEntryName = entryName; + ++badLinkCount; + + LogMsg(tr("Blocked opening search result description page URL. URL pointing to local file might be malicious behaviour. Name: \"%1\". URL: \"%2\".") + .arg(entryName, descrLink), Log::WARNING); + } + else [[likely]] + { QDesktopServices::openUrl(descrLinkURL); + } + } + + if (badLinkCount > 0) + { + QString message = tr("Blocked opening search result description page URL. The following result URL is pointing to local file and it may be malicious behaviour:\n%1").arg(warningEntryName); + if (badLinkCount > 1) + message.append(u"\n" + tr("There are %1 more results with the same issue.").arg(badLinkCount - 1)); + QMessageBox::warning(this, u"qBittorrent"_s, message, QMessageBox::Ok); + } + else if (emptyLinkCount > 0) + { + QString message = tr("Entry \"%1\" has no description page URL provided.").arg(warningEntryName); + if (emptyLinkCount > 1) + message.append(u"\n" + tr("There are %1 more entries with the same issue.").arg(emptyLinkCount - 1)); + QMessageBox::warning(this, u"qBittorrent"_s, message, QMessageBox::Ok); } } diff --git a/src/gui/search/searchjobwidget.h b/src/gui/search/searchjobwidget.h index 7ef36cf38..f6b879fce 100644 --- a/src/gui/search/searchjobwidget.h +++ b/src/gui/search/searchjobwidget.h @@ -127,7 +127,7 @@ private: void onUIThemeChanged(); void downloadTorrents(AddTorrentOption option = AddTorrentOption::Default); - void openTorrentPages() const; + void openTorrentPages(); void copyTorrentURLs() const; void copyTorrentDownloadLinks() const; void copyTorrentNames() const;