/************************************
Web Command Console
Copyright (C) 2005  Brian Murray
************************************/

//function console(prompt, history, iframe, hidden, root) {
function console(ttydiv, iframe, hidden, root) {
	this.curcommand = "";
	this.show = true;
	this.histarea = document.getElementsByName('history')[0];
	this.typefield = document.getElementsByName('current')[0];
	this.master = document.getElementById(iframe);
	this.ttydiv = ttydiv;
	
	this.hidden = document.getElementById(hidden);
	this.goStack = 0;
	this.ttys = new Array();
	this.attys = new Array();
	this.atty = "";
	this.Stack = new Array();
	this.Commands = new Array();
	this.dir = new Array();
	this.dir["/"] = document.createElement('iframe');
	this.dir["/"].src = root;
	var me = this;

this.tty = function tty() {
	this.writettyh = function writettyh() { return true; }
	this.writetty = function writetty() { return true; }
	this.activatetty = function activatetty() { return true; }
	this.deactivatetty = function deactivatetty() { return true; }
	this.name = "";
}

this.addTTY = function addTTY(div) {
	if (!document.getElementById(div)) return false;
	me.ttys[div] = new me.tty();
	var it = me.ttys[div];
	if (me.atty == "") me.atty = div;
	it.name = div;
	recurse = document.getElementById(div).childNodes;
	for (i = 0; i < recurse.length; i++) {
		if (recurse[i].className == "history") it.histarea = recurse[i];
		if (recurse[i].className == "current") it.current = recurse[i];
		if (recurse[i].className == "head") it.head = recurse[i];
	}
	it.writettyh = function writettyh(buffer) {
		it.histarea.innerHTML += buffer;
		it.histarea.scrollTop = it.histarea.scrollHeight;
	}
	it.writetty = function writetty(buffer) {
		it.current.innerHTML = buffer;
	}
	it.cleartty = function cleartty() {
		it.histarea.innerHTML = "";
	}
	it.activatetty = function activatetty() {
		it.head.style.background = "#afa";
	}
	it.deactivatetty = function deactivatetty() {
		it.head.style.background = "#ccc";
	}

}

this.buildTTY = function buildTTY(app) {
	if (app[0]) {
		var death = true;
		var z = me.getCommands();
		var cwd = this.getEnv("cwd");
		if (!cwd) cwd = "/";
		var zz = this.getDirCommands(cwd);
		for (var i in zz) z[z.length] = "./" + zz[i];
		for (var i in z)
			if (z[i] == app[0]) { death = false; break; }
		if (death) {
			this.print("Sorry, cannot build a tty without a proper app to exec\n");
			return false;
		}
	} else return false;
	var ff = document.getElementById(me.ttydiv);
	var buff = "";
	var i = 0;
	while (document.getElementById('tty' + i)) { i = i + 1; }
	var ttyname = 'tty' + i;
	var ttydiv = document.createElement('div');
	ttydiv.id = ttyname;
	ttydiv.className = 'console';
	ttydiv.onclick = function onclick() { var a = ttyname;  me.chTTY(a); }
	var ttyhead = document.createElement('div');
	ttyhead.onmousedown = function onmousedown(e) { var t = this.ttyname; dragStart(e, t); }
	ttyhead.ttyname = ttyname;
	ttyhead.className = "head";
	ttyhead.innerHTML = "Web Command Console (" + ttyname + ")";
	ttydiv.appendChild(ttyhead);
	var ttyhistory = document.createElement('div');
	ttyhistory.className = "history";
	ttydiv.appendChild(ttyhistory);
	var ttycurrent = document.createElement('div');
	ttycurrent.className = "current";
	ttydiv.appendChild(ttycurrent);
	ff.appendChild(ttydiv);
	me.addTTY(ttyname);
	me.chTTY(ttyname);
	me.exec(app);
}

this.topTTY = function topTTY() {
	if (me.ttys[me.atty])
		return me.ttys[me.atty];
	return false;
	for (var i in me.ttys) {
		return me.ttys[i];
	}
}
this.chTTY = function chTTY(tty) {
	if (me.ttys[me.atty] && me.ttys[me.atty].deactivatetty)  me.ttys[me.atty].deactivatetty();
	if (me.ttys[tty]) {
		me.atty = tty;
		if (me.ttys[me.atty].deactivatetty)  me.ttys[me.atty].activatetty();
	}
	return true;
	if (me.ttys[tty])
		return me.ttys[tty];
	else return false;
	for (var i in me.ttys) {
		return me.ttys[i];
	}
}

this.loadURI = function loadURI(uri) {
	me.master.src = uri;
}

this.clearHistory = function clearHistory(buffer) {	
	a = this.getEnv("tty");
	a.cleartty();
	//me.histarea.innerHTML = "";
}

this.print = function print() {
	if (arguments.length < 1) return false;
	var arg = arguments[0];
	a = this.getEnv("tty");
	if (!a) a = me.ttys[me.atty];
	for (i = 0; i < arg.length; i++) {
		switch(arg.substr(i, 1)) {
			case '\n':
				a.writettyh(me.curcommand + "<br/>");
			case '\r':
				me.curcommand = "";
				break;
			case '&':
				me.curcommand += "&amp;";
				break;
			case '<':
				me.curcommand += "&lt;";
				break;
			case '>':
				me.curcommand += "&gt;";
				break;
			default:
				me.curcommand += arg.substr(i, 1);
		}
	}
	//firebug(a);
	//alert(buff);
	a.writetty(me.curcommand);
}
this.printf = function printf() {
	if (arguments.length < 1) return false;
	var decihold = 1;
	a = this.getEnv("tty");
	var arg = arguments[0];
	for (i = 0; i < arg.length; i++) {
		switch(arg[i]) {
			case '\n':
				a.writettyh(me.curcommand + "<br/>");
			case '\r':
				me.curcommand = "";
				break;
			case '&':
				me.curcommand += "&amp;";
				break;
			case '<':
				me.curcommand += "&lt;";
				break;
			case '>':
				me.curcommand += "&gt;";
				break;
			case '%':
				var num = 0;
				for (var j = 0; j < 6; j++) {
					
				}
			break;
			default:
				me.curcommand += arg[i];
		}
	}
	a.writetty(me.curcommand);
}
this.printCodes = function printCodes() {
	if (arguments.length < 1) return false;
	var arg = arguments[0];
	a = this.getEnv("tty");
	for (i = 0; i < arg.length; i++) {
		switch(arg.substr(i, 1)) {
			case '\n':
				a.writettyh(me.curcommand + "<br/>");
			case '\r':
				me.curcommand = "";
				break;
			default:
				me.curcommand += arg.substr(i, 1);
		}
	}
	a.writetty(me.curcommand);
}
this.process = function process() {
	this.pid = 0;
	this.ppid = 0;
	this.command = "";
	this.cwd = "";
	this.starttime = Object();
	this.env = Array();
	this.program = Object();
	this.tty = Object();
}
this.addCommand = function addCommand(string, funct) {
	if(!me.Commands[string])
		me.Commands[string] = funct;
}
this.exit = function exit() {
	var tempStack = new Array();
	var ppid = this.getEnv("ppid");
	var a = this.getEnv("tty");
	if (me.attys[a.name].program == this) {
	//alert(ppid + " : " + me.procbypid(ppid));
		if (me.procbypid(ppid) && ppid != false) me.attys[a.name] = me.procbypid(ppid);
		else {
			cc = false;
			for (var i in me.Stack) {
				if (me.Stack[i].program.getEnv("tty").name == a.name && me.Stack[i].program != this) {
					me.attys[a.name] = me.Stack[i];
					cc = true;
					break;
				} 
			}
			//alert(document.getElementById(a.name).display);
			if (!cc) document.getElementById(a.name).style.display = "none";
		}
	}
			
	for (var i in me.Stack) {
		if (this != me.Stack[i].program) {
			tempStack[tempStack.length] = me.Stack[i];
		} else {
			if (me.Stack[i].program.signal)
				me.Stack[i].program.signal("SIGKILL");
			me.Stack[i].program = null;
			me.Stack[i] = null;
		}
	}
	me.Stack = null;
	me.Stack = tempStack;
	if (!me.Stack[me.Stack.length - 1]) {
		me.print("Done\n");
		window.location = me.master.src;
		return 0;
	}
	var topStack = me.Stack[me.Stack.length - 1];
	if (topStack.program) topStack = topStack.program;
	if (topStack.main) topStack.main();
	me.chprocess(ppid);
	if (!me.goStack.program) me.goStack = me.Stack[me.Stack.length - 1];
}
this.getiframe = function getiframe() {
	return me.master.contentWindow;
}
this.addapp = function addapp(node) {
	me.hidden.appendChild(node);
}
this.getCommands = function getCommand() {
	var ret = new Array();
	for (var i in me.Commands) {
		ret[ret.length] = i;
	}
	return ret;

}
this.thisproc = function thisproc(what) {
	for (var i in me.Stack) {
		if (what == me.Stack[i].program)
			return me.Stack[i];
	}
	return false;
}
this.procbypid = function procbypid(pid) {
	if (pid == false && pid != 0 ) return false;
	for (var i in me.Stack) {
		if (me.Stack[i].pid == pid)
			return me.Stack[i];
	}
	return false;

}
this.getEnv = function getEnv(it) {
	switch (it) {
	case "pid":
	case "ppid":
	case "command":
	case "cwd":
	case "tty":
	for (var i in me.Stack) {
		if (this == me.Stack[i].program) {
			var s = me.Stack[i];
			return s[it];
		}
	}
	default:
	for (var i in me.Stack) {
		if (this == me.Stack[i].program) {
			var s = me.Stack[i].env;
			return s[it];
		}
	}
	return false;
	}
}
this.setEnv = function setEnv(it, to) {
	switch (it) {
	case "pid":
	case "ppid":
	case "command":
	case "cwd":
	case "tty":
	return false;
	break;
	default:
	for (var i in me.Stack) {
		if (this == me.Stack[i].program) {
			var s = me.Stack[i].env[it] = to;
		}
	}
	}

}

this.cd = function cd(pathspec) {
	if (!pathspec) {
		return false;
	}
	var paths = pathspec.split('/');
	var thisproc = me.thisproc(this);
	var path = thisproc.cwd;
	var holdpath = new Array();
	//this.print(" " + thisproc.pid + "\n");
	holdpath[0] = "/";
	if (paths[0] != "") {
		var temp = path.split('/');
		if (temp[0] != "") {
			me.print("Error in path\n");
			return false;
		}
		for (var i = 1; i < temp.length; i++) {
			if (temp[i] != "") {
				if (temp[i] == "..") {
					if (holdpath.length > 1) {
						var temp1 = new Array();
						for (var j = 0; j < (holdpath.length - 1); j++) 
							temp1[j] = holdpath[j];
						holdpath = temp1;
						//holdpath[holdpath.length - 1] = "";
					}
				} else {
					holdpath[holdpath.length] = temp[i] + "/";
				}
			}
			
		}
		//holdpath[0] = paths[0] + "/";
		//path += paths[0] + "/";
	}
	for (var i = 0; i < paths.length; i++) {
		if (paths[i] != "") {
			if (paths[i] == "..") {
				if (holdpath.length > 1) {
					var temp1 = new Array();
					for (var j = 0; j < (holdpath.length - 1); j++) 
						temp1[j] = holdpath[j];
					//holdpath[holdpath.length - 1] = "";
					holdpath = temp1;
				}
			} else {
				holdpath[holdpath.length] = paths[i] + "/";
			}
			//path += paths[i] + "/";
		}
	}
	path = "";
	for (var i = 0; i < holdpath.length; i++) {
		path += holdpath[i];
	}
	me.loadPath(path);
	if (me.dir[path]) {
		me.print(path + "\n");
		thisproc.cwd = path;
		return true;
	} else {
		me.print("Cannot Change Dir\n");
		return false;
	}
}
this.loadPath = function loadPath(pathspec) {
	//me.print(pathspec + "\n");
	var paths = pathspec.split('/');
	if (paths[0] != "") return false;
	var path = "/";
	for (var i = 1; i < paths.length; i++) {
		//me.print("aPath: " + path + " : " + paths[i] + "\n");
		if (!paths[i]) return true;
		if (!me.dir[path]) {
			me.print("Cannot find path: " + path + "\n");
			return false;
		} else {
			/*
			for (var j in me.dir[path].contentWindow) {
				me.print(j + " " + me.dir[path].contentWindow[j] + "\n");

			}
			*/
			
			if (!me.dir[path].contentWindow) {
				me.print("Oops. Something broke Content. " + path + "\n");
				return false;
			}
			if (!me.dir[path].contentWindow.Paths) {
				//me.print("A: " + me.dir[path].src + "\n");
				me.print("Oops. Something broke in Paths. " + path + "\n");
				return false;
			}
			if (!me.dir[path + paths[i] + "/"]) {
				if (me.dir[path].contentWindow.Paths[paths[i]]) {
					me.dir[path + paths[i] + "/"] = document.createElement('iframe');
					me.dir[path + paths[i] + "/"].src = "/mod.php?name=Console&file=inc&inc=" + me.dir[path].contentWindow.Paths[paths[i]];
					me.addapp(me.dir[path + paths[i] + "/"]);
				} else {
					me.print("Cannot Load: " + path + paths[i] + "/\n");
				}
			}
			/*
			}
			for (var j in me.dir[path].contentWindow.Paths) {
				if (!me.dir[path + j + "/"]) {
				//me.print("Path: " + path + " : " + j + "\n");
				//me.dir[path + j + "/"] = me.dir[path].document.Paths[j]; //new element
				me.dir[path + j + "/"] = document.createElement('iframe');
				me.dir[path + j + "/"].src = me.dir[path].contentWindow.Paths[j];
				me.addapp(me.dir[path + j + "/"]);
				}
			}
			*/
			path += paths[i] + "/";
		}
	}
		//me.print("--------------\n");
	return true;

}
this.getDirs = function getDirs(path) {
	if (!path) {
		var thisproc = me.thisproc(this);
		var path = thisproc.cwd;
	}
	var paths = path.split('/');
	var ret = new Array();
	//path = "";
	//for (var i in me.dir) me.print(i + "\n");
	//me.print("--------------" + path + "\n");
	//for (var i = 0; i < (paths.length - 1); i++) path += paths[i] + "/";
	//me.print(path + "\n");
	//me.print(me.dir[path].src + "\n");
	if (me.dir[path] && me.dir[path].contentWindow && me.dir[path].contentWindow["Paths"]) {
		for (var i in me.dir[path].contentWindow.Paths) {
			ret[ret.length] = i;
		}
	}// else me.print("-No Paths!-\n");
	return ret;
}
this.getDirCommands = function getDirCommands(path) {
	if (!path) {
		var thisproc = me.thisproc(this);
		var path = thisproc.cwd;
	}
	var paths = path.split('/');
	var ret = new Array();
	if (me.dir[path] && me.dir[path].contentWindow && me.dir[path].contentWindow.Commands) {
		for (var i in me.dir[path].contentWindow.Commands) {
			ret[ret.length] = i;
		}
	}// else me.print("-No Commands!-\n");
	return ret;
}

this.exec = function exec(command) {
	var thispath = /^\.\//;
	if (me.Commands[command[0]] || thispath.test(command[0])) {
		var stop = false;
		var point = new me.process;
		if (!point) return false;
		var topStack = point;
		if (thispath.test(command[0])) {
			var thisproc = me.thisproc(this);
			var path = thisproc.cwd;
			if (!path) path = "/";
			//me.print("A: " + path + "\n");
			//for (var i in me.dir[path].contentWindow.Commands) me.print("B: " + i + "\n");
			if (me.dir[path] && me.dir[path].contentWindow.Commands[command[0].replace(thispath, "")]) 
				topStack.program = new me.dir[path].contentWindow.Commands[command[0].replace(thispath, "")](command);
			else return false;

			
		} else topStack.program = new me.Commands[command[0]](command);
		
		if (!topStack.program) return false;
		
		topStack.ppid = this.getEnv("pid");
		if ( topStack.ppid != 0 && topStack.ppid == false ) topStack.ppid = -1;
		
		topStack.cwd = this.getEnv("cwd");
		if (!topStack.cwd) topStack.cwd = "/";
		
		a = this.getEnv("tty");
		if (!a || !a.writetty || !a.writettyh)
			topStack.tty = me.topTTY();
		else
			topStack.tty = a;
		if (!topStack.tty) topStack.tty = me.topTTY();
		//alert(topStack.tty)
		if (me.procbypid(this.getEnv("pid"))) {
			var z = me.procbypid(this.getEnv("pid")).env;
			for (var i in z)
				topStack.env[i] = z[i];
			
			//topStack.env = me.procbypid(this.getEnv("pid")).env;
		}	

		topStack.starttime = new Date();
		
		var pid = 0;
		
		while (me.procbypid(pid)) {
		//do {
			pid = (Math.round(Math.random()*100) % 99) + 1;
		} //while (me.procbypid(pid));
		topStack.pid = pid;
		for (var i in command) {
			topStack.command += command[i] + " ";
		}
		topStack = topStack.program;
		topStack.exec = me.exec;
		topStack.print = me.print;
		topStack.printCodes = me.printCodes;
		topStack.getiframe = me.getiframe;
		topStack.loadURI = me.loadURI;
		topStack.addapp = me.addapp;
		topStack.getCommands = me.getCommands;
		topStack.getDirCommands = me.getDirCommands;
		topStack.getEnv = me.getEnv;
		topStack.setEnv = me.setEnv;
		topStack.getDirs = me.getDirs;
		topStack.cd = me.cd;
		topStack.clearHistory = me.clearHistory;
		topStack.psaux = me.psaux;
		topStack.chprocess = me.chprocess;
		topStack.buildTTY = me.buildTTY;
		if (topStack.exit) stop = true;
		topStack.exit = me.exit;
		me.Stack[me.Stack.length] = point;
		me.goStack = me.Stack[me.Stack.length - 1];
		me.attys[topStack.getEnv("tty").name] = me.goStack;
		if (stop) {
			if (!topStack.main) me.print("Exit called, but no main!\n");
			else topStack.main(command);

			topStack.exit();
		}
		topStack = me.Stack[me.Stack.length - 1].program;
		
		if (me.goStack.program.main) {
			me.goStack.program.main(command);
		}
		
		return true;
	} else {
		return false;
	}
}
this.psaux = function psaux() {
	var ret = new Array();
	
	for ( var i = 0; i < me.Stack.length; i++) {
		//me.print("PID: " + me.Stack[i].pid + "\n");
		ret[i] = new Array();
		ret[i]["pid"] = me.Stack[i].pid;
		ret[i]["ppid"] = me.Stack[i].ppid;
		ret[i]["tty"] = me.Stack[i].tty.name;
		ret[i]["date"] = me.Stack[i].starttime;
		ret[i]["command"] = me.Stack[i].command;
	}
	return ret;

}
this.chprocess = function chprocess(pid) {
	for (var i = 0; i < me.Stack.length; i++) {
		if (me.Stack[i].pid == pid) {
			me.goStack = me.Stack[i];
			if (me.goStack.program && me.goStack.program.main)
			me.goStack.program.main();
			return true;
		}
	}
	return false;
}
this.input = function input(e) {
	//var topStack = me.Stack[me.Stack.length - 1];
	//var topStack = me.goStack;
	var topStack = me.attys[me.atty];
	//alert(me.atty);
	if (!topStack) {
		me.print("Nothing on the stack\n");
		window.location = me.master.src;
		return false;
	}
	var topStack = topStack.program;
	if (!topStack) {
		me.print("Nothing Usable on the Stack\n");
		return false;
	}
	if (topStack.input) {
		topStack.input(e);
	} else {
		if (topStack.controlCode)
			topStack.controlCode(e.ctrlKey, e.altKey);
		if (e.charCode) {
			var code = e.charCode;
			if (topStack.takeCode)
				topStack.takeCode(code);
			else if (topStack.stdin)
				topStack.stdin(String.fromCharCode(code));
		} else if (e.keyCode) {
			var code = e.keyCode;

			if (!document.all || (code < 32 && topStack.editCode))
				topStack.editCode(code);
			else if (topStack.takeCode)
				topStack.takeCode(code);
			else if (topStack.stdin)
				topStack.stdin(String.fromCharCode(code));
		}
	}
}
me.addapp(me.dir["/"]);
//me.addTTY(div);
//me.addTTY("tty1");

}


