aboutsummaryrefslogtreecommitdiffstats
path: root/src/messageview.cpp
AgeCommit message (Collapse)AuthorFilesLines
21 hoursfix: render the message pane at allDanilo M.1-4/+12
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>
21 hoursfeat: add MessageView with locked-down web engine profileDanilo M.1-0/+227
Off-the-record profile, JavaScript off, deny-by-default interceptor, and a page subclass that hands link clicks to the system browser so a message can never navigate the pane. Honours the obligation task 5 recorded: the interceptor trusts exactly one qtmaildir: URL and fails closed otherwise, so setHtml() and setDocumentUrl() must agree or the pane renders nothing. Rather than pairing those calls at each site, every load goes through one setDocument() and the URL comes from a single documentUrl() accessor. Verified against the real interceptor that this URL is allowed while siblings, subpaths, remote and file: are not. Three fixes against the drafted version: - showError() called setHtml() with a base URL but never setDocumentUrl(), so an error card would have rendered blank. Now impossible to repeat. - clear() and showError() left the previous thread's inline parts in the scheme handler and its cids in the interceptor. Both now empty the policy, so no thread's parts outlive it. - MessagePage trusted the whole qtmaildir: scheme for typed navigations, which is the same blanket-trust mistake task 5 removed from the interceptor. It now matches the exact document URL. The parts-flattening is extracted into buildThreadCidMap() so it can be tested without a live profile, and a cidPrefix containing '!' is sanitized rather than trusted, since Q_ASSERT is compiled out in release and this map decides which bytes a message can name. The sanitizer escapes '_' before replacing '!', because a plain replace would map "m0!x" and "m0_x" onto one key and merge two messages, which is the very collision the namespacing exists to prevent. Mutation-verified: the naive replace fails the distinctness test, and dropping the sanitizer trips the assert. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>