diff --git a/src/gui/rss/rsswidget.cpp b/src/gui/rss/rsswidget.cpp index a6ca52b6c..521e8eb2f 100644 --- a/src/gui/rss/rsswidget.cpp +++ b/src/gui/rss/rsswidget.cpp @@ -559,6 +559,41 @@ bool RSSWidget::eventFilter(QObject *obj, QEvent *event) return false; } +void RSSWidget::convertRelativePathToAbsolute(QString &html, const QString &basePath) const +{ + QRegularExpression rx; + rx.setPatternOptions(QRegularExpression::CaseInsensitiveOption); + // href regex + rx.setPattern( + uR"(((]*?href|]*?src)\s*=\s*["'])((https?|ftp):)?(\/\/[^\/]*)?(\/?[^\/"].*?)(["']))"_s); + + QString normalizedBasePath = basePath.endsWith(u'/') ? basePath : basePath + u'/'; + QRegularExpressionMatchIterator iter = rx.globalMatch(html); + + while (iter.hasNext()) + { + QRegularExpressionMatch match = iter.next(); + const QString &fullMatch = match.captured(0); + const Qstring &prefix = match.captured(1); + const QString &scheme = match.captured(4); + const QString &host = match.captured(5); + QString relativePath = match.captured(6); + const QString &suffix = match.captured(7); + if (relativePath.startsWith(u'/')) + relativePath = relativePath.mid(1); + if (!scheme.isEmpty() && !host.isEmpty()) // already absolute path + continue; + else if (!host.isEmpty()) + normalizedBasePath = u"http:" + host; + else if (!scheme.isEmpty()) + break; // invalid url, should never happen + QString absolutePath = normalizedBasePath + relativePath; + + html.replace(fullMatch, + prefix + absolutePath + suffix); + } +} + void RSSWidget::renderArticle(const RSS::Article *article) const { Q_ASSERT(article); @@ -610,6 +645,11 @@ void RSSWidget::renderArticle(const RSS::Article *article) const html += u"
" + description + u"
"; } + // Supplement relative path to absolute path + + QUrl url {article->link()}; + QString basePath = url.scheme() + u"://" + url.host(); + convertRelativePathToAbsolute(html, basePath); html += u""; m_ui->textBrowser->setHtml(html); } diff --git a/src/gui/rss/rsswidget.h b/src/gui/rss/rsswidget.h index cc1da53bc..f90f41789 100644 --- a/src/gui/rss/rsswidget.h +++ b/src/gui/rss/rsswidget.h @@ -91,6 +91,7 @@ private slots: private: bool eventFilter(QObject *obj, QEvent *event) override; + void convertRelativePathToAbsolute(QString &html, const QString &basePath) const; void renderArticle(const RSS::Article *article) const; Ui::RSSWidget *m_ui = nullptr;