mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-07-12 22:39:02 +00:00
atomic file updates, escape attributes
This commit is contained in:
@@ -26,7 +26,7 @@ where
|
||||
import Control.Concurrent.STM (check)
|
||||
import Control.Exception (SomeException, catch)
|
||||
import Control.Logger.Simple
|
||||
import Control.Monad (forM_, unless, void, when)
|
||||
import Control.Monad (forM_, void, when)
|
||||
import Control.Monad.Except (runExceptT)
|
||||
import Data.Either (rights)
|
||||
import Data.Int (Int64)
|
||||
@@ -77,7 +77,7 @@ import Simplex.Chat.Types
|
||||
import Simplex.Messaging.Agent.Store.Common (withTransaction)
|
||||
import Simplex.Messaging.Encoding.String (strEncode)
|
||||
import Simplex.Messaging.Parsers (defaultJSON)
|
||||
import System.Directory (createDirectoryIfMissing, listDirectory, removeFile)
|
||||
import System.Directory (createDirectoryIfMissing, listDirectory, removeFile, renameFile)
|
||||
import System.FilePath (takeExtension, (</>))
|
||||
import UnliftIO.STM
|
||||
|
||||
@@ -261,7 +261,10 @@ renderGroupPreview WebPreviewConfig {webJsonDir, webPreviewItemCount} cc user gI
|
||||
messages = msgs,
|
||||
updatedAt = ts
|
||||
}
|
||||
LB.writeFile (webJsonDir </> fName) (J.encode preview)
|
||||
let destPath = webJsonDir </> fName
|
||||
tmpPath = destPath <> ".tmp"
|
||||
LB.writeFile tmpPath (J.encode preview)
|
||||
renameFile tmpPath destPath
|
||||
pure $ corsEntry publicGroupId <$> publicGroupAccess
|
||||
Nothing -> pure Nothing
|
||||
where
|
||||
@@ -395,8 +398,9 @@ writeCorsConfig entries path =
|
||||
|
||||
removeStaleFiles :: FilePath -> S.Set FilePath -> IO ()
|
||||
removeStaleFiles dir activeFiles = do
|
||||
let jsonFiles = S.filter (\f -> takeExtension f == ".json") . S.fromList
|
||||
allFiles <- jsonFiles <$> listDirectory dir
|
||||
let isPreviewFile f = takeExtension f == ".json" && all isBase64Url (takeWhile (/= '.') f)
|
||||
isBase64Url c = (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '-' || c == '_'
|
||||
allFiles <- S.filter isPreviewFile . S.fromList <$> listDirectory dir
|
||||
mapM_ (\f -> removeFile (dir </> f)) $ S.difference allFiles activeFiles
|
||||
|
||||
toFormattedText :: Text -> Maybe MarkdownList
|
||||
|
||||
@@ -14,6 +14,15 @@ function escapeHtml(text) {
|
||||
.replace(/\n/g, "<br>");
|
||||
}
|
||||
|
||||
function escapeAttr(text) {
|
||||
return text
|
||||
.replace(/&/g, "&")
|
||||
.replace(/"/g, """)
|
||||
.replace(/'/g, "'")
|
||||
.replace(/</g, "<")
|
||||
.replace(/>/g, ">");
|
||||
}
|
||||
|
||||
function getSimplexLinkDescr(linkType) {
|
||||
switch (linkType) {
|
||||
case 'contact': return 'SimpleX contact address';
|
||||
@@ -71,17 +80,17 @@ function renderMarkdown(fts) {
|
||||
break;
|
||||
case 'uri':
|
||||
let href = text.startsWith('http://') || text.startsWith('https://') || text.startsWith('simplex:/') ? text : 'https://' + text;
|
||||
html += `<a href="${href}"${targetBlank(href)}>${escapeHtml(text)}</a>`;
|
||||
html += `<a href="${escapeAttr(href)}"${targetBlank(href)}>${escapeHtml(text)}</a>`;
|
||||
break;
|
||||
case 'hyperLink': {
|
||||
const { showText, linkUri } = format;
|
||||
html += `<a href="${linkUri}"${targetBlank(linkUri)}>${escapeHtml(showText ?? linkUri)}</a>`;
|
||||
html += `<a href="${escapeAttr(linkUri)}"${targetBlank(linkUri)}>${escapeHtml(showText ?? linkUri)}</a>`;
|
||||
break;
|
||||
}
|
||||
case 'simplexLink': {
|
||||
const { showText, linkType, simplexUri, smpHosts } = format;
|
||||
const linkText = showText ? escapeHtml(showText) : getSimplexLinkDescr(linkType);
|
||||
html += `<a href="${platformSimplexUri(simplexUri)}" target="_blank">${linkText} <em>(${viaHost(smpHosts)})</em></a>`;
|
||||
html += `<a href="${escapeAttr(platformSimplexUri(simplexUri))}" target="_blank">${linkText} <em>(${escapeHtml(viaHost(smpHosts))})</em></a>`;
|
||||
break;
|
||||
}
|
||||
case 'command':
|
||||
@@ -91,10 +100,10 @@ function renderMarkdown(fts) {
|
||||
html += `<strong>${escapeHtml(text)}</strong>`;
|
||||
break;
|
||||
case 'email':
|
||||
html += `<a href="mailto:${text}">${escapeHtml(text)}</a>`;
|
||||
html += `<a href="mailto:${escapeAttr(text)}">${escapeHtml(text)}</a>`;
|
||||
break;
|
||||
case 'phone':
|
||||
html += `<a href="tel:${text}">${escapeHtml(text)}</a>`;
|
||||
html += `<a href="tel:${escapeAttr(text)}">${escapeHtml(text)}</a>`;
|
||||
break;
|
||||
case 'unknown':
|
||||
html += escapeHtml(text);
|
||||
|
||||
Reference in New Issue
Block a user