");
response.end();
}
} else {
var finished = false;
response.on("finish", function () {
if (!finished) {
finished = true;
serverconsole.locmessage("Client disconnected.");
}
});
response.on("close", function () {
if (!finished) {
finished = true;
serverconsole.locmessage("Client disconnected.");
}
});
var isProxy = false;
if (request.url.indexOf("/") != 0 && request.url != "*") isProxy = true;
serverconsole.locmessage("Somebody connected to " + (secure && fromMain ? ((typeof sport == "number" ? "port " : "socket ") + sport) : ((typeof port == "number" ? "port " : "socket ") + port)) + "...");
if (request.socket == null) {
serverconsole.errmessage("Client socket is null!!!");
return;
}
var reqport = "";
var reqip = "";
var oldport = "";
var oldip = "";
if (request.headers["x-svr-js-client"] != undefined && enableIPSpoofing) {
var kl = request.headers["x-svr-js-client"].split(":");
reqport = kl.pop();
reqip = kl.join(":");
try {
oldport = request.socket.remotePort;
oldip = request.socket.remoteAddress;
request.socket.realRemotePort = reqport;
request.socket.realRemoteAddress = reqip;
request.socket.originalRemotePort = oldport;
request.socket.originalRemoteAddress = oldip;
response.socket.realRemotePort = reqport;
response.socket.realRemoteAddress = reqip;
response.socket.originalRemotePort = oldport;
response.socket.originalRemoteAddress = oldip;
} catch (ex) {
//Address setting failed
}
} else if (request.headers["x-forwarded-for"] != undefined && enableIPSpoofing) {
reqport = null;
reqip = request.headers["x-forwarded-for"].split(",")[0].replace(/ /g, "");
if (reqip.indexOf(":") == -1) reqip = "::ffff:" + reqip;
try {
oldport = request.socket.remotePort;
oldip = request.socket.remoteAddress;
request.socket.realRemotePort = reqport;
request.socket.realRemoteAddress = reqip;
request.socket.originalRemotePort = oldport;
request.socket.originalRemoteAddress = oldip;
response.socket.realRemotePort = reqport;
response.socket.realRemoteAddress = reqip;
response.socket.originalRemotePort = oldport;
response.socket.originalRemoteAddress = oldip;
} catch (ex) {
//Address setting failed
}
} else {
reqip = request.socket.remoteAddress;
reqport = request.socket.remotePort;
}
if (!isProxy) serverconsole.reqmessage("Client " + ((!reqip || reqip == "") ? "[unknown client]" : (reqip + ((reqport && reqport !== 0) && reqport != "" ? ":" + reqport : ""))) + " wants " + (request.method == "GET" ? "content in " : (request.method == "POST" ? "to post content in " : (request.method == "PUT" ? "to add content in " : (request.method == "DELETE" ? "to delete content in " : (request.method == "PATCH" ? "to patch content in " : "to access content using " + request.method + " method in "))))) + (request.headers.host == undefined ? "" : request.headers.host) + request.url);
else serverconsole.reqmessage("Client " + ((!reqip || reqip == "") ? "[unknown client]" : (reqip + ((reqport && reqport !== 0) && reqport != "" ? ":" + reqport : ""))) + " wants " + (request.method == "GET" ? "content in " : (request.method == "POST" ? "to post content in " : (request.method == "PUT" ? "to add content in " : (request.method == "DELETE" ? "to delete content in " : (request.method == "PATCH" ? "to patch content in " : "to access content using " + request.method + " method in "))))) + request.url);
if (request.headers["user-agent"] != undefined) serverconsole.reqmessage("Client uses " + request.headers["user-agent"]);
var acceptEncoding = request.headers["accept-encoding"];
if (!acceptEncoding) acceptEncoding = "";
var head = fs.existsSync("./.head") ? fs.readFileSync("./.head").toString() : (fs.existsSync("./head.html") ? fs.readFileSync("./head.html").toString() : ""); // header
var foot = fs.existsSync("./.foot") ? fs.readFileSync("./.foot").toString() : (fs.existsSync("./foot.html") ? fs.readFileSync("./foot.html").toString() : ""); // footer
var fd = "";
function responseEnd(d) {
if (d === undefined) d = fd;
res.write(head + d + foot);
res.end();
}
// function responseEndGzip(d) {
// if (d === undefined) d = fd;
// zlib.gzip(head + d + foot, function (err, buff) {
// if (err) {
// throw err;
// } else {
// res.write(buff);
// res.end();
// }
// });
// }
//
// function responseEndDeflate(d) {
// if (d === undefined) d = fd;
// zlib.deflateRaw(head + d + foot, function (err, buff) {
// if (err) {
// throw err;
// } else {
// res.write(buff);
// res.end();
// }
// });
// }
var req = request; // request var is req = request
var res = response; // response var is res = response
//Error descriptions
var serverErrorDescs = {
200: "The request succeeded! :)",
201: "New resource has been created.",
202: "The request has been accepted for processing, but the processing has not been completed.",
400: "The request you made is invalid.",
401: "You need to authenticate yourself in order to access the requested file.",
402: "You need to pay in order to access the requested file.",
403: "You don't have access to the requested file.",
404: "The requested file doesn't exist. If you have typed URL manually, then please check the spelling.",
405: "Method used to access the requested file isn't allowed.",
406: "The request is capable of generating only not acceptable content.",
407: "You need to authenticate yourself in order to use the proxy.",
408: "You have timed out.",
409: "The request you sent conflicts with the current state of the server.",
410: "The requested file is permanently deleted.",
411: "Content-Length property is required.",
412: "The server doesn't meet preconditions you put in the request.",
413: "The request you sent is too large.",
414: "URL you sent is too long.",
415: "The media type of request you sent isn't supported by the server.",
416: "Content-Range you sent is unsatisfiable.",
417: "Expectation in Expect property couldn't be satisfied.",
418: "The server (teapot) can't brew any coffee! ;)",
421: "The request you made isn't intended for this server.",
422: "The server couldn't process content sent by you.",
423: "The requested file is locked.",
424: "The request depends on another failed request.",
425: "The server is unwilling to risk processing a request that might be replayed.",
426: "You need to upgrade protocols you use to request a file.",
428: "The request you sent needs to be conditional, but it isn't.",
429: "You sent too much requests to the server.",
431: "The request you sent contains headers, that are too large.",
451: "The requested file isn't accessible for legal reasons.",
500: "The server had an unexpected error. Below, the error stack is shown: {stack}
Please contact with developer/administrator at {contact}.",
501: "The request requires use of a function, which isn't implemented (yet) by the server.",
502: "The server had an error, while it was acting as a gateway.
Please contact with developer/administrator at {contact}.",
503: "Service provided by the server isn't available (yet).
Please contact with developer/administrator at {contact}.",
504: "The server couldn't get response in time, while it was acting as a gateway.
Please contact with developer/administrator at {contact}.",
505: "The server doesn't support HTTP version used in the request.",
506: "Variant header is configured to be engaged in content negotiation.
Please contact with developer/administrator at {contact}.",
507: "The server ran out of disk space neccessary to complete the request.",
508: "The server detected an infinite loop while processing the request.",
509: "The server has it's bandwidth limit exceeded.
Please contact with developer/administrator at {contact}.",
510: "The server requires an extended HTTP request. The request you made isn't an extended HTTP request.",
511: "You need to authenticate yourself in order to get network access.",
598: "The server couldn't get response in time, while it was acting as a proxy.",
599: "The server couldn't connect in time, while it was acting as a proxy."
};
//Server error calling method
// Server error calling method
function callServerError(errorCode, extName, stack, ch) {
if (typeof errorCode !== "number") {
throw new TypeError("HTTP error code parameter needs to be an integer.");
}
// Handle optional parameters
if (extName && typeof extName === "object") {
ch = stack;
stack = extName;
extName = undefined;
} else if (typeof extName !== "string" && extName !== null && extName !== undefined) {
throw new TypeError("Extension name parameter needs to be a string.");
}
if (stack && typeof stack === "object" && Object.prototype.toString.call(stack) !== "[object Error]") {
ch = stack;
stack = undefined;
} else if (typeof stack !== "object" && typeof stack !== "string" && stack) {
throw new TypeError("Error stack parameter needs to be either a string or an instance of Error object.");
}
var errorFile = errorCode.toString() + ".html";
var errorFile2 = "." + errorCode.toString();
if (fs.existsSync(errorFile2)) errorFile = errorFile2;
if (errorCode == 404 && fs.existsSync(page404)) errorFile = page404;
// Generate error stack if not provided
if (Object.prototype.toString.call(stack) === "[object Error]") stack = generateErrorStack(stack);
if (stack === undefined) stack = generateErrorStack(new Error("Unknown error"));
if (errorCode == 500 || errorCode == 502) {
serverconsole.errmessage("There was an error while processing the request!");
serverconsole.errmessage("Stack:");
serverconsole.errmessage(stack);
}
// Hide the error stack if specified
if (stackHidden) stack = "[error stack hidden]";
// Validate the error code and handle unknown codes
if (serverErrorDescs[errorCode] === undefined) {
callServerError(501, extName, stack);
} else {
var cheaders = getCustomHeaders();
// Process custom headers if provided
if (ch) {
var chon = Object.keys(cheaders);
var chn = Object.keys(ch);
for (var i = 0; i < chn.length; i++) {
var nhn = chn[i];
for (var j = 0; j < chon.length; j++) {
if (chon[j].toLowerCase() == chn[i].toLowerCase()) {
nhn = chon[j];
break;
}
}
if (ch[chn[i]]) cheaders[nhn] = ch[chn[i]];
}
}
cheaders["Content-Type"] = "text/html; charset=utf-8";
// Set default Allow header for 405 error if not provided
if (errorCode == 405 && !cheaders["Allow"]) cheaders["Allow"] = "GET, POST, HEAD, OPTIONS";
// Read the error file and replace placeholders with error information
fs.readFile(errorFile, function (err, data) {
try {
if (err) throw err;
response.writeHead(errorCode, http.STATUS_CODES[errorCode], cheaders);
fd += data.toString().replace(/{errorMessage}/g, errorCode.toString() + " " + http.STATUS_CODES[errorCode]).replace(/{errorDesc}/g, serverErrorDescs[errorCode]).replace(/{stack}/g, stack.replace(/&/g, "&").replace(//g, ">").replace(/\r\n/g, " ").replace(/\n/g, " ").replace(/\r/g, " ").replace(/ {2}/g, " ")).replace(/{path}/g, request.url.replace(/&/g, "&").replace(//g, ">")).replace(/{server}/g, "" + (exposeServerVersion ? "SVR.JS/" + version + " (" + getOS() + "; " + (process.isBun ? ("Bun/v" + process.versions.bun + "; like Node.JS/" + process.version) : ("Node.JS/" + process.version)) + ")" : "SVR.JS") + (extName == undefined ? "" : " " + extName) + ((req.headers.host == undefined || isProxy) ? "" : " on " + String(req.headers.host).replace(/&/g, "&").replace(//g, ">"))).replace(/{contact}/g, serverAdmin.replace(/\./g, "[dot]").replace(/@/g, "[at]")); // Replace placeholders in error response
responseEnd();
} catch (ex) {
var additionalError = 500;
// Handle additional error cases
if (ex.code == "ENOENT") {
additionalError = 404;
} else if (ex.code == "EACCES") {
additionalError = 403;
} else if (ex.code == "EMFILE") {
additionalError = 429;
} else if (ex.code == "ELOOP") {
additionalError = 508;
}
response.writeHead(errorCode, http.STATUS_CODES[errorCode], cheaders);
response.write(("
{errorMessage}
{errorMessage}
{errorDesc}
" + ((additionalError == 404) ? "" : "
Additionally, a {additionalError} error occurred while loading an error page.
") + "
{server}
").replace(/{errorMessage}/g, errorCode.toString() + " " + http.STATUS_CODES[errorCode]).replace(/{errorDesc}/g, serverErrorDescs[errorCode]).replace(/{stack}/g, stack.replace(/&/g, "&").replace(//g, ">").replace(/\r\n/g, " ").replace(/\n/g, " ").replace(/\r/g, " ").replace(/ {2}/g, " ")).replace(/{path}/g, request.url.replace(/&/g, "&").replace(//g, ">")).replace(/{server}/g, "" + (exposeServerVersion ? "SVR.JS/" + version + " (" + getOS() + "; " + (process.isBun ? ("Bun/v" + process.versions.bun + "; like Node.JS/" + process.version) : ("Node.JS/" + process.version)) + ")" : "SVR.JS") + (extName == undefined ? "" : " " + extName) + ((req.headers.host == undefined || isProxy) ? "" : " on " + String(req.headers.host).replace(/&/g, "&").replace(//g, ">"))).replace(/{contact}/g, serverAdmin.replace(/\./g, "[dot]").replace(/@/g, "[at]")).replace(/{additionalError}/g, additionalError.toString())); // Replace placeholders in error response
response.end();
}
});
}
}
// Function to perform HTTP redirection to a specified destination URL
function redirect(destination, isTemporary, customHeaders) {
// If customHeaders are not provided, get the default custom headers
if (customHeaders === undefined) customHeaders = getCustomHeaders();
// Set the "Location" header to the destination URL
customHeaders["Location"] = destination;
// Determine the status code for redirection based on the isTemporary flag
var statusCode = isTemporary ? 302 : 301;
// Write the response header with the appropriate status code and message
res.writeHead(statusCode, http.STATUS_CODES[statusCode], customHeaders);
// Log the redirection message
serverconsole.resmessage("Client redirected to " + destination);
// End the response
res.end();
// Return from the function
return;
}
// Function to parse incoming POST data from the request
function parsePostData(options, callback) {
// If the request method is not POST, return a 405 Method Not Allowed error
if (req.method != "POST") {
// Get the default custom headers and add "Allow" header with value "POST"
var customHeaders = getCustomHeaders();
customHeaders["Allow"] = "POST";
// Call the server error function with 405 status code and custom headers
callServerError(405, undefined, undefined, customHeaders);
return;
}
// Set formidableOptions to options, if provided; otherwise, set it to an empty object
var formidableOptions = options ? options : {};
// If no callback is provided, set the callback to options and reset formidableOptions
if (!callback) {
callback = options;
formidableOptions = {};
}
// If the formidable module had an error, call the server error function with 500 status code and error stack
if (formidable._errored) callServerError(500, undefined, generateErrorStack(formidable._errored));
// Create a new formidable form
var form = formidable(formidableOptions);
// Parse the request and process the fields and files
form.parse(req, function (err, fields, files) {
// If there was an error, call the server error function with status code determined by error
if (err) {
if(err.httpCode) callServerError(err.httpCode);
else callServerError(400);
return;
}
// Otherwise, call the provided callback function with the parsed fields and files
callback(fields, files);
});
}
// Function to parse a URL string into a URL object
function parseURL(uri) {
// Check if the URL API is available (Node.js version >= 10)
if (typeof URL !== "undefined" && url.Url) {
try {
// Create a new URL object using the provided URI and base URL
var uobject = new URL(uri, "http" + (req.socket.encrypted ? "s" : "") + "://" + (req.headers.host ? req.headers.host : (domain ? domain : "unknown.invalid")));
// Create a new URL object (similar to deprecated url.Url)
var nuobject = new url.Url();
// Set properties of the new URL object from the provided URL
if (uri.indexOf("/") != -1) nuobject.slashes = true;
if (uobject.protocol != "") nuobject.protocol = uobject.protocol;
if (uobject.username != "" && uobject.password != "") nuobject.auth = uobject.username + ":" + uobject.password;
if (uobject.host != "") nuobject.host = uobject.host;
if (uobject.hostname != "") nuobject.hostname = uobject.hostname;
if (uobject.port != "") nuobject.port = uobject.port;
if (uobject.pathname != "") nuobject.pathname = uobject.pathname;
if (uobject.search != "") nuobject.search = uobject.search;
if (uobject.hash != "") nuobject.hash = uobject.hash;
if (uobject.href != "") nuobject.href = uobject.href;
// Adjust the pathname and href properties if the URI doesn't start with "/"
if (uri.indexOf("/") != 0) {
if (nuobject.pathname) {
nuobject.pathname = nuobject.pathname.substr(1);
nuobject.href = nuobject.pathname + (nuobject.search ? nuobject.search : "");
}
}
// Set the path property as a combination of pathname and search
if (nuobject.pathname) {
nuobject.path = nuobject.pathname + (nuobject.search ? nuobject.search : "");
}
// Initialize the query object and copy URL search parameters to it
nuobject.query = {};
uobject.searchParams.forEach(function (value, key) {
nuobject.query[key] = value;
});
// Return the created URL object
return nuobject;
} catch (ex) {
// If there was an error using the URL API, fall back to deprecated url.parse
return url.parse(uri, true);
}
} else {
// If the URL API is not available, fall back to deprecated url.parse
return url.parse(uri, true);
}
}
var uobject = parseURL(req.url);
var search = uobject.search;
var href = uobject.pathname;
var ext = path.extname(href).toLowerCase();
ext = ext.substr(1, ext.length);
var decodedHref = "";
try {
decodedHref = decodeURIComponent(href);
} catch (ex) {
//Return 400 error
callServerError(400);
serverconsole.errmessage("Bad request!");
return;
}
if (req.headers["expect"] && req.headers["expect"] != "100-continue") {
callServerError(417);
return;
}
//MOD EXCECUTION FUNCTION
function modExecute(mods, ffinals) {
var modFunction = ffinals;
for (var i = mods.length - 1; i >= 0; i--) {
modFunction = mods[i].callback(req, res, serverconsole, responseEnd, href, ext, uobject, search, "index.html", users, page404, head, foot, fd, modFunction, configJSON, callServerError, getCustomHeaders, origHref, redirect, parsePostData);
}
modFunction();
}
var vresCalled = false;
function vres(req, res, serverconsole, responseEnd, href, ext, uobject, search, defaultpage, users, page404, head, foot, fd, callServerError, getCustomHeaders, origHref, redirect, parsePostData) {
return function () {
if (vresCalled) {
process.emitWarning("elseCallback() invoked multiple times.", {
code: "WARN_SVRJS_MULTIPLE_ELSECALLBACK"
});
return;
} else {
vresCalled = true;
}
// function responseEndGzip(d) {
// if (d === undefined) d = fd;
// zlib.gzip(head + d + foot, function (err, buff) {
// if (err) {
// throw err;
// } else {
// res.write(buff);
// res.end();
// }
// });
// }
//
// function responseEndDeflate(d) {
// if (d === undefined) d = fd;
// zlib.deflateRaw(head + d + foot, function (err, buff) {
// if (err) {
// throw err;
// } else {
// res.write(buff);
// res.end();
// }
// });
// }
function responseEnd(d) {
if (d === undefined) d = fd;
res.write(head + d + foot);
res.end();
}
if (req.socket == null) {
serverconsole.errmessage("Client socket is null!!!");
return;
}
var reqport = "";
var reqip = "";
var oldport = "";
var oldip = "";
if (req.headers["x-svr-js-client"] != undefined && enableIPSpoofing) {
var kl = req.headers["x-svr-js-client"].split(":");
reqport = kl.pop();
reqip = kl.join(":");
try {
oldport = req.socket.remotePort;
oldip = req.socket.remoteAddress;
req.socket.realRemotePort = reqport;
req.socket.realRemoteAddress = reqip;
req.socket.originalRemotePort = oldport;
req.socket.originalRemoteAddress = oldip;
res.socket.realRemotePort = reqport;
res.socket.realRemoteAddress = reqip;
res.socket.originalRemotePort = oldport;
res.socket.originalRemoteAddress = oldip;
} catch (ex) {
//Nevermind...
}
} else if (req.headers["x-forwarded-for"] != undefined && enableIPSpoofing) {
reqport = null;
reqip = req.headers["x-forwarded-for"].split(",")[0].replace(/ /g, "");
if (reqip.indexOf(":") == -1) reqip = "::ffff:" + reqip;
try {
oldport = req.socket.remotePort;
oldip = req.socket.remoteAddress;
req.socket.realRemotePort = reqport;
req.socket.realRemoteAddress = reqip;
req.socket.originalRemotePort = oldport;
req.socket.originalRemoteAddress = oldip;
res.socket.realRemotePort = reqport;
res.socket.realRemoteAddress = reqip;
res.socket.originalRemotePort = oldport;
res.socket.originalRemoteAddress = oldip;
} catch (ex) {
//Nevermind...
}
} else {
reqip = req.socket.remoteAddress;
reqport = req.socket.remotePort;
}
// Function to check the level of a path relative to the web root
function checkPathLevel(path) {
// Split the path into an array of components based on "/"
var pathComponents = path.split("/");
// Initialize counters for level up (..) and level down (.)
var levelUpCount = 0;
var levelDownCount = 0;
// Loop through the path components
for (var i = 0; i < pathComponents.length; i += 1) {
// If the component is "..", decrement the levelUpCount
if (".." === pathComponents[i]) {
levelUpCount -= 1;
}
// If the component is not "." or an empty string, increment the levelDownCount
else if ("." !== pathComponents[i] && "" !== pathComponents[i]) {
levelDownCount += 1;
}
}
// Calculate the overall level by subtracting levelUpCount from levelDownCount
var overallLevel = levelDownCount - levelUpCount;
// Return the overall level
return overallLevel;
}
if (isProxy) {
var eheaders = getCustomHeaders();
eheaders["Content-Type"] = "text/html; charset=utf-8";
res.writeHead(501, "Not implemented", eheaders);
res.write("Proxy not implemented
Proxy not implemented
SVR.JS doesn't support proxy without proxy mod. If you're administator of this server, then install this mod in order to use SVR.JS as a proxy.
To use all DorianTech SVR.JS features, such as all directory traversal protections; use server-side JS; and recieve product support, your copy of DorianTech SVR.JS must be validated as genuine.
This copy of SVR.JS is not genuine.");
serverconsole.resmessage("You may be a victim of software counterfeiting.");
} else {
res.writeHead(200, "OK", hdhds);
res.end("\n\n\n\nSVR.JS Genuine Advantage\n\n\n
Activate SVR.JS
\nYou will then be able to use all of SVR.JS features through SVR.JS Genuine Advantage!\n\n
And Satan created Mammon. His work won people from all over the school. When people abandoned them through the Piracy Window, so Satan went back in time and created the Server to continue to wreak havoc all over the school.
\n
from The Summary of Book of ZSOiE
\n \n \n");
return;
}
var randomValue = Math.random();
if (randomValue > 0.85714) {
res.end("\n\n\n\n \n The Book of ZSOiE, 7:28\n \n \n \n \n \n \n
The Server continues to cultivate it's Dafa. The Author found the Robot and asked him for help. Then the Robot started to help the Author to improve his Server. And the Author tries to create yet another server without using the main node...
\n
from The Book of ZSOiE, 7:28
\n \n \n");
} else if (randomValue > 0.71429) {
res.end("\n\n\n\n \n The Book of ZSOiE, 7:16\n \n \n \n \n \n \n
The Server is still going. But the Author commanded to the Server: \"thou shalt you split to two branches.\". And the Server did split it's Dafa. One of two branches stopped serving on old and rusty node. Other one is still serving on that, but it will later vanish... \"Mammon will get confused\" - said the Author.
\n
from The Book of ZSOiE, 7:16
\n \n \n");
} else if (randomValue > 0.57143) {
res.end("\n\n\n\n \n The Book of ZSOiE, 7:2\n \n \n \n \n \n \n
The old Server forces died. The all-powerful new Server rosen from ashes of old Server like phoenix followed the ways of Durability-Ease-Reliability and cultivated his Dafa. Then, the Author and Whyvn appeared on best former Mammon's disciples paper.
\n
from The Book of ZSOiE, 7:2
\n \n \n");
} else if (randomValue > 0.42857) {
res.end("\n\n\n\n \n The Book of ZSOiE, 6:24\n \n \n \n \n \n \n
Mammon had enough karmic retribution. The Author tried it's Server on main node's substitute. Then, the Author saw, that Server's Dafa is good, and that main node, it's substitute, and older Mammon are good. Meanwhile the Author, Whyvn, and Snovbyn rejoiced even more from their success over older Mammon.
\n
from The Book of ZSOiE, 6:24
\n \n \n");
} else if (randomValue > 0.32143) {
res.end("\n\n\n\n \n The Book of ZSOiE, 6:6\n \n \n \n \n \n \n
And the Server is about to come. The Author along with Whyvn and Snovbyn passing the Mammon's test rejoiced their success over older Mammon.
\n
from The Book of ZSOiE, 6:6
\n \n \n");
} else if (randomValue > 0.14286) {
res.end("\n\n\n\n \n The Book of ZSOiE, 5:25\n \n \n \n \n \n \n
The twins of Mammon quarrelled. The Author with it's Server and it's main node plunged the Mammon's servers into darkness. Meanwhile Whyvn and Snovbyn helped him to break Mammon's servers.
\n
from The Book of ZSOiE, 5:25
\n \n \n");
} else {
res.end("\n\n\n\n \n The Book of ZSOiE, 3:16\n \n \n \n \n \n \n
Mammon slept. Meanwhile, the Author, Whyvn and Snovbyn being in very skill-requiring challenge casted tcpdump and mongodb on him.
\n
from The Book of ZSOiE, 3:16
\n \n \n");
}
return;
} else if (version.indexOf("Nightly-") === 0 && (href == "/crash.svr" || (os.platform() == "win32" && href.toLowerCase() == "/crash.svr"))) {
throw new Error("Intentionally crashed");
}
var pth = decodeURIComponent(href).replace(/\/+/g, "/").substr(1);
var readFrom = "./" + pth;
fs.stat(readFrom, function (err, stats) {
if (err) {
if (err.code == "ENOENT") {
if (__dirname != process.cwd() && pth.match(/^\.dirimages\/(?:(?!\.png$).)+\.png$/)) {
stats = {
isDirectory: function isDirectory() {
return false;
},
isFile: function isFile() {
return true;
}
};
readFrom = __dirname + "/" + pth;
} else {
callServerError(404);
serverconsole.errmessage("Resource not found.");
return;
}
} else if (err.code == "EACCES") {
callServerError(403);
serverconsole.errmessage("Access denied.");
return;
} else if (err.code == "EMFILE") {
callServerError(500, undefined, generateErrorStack(err)); // Too many file descriptors or open files were reached by the process. It is an internal server issue.
return;
} else if (err.code == "ELOOP") {
callServerError(508); // The symbolic link loop is detected during file system operations.
serverconsole.errmessage("Symbolic link loop detected.");
return;
} else {
callServerError(500, undefined, generateErrorStack(err));
return;
}
}
//Check if index file exists
if (req.url == "/" || stats.isDirectory()) {
fs.stat(readFrom + "/.notindex".replace(/\/+/g, "/"), function (e) {
if (e) {
fs.stat((readFrom + "/index.html").replace(/\/+/g, "/"), function (e, s) {
if (e || !s.isFile()) {
fs.stat((readFrom + "/index.htm").replace(/\/+/g, "/"), function (e, s) {
if (e || !s.isFile()) {
fs.stat((readFrom + "/index.xhtml").replace(/\/+/g, "/"), function (e, s) {
if (e || !s.isFile()) {
properServe();
} else {
stats = s;
pth = (pth + "/index.xhtml").replace(/\/+/g, "/");
ext = "xhtml";
readFrom = "./" + pth;
properServe();
}
});
} else {
stats = s;
pth = (pth + "/index.htm").replace(/\/+/g, "/");
ext = "htm";
readFrom = "./" + pth;
properServe();
}
});
} else {
stats = s;
pth = (pth + "/index.html").replace(/\/+/g, "/");
ext = "html";
readFrom = "./" + pth;
properServe();
}
});
}
});
} else {
properServe();
}
function properServe() {
if (stats.isDirectory()) {
// Check if directory listing is enabled in the configuration
if (configJSON.enableDirectoryListing || configJSON.enableDirectoryListing === 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 heada = 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 foota = 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()
: "";
// Generate HTML head and footer based on configuration and custom content
var htmlHead = (!configJSON.enableDirectoryListingWithDefaultHead || head == ""
? (heada.indexOf("") == -1
? "Directory: " + decodeURIComponent(origHref).replace(/&/g, "&").replace(//g, ">") + ""
: heada.replace("", "Directory: " + decodeURIComponent(origHref).replace(/&/g, "&").replace(//g, ">") + ""))
: head.replace("", "Directory: " + decodeURIComponent(origHref).replace(/&/g, "&").replace(//g, ">") + "")) +
(heada.indexOf("") == -1 ? heada : "") +
"
\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 = "
");
serverconsole.errmessage("Client blocked");
return;
}
if (req.url == "*") {
if (req.method == "OPTIONS") {
var hdss = getCustomHeaders();
hdss["Allow"] = "GET, POST, HEAD, OPTIONS";
res.writeHead(204, "No Content", hdss);
res.end();
return;
} else {
callServerError(400);
return;
}
}
if (req.method == "CONNECT") {
callServerError(501);
serverconsole.errmessage("CONNECT requests aren't supported. Your JS runtime probably doesn't support 'connect' handler for HTTP library.");
return;
}
//SANITIZE URL
var sanitizedHref = sanitizeURL(href);
//Check if URL is "dirty"
if (href != sanitizedHref && !isProxy) {
var sanitizedURL = uobject;
sanitizedURL.path = null;
sanitizedURL.href = null;
sanitizedURL.pathname = sanitizedHref;
sanitizedURL.hostname = null;
sanitizedURL.host = null;
sanitizedURL.port = null;
sanitizedURL.protocol = null;
sanitizedURL.slashes = null;
sanitizedURL = url.format(sanitizedURL);
serverconsole.resmessage("URL sanitized: " + req.url + " => " + sanitizedURL);
redirect(sanitizedURL, false);
return;
}
//URL REWRITING
function rewriteURL(address, map) {
var rewrittenAddress = address;
for (var i = 0; i < map.length; i++) {
if (createRegex(map[i].definingRegex).test(address)) {
for (var j = 0; j < map[i].replacements.length; j++) {
rewrittenAddress = rewrittenAddress.replace(createRegex(map[i].replacements[j].regex), map[i].replacements[j].replacement);
}
if (map[i].append) rewrittenAddress += map[i].append;
break;
}
}
return rewrittenAddress;
}
var origHref = href;
if (!isProxy) {
var rewrittenURL = rewriteURL(req.url, rewriteMap);
if (rewrittenURL != req.url) {
serverconsole.resmessage("URL rewritten: " + req.url + " => " + rewrittenURL);
req.url = rewrittenURL;
uobject = parseURL(req.url);
search = uobject.search;
href = uobject.pathname;
ext = path.extname(href).toLowerCase();
ext = ext.substr(1, ext.length);
try {
decodedHref = decodeURIComponent(href);
} catch (ex) {
//Return 400 error
callServerError(400);
serverconsole.errmessage("Bad request!");
return;
}
var sHref = sanitizeURL(href);
if (sHref != href.replace(/\/\.(?=\/|$)/g, "/").replace(/\/+/g, "/")) {
callServerError(403);
serverconsole.errmessage("Content blocked.");
return;
} else if (sHref != href) {
var rewrittenAgainURL = uobject;
rewrittenAgainURL.path = null;
rewrittenAgainURL.href = null;
rewrittenAgainURL.pathname = sHref;
rewrittenAgainURL = url.format(rewrittenAgainURL);
serverconsole.resmessage("URL sanitized: " + req.url + " => " + rewrittenAgainURL);
req.url = rewrittenAgainURL;
uobject = parseURL(req.url);
search = uobject.search;
href = uobject.pathname;
ext = path.extname(href).toLowerCase();
ext = ext.substr(1, ext.length);
try {
decodedHref = decodeURIComponent(href);
} catch (ex) {
//Return 400 error
callServerError(400);
serverconsole.errmessage("Bad request!");
return;
}
}
}
}
//Set response headers
if (!isProxy) {
reqcounter++;
var hkh = getCustomHeaders();
var hk = Object.keys(hkh);
for (var i = 0; i < hk.length; i++) {
try {
response.setHeader(hk[i], hkh[hk[i]]);
} catch (ex) {
//Headers will not be set.
}
}
}
//Check if path is forbidden
if ((isForbiddenPath(decodedHref, "config") || isForbiddenPath(decodedHref, "certificates")) && !isProxy) {
callServerError(403);
serverconsole.errmessage("Access to configuration file/certificates is denied.");
return;
} else if (isIndexOfForbiddenPath(decodedHref, "log") && !isProxy && (configJSON.enableLogging || configJSON.enableLogging == undefined) && !(configJSON.enableRemoteLogBrowsing || configJSON.enableRemoteLogBrowsing == undefined)) {
callServerError(403);
serverconsole.errmessage("Access to log files is denied.");
return;
} else if (isForbiddenPath(decodedHref, "svrjs") && !isProxy && !exposeServerVersion && process.cwd() == __dirname) {
callServerError(403);
serverconsole.errmessage("Access to SVR.JS script is denied.");
return;
} else if ((isForbiddenPath(decodedHref, "svrjs") || isForbiddenPath(decodedHref, "serverSideScripts") || isIndexOfForbiddenPath(decodedHref, "serverSideScriptDirectories")) && !isProxy && (configJSON.disableServerSideScriptExpose && configJSON.disableServerSideScriptExpose != undefined)) {
callServerError(403);
serverconsole.errmessage("Access to sources is denied.");
return;
} else {
var nonscodeIndex = -1;
var authIndex = -1;
var regexI = [];
if (!isProxy && nonStandardCodes != undefined) {
for (var i = 0; i < nonStandardCodes.length; i++) {
var mth = false;
if (nonStandardCodes[i].regex) {
var regexObj = nonStandardCodes[i].regex.split("/");
if (regexObj.length == 0) throw new Error("Invalid regex!");
var modifiers = regexObj.pop();
if (!modifiers.match(/i/i) && os.platform() == "win32") modifiers += "i";
regexObj.shift();
var searchString = regexObj.join("/");
var rx = RegExp(searchString, modifiers);
mth = req.url.match(rx) || href.match(rx);
regexI.push(rx);
} else {
mth = nonStandardCodes[i].url == href || (os.platform() == "win32" && nonStandardCodes[i].url.toLowerCase() == href.toLowerCase());
}
if (mth) {
if (nonStandardCodes[i].scode == 401) {
if (authIndex == -1) {
authIndex = i;
}
} else {
if (nonscodeIndex == -1) {
if ((nonStandardCodes[i].scode == 403 || nonStandardCodes[i].scode == 451) && nonStandardCodes[i].users !== undefined) {
var lpk = false;
if (nonStandardCodes[i].users.check(reqip)) {
nonscodeIndex = i;
lpk = true;
}
if (lpk) break;
} else {
nonscodeIndex = i;
}
}
}
}
}
}
// Handle non-standard codes
if (nonscodeIndex > -1) {
var nonscode = nonStandardCodes[nonscodeIndex];
if (nonscode.scode == 301 || nonscode.scode == 302) {
var location = "";
if (regexI[nonscodeIndex]) {
location = req.url.replace(regexI[nonscodeIndex], nonscode.location);
} else if (req.url.split("?")[1] == undefined || req.url.split("?")[1] == null || req.url.split("?")[1] == "" || req.url.split("?")[1] == " ") {
location = nonscode.location;
} else {
location = nonscode.location + "?" + req.url.split("?")[1];
}
redirect(location, nonscode.scode == 302);
return;
} else if (nonscode.scode == 403) {
callServerError(403);
serverconsole.errmessage("Content blocked.");
return;
} else if (nonscode.scode == 410) {
callServerError(410);
serverconsole.errmessage("Content is gone.");
return;
} else if (nonscode.scode == 418) {
callServerError(418);
serverconsole.errmessage("SVR.JS is always a teapot ;)");
return;
} else {
callServerError(nonscode.scode);
serverconsole.errmessage("Client fails recieving content.");
return;
}
}
// Handle HTTP authentication
if (authIndex > -1) {
var authcode = nonStandardCodes[authIndex];
function authorizedCallback(bruteProtection) {
var ha = getCustomHeaders();
ha["WWW-Authenticate"] = "Basic realm=\"" + (authcode.realm ? authcode.realm.replace(/(\\|")/g, "\\$1") : "SVR.JS HTTP Basic Authorization") + "\", charset=\"UTF-8\"";
var credentials = req.headers["authorization"];
if (!credentials) {
callServerError(401, undefined, undefined, ha);
serverconsole.errmessage("Content needs authorization.");
return;
}
var cmatch = credentials.match(/^Basic (.+)$/);
if (!cmatch) {
callServerError(401, undefined, undefined, ha);
serverconsole.errmessage("Malformed credentials.");
return;
}
var c2 = Buffer.from(cmatch[1], "base64").toString("utf8");
var c2match = c2.match(/^([^:]*):(.*)$/);
if (!c2match) {
callServerError(401, undefined, undefined, ha);
serverconsole.errmessage("Malformed credentials.");
return;
}
var username = c2match[1];
var password = c2match[2];
var authorized = false;
for (var i = 0; i < users.length; i++) {
var hash = sha256(password + users[i].salt);
if (users[i].name == username && users[i].pass == hash) {
authorized = true;
break;
}
}
if (!authorized) {
if (bruteProtection) {
if (process.send) {
process.send("\x12AUTHW" + reqip);
} else {
if (!bruteForceDb[reqip]) bruteForceDb[reqip] = {
invalidAttempts: 0
};
bruteForceDb[reqip].invalidAttempts++;
if (bruteForceDb[reqip].invalidAttempts >= 10) {
bruteForceDb[reqip].lastAttemptDate = new Date();
}
}
}
callServerError(401, undefined, undefined, ha);
serverconsole.errmessage("User " + username + " failed to log in.");
} else {
if (bruteProtection) {
if (process.send) {
process.send("\x12AUTHR" + reqip);
} else {
if (bruteForceDb[reqip]) bruteForceDb[reqip] = {
invalidAttempts: 0
};
}
}
modExecute(mods, vres(req, res, serverconsole, responseEnd, href, ext, uobject, search, "index.html", users, page404, head, foot, fd, callServerError, getCustomHeaders, origHref, redirect, parsePostData));
}
}
if (authcode.disableBruteProtection) {
authorizedCallback(false);
} else if (!process.send) {
if (!bruteForceDb[reqip] || !bruteForceDb[reqip].lastAttemptDate || (new Date() - 300000 >= bruteForceDb[reqip].lastAttemptDate)) {
if (bruteForceDb[reqip] && bruteForceDb[reqip].invalidAttempts >= 10) bruteForceDb[reqip] = {
invalidAttempts: 5
};
authorizedCallback(true);
} else {
callServerError(429);
serverconsole.errmessage("Brute force limit reached!");
}
} else {
var listenerEmitted = false;
function authMessageListener(message) {
if (listenerEmitted) return;
if (message == "\x14AUTHA" + reqip || message == "\x14AUTHD" + reqip) {
process.removeListener("message", authMessageListener);
listenerEmitted = true;
}
if (message == "\x14AUTHD" + reqip) {
callServerError(429);
serverconsole.errmessage("Brute force limit reached!");
} else if (message == "\x14AUTHA" + reqip) {
authorizedCallback(true);
}
}
process.on("message", authMessageListener);
process.send("\x12AUTHQ" + reqip);
}
} else {
modExecute(mods, vres(req, res, serverconsole, responseEnd, href, ext, uobject, search, "index.html", users, page404, head, foot, fd, callServerError, getCustomHeaders, origHref, redirect, parsePostData));
}
}
} catch (ex) {
//CRASH HANDLER
if (ex.message == "Intentionally crashed") throw ex; //If intentionally crashed, then crash SVR.JS
callServerError(500, undefined, generateErrorStack(ex)); //Else just return 500 error
}
}
}
//Listen port to server
server.on("error", function (err) {
if (err.code == "EADDRINUSE" || err.code == "EADDRNOTAVAIL" || err.code == "EACCES") {
attmts--;
if (cluster.isMaster === undefined) {
if (err.code == "EADDRINUSE") {
serverconsole.locerrmessage("Address is already in use by another process.");
} else if (err.code == "EADDRNOTAVAIL") {
serverconsole.locerrmessage("Address is not available on this machine.");
} else if (err.code == "EACCES") {
serverconsole.locerrmessage("Permission denied. You may not have sufficient privileges to access the requested address.");
} else if (err.code == "EAFNOSUPPORT") {
serverconsole.locerrmessage("Address family not supported. The address family (IPv4 or IPv6) of the requested address is not supported.");
} else if (err.code == "EALREADY") {
serverconsole.locerrmessage("Operation already in progress. The server is already in the process of establishing a connection on the requested address.");
} else if (err.code == "ECONNABORTED") {
serverconsole.locerrmessage("Connection aborted. The connection to the server was terminated abruptly.");
} else if (err.code == "ECONNREFUSED") {
serverconsole.locerrmessage("Connection refused. The server refused the connection attempt.");
} else if (err.code == "ECONNRESET") {
serverconsole.locerrmessage("Connection reset by peer. The connection to the server was reset by the remote host.");
} else if (err.code == "EDESTADDRREQ") {
serverconsole.locerrmessage("Destination address required. The destination address must be specified.");
} else if (err.code == "ENETDOWN") {
serverconsole.locerrmessage("Network is down. The network interface used for the connection is not available.");
} else if (err.code == "ENETUNREACH") {
serverconsole.locerrmessage("Network is unreachable. The network destination is not reachable from this host.");
} else if (err.code == "ENOBUFS") {
serverconsole.locerrmessage("No buffer space available. Insufficient buffer space is available for the server to process the request.");
} else if (err.code == "ENOTSOCK") {
serverconsole.locerrmessage("Not a socket. The file descriptor provided is not a valid socket.");
} else if (err.code == "EPROTO") {
serverconsole.locerrmessage("Protocol error. An unspecified protocol error occurred.");
} else if (err.code == "EPROTONOSUPPORT") {
serverconsole.locerrmessage("Protocol not supported. The requested network protocol is not supported.");
} else if (err.code == "ETIMEDOUT") {
serverconsole.locerrmessage("Connection timed out. The server did not respond within the specified timeout period.");
} else {
serverconsole.locerrmessage("There was an unknown error with the server.");
}
serverconsole.locmessage(attmts + " attempts left.");
} else {
process.send("\x12ERRLIST" + attmts + err.code);
}
if (attmts > 0) {
server2.close();
setTimeout(start, 900);
} else {
if (cluster.isMaster !== undefined) process.send("\x12" + err.code);
process.exit(errors[err.code]);
}
} else {
serverconsole.locerrmessage("There was a problem starting SVR.JS!!!");
serverconsole.locerrmessage("Stack:");
serverconsole.locerrmessage(generateErrorStack(err));
if (cluster.isMaster !== undefined) process.send("\x12CRASH");
process.exit(err.code ? errors[err.code] : 1);
}
});
server.once("listening", function () {
listeningMessage();
});
}
function listenConnListener(msg) {
if (msg == "\x12LISTEN") {
listeningMessage();
}
}
function bruteForceListenerWrapper(worker) {
return function bruteForceListener(message) {
var ip = "";
if (message.substr(0, 6) == "\x12AUTHQ") {
ip = message.substr(6);
if (!bruteForceDb[ip] || !bruteForceDb[ip].lastAttemptDate || (new Date() - 300000 >= bruteForceDb[ip].lastAttemptDate)) {
if (bruteForceDb[ip] && bruteForceDb[ip].invalidAttempts >= 10) bruteForceDb[ip] = {
invalidAttempts: 5
};
worker.send("\x14AUTHA" + ip);
} else {
worker.send("\x14AUTHD" + ip);
}
} else if (message.substr(0, 6) == "\x12AUTHR") {
ip = message.substr(6);
if (bruteForceDb[ip]) bruteForceDb[ip] = {
invalidAttempts: 0
};
} else if (message.substr(0, 6) == "\x12AUTHW") {
ip = message.substr(6);
if (!bruteForceDb[ip]) bruteForceDb[ip] = {
invalidAttempts: 0
};
bruteForceDb[ip].invalidAttempts++;
if (bruteForceDb[ip].invalidAttempts >= 10) {
bruteForceDb[ip].lastAttemptDate = new Date();
}
}
};
}
function msgListener(msg) {
for (var i = 0; i < Object.keys(cluster.workers).length; i++) {
if (msg == "\x12END") {
cluster.workers[Object.keys(cluster.workers)[i]].removeAllListeners("message");
cluster.workers[Object.keys(cluster.workers)[i]].on("message", bruteForceListenerWrapper(cluster.workers[Object.keys(cluster.workers)[i]]));
cluster.workers[Object.keys(cluster.workers)[i]].on("message", listenConnListener);
}
}
if (msg == "\x12CLOSE") {
closedMaster = true;
} else if (msg == "\x12LISTEN" || msg.substr(0, 4) == "\x12AUTH") {
//Do nothing!
} else if (msg == "\x12SAVEGOOD") {
serverconsole.locmessage("Configuration saved.");
} else if (msg.indexOf("\x12SAVEERR") == 0) {
serverconsole.locwarnmessage("There was a problem, while saving configuration file. Reason: " + msg.substr(8));
} else if (msg == "\x12OPEN") {
closedMaster = false;
} else if (msg == "\x12END") {
cluster.workers[Object.keys(cluster.workers)[0]].on("message", function (msg) {
if (msg.length > 9 && msg.indexOf("\x12ERRLIST") == 0) {
var tries = parseInt(msg.substr(8, 1));
var errCode = msg.substr(9);
if (errCode == "EADDRINUSE") {
serverconsole.locerrmessage("Address is already in use by another process.");
} else if (errCode == "EADDRNOTAVAIL") {
serverconsole.locerrmessage("Address is not available on this machine.");
} else if (errCode == "EACCES") {
serverconsole.locerrmessage("Permission denied. You may not have sufficient privileges to access the requested address.");
} else if (errCode == "EAFNOSUPPORT") {
serverconsole.locerrmessage("Address family not supported. The address family (IPv4 or IPv6) of the requested address is not supported.");
} else if (errCode == "EALREADY") {
serverconsole.locerrmessage("Operation already in progress. The server is already in the process of establishing a connection on the requested address.");
} else if (errCode == "ECONNABORTED") {
serverconsole.locerrmessage("Connection aborted. The connection to the server was terminated abruptly.");
} else if (errCode == "ECONNREFUSED") {
serverconsole.locerrmessage("Connection refused. The server refused the connection attempt.");
} else if (errCode == "ECONNRESET") {
serverconsole.locerrmessage("Connection reset by peer. The connection to the server was reset by the remote host.");
} else if (errCode == "EDESTADDRREQ") {
serverconsole.locerrmessage("Destination address required. The destination address must be specified.");
} else if (errCode == "ENETDOWN") {
serverconsole.locerrmessage("Network is down. The network interface used for the connection is not available.");
} else if (errCode == "ENETUNREACH") {
serverconsole.locerrmessage("Network is unreachable. The network destination is not reachable from this host.");
} else if (errCode == "ENOBUFS") {
serverconsole.locerrmessage("No buffer space available. Insufficient buffer space is available for the server to process the request.");
} else if (errCode == "ENOTSOCK") {
serverconsole.locerrmessage("Not a socket. The file descriptor provided is not a valid socket.");
} else if (errCode == "EPROTO") {
serverconsole.locerrmessage("Protocol error. An unspecified protocol error occurred.");
} else if (errCode == "EPROTONOSUPPORT") {
serverconsole.locerrmessage("Protocol not supported. The requested network protocol is not supported.");
} else if (errCode == "ETIMEDOUT") {
serverconsole.locerrmessage("Connection timed out. The server did not respond within the specified timeout period.");
} else {
serverconsole.locerrmessage("There was an unknown error with the server.");
}
serverconsole.locmessage(tries + " attempts left.");
}
if (msg == "\x12CRASH") process.exit(1);
if (msg == "\x12EADDRINUSE" || msg == "\x12EADDRNOTAVAIL" || msg == "\x12EACCES") process.exit(errors[msg.substr(1)]);
});
} else {
serverconsole.climessage(msg);
}
}
var messageTransmitted = false;
function listeningMessage() {
if (messageTransmitted) return;
messageTransmitted = true;
if (!cluster.isMaster && cluster.isMaster !== undefined) {
process.send("\x12LISTEN");
return;
}
serverconsole.locmessage("Started server at: ");
if (secure) {
if (typeof sport === "number") {
serverconsole.locmessage("* https://localhost" + (sport == 443 ? "" : (":" + sport)));
} else {
serverconsole.locmessage("* " + sport); //Unix socket or Windows named pipe
}
}
if (!(secure && disableNonEncryptedServer)) {
if (typeof port === "number") {
serverconsole.locmessage("* http://localhost" + (port == 80 ? "" : (":" + port)));
} else {
serverconsole.locmessage("* " + port); //Unix socket or Windows named pipe
}
}
if (host != "" && host != "[offline]") {
if (secure && typeof sport === "number") serverconsole.locmessage("* https://" + (host.indexOf(":") > -1 ? "[" + host + "]" : host) + (sport == 443 ? "" : (":" + sport)));
if (!(secure && disableNonEncryptedServer) && typeof port === "number") serverconsole.locmessage("* http://" + (host.indexOf(":") > -1 ? "[" + host + "]" : host) + (port == 80 ? "" : (":" + port)));
}
ipStatusCallback(function () {
if (pubip != "") {
if (secure) serverconsole.locmessage("* https://" + (pubip.indexOf(":") > -1 ? "[" + pubip + "]" : pubip) + (spubport == 443 ? "" : (":" + spubport)));
if (!(secure && disableNonEncryptedServer)) serverconsole.locmessage("* http://" + (pubip.indexOf(":") > -1 ? "[" + pubip + "]" : pubip) + (pubport == 80 ? "" : (":" + pubport)));
}
if (domain != "") {
if (secure) serverconsole.locmessage("* https://" + domain + (spubport == 443 ? "" : (":" + spubport)));
if (!(secure && disableNonEncryptedServer)) serverconsole.locmessage("* http://" + domain + (pubport == 80 ? "" : (":" + pubport)));
}
serverconsole.locmessage("For CLI help, you can type \"help\"");
});
}
var closedMaster = false;
function start(init) {
init = Boolean(init);
if (cluster.isMaster || cluster.isMaster === undefined) {
if (init) {
for (i = 0; i < logo.length; i++) console.log(logo[i]); //Print logo
console.log();
console.log("Welcome to DorianTech SVR.JS server.");
//Print warnings
if (version.indexOf("Nightly-") === 0) serverconsole.locwarnmessage("This version is only for test purposes and may be unstable.");
if (http2.__disabled__ !== undefined) serverconsole.locwarnmessage("HTTP/2 isn't supported by your Node.JS version! You may not be able to use HTTP/2 with SVR.JS");
if (configJSON.enableHTTP2 && !secure) serverconsole.locwarnmessage("HTTP/2 without HTTPS may not work in web browsers. Web browsers only support HTTP/2 with HTTPS!");
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.");
if (cluster.isMaster === 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 (process.getuid && process.getuid() == 0) serverconsole.locwarnmessage("You're running SVR.JS as root. It's recommended to run SVR.JS as an non-root user. Running SVR.JS as root may increase the risks of OS command execution vulnerabilities.");
if (secure && process.versions && process.versions.openssl && process.versions.openssl.substr(0, 2) == "1.") {
if (new Date() > new Date("11 September 2023")) {
serverconsole.locwarnmessage("OpenSSL 1.x is no longer recieving security updates after 11th September 2023. Your HTTPS communication might be vulnerable. It is recommended to update to a newer version of Node.JS that includes OpenSSL 3.0 or higher to ensure the security of your server and data.");
} else {
serverconsole.locwarnmessage("OpenSSL 1.x will no longer recieve security updates after 11th September 2023. Your HTTPS communication might be vulnerable in future. It is recommended to update to a newer version of Node.JS that includes OpenSSL 3.0 or higher to ensure the security of your server and data.");
}
}
if (secure && configJSON.enableOCSPStapling && ocsp._errored) serverconsole.locwarnmessage("Can't load OCSP module. OCSP stapling will be disabled. OCSP stapling is a security feature that improves the performance and security of HTTPS connections by caching the certificate status response. If you require this feature, consider updating your Node.JS version or checking for any issues with the 'ocsp' module.");
if (disableMods) serverconsole.locwarnmessage("SVR.JS is running without mods and server-side JavaScript enabled. Web applications may not work as expected");
console.log();
//Print info
serverconsole.locmessage("Server version: " + version);
if (process.isBun) serverconsole.locmessage("Bun version: v" + process.versions.bun);
else serverconsole.locmessage("Node.JS version: " + process.version);
var CPUs = os.cpus();
if (CPUs.length > 0) serverconsole.locmessage("CPU: " + (CPUs.length > 1 ? CPUs.length + "x " : "") + CPUs[0].model);
//Throw errors
if (vnum < 64) {
throw new Error("SVR.JS requires Node.JS 10.0.0 and newer, but your Node.JS version isn't supported by SVR.JS.");
}
if (configJSON.enableHTTP2 && !secure && (typeof port != "number")) {
throw new Error("HTTP/2 without HTTPS, along with Unix sockets/Windows named pipes aren't supported by SVR.JS.");
}
}
//Information about starting the server
if (!(secure && disableNonEncryptedServer)) serverconsole.locmessage("Starting HTTP server at " + (typeof port == "number" ? "localhost:" : "") + port.toString() + "...");
if (secure) serverconsole.locmessage("Starting HTTPS server at " + (typeof sport == "number" ? "localhost:" : "") + sport.toString() + "...");
}
if (!cluster.isMaster) {
if (secure) {
server.listen(sport);
if (!disableNonEncryptedServer) server2.listen(port);
} else {
server.listen(port);
}
}
//SVR.JS commmands
var commands = {
close: function () {
try {
server.close();
if (secure && !disableNonEncryptedServer) {
server2.close();
}
if (cluster.isMaster === undefined) serverconsole.climessage("Server closed.");
else {
process.send("Server closed.");
process.send("\x12CLOSE");
}
} catch (ex) {
if (cluster.isMaster === undefined) serverconsole.climessage("Cannot close server! Reason: " + ex.message);
else process.send("Cannot close server! Reason: " + ex.message);
}
},
open: function () {
try {
if (secure) {
server.listen(sport);
if (!disableNonEncryptedServer) server2.listen(port);
} else {
server.listen(port); // Reopen Server
}
if (cluster.isMaster === undefined) serverconsole.climessage("Server opened.");
else {
process.send("Server opened.");
process.send("\x12OPEN");
}
} catch (ex) {
if (cluster.isMaster === undefined) serverconsole.climessage("Cannot open server! Reason: " + ex.message);
else process.send("Cannot open server! Reason: " + ex.message);
}
},
help: function () {
if (cluster.isMaster === undefined) serverconsole.climessage("Server commands:\n" + Object.keys(commands).join(" "));
else process.send("Server commands:\n" + Object.keys(commands).join(" "));
},
mods: function () {
if (cluster.isMaster === undefined) serverconsole.climessage("Mods:");
else process.send("Mods:");
for (var i = 0; i < modInfos.length; i++) {
if (cluster.isMaster === undefined) serverconsole.climessage((i + 1).toString() + ". " + modInfos[i].name + " " + modInfos[i].version);
else process.send((i + 1).toString() + ". " + modInfos[i].name + " " + modInfos[i].version);
}
if (modInfos.length == 0) {
if (cluster.isMaster === undefined) serverconsole.climessage("No mods installed.");
else process.send("No mods installed.");
}
},
stop: function (retcode) {
reallyExiting = true;
if (typeof retcode == "number") {
process.exit(retcode);
} else {
process.exit(0);
}
},
clear: function () {
console.clear();
},
block: function (ip) {
if (ip == undefined || JSON.stringify(ip) == "[]") {
if (cluster.isMaster === undefined) serverconsole.climessage("Cannot block non-existent IP.");
else if (!cluster.isMaster) process.send("Cannot block non-existent IP.");
} else {
for (var i = 0; i < ip.length; i++) {
if (ip[i].indexOf(":") == -1) {
ip[i] = "::ffff:" + ip[i];
}
if (!blacklist.check(ip[i])) {
blacklist.add(ip[i]);
}
}
if (cluster.isMaster === undefined) serverconsole.climessage("IPs successfully blocked.");
else if (!cluster.isMaster) process.send("IPs successfully blocked.");
}
},
unblock: function (ip) {
if (ip == undefined || JSON.stringify(ip) == "[]") {
if (cluster.isMaster === undefined) serverconsole.climessage("Cannot unblock non-existent IP.");
else if (!cluster.isMaster) process.send("Cannot unblock non-existent IP.");
} else {
for (var i = 0; i < ip.length; i++) {
if (ip[i].indexOf(":") == -1) {
ip[i] = "::ffff:" + ip[i];
}
blacklist.remove(ip[i]);
}
if (cluster.isMaster === undefined) serverconsole.climessage("IPs successfully unblocked.");
else if (!cluster.isMaster) process.send("IPs successfully unblocked.");
}
},
restart: function () {
if (cluster.isMaster === undefined) serverconsole.climessage("This command is not supported on single-threaded SVR.JS.");
else process.send("This command need to be run in SVR.JS master.");
}
};
if (init) {
if (cluster.isMaster === undefined) {
setInterval(function () {
try {
saveConfig();
serverconsole.locmessage("Configuration saved.");
} catch (ex) {
throw new Error(ex);
}
}, 300000);
} else if (cluster.isMaster) {
setInterval(function () {
var allClusters = Object.keys(cluster.workers);
for (var i = 0; i < allClusters.length; i++) {
try {
if (cluster.workers[allClusters[i]]) {
cluster.workers[allClusters[i]].on("message", msgListener);
cluster.workers[allClusters[i]].send("\x14SAVECONF");
}
} catch (ex) {
if (cluster.workers[allClusters[i]]) {
cluster.workers[allClusters[i]].removeAllListeners("message");
cluster.workers[allClusters[i]].on("message", bruteForceListenerWrapper(cluster.workers[allClusters[i]]));
cluster.workers[allClusters[i]].on("message", listenConnListener);
}
serverconsole.locwarnmessage("There was a problem, while saving configuration file. Reason: " + ex.message);
}
}
}, 300000);
}
if (!cluster.isMaster && cluster.isMaster !== undefined) {
process.on("message", function (line) {
try {
if (line == "") {
//Does Nothing
process.send("\x12END");
} else if (line == "\x14SAVECONF") {
//Save configuration file
try {
saveConfig();
process.send("\x12SAVEGOOD");
} catch (ex) {
process.send("\x12SAVEERR" + ex.message);
}
process.send("\x12END");
} else if (commands[line.split(" ")[0]] !== undefined && commands[line.split(" ")[0]] !== null) {
var argss = line.split(" ");
var command = argss.shift();
commands[command](argss);
process.send("\x12END");
} else {
process.send("Unrecognized command \"" + line.split(" ")[0] + "\".");
process.send("\x12END");
}
} catch (ex) {
if (line != "") {
process.send("Can't execute command \"" + line.split(" ")[0] + "\".");
process.send("\x12END");
}
}
});
} else {
var rla = readline.createInterface({
input: process.stdin,
output: process.stdout,
prompt: ""
});
rla.prompt();
rla.on("line", function (line) {
line = line.trim();
var argss = line.split(" ");
var command = argss.shift();
if (line != "") {
if (cluster.isMaster !== undefined) {
var allClusters = Object.keys(cluster.workers);
if (command == "block") commands.block(argss);
if (command == "unblock") commands.unblock(argss);
if (command == "restart") {
var stopError = false;
exiting = true;
for (var i = 0; i < allClusters.length; i++) {
try {
if (cluster.workers[allClusters[i]]) {
cluster.workers[allClusters[i]].kill();
}
} catch (ex) {
stopError = true;
}
}
if (stopError) serverconsole.climessage("Some SVR.JS workers might not be stopped.");
SVRJSInitialized = false;
var cpus = os.cpus().length;
if (cpus > 16) cpus = 16;
try {
var useAvailableCores = Math.round((os.freemem()) / 50000000) - 1; //1 core deleted for safety...
if (cpus > useAvailableCores) cpus = useAvailableCores;
} catch (ex) {
//Nevermind... Don't want SVR.JS to fail starting, because os.freemem function is not working.
}
if (cpus < 1) cpus = 1; //If SVR.JS is run on Haiku or if useAvailableCores = 0
for (var i = 0; i < cpus; i++) {
if (i == 0) {
SVRJSFork();
} else {
setTimeout((function (i) {
return function () {
SVRJSFork();
if (i >= cpus - 1) {
SVRJSInitialized = true;
exiting = false;
serverconsole.climessage("SVR.JS workers restarted.");
}
};
})(i), i * 6.6);
}
}
return;
}
if (command == "stop") {
exiting = true;
allClusters = Object.keys(cluster.workers);
}
for (var i = 0; i < allClusters.length; i++) {
try {
if (cluster.workers[allClusters[i]]) {
cluster.workers[allClusters[i]].on("message", msgListener);
cluster.workers[allClusters[i]].send(line);
}
} catch (ex) {
if (cluster.workers[allClusters[i]]) {
cluster.workers[allClusters[i]].removeAllListeners("message");
cluster.workers[allClusters[i]].on("message", bruteForceListenerWrapper(cluster.workers[allClusters[i]]));
cluster.workers[allClusters[i]].on("message", listenConnListener);
}
serverconsole.climessage("Can't run command \"" + command + "\".");
}
}
if (command == "stop") {
setTimeout(function () {
reallyExiting = true;
process.exit(0);
}, 50);
}
} else {
if (command == "stop") {
reallyExiting = true;
process.exit(0);
}
try {
commands[command](argss);
} catch (ex) {
serverconsole.climessage("Unrecognized command \"" + command + "\".");
}
}
}
rla.prompt();
});
}
if (cluster.isMaster || cluster.isMaster === undefined) {
//Cluster forking code
if (cluster.isMaster !== undefined && init) {
var cpus = os.cpus().length;
if (cpus > 16) cpus = 16;
try {
var useAvailableCores = Math.round((os.freemem()) / 50000000) - 1; //1 core deleted for safety...
if (cpus > useAvailableCores) cpus = useAvailableCores;
} catch (ex) {
//Nevermind... Don't want SVR.JS to fail starting, because os.freemem function is not working.
}
if (cpus < 1) cpus = 1; //If SVR.JS is run on Haiku (os.cpus in Haiku returns empty array) or if useAvailableCores = 0
for (var i = 0; i < cpus; i++) {
if (i == 0) {
SVRJSFork();
} else {
setTimeout((function (i) {
return function () {
SVRJSFork();
if (i >= cpus - 1) SVRJSInitialized = true;
};
})(i), i * 6.6);
}
}
cluster.workers[Object.keys(cluster.workers)[0]].on("message", function (msg) {
if (msg.length > 9 && msg.indexOf("\x12ERRLIST") == 0) {
var tries = parseInt(msg.substr(8, 1));
var errCode = msg.substr(9);
if (errCode == "EADDRINUSE") {
serverconsole.locerrmessage("Address is already in use by another process.");
} else if (errCode == "EADDRNOTAVAIL") {
serverconsole.locerrmessage("Address is not available on this machine.");
} else if (errCode == "EACCES") {
serverconsole.locerrmessage("Permission denied. You may not have sufficient privileges to access the requested address.");
} else if (errCode == "EAFNOSUPPORT") {
serverconsole.locerrmessage("Address family not supported. The address family (IPv4 or IPv6) of the requested address is not supported.");
} else if (errCode == "EALREADY") {
serverconsole.locerrmessage("Operation already in progress. The server is already in the process of establishing a connection on the requested address.");
} else if (errCode == "ECONNABORTED") {
serverconsole.locerrmessage("Connection aborted. The connection to the server was terminated abruptly.");
} else if (errCode == "ECONNREFUSED") {
serverconsole.locerrmessage("Connection refused. The server refused the connection attempt.");
} else if (errCode == "ECONNRESET") {
serverconsole.locerrmessage("Connection reset by peer. The connection to the server was reset by the remote host.");
} else if (errCode == "EDESTADDRREQ") {
serverconsole.locerrmessage("Destination address required. The destination address must be specified.");
} else if (errCode == "ENETDOWN") {
serverconsole.locerrmessage("Network is down. The network interface used for the connection is not available.");
} else if (errCode == "ENETUNREACH") {
serverconsole.locerrmessage("Network is unreachable. The network destination is not reachable from this host.");
} else if (errCode == "ENOBUFS") {
serverconsole.locerrmessage("No buffer space available. Insufficient buffer space is available for the server to process the request.");
} else if (errCode == "ENOTSOCK") {
serverconsole.locerrmessage("Not a socket. The file descriptor provided is not a valid socket.");
} else if (errCode == "EPROTO") {
serverconsole.locerrmessage("Protocol error. An unspecified protocol error occurred.");
} else if (errCode == "EPROTONOSUPPORT") {
serverconsole.locerrmessage("Protocol not supported. The requested network protocol is not supported.");
} else if (errCode == "ETIMEDOUT") {
serverconsole.locerrmessage("Connection timed out. The server did not respond within the specified timeout period.");
} else {
serverconsole.locerrmessage("There was an unknown error with the server.");
}
serverconsole.locmessage(tries + " attempts left.");
}
if (msg == "\x12CRASH") process.exit(1);
if (msg == "\x12EADDRINUSE" || msg == "\x12EADDRNOTAVAIL" || msg == "\x12EACCES") process.exit(errors[msg.substr(1)]);
});
setInterval(function () {
if (!closedMaster && !exiting) {
var chksocket = {};
if (secure && disableNonEncryptedServer) {
chksocket = https.get({
port: (typeof sport == "number") ? sport : undefined,
socketPath: (typeof sport == "number") ? undefined : sport,
headers: {
"X-SVR-JS-From-Main-Thread": "true",
"User-Agent": (exposeServerVersion ? "SVR.JS/" + version + " (" + getOS() + "; " + (process.isBun ? ("Bun/v" + process.versions.bun + "; like Node.JS/" + process.version) : ("Node.JS/" + process.version)) + ")" : "SVR.JS")
},
timeout: 2000,
rejectUnauthorized: false
}, function (res) {
chksocket.removeAllListeners("timeout");
res.destroy();
res.on("data", function () {});
res.on("end", function () {});
crashed = false;
}).on("error", function () {
if (!exiting) {
if (!crashed) SVRJSFork();
else crashed = false;
}
}).on("timeout", function () {
if (!exiting) SVRJSFork();
crashed = true;
});
} else if ((configJSON.enableHTTP2 == undefined ? false : configJSON.enableHTTP2) && !secure) {
//It doesn't support through Unix sockets or Windows named pipes
var connection = http2.connect("http://localhost:" + port.toString());
connection.on("error", function () {
if (!exiting) {
if (!crashed) SVRJSFork();
else crashed = false;
}
});
connection.setTimeout(2000, function () {
if (!exiting) SVRJSFork();
crashed = true;
});
chksocket = connection.request({
":path": "/",
"x-svr-js-from-main-thread": "true",
"user-agent": (exposeServerVersion ? "SVR.JS/" + version + " (" + getOS() + "; " + (process.isBun ? ("Bun/v" + process.versions.bun + "; like Node.JS/" + process.version) : ("Node.JS/" + process.version)) + ")" : "SVR.JS")
});
chksocket.on("response", function () {
connection.close();
crashed = false;
});
chksocket.on("error", function () {
if (!exiting) {
if (!crashed) SVRJSFork();
else crashed = false;
}
});
} else {
chksocket = http.get({
port: (typeof port == "number") ? port : undefined,
socketPath: (typeof port == "number") ? undefined : port,
headers: {
"X-SVR-JS-From-Main-Thread": "true",
"User-Agent": (exposeServerVersion ? "SVR.JS/" + version + " (" + getOS() + "; " + (process.isBun ? ("Bun/v" + process.versions.bun + "; like Node.JS/" + process.version) : ("Node.JS/" + process.version)) + ")" : "SVR.JS")
},
timeout: 2000
}, function (res) {
chksocket.removeAllListeners("timeout");
res.destroy();
res.on("data", function () {});
res.on("end", function () {});
crashed = false;
}).on("error", function () {
if (!exiting) {
if (!crashed) SVRJSFork();
else crashed = false;
}
}).on("timeout", function () {
if (!exiting) SVRJSFork();
crashed = true;
});
}
}
}, 5000);
}
}
}
}
//Save configuration file
function saveConfig() {
for (var i = 0; i < 3; i++) {
try {
var configJSONobj = {};
if (fs.existsSync(__dirname + "/config.json")) configJSONobj = JSON.parse(fs.readFileSync(__dirname + "/config.json").toString());
if (configJSONobj.users === undefined) configJSONobj.users = [];
if (secure) {
if (configJSONobj.key === undefined) configJSONobj.key = "cert/key.key";
if (configJSONobj.cert === undefined) configJSONobj.cert = "cert/cert.crt";
if (configJSONobj.sport === undefined) configJSONobj.sport = 443;
if (configJSONobj.spubport === undefined) configJSONobj.spubport = 443;
if (configJSONobj.sni === undefined) configJSONobj.sni = {};
if (configJSONobj.enableOCSPStapling === undefined) configJSONobj.enableOCSPStapling = false;
}
if (configJSONobj.port === undefined) configJSONobj.port = 80;
if (configJSONobj.pubport === undefined) configJSONobj.pubport = 80;
if (configJSONobj.domain === undefined && configJSONobj.domian !== undefined) configJSONobj.domain = configJSONobj.domian;
delete configJSONobj.domian;
if (configJSONobj.page404 === undefined) configJSONobj.page404 = "404.html";
configJSONobj.timestamp = timestamp;
configJSONobj.blacklist = blacklist.raw;
if (configJSONobj.nonStandardCodes === undefined) configJSONobj.nonStandardCodes = [];
if (configJSONobj.enableCompression === undefined) configJSONobj.enableCompression = true;
if (configJSONobj.customHeaders === undefined) configJSONobj.customHeaders = {};
if (configJSONobj.enableHTTP2 === undefined) configJSONobj.enableHTTP2 = false;
if (configJSONobj.enableLogging === undefined) configJSONobj.enableLogging = true;
if (configJSONobj.enableDirectoryListing === undefined) configJSONobj.enableDirectoryListing = true;
if (configJSONobj.enableDirectoryListingWithDefaultHead === undefined) configJSONobj.enableDirectoryListingWithDefaultHead = false;
if (configJSONobj.serverAdministratorEmail === undefined) configJSONobj.serverAdministratorEmail = "[no contact information]";
if (configJSONobj.stackHidden === undefined) configJSONobj.stackHidden = false;
if (configJSONobj.enableRemoteLogBrowsing === undefined) configJSONobj.enableRemoteLogBrowsing = true;
if (configJSONobj.exposeServerVersion === undefined) configJSONobj.exposeServerVersion = true;
if (configJSONobj.disableServerSideScriptExpose === undefined) configJSONobj.disableServerSideScriptExpose = false;
if (configJSONobj.allowStatus === undefined) configJSONobj.allowStatus = true;
if (configJSONobj.rewriteMap === undefined) configJSONobj.rewriteMap = [];
if (configJSONobj.dontCompress === undefined) configJSONobj.dontCompress = [];
if (configJSONobj.enableIPSpoofing === undefined) configJSONobj.enableIPSpoofing = false;
if (configJSONobj.secure === undefined) configJSONobj.secure = false;
if (configJSONobj.disableNonEncryptedServer === undefined) configJSONobj.disableNonEncryptedServer = false;
if (configJSONobj.disableToHTTPSRedirect === undefined) configJSONobj.disableToHTTPSRedirect = false;
if (configJSONobj.enableETag === undefined) configJSONobj.enableETag = true;
var configString = JSON.stringify(configJSONobj, null, 2);
fs.writeFileSync(__dirname + "/config.json", configString);
break;
} catch (ex) {
if (i >= 2) throw ex;
var now = Date.now();
while (Date.now() - now < 2);
}
}
}
//Process event listeners
if (cluster.isMaster || cluster.isMaster === undefined) {
process.on("uncaughtException", function (ex) {
//CRASH HANDLER
serverconsole.locerrmessage("SVR.JS master process just crashed!!!");
serverconsole.locerrmessage("Stack:");
serverconsole.locerrmessage(generateErrorStack(ex));
process.exit(ex.errno);
});
process.on("unhandledRejection", function (ex) {
//CRASH HANDLER
serverconsole.locerrmessage("SVR.JS master process just crashed!!!");
serverconsole.locerrmessage("Stack:");
serverconsole.locerrmessage(ex.stack ? generateErrorStack(ex) : String(ex));
process.exit(ex.errno);
});
process.on("exit", function (code) {
try {
saveConfig();
} catch (ex) {
serverconsole.locwarnmessage("There was a problem, while saving configuration file. Reason: " + ex.message);
}
try {
deleteFolderRecursive(__dirname + "/temp");
} catch (ex) {
//Error!
}
try {
fs.mkdirSync(__dirname + "/temp");
} catch (ex) {
//Error!
}
if (process.isBun) {
try {
fs.writeFileSync(__dirname + "/temp/serverSideScript.js", "//Placeholder server-side JavaScript to workaround Bun bug.\r\n");
} catch (ex) {
//Error!
}
}
serverconsole.locmessage("Server closed with exit code: " + code);
});
process.on("warning", function (warning) {
serverconsole.locwarnmessage(warning.message);
if (generateErrorStack(warning)) {
serverconsole.locwarnmessage("Stack:");
serverconsole.locwarnmessage(generateErrorStack(warning));
}
});
process.on("SIGINT", function () {
reallyExiting = true;
if (cluster.isMaster !== undefined) {
exiting = true;
var allClusters = Object.keys(cluster.workers);
for (var i = 0; i < allClusters.length; i++) {
try {
if (cluster.workers[allClusters[i]]) {
cluster.workers[allClusters[i]].send("stop");
}
} catch (ex) {
//Worker will crash with EPIPE anyway.
}
}
}
serverconsole.locmessage("Server terminated using SIGINT");
process.exit();
});
} else {
process.on("uncaughtException", function (ex) {
//CRASH HANDLER
serverconsole.locerrmessage("SVR.JS worker just crashed!!!");
serverconsole.locerrmessage("Stack:");
serverconsole.locerrmessage(generateErrorStack(ex));
process.exit(ex.errno);
});
process.on("unhandledRejection", function (ex) {
//CRASH HANDLER
serverconsole.locerrmessage("SVR.JS worker just crashed!!!");
serverconsole.locerrmessage("Stack:");
serverconsole.locerrmessage(ex.stack ? generateErrorStack(ex) : String(ex));
process.exit(ex.errno);
});
process.on("warning", function (warning) {
serverconsole.locwarnmessage(warning.message);
if (warning.stack) {
serverconsole.locwarnmessage("Stack:");
serverconsole.locwarnmessage(generateErrorStack(warning));
}
});
}
//Call start
try {
start(true);
} catch (ex) {
serverconsole.locerrmessage("There was a problem starting SVR.JS!!!");
serverconsole.locerrmessage("Stack:");
serverconsole.locerrmessage(generateErrorStack(ex));
process.exit(ex.errno);
}
//////////////////////////////////
//// THE END! ////
//// WARNING: THE CODE HAS ////
//// 5000+ LINES! ////
//////////////////////////////////