function is_object( mixed_var ){
    // Returns true if variable is an object  
    // 
    // version: 810.114
    // discuss at: http://phpjs.org/functions/is_object
    // +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   improved by: Legaev Andrey
    // +   improved by: Michael White (http://getsprink.com)
    // *     example 1: is_object('23');
    // *     returns 1: false
    // *     example 2: is_object({foo: 'bar'});
    // *     returns 2: true
    // *     example 3: is_object(null);
    // *     returns 3: false
    if(mixed_var instanceof Array) {
        return false;
    } else {
        return (mixed_var !== null) && (typeof( mixed_var ) == 'object');
    }
}


(function($) {
	 
	$.fn.bash = function(settings) {
	    
		// some txt formatting
		var prefix  = '> '; 
	    var newline = "\n";
	    var cmdline = newline+prefix;
	    var tab		= "\t";

	    // some history objects
	    var cmdHistory = [];
	    var historyCur = 0; 
	    
		var config = {
	    	style : {
				'position'  : 	'static',
				'background': 	'black',
			    'color'		: 	'white',
			    'border'	:	'1px solid silver',
			    'text-align': 	'left',
			    'width'		: 	'100%',
			    'height'	: 	'300px',
			    'font-size' : 	'10px',
			    'font-family':	'Courier New, Courier New, Courier, monospace'
	    	},
	    	keys : {
	    		k8  : 'dellast',
	    		k13 : 'enter',
	    		k33 : 'pgup',
	    		k34 : 'pgdown',
	    		k36 : 'pos1',
	    		k37 : 'leftarr',
	    		k38 : 'uparr',
	    		k39 : 'rightarr',
	    		k40 : 'downarr',
	    		k116: 'f5'
	    	},
	    	blockkeys : {
	    		'pgup' 		: true,
	    		'pgdown' 	: true,
	    		'pos1' 		: true
	    	},
	    	help : {
	    		help 		: 'help [-func] - shows all commands [-func: - shows man page for func]',
	    		calc		: 'calc equation - solves the equation',
	    		clear		: 'clear - clears bash',
	    		fread		: 'fread "file.ext" - outs file content to bash',
	    		fullscreen	: 'fullscreen - alias of maximize',
	    		log 		: 'log "msg" - echoes msg, adds cmdline',
	    		ls			: 'ls "../my/dir" [-p] - list directory contents [-p: in steps of 10 entries]',
	    		man 		: 'man [-func] - alias of help',
	    		maximize	: 'maximize - goto fullscreen mode',
	    		minimize	: 'minimize - quit fullscreen mode',
	    		out			: 'out "msg" - just outs the $msg',
	    		sql			: 'sql mode "query" - makes sql query and outputs results, mode can be one of: get,delete,update,show',
	    		quit 		: 'help - removes current bash instance'
	    	},
	    	files : {
	    		bashPHP : HTTP_ROOT+'ajax/plugin/admin/bash'
	    	}
	    };
	    
	    if (settings) $.extend(config, settings);
	    
	    // style it
	    for (i in config.style) {
			$(this).css(i,config.style[i]);
		}
	    
	    this.each(function() {

	    	var $bash = $(this);
	    	$bash.val(prefix);
	    	$bash.focus();
	    	
	    	/**
	    	 * listener
	    	 */
	    	$bash.keypress(function(ev){
	    		
				var key 		= ev.keyCode;
				var keyName		= eval('config.keys.k'+key);
				
				if (config.blockkeys[keyName] == true) {
					return false;
				}
				if (keyName == 'enter') {
					$bash.react();
					return false;
				} 
				if (keyName == 'f5') {
					$bash.clear();
					return false;
				} 
				if (keyName == 'uparr') {
					if (p = $bash.prevCmd()) $bash.replaceCmd(p);
					return false;
				}
				if (keyName == 'downarr') {
					if (p = $bash.nextCmd()) $bash.replaceCmd(p);
					return false;
				}
				if (keyName == 'leftarr' || keyName == 'dellast') {
					// here we fetch our text range object
					var start = $bash.getSelection();
					start = start.start - $bash.beforeRows().length;
					if (start == prefix.length) return false;
				}
				
				if (window.console && window.console.log) {
					//console.log(key + ' - ' + keyName);
				}
	    	});
	    	
	    	
	    	/**
	    	 * get last row in bash
	    	 */
	    	$bash.currentRow = function(){
	    		var cmdl = $bash.val();
	    		cmdl = cmdl.split(newline);
	    		return cmdl[cmdl.length-1];
	    	};
	    	
	    	
	    	/**
	    	 * get everything but last row in bash
	    	 */
	    	$bash.beforeRows = function(){
	    		var con = $bash.val();
	    		var cmd = con.split(newline);
	    		cmd = cmd[cmd.length-1];
	    		return con.replace(cmd,'');
	    	};
	    	
	    	
	    	/**
	    	 * get command with index previous to i
	    	 */
	    	$bash.prevCmd = function(){
	    		t = historyCur;
	    		if (cmdHistory[t] == undefined) return false;
	    		historyCur++;
	    		return cmdHistory[t];
	    	};
	    	
	    	/**
	    	 * get command with index previous to i
	    	 */
	    	$bash.nextCmd = function(){
	    		t = historyCur-1;
	    		if (cmdHistory[t] == undefined) return false;
	    		historyCur--;
	    		return cmdHistory[t];
	    	};
	    	
	    	
	    	/**
	    	 * replaces current cmd lines content with new content
	    	 */
	    	$bash.replaceCmd = function(newCmd){
	    		var cmdl = $bash.val();
	    		cmdl = cmdl.split(newline);
	    		last = cmdl.pop();
	    		cmdl = cmdl.join(newline);
	    		cmdl = cmdl + cmdline + newCmd; 
	    		$bash.val(cmdl);
	    	};
	    	
	    	
	    	
	    	/**
	    	 * outs a log message in new line and a cmd prompt afterwards 
	    	 */
	    	$bash.log = function (m) {
	    		$bash.val($bash.val()+newline+m+cmdline);
	    		$bash.animate({ scrollTop: $bash.height() }, 100);
	    	};
	    	
	    	
	    	/**
	    	 * quits the bash instance
	    	 */
	    	$bash.quit = function () {
	    		$bash.val($bash.val()+newline+'bye bye ...'+cmdline);
	    		$bash.remove();
	    	};
	    	
	    	/**
	    	 * go to fullscreen mode 
	    	 */
	    	$bash.maximize = function () {
	    		height = $(window).height()+"px";
	    		var style = {
					'height':height,'position':'fixed','top':'0px','left':'0px','z-index':'1000',
					'width':'99%','background':'black','font-size':'10px',
					'font-family':'Courier New, Courier New, Courier, monospace',
					'color':'white'
				}
		    	// style it
			    for (i in style) {
					$bash.css(i,style[i]);
				}
	    		$bash.val($bash.val()+newline+'welcome to fullscreen mode. type "minimize" to return to normal mode.'+cmdline);
	    		$bash.animate({ scrollTop: $bash.height() }, 100);
	    	};
	    	$bash.fullscreen = $bash.maximize;
	    	
	    	
	    	/**
	    	 * quit fullscreen mode 
	    	 */
	    	$bash.minimize = function () {
	    		// style it
			    for (i in config.style) {
					$bash.css(i,config.style[i]);
				}
	    		$bash.val($bash.val()+newline+'returned from fullscreen mode.'+cmdline);
	    		$bash.animate({ scrollTop: $bash.height() }, 100);
	    	};
	    	
	    	
	    	/**
	    	 * just output unformatted m to bash
	    	 */
	    	$bash.out = function(m) {
	    		$bash.val($bash.val()+m);
	    		$bash.animate({ scrollTop: $bash.height() }, 100);
	    	};
	    	
	    	
	    	/**
	    	 * just output unformatted m to bash
	    	 */
	    	$bash.clear = function(m) {
	    		$bash.val(prefix);
	    	};
	    	
	    	
	    	/**
	    	 * solve an equation 
	    	 */
	    	$bash.calc = function (m) {
	    		$bash.out(newline+'[calc "'+m+'"]');
	    		$bash.out(newline+eval(m)+newline);
	    	};
	    	
	    	
	    	
	    	/**
	    	 * called when keypress enter, calls functions 
	    	 */
	    	$bash.react = function () {
	    		var cmdl = $bash.currentRow();
	    		cmdl = cmdl.replace(prefix,'');
	    		var cmd = cmdl.split(' ');
	    		cmd = cmd[0];
	    		if (cmd == "") return false;
	    		cmdHistory.unshift(cmdl);
	    		if (eval("typeof $bash." + cmd + " == 'function'")) {
	    			var p = cmdl.substr(cmd.length+1);
	    			p = p.split('"');
	    			if (p.length > 1) {
	    				r = new Array();
	    				for (i in p) {
	    					trimmed = p[i].replace(/^\s+/, '').replace (/\s+$/, '');
	    					if (trimmed != p[i]) {
	    						trimmed = trimmed.split(' ');
	    						for (i in trimmed) {
	    							r.push(trimmed[i]);
	    						}
	    					} else {
	    						if (p[i].length > 0) r.push(trimmed);
	    					}
	    					
	    				}
	    				eval("$bash." + cmd + "([\""+r.join('","')+"\"]);");
	    				
	    			} else {
	    				eval("$bash." + cmd + "('"+p+"');");
	    			}
	    			
	    		} else {
	    			$bash.log("unknown function '"+cmd+"'. type help for help.");
	    		}
	    	};
	    	
	    	
	    	/**
	    	 * lists commands or shos help on a function
	    	 */
	    	$bash.help = function(which) {
	    		if (which != "") {
	    			var man = eval("config.help."+which);
	    			$bash.out(newline+man+cmdline);
	    			
	    			
	    		} else {
	    			var man = config.help;
	    			for (i in man) {
	    				$bash.out(newline+i+tab+' : '+man[i]);
	    			}
	    			$bash.out(cmdline);
	    		}
	    	};
	    	$bash.man = $bash.help;
	    	
	    	
	    	/**
	    	 * just output unformatted m to bash
	    	 */
	    	$bash.sql = function(params) {
	    		$bash.out(newline+'[sql query "'+params[1]+'"]'+newline);
	    		var settings = {'cmd':'sql','sql':params[1],'mode':params[0]};
	    		$bash.php(settings);
	    	};
	    	
	    	/**
	    	 * reads a file and outs it to bash
	    	 */
	    	$bash.fread = function(params) {
	    		$bash.out(newline+'[reading '+params[0]+']'+newline);
	    		var settings = {'cmd':'fread','file':params[0]};
	    		$bash.php(settings);
	    	};
	    	
	    	/**
	    	 * reads a file and outs it to bash
	    	 */
	    	$bash.ls = function(params) {
	    		$bash.out(newline+'[reading '+params[0]+']'+newline);
	    		var settings = {'cmd':'ls','dir':params[0],'mod':params[1]};
	    		if (params[1] != undefined) {
	    			if (params[2] == undefined) params[2] = 0;
	    			settings.offset = params[2];
	    			$bash.php(settings,function(){
	    				$bash.out('ls "'+params[0]+'" -p '+(parseInt(params[2])+10));
	    			});
	    		} else {
	    			$bash.php(settings);
	    		}
	    	};
	    	
	    	/**
	    	 * passes settings on to bashPHP and outputs results
	    	 */
	    	$bash.php = function(settings,callback){
	    		jQuery.get(config.files.bashPHP,settings,function(data){
	    			
	    			for (i in data) {
	    				if (is_object(data[i])) {
	    					
	    					$bash.out(i + tab);
	    					jQuery.each(data[i], function(key, value) { 
	    						$bash.out(value + tab);
	    					});
	    					$bash.out(newline);
	    					
	    				} else {
	    					$bash.out(i + tab + data[i]+newline);
	    				}
			    	}
	    			
	    			$bash.out(cmdline);
	    			
	    			if (callback != undefined) {
	    				callback();
	    			}
	    			
	    		},'json');
	    	}
	    	
	    	
	    });
	    
	    return this;
	};
	 
})(jQuery);