/******************************************************************************
@owner: SVSi
@author: Arthur Johnson
@function: Sandboxing for Javascript scripts on buttons and conditionals
*******************************************************************************/

	var Sandbox = {};
	var Modules = {};
	
	var ringBuffer = function(size, init){
		var self = []; if (size) self.size = size; else self.size = 0;
		self.push = function(){
			var len = Array.prototype.push.apply(self, arguments);
			self.splice(0, self.length - self.size);
			if (len >= 0 && len <= self.size) return len;
			else return self.size;
		}
		if (init) for (var i=0; i<init.length; i++) self.push(init[i]);
		return self;
	}
	
	Sandbox.sockets = new ringBuffer(50);
	Sandbox.responses = {};
	Sandbox.globalvars = {};
	Sandbox.callback = noop;
	Sandbox.canvas = document.createElement('canvas');

	Sandbox.frame = document.createElement('iframe');
	Sandbox.frame.style.display = 'none';

	waitfor(function(){return document.body;}, function(){
		document.body.appendChild(Sandbox.frame);
		Sandbox.F = Sandbox.frame.contentWindow.Function;
		Sandbox.Args = Object.keys(Sandbox.frame.contentWindow).join();
		Sandbox.frame.contentWindow.alert = alert;
		Sandbox.frame.contentWindow.prompt = prompt;
		Sandbox.frame.contentWindow.confirm = confirm;
		Sandbox.frame.contentWindow.console = {};
		Sandbox.frame.contentWindow.console.log = console.log.bind(console);
		Sandbox.isready = true;
	});
	
	
	function sleep(milliseconds){
		var start = new Date().getTime();
		for (var i = 0; i < 1e7; i++){
			if ((new Date().getTime() - start) > milliseconds){
				break;
			}
		}
	}
	
	function ping(ip, count){
		if (count > 5) count = 5;
		var xmlhttp = new XMLHttpRequest();
		xmlhttp.open("GET", '../ping.php'+"?host="+ip+"&count="+count+"&submit=Ping", true);
		xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
		xmlhttp.send("host="+ip+"&count="+count+"&submit=Ping");
		xmlhttp.onreadystatechange = function(){
			if (xmlhttp.readyState == 4 && xmlhttp.status == 200){
				console.log(xmlhttp.responseText);			
			}
		}
	}
	
	function gotopanel(ind){
		panelswitched = true;
		setPanel(ind-1);
	}
	
	function include(filename){
		var fileref = document.createElement('script');
		fileref.setAttribute("type", "text/javascript");
		fileref.setAttribute("src", filename);

		if (typeof fileref != "undefined")
			document.getElementsByTagName("head")[0].appendChild(fileref);
	}
	
	function _require(file, callback){

		if (undef(callback)){
			var xhrObj = new XMLHttpRequest();
			
			xhrObj.open('GET', file, false);
			xhrObj.send('');
			
			var se = document.createElement('script');
			se.type = "text/javascript";
			se.text = xhrObj.responseText;
			
			document.getElementsByTagName('head')[0].appendChild(se);
			for (var property in Modules){
				if (Modules.hasOwnProperty(property)){
					Sandbox.frame.contentWindow[property] = Modules[property];
				}
			}
			return;
		}
		
		callback = callback || noop;
		
		var filenode;
		var jsfile_extension = /(.js)$/i;
		var cssfile_extension = /(.css)$/i;

		if (jsfile_extension.test(file)){
			filenode = document.createElement('script');
			filenode.src = file;
			filenode.onreadystatechange = function(){
				if (filenode.readyState === 'loaded' || filenode.readyState === 'complete'){
					filenode.onreadystatechange = null;
					callback();
				}
			};
			filenode.onload = function(){
				callback();
			};
			document.head.appendChild(filenode);
		}
		else if (cssfile_extension.test(file)){
			filenode = document.createElement('link');
			filenode.rel = 'stylesheet';
			filenode.type = 'text/css';
			filenode.href = file;
			document.head.appendChild(filenode);
			callback();
		}
		else {
			console.log("Unknown file type to load.");
		}
	};
	
	function pseudoRequire(file, callback){
		console.log('prequire', file);
		//if (standalone) file = file.replace('/', 'js/');
		//else file = file.replace('/', 'js/');
		callback = callback || noop;
		
		var filenode;
		var jsfile_extension = /(.js)$/i;
		var cssfile_extension = /(.css)$/i;

		if (jsfile_extension.test(file)){
			console.log('prequire is js');
			$.ajax({url: file, cache: false, dataType: 'text', success: function(val){
				console.log('prequire got back', val);
				eval(val);
				console.log('mcl', window.module_command_list);
				if (0&&window.module_command_list){
					for (var i=0; i<window.module_command_list.length; i++){
						if (ngmodel.maintextarea && ngmodel.maintextarea.select3)
							ngmodel.maintextarea.select3.push(
								{value: i, text: window.module_command_list[i].name}
							);
					}
				}
				callback();
			}, error: function(obj, obj2, err){console.log('prequire error', obj, obj2, err); eval(obj.responseText); ngModel(ngmodel);}});
			
		}
		else if (cssfile_extension.test(file)){
			console.log('prequire is css');
			filenode = document.createElement('link');
			filenode.rel = 'stylesheet';
			filenode.type = 'text/css';
			filenode.href = file;
			document.head.appendChild(filenode);
			callback();
		}
		else {
			console.log("Unknown file type to load.")
		}
	};
	
	function asciiToHex(str){
		str = str.toString();
		var arr = [];
		for (var i = 0, l = str.length; i < l; i ++){
			var hex = Number(str.charCodeAt(i)).toString(16);
			arr.push(hex.length > 1 && hex || "0" + hex);
		}
		return arr.join(' ');
	}
	
	function hexToAscii(hex){
		var _hex = hex.toString();
		var str = '';
		for (var i = 0; i < _hex.length; i += 3)
			str += String.fromCharCode(parseInt(_hex.substr(i, 2), 16));
		return str;
	}
	
	function getButton(id){
		if (typeof id === 'number'){
			for (var i=0; i<project.panels.length; i++){
				for (var j=0; j<project.panels[i].buttons.length; j++){
					if (project.panels[i].buttons[j].core.id == 'Button-'+id ||
						project.panels[i].buttons[j].id == 'Button-'+id)
						return project.panels[i].buttons[j];
				}
			}
		}
		try {
			for (var i=0; i<project.panels.length; i++){
				for (var j=0; j<project.panels[i].buttons.length; j++){
					if (project.panels[i].buttons[j].core.id == id ||
						project.panels[i].buttons[j].id == id)
						return project.panels[i].buttons[j];
				}
			}
		}
		catch (e){
			return pb.getItem(id);
		}
		return false;
	}
	
	function getWidget(id){
		try {
			if (typeof id === 'number'){
				for (var i=0; i<project.panels.length; i++){
					for (var j=0; j<project.panels[i].widgets.length; j++){
						if (project.panels[i].widgets[j].core.id == 'Widget-'+id ||
							project.panels[i].widgets[j].id == 'Widget-'+id)
							return project.panels[i].widgets[j];
					}
				}
			}
			for (var i=0; i<project.panels.length; i++){
				for (var j=0; j<project.panels[i].widgets.length; j++){
					if (project.panels[i].widgets[j].core.id == id ||
						project.panels[i].widgets[j].id == id)
						return project.panels[i].widgets[j];
				}
			}
		}
		catch (e){console.log('hmm', e);}
		return false;
	}
	
	function getPanel(id){
		if (typeof id === 'number'){
			for (var i=0; i<project.panels.length; i++){
				if (project.panels[i].core.id == 'Panel-'+id ||
					project.panels[i].id == 'Panel-'+id)
					return project.panels[i];
			}
		}
		for (var i=0; i<project.panels.length; i++){
			if (project.panels[i].core.id == id ||
				project.panels[i].core.name == id ||
					project.panels[i].id == id)
				return project.panels[i];
		}
		return false;
	}
	
	function getProject(){
		if (project) return project;
		else return false;
	}
	
	function get(id){
		try {
			if (!window.project) return pb.getItem(id);
			var result = getButton(id);
			if (!result) result = getWidget(id);
			if (!result) result = getPanel(id);
			if (!result) result = pb.getItem(id);
		}
		catch (e){}
		return result;
	}
	
	function tcpopen(ip, port, callback, opts){
		if (undef(opts)) opts = {};
		opts.autoclose = false; opts.timeout = false;
		return wsCmd({command: 'tcpopen', ip: ip, port: port, opts: opts}, callback);
	}
	
	function udpopen(ip, port, callback, opts){
		if (undef(opts)) opts = {};
		return wsCmd({command: 'udpopen', ip: ip, port: port, opts: opts}, callback);
	}
	
	function tcpsend(ip, port, callback, opts){
		if (undef(opts)) opts = {};
		return wsCmd({command: 'tcpsend', ip: ip, port: port, opts: opts}, callback);
	}
	
	function udpsend(ip, port, callback, opts){
		if (undef(opts)) opts = {};
		return wsCmd({command: 'udpsend', ip: ip, port: port, opts: opts}, callback);
	}
	
	function tcpclose(ip, port, callback, opts){
		if (undef(opts)) opts = {};
		return wsCmd({command: 'tcpclose', ip: ip, port: port, opts: opts}, callback);
	}
	
	function udpclose(ip, port, callback, opts){
		if (undef(opts)) opts = {};
		return wsCmd({command: 'udpclose', ip: ip, port: port, opts: opts}, callback);
	}
	
	function tcpclient(ip, port, message, callback, opts){
		if (undef(opts)) opts = {};
		if (undef(opts.nodelay)) opts.nodelay = true;
		if (undef(opts.timeout)) opts.timeout = 5000;
		if (undef(opts.autoclose)) opts.autoclose = true;
		if (undef(opts.expect_response)) opts.expect_response = true;
		return wsCmd({command: 'tcpclient', ip: ip, port: port, message: hexToAscii(message), opts: opts}, callback);
	}
	
	function tcppersistent(ip, port, callback, opts){
		if (undef(opts)) opts = {};
		var sock_id = randomString(16);
		//return wsCmd({command: 'tcppersistent', ip: ip, port: port, message: hexToAscii(message)}, callback);
		window.websocket.emit('message', {
			ip: ip, port: port, command: 'tcppersistent', sock_id: sock_id//, message: hexToAscii(message)
		});
		var stream = {
			//ip: ip, port: port,
			sock_id: sock_id, onMessage: callback,
			send: function(msg){
				window.websocket.emit('message', {
					ip: ip, port: port, command: 'tcppersistent', sock_id: sock_id, message: hexToAscii(msg)
				});
			},
			destroy: function(){window.websocket.emit('message', {command: 'tcppersistentclose', sock_id: sock_id,}); this.send = function(){console.log('persistent session ended')}},
			close: function(){this.destroy();}
		};
		Sandbox.sockets.push(stream);
		return stream;
	}
	
	function tcp(ip, port, message){
		var callback, opts;
		if (arguments[3] && typeof arguments[3] === 'function') callback = arguments[3];
		if (arguments[4] && typeof arguments[4] === 'function') callback = arguments[4];
		if (arguments[3] && typeof arguments[3] === 'object') opts = arguments[3];
		if (arguments[4] && typeof arguments[4] === 'object') opts = arguments[4];
		return wsCmd({command: 'tcpclient', ip: ip, port: port, message: message, opts: opts}, callback);
	}
	
	function udpclient(ip, port, message, callback, opts){
		if (undef(opts)) opts = {};
		if (undef(opts.listen)) opts.listen = 50900;
		if (undef(opts.timeout)) opts.timeout = 5000;
		if (undef(opts.autoclose)) opts.autoclose = true;
		if (undef(opts.expect_response)) opts.expect_response = true;
		return wsCmd({command: 'udpclient', ip: ip, port: port, message: hexToAscii(message), opts: opts}, callback);
	}
	
	function udp(ip, port, message){
		var callback, opts;
		if (arguments[3] && typeof arguments[3] === 'function') callback = arguments[3];
		if (arguments[4] && typeof arguments[4] === 'function') callback = arguments[4];
		if (arguments[3] && typeof arguments[3] === 'object') opts = arguments[3];
		if (arguments[4] && typeof arguments[4] === 'object') opts = arguments[4];
		if (undef(opts)) opts = {}; if (undef(opts.listen)) opts.listen = 50900; if (undef(opts.timeout)) opts.timeout = 5000;
		if (undef(opts.autoclose)) opts.autoclose = true; if (undef(opts.expect_response)) opts.expect_response = true;
		return wsCmd({command: 'udpclient', ip: ip, port: port, message: message, opts: opts}, callback);
	}
	
	function telnetclient(ip, port, message, callback, delay){
		if (undef(delay)) delay = 2;
		if (typeof callback !== 'function') callback = function(data){console.log(data)};
		var command = 'telnetclient ' + delay + ' ' + ip + ' ' + port + ' ' + message;
		return ajaxCmd(command, callback);
	}
	
	function tcplistener(port, callback, opts){
		if (undef(opts)) opts = {};
		opts.port = port;
		return wsCmd({command: 'tcplistener', port: port, opts: opts}, callback);
	}
	
	function udplistener(port, callback, opts){
		if (undef(opts)) opts = {};
		opts.port = port;
		return wsCmd({command: 'udplistener', port: port, opts: opts}, callback);
	}
	
	function setServerVar(name, obj){
		window.websocket.emit('message', {
				command: 'set_var',
				name: name,
				data: obj
			},
			function(data){
				if (data === false) console.log('Server: Error saving variable.');
			}
		)
	}
	
	function getServerVar(name, callback){
		window.websocket.emit('message', {
				command: 'get_var',
				name: name,
			},
			function(data){
				if (callback) callback(data);
			}
		)
	}
	
	function setProjectVar(name, obj){
		window.websocket.emit('message', {
				command: 'set_project_var',
				name: name,
				data: obj,
				id: project.puid
			},
			function(data){
				if (data === false) console.log('Server: Error saving project variable.');
			}
		)
	}
	
	function getProjectVar(name, callback){
		window.websocket.emit('message', {
				command: 'get_project_var',
				name: name,
				id: project.puid
			},
			function(data){
				if (callback) callback(data);
			}
		)
	}
	
	function wsCmd(opts, callback){
		//return;
		if (Sandbox.sockets.length > 5000) Sandbox.sockets = [];
		if (undef(callback)) callback = Sandbox.callback;
		
		if (1) if (!undef(opts.opts)){
			for (var prop in opts.opts){
				opts[prop] = opts.opts[prop];
			}
			delete opts.opts;
		}
		//return;
		if (undef(opts.sock_id)) opts.sock_id = randomString(16); //return;
		if (opts.command === 'tcplistener' || opts.command === 'udplistener'){
			var obj = {port: opts.port, sock_id: opts.sock_id, onMessage: callback};
			if (opts.onDestroy) obj.onDestroy = opts.onDestroy;
			obj.destroy = function(onClose){
				if (!undef(onClose)) this.onDestroy = onClose; var self = this;
				window.websocket.emit('message', {
						command: opts.command.substring(0,3)+'close',
						sock_id: opts.sock_id
					}/*,
					function(data){
						self.onDestroy(data);
						removeFromArray(Sandbox.sockets, self);
					}*/
				);
			};
			var obj = new function(){
				this.port = opts.port;
				this.sock_id = opts.sock_id;
				this.onMessage = callback;
				this.onDestroy = !undef(opts.onDestroy) ? opts.onDestroy : noop;
				delete opts.onDestroy;
				this.destroy = this.close = function(onClose){
					if (!undef(onClose)) this.onDestroy = onClose;
					window.websocket.emit('message', {
							command: opts.command.substring(0,3)+'close',
							sock_id: opts.sock_id
						}/*,
						function(data){
							this.onDestroy(data);
							removeFromArray(Sandbox.sockets, this);
						}.bind(this)*/
					);
				}.bind(this);
			}
			Sandbox.sockets.push(obj); //change this to Sandbox.listeners?
		}
		if (opts.command === 'tcpopen' || opts.command === 'udpopen' ||
			opts.command === 'tcpclient' || opts.command === 'udpclient'){
			var obj = {ip: opts.ip, port: opts.port, sock_id: opts.sock_id, onMessage: callback};
			if (opts.onDestroy) obj.onDestroy = opts.onDestroy;
			obj.send = function(){
				var self = this;
				if (!undef(onMessage)) this.onMessage = onMessage;
				if (undef(onMessage)) this.onMessage = callback;
				if (undef(this.onMessage)) this.onMessage = function(data){console.log(data)};//noop;
				window.websocket.emit('message',
					{
						ip: this.ip, port: this.port,
						command: opts.command.substring(0,3)+'send',
						sock_id: opts.sock_id, message: hexToAscii(msg)
					}/*,
					function(data){
						self.onMessage(data);
					}*/
				);
			};
			obj.destroy = obj.close = function(onClose){
				var self = this;
				if (!undef(onClose)) this.onDestroy = onClose;
				window.websocket.emit('message',
					{
						ip: this.ip, port: this.port,
						command: opts.command.substring(0,3)+'close',
						sock_id: opts.sock_id
					}/*,
					function(data){
						self.onDestroy(data);
						removeFromArray(Sandbox.sockets, this);
					}*/
				);
			};
			var obj = new function(){
				this.ip = opts.ip;
				this.port = opts.port;
				this.sock_id = opts.sock_id;
				this.onMessage = callback;
				this.onDestroy = !undef(opts.onDestroy) ? opts.onDestroy : noop;
				delete opts.onDestroy;
				this.send = function(msg, onMessage){
					if (!undef(onMessage)) this.onMessage = onMessage;
					if (undef(onMessage)) this.onMessage = callback;
					if (undef(this.onMessage)) this.onMessage = function(data){console.log(data)};//noop;
					window.websocket.emit('message',
						{
							ip: this.ip, port: this.port,
							command: opts.command.substring(0,3)+'send',
							sock_id: opts.sock_id, message: hexToAscii(msg)
						}/*,
						function(data){
							this.onMessage(data);
						}.bind(this)*/
					);
				}.bind(this);
				this.destroy = this.close = function(onClose){
					if (!undef(onClose)) this.onDestroy = onClose;
					window.websocket.emit('message',
						{
							ip: this.ip, port: this.port,
							command: opts.command.substring(0,3)+'close',
							sock_id: opts.sock_id
						}/*,
						function(data){
							this.onDestroy(data);
							removeFromArray(Sandbox.sockets, this);
						}.bind(this)*/
					);
				}.bind(this);
			}
			Sandbox.sockets.push(obj);
		}
		if (opts.command === 'tcpclose' || opts.command === 'udpclose'){
			window.websocket.emit('message', opts, noop);
			for (var i=Sandbox.sockets.length; i--;){
				if (Sandbox.sockets[i].ip == opts.ip && Sandbox.sockets[i].port == opts.port){
					removeFromArray(Sandbox.sockets, Sandbox.sockets[i]);
				}
			}
		}
		if (Server.outbound) console.log('Sending to Server: ', opts);
		window.websocket.emit('message', opts/*,
			function(data){
				if (callback) callback(data);
				else console.log('databack', data);
			}*/
		);
		if (obj) return obj;
		else return opts.sock_id;
	}
	
	function ajaxCmd(script, callback, php){
		if (callback !== false) var _async = true;
		else var _async = false;
		if (undef(php)){
			if (wallcon) php = "../runscript.php";
			if (ncommand) php = "../scripts/index.php";
		}
		if (_async){
			var xmlhttp = new XMLHttpRequest();
			xmlhttp.open("POST", php, true);
			xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
			xmlhttp.send("executescript=yes&script="+script);
			xmlhttp.onreadystatechange = function(){
				if (xmlhttp.readyState == 4 && xmlhttp.status == 200){
					if (callback) callback(xmlhttp.responseText);			
				}
			}
			return false;
		}
		else {
			var xmlhttp = new XMLHttpRequest();
			xmlhttp.open("POST", php, false);
			xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
			xmlhttp.send("executescript=yes&script="+script);
			if (xmlhttp.status == 200) return xmlhttp.responseText;
			else return 'error';
		}
	}
	
	function nCmd(script, callback){
		
		ajaxCmd(script, callback);
		
	}
	
	function nCmdAsync(script, response, onComplete, onError){
		
		var tscript = script;
		
		var xmlhttp = new XMLHttpRequest();
		xmlhttp.open("POST", "../runscript.php", true);
		xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
		xmlhttp.send("executescript=yes&script="+tscript);

		xmlhttp.onreadystatechange = function(){
			if (xmlhttp.readyState == 4 && xmlhttp.status == 200){
				console.log('nCmdAsync response', script, xmlhttp.responseText);
				if (response){
					Sandbox.responses[response] = xmlhttp.responseText;
					if (onComplete) Sandbox.responses[response] = onComplete(xmlhttp.responseText, onError);
				}			
			}
		}
		
	}
	
	function subPanel(index, w, h, left, top){
	
		var npanel = project.panels[index];
		npanel.subpanel = true;
		npanel.core.basewidth = parseFloat(npanel.element.style.width);
		npanel.core.baseheight = parseFloat(npanel.element.style.height);
		$(project.currentpanel.element).append(npanel.element);
		npanel.resize(w, h);
		$(npanel.element).css({
			left: left+'px',
			top: top+'px',
			display: 'block',
			zIndex: 20000
		});
		for (var i=0; i<npanel.buttons.length; i++){
			npanel.buttons[i].textnode.style.fontSize = (parseFloat(npanel.buttons[i].element.style.height)/6)+'px';
			npanel.buttons[i].click = function(){
				this.down = true;
				tweencss({
					object: this.element,
					time: 0.08,
					props: {scale: 1.0},
					to: {scale: 1.14}
				});
				var thisscript = this.core.scripts[this.core.currentstate];
				eval(thisscript, this);	
			}.bind(npanel.buttons[i]);
			npanel.buttons[i].clickup = function(){
				this.down = false;
				tweencss({
					object: this.element,
					time: 0.08,
					props: {scale: 1.14},
					to: {scale: 1.0}
				});
				if (this.clickupscript){
					eval(this.clickupscript, this);
				}
			}.bind(npanel.buttons[i]);
		}
	}
	
	function saveGlobals(globals){
		//return;
		var results = Object.keys(globals);
		
		for (var i=0; i<results.length; i++){
			if (results[i] != 'top' && results[i] != 'window' && results[i] != 'location' && 
				results[i] != 'external' &&results[i] != 'chrome' &&results[i] != 'document' &&  
				results[i] != 'nCmd' && results[i] != 'panel' && results[i] != 'buttons' &&
				results[i] != 'widgets' && results[i] != 'canvas' && results[i] != 'Image' &&
				results[i] != 'setInterval' && results[i] != 'createElement' && results[i] != 'self' &&
				results[i] != 'gotopanel' && results[i] != 'reload' && results[i] != 'responses' &&
				results[i] != 'saveGlobals' && results[i] != '$' && results[i] != 'getButton' &&
				results[i] != 'getWidget' && results[i] != 'getPanel' && results[i] != 'getProject' &&
				results[i] != 'console'){
					Sandbox.globalvars[results[i]] = globals[results[i]];
			}
			if (results[i] == 'panelswitched') panelswitched = results[i];
		}
		
	}
	
	/*function construct(constructor, args) {
		function F() {
			return constructor.apply(this, args);
		}
		F.prototype = constructor.prototype;
		return new F();
	}
	// Sanboxer
	function sandboxcode(string, inject) {
		"use strict";
		var globals = [];
		for (var i in window) {
			// <--REMOVE THIS CONDITION
			if (i != "console")
				// REMOVE THIS CONDITION -->
				globals.push(i);
		}
		globals.push('"use strict";\n' + string);
		return construct(Function, globals).apply(inject ? inject : {});
	}
	//sandboxcode('console.log( this, window, top , self, parent, this["jQuery"], (function(){return this;}()));');*/
	
	//var global = {};
	
	function sandbox(code, _self){
		//return;
		//Sandbox.Args = Sandbox.Args.replace(/self,/g, '');
		//FIREFOX OVERWRITES CONSOLE WITH UNDEFINED WITHOUT THIS, MAY NEED OTHERS
		//Sandbox.Args = Sandbox.Args.replace(/console,/g, '');
		//Sandbox.Args = Sandbox.Args.replace(/prompt,/g, '');
		//Sandbox.Args = Sandbox.Args.replace(/alert,/g, '');
		//Sandbox.Args = Sandbox.Args.replaceAll('window,',''); //causes security risk
	
		//for (var prop in global){
		//	if (global.hasOwnProperty(prop)) Sandbox.frame.contentWindow[prop] = global[prop];
		//}
		
		var self = _self;
		var require = _require;

		//Sandbox.frame.contentWindow['console'] = {log: noop};
		//Sandbox.frame.contentWindow.console.log = Function.prototype.bind.call(console.log, console);
		
		//code = code.replace(/.ownerDocument/g, '');
		//code = code.replace(/.parentNode/g, '');
		//code += '; saveGlobals(this);';
		
		//for (var prop in global){
		//	if (global.hasOwnProperty(prop)) this[prop] = global[prop];
		//}
		
		if (!window.__moduled){
			for (var prop in Modules){
				if (Modules.hasOwnProperty(prop)) window[prop] = Modules[prop];
			}
			if (window.SVSi) for (var prop in window.SVSi){
				if (Modules.hasOwnProperty(prop)) window[prop] = window.SVSi[prop];
			}
			window.__moduled = true;
		}
		
		
		//return;
		//code = 'console.log("checkcheck")';
		//console.log('running', code);
		var codecopy = code;
		
		window.onerror = function(errorMsg, url, lineNumber){
			var id = 'unknown'; if (self && self.id) id = self.id; if (self && self.core && self.core.id) id = self.core.id;
			if (Server.debugging) websocket.emit('message', {command: 'jserror', args: 
			[errorMsg+',', 'script ID: "'+id+'",', 'line: '+(lineNumber-733), 'script: \n'+(codecopy.substring(0, 50)+' ...')]});
		}
		
		var ln = 0;
		
		if (0) code = 'try {'+code+'}\
		catch (err){\
			var id = \'unknown\'; if (self && self.id) id = self.id; if (self && self.core && self.core.id) id = self.core.id;\
			if (Server.debugging) websocket.emit(\'message\', {command: \'jserror\', args:\
				[err.message+\',\', \'script ID: "\'+id+\'",\', \'script: \'+(code.substring(0, 50)+\' ...\')]});\
			ln = err.lineNumber;\
		}';
		
		eval(code);
		
		//eval(code);
		
		//for (var prop in this){
		//	if (this.hasOwnProperty(prop)) global[prop] = this[prop];
		//}
		
		/*saveGlobals(this);*/ //return;
		//return sandboxcode(code);
		//return Sandbox.F(Sandbox.Args, code)();
		
	}
	
	function evalJavascript(script, self, bypass_security){
		
		if (!script || typeof script !== 'string') return;
		var tscript = script;
		
		while (tscript.indexOf('<nCmd>') != -1){
	
			if (tscript.indexOf('</nCmd>') != -1){
				var nscript = tscript.substring(
					tscript.indexOf('<nCmd>')+6,
					tscript.indexOf('</nCmd>')
				);
				var prenscript = '<nCmd>';
				var postnscript = '</nCmd>';
			}
			else {
				var nscript = tscript.substring(
					tscript.indexOf('<nCmd>')+6
				);
				var prenscript = '<nCmd>';
				var postnscript = '';
			}
			
			var tscript = tscript.replace(prenscript+nscript+postnscript, 
				"ajaxCmd('"+nscript.replace(/[\r\n]/g, "\\\n")+"');");

		}
		
		if (bypass_security === true && 0){ //disabled for now
			//todo: not tested
			window.panel = project.currentpanel;
			window.buttons = project.currentpanel.buttons;
			window.canvas = Sandbox.canvas;
			window.createElement = document.createElement;
			eval(tscript);
		}
		else {
			var global = {
				$: $,
				noop: noop,
				include: include,
				require: _require,
				gotopanel: gotopanel,
				asciiToHex: asciiToHex,
				hexToAscii: hexToAscii,
				json_encode: json_encode,
				json_decode: json_decode,
				tcpopen: tcpopen,
				tcpsend: tcpsend,
				tcpclose: tcpclose,
				tcpclient: tcpclient,
				udpclient: udpclient,
				telnetclient: telnetclient,
				tcplistener: tcplistener,
				udplistener: udplistener,
				websocket: websocket,
				get: get,
				getButton: getButton,
				getWidget: getWidget,
				getPanel: getPanel,
				getProject: getProject,
				wsCmd: wsCmd,
				ajaxCmd: ajaxCmd,
				nCmd: nCmd,
				nCmdAsync: nCmdAsync,
				subPanel: subPanel,
				self: self,
				project: project,
				currentpanel: project.currentpanel,
				buttons: project.currentpanel.buttons,
				widgets: project.currentpanel.widgets,
				canvas: Sandbox.canvas,
				Image: Image,
				sleep: sleep,
				setTimeout: setTimeout,
				setInterval: setInterval,
				clearTimeout: clearTimeout,
				clearInterval: clearInterval,
				createElement: document.createElement,
				tweencss: tweencss,
				responses: Sandbox.responses,
				saveGlobals: saveGlobals,
				int: function(m){return parseInt(m)},
				float: function(m){return parseFloat(m)},
				string: function(m){return m.toString()},
				//console: {log: function(m){console.log(m)}},
				time: time,
				millitime: millitime,
				Server: Server,
				Client: Client,
				openLink: window.open,
				setServerVar: setServerVar,
				getServerVar: getServerVar,
				setProjectVar: setProjectVar,
				getProjectVar: getProjectVar,
				ping: ping,
				username: username,
			}

			for (var property in Sandbox.globalvars){
				if (Sandbox.globalvars.hasOwnProperty(property)){
					global[property] = Sandbox.globalvars[property];
				}
			}
			for (var property in Modules){
				if (Modules.hasOwnProperty(property)){
					global[property] = Modules[property];
				}
			}

			sandbox(tscript, global);
		}
		
		return tscript;
		
	}
	
	function testJavascript(script){

		var tscript = script;
		
		var global = {
			$: $,
			saveGlobals: saveGlobals
		}
		
		for (var property in Sandbox.globalvars){
			if (Sandbox.globalvars.hasOwnProperty(property)){
				global[property] = Sandbox.globalvars[property];
			}
		}
		for (var property in Modules){
			if (Modules.hasOwnProperty(property)){
				global[property] = Modules[property];
			}
		}

		sandbox(tscript, global);
		
		return tscript;
		
	}
	
	