forked from svrjs/svrjs
Change the order of static file serving.
This commit is contained in:
parent
86234d4795
commit
8978515e49
1 changed files with 226 additions and 232 deletions
458
svr.js
458
svr.js
|
@ -3571,241 +3571,10 @@ if (!cluster.isPrimary) {
|
|||
}
|
||||
|
||||
function properDirectoryListingAndStaticFileServe() {
|
||||
if (stats.isDirectory()) {
|
||||
// Check if directory listing is enabled in the configuration
|
||||
if (checkForEnabledDirectoryListing(req.headers.host, req.socket ? req.socket.localAddress : undefined)) {
|
||||
var customHeaders = getCustomHeaders();
|
||||
customHeaders["Content-Type"] = "text/html; charset=utf-8";
|
||||
res.writeHead(200, http.STATUS_CODES[200], customHeaders);
|
||||
|
||||
// Read custom header and footer content (if available)
|
||||
var customDirListingHeader = fs.existsSync(("." + decodeURIComponent(href) + "/.dirhead").replace(/\/+/g, "/")) ?
|
||||
fs.readFileSync(("." + decodeURIComponent(href) + "/.dirhead").replace(/\/+/g, "/")).toString() :
|
||||
(fs.existsSync(("." + decodeURIComponent(href) + "/HEAD.html").replace(/\/+/g, "/")) && (os.platform != "win32" || href != "/")) ?
|
||||
fs.readFileSync(("." + decodeURIComponent(href) + "/HEAD.html").replace(/\/+/g, "/")).toString() :
|
||||
"";
|
||||
var customDirListingFooter = fs.existsSync(("." + decodeURIComponent(href) + "/.dirfoot").replace(/\/+/g, "/")) ?
|
||||
fs.readFileSync(("." + decodeURIComponent(href) + "/.dirfoot").replace(/\/+/g, "/")).toString() :
|
||||
(fs.existsSync(("." + decodeURIComponent(href) + "/FOOT.html").replace(/\/+/g, "/")) && (os.platform != "win32" || href != "/")) ?
|
||||
fs.readFileSync(("." + decodeURIComponent(href) + "/FOOT.html").replace(/\/+/g, "/")).toString() :
|
||||
"";
|
||||
|
||||
// Check if custom header has HTML tag
|
||||
var headerHasHTMLTag = customDirListingHeader.replace(/<!--(?:(?:(?!--\>)[\s\S])*|)(?:-->|$)/g, "").match(/<html(?![a-zA-Z0-9])(?:"(?:\\(?:[\s\S]|$)|[^\\"])*(?:"|$)|'(?:\\(?:[\s\S]|$)|[^\\'])*(?:'|$)|[^'">])*(?:>|$)/i);
|
||||
|
||||
// Generate HTML head and footer based on configuration and custom content
|
||||
var htmlHead = (!configJSON.enableDirectoryListingWithDefaultHead || head == "" ?
|
||||
(!headerHasHTMLTag ?
|
||||
"<!DOCTYPE html><html><head><title>Directory: " + decodeURIComponent(origHref).replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">") + "</title><meta charset=\"UTF-8\" /><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" /></head><body>" :
|
||||
customDirListingHeader.replace(/<head>/i, "<head><title>Directory: " + decodeURIComponent(origHref).replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">") + "</title>")) :
|
||||
head.replace(/<head>/i, "<head><title>Directory: " + decodeURIComponent(origHref).replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">") + "</title>")) +
|
||||
(!headerHasHTMLTag ? customDirListingHeader : "") +
|
||||
"<h1>Directory: " + decodeURIComponent(origHref).replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">") + "</h1><table id=\"directoryListing\"> <tr> <th></th> <th>Filename</th> <th>Size</th> <th>Date</th> </tr>" + (checkPathLevel(decodeURIComponent(origHref)) < 1 ? "" : "<tr><td style=\"width: 24px;\"><img src=\"/.dirimages/return.png\" width=\"24px\" height=\"24px\" alt=\"[RET]\" /></td><td style=\"word-wrap: break-word; word-break: break-word; overflow-wrap: break-word;\"><a href=\"" + (origHref).replace(/\/+/g, "/").replace(/\/[^\/]*\/?$/, "/") + "\">Return</a></td><td></td><td></td></tr>");
|
||||
|
||||
var htmlFoot = "</table><p><i>" + (exposeServerVersion ? "SVR.JS/" + version + " (" + getOS() + "; " + (process.isBun ? ("Bun/v" + process.versions.bun + "; like Node.JS/" + process.version) : ("Node.JS/" + process.version)) + ")" : "SVR.JS").replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">") + (req.headers.host == undefined ? "" : " on " + String(req.headers.host).replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">")) + "</i></p>" + customDirListingFooter + (!configJSON.enableDirectoryListingWithDefaultHead || foot == "" ? "</body></html>" : foot);
|
||||
|
||||
if (fs.existsSync("." + decodeURIComponent(href) + "/.maindesc".replace(/\/+/g, "/"))) {
|
||||
htmlFoot = "</table><hr/>" + fs.readFileSync("." + decodeURIComponent(href) + "/.maindesc".replace(/\/+/g, "/")) + htmlFoot;
|
||||
}
|
||||
|
||||
fs.readdir("." + decodeURIComponent(href), function (err, list) {
|
||||
try {
|
||||
if (err) throw err;
|
||||
list = list.sort();
|
||||
|
||||
// Function to get stats for all files in the directory
|
||||
function getStatsForAllFilesI(fileList, callback, prefix, pushArray, index) {
|
||||
if (fileList.length == 0) {
|
||||
callback(pushArray);
|
||||
return;
|
||||
}
|
||||
|
||||
fs.stat((prefix + "/" + fileList[index]).replace(/\/+/g, "/"), function (err, stats) {
|
||||
if (err) {
|
||||
fs.lstat((prefix + "/" + fileList[index]).replace(/\/+/g, "/"), function (err, stats) {
|
||||
if (err) {
|
||||
pushArray.push({
|
||||
name: fileList[index],
|
||||
stats: null,
|
||||
errored: true
|
||||
});
|
||||
if (index < fileList.length - 1) {
|
||||
getStatsForAllFilesI(fileList, callback, prefix, pushArray, index + 1);
|
||||
} else {
|
||||
callback(pushArray);
|
||||
}
|
||||
} else {
|
||||
pushArray.push({
|
||||
name: fileList[index],
|
||||
stats: stats,
|
||||
errored: true
|
||||
});
|
||||
if (index < fileList.length - 1) {
|
||||
getStatsForAllFilesI(fileList, callback, prefix, pushArray, index + 1);
|
||||
} else {
|
||||
callback(pushArray);
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
pushArray.push({
|
||||
name: fileList[index],
|
||||
stats: stats,
|
||||
errored: false
|
||||
});
|
||||
if (index < fileList.length - 1) {
|
||||
getStatsForAllFilesI(fileList, callback, prefix, pushArray, index + 1);
|
||||
} else {
|
||||
callback(pushArray);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Wrapper function to get stats for all files
|
||||
function getStatsForAllFiles(fileList, prefix, callback) {
|
||||
if (!prefix) prefix = "";
|
||||
getStatsForAllFilesI(fileList, callback, prefix, [], 0);
|
||||
}
|
||||
|
||||
// Get stats for all files in the directory and generate the listing
|
||||
getStatsForAllFiles(list, "." + decodeURIComponent(href), function (filelist) {
|
||||
var directoryListingRows = [];
|
||||
for (var i = 0; i < filelist.length; i++) {
|
||||
if (filelist[i].name[0] !== ".") {
|
||||
var estats = filelist[i].stats;
|
||||
var ename = filelist[i].name;
|
||||
var eext = ename.match(/\.([^.]+)$/);
|
||||
if (eext) eext = eext[1];
|
||||
else eext = "";
|
||||
var emime = eext ? mime.contentType(eext) : false;
|
||||
if (filelist[i].errored) {
|
||||
directoryListingRows.push(
|
||||
"<tr><td style=\"width: 24px;\"><img src=\"/.dirimages/bad.png\" alt=\"[BAD]\" width=\"24px\" height=\"24px\" /></td><td style=\"word-wrap: break-word; word-break: break-word; overflow-wrap: break-word;\"><a href=\"" +
|
||||
(href + "/" + encodeURI(ename)).replace(/\/+/g, "/") +
|
||||
"\">" +
|
||||
ename.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">") +
|
||||
"</a></td><td>-</td><td>" +
|
||||
(estats ? estats.mtime.toDateString() : "-") +
|
||||
"</td></tr>\r\n"
|
||||
);
|
||||
} else {
|
||||
var entry = "<tr><td style=\"width: 24px;\"><img src=\"[img]\" alt=\"[alt]\" width=\"24px\" height=\"24px\" /></td><td style=\"word-wrap: break-word; word-break: break-word; overflow-wrap: break-word;\"><a href=\"" +
|
||||
(origHref + "/" + encodeURIComponent(ename)).replace(/\/+/g, "/") +
|
||||
(estats.isDirectory() ? "/" : "") +
|
||||
"\">" +
|
||||
ename.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">") +
|
||||
"</a></td><td>" +
|
||||
(estats.isDirectory() ? "-" : sizify(estats.size.toString())) +
|
||||
"</td><td>" +
|
||||
estats.mtime.toDateString() +
|
||||
"</td></tr>\r\n";
|
||||
|
||||
// Determine the file type and set the appropriate image and alt text
|
||||
if (estats.isDirectory()) {
|
||||
entry = entry.replace("[img]", "/.dirimages/directory.png").replace("[alt]", "[DIR]");
|
||||
} else if (!estats.isFile()) {
|
||||
entry = "<tr><td style=\"width: 24px;\"><img src=\"[img]\" alt=\"[alt]\" width=\"24px\" height=\"24px\" /></td><td style=\"word-wrap: break-word; word-break: break-word; overflow-wrap: break-word;\"><a href=\"" +
|
||||
(origHref + "/" + encodeURIComponent(ename)).replace(/\/+/g, "/") +
|
||||
"\">" +
|
||||
ename.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">") +
|
||||
"</a></td><td>-</td><td>" +
|
||||
estats.mtime.toDateString() +
|
||||
"</td></tr>\r\n";
|
||||
|
||||
// Determine the special file types (block device, character device, etc.)
|
||||
if (estats.isBlockDevice()) {
|
||||
entry = entry.replace("[img]", "/.dirimages/hwdevice.png").replace("[alt]", "[BLK]");
|
||||
} else if (estats.isCharacterDevice()) {
|
||||
entry = entry.replace("[img]", "/.dirimages/hwdevice.png").replace("[alt]", "[CHR]");
|
||||
} else if (estats.isFIFO()) {
|
||||
entry = entry.replace("[img]", "/.dirimages/fifo.png").replace("[alt]", "[FIF]");
|
||||
} else if (estats.isSocket()) {
|
||||
entry = entry.replace("[img]", "/.dirimages/socket.png").replace("[alt]", "[SCK]");
|
||||
}
|
||||
} else if (ename.match(/README|LICEN[SC]E/i)) {
|
||||
entry = entry.replace("[img]", "/.dirimages/important.png").replace("[alt]", "[IMP]");
|
||||
} else if (eext.match(/^(?:[xs]?html?|xml)$/i)) {
|
||||
entry = entry.replace("[img]", "/.dirimages/html.png").replace("[alt]", (eext == "xml" ? "[XML]" : "[HTM]"));
|
||||
} else if (eext == "js") {
|
||||
entry = entry.replace("[img]", "/.dirimages/javascript.png").replace("[alt]", "[JS ]");
|
||||
} else if (eext == "php") {
|
||||
entry = entry.replace("[img]", "/.dirimages/php.png").replace("[alt]", "[PHP]");
|
||||
} else if (eext == "css") {
|
||||
entry = entry.replace("[img]", "/.dirimages/css.png").replace("[alt]", "[CSS]");
|
||||
} else if (emime && emime.split("/")[0] == "image") {
|
||||
entry = entry.replace("[img]", "/.dirimages/image.png").replace("[alt]", (eext == "ico" ? "[ICO]" : "[IMG]"));
|
||||
} else if (emime && emime.split("/")[0] == "font") {
|
||||
entry = entry.replace("[img]", "/.dirimages/font.png").replace("[alt]", "[FON]");
|
||||
} else if (emime && emime.split("/")[0] == "audio") {
|
||||
entry = entry.replace("[img]", "/.dirimages/audio.png").replace("[alt]", "[AUD]");
|
||||
} else if ((emime && emime.split("/")[0] == "text") || eext == "json") {
|
||||
entry = entry.replace("[img]", "/.dirimages/text.png").replace("[alt]", (eext == "json" ? "[JSO]" : "[TXT]"));
|
||||
} else if (emime && emime.split("/")[0] == "video") {
|
||||
entry = entry.replace("[img]", "/.dirimages/video.png").replace("[alt]", "[VID]");
|
||||
} else if (eext.match(/^(?:zip|rar|bz2|[gb7x]z|lzma|tar)$/i)) {
|
||||
entry = entry.replace("[img]", "/.dirimages/archive.png").replace("[alt]", "[ARC]");
|
||||
} else if (eext.match(/^(?:[id]mg|iso|flp)$/i)) {
|
||||
entry = entry.replace("[img]", "/.dirimages/diskimage.png").replace("[alt]", "[DSK]");
|
||||
} else {
|
||||
entry = entry.replace("[img]", "/.dirimages/other.png").replace("[alt]", "[OTH]");
|
||||
}
|
||||
directoryListingRows.push(entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Push the information about empty directory
|
||||
if (directoryListingRows.length == 0) {
|
||||
directoryListingRows.push("<tr><td></td><td>No files found</td><td></td><td></td></tr>");
|
||||
}
|
||||
|
||||
// Send the directory listing response
|
||||
res.end(htmlHead + directoryListingRows.join("") + htmlFoot);
|
||||
serverconsole.resmessage("Client successfully received content.");
|
||||
});
|
||||
|
||||
} catch (err) {
|
||||
if (err.code == "ENOENT") {
|
||||
callServerError(404);
|
||||
serverconsole.errmessage("Resource not found.");
|
||||
} else if (err.code == "ENOTDIR") {
|
||||
callServerError(404); // Assume that file doesn't exist.
|
||||
serverconsole.errmessage("Resource not found.");
|
||||
} else if (err.code == "EACCES") {
|
||||
callServerError(403);
|
||||
serverconsole.errmessage("Access denied.");
|
||||
} else if (err.code == "ENAMETOOLONG") {
|
||||
callServerError(414);
|
||||
} else if (err.code == "EMFILE") {
|
||||
callServerError(503);
|
||||
} else if (err.code == "ELOOP") {
|
||||
callServerError(508); // The symbolic link loop is detected during file system operations.
|
||||
serverconsole.errmessage("Symbolic link loop detected.");
|
||||
} else {
|
||||
callServerError(500, err);
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// Directory listing is disabled, call 403 Forbidden error
|
||||
callServerError(403);
|
||||
serverconsole.errmessage("Directory listing is disabled.");
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
if (stats.isFile()) {
|
||||
var acceptEncoding = req.headers["accept-encoding"];
|
||||
if (!acceptEncoding) acceptEncoding = "";
|
||||
|
||||
// Check if the requested file exists and handle errors
|
||||
// Check if the requested resource is a file
|
||||
if (!stats.isFile()) {
|
||||
callServerError(501);
|
||||
serverconsole.errmessage("SVR.JS doesn't support block devices, character devices, FIFOs nor sockets.");
|
||||
return;
|
||||
}
|
||||
|
||||
var filelen = stats.size;
|
||||
|
||||
// ETag code
|
||||
|
@ -4031,6 +3800,231 @@ if (!cluster.isPrimary) {
|
|||
callServerError(500, err);
|
||||
}
|
||||
}
|
||||
} else if (stats.isDirectory()) {
|
||||
// Check if directory listing is enabled in the configuration
|
||||
if (checkForEnabledDirectoryListing(req.headers.host, req.socket ? req.socket.localAddress : undefined)) {
|
||||
var customHeaders = getCustomHeaders();
|
||||
customHeaders["Content-Type"] = "text/html; charset=utf-8";
|
||||
res.writeHead(200, http.STATUS_CODES[200], customHeaders);
|
||||
|
||||
// Read custom header and footer content (if available)
|
||||
var customDirListingHeader = fs.existsSync(("." + decodeURIComponent(href) + "/.dirhead").replace(/\/+/g, "/")) ?
|
||||
fs.readFileSync(("." + decodeURIComponent(href) + "/.dirhead").replace(/\/+/g, "/")).toString() :
|
||||
(fs.existsSync(("." + decodeURIComponent(href) + "/HEAD.html").replace(/\/+/g, "/")) && (os.platform != "win32" || href != "/")) ?
|
||||
fs.readFileSync(("." + decodeURIComponent(href) + "/HEAD.html").replace(/\/+/g, "/")).toString() :
|
||||
"";
|
||||
var customDirListingFooter = fs.existsSync(("." + decodeURIComponent(href) + "/.dirfoot").replace(/\/+/g, "/")) ?
|
||||
fs.readFileSync(("." + decodeURIComponent(href) + "/.dirfoot").replace(/\/+/g, "/")).toString() :
|
||||
(fs.existsSync(("." + decodeURIComponent(href) + "/FOOT.html").replace(/\/+/g, "/")) && (os.platform != "win32" || href != "/")) ?
|
||||
fs.readFileSync(("." + decodeURIComponent(href) + "/FOOT.html").replace(/\/+/g, "/")).toString() :
|
||||
"";
|
||||
|
||||
// Check if custom header has HTML tag
|
||||
var headerHasHTMLTag = customDirListingHeader.replace(/<!--(?:(?:(?!--\>)[\s\S])*|)(?:-->|$)/g, "").match(/<html(?![a-zA-Z0-9])(?:"(?:\\(?:[\s\S]|$)|[^\\"])*(?:"|$)|'(?:\\(?:[\s\S]|$)|[^\\'])*(?:'|$)|[^'">])*(?:>|$)/i);
|
||||
|
||||
// Generate HTML head and footer based on configuration and custom content
|
||||
var htmlHead = (!configJSON.enableDirectoryListingWithDefaultHead || head == "" ?
|
||||
(!headerHasHTMLTag ?
|
||||
"<!DOCTYPE html><html><head><title>Directory: " + decodeURIComponent(origHref).replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">") + "</title><meta charset=\"UTF-8\" /><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" /></head><body>" :
|
||||
customDirListingHeader.replace(/<head>/i, "<head><title>Directory: " + decodeURIComponent(origHref).replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">") + "</title>")) :
|
||||
head.replace(/<head>/i, "<head><title>Directory: " + decodeURIComponent(origHref).replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">") + "</title>")) +
|
||||
(!headerHasHTMLTag ? customDirListingHeader : "") +
|
||||
"<h1>Directory: " + decodeURIComponent(origHref).replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">") + "</h1><table id=\"directoryListing\"> <tr> <th></th> <th>Filename</th> <th>Size</th> <th>Date</th> </tr>" + (checkPathLevel(decodeURIComponent(origHref)) < 1 ? "" : "<tr><td style=\"width: 24px;\"><img src=\"/.dirimages/return.png\" width=\"24px\" height=\"24px\" alt=\"[RET]\" /></td><td style=\"word-wrap: break-word; word-break: break-word; overflow-wrap: break-word;\"><a href=\"" + (origHref).replace(/\/+/g, "/").replace(/\/[^\/]*\/?$/, "/") + "\">Return</a></td><td></td><td></td></tr>");
|
||||
|
||||
var htmlFoot = "</table><p><i>" + (exposeServerVersion ? "SVR.JS/" + version + " (" + getOS() + "; " + (process.isBun ? ("Bun/v" + process.versions.bun + "; like Node.JS/" + process.version) : ("Node.JS/" + process.version)) + ")" : "SVR.JS").replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">") + (req.headers.host == undefined ? "" : " on " + String(req.headers.host).replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">")) + "</i></p>" + customDirListingFooter + (!configJSON.enableDirectoryListingWithDefaultHead || foot == "" ? "</body></html>" : foot);
|
||||
|
||||
if (fs.existsSync("." + decodeURIComponent(href) + "/.maindesc".replace(/\/+/g, "/"))) {
|
||||
htmlFoot = "</table><hr/>" + fs.readFileSync("." + decodeURIComponent(href) + "/.maindesc".replace(/\/+/g, "/")) + htmlFoot;
|
||||
}
|
||||
|
||||
fs.readdir("." + decodeURIComponent(href), function (err, list) {
|
||||
try {
|
||||
if (err) throw err;
|
||||
list = list.sort();
|
||||
|
||||
// Function to get stats for all files in the directory
|
||||
function getStatsForAllFilesI(fileList, callback, prefix, pushArray, index) {
|
||||
if (fileList.length == 0) {
|
||||
callback(pushArray);
|
||||
return;
|
||||
}
|
||||
|
||||
fs.stat((prefix + "/" + fileList[index]).replace(/\/+/g, "/"), function (err, stats) {
|
||||
if (err) {
|
||||
fs.lstat((prefix + "/" + fileList[index]).replace(/\/+/g, "/"), function (err, stats) {
|
||||
if (err) {
|
||||
pushArray.push({
|
||||
name: fileList[index],
|
||||
stats: null,
|
||||
errored: true
|
||||
});
|
||||
if (index < fileList.length - 1) {
|
||||
getStatsForAllFilesI(fileList, callback, prefix, pushArray, index + 1);
|
||||
} else {
|
||||
callback(pushArray);
|
||||
}
|
||||
} else {
|
||||
pushArray.push({
|
||||
name: fileList[index],
|
||||
stats: stats,
|
||||
errored: true
|
||||
});
|
||||
if (index < fileList.length - 1) {
|
||||
getStatsForAllFilesI(fileList, callback, prefix, pushArray, index + 1);
|
||||
} else {
|
||||
callback(pushArray);
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
pushArray.push({
|
||||
name: fileList[index],
|
||||
stats: stats,
|
||||
errored: false
|
||||
});
|
||||
if (index < fileList.length - 1) {
|
||||
getStatsForAllFilesI(fileList, callback, prefix, pushArray, index + 1);
|
||||
} else {
|
||||
callback(pushArray);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Wrapper function to get stats for all files
|
||||
function getStatsForAllFiles(fileList, prefix, callback) {
|
||||
if (!prefix) prefix = "";
|
||||
getStatsForAllFilesI(fileList, callback, prefix, [], 0);
|
||||
}
|
||||
|
||||
// Get stats for all files in the directory and generate the listing
|
||||
getStatsForAllFiles(list, "." + decodeURIComponent(href), function (filelist) {
|
||||
var directoryListingRows = [];
|
||||
for (var i = 0; i < filelist.length; i++) {
|
||||
if (filelist[i].name[0] !== ".") {
|
||||
var estats = filelist[i].stats;
|
||||
var ename = filelist[i].name;
|
||||
var eext = ename.match(/\.([^.]+)$/);
|
||||
if (eext) eext = eext[1];
|
||||
else eext = "";
|
||||
var emime = eext ? mime.contentType(eext) : false;
|
||||
if (filelist[i].errored) {
|
||||
directoryListingRows.push(
|
||||
"<tr><td style=\"width: 24px;\"><img src=\"/.dirimages/bad.png\" alt=\"[BAD]\" width=\"24px\" height=\"24px\" /></td><td style=\"word-wrap: break-word; word-break: break-word; overflow-wrap: break-word;\"><a href=\"" +
|
||||
(href + "/" + encodeURI(ename)).replace(/\/+/g, "/") +
|
||||
"\">" +
|
||||
ename.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">") +
|
||||
"</a></td><td>-</td><td>" +
|
||||
(estats ? estats.mtime.toDateString() : "-") +
|
||||
"</td></tr>\r\n"
|
||||
);
|
||||
} else {
|
||||
var entry = "<tr><td style=\"width: 24px;\"><img src=\"[img]\" alt=\"[alt]\" width=\"24px\" height=\"24px\" /></td><td style=\"word-wrap: break-word; word-break: break-word; overflow-wrap: break-word;\"><a href=\"" +
|
||||
(origHref + "/" + encodeURIComponent(ename)).replace(/\/+/g, "/") +
|
||||
(estats.isDirectory() ? "/" : "") +
|
||||
"\">" +
|
||||
ename.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">") +
|
||||
"</a></td><td>" +
|
||||
(estats.isDirectory() ? "-" : sizify(estats.size.toString())) +
|
||||
"</td><td>" +
|
||||
estats.mtime.toDateString() +
|
||||
"</td></tr>\r\n";
|
||||
|
||||
// Determine the file type and set the appropriate image and alt text
|
||||
if (estats.isDirectory()) {
|
||||
entry = entry.replace("[img]", "/.dirimages/directory.png").replace("[alt]", "[DIR]");
|
||||
} else if (!estats.isFile()) {
|
||||
entry = "<tr><td style=\"width: 24px;\"><img src=\"[img]\" alt=\"[alt]\" width=\"24px\" height=\"24px\" /></td><td style=\"word-wrap: break-word; word-break: break-word; overflow-wrap: break-word;\"><a href=\"" +
|
||||
(origHref + "/" + encodeURIComponent(ename)).replace(/\/+/g, "/") +
|
||||
"\">" +
|
||||
ename.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">") +
|
||||
"</a></td><td>-</td><td>" +
|
||||
estats.mtime.toDateString() +
|
||||
"</td></tr>\r\n";
|
||||
|
||||
// Determine the special file types (block device, character device, etc.)
|
||||
if (estats.isBlockDevice()) {
|
||||
entry = entry.replace("[img]", "/.dirimages/hwdevice.png").replace("[alt]", "[BLK]");
|
||||
} else if (estats.isCharacterDevice()) {
|
||||
entry = entry.replace("[img]", "/.dirimages/hwdevice.png").replace("[alt]", "[CHR]");
|
||||
} else if (estats.isFIFO()) {
|
||||
entry = entry.replace("[img]", "/.dirimages/fifo.png").replace("[alt]", "[FIF]");
|
||||
} else if (estats.isSocket()) {
|
||||
entry = entry.replace("[img]", "/.dirimages/socket.png").replace("[alt]", "[SCK]");
|
||||
}
|
||||
} else if (ename.match(/README|LICEN[SC]E/i)) {
|
||||
entry = entry.replace("[img]", "/.dirimages/important.png").replace("[alt]", "[IMP]");
|
||||
} else if (eext.match(/^(?:[xs]?html?|xml)$/i)) {
|
||||
entry = entry.replace("[img]", "/.dirimages/html.png").replace("[alt]", (eext == "xml" ? "[XML]" : "[HTM]"));
|
||||
} else if (eext == "js") {
|
||||
entry = entry.replace("[img]", "/.dirimages/javascript.png").replace("[alt]", "[JS ]");
|
||||
} else if (eext == "php") {
|
||||
entry = entry.replace("[img]", "/.dirimages/php.png").replace("[alt]", "[PHP]");
|
||||
} else if (eext == "css") {
|
||||
entry = entry.replace("[img]", "/.dirimages/css.png").replace("[alt]", "[CSS]");
|
||||
} else if (emime && emime.split("/")[0] == "image") {
|
||||
entry = entry.replace("[img]", "/.dirimages/image.png").replace("[alt]", (eext == "ico" ? "[ICO]" : "[IMG]"));
|
||||
} else if (emime && emime.split("/")[0] == "font") {
|
||||
entry = entry.replace("[img]", "/.dirimages/font.png").replace("[alt]", "[FON]");
|
||||
} else if (emime && emime.split("/")[0] == "audio") {
|
||||
entry = entry.replace("[img]", "/.dirimages/audio.png").replace("[alt]", "[AUD]");
|
||||
} else if ((emime && emime.split("/")[0] == "text") || eext == "json") {
|
||||
entry = entry.replace("[img]", "/.dirimages/text.png").replace("[alt]", (eext == "json" ? "[JSO]" : "[TXT]"));
|
||||
} else if (emime && emime.split("/")[0] == "video") {
|
||||
entry = entry.replace("[img]", "/.dirimages/video.png").replace("[alt]", "[VID]");
|
||||
} else if (eext.match(/^(?:zip|rar|bz2|[gb7x]z|lzma|tar)$/i)) {
|
||||
entry = entry.replace("[img]", "/.dirimages/archive.png").replace("[alt]", "[ARC]");
|
||||
} else if (eext.match(/^(?:[id]mg|iso|flp)$/i)) {
|
||||
entry = entry.replace("[img]", "/.dirimages/diskimage.png").replace("[alt]", "[DSK]");
|
||||
} else {
|
||||
entry = entry.replace("[img]", "/.dirimages/other.png").replace("[alt]", "[OTH]");
|
||||
}
|
||||
directoryListingRows.push(entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Push the information about empty directory
|
||||
if (directoryListingRows.length == 0) {
|
||||
directoryListingRows.push("<tr><td></td><td>No files found</td><td></td><td></td></tr>");
|
||||
}
|
||||
|
||||
// Send the directory listing response
|
||||
res.end(htmlHead + directoryListingRows.join("") + htmlFoot);
|
||||
serverconsole.resmessage("Client successfully received content.");
|
||||
});
|
||||
|
||||
} catch (err) {
|
||||
if (err.code == "ENOENT") {
|
||||
callServerError(404);
|
||||
serverconsole.errmessage("Resource not found.");
|
||||
} else if (err.code == "ENOTDIR") {
|
||||
callServerError(404); // Assume that file doesn't exist.
|
||||
serverconsole.errmessage("Resource not found.");
|
||||
} else if (err.code == "EACCES") {
|
||||
callServerError(403);
|
||||
serverconsole.errmessage("Access denied.");
|
||||
} else if (err.code == "ENAMETOOLONG") {
|
||||
callServerError(414);
|
||||
} else if (err.code == "EMFILE") {
|
||||
callServerError(503);
|
||||
} else if (err.code == "ELOOP") {
|
||||
callServerError(508); // The symbolic link loop is detected during file system operations.
|
||||
serverconsole.errmessage("Symbolic link loop detected.");
|
||||
} else {
|
||||
callServerError(500, err);
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// Directory listing is disabled, call 403 Forbidden error
|
||||
callServerError(403);
|
||||
serverconsole.errmessage("Directory listing is disabled.");
|
||||
}
|
||||
} else {
|
||||
callServerError(501);
|
||||
serverconsole.errmessage("SVR.JS doesn't support block devices, character devices, FIFOs nor sockets.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
Reference in a new issue