scriptbox
Version:
Script box is a full VAS application
219 lines (213 loc) • 6.92 kB
JavaScript
var path = require('path'),
vm = require("vm"),
fs = require("fs"),
logger = require("console").Console,
util = require("util"),
memory = require("./memory"),
events = require("events");
var colors = require('colors');
function VMStream(filename,id,error) {
this.filename = filename;
this.id = id;
this.error = !!error;
}
util.inherits(VMStream,events.EventEmitter)
VMStream.prototype.write = function() {
process.stdout
.write( ("VM-SMS " + (this.error ? "ERROR" : "LOG") +' "' +this.filename + '" "'+ this.id +'" > '+ util.format.apply(this, arguments)).grey);
}
var sessions = {};
var localStorage = {};
var preScript = "if(!Array.prototype.rnd)Object.defineProperty(Array.prototype,'rnd',{get:function (){ var randscript = -1, max = this.length-1; while (randscript < 0 || randscript > max || isNaN(randscript))\
randscript = parseInt(Math.random()*(max+1)); return this[randscript]; }}); ";
var lang = false;
var script = {};
var modules = {};
var settings = {};
var allowNativeModules = {
tcp : function(){
return {
http : require("http").request,
https: require("https").request,
socket : require("net").connect,
dgram : require('dgram').createSocket,
tls : require('tls').connect
};
},
url : function(){
return require("url");
},
assert : function(){
return require("assert");
},
md5 : function(){
return require("MD5")
},
randomstring : function(){
return require("randomstring");
},
punycode : function(){
return require("punycode");
},
dns : function(){
return require('dns');
},
events : function(){
return require('events');
}
}
var adapter = {
//"arango" : ["ArangoDB","arango"],
//"firebird" : ["firebird" ,"node-firebird"],
"mongoose" : ["createConnection","mongodb"],
"mongoose/schema" : ["Schema","mongodb-schema"],
"mysql" : ["createConnection","mysql"],
//"nano" : ["Nano","nano"],
//"neo4j" : ["Neo4J","neo4j"],
"pg" : ["Client","postgres"],
"redis" : ["createClient" ,"redis"],
//"rethinkdb" : ["RethinkDB","rethinkdb"],
//"riak" : ["Riak","riak-js"],
"node-sqlite-purejs" : ["open","sqlite"],
//"tingodb" : ["TingoDB", "tingodb"]
}
console.log("Expose module to VMs".grey, process.argv[4].grey,process.argv[2].grey);
for(var i in adapter){
try {
require.resolve(i.split('/')[0]);
console.log("resolve ".grey,adapter[i][1].grey,'(',i.split('/')[0].yellow,')',"...OK".grey);
allowNativeModules[adapter[i][1]] = (function(m,name){
if(name){
var mod = require(m);
var ret = mod[name];
if(ret instanceof Function)
return ret.bind(mod);
else
return ret;
}
return require(m);
}).bind(null,i.split('/')[0],adapter[i][0]);
} catch(e){}
}
var currSMS;
process.on("message",function(m){
if (m.type === 'settings'){
settings = m.data;
}else if (m.type === 'setDIR'){
__DIR = m.data;
}else if (m.type === 'sms'){
console.log("recieve SMS",m.time);
m.msgdata_orig = m.msgdata;
m.msgdata = new Buffer(m.msgdata).toString().trim();
m.receiver = new Buffer(m.receiver).toString().toLowerCase();
m.sender = new Buffer(m.sender).toString().toLowerCase();
var sendError = function(err){
var tmp = m.receiver;
m.receiver = m.sender;
m.sender = tmp;
console.log(("SMS SEND Exec Error".red, process.argv[2],m.file, err.stack || err).grey);
m.msgdata = settings.defautErrorMSG || "EXEC ERROR";
process.send(m);
};
if(!script[m.file]){
try{data = fs.readFileSync(m.file);}catch(e){return sendError(e);}
script[m.file] = vm.createScript(preScript+";"+data, m.file);
fs.watchFile(m.file, (function (file,sendError,curr, prev) {
console.log('VM script reload: '.grey, process.argv[4].grey,process.argv[2].grey , file);
try{data = fs.readFileSync(file);}catch(err){return console.log('VM Script Exception: '.grey, process.argv[4].grey,process.argv[2].grey , err);}
script[file] = vm.createScript(preScript+";"+data, file);
}).bind(null,m.file,sendError));
}
/* definition de la session et du storage */
var _id = new Buffer(m.sender).toString();
m.filename = path.basename(m.file);
var MSG = function(conf){
conf = conf || {};
if(this instanceof arguments.callee){
for (var property in conf)
this[property] = conf[property];
var tmp = this.receiver;
this.receiver = this.sender;
this.sender = tmp;
delete this.type;
Object.defineProperties(this, {
sendSMS : {
value: function(msg){
if(msg)
this.msgdata = msg;
process.send(this);
},
writable: false,
enumerable: false,
configurable: false
},
send : {
value: function(msg){
if(msg)
this.msgdata = msg;
process.send(this);
},
writable: false,
enumerable: false,
configurable: false
},
type : {
value: "sms",
writable: false,
enumerable: true,
configurable: false
}
});
}else
return new arguments.callee(conf);
};
var require = function(name){
name = name.split(/[ -]/).join("-").replace(/[^\w\-]+/g,"").toLowerCase();
if(modules[name])
return modules[name];
if(allowNativeModules[name])
return modules[name] = allowNativeModules[name]();
var n = path.join(__DIR,"scripts","modules" ,name);
if(!fs.existsSync(n)) throw "Module "+name+" not found";
try{
var n = fs.readFileSync(n);
var sand = {
exports : {},
module : {
id : name,
exports : null
},
session : new memory.Client(_id),
localStorage : new memory.Client(m.keywords[0].toLowerCase()),
globalStorage : new memory.Client(m.receiver),
logger : new logger(new VMStream(name, "module-"+name),new VMStream(name, "module-"+name,true)),
Buffer : Buffer,
require : require,
get MSG() {return MSG }
};
vm.runInNewContext(n, sand);
return modules[name]=sand.module.exports ? sand.module.exports : sand.exports;
}catch(e){
throw e;
}
};
try{
script[m.file].runInContext(vm.createContext({
sms : m ,
logger : new logger(new VMStream(path.basename(m.file), m.id),new VMStream(path.basename(m.file), m.id,true)),
Buffer : Buffer,
now : Date.now(),
require : require,
get MSG() {return MSG },
session : new memory.Client(_id),
localStorage : new memory.Client(m.keywords[0].toLowerCase()),
globalStorage : new memory.Client(m.receiver)
})); }catch(e){
return sendError(e);
}
delete sandbox;
}
});
process.on('uncaughtException', function(err) {
console.log('VM Caught exception: '.grey, process.argv[4].grey,process.argv[2].grey , err.stack);
});