From 5c67e6b7a6cbd23c9f6992ee60fb1e7be182a69a Mon Sep 17 00:00:00 2001 From: Dorian Niemiec Date: Tue, 1 Aug 2023 23:37:53 +0200 Subject: [PATCH] Replaced some blocking calls in favor of non-blocking ones and also formatted the code. --- index.js | 549 +++++++++++++++++++++++++++++++++++-------------------- mod.info | 2 +- 2 files changed, 350 insertions(+), 201 deletions(-) diff --git a/index.js b/index.js index 9e946d1..0aca650 100644 --- a/index.js +++ b/index.js @@ -9,23 +9,40 @@ var version = "UNKNOWN"; try { version = JSON.parse(fs.readFileSync(__dirname + "/mod.info")).version; } catch (ex) { - //Can"t determine version + // Can't determine version } -var configJSONS = JSON.parse(fs.readFileSync("config.json")); //Read configuration JSON +var configJSONS = JSON.parse(fs.readFileSync("config.json")); // Read configuration JSON + function Mod() {} -Mod.prototype.callback = function callback(req, res, serverconsole, responseEnd, href, ext, uobject, search, defaultpage, users, page404, head, foot, fd, elseCallback, configJSON, callServerError, getCustomHeaders, origHref, redirect, parsePostData) { + +Mod.prototype.callback = function (req, res, serverconsole, responseEnd, href, ext, uobject, search, defaultpage, users, page404, head, foot, fd, elseCallback, configJSON, callServerError, getCustomHeaders, origHref, redirect, parsePostData) { return function () { - if (!configJSON) configJSON = configJSONS; + if (!configJSON) { + configJSON = configJSONS; + } + if (!getCustomHeaders) { var bheaders = JSON.parse(JSON.stringify(configJSON.customHeaders)); } else { var bheaders = getCustomHeaders(); } - bheaders["Content-Type"] = "text/html" //HTML output - if (!getCustomHeaders) bheaders["Server"] = "SVR.JS/" + configJSON.version + " (" + os.platform()[0].toUpperCase() + os.platform().slice(1) + ")"; //Add Server header + + bheaders["Content-Type"] = "text/html"; // HTML output + + if (!getCustomHeaders) { + bheaders["Server"] = + "SVR.JS/" + + configJSON.version + + " (" + + os.platform()[0].toUpperCase() + + os.platform().slice(1) + + ")"; // Add Server header + } + var abheaders = JSON.parse(JSON.stringify(bheaders)); function executeCGI(fname, req, res, dh, nEnv) { + // Function to execute CGI scripts var env = JSON.parse(JSON.stringify(process.env)); var nEnvKeys = Object.keys(nEnv); for (var i = 0; i < nEnvKeys.length; i++) { @@ -44,162 +61,208 @@ Mod.prototype.callback = function callback(req, res, serverconsole, responseEnd, ".pyw": ["python"], ".rb": ["ruby"], ".php": ["php-cgi"] - } + }; var exttointerpreteruser = {}; - try { - exttointerpreteruser = JSON.parse(fs.readFileSync(__dirname + "/redbrick-interpreters.json")); - } catch (ex) {} - var script = fs.readFileSync(fname).toString(); - var fl = script.replace(/[\r\n]+/g, "\n").split("\n")[0]; - if (fl[0] == undefined) fl[0] = ""; - var ext = path.extname(fname); - var args = []; - var buffer = ""; - var stderr = ""; - var headerendline = -1; - var cned = false; - var tempID = "redbrick" + Math.round(Math.random() * 1000000).toString(16) + ext; - args.push(fname); - if (fl.indexOf("#!") == 0) { - if (os.platform() == "win32") { - args = fl.substr(2).split(" "); - var lns = script.split("\n"); - if (lns.length < 2) lns = script.split("\r"); - if (lns.length > 1) lns.shift(); - fs.writeFileSync(__dirname + "/../../../temp/" + tempID, lns.join(require("os").EOL)); - args.push(fname); - filename = args.shift(); - } else { - filename = (process.cwd() + (os.platform() == "win32" ? "\\" + fname.replace(/\//g, "\\") : "/" + fname)).replace(os.platform() == "win32" ? /\\+/ : /\/+/, os.platform() == "win32" ? "\\" : "/") - args = []; - } - } else if (fl.indexOf("\x7fELF") == 0 || fl.indexOf("MZ") == 0) { - filename = (process.cwd() + (os.platform() == "win32" ? "\\" + fname.replace(/\//g, "\\") : "/" + fname)).replace(os.platform() == "win32" ? /\\+/ : /\/+/, os.platform() == "win32" ? "\\" : "/") - args = []; - } else { - args = exttointerpreteruser[ext]; - if (!args) { - args = exttointerpreter[ext]; - if (!args) { - elseCallback(); - return; - } - } - args.push(fname); - filename = args.shift(); - } - - var wd = fname.split("/"); - wd[0] = ""; - wd[wd.length - 1] = ""; - wd = wd.join(os.platform() == "win32" ? "\\" : "/"); - var interpreter = childProcess.spawn(filename, args, { - cwd: (process.cwd() + wd).replace(os.platform() == "win32" ? /\\+/ : /\/+/, os.platform() == "win32" ? "\\" : "/"), - env: env - }); - interpreter.on("error", (error) => { - if (!callServerError) { - res.writeHead(500, { - "Content-Type": "text/html", - "Server": "RedBrick/" + version - }); - res.end("

RedBrick Error!

Reason: " + error.message + "

"); - } else { - callServerError(500, "RedBrick/" + version, error); - } - }); - var dataHandler = function (data) { - buffer += data.toString("latin1"); - var m = null; - if (!cned) m = buffer.match(/(?:\r\n\r\n|\n\n|\r\r)/); - if (!cned && m) { - cned = true; - eol = m[0]; - headerendline = m.index; - var bheaders = buffer.substr(0, headerendline).split(/(?:\r\n|\n|\r)/); - var bheaderso = {}; - if (dh) bheaderso = dh; - var code = 200; - var msg = "OK"; - if (bheaders[0].indexOf("HTTP/") == 0) { - var heada = bheaders.shift(); - code = heada.split(" ")[1]; - if (heada.split(" ")[2] !== undefined) msg = heada.split(" ").splice(2).join(" "); - } else if (bheaders[0].indexOf(":") == -1) { - var heada = bheaders.shift(); - code = heada.split(" ")[0]; - if (heada.split(" ")[1] !== undefined) msg = heada.split(" ").splice(1).join(" "); - } - for (var i = 0; i < bheaders.length; i++) { - var headerp = bheaders[i].split(": "); - var headern = headerp.shift(); - var headerv = headerp.join(": "); - if (headern.toLowerCase() == "status") { - code = headerv.split(" ")[0]; - if (headerv.split(" ")[1] !== undefined) msg = headerv.split(" ").splice(1).join(" "); - } else if (headern.toLowerCase() == "set-cookie") { - if (!bheaderso["Set-Cookie"]) bheaderso["Set-Cookie"] = []; - bheaderso["Set-Cookie"].push(headerv); - } else { - bheaderso[headern] = headerv; - } - } - - if (code == 200 && (bheaderso["Location"] || bheaderso["location"])) { - code = 302; - msg = "Found"; - } - + fs.readFile(__dirname + "/redbrick-interpreters.json", function (err, data) { + if (!err) { try { - res.writeHead(code, msg, bheaderso); - res.write(buffer.substr(headerendline + eol.length), "latin1"); - } catch (ex) { + exttointerpreteruser = JSON.parse(data.toString()); + } catch (ex) {} + } + fs.readFile(fname, function (err, data) { + if (err) { if (!callServerError) { - res.writeHead(500); - res.end(ex.stack); + res.writeHead(500, { + "Content-Type": "text/html", + "Server": "RedBrick/" + version + }); + res.end("

RedBrick Error!

Reason: " + err.message + "

"); + } else { - callServerError(500, "RedBrick/" + version, ex); + callServerError(500, "RedBrick/" + version, err); } return; } - } else { - if (cned && !res.finished) res.write(data); - } - } - if (interpreter.stdout) { - interpreter.stdout.on("data", dataHandler); - interpreter.stderr.on("data", function (data) { - stderr += data.toString() - }); - req.pipe(interpreter.stdin); - interpreter.on("exit", (code, signal) => { - if (!cned && (signal || code !== 0)) { - var ex = new Error("Process execution failed!" + (stderr ? " Reason: " + stderr.trim() : "")); - if (!callServerError) { - res.writeHead(500); - res.end(ex.stack); + var script = data.toString(); + var fl = script.replace(/[\r\n]+/g, "\n").split("\n")[0]; + if (fl[0] == undefined) fl[0] = ""; + var ext = path.extname(fname); + var args = []; + var buffer = ""; + var stderr = ""; + var headerendline = -1; + var cned = false; + var tempID = "redbrick" + Math.round(Math.random() * 1000000).toString(16) + ext; + args.push(fname); + if (fl.indexOf("#!") == 0) { + if (os.platform() == "win32") { + args = fl.substr(2).split(" "); + var lns = script.split("\n"); + if (lns.length < 2) lns = script.split("\r"); + if (lns.length > 1) lns.shift(); + try { + fs.writeFileSync(__dirname + "/../../../temp/" + tempID, lns.join(require("os").EOL)); + } catch (ex) { + res.writeHead(500, { + "Content-Type": "text/html", + "Server": "RedBrick/" + version + }); + res.end("

RedBrick Error!

Reason: " + ex.message + "

"); + return; + } + args.push(fname); + filename = args.shift(); } else { - callServerError(500, "RedBrick/" + version, ex); + filename = (process.cwd() + (os.platform() == "win32" ? "\\" + fname.replace(/\//g, "\\") : "/" + fname)).replace(os.platform() == "win32" ? /\\+/ : /\/+/, os.platform() == "win32" ? "\\" : "/"); + args = []; } + } else if (fl.indexOf("\x7fELF") == 0 || fl.indexOf("MZ") == 0) { + filename = (process.cwd() + (os.platform() == "win32" ? "\\" + fname.replace(/\//g, "\\") : "/" + fname)).replace(os.platform() == "win32" ? /\\+/ : /\/+/, os.platform() == "win32" ? "\\" : "/"); + args = []; } else { - res.end(); + args = exttointerpreteruser[ext]; + if (!args) { + args = exttointerpreter[ext]; + if (!args) { + elseCallback(); + return; + } + } + args.push(fname); + filename = args.shift(); + } + + var wd = fname.split("/"); + wd[0] = ""; + wd[wd.length - 1] = ""; + wd = wd.join(os.platform() == "win32" ? "\\" : "/"); + var interpreter = childProcess.spawn(filename, args, { + cwd: (process.cwd() + wd).replace(os.platform() == "win32" ? /\\+/ : /\/+/, os.platform() == "win32" ? "\\" : "/"), + env: env + }); + interpreter.on("error", (error) => { + if (!callServerError) { + res.writeHead(500, { + "Content-Type": "text/html", + "Server": "RedBrick/" + version + }); + res.end("

RedBrick Error!

Reason: " + error.message + "

"); + } else { + callServerError(500, "RedBrick/" + version, error); + } + }); + var dataHandler = function (data) { + buffer += data.toString("latin1"); + var m = null; + if (!cned) m = buffer.match(/(?:\r\n\r\n|\n\n|\r\r)/); + if (!cned && m) { + cned = true; + eol = m[0]; + headerendline = m.index; + var bheaders = buffer.substr(0, headerendline).split(/(?:\r\n|\n|\r)/); + var bheaderso = {}; + if (dh) bheaderso = dh; + var code = 200; + var msg = "OK"; + if (bheaders[0].indexOf("HTTP/") == 0) { + var heada = bheaders.shift(); + var hso = heada.split(" "); + code = hso[1]; + if (hso[2] !== undefined) msg = heada.split(" ").splice(2).join(" "); + } else if (bheaders[0].indexOf(":") == -1) { + var heada = bheaders.shift(); + var hso = heada.split(" "); + code = hso[0]; + if (hso[1] !== undefined) msg = heada.split(" ").splice(1).join(" "); + } + for (var i = 0; i < bheaders.length; i++) { + var headerp = bheaders[i].split(": "); + var headern = headerp.shift(); + var headerv = headerp.join(": "); + if (headern.toLowerCase() == "status") { + code = headerv.split(" ")[0]; + if (headerv.split(" ")[1] !== undefined) msg = headerv.split(" ").splice(1).join(" "); + } else if (headern.toLowerCase() == "set-cookie") { + if (!bheaderso["Set-Cookie"]) bheaderso["Set-Cookie"] = []; + bheaderso["Set-Cookie"].push(headerv); + } else { + bheaderso[headern] = headerv; + } + } + + if (code == 200 && (bheaderso["Location"] || bheaderso["location"])) { + code = 302; + msg = "Found"; + } + + try { + res.writeHead(code, msg, bheaderso); + res.write(buffer.substr(headerendline + eol.length), "latin1"); + } catch (ex) { + if (!callServerError) { + res.writeHead(500); + res.end(ex.stack); + } else { + callServerError(500, "RedBrick/" + version, ex); + } + return; + } + } else { + if (cned && !res.finished) res.write(data); + } + }; + if (interpreter.stdout) { + interpreter.stdout.on("data", dataHandler); + interpreter.stderr.on("data", function (data) { + stderr += data.toString(); + }); + req.pipe(interpreter.stdin); + interpreter.on("exit", (code, signal) => { + if (!cned && (signal || code !== 0)) { + var ex = new Error("Process execution failed!" + (stderr ? " Reason: " + stderr.trim() : "")); + if (!callServerError) { + res.writeHead(500); + res.end(ex.stack); + } else { + callServerError(500, "RedBrick/" + version, ex); + } + } else { + res.end(); + } + }); } }); - } + }); } function executeCGIWithEnv(a, b, req, res, pubip, port, software, dh) { + // Function to set up environment variables and execute CGI scripts var nEnv = {}; + if (req.headers.authorization) { + nEnv["AUTH_TYPE"] = req.headers.authorization.split(" ")[0]; + if (nEnv["AUTH_TYPE"] == "Basic") { + var remoteCred = req.headers.authorization.split(" ")[1]; + if (!remoteCred) { + nEnv["REMOTE_USER"] = "redbrick_cgi_invalid_user"; + } else { + var remoteCredDecoded = Buffer.from(remoteCred, "base64").toString("utf8"); + nEnv["REMOTE_USER"] = remoteCredDecoded.split(":")[0]; + } + } else { + nEnv["REMOTE_USER"] = "svrjs_this_property_is_not_yet_supported_by_redbrick_cgi"; + } + } nEnv["QUERY_STRING"] = req.url.split("?")[1]; if (nEnv["QUERY_STRING"] == undefined || nEnv["QUERY_STRING"] == "undefined") nEnv["QUERY_STRING"] = ""; nEnv["SERVER_SOFTWARE"] = software; nEnv["SERVER_PROTOCOL"] = "HTTP/" + req.httpVersion; nEnv["SERVER_PORT"] = port; nEnv["SERVER_ADDR"] = pubip.replace(/^::ffff:/i, ""); + if (nEnv["SERVER_ADDR"].indexOf(":") != -1) nEnv["SERVER_ADDR"] = "[" + nEnv["SERVER_ADDR"] + "]"; nEnv["SERVER_NAME"] = req.headers.host; nEnv["DOCUMENT_ROOT"] = process.cwd(); - nEnv["PATH_INFO"] = b; - nEnv["PATH_TRANSLATED"] = (process.cwd() + (require("os").platform == "win32" ? b.replace(/\//g, "\\") : b)).replace((require("os").platform == "win32" ? /\\\\/g : /\/\//g), (require("os").platform == "win32" ? "\\" : "/")); + nEnv["PATH_INFO"] = decodeURI(b); + nEnv["PATH_TRANSLATED"] = b ? decodeURI((process.cwd() + (require("os").platform == "win32" ? b.replace(/\//g, "\\") : b)).replace((require("os").platform == "win32" ? /\\\\/g : /\/\//g), (require("os").platform == "win32" ? "\\" : "/"))) : ""; nEnv["REQUEST_METHOD"] = req.method; nEnv["GATEWAY_INTERFACE"] = "CGI/1.1"; nEnv["REQUEST_URI"] = req.url; @@ -218,94 +281,180 @@ Mod.prototype.callback = function callback(req, res, serverconsole, responseEnd, } executeCGI("." + a, req, res, dh, nEnv); } + if (href.indexOf("/cgi-bin") == 0) { - try { - if (fs.existsSync("." + href)) { + fs.stat("." + href, function (err, stats) { + if (err && err.code == "ENOENT") { var invokeElseCallback = false; try { - invokeElseCallback = !fs.statSync("." + href).isFile(); + invokeElseCallback = stats.isFile(); } catch (ex) {} if (invokeElseCallback) { elseCallback(); } else { try { - try { - executeCGIWithEnv(href, "", req, res, req.socket.localAddress, req.socket.localPort, (getCustomHeaders ? (getCustomHeaders()["Server"] + " RedBrick/" + version) : ("SVR.JS/" + configJSON.version + " (" + os.platform()[0].toUpperCase() + os.platform().slice(1) + "; Node.JS/" + process.version + ") RedBrick/" + version)), bheaders); - } catch (ex) { - if (!callServerError) { - res.writeHead(500, "Internal Server Error", abheaders); - res.write("500 Internal Server Error

500 Internal Server Error

A server had unexcepted execption. Below, stack of the error is shown:

" + ex.stack.replace(/\r\n/g, "
").replace(/\n/g, "
").replace(/\r/g, "
").replace(/ /g, " ") + "

Please contact with developer/administrator of the website.

SVR.JS " + configJSON.version + " (" + os.platform()[0].toUpperCase() + os.platform().slice(1) + "; Node.JS/" + process.version + ") RedBrick/" + version + " " + (req.headers.host == undefined ? "" : " on " + req.headers.host) + "

"); - res.end(); - } else { - callServerError(500, "RedBrick/" + version, ex); - } - } - } catch (ex) { - if (!callServerError) { - res.writeHead(500); - res.end(ex.stack); - } else { - callServerError(500, "RedBrick/" + version, ex); - } - } - } - } else { - function checkPath(pth, a) { - var cpth = pth.split("/"); - if (cpth.length < 3) return false; - if (!a) b = []; - else var b = a.split("/"); - var isFile = false; - try { - isFile = fs.statSync(pth).isFile(); - } catch (ex) {} - if (fs.existsSync(pth) && isFile) { - return { - fpth: pth, - rpth: "/" + a - } - } else { - b.unshift(cpth.pop()); - return checkPath(cpth.join("/"), b.join("/")); - } - } - var pathp = checkPath("." + href); - if (pathp == false) { - elseCallback(); - } else { - try { - executeCGIWithEnv(pathp.fpth.substr(1), pathp.rpth, req, res, req.socket.localAddress, req.socket.localPort, (getCustomHeaders ? (getCustomHeaders()["Server"] + " RedBrick/" + version) : ("SVR.JS/" + configJSON.version + " (" + os.platform()[0].toUpperCase() + os.platform().slice(1) + "; Node.JS/" + process.version + ") RedBrick/" + version)), bheaders); + executeCGIWithEnv( + href, + "", + req, + res, + req.socket.localAddress, + req.socket.localPort, + getCustomHeaders ? + getCustomHeaders()["Server"] + + " RedBrick/" + + version : + "SVR.JS/" + + configJSON.version + + " (" + + os.platform()[0].toUpperCase() + + os.platform().slice(1) + + "; Node.JS/" + + process.version + + ") RedBrick/" + + version, + bheaders + ); } catch (ex) { if (!callServerError) { res.writeHead(500, "Internal Server Error", abheaders); - res.write("500 Internal Server Error

500 Internal Server Error

A server had unexcepted execption. Below, stack of the error is shown:

" + ex.stack.replace(/\r\n/g, "
").replace(/\n/g, "
").replace(/\r/g, "
").replace(/ /g, " ") + "

Please contact with developer/administrator of the website.

SVR.JS " + configJSON.version + " (" + os.platform()[0].toUpperCase() + os.platform().slice(1) + "; Node.JS/" + process.version + ") RedBrick/" + version + " " + (req.headers.host == undefined ? "" : " on " + req.headers.host) + "

"); + res.write( + "500 Internal Server Error

500 Internal Server Error

A server had unexpected exception. Below, the stack trace of the error is shown:

" + + ex.stack.replace(/\r\n/g, "
").replace(/\n/g, "
").replace(/\r/g, "
").replace(/ /g, " ") + + "

Please contact the developer/administrator of the website.

SVR.JS " + + configJSON.version + + " (" + + os.platform()[0].toUpperCase() + + os.platform().slice(1) + + "; Node.JS/" + + process.version + + ") RedBrick/" + + version + + " " + + (req.headers.host == undefined ? "" : " on " + req.headers.host) + + "

" + ); res.end(); } else { callServerError(500, "RedBrick/" + version, ex); } } } - } - } catch (ex) { - if (!callServerError) { - res.writeHead(500, "Internal Server Error", abheaders); - res.write("500 Internal Server Error

500 Internal Server Error

A server had unexcepted execption. Below, stack of the error is shown:

" + ex.stack.replace(/\r\n/g, "
").replace(/\n/g, "
").replace(/\r/g, "
").replace(/ /g, " ") + "

Please contact with developer/administrator of the website.

SVR.JS " + configJSON.version + " (" + os.platform()[0].toUpperCase() + os.platform().slice(1) + "; Node.JS/" + process.version + ") RedBrick/" + version + " " + (req.headers.host == undefined ? "" : " on " + req.headers.host) + "

"); - res.end(); + } else if (!err || (err && err.code == "ENOTDIR")) { + function checkPath(pth, cb, a) { + // Function to check the path of the file and execute CGI script + var cpth = pth.split("/"); + if (cpth.length < 3) { + cb(false); + return; + } + if (!a) b = []; + else var b = a.split("/"); + var isFile = false; + fs.stat(pth, function (err, stats) { + if (!err && stats.isFile()) { + cb({ + fpth: pth, + rpth: (a !== undefined ? "/" + a : "") + }) + } else { + b.unshift(cpth.pop()); + return checkPath(cpth.join("/"), cb, b.join("/")); + } + }); + } + checkPath("." + href, function (pathp) { + if (!pathp) { + elseCallback(); + } else { + try { + executeCGIWithEnv( + pathp.fpth.substr(1), + pathp.rpth, + req, + res, + req.socket.localAddress, + req.socket.localPort, + getCustomHeaders ? + getCustomHeaders()["Server"] + + " RedBrick/" + + version : + "SVR.JS/" + + configJSON.version + + " (" + + os.platform()[0].toUpperCase() + + os.platform().slice(1) + + "; Node.JS/" + + process.version + + ") RedBrick/" + + version, + bheaders + ); + } catch (ex) { + if (!callServerError) { + res.writeHead(500, "Internal Server Error", abheaders); + res.write( + "500 Internal Server Error

500 Internal Server Error

A server had unexpected exception. Below, the stack trace of the error is shown:

" + + ex.stack.replace(/\r\n/g, "
").replace(/\n/g, "
").replace(/\r/g, "
").replace(/ /g, " ") + + "

Please contact the developer/administrator of the website.

SVR.JS " + + configJSON.version + + " (" + + os.platform()[0].toUpperCase() + + os.platform().slice(1) + + "; Node.JS/" + + process.version + + ") RedBrick/" + + version + + " " + + (req.headers.host == undefined ? "" : " on " + req.headers.host) + + "

" + ); + res.end(); + } else { + callServerError(500, "RedBrick/" + version, ex); + } + } + } + }); } else { - callServerError(500, "RedBrick/" + version, ex); + if (!callServerError) { + res.writeHead(500, "Internal Server Error", abheaders); + res.write( + "500 Internal Server Error

500 Internal Server Error

A server had unexpected exception. Below, the stack trace of the error is shown:

" + + err.stack.replace(/\r\n/g, "
").replace(/\n/g, "
").replace(/\r/g, "
").replace(/ /g, " ") + + "

Please contact the developer/administrator of the website.

SVR.JS " + + configJSON.version + + " (" + + os.platform()[0].toUpperCase() + + os.platform().slice(1) + + "; Node.JS/" + + process.version + + ") RedBrick/" + + version + + " " + + (req.headers.host == undefined ? "" : " on " + req.headers.host) + + "

" + ); + res.end(); + } else { + callServerError(500, "RedBrick/" + version, err); + } } - } + }); } else if (href == "/redbrick-interpreters.json" && path.normalize(__dirname + "/../../..") == process.cwd()) { if (!callServerError) { - res.writeHead(403, "Forbidden", abheaders); - res.write("403 Forbidden

403 Forbidden

You don't have access to specific page.

SVR.JS " + configJSON.version + " (" + os.platform()[0].toUpperCase() + os.platform().slice(1) + "; Node.JS/" + process.version + ") RedBrick/" + version + " " + (req.headers.host == undefined ? "" : " on " + req.headers.host) + "

"); - res.end(); + res.writeHead(200, "OK", { + "Content-Type": "application/json", + "Server": "RedBrick/" + version + }); + res.end(JSON.stringify(exttointerpreteruser, null, 2)); } else { - callServerError(403, "RedBrick/" + version); + callServerError(200, "RedBrick/" + version, exttointerpreteruser); } } else { elseCallback(); } } } + module.exports = Mod; diff --git a/mod.info b/mod.info index 38a2bf6..03e333a 100755 --- a/mod.info +++ b/mod.info @@ -1,4 +1,4 @@ { "name": "DorianTech RedBrick CGI engine for SVR.JS", - "version": "2.1.1" + "version": "2.2.0" }