From 2f90d39c969f91a2d2908cf6aec532b2cb98573c Mon Sep 17 00:00:00 2001 From: Warren R Bank Date: Wed, 22 Dec 2021 03:33:00 -0800 Subject: [PATCH] in directory listings, properly encode unsafe URL characters in links fixes: * upstream issue 566 https://github.com/vercel/serve/issues/566 --- lib/serve-handler/src/directory.js | 31 +++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/lib/serve-handler/src/directory.js b/lib/serve-handler/src/directory.js index 4c54dd9..d97f304 100644 --- a/lib/serve-handler/src/directory.js +++ b/lib/serve-handler/src/directory.js @@ -192,22 +192,35 @@ const staticTemplateStrings = { const doNotSkipEncoded = false const matchHTML = doNotSkipEncoded ? /[&<>"'\/]/g : /&(?!#?\w+;)|[<>"'\/]/g const encodeHTMLRules = { -//"/": "/", "&": "&", "<": "<", ">": ">", '"': """, - "'": "'" + "'": "'", + "/": "/" } -const encodeHTML = code => { - return (!code || (typeof code !== 'string')) +const matchURL = /[ <>%#\?]/g +const encodeURLRules = { + " ": "%20", + "<": "%3C", + ">": "%3E", + '%': "%25", + "#": "%23", + "?": "%3F" +} + +const encodeString = (text, charset_regex, charset_map) => { + return (!text || (typeof text !== 'string')) ? '' - : code.toString().replace(matchHTML, function(m) { - return encodeHTMLRules[m] || m + : text.toString().replace(charset_regex, function(char_value) { + return charset_map[char_value] || char_value }) } +const encodeHTML = text => encodeString(text, matchHTML, encodeHTMLRules) +const encodeURL = text => encodeString(text, matchURL, encodeURLRules) + const directoryTemplate = spec => { const {paths, files} = spec const title = encodeHTML(spec.directory) @@ -220,7 +233,7 @@ const directoryTemplate = spec => { if (Array.isArray(paths) && paths.length) { for (let path of paths) { - html += `${encodeHTML(path.name)}` + html += `${encodeHTML(path.name)}` } } @@ -230,10 +243,10 @@ const directoryTemplate = spec => { if (Array.isArray(files) && files.length) { for (let file of files) { html += '
  • ' - html += `${encodeHTML(file.base)}` + html += `${encodeHTML(file.base)}` if ((file.stats instanceof Object) && file.stats.mtime) - html += `
    ${file.stats.size ? `${file.stats.size} | ` : ''}${file.stats.mtime}
    ` + html += `
    ${file.stats.size ? `${encodeHTML(file.stats.size)} | ` : ''}${encodeHTML(file.stats.mtime)}
    ` html += '
  • ' }