diff --git a/test/webserver.js b/test/webserver.js index 9ea02d21b..ee5e80255 100644 --- a/test/webserver.js +++ b/test/webserver.js @@ -80,7 +80,7 @@ WebServer.prototype = { } }, _handler: function (req, res) { - var url = req.url; + var url = req.url.replace(/\/\//g, '/'); var urlParts = /([^?]*)((?:\?(.*))?)/.exec(url); var pathPart = decodeURI(urlParts[1]), queryPart = urlParts[3]; var verbose = this.verbose; @@ -172,6 +172,17 @@ WebServer.prototype = { serveRequestedFile(filePath); } + function escapeHTML(untrusted) { + // Escape untrusted input so that it can safely be used in a HTML response + // in HTML and in HTML attributes. + return untrusted + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"') + .replace(/'/g, '''); + } + function serveDirectoryIndex(dir) { res.setHeader('Content-Type', 'text/html'); res.writeHead(200); @@ -194,21 +205,34 @@ WebServer.prototype = { res.write('..
\n'); } files.forEach(function (file) { - var stat = fs.statSync(path.join(dir, file)); + var stat; var item = pathPart + file; - if (stat.isDirectory()) { - res.write('' + - file + '
\n'); - return; + 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"'; } - var ext = path.extname(file).toLowerCase(); - if (ext === '.pdf') { - res.write('' + - file + '
\n'); - } else if (all) { - res.write('' + - file + '
\n'); + 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) {