1
0
Fork 0
forked from svrjs/svrjs

Clean up the code.

This commit is contained in:
Dorian Niemiec 2024-02-02 19:32:40 +01:00
parent 88e923ffbc
commit d85dedea65

80
svr.js
View file

@ -872,8 +872,8 @@ function generateErrorStack(errorObject) {
// If the error stack starts with the error name, return the original stack (it is V8-style then). // If the error stack starts with the error name, return the original stack (it is V8-style then).
if (errorStack.some(function (errorStackLine) { if (errorStack.some(function (errorStackLine) {
return (errorStackLine.indexOf(errorObject.name) == 0); return (errorStackLine.indexOf(errorObject.name) == 0);
})) { })) {
return errorObject.stack; return errorObject.stack;
} }
@ -1355,7 +1355,7 @@ if (secure) {
var sniNames = Object.keys(sni); var sniNames = Object.keys(sni);
var sniCredentials = []; var sniCredentials = [];
sniNames.forEach(function (sniName) { sniNames.forEach(function (sniName) {
if(typeof sniName === "string" && sniName.match(/\*[^*.:]*\*[^*.:]*(?:\.|:|$)/)) { if (typeof sniName === "string" && sniName.match(/\*[^*.:]*\*[^*.:]*(?:\.|:|$)/)) {
sniReDos = true; sniReDos = true;
} }
sniCredentials.push({ sniCredentials.push({
@ -1384,7 +1384,7 @@ function LOG(s) {
flags: "a", flags: "a",
autoClose: false autoClose: false
}); });
logFile.on("error", function(err) { logFile.on("error", function (err) {
if (!s.match(/^SERVER WARNING MESSAGE(?: \[Request Id: [0-9a-f]{6}\])?: There was a problem while saving logs! Logs will not be kept in log file\. Reason: /) && !reallyExiting) serverconsole.locwarnmessage("There was a problem while saving logs! Logs will not be kept in log file. Reason: " + err.message); if (!s.match(/^SERVER WARNING MESSAGE(?: \[Request Id: [0-9a-f]{6}\])?: There was a problem while saving logs! Logs will not be kept in log file\. Reason: /) && !reallyExiting) serverconsole.locwarnmessage("There was a problem while saving logs! Logs will not be kept in log file. Reason: " + err.message);
}); });
} }
@ -2196,9 +2196,9 @@ if (!cluster.isPrimary) {
}); });
try { try {
var snMatches = sniCredentialsSingle.name.match(/^([^:[]*|\[[^]]*\]?)((?::.*)?)$/); var snMatches = sniCredentialsSingle.name.match(/^([^:[]*|\[[^]]*\]?)((?::.*)?)$/);
if(!snMatches[1][0].match(/^\.+$/)) snMatches[1][0] = snMatches[1][0].replace(/\.+$/,""); if (!snMatches[1][0].match(/^\.+$/)) snMatches[1][0] = snMatches[1][0].replace(/\.+$/, "");
server._contexts[server._contexts.length-1][0] = new RegExp("^" + snMatches[1].replace(/([.^$+?\-\\[\]{}])/g, "\\$1").replace(/\*/g, "[^.:]*") + ((snMatches[1][0] == "[" || snMatches[1].match(/^(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])$/)) ? "" : "\.?") + snMatches[2].replace(/([.^$+?\-\\[\]{}])/g, "\\$1").replace(/\*/g, "[^.]*") + "$", "i"); server._contexts[server._contexts.length - 1][0] = new RegExp("^" + snMatches[1].replace(/([.^$+?\-\\[\]{}])/g, "\\$1").replace(/\*/g, "[^.:]*") + ((snMatches[1][0] == "[" || snMatches[1].match(/^(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])$/)) ? "" : "\.?") + snMatches[2].replace(/([.^$+?\-\\[\]{}])/g, "\\$1").replace(/\*/g, "[^.]*") + "$", "i");
} catch(ex) { } catch (ex) {
// Can't replace regex, ignoring... // Can't replace regex, ignoring...
} }
}); });
@ -2304,8 +2304,8 @@ if (!cluster.isPrimary) {
}); });
}; };
res.writeHead = function (code, name, headers) { res.writeHead = function (code, name, headers) {
if(code >= 400 && code <= 499) err4xxcounter++; if (code >= 400 && code <= 499) err4xxcounter++;
if(code >= 500 && code <= 599) err5xxcounter++; if (code >= 500 && code <= 599) err5xxcounter++;
var head = ("HTTP/1.1 " + code.toString() + " " + name + "\r\n"); var head = ("HTTP/1.1 " + code.toString() + " " + name + "\r\n");
var headers = JSON.parse(JSON.stringify(headers)); var headers = JSON.parse(JSON.stringify(headers));
headers["Date"] = (new Date()).toGMTString(); headers["Date"] = (new Date()).toGMTString();
@ -3053,7 +3053,7 @@ if (!cluster.isPrimary) {
var oldHostHeader = req.headers.host; var oldHostHeader = req.headers.host;
if (typeof req.headers.host == "string") { if (typeof req.headers.host == "string") {
req.headers.host = req.headers.host.toLowerCase(); req.headers.host = req.headers.host.toLowerCase();
if(!req.headers.host.match(/^\.+$/)) req.headers.host = req.headers.host.replace(/\.$/g,""); if (!req.headers.host.match(/^\.+$/)) req.headers.host = req.headers.host.replace(/\.$/g, "");
} }
if (!isProxy) serverconsole.reqmessage("Client " + ((!reqip || reqip == "") ? "[unknown client]" : (reqip + ((reqport && reqport !== 0) && reqport != "" ? ":" + reqport : ""))) + " wants " + (req.method == "GET" ? "content in " : (req.method == "POST" ? "to post content in " : (req.method == "PUT" ? "to add content in " : (req.method == "DELETE" ? "to delete content in " : (req.method == "PATCH" ? "to patch content in " : "to access content using " + req.method + " method in "))))) + (req.headers.host == undefined ? "" : req.headers.host) + req.url); if (!isProxy) serverconsole.reqmessage("Client " + ((!reqip || reqip == "") ? "[unknown client]" : (reqip + ((reqport && reqport !== 0) && reqport != "" ? ":" + reqport : ""))) + " wants " + (req.method == "GET" ? "content in " : (req.method == "POST" ? "to post content in " : (req.method == "PUT" ? "to add content in " : (req.method == "DELETE" ? "to delete content in " : (req.method == "PATCH" ? "to patch content in " : "to access content using " + req.method + " method in "))))) + (req.headers.host == undefined ? "" : req.headers.host) + req.url);
@ -3494,8 +3494,8 @@ if (!cluster.isPrimary) {
statusBody += "Server errors (5xx): " + err5xxcounter + "<br/>"; statusBody += "Server errors (5xx): " + err5xxcounter + "<br/>";
statusBody += "Average error rate: " + (Math.round(((err4xxcounter + err5xxcounter) / reqcounter) * 10000) / 100) + "%<br/>"; statusBody += "Average error rate: " + (Math.round(((err4xxcounter + err5xxcounter) / reqcounter) * 10000) / 100) + "%<br/>";
statusBody += "Malformed HTTP requests: " + malformedcounter; statusBody += "Malformed HTTP requests: " + malformedcounter;
if(process.memoryUsage) statusBody += "<br/>Memory usage of thread: " + sizify(process.memoryUsage().rss, true) + "B"; if (process.memoryUsage) statusBody += "<br/>Memory usage of thread: " + sizify(process.memoryUsage().rss, true) + "B";
if(process.cpuUsage) statusBody += "<br/>Total CPU usage by thread: u" + (process.cpuUsage().user / 1000) + "ms s" + (process.cpuUsage().system / 1000) + "ms - " + (Math.round((((process.cpuUsage().user + process.cpuUsage().system) / 1000000) / process.uptime()) * 1000) / 1000) + "%"; if (process.cpuUsage) statusBody += "<br/>Total CPU usage by thread: u" + (process.cpuUsage().user / 1000) + "ms s" + (process.cpuUsage().system / 1000) + "ms - " + (Math.round((((process.cpuUsage().user + process.cpuUsage().system) / 1000000) / process.uptime()) * 1000) / 1000) + "%";
statusBody += "<br/>Thread PID: " + process.pid + "<br/>"; statusBody += "<br/>Thread PID: " + process.pid + "<br/>";
var hdhds = getCustomHeaders(); var hdhds = getCustomHeaders();
@ -3603,23 +3603,23 @@ if (!cluster.isPrimary) {
var customDirListingHeader = fs.existsSync(("." + decodeURIComponent(href) + "/.dirhead").replace(/\/+/g, "/")) ? var customDirListingHeader = fs.existsSync(("." + decodeURIComponent(href) + "/.dirhead").replace(/\/+/g, "/")) ?
fs.readFileSync(("." + decodeURIComponent(href) + "/.dirhead").replace(/\/+/g, "/")).toString() : fs.readFileSync(("." + decodeURIComponent(href) + "/.dirhead").replace(/\/+/g, "/")).toString() :
(fs.existsSync(("." + decodeURIComponent(href) + "/HEAD.html").replace(/\/+/g, "/")) && (os.platform != "win32" || href != "/")) ? (fs.existsSync(("." + decodeURIComponent(href) + "/HEAD.html").replace(/\/+/g, "/")) && (os.platform != "win32" || href != "/")) ?
fs.readFileSync(("." + decodeURIComponent(href) + "/HEAD.html").replace(/\/+/g, "/")).toString() : fs.readFileSync(("." + decodeURIComponent(href) + "/HEAD.html").replace(/\/+/g, "/")).toString() :
""; "";
var customDirListingFooter = fs.existsSync(("." + decodeURIComponent(href) + "/.dirfoot").replace(/\/+/g, "/")) ? var customDirListingFooter = fs.existsSync(("." + decodeURIComponent(href) + "/.dirfoot").replace(/\/+/g, "/")) ?
fs.readFileSync(("." + decodeURIComponent(href) + "/.dirfoot").replace(/\/+/g, "/")).toString() : fs.readFileSync(("." + decodeURIComponent(href) + "/.dirfoot").replace(/\/+/g, "/")).toString() :
(fs.existsSync(("." + decodeURIComponent(href) + "/FOOT.html").replace(/\/+/g, "/")) && (os.platform != "win32" || href != "/")) ? (fs.existsSync(("." + decodeURIComponent(href) + "/FOOT.html").replace(/\/+/g, "/")) && (os.platform != "win32" || href != "/")) ?
fs.readFileSync(("." + decodeURIComponent(href) + "/FOOT.html").replace(/\/+/g, "/")).toString() : fs.readFileSync(("." + decodeURIComponent(href) + "/FOOT.html").replace(/\/+/g, "/")).toString() :
""; "";
// Check if custom header has HTML tag // 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); 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 // Generate HTML head and footer based on configuration and custom content
var htmlHead = (!configJSON.enableDirectoryListingWithDefaultHead || head == "" ? var htmlHead = (!configJSON.enableDirectoryListingWithDefaultHead || head == "" ?
(!headerHasHTMLTag ? (!headerHasHTMLTag ?
"<!DOCTYPE html><html><head><title>Directory: " + decodeURIComponent(origHref).replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;") + "</title><meta charset=\"UTF-8\" /><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" /></head><body>" : "<!DOCTYPE html><html><head><title>Directory: " + decodeURIComponent(origHref).replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;") + "</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, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;") + "</title>")) : customDirListingHeader.replace(/<head>/i, "<head><title>Directory: " + decodeURIComponent(origHref).replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;") + "</title>")) :
head.replace(/<head>/i, "<head><title>Directory: " + decodeURIComponent(origHref).replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;") + "</title>")) + head.replace(/<head>/i, "<head><title>Directory: " + decodeURIComponent(origHref).replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;") + "</title>")) +
(!headerHasHTMLTag ? customDirListingHeader : "") + (!headerHasHTMLTag ? customDirListingHeader : "") +
"<h1>Directory: " + decodeURIComponent(origHref).replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;") + "</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>"); "<h1>Directory: " + decodeURIComponent(origHref).replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;") + "</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>");
@ -4281,14 +4281,14 @@ if (!cluster.isPrimary) {
if (!isProxy) { if (!isProxy) {
for (var i = (_mapBegIndex ? _mapBegIndex : 0); i < map.length; i++) { for (var i = (_mapBegIndex ? _mapBegIndex : 0); i < map.length; i++) {
var mapEntry = map[i]; var mapEntry = map[i];
if(href != "/" && (mapEntry.isNotDirectory || mapEntry.isNotFile) && !_fileState) { if (href != "/" && (mapEntry.isNotDirectory || mapEntry.isNotFile) && !_fileState) {
fs.stat("." + decodeURIComponent(href), function(err, stats) { fs.stat("." + decodeURIComponent(href), function (err, stats) {
var _fileState = 3; var _fileState = 3;
if(err) { if (err) {
_fileState = 3; _fileState = 3;
} else if(stats.isDirectory()) { } else if (stats.isDirectory()) {
_fileState = 2; _fileState = 2;
} else if(stats.isFile()) { } else if (stats.isFile()) {
_fileState = 1; _fileState = 1;
} else { } else {
_fileState = 3; _fileState = 3;
@ -4312,7 +4312,7 @@ if (!cluster.isPrimary) {
} }
} }
} }
if(doCallback) callback(null, rewrittenURL); if (doCallback) callback(null, rewrittenURL);
} }
// Trailing slash redirection // Trailing slash redirection
@ -4347,12 +4347,12 @@ if (!cluster.isPrimary) {
var origHref = href; var origHref = href;
// Add web root postfixes // Add web root postfixes
if(!isProxy) { if (!isProxy) {
var urlWithPostfix = req.url; var urlWithPostfix = req.url;
var postfixPrefix = ""; var postfixPrefix = "";
wwwrootPostfixPrefixesVHost.every(function (currentPostfixPrefix) { wwwrootPostfixPrefixesVHost.every(function (currentPostfixPrefix) {
if (req.url.indexOf(currentPostfixPrefix) == 0) { if (req.url.indexOf(currentPostfixPrefix) == 0) {
if (currentPostfixPrefix.match(/\/+$/)) postfixPrefix = currentPostfixPrefix.replace(/\/+$/,""); if (currentPostfixPrefix.match(/\/+$/)) postfixPrefix = currentPostfixPrefix.replace(/\/+$/, "");
else if (urlWithPostfix.length == currentPostfixPrefix.length || urlWithPostfix[currentPostfixPrefix.length] == "?" || urlWithPostfix[currentPostfixPrefix.length] == "/" || urlWithPostfix[currentPostfixPrefix.length] == "#") postfixPrefix = currentPostfixPrefix; else if (urlWithPostfix.length == currentPostfixPrefix.length || urlWithPostfix[currentPostfixPrefix.length] == "?" || urlWithPostfix[currentPostfixPrefix.length] == "/" || urlWithPostfix[currentPostfixPrefix.length] == "#") postfixPrefix = currentPostfixPrefix;
else return true; else return true;
urlWithPostfix = urlWithPostfix.substr(postfixPrefix.length); urlWithPostfix = urlWithPostfix.substr(postfixPrefix.length);
@ -4423,9 +4423,9 @@ if (!cluster.isPrimary) {
} }
} }
} }
// Rewrite URLs // Rewrite URLs
rewriteURL(req.url, rewriteMap, function(err, rewrittenURL) { rewriteURL(req.url, rewriteMap, function (err, rewrittenURL) {
if (err) { if (err) {
callServerError(500, undefined, err); callServerError(500, undefined, err);
return; return;
@ -4490,7 +4490,7 @@ if (!cluster.isPrimary) {
try { try {
res.setHeader(hkS, hkh[hkS]); res.setHeader(hkS, hkh[hkS]);
} catch (err) { } catch (err) {
// Headers will not be set. // Headers will not be set.
} }
}); });
} }
@ -4527,17 +4527,17 @@ if (!cluster.isPrimary) {
if (matchHostname(nonStandardCodes[i].host) && ipMatch(nonStandardCodes[i].ip, req.socket ? req.socket.localAddress : undefined)) { if (matchHostname(nonStandardCodes[i].host) && ipMatch(nonStandardCodes[i].ip, req.socket ? req.socket.localAddress : undefined)) {
var isMatch = false; var isMatch = false;
if (nonStandardCodes[i].regex) { if (nonStandardCodes[i].regex) {
// Regex match // Regex match
var createdRegex = createRegex(nonStandardCodes[i].regex, true); var createdRegex = createRegex(nonStandardCodes[i].regex, true);
isMatch = req.url.match(createdRegex) || href.match(createdRegex); isMatch = req.url.match(createdRegex) || href.match(createdRegex);
regexI[i] = createdRegex; regexI[i] = createdRegex;
} else { } else {
// Non-regex match // Non-regex match
isMatch = nonStandardCodes[i].url == href || (os.platform() == "win32" && nonStandardCodes[i].url.toLowerCase() == href.toLowerCase()); isMatch = nonStandardCodes[i].url == href || (os.platform() == "win32" && nonStandardCodes[i].url.toLowerCase() == href.toLowerCase());
} }
if (isMatch) { if (isMatch) {
if (nonStandardCodes[i].scode == 401) { if (nonStandardCodes[i].scode == 401) {
// HTTP authentication // HTTP authentication
if (authIndex == -1) { if (authIndex == -1) {
authIndex = i; authIndex = i;
} }
@ -4748,10 +4748,10 @@ if (!cluster.isPrimary) {
} }
} }
if (authcode.disableBruteProtection) { if (authcode.disableBruteProtection) {
// Don't brute-force protect it, just do HTTP authentication // Don't brute-force protect it, just do HTTP authentication
authorizedCallback(false); authorizedCallback(false);
} else if (!process.send) { } else if (!process.send) {
// Query data from JS object database // Query data from JS object database
if (!bruteForceDb[reqip] || !bruteForceDb[reqip].lastAttemptDate || (new Date() - 300000 >= bruteForceDb[reqip].lastAttemptDate)) { if (!bruteForceDb[reqip] || !bruteForceDb[reqip].lastAttemptDate || (new Date() - 300000 >= bruteForceDb[reqip].lastAttemptDate)) {
if (bruteForceDb[reqip] && bruteForceDb[reqip].invalidAttempts >= 10) bruteForceDb[reqip] = { if (bruteForceDb[reqip] && bruteForceDb[reqip].invalidAttempts >= 10) bruteForceDb[reqip] = {
invalidAttempts: 5 invalidAttempts: 5
@ -5056,11 +5056,11 @@ function start(init) {
if (process.isBun) { if (process.isBun) {
serverconsole.locwarnmessage("Bun support is experimental. Some features of SVR.JS, SVR.JS mods and SVR.JS server-side JavaScript may not work as expected."); serverconsole.locwarnmessage("Bun support is experimental. Some features of SVR.JS, SVR.JS mods and SVR.JS server-side JavaScript may not work as expected.");
if (users.some(function (entry) { if (users.some(function (entry) {
return entry.pbkdf2; return entry.pbkdf2;
})) serverconsole.locwarnmessage("PBKDF2 password hashing function in Bun blocks the event loop, which may result in denial of service."); })) serverconsole.locwarnmessage("PBKDF2 password hashing function in Bun blocks the event loop, which may result in denial of service.");
if (users.some(function (entry) { if (users.some(function (entry) {
return entry.scrypt; return entry.scrypt;
})) serverconsole.locwarnmessage("scrypt password hashing function in Bun blocks the event loop, which may result in denial of service."); })) serverconsole.locwarnmessage("scrypt password hashing function in Bun blocks the event loop, which may result in denial of service.");
} }
if (cluster.isPrimary === undefined) serverconsole.locwarnmessage("You're running SVR.JS on single thread. Reliability may suffer, as the server is stopped after crash."); if (cluster.isPrimary === undefined) serverconsole.locwarnmessage("You're running SVR.JS on single thread. Reliability may suffer, as the server is stopped after crash.");
if (crypto.__disabled__ !== undefined) serverconsole.locwarnmessage("Your Node.JS version doesn't have crypto support! The 'crypto' module is essential for providing cryptographic functionality in Node.JS. Without crypto support, certain security features may be unavailable, and some functionality may not work as expected. It's recommended to use a Node.JS version that includes crypto support to ensure the security and proper functioning of your server."); if (crypto.__disabled__ !== undefined) serverconsole.locwarnmessage("Your Node.JS version doesn't have crypto support! The 'crypto' module is essential for providing cryptographic functionality in Node.JS. Without crypto support, certain security features may be unavailable, and some functionality may not work as expected. It's recommended to use a Node.JS version that includes crypto support to ensure the security and proper functioning of your server.");