aboutsummaryrefslogtreecommitdiffstats
path: root/src/requestinterceptor.cpp
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-08-03 09:43:07 +0200
committerDanilo M. <danix@danix.xyz>2026-08-03 09:43:07 +0200
commit5de81471ebcac21dbf8c5d781cd1b5f1df931bb8 (patch)
tree785b57c48190602a521bed871ca9242a1f6d3fd9 /src/requestinterceptor.cpp
parentcf17e6126c6487527a1fd1ff2c078e7637c92118 (diff)
downloadqtmaildir-5de81471ebcac21dbf8c5d781cd1b5f1df931bb8.tar.gz
qtmaildir-5de81471ebcac21dbf8c5d781cd1b5f1df931bb8.zip
fix: render the message pane at all
Clicking a thread left the pane blank. Two independent bugs, both from the same false premise: that setHtml() navigates to the base URL it is given. It does not. setHtml() navigates to a data: URL carrying the markup and applies the base URL afterwards, purely as the document's origin. Verified empirically on Qt 6.11. Built on that wrong assumption were: - MessagePage::acceptNavigationRequest compared the navigation's URL against documentUrl() and rejected everything else, so the document load was refused. It now accepts a typed main-frame navigation, which is one we initiated ourselves. - RequestInterceptor exempted exactly the qtmaildir: base URL and denied everything else, so the data: document load was blocked too. The interceptor fix is scoped to ResourceTypeMainFrame rather than allowing the data: scheme outright. A blanket allow would have been a real hole: a message body can write <img src="data:..."> or an iframe, and the existing dataSchemeBlocked test in test_interceptor.cpp was right to fail when that was tried. Sub-resource data: URLs remain denied. Note this was never working. The drafted version had the same defect in a different spelling (it compared url.scheme() rather than the whole URL, and would have rejected the data: navigation just the same), and task 11 shipped with no runtime test to catch it. test_messageview.cpp now pins all three facts: the document loads, its text reaches the page, and a data: image inside a hostile body stays blocked. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Diffstat (limited to 'src/requestinterceptor.cpp')
-rw-r--r--src/requestinterceptor.cpp26
1 files changed, 24 insertions, 2 deletions
diff --git a/src/requestinterceptor.cpp b/src/requestinterceptor.cpp
index 8fd2419..6267b64 100644
--- a/src/requestinterceptor.cpp
+++ b/src/requestinterceptor.cpp
@@ -14,8 +14,13 @@ bool RequestInterceptor::shouldAllow(const QUrl &url)
// by unusual casing, in either the allow or the deny direction.
const QString scheme = url.scheme();
- // The document itself is loaded via setHtml() with a qtmaildir: base URL,
- // so a request for exactly that URL must pass or nothing renders at all.
+ // data: is never allowed here. It is permitted for the main-frame
+ // document only, which is handled in interceptRequest() where the resource
+ // type is known: a message body can put data: in <img src> or
+ // <iframe src>, and those must stay blocked.
+
+ // The document's origin is the qtmaildir: base URL, so requests can still
+ // arrive on that scheme once the document is live.
// This is the ONLY trusted qtmaildir: URL: everything else on this scheme
// is denied, including sub-paths of it. A hostile message body can put
// arbitrary qtmaildir: URLs in <img src>, <link href>, etc., so this
@@ -64,6 +69,23 @@ bool RequestInterceptor::shouldAllow(const QUrl &url)
void RequestInterceptor::interceptRequest(QWebEngineUrlRequestInfo &info)
{
+ // The main-frame document arrives as a data: URL, because setHtml() does
+ // not fetch the base URL it is given: it navigates to a data: URL carrying
+ // the markup and applies the base URL afterwards as the document's origin.
+ // (Verified empirically on Qt 6.11. The qtmaildir: rule in shouldAllow()
+ // was written on the opposite assumption, and until this was found every
+ // document load was blocked and the pane rendered blank.)
+ //
+ // Scoping this to ResourceTypeMainFrame is what keeps it from being a
+ // hole: those bytes are the ones HtmlBuilder produced a moment earlier and
+ // they arrive in the navigation itself rather than over any transport,
+ // while a data: URL written into a message body reaches this function as
+ // an image, stylesheet or subframe and is still denied by shouldAllow().
+ if (info.resourceType() == QWebEngineUrlRequestInfo::ResourceTypeMainFrame
+ && info.requestUrl().scheme() == QLatin1String("data")) {
+ return;
+ }
+
if (!shouldAllow(info.requestUrl()))
info.block(true);
}