diff --git a/test/webserver.mjs b/test/webserver.mjs index 57c913d66a977..f920165cf1d57 100644 --- a/test/webserver.mjs +++ b/test/webserver.mjs @@ -16,6 +16,7 @@ /* eslint-disable no-var */ import fs from "fs"; +import fsPromises from "fs/promises"; import http from "http"; import path from "path"; @@ -162,7 +163,7 @@ class WebServer { return; } if (isDir) { - serveDirectoryIndex(filePath); + self.#serveDirectoryIndex(res, pathPart, queryPart, filePath); return; } @@ -196,97 +197,101 @@ class WebServer { } self.#serveFile(res, filePath, fileSize); } + } + + async #serveDirectoryIndex(response, pathPart, queryPart, directory) { + response.setHeader("Content-Type", "text/html"); + response.writeHead(200); + + if (queryPart === "frame") { + response.end( + ` + + + + + `, + "utf8" + ); + return; + } + + let files; + try { + files = await fsPromises.readdir(directory); + } catch { + response.end(); + return; + } - function escapeHTML(untrusted) { + response.write( + ` + + + + +

Index of ${pathPart}

` + ); + if (pathPart !== "/") { + response.write('..
'); + } + + const all = queryPart === "all"; + const escapeHTML = untrusted => // Escape untrusted input so that it can safely be used in a HTML response // in HTML and in HTML attributes. - return untrusted + untrusted .replaceAll("&", "&") .replaceAll("<", "<") .replaceAll(">", ">") .replaceAll('"', """) .replaceAll("'", "'"); - } - function serveDirectoryIndex(dir) { - res.setHeader("Content-Type", "text/html"); - res.writeHead(200); - - if (queryPart === "frame") { - res.end( - "" + - '', - "utf8" - ); - return; + for (const file of files) { + let stat; + const item = pathPart + file; + let href = ""; + let label = ""; + let extraAttributes = ""; + + try { + stat = fs.statSync(path.join(directory, file)); + } catch (ex) { + href = encodeURI(item); + label = `${file} (${ex})`; + extraAttributes = ' style="color:red"'; } - var all = queryPart === "all"; - fs.readdir(dir, function (err, files) { - if (err) { - res.end(); - return; + + if (stat) { + if (stat.isDirectory()) { + href = encodeURI(item); + label = file; + } else if (path.extname(file).toLowerCase() === ".pdf") { + href = `/web/viewer.html?file=${encodeURIComponent(item)}`; + label = file; + extraAttributes = ' target="pdf"'; + } else if (all) { + href = encodeURI(item); + label = file; } - res.write( - '' + - "

PDFs of " + - pathPart + - "

\n" + } + + if (label) { + response.write( + `${escapeHTML(label)}
` ); - if (pathPart !== "/") { - res.write('..
\n'); - } - files.forEach(function (file) { - var stat; - var item = pathPart + file; - var href = ""; - var label = ""; - var extraAttributes = ""; - try { - stat = fs.statSync(path.join(dir, file)); - } catch (e) { - href = encodeURI(item); - label = file + " (" + e + ")"; - extraAttributes = ' style="color:red"'; - } - if (stat) { - if (stat.isDirectory()) { - href = encodeURI(item); - label = file; - } else if (path.extname(file).toLowerCase() === ".pdf") { - href = "/web/viewer.html?file=" + encodeURIComponent(item); - label = file; - extraAttributes = ' target="pdf"'; - } else if (all) { - href = encodeURI(item); - label = file; - } - } - if (label) { - res.write( - '" + - escapeHTML(label) + - "
\n" - ); - } - }); - if (files.length === 0) { - res.write("

no files found

\n"); - } - if (!all && queryPart !== "side") { - res.write( - "

(only PDF files are shown, " + - 'show all)

\n' - ); - } - res.end(""); - }); + } + } + + if (files.length === 0) { + response.write("

No files found

"); + } + if (!all && queryPart !== "side") { + response.write( + '

(only PDF files are shown, show all)

' + ); } + response.end(""); } #serveFile(response, filePath, fileSize) {