From e8bf3a12cd24780dbe59c8798b1eb6536c9828d0 Mon Sep 17 00:00:00 2001 From: "Danilo M." Date: Sun, 2 Aug 2026 17:46:21 +0200 Subject: feat: add HTML builder and cid: scheme handler HtmlBuilder renders parsed messages (and whole threads, as one document, so newsletter threads don't spawn one Chromium process per message) into the HTML string the web view loads. Plain text is escaped and quote lines marked; the cid: rewrite is namespaced per message ("!") so two thread messages sharing a Content-ID don't collide. Hardened namespaceCids beyond the initial sketch after attacking it: handles unquoted cid: attribute values, background=/poster= (not just src/href), and CSS url(cid:...) in both style="" attributes and "), + QStringLiteral("m0")); + QVERIFY(html.contains(QStringLiteral("cid:m0!bg@example.org"))); +} + +void TestHtmlBuilder::namespacesMultipleCidRefsOnOneLine() +{ + // Guards against a greedy [^"']+ eating past the first closing quote. + const QString html = HtmlBuilder::namespaceCids( + QStringLiteral(""), + QStringLiteral("m0")); + QVERIFY(html.contains(QStringLiteral("cid:m0!a@x"))); + QVERIFY(html.contains(QStringLiteral("cid:m0!b@x"))); + // A greedy [^"']+ would eat past the first closing quote and swallow the + // second tag's markup into the first cid value; guard against that by + // requiring the first tag to close immediately after its own value. + QVERIFY(html.contains(QStringLiteral("cid:m0!a@x\">"), + QStringLiteral("m0")); + QVERIFY(html.contains(QStringLiteral("cid:m0!logo@example.org"))); +} + +QTEST_MAIN(TestHtmlBuilder) +#include "test_htmlbuilder.moc" -- cgit v1.2.3