From d7f55c16f1249d1f8f1ba6771d71aebfeefb4088 Mon Sep 17 00:00:00 2001 From: defnax <9952056+defnax@users.noreply.github.com> Date: Wed, 9 Sep 2026 20:21:47 +0200 Subject: [PATCH] Fixed. Valid retroshare://file attachments now survive HTML removal and provide a clickable download action. --- webui-src/app/chat/chat_state.js | 35 ++++++++++++++++++++++++++ webui-src/app/files/files_downloads.js | 1 + 2 files changed, 36 insertions(+) diff --git a/webui-src/app/chat/chat_state.js b/webui-src/app/chat/chat_state.js index afff2c6..37e3e66 100644 --- a/webui-src/app/chat/chat_state.js +++ b/webui-src/app/chat/chat_state.js @@ -213,6 +213,41 @@ function openChatImageViewer(src) { function renderChatMessage(rawText) { if (!rawText) return ''; + // Preserve file attachments before HTML-to-text conversion drops their href. + // Parse inside an inert template and rebuild the link, never render peer HTML. + const anchorRegex = /]*>[\s\S]*?<\/a\s*>/gi; + const fileParts = []; + let fileEnd = 0; + let anchor; + while ((anchor = anchorRegex.exec(rawText)) !== null) { + const template = document.createElement('template'); + template.innerHTML = anchor[0]; + const link = template.content.querySelector('a'); + const href = link && link.getAttribute('href'); + if (!href || !/^retroshare:\/\/file\?/i.test(href)) continue; + let url; + try { url = new URL(href); } catch (_) { continue; } + const name = url.searchParams.get('name'); + const size = url.searchParams.get('size'); + const hash = url.searchParams.get('hash'); + if (!name || !/^\d+$/.test(size || '') || !/^[a-f0-9]{40}$/i.test(hash || '')) continue; + const safeHref = `retroshare://file?name=${encodeURIComponent(name)}&size=${size}&hash=${hash}`; + if (anchor.index > fileEnd) fileParts.push(renderChatMessage(rawText.slice(fileEnd, anchor.index))); + fileParts.push(m('a.chat-file-link', { + href: safeHref, + title: `Download ${name}`, + onclick: (event) => { + event.preventDefault(); + require('files/files_downloads').addFile(safeHref); + }, + }, link.textContent || name)); + fileEnd = anchorRegex.lastIndex; + } + if (fileParts.length) { + if (fileEnd < rawText.length) fileParts.push(renderChatMessage(rawText.slice(fileEnd))); + return fileParts; + } + // 1. Check for HTML tags const imgRegex = /]*src=["']([^"']+)["'][^>]*>/gi; if (imgRegex.test(rawText)) { diff --git a/webui-src/app/files/files_downloads.js b/webui-src/app/files/files_downloads.js index 3205081..dff154b 100644 --- a/webui-src/app/files/files_downloads.js +++ b/webui-src/app/files/files_downloads.js @@ -190,6 +190,7 @@ const Component = () => { }; module.exports = { + addFile, Component, Downloads, list: Downloads.statusMap,