From 257d928ab385a6520040688ed599676735e206a8 Mon Sep 17 00:00:00 2001 From: Zentino <52699319+zent1n0@users.noreply.github.com> Date: Fri, 20 Dec 2024 15:19:34 +0800 Subject: [PATCH] Resolve relative URLs within RSS article description PR #21943. --------- Co-authored-by: Vladimir Golovnev --- src/gui/rss/rsswidget.cpp | 47 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/src/gui/rss/rsswidget.cpp b/src/gui/rss/rsswidget.cpp index d6e7439ab..5d05df0b8 100644 --- a/src/gui/rss/rsswidget.cpp +++ b/src/gui/rss/rsswidget.cpp @@ -54,6 +54,48 @@ #include "feedlistwidget.h" #include "ui_rsswidget.h" +namespace +{ + void convertRelativeUrlToAbsolute(QString &html, const QString &baseUrl) + { + const QRegularExpression rx {uR"(((]*?href|]*?src)\s*=\s*["'])((https?|ftp):)?(\/\/[^\/]*)?(\/?[^\/"].*?)(["']))"_s + , QRegularExpression::CaseInsensitiveOption}; + + const QString normalizedBaseUrl = baseUrl.endsWith(u'/') ? baseUrl : (baseUrl + u'/'); + const QUrl url {normalizedBaseUrl}; + const QString defaultScheme = url.scheme(); + QRegularExpressionMatchIterator iter = rx.globalMatch(html); + + while (iter.hasNext()) + { + const QRegularExpressionMatch match = iter.next(); + const QString scheme = match.captured(4); + const QString host = match.captured(5); + if (!scheme.isEmpty()) + { + if (host.isEmpty()) + break; // invalid URL, should never happen + + // already absolute URL + continue; + } + + QString relativePath = match.captured(6); + if (relativePath.startsWith(u'/')) + relativePath = relativePath.mid(1); + + const QString absoluteUrl = !host.isEmpty() + ? QString(defaultScheme + u':' + host) : (normalizedBaseUrl + relativePath); + const QString fullMatch = match.captured(0); + const QString prefix = match.captured(1); + const QString suffix = match.captured(7); + + html.replace(fullMatch, (prefix + absoluteUrl + suffix)); + } + } +} + + RSSWidget::RSSWidget(IGUIApplication *app, QWidget *parent) : GUIApplicationComponent(app, parent) , m_ui {new Ui::RSSWidget} @@ -605,6 +647,11 @@ void RSSWidget::renderArticle(const RSS::Article *article) const html += u"
" + description + u"
"; } + + // Supplement relative URLs to absolute ones + const QUrl url {article->link()}; + const QString baseUrl = url.toString(QUrl::RemovePath | QUrl::RemoveQuery); + convertRelativeUrlToAbsolute(html, baseUrl); html += u""; m_ui->textBrowser->setHtml(html); }