From 8215c7bcde3e1fcb3635059c408b4b97e42f2141 Mon Sep 17 00:00:00 2001 From: "Danilo M." Date: Tue, 29 Sep 2026 16:16:36 +0200 Subject: feat(notifications): render bodies as Markdown Balloon and drawer bodies switch from RichText to Qt's MarkdownText (CommonMark plus GitHub extensions). Raw HTML still goes through Qt's HTML importer, so body-markup senders keep working. Markdown images fetch their destination the same way an does, which the existing sanitize filter would miss since it only inspects tags. sanitize now escapes every "![" so the syntax renders as literal text, local or remote; parsing CommonMark destinations and reference definitions to allow local ones is not worth the grammar. Verified in the shell log: before the filter reached the running shell, a test body fetched https://example.org/a.png; after, a second one did not. Co-Authored-By: Claude Opus 5.5 --- shared/Notify.qml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'shared') diff --git a/shared/Notify.qml b/shared/Notify.qml index 1abe57d..cb1e2fe 100644 --- a/shared/Notify.qml +++ b/shared/Notify.qml @@ -75,6 +75,13 @@ Singleton { // not just the first, so a decoy attribute cannot shadow a remote one; // entities are decoded before the test, so an encoded scheme cannot slip // past. + // + // The body renders as Markdown, so the same rule covers its image syntax: + // `![alt](url)` and `![alt][ref]` fetch just as an does, and parsing + // their destinations would mean reimplementing CommonMark's link grammar. + // Escaping the bracket turns every one into literal text instead, local or + // not. Raw HTML inside Markdown goes through Qt's HTML importer, so the + // tag filter below still applies to it. function sanitize(body) { function decode(s) { return s.replace(/&(?:#x([0-9a-f]+)|#(\d+)|(amp|colon|sol|tab|quot));/gi, @@ -84,7 +91,7 @@ Singleton { return { amp: "&", colon: ":", sol: "/", tab: "\t", quot: "\"" }[name.toLowerCase()]; }); } - return (body || "").replace(/]*>/gi, function (tag) { + return (body || "").replace(/!\[/g, "!\\[").replace(/]*>/gi, function (tag) { const re = /(?:^|\s)src\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s>]+))/gi; let m, found = false, local = true; while ((m = re.exec(tag))) { -- cgit v1.2.3