2023-07-29 23:44:21 +02:00
var https = require ( "https" ) ;
var os = require ( "os" ) ;
var http = require ( "http" ) ;
var url = require ( "url" ) ;
var fs = require ( "fs" ) ;
var path = require ( "path" ) ;
2023-07-30 02:24:20 +02:00
var childProcess = require ( "child_process" ) ;
2023-07-29 23:44:21 +02:00
var version = "UNKNOWN" ;
try {
version = JSON . parse ( fs . readFileSync ( _ _dirname + "/mod.info" ) ) . version ;
2023-07-30 02:24:20 +02:00
} catch ( ex ) {
2023-07-29 23:44:21 +02:00
//Can"t determine version
}
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 ) {
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
2023-07-30 02:24:20 +02:00
var abheaders = JSON . parse ( JSON . stringify ( bheaders ) ) ;
2023-07-29 23:44:21 +02:00
function executeCGI ( fname , req , res , dh , nEnv ) {
var env = JSON . parse ( JSON . stringify ( process . env ) ) ;
var nEnvKeys = Object . keys ( nEnv ) ;
2023-07-30 02:24:20 +02:00
for ( var i = 0 ; i < nEnvKeys . length ; i ++ ) {
2023-07-29 23:44:21 +02:00
env [ nEnvKeys [ i ] ] = nEnv [ nEnvKeys [ i ] ] ;
}
var exttointerpreter = {
".pl" : [ "perl" ] ,
".py" : [ "python" ] ,
".sh" : [ "bash" ] ,
".ksh" : [ "ksh" ] ,
".csh" : [ "csh" ] ,
".bat" : [ "cmd" , "/c" ] ,
".cmd" : [ "cmd" , "/c" ] ,
".vbs" : [ "cscript" ] ,
".jar" : [ "java" ] ,
".pyw" : [ "python" ] ,
".rb" : [ "ruby" ] ,
".php" : [ "php-cgi" ]
}
var exttointerpreteruser = { } ;
try {
exttointerpreteruser = JSON . parse ( fs . readFileSync ( _ _dirname + "/redbrick-interpreters.json" ) ) ;
2023-07-30 02:24:20 +02:00
} catch ( ex ) { }
2023-07-29 23:44:21 +02:00
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 = [ ] ;
}
2023-07-30 02:24:20 +02:00
} else if ( fl . indexOf ( "\x7fELF" ) == 0 || fl . indexOf ( "MZ" ) == 0 ) {
2023-07-29 23:44:21 +02:00
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 ] = "" ;
2023-07-30 02:24:20 +02:00
wd [ wd . length - 1 ] = "" ;
2023-07-29 23:44:21 +02:00
wd = wd . join ( os . platform ( ) == "win32" ? "\\" : "/" ) ;
2023-07-30 02:24:20 +02:00
var interpreter = childProcess . spawn ( filename , args , {
2023-07-29 23:44:21 +02:00
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 ( "<html><head></head><body><h1>RedBrick Error!</h1><p>Reason: " + error . message + "</p></body></html>" ) ;
} 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 ;
}
}
2023-07-30 02:24:20 +02:00
if ( code == 200 && ( bheaderso [ "Location" ] || bheaderso [ "location" ] ) ) {
2023-07-29 23:44:21 +02:00
code = 302 ;
msg = "Found" ;
}
2023-07-30 02:24:20 +02:00
2023-07-29 23:44:21 +02:00
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 ) ;
2023-07-30 02:24:20 +02:00
interpreter . stderr . on ( "data" , function ( data ) {
stderr += data . toString ( )
2023-07-29 23:44:21 +02:00
} ) ;
req . pipe ( interpreter . stdin ) ;
interpreter . on ( "exit" , ( code , signal ) => {
2023-07-30 02:24:20 +02:00
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 ) ;
2023-07-29 23:44:21 +02:00
} else {
2023-07-30 02:24:20 +02:00
callServerError ( 500 , "RedBrick/" + version , ex ) ;
2023-07-29 23:44:21 +02:00
}
2023-07-30 02:24:20 +02:00
} else {
res . end ( ) ;
}
2023-07-29 23:44:21 +02:00
} ) ;
}
}
function executeCGIWithEnv ( a , b , req , res , pubip , port , software , dh ) {
var nEnv = { } ;
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 , "" ) ;
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 [ "REQUEST_METHOD" ] = req . method ;
nEnv [ "GATEWAY_INTERFACE" ] = "CGI/1.1" ;
nEnv [ "REQUEST_URI" ] = req . url ;
2023-07-30 02:24:20 +02:00
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 , "" ) ;
2023-07-29 23:44:21 +02:00
nEnv [ "REMOTE_PORT" ] = ( req . socket . realRemotePort ? req . socket . realRemotePort : req . socket . remoteAddress ) ;
nEnv [ "SCRIPT_NAME" ] = a ;
nEnv [ "SCRIPT_FILENAME" ] = ( process . cwd ( ) + ( require ( "os" ) . platform == "win32" ? a . replace ( /\//g , "\\" ) : a ) ) . replace ( ( require ( "os" ) . platform == "win32" ? /\\\\/g : /\/\//g ) , ( require ( "os" ) . platform == "win32" ? "\\" : "/" ) ) ;
if ( req . headers [ "content-type" ] ) nEnv [ "CONTENT_TYPE" ] = req . headers [ "content-type" ] ;
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 ] ] ;
}
executeCGI ( "." + a , req , res , dh , nEnv ) ;
}
if ( href . indexOf ( "/cgi-bin" ) == 0 ) {
try {
if ( fs . existsSync ( "." + href ) ) {
var invokeElseCallback = false ;
try {
invokeElseCallback = ! fs . statSync ( "." + href ) . isFile ( ) ;
2023-07-30 02:24:20 +02:00
} catch ( ex ) { }
2023-07-29 23:44:21 +02:00
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 ( "<html><head><title>500 Internal Server Error</title></head><body><h1>500 Internal Server Error</h1><p>A server had unexcepted execption. Below, stack 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 with 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 + ") RedBrick/" + version + " " + ( req . headers . host == undefined ? "" : " on " + req . headers . host ) + "</p></body></html>" ) ;
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 ;
2023-07-30 02:24:20 +02:00
if ( ! a ) b = [ ] ;
2023-07-29 23:44:21 +02:00
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 ) ;
} 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 unexcepted execption. Below, stack 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 with 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 + ") RedBrick/" + version + " " + ( req . headers . host == undefined ? "" : " on " + req . headers . host ) + "</p></body></html>" ) ;
res . end ( ) ;
} else {
callServerError ( 500 , "RedBrick/" + version , ex ) ;
}
}
}
}
} 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 unexcepted execption. Below, stack 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 with 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 + ") RedBrick/" + version + " " + ( req . headers . host == undefined ? "" : " on " + req . headers . host ) + "</p></body></html>" ) ;
res . end ( ) ;
} else {
callServerError ( 500 , "RedBrick/" + version , ex ) ;
}
}
2023-07-30 02:24:20 +02:00
} else if ( href == "/redbrick-interpreters.json" && path . normalize ( _ _dirname + "/../../.." ) == process . cwd ( ) ) {
if ( ! callServerError ) {
res . writeHead ( 403 , "Forbidden" , abheaders ) ;
res . write ( "<html><head><title>403 Forbidden</title></head><body><h1>403 Forbidden</h1><p>You don't have access to specific page.</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 + ") RedBrick/" + version + " " + ( req . headers . host == undefined ? "" : " on " + req . headers . host ) + "</p></body></html>" ) ;
res . end ( ) ;
} else {
callServerError ( 403 , "RedBrick/" + version ) ;
}
2023-07-29 23:44:21 +02:00
} else {
elseCallback ( ) ;
}
}
}
module . exports = Mod ;