From d49c337dadb9ebc217e5befded26e8b0510b8af4 Mon Sep 17 00:00:00 2001 From: Bobby Date: Wed, 6 Dec 2023 05:55:50 +0700 Subject: [PATCH] fix: special characters in album titles --- controllers/albumsController.js | 2 +- controllers/middlewares/NunjucksRenderer.js | 3 +- controllers/utilsController.js | 70 +++++++-------------- routes/album.js | 4 +- views/_layout.njk | 6 +- views/album-notice.njk | 2 +- views/album.njk | 2 +- 7 files changed, 33 insertions(+), 56 deletions(-) diff --git a/controllers/albumsController.js b/controllers/albumsController.js index 202ae72..f1ab39d 100644 --- a/controllers/albumsController.js +++ b/controllers/albumsController.js @@ -452,7 +452,7 @@ self.edit = async (req, res) => { identifier: update.identifier }) } else { - return res.json({ success: true, name }) + return res.json({ success: true, name: utils.unescape(name) }) } } diff --git a/controllers/middlewares/NunjucksRenderer.js b/controllers/middlewares/NunjucksRenderer.js index 273692a..5b14158 100644 --- a/controllers/middlewares/NunjucksRenderer.js +++ b/controllers/middlewares/NunjucksRenderer.js @@ -54,7 +54,8 @@ class NunjucksRenderer { resolve(html) }) }).then(html => { - res.type('html').send(html) + res.header('Content-Type', 'text/html; charset=utf-8') + res.send(html) return html }) } diff --git a/controllers/utilsController.js b/controllers/utilsController.js index 188cd33..59b4d78 100644 --- a/controllers/utilsController.js +++ b/controllers/utilsController.js @@ -292,56 +292,30 @@ self.extname = (filename, lower) => { return lower ? str.toLowerCase() : str } +const escapeMap = { + '&': '&', + '"': '"', + '\'': ''', + '<': '<', + '>': '>', + '\\': '\' +} + +const escapeRegex = /[&"'<>\\]/g + +const unescapeMap = Object.keys(escapeMap).reduce((ret, key) => { + ret[escapeMap[key]] = key + return ret +}, {}) + +const unescapeRegex = /&(amp|quot|#39|lt|gt|#92);/g + self.escape = string => { - // MIT License - // Copyright(c) 2012-2013 TJ Holowaychuk - // Copyright(c) 2015 Andreas Lubbe - // Copyright(c) 2015 Tiancheng "Timothy" Gu + return string.replace(escapeRegex, key => escapeMap[key]) +} - if (!string) return string - - const str = String(string) - const match = /["'&<>]/.exec(str) - - if (!match) return str - - let escape - let html = '' - let index = 0 - let lastIndex = 0 - - for (index = match.index; index < str.length; index++) { - switch (str.charCodeAt(index)) { - case 34: // " - escape = '"' - break - case 38: // & - escape = '&' - break - case 39: // ' - escape = ''' - break - case 60: // < - escape = '<' - break - case 62: // > - escape = '>' - break - default: - continue - } - - if (lastIndex !== index) { - html += str.substring(lastIndex, index) - } - - lastIndex = index + 1 - html += escape - } - - return lastIndex !== index - ? html + str.substring(lastIndex, index) - : html +self.unescape = string => { + return string.replace(unescapeRegex, key => unescapeMap[key]) } self.stripIndents = string => { diff --git a/routes/album.js b/routes/album.js index 4807e39..6e06b97 100644 --- a/routes/album.js +++ b/routes/album.js @@ -23,6 +23,7 @@ routes.get('/a/:identifier', async (req, res) => { return errors.handleNotFound(req, res) } + album.name = utils.unescape(album.name) const nojs = req.query_parameters.nojs !== undefined let cacheid @@ -32,7 +33,8 @@ routes.get('/a/:identifier', async (req, res) => { const cache = utils.albumRenderStore.get(cacheid) if (cache) { - return res.type('html').send(cache) + res.header('Content-Type', 'text/html; charset=utf-8') + return res.send(cache) } else if (cache === null) { return res.render('album-notice', { config, diff --git a/views/_layout.njk b/views/_layout.njk index 31b0420..f4ba6f9 100644 --- a/views/_layout.njk +++ b/views/_layout.njk @@ -22,7 +22,7 @@ - {{ title }} + {{ title | safe }} {% block stylesheets %} @@ -33,7 +33,7 @@ - + {%- if metaImage %} @@ -48,7 +48,7 @@ - + {%- if metaImage %} diff --git a/views/album-notice.njk b/views/album-notice.njk index f80b50c..27afc83 100644 --- a/views/album-notice.njk +++ b/views/album-notice.njk @@ -1,5 +1,5 @@ {% set metaTitle %} -{{- album.name | truncate(60, true, '…') -}} +{{- album.name | safe | truncate(60, true, '…') -}} {% endset %} {% set metaDesc = album.description | striptags | truncate(200, true, '…') %} {% set metaUrl = '/' + album.url %} diff --git a/views/album.njk b/views/album.njk index 7ba68c5..ecbd82b 100644 --- a/views/album.njk +++ b/views/album.njk @@ -1,5 +1,5 @@ {% set metaTitle %} -{{- album.name | truncate(60, true, '…') + ' – ' + files.length + ' file' + ('s' if files.length !== 1) -}} +{{- album.name | safe | truncate(60, true, '…') }} - {{ files.length + ' file' + ('s' if files.length !== 1) -}} {% endset %} {% set metaDesc = album.description | striptags | truncate(200, true, '…') %} {% set metaUrl = '/' + album.url %}