Initial commit
This commit is contained in:
commit
2691860bcb
2 changed files with 282 additions and 0 deletions
278
index.js
Normal file
278
index.js
Normal file
|
@ -0,0 +1,278 @@
|
||||||
|
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 version = "UNKNOWN";
|
||||||
|
try {
|
||||||
|
version = JSON.parse(fs.readFileSync(__dirname + "/mod.info")).version;
|
||||||
|
} catch (ex) {
|
||||||
|
// Can't determine version
|
||||||
|
}
|
||||||
|
var configJSONS = JSON.parse(fs.readFileSync("config.json")); // Read configuration JSON
|
||||||
|
var scgiConf = {};
|
||||||
|
try {
|
||||||
|
scgiConf = JSON.parse(fs.readFileSync(__dirname + "/../../../orangecircle-config.json"));
|
||||||
|
} catch (ex) {
|
||||||
|
// Use defaults
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load default configuration
|
||||||
|
if (scgiConf.path === undefined) scgiConf.path = "/scgi";
|
||||||
|
scgiConf.path = scgiConf.path.replace(/([^\/])\/+$/, "$1");
|
||||||
|
if (scgiConf.host === undefined) scgiConf.host = "localhost";
|
||||||
|
if (scgiConf.port === undefined) scgiConf.port = 4000;
|
||||||
|
|
||||||
|
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) {
|
||||||
|
return function () {
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
var abheaders = JSON.parse(JSON.stringify(bheaders));
|
||||||
|
|
||||||
|
function executeSCGI(req, res, dh, nEnv) {
|
||||||
|
// Function to execute SCGI 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 headerendline = -1;
|
||||||
|
var cned = false;
|
||||||
|
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(" ");
|
||||||
|
if (hso[0].match(/^[0-9]{3}$/)) {
|
||||||
|
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, "OrangeCircle/" + version, ex);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (cned && !res.finished) res.write(data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var socket = net.createConnection({
|
||||||
|
host: scgiConf.host,
|
||||||
|
port: scgiConf.port,
|
||||||
|
}, function () {
|
||||||
|
socket.on("data", dataHandler);
|
||||||
|
socket.on("end", function () {
|
||||||
|
res.end();
|
||||||
|
});
|
||||||
|
var envEncoded = "";
|
||||||
|
var envNames = Object.keys(env);
|
||||||
|
for (var i = 0; i < envNames.length; i++) {
|
||||||
|
var envName = String(envNames[i]).replace(/\0/g, "");
|
||||||
|
var envValue = String(env[envNames[i]]).replace(/\0/g, "");
|
||||||
|
if(envName == "CONTENT_LENGTH") {
|
||||||
|
// CONTENT_LENGTH environment variable must be first!!!
|
||||||
|
envEncoded = envName + "\0" + envValue + "\0" + envEncoded;
|
||||||
|
} else {
|
||||||
|
envEncoded += envName + "\0" + envValue + "\0";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
socket.write(envEncoded.length + ":" + envEncoded + ",");
|
||||||
|
req.pipe(socket, {end: false});
|
||||||
|
}).on("error", function (error) {
|
||||||
|
if (!callServerError) {
|
||||||
|
res.writeHead(500, {
|
||||||
|
"Content-Type": "text/html",
|
||||||
|
"Server": "OrangeCircle/" + version
|
||||||
|
});
|
||||||
|
res.end("<html><head></head><body><h1>OrangeCircle Error!</h1><p>Reason: " + error.message + "</p></body></html>");
|
||||||
|
} else {
|
||||||
|
callServerError(500, "OrangeCircle/" + version, error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function executeSCGIWithEnv(a, req, res, pubip, port, software, dh) {
|
||||||
|
// Function to set up environment variables and execute sCGI scripts
|
||||||
|
var b = href.replace(scgiConf.path,"")
|
||||||
|
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"] = "orangecircle_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_orangecircle_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"] + "]";
|
||||||
|
}
|
||||||
|
nEnv["SERVER_NAME"] = req.headers.host;
|
||||||
|
nEnv["DOCUMENT_ROOT"] = process.cwd();
|
||||||
|
nEnv["SCRIPT_NAME"] = scgiConf.path;
|
||||||
|
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["SCGI"] = "1";
|
||||||
|
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, "");
|
||||||
|
nEnv["REMOTE_PORT"] = (req.socket.realRemotePort ? req.socket.realRemotePort : req.socket.remotePort);
|
||||||
|
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]];
|
||||||
|
}
|
||||||
|
executeSCGI(req, res, dh, nEnv);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (href == scgiConf.path || href.indexOf(scgiConf.path + "/") == 0) {
|
||||||
|
try {
|
||||||
|
executeSCGIWithEnv(
|
||||||
|
href,
|
||||||
|
req,
|
||||||
|
res,
|
||||||
|
req.socket.localAddress,
|
||||||
|
req.socket.localPort,
|
||||||
|
getCustomHeaders ?
|
||||||
|
getCustomHeaders()["Server"] +
|
||||||
|
" OrangeCircle/" +
|
||||||
|
version :
|
||||||
|
"SVR.JS/" +
|
||||||
|
configJSON.version +
|
||||||
|
" (" +
|
||||||
|
os.platform()[0].toUpperCase() +
|
||||||
|
os.platform().slice(1) +
|
||||||
|
"; Node.JS/" +
|
||||||
|
process.version +
|
||||||
|
") OrangeCircle/" +
|
||||||
|
version,
|
||||||
|
bheaders
|
||||||
|
);
|
||||||
|
} 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 +
|
||||||
|
") OrangeCircle/" +
|
||||||
|
version +
|
||||||
|
" " +
|
||||||
|
(req.headers.host == undefined ? "" : " on " + req.headers.host) +
|
||||||
|
"</p></body></html>"
|
||||||
|
);
|
||||||
|
res.end();
|
||||||
|
} else {
|
||||||
|
callServerError(500, "OrangeCircle/" + version, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (href == "/orangecircle-config.json" && path.normalize(__dirname + "/../../..") == process.cwd()) {
|
||||||
|
if (!callServerError) {
|
||||||
|
res.writeHead(200, "OK", {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
"Server": "OrangeCircle/" + version
|
||||||
|
});
|
||||||
|
res.end(JSON.stringify(exttointerpreteruser, null, 2));
|
||||||
|
} else {
|
||||||
|
callServerError(200, "OrangeCircle/" + version, exttointerpreteruser);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
elseCallback();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = Mod;
|
4
mod.info
Executable file
4
mod.info
Executable file
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"name": "DorianTech OrangeCircle SCGI client for SVR.JS",
|
||||||
|
"version": "Nightly-GitMain"
|
||||||
|
}
|
Loading…
Reference in a new issue