diff --git a/package-lock.json b/package-lock.json index aacf5d057..3a478467a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,11 @@ { "name": "trilium", - "version": "0.62.1-beta", + "version": "0.62.2", "lockfileVersion": 2, "requires": true, "packages": { "": { - "name": "trilium", - "version": "0.62.1-beta", + "version": "0.62.2", "hasInstallScript": true, "license": "AGPL-3.0-only", "dependencies": { diff --git a/src/public/app/services/content_renderer.js b/src/public/app/services/content_renderer.js index 6f66adfb0..8be8ba1e8 100644 --- a/src/public/app/services/content_renderer.js +++ b/src/public/app/services/content_renderer.js @@ -117,14 +117,14 @@ async function renderCode(note, $renderedContent) { } function renderImage(entity, $renderedContent, options = {}) { - const sanitizedTitle = entity.title.replace(/[^a-z0-9-.]/gi, ""); + const encodedTitle = encodeURIComponent(entity.title); let url; if (entity instanceof FNote) { - url = `api/images/${entity.noteId}/${sanitizedTitle}?${Math.random()}`; + url = `api/images/${entity.noteId}/${encodedTitle}?${Math.random()}`; } else if (entity instanceof FAttachment) { - url = `api/attachments/${entity.attachmentId}/image/${sanitizedTitle}?${entity.utcDateModified}">`; + url = `api/attachments/${entity.attachmentId}/image/${encodedTitle}?${entity.utcDateModified}">`; } $renderedContent // styles needed for the zoom to work well diff --git a/src/public/app/widgets/dialogs/revisions.js b/src/public/app/widgets/dialogs/revisions.js index 1799ce37a..b040ed994 100644 --- a/src/public/app/widgets/dialogs/revisions.js +++ b/src/public/app/widgets/dialogs/revisions.js @@ -274,16 +274,16 @@ export default class RevisionsDialog extends BasicWidget { this.$content.html($table); } else if (revisionItem.type === 'canvas') { - const sanitizedTitle = revisionItem.title.replace(/[^a-z0-9-.]/gi, ""); + const encodedTitle = encodeURIComponent(revisionItem.title); this.$content.html($("") - .attr("src", `api/revisions/${revisionItem.revisionId}/image/${sanitizedTitle}?${Math.random()}`) + .attr("src", `api/revisions/${revisionItem.revisionId}/image/${encodedTitle}?${Math.random()}`) .css("max-width", "100%")); } else if (revisionItem.type === 'mermaid') { - const sanitizedTitle = revisionItem.title.replace(/[^a-z0-9-.]/gi, ""); + const encodedTitle = encodeURIComponent(revisionItem.title); this.$content.html($("") - .attr("src", `api/revisions/${revisionItem.revisionId}/image/${sanitizedTitle}?${Math.random()}`) + .attr("src", `api/revisions/${revisionItem.revisionId}/image/${encodedTitle}?${Math.random()}`) .css("max-width", "100%")); this.$content.append($("
").text(fullRevision.content));
diff --git a/src/public/app/widgets/type_widgets/editable_text.js b/src/public/app/widgets/type_widgets/editable_text.js
index 36cdc170f..d2c601658 100644
--- a/src/public/app/widgets/type_widgets/editable_text.js
+++ b/src/public/app/widgets/type_widgets/editable_text.js
@@ -365,8 +365,8 @@ export default class EditableTextTypeWidget extends AbstractTextTypeWidget {
         const note = await froca.getNote(noteId);
 
         this.watchdog.editor.model.change( writer => {
-            const sanitizedTitle = note.title.replace(/[^a-z0-9-.]/gi, "");
-            const src = `api/images/${note.noteId}/${sanitizedTitle}`;
+            const encodedTitle = encodeURIComponent(note.title);
+            const src = `api/images/${note.noteId}/${encodedTitle}`;
 
             const imageElement = writer.createElement( 'image',  { 'src': src } );
 
diff --git a/src/routes/api/clipper.js b/src/routes/api/clipper.js
index a1eaba3b4..9a39ca797 100644
--- a/src/routes/api/clipper.js
+++ b/src/routes/api/clipper.js
@@ -153,7 +153,9 @@ function processContent(images, note, content) {
             const buffer = Buffer.from(dataUrl.split(",")[1], 'base64');
 
             const attachment = imageService.saveImageToAttachment(note.noteId, buffer, filename, true);
-            const sanitizedTitle = attachment.title.replace(/[^a-z0-9-.]/gi, "");
+
+            // We might want to replace with escape-html. For non-latin-based languages, this doesn't work well.
+            const sanitizedTitle = attachment.title.replace(/[^a-z0-9-.]/gi, "") || "attachment";
             const url = `api/attachments/${attachment.attachmentId}/image/${sanitizedTitle}`;
 
             log.info(`Replacing '${imageId}' with '${url}' in note '${note.noteId}'`);
diff --git a/src/services/import/enex.js b/src/services/import/enex.js
index 5dcd9453b..ec2a36c53 100644
--- a/src/services/import/enex.js
+++ b/src/services/import/enex.js
@@ -303,7 +303,8 @@ function importEnex(taskContext, file, parentNote) {
 
                     const attachment = imageService.saveImageToAttachment(noteEntity.noteId, resource.content, originalName, taskContext.data.shrinkImages);
 
-                    const sanitizedTitle = attachment.title.replace(/[^a-z0-9-.]/gi, "");
+                    // We might want to replace with escape-html. For non-latin-based languages, this doesn't work well.
+                    const sanitizedTitle = attachment.title.replace(/[^a-z0-9-.]/gi, "") || "attachment";
                     const url = `api/attachments/${attachment.attachmentId}/image/${sanitizedTitle}`;
                     const imageLink = ``;
 
diff --git a/src/services/notes.js b/src/services/notes.js
index 3e63dea8e..e9c7e1b76 100644
--- a/src/services/notes.js
+++ b/src/services/notes.js
@@ -529,7 +529,8 @@ function downloadImages(noteId, content) {
             const imageService = require('../services/image');
             const attachment = imageService.saveImageToAttachment(noteId, imageBuffer, "inline image", true, true);
 
-            const sanitizedTitle = attachment.title.replace(/[^a-z0-9-.]/gi, "");
+            // We might want to replace with escape-html. For non-latin-based languages, this doesn't work well.
+            const sanitizedTitle = attachment.title.replace(/[^a-z0-9-.]/gi, "") || "attachment";
 
             content = `${content.substr(0, imageMatch.index)}