diff --git a/test/webserver.mjs b/test/webserver.mjs
index 57c913d66..f920165cf 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);
}
+ }
- function escapeHTML(untrusted) {
+ 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;
+ }
+
+ 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);
+ for (const file of files) {
+ let stat;
+ const item = pathPart + file;
+ let href = "";
+ let label = "";
+ let extraAttributes = "";
- if (queryPart === "frame") {
- res.end(
- "',
- "utf8"
- );
- return;
+ 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) {