var https = require("https"); var os = require("os"); var http = require("http"); var url = require("url"); var fs = require("fs"); var path = require("path"); var net = require("net"); var stream = require("stream"); var EventEmitter = require("events"); var version = "UNKNOWN"; try { version = JSON.parse(fs.readFileSync(__dirname + "/mod.info")).version; } catch (ex) { // Can't determine version } var configJSONS = {}; try { configJSONS = JSON.parse(fs.readFileSync(__dirname + "/../../../config.json")); // Read configuration JSON } catch (ex) { //GreenRhombus will not care about configJSONS in SVR.JS 3.x and newer //SVR.JS 2.x and older will fail to start with broken configuration file anyway... } var fastcgiConf = {}; try { fastcgiConf = JSON.parse(fs.readFileSync(__dirname + "/../../../greenrhombus-config.json")); } catch (ex) { // Use defaults } var scriptExts = []; try { scriptExts = JSON.parse(fs.readFileSync(__dirname + "/../../../greenrhombus-scriptexts.json")); } catch (ex) { } function createFastCGIHandler(options) { var requestID = options.requestID; if (!requestID) requestID = 1; var BEGIN_REQUEST = 1; var ABORT_REQUEST = 2; var END_REQUEST = 3; var PARAMS = 4; var STDIN = 5; var STDOUT = 6; var STDERR = 7; var DATA = 8; var GET_VALUES = 9; var GET_VALUES_RESULT = 10; var UNKNOWN_TYPE = 11; var RESPONDER = 1; var AUTHORIZER = 2; var FILTER = 3; // Response codes var REQUEST_COMPLETE = 0; var CANT_MPX_CONN = 1; var OVERLOADED = 2; var UNKNOWN_ROLE = 3; function buildFastCGIPacket(type, requestID, content) { var packet = Buffer.alloc(content.length + (content.length % 8) + 8); packet.writeUInt8(1, 0); //version packet.writeUInt8(type, 1); //type packet.writeUInt16BE(requestID, 2); //requestId packet.writeUInt16BE(content.length, 4); //contentLength packet.writeUInt8(content.length % 8, 6); //paddingLength packet.writeUInt8(0, 7); //reserved Buffer.from(content).copy(packet, 8); //content return packet; } function parseFastCGIPacket(packet) { var data = {}; data.fcgiVersion = packet.readUInt8(0); //version data.type = packet.readUInt8(1); //type data.requestID = packet.readUInt16BE(2); //requestId data.content = packet.subarray(8, 8 + packet.readUInt16BE(4)); //contentLength return data; } function writeFastCGIPacket(socket, type, requestID, content) { if (content.length != 0) { var contentSlices = Math.ceil(content.length / 65535); var chunk = {}; for (var i = 0; i < contentSlices; i++) { var chunkOffset = 65536 * i; var chunkSize = Math.min(65535, content.length - chunkOffset); chunk = Buffer.alloc(chunkSize); content.copy(chunk, 0, chunkOffset, chunkOffset + chunkSize); socket.write(buildFastCGIPacket(type, requestID, chunk)); } } else { socket.write(buildFastCGIPacket(type, requestID, Buffer.alloc(0))); } } function buildNameValuePair(name, value) { if (typeof name == "undefined" || typeof value == "undefined") return Buffer.alloc(0); name = String(name); value = String(value); var nameLength = name.length; var valueLength = value.length; var nameLengthBytes = nameLength > 127 ? 4 : 1; var valueLengthBytes = valueLength > 127 ? 4 : 1; var pair = Buffer.alloc(nameLength + valueLength + nameLengthBytes + valueLengthBytes); //nameLength if (nameLengthBytes == 4) { pair.writeUInt32BE(Math.min(0xFFFFFFFF, 0x80000000 + nameLength), 0); } else { pair.writeUInt8(nameLength, 0); } //valueLength if (valueLengthBytes == 4) { pair.writeUInt32BE(Math.min(0xFFFFFFFF, 0x80000000 + valueLength), nameLengthBytes); } else { pair.writeUInt8(valueLength, nameLengthBytes); } Buffer.from(name).copy(pair, nameLengthBytes + valueLengthBytes); //nameData Buffer.from(value).copy(pair, nameLengthBytes + valueLengthBytes + nameLength); //valueData return pair; } function fastCGISocketHandler(chunk) { var chunkIndex = 0; while (chunkIndex < chunk.length || (headerIndex == 8 && bodyIndex == packetBody.length && paddingLength == 0)) { if (headerIndex < 8) { chunk.copy(packetHeader, headerIndex, chunkIndex, Math.min(chunk.length, chunkIndex + 8 - headerIndex)); var ic = Math.min(chunk.length - chunkIndex, 8 - headerIndex); headerIndex += ic; chunkIndex += ic; if (headerIndex == 8) { packetBody = Buffer.alloc(packetHeader.readUInt16BE(4)); paddingLength = packetHeader.readUInt8(6); } } else if (headerIndex == 8 && bodyIndex < packetBody.length) { chunk.copy(packetBody, bodyIndex, chunkIndex, Math.min(chunk.length, chunkIndex + packetBody.length - bodyIndex)); var ic = Math.min(chunk.length - chunkIndex, packetBody.length - bodyIndex); bodyIndex += ic; chunkIndex += ic; } else if (headerIndex == 8 && bodyIndex == packetBody.length && paddingIndex <= paddingLength) { var ic = Math.min(chunk.length - chunkIndex, paddingLength - paddingIndex); paddingIndex += ic; chunkIndex += ic; if (paddingIndex == paddingLength) { headerIndex = 0; bodyIndex = 0; paddingIndex = 0; var packet = Buffer.alloc(8 + packetBody.length + paddingLength); packetHeader.copy(packet); packetBody.copy(packet, 8); processFastCGIPacket(packet); } } } } function processFastCGIPacket(packet) { var processedPacket = parseFastCGIPacket(packet); if (processedPacket.requestID != requestID) return; //Drop the packet if (processedPacket.type == STDOUT) { try { if(processedPacket.content.length > 0) stdoutPush(processedPacket.content); } catch (err) { //STDOUT will be lost instead of crashing the server } } else if (processedPacket.type == STDERR) { try { if(processedPacket.content.length > 0) emulatedStderr.push(processedPacket.content); } catch (err) { //STDERR will be lost anyway... } } else if (processedPacket.type == END_REQUEST && processedPacket.content.length > 5) { if (typeof socket !== "undefined") { socket.removeListener("data", fastCGISocketHandler); processFastCGIPacket = function() {}; try { socket.end(); //Fixes connection not closing properly in Bun } catch (err) { //It is already closed } } var appStatus = processedPacket.content.readUInt32BE(0); var protocolStatus = processedPacket.content.readUInt8(4); if (protocolStatus != REQUEST_COMPLETE) { var err = new Error("Unknown error"); if (protocolStatus == OVERLOADED) { err = new Error("FastCGI server overloaded"); err.code = "EMFILE"; err.errno = 24; } else if (protocolStatus == UNKNOWN_ROLE) { err = new Error("Role not supported by the FastCGI application"); } else if (protocolStatus == CANT_MPX_CONN) { err = new Error("Multiplexed connections not supported by the FastCGI application"); } stdoutPush(null); if (emulatedStdout._readableState && emulatedStdout._readableState.flowing !== null && !emulatedStdout.endEmitted) { emulatedStdout.on("end", function() { emulatedStderr.push(null); eventEmitter.emit("error", err); }); } else { emulatedStderr.push(null); eventEmitter.emit("error", err); } } else { stdoutPush(null); if (emulatedStdout._readableState && emulatedStdout._readableState.flowing !== null && !emulatedStdout.endEmitted) { emulatedStdout.on("end", function() { emulatedStderr.push(null); eventEmitter.emit("exit", appStatus, null); }); } else { emulatedStderr.push(null); eventEmitter.emit("exit", appStatus, null); } } } } var eventEmitter = new EventEmitter(); var packetHeader = Buffer.alloc(8); var packetBody = {}; var paddingLength = 0; var headerIndex = 0; var bodyIndex = 0; var paddingIndex = 0; var emulatedStdin = new stream.Writable({ write: function (chunk, encoding, callback) { try { if (chunk.length != 0) { writeFastCGIPacket(socket, STDIN, requestID, chunk); } callback(null); } catch (err) { callback(err); } }, final: function (callback) { try { writeFastCGIPacket(socket, STDIN, requestID, Buffer.alloc(0)); } catch (err) { //writing failed } callback(); } }); function stdoutPush(data) { if(data === null) { stdoutToEnd = true; } else { stdoutBuffer = Buffer.concat([stdoutBuffer, Buffer.from(data)]); } var hpLength = hp.length; for(var i = 0; i < hpLength; i++) { var func = hp.shift(); if(func) func(); } emulatedStdout.resume(); } var zeroed = false; var stdoutBuffer = Buffer.alloc(0); var stdoutToEnd = false; var hp = []; var emulatedStdout = new stream.Readable({ read: function (n) { var s = this; var handler = function () { if (stdoutBuffer.length == 0) { if (!stdoutToEnd) { hp.push(handler); s.pause(); } else { s.push(null); } } else { var bytesToPush = Math.min(stdoutBuffer.length, n); var bufferToPush = stdoutBuffer.subarray(0, bytesToPush); stdoutBuffer = stdoutBuffer.subarray(bytesToPush); s.push(bufferToPush); if (stdoutBuffer.length == 0 && !stdoutToEnd) s.pause(); } }; if (n != 0) handler(); } }); emulatedStdout.pause(); //Reduce backpressure var emulatedStderr = new stream.Readable({ read: function () {} }); function init() { //Begin the request var beginPacket = Buffer.alloc(8); beginPacket.writeUInt16BE(RESPONDER, 0); //FastCGI responder beginPacket.writeUInt8(0, 2); //Don't keep alive writeFastCGIPacket(socket, BEGIN_REQUEST, requestID, beginPacket); //Environment variables var envPacket = Buffer.alloc(0); Object.keys(options.env).forEach(function (key) { envPacket = Buffer.concat([envPacket, buildNameValuePair(key, options.env[key])]); }); if(envPacket.length > 0) writeFastCGIPacket(socket, PARAMS, requestID, envPacket); writeFastCGIPacket(socket, PARAMS, requestID, Buffer.alloc(0)); } eventEmitter.stdin = emulatedStdin; eventEmitter.stdout = emulatedStdout; eventEmitter.stderr = emulatedStderr; eventEmitter.init = init; //Create socket var socket = net.createConnection(options, function () { eventEmitter.emit("connect"); }).on("error", function (err) { stdoutPush(null); emulatedStderr.push(null); eventEmitter.removeAllListeners("exit"); eventEmitter.emit("error", err); }).on("data", fastCGISocketHandler); eventEmitter.socket = socket; return eventEmitter; } // Load default configuration if (fastcgiConf.path !== undefined) fastcgiConf.path = fastcgiConf.path.replace(/([^\/])\/+$/, "$1"); if (fastcgiConf.socketPath === undefined) { if (fastcgiConf.host === undefined) fastcgiConf.host = "localhost"; if (fastcgiConf.port === undefined) fastcgiConf.port = 4000; } var disableModExposeSupported = process.versions.svrjs && process.versions.svrjs.match(/^(?:Nightly-|(?:[4-9]|[123][0-9])[0-9]*\.|3\.(?:[1-9][0-9]+\.|9\.(?:[1-9])|4\.(?:(?:[3-9]|[12][0-9])[0-9]+|29)))/i); function Mod() {} 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, authUser) { return function () { if (!configJSON) { configJSON = configJSONS; } function checkIfThereIsA401Rule() { var actually401 = false; function createRegex(regex) { var regexObj = regex.split("/"); if (regexObj.length == 0) throw new Error("Invalid regex!"); var modifiers = regexObj.pop(); regexObj.shift(); var searchString = regexObj.join("/"); return new RegExp(searchString, modifiers); } if (configJSON.nonStandardCodes) { configJSON.nonStandardCodes.every(function (nonscode) { if (nonscode.scode == 401) { if (nonscode.regex && (req.url.match(createRegex(nonscode.regex)) || href.match(createRegex(nonscode.regex)))) { actually401 = true; return true; } else if (nonscode.url && (nonStandardCodes[i].url == href || (os.platform() == "win32" && nonStandardCodes[i].url.toLowerCase() == href.toLowerCase()))) { actually401 = true; return true; } } return false; }); } return actually401; } 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 } var abheaders = JSON.parse(JSON.stringify(bheaders)); var socket = {}; function executeFastCGI(req, res, dh, nEnv) { // Function to execute FastCGI scripts var env = JSON.parse(JSON.stringify(process.env)); var nEnvKeys = Object.keys(nEnv); for (var i = 0; i < nEnvKeys.length; i++) { env[nEnvKeys[i]] = nEnv[nEnvKeys[i]]; } var buffer = ""; var stderr = ""; var headerendline = -1; var cned = false; var dataHandler = function (data) { if (!cned) buffer += data.toString("latin1"); var m = null; if (!cned) m = buffer.match(/(?:\r\n\r\n|\n\r\n\r|\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|\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(" "); if (hso[0].match(/^[0-9]{3}$/)) { code = hso[0]; if (hso[1] !== undefined) msg = heada.split(" ").splice(1).join(" "); } } var hasLocation = false; 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 { if (headern.toLowerCase() == "location") hasLocation = true; bheaderso[headern] = headerv; } } if ((code < 300 || code > 399) && hasLocation) { code = 302; msg = "Found"; } try { res.writeHead(code, msg, bheaderso); res.write(Buffer.from(buffer.substr(headerendline + eol.length), "latin1")); } catch (ex) { handler.removeAllListeners("exit"); handler.stdout.removeAllListeners("data"); if (!callServerError) { res.writeHead(500); res.end(ex.stack); } else { callServerError(500, "GreenRhombus/" + version, ex); } return; } } else { if (cned && !res.finished) { res.write(data); handler.stdout.removeListener("data", dataHandler); handler.stdout.pipe(res, { end: false }); dataHandler = function () {}; //Prevent event listener memory leaks } } }; var options = { host: fastcgiConf.host, port: fastcgiConf.port, path: fastcgiConf.socketPath, env: env }; var handler = createFastCGIHandler(options); handler.on("error", function (error) { var errorcode = 0; if (error.code == "ENOTFOUND" || error.code == "EHOSTUNREACH" || error.code == "ECONNREFUSED") { errorcode = 503; } else if (error.code == "EMFILE") { errorcode = 429; } else { errorcode = 500; } if (!callServerError) { res.writeHead(errorcode, { "Content-Type": "text/html", "Server": "GreenRhombus/" + version }); res.end("
Reason: " + error.message + "
"); } else { callServerError(errorcode, "GreenRhombus/" + version, error); } }); res.prependListener("close", function() { if(handler.stdout) handler.stdout.unpipe(res); //Prevent server crashes with write after the end }); res.on("error", function() {}); //Suppress response stream errors function handlerConnection() { handler.stdout.on("data", dataHandler); handler.stderr.on("data", function (data) { stderr += data.toString(); }); handler.init(); req.pipe(handler.stdin); handler.on("exit", function (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, "GreenRhombus/" + version, ex); } } else { var preparedStderr = stderr.trim(); if (preparedStderr) { serverconsole.errmessage("There were FastCGI application errors:"); serverconsole.errmessage(preparedStderr); } handler.stdout.removeListener("data", dataHandler); handler.stdout.unpipe(res); //Prevent server crashes with write after the end if(!res.finished) res.end(); } }); } if(typeof handler.socket.connecting == "undefined" || handler.socket.connecting) handler.on("connect", handlerConnection); else if(!handler.socket.destroyed) handlerConnection(); } function executeFastCGIWithEnv(a, b, req, res, pubip, port, software, dh, user, cPath) { // Function to set up environment variables and execute sCGI scripts var nEnv = {}; if (typeof user != "undefined") { if (user !== null) { if (req.headers.authorization) nEnv["AUTH_TYPE"] = req.headers.authorization.split(" ")[0]; nEnv["REMOTE_USER"] = user; } } else if (req.headers.authorization && (typeof checkIfThereIsA401Rule == "undefined" || checkIfThereIsA401Rule())) { 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"] = "greenrhombus_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_greenrhombus_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; if (pubip && (port !== null && port !== undefined)) { nEnv["SERVER_PORT"] = port; nEnv["SERVER_ADDR"] = pubip.replace(/^::ffff:/i, ""); if (nEnv["SERVER_ADDR"].indexOf(":") != -1) nEnv["SERVER_ADDR"] = "[" + nEnv["SERVER_ADDR"] + "]"; } if (configJSON.serverAdministratorEmail && configJSON.serverAdministratorEmail != "[no contact information]") { nEnv["SERVER_ADMIN"] = configJSON.serverAdministratorEmail; } nEnv["SERVER_NAME"] = req.headers.host; nEnv["DOCUMENT_ROOT"] = process.cwd(); nEnv["SCRIPT_NAME"] = cPath; nEnv["SCRIPT_FILENAME"] = (process.cwd() + (require("os").platform == "win32" ? cPath.replace(/\//g, "\\") : cPath)).replace((require("os").platform == "win32" ? /\\\\/g : /\/\//g), (require("os").platform == "win32" ? "\\" : "/")); nEnv["PATH_INFO"] = decodeURIComponent(b); nEnv["PATH_TRANSLATED"] = b ? ((process.cwd() + decodeURIComponent(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["REQUEST_URI"] = (!origHref || origHref == href) ? req.url : (origHref + (uobject.search ? ((uobject.search[0] == "?" ? "" : "?") + uobject.search) : "")); nEnv["REMOTE_ADDR"] = (req.socket.realRemoteAddress ? req.socket.realRemoteAddress : ((req.headers["x-forwarded-for"] && configJSON.enableIPSpoofing) ? req.headers["x-forwarded-for"].split(",")[0].replace(/ /g, "") : req.socket.remoteAddress)).replace(/^::ffff:/i, ""); if (req.socket.realRemoteAddress && req.socket.realRemotePort) { nEnv["REMOTE_PORT"] = req.socket.realRemotePort; } else if (!(req.socket.realRemoteAddress && !req.socket.realRemotePort)) { nEnv["REMOTE_PORT"] = req.socket.remotePort; } if (req.socket.encrypted) nEnv["HTTPS"] = "ON"; if (req.headers["content-type"]) nEnv["CONTENT_TYPE"] = req.headers["content-type"]; nEnv["CONTENT_LENGTH"] = "0"; if (req.headers["content-length"]) nEnv["CONTENT_LENGTH"] = req.headers["content-length"]; var nh = JSON.parse(JSON.stringify(req.headers)); delete nh["content-type"]; delete nh["content-length"]; var nhKeys = Object.keys(nh); for (var i = 0; i < nhKeys.length; i++) { nEnv["HTTP_" + nhKeys[i].replace(/[^0-9A-Za-z]+/g, "_").toUpperCase()] = req.headers[nhKeys[i]]; } executeFastCGI(req, res, dh, nEnv); } var isScriptExt = scriptExts.indexOf("." + ext) != -1; if (fastcgiConf.path !== undefined && (href == fastcgiConf.path || href.indexOf(fastcgiConf.path + "/") == 0)) { try { executeFastCGIWithEnv( decodeURIComponent(href), href.replace(fastcgiConf.path, ""), req, res, req.socket.localAddress, req.socket.localPort, getCustomHeaders ? getCustomHeaders()["Server"] + (disableModExposeSupported && (configJSON.exposeModsInErrorPages || configJSON.exposeModsInErrorPages === undefined) ? " GreenRhombus/" + version : "") : "SVR.JS/" + configJSON.version + " (" + os.platform()[0].toUpperCase() + os.platform().slice(1) + "; Node.JS/" + process.version + ") GreenRhombus/" + version, bheaders, authUser, fastcgiConf.path ); } catch (ex) { if (!callServerError) { res.writeHead(500, "Internal Server Error", abheaders); res.write( "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 + ") GreenRhombus/" + version + " " + (req.headers.host == undefined ? "" : " on " + req.headers.host) + "
" ); res.end(); } else { callServerError(500, "GreenRhombus/" + version, ex); } } } else if (((href == "/greenrhombus-config.json" || (os.platform() == "win32" && href.toLowerCase() == "/greenrhombus-config.json")) && path.normalize(__dirname + "/../../..") == process.cwd()) || ((href == "/greenrhombus-scriptexts.json" || (os.platform() == "win32" && href.toLowerCase() == "/greenrhombus-scriptexts.json")) && path.normalize(__dirname + "/../../..") == process.cwd())) { if (!callServerError) { res.writeHead(200, "OK", { "Content-Type": "application/json", "Server": "GreenRhombus/" + version }); res.end(JSON.stringify(exttointerpreteruser, null, 2)); } else { callServerError(200, "GreenRhombus/" + version, exttointerpreteruser); } } else { fs.stat("." + decodeURIComponent(href), function (err, stats) { if (!err) { if (!stats.isFile()) { if (scriptExts.indexOf(".php") != -1) { fs.stat("." + decodeURIComponent(href) + "/index.php", function (e2, s2) { if (!e2 && s2.isFile()) { try { executeFastCGIWithEnv( (decodeURIComponent(href) + "/index.php").replace(/\/+/g, "/"), "", req, res, req.socket.localAddress, req.socket.localPort, getCustomHeaders ? getCustomHeaders()["Server"] + (disableModExposeSupported && (configJSON.exposeModsInErrorPages || configJSON.exposeModsInErrorPages === undefined) ? " GreenRhombus/" + version : "") : "SVR.JS/" + configJSON.version + " (" + os.platform()[0].toUpperCase() + os.platform().slice(1) + "; Node.JS/" + process.version + ") GreenRhombus/" + version, bheaders, authUser, (decodeURIComponent(href) + "/index.php").replace(/\/+/g, "/") ); } catch (ex) { if (!callServerError) { res.writeHead(500, "Internal Server Error", abheaders); res.write( "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 + ") GreenRhombus/" + version + " " + (req.headers.host == undefined ? "" : " on " + req.headers.host) + "
" ); res.end(); } else { callServerError(500, "GreenRhombus/" + version, ex); } } } else { elseCallback(); } }); } else if (scriptExts.indexOf(".cgi") != -1) { fs.stat("." + decodeURIComponent(href) + "/index.cgi", function (e3, s3) { if (!e3 && s3.isFile()) { try { executeFastCGIWithEnv( (decodeURIComponent(href) + "/index.cgi").replace(/\/+/g, "/"), "", req, res, req.socket.localAddress, req.socket.localPort, getCustomHeaders ? getCustomHeaders()["Server"] + (disableModExposeSupported && (configJSON.exposeModsInErrorPages || configJSON.exposeModsInErrorPages === undefined) ? " GreenRhombus/" + version : "") : "SVR.JS/" + configJSON.version + " (" + os.platform()[0].toUpperCase() + os.platform().slice(1) + "; Node.JS/" + process.version + ") GreenRhombus/" + version, bheaders, authUser, (decodeURIComponent(href) + "/index.cgi").replace(/\/+/g, "/") ); } catch (ex) { if (!callServerError) { res.writeHead(500, "Internal Server Error", abheaders); res.write( "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 + ") GreenRhombus/" + version + " " + (req.headers.host == undefined ? "" : " on " + req.headers.host) + "
" ); res.end(); } else { callServerError(500, "GreenRhombus/" + version, ex); } } } else { elseCallback(); } }); } else { elseCallback(); } } else { if (isScriptExt) { try { executeFastCGIWithEnv( decodeURIComponent(href), "", req, res, req.socket.localAddress, req.socket.localPort, getCustomHeaders ? getCustomHeaders()["Server"] + (disableModExposeSupported && (configJSON.exposeModsInErrorPages || configJSON.exposeModsInErrorPages === undefined) ? " GreenRhombus/" + version : "") : "SVR.JS/" + configJSON.version + " (" + os.platform()[0].toUpperCase() + os.platform().slice(1) + "; Node.JS/" + process.version + ") GreenRhombus/" + version, bheaders, authUser, decodeURIComponent(href) ); } catch (ex) { if (!callServerError) { res.writeHead(500, "Internal Server Error", abheaders); res.write( "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 + ") GreenRhombus/" + version + " " + (req.headers.host == undefined ? "" : " on " + req.headers.host) + "
" ); res.end(); } else { callServerError(500, "GreenRhombus/" + version, ex); } } } else { elseCallback(); } } } else if (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 < 2) { 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("." + decodeURIComponent(href), function (pathp) { if (!pathp) { elseCallback(); } else { var newext = path.extname(pathp.fpth); if (scriptExts.indexOf(newext) != -1) { try { executeFastCGIWithEnv( pathp.fpth.substr(1), pathp.rpth, req, res, req.socket.localAddress, req.socket.localPort, getCustomHeaders ? getCustomHeaders()["Server"] + (disableModExposeSupported && (configJSON.exposeModsInErrorPages || configJSON.exposeModsInErrorPages === undefined) ? " GreenRhombus/" + version : "") : "SVR.JS/" + configJSON.version + " (" + os.platform()[0].toUpperCase() + os.platform().slice(1) + "; Node.JS/" + process.version + ") GreenRhombus/" + version, bheaders, authUser, pathp.fpth.substr(1) ); } catch (ex) { if (!callServerError) { res.writeHead(500, "Internal Server Error", abheaders); res.write( "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 + ") GreenRhombus/" + version + " " + (req.headers.host == undefined ? "" : " on " + req.headers.host) + "
" ); res.end(); } else { callServerError(500, "GreenRhombus/" + version, ex); } } } else { elseCallback(); } } }); } else { elseCallback(); //Invoke default error handler } }); } } } module.exports = Mod;