Initial commit
This commit is contained in:
commit
47068ba0b0
2 changed files with 865 additions and 0 deletions
861
index.js
Normal file
861
index.js
Normal file
|
@ -0,0 +1,861 @@
|
|||
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) {
|
||||
emulatedStdout.push(processedPacket.content);
|
||||
} else if (processedPacket.type == STDERR) {
|
||||
emulatedStderr.push(processedPacket.content);
|
||||
} else if (processedPacket.type == END_REQUEST && processedPacket.content.length > 5) {
|
||||
if (typeof socket !== "undefined") socket.removeListener("data", fastCGISocketHandler);
|
||||
var appStatus = processedPacket.content.readUInt32BE(0);
|
||||
var protocolStatus = processedPacket.content.readUInt8(4);
|
||||
emulatedStdout.push(null);
|
||||
emulatedStderr.push(null);
|
||||
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");
|
||||
}
|
||||
eventEmitter.emit("error", err);
|
||||
} else {
|
||||
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();
|
||||
}
|
||||
});
|
||||
|
||||
var emulatedStdout = new stream.Readable({
|
||||
read: function () {}
|
||||
});
|
||||
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) {
|
||||
emulatedStdout.push(null);
|
||||
emulatedStderr.push(null);
|
||||
eventEmitter.emit("error", err);
|
||||
}).on("data", fastCGISocketHandler);
|
||||
|
||||
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.substr(headerendline + eol.length), "latin1");
|
||||
} catch (ex) {
|
||||
handler.removeAllListeners("exit");
|
||||
handler.stdout.removeAllListeners("dat");
|
||||
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
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var options = {
|
||||
host: fastcgiConf.host,
|
||||
port: fastcgiConf.port,
|
||||
path: fastcgiConf.socketPath,
|
||||
env: env
|
||||
};
|
||||
|
||||
handler = createFastCGIHandler(options);
|
||||
handler.on("error", function (error) {
|
||||
var errorcode = (error.code == "ENOTFOUND" || error.code == "EHOSTUNREACH" || error.code == "ECONNREFUSED") ? 503 : 500;
|
||||
if (!callServerError) {
|
||||
res.writeHead(errorcode, {
|
||||
"Content-Type": "text/html",
|
||||
"Server": "GreenRhombus/" + version
|
||||
});
|
||||
res.end("<html><head></head><body><h1>GreenRhombus Error!</h1><p>Reason: " + error.message + "</p></body></html>");
|
||||
} else {
|
||||
callServerError(errorcode, "GreenRhombus/" + version, error);
|
||||
}
|
||||
});
|
||||
|
||||
handler.on("connect", function () {
|
||||
handler.init();
|
||||
handler.stdout.on("data", dataHandler);
|
||||
handler.stderr.on("data", function (data) {
|
||||
stderr += data.toString();
|
||||
});
|
||||
req.pipe(handler.stdin);
|
||||
handler.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, "GreenRhombus/" + version, ex);
|
||||
}
|
||||
} else {
|
||||
var preparedStderr = stderr.trim();
|
||||
if (preparedStderr) {
|
||||
serverconsole.errmessage("There were FastCGI application errors:");
|
||||
serverconsole.errmessage(preparedStderr);
|
||||
}
|
||||
handler.stdout.unpipe(res); //Prevent server crashes with write after the end
|
||||
res.end();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
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) : ""));
|
||||
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(
|
||||
"<html><head><title>500 Internal Server Error</title></head><body><h1>500 Internal Server Error</h1><p>A server had unexpected exception. Below, the stack trace of the error is shown:</p><code>" +
|
||||
ex.stack.replace(/\r\n/g, "<br/>").replace(/\n/g, "<br/>").replace(/\r/g, "<br/>").replace(/ /g, " ") +
|
||||
"</code><p>Please contact the developer/administrator of the website.</p><p style=\"font-style: italic; font-weight: normal;\">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) +
|
||||
"</p></body></html>"
|
||||
);
|
||||
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()) {
|
||||
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(
|
||||
"<html><head><title>500 Internal Server Error</title></head><body><h1>500 Internal Server Error</h1><p>A server had unexpected exception. Below, the stack trace of the error is shown:</p><code>" +
|
||||
ex.stack.replace(/\r\n/g, "<br/>").replace(/\n/g, "<br/>").replace(/\r/g, "<br/>").replace(/ /g, " ") +
|
||||
"</code><p>Please contact the developer/administrator of the website.</p><p style=\"font-style: italic; font-weight: normal;\">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) +
|
||||
"</p></body></html>"
|
||||
);
|
||||
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(
|
||||
"<html><head><title>500 Internal Server Error</title></head><body><h1>500 Internal Server Error</h1><p>A server had unexpected exception. Below, the stack trace of the error is shown:</p><code>" +
|
||||
ex.stack.replace(/\r\n/g, "<br/>").replace(/\n/g, "<br/>").replace(/\r/g, "<br/>").replace(/ /g, " ") +
|
||||
"</code><p>Please contact the developer/administrator of the website.</p><p style=\"font-style: italic; font-weight: normal;\">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) +
|
||||
"</p></body></html>"
|
||||
);
|
||||
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(
|
||||
"<html><head><title>500 Internal Server Error</title></head><body><h1>500 Internal Server Error</h1><p>A server had unexpected exception. Below, the stack trace of the error is shown:</p><code>" +
|
||||
ex.stack.replace(/\r\n/g, "<br/>").replace(/\n/g, "<br/>").replace(/\r/g, "<br/>").replace(/ /g, " ") +
|
||||
"</code><p>Please contact the developer/administrator of the website.</p><p style=\"font-style: italic; font-weight: normal;\">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) +
|
||||
"</p></body></html>"
|
||||
);
|
||||
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(
|
||||
"<html><head><title>500 Internal Server Error</title></head><body><h1>500 Internal Server Error</h1><p>A server had unexpected exception. Below, the stack trace of the error is shown:</p><code>" +
|
||||
ex.stack.replace(/\r\n/g, "<br/>").replace(/\n/g, "<br/>").replace(/\r/g, "<br/>").replace(/ /g, " ") +
|
||||
"</code><p>Please contact the developer/administrator of the website.</p><p style=\"font-style: italic; font-weight: normal;\">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) +
|
||||
"</p></body></html>"
|
||||
);
|
||||
res.end();
|
||||
} else {
|
||||
callServerError(500, "GreenRhombus/" + version, ex);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
elseCallback();
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
elseCallback(); //Invoke default error handler
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Mod;
|
4
mod.info
Executable file
4
mod.info
Executable file
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"name": "GreenRhombus FastCGI client for SVR.JS",
|
||||
"version": "Nightly-GitMain"
|
||||
}
|
Loading…
Reference in a new issue