aboutsummaryrefslogtreecommitdiffstats
path: root/tests/test_htmlbuilder.cpp
AgeCommit message (Collapse)AuthorFilesLines
2026-08-07feat(ui): fill the blank message pane with a branded placeholderDanilo M.1-0/+171
An empty right pane said nothing, and multi-select made it a routine sight. It now carries the wordmark, thread counts that run their query when clicked, and a sync line that appears only when something needs attention. Rendered into the existing web view as a third document shape, so there is one document path and one set of security rules. The brand palette is a deliberate exception to deriving colours from the desktop theme, since a logo is brand rather than chrome; the theme still picks which of the two sets is used. Counts refresh when the pane is about to show rather than in the background: one goes stale the moment a tag is edited, and refreshing one nobody is looking at is work for nothing. A generation counter discards a superseded reply, and a late answer cannot repaint over an opened thread. The helper lines are real links because JavaScript is off in this profile. The handler is gated on the placeholder actually being displayed, so the same URL inside a message body is dropped: a stranger's mail must not drive the thread list, even to run a harmless query. Three defects found while building, all silent: - Every CSS percentage was invalid. QString::arg does not collapse "%%" into "%", so the document carried "50%%" and the browser dropped each declaration holding one, disabling the mask, the glow and both radial gradients while still rendering something plausible. Substitution is by named token now, which cannot collide with a percent sign. - A geometry probe endorsed the layout while that was live, because it measured only properties without percentages. - The font test passed against a build with one face missing, since the other satisfied both of its checks on its own. The mockup's light values needed correcting against a real pane: the grid vanished at a 2% luminance step on white, and the glow subtracts light there rather than adding it, washing the pane. Strength only, not hue.
2026-08-07fix(ui): the message pane follows the desktop themeDanilo M.1-0/+121
The stylesheet hardcoded #bbb, #555, #000, #666, #ddd and #4a6f8a, and set no background at all, so on a dark desktop plain-text mail rendered as black on white inside a dark window and the web view's own default showed through. The colours now come from a Palette struct derived from QPalette, and are passed into the builder rather than read from qApp inside it, so the stylesheet can be tested against a known palette with no running application. Base and Text rather than Window and WindowText: the pane is a content surface like a text edit, and on many themes those differ. The secondary colours are blends of text and background, not fixed greys. That is the part that makes it work both ways round, since a #555 chosen to read as subtle on white is nearly invisible on #2b2b2b. The quote colour keeps its hue, because "this is quoted" is carried by being a different colour rather than a dimmer one, but is pulled toward the background so it stays readable instead of glowing on dark. A sender's own HTML is deliberately left alone, and a test asserts that so it cannot drift: rewriting a sender's styling would break layouts that depend on it, and a newsletter setting a white background is entitled to stay white. This themes the plain-text render and the chrome around messages, nothing more. MessageView passes its own widget palette rather than the application's, since a style sheet or a themed parent can give the pane different colours from qApp, and re-renders on PaletteChange: the document's colours are baked into its stylesheet at build time, so unlike a widget it does not restyle itself when the desktop theme changes. The load-bearing test asserts the negative, that no hex colour appears in the style block which the palette did not supply. A test checking only that the palette's colours are present passes with a leftover literal still there, and one leftover literal is the whole defect. Confirmed by mutation. Closes item 12. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-04Add GPLv2-only license and per-file headersDanilo M.1-0/+18
Confirmed with the maintainer as v2-only rather than v2-or-later. LICENSE is the official text from gnu.org. Every file under src/ and tests/ carries the matching notice. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-04fix: enforce !-free cidPrefix invariant at both concatenation sitesDanilo M.1-0/+56
The cid: namespacing scheme (cid:<prefix>!<id>) is only unambiguous because the prefix half is guaranteed free of '!': the first '!' in the result is always the separator, so an attacker-controlled Content-ID containing '!' only extends the id half rather than colliding with a different prefix. That invariant previously existed only as a comment. Add Q_ASSERT_X at both independent call sites that perform this concatenation (CidSchemeHandler::namespacedKey and HtmlBuilder::namespaceCids) so a future prefix generator that violates it traps in debug builds, per Task 5's precedent of not letting one unit's correctness depend silently on another's future behaviour. Since Q_ASSERT compiles out in release, pin the property that actually matters release builds too test: distinct (prefix, id) pairs across a documented "m<index>" prefix set and hostile Content-IDs (containing '!', percent- encoded '!', empty, leading/trailing '!') never collide, and the key always splits at its first '!' back to the exact original prefix.
2026-08-04feat: add HTML builder and cid: scheme handlerDanilo M.1-0/+206
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 ("<prefix>!<id>") 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 <style> blocks, all case-insensitively. Replaced the greedy [^"']+ capture with per-quote-style alternation so two cid: refs on one line can't bleed into each other. CidSchemeHandler serves cid: requests from the thread's inline-parts map, keyed by the same namespaced string, replaced wholesale per thread.