
/* Works with AjaxGateway php class
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */

function AjaxClient(instanceName) {
	this.instanceName   = instanceName;

	this.hostName       = undefined;
	this.secureHostName = undefined;

	this.requestSchema = '<?xml version="1.0" encoding="utf-8" ?><request><command name="" /></request>';
	this.connecting = false;
	this.httpsready = false;
	this.modeXML    = true;
	this.timer      = undefined;
	this.gateway    = '';
	this.piframe    = '';
	this.lastCall   = {command: undefined, args: undefined, callback: undefined, errorHandler: undefined, debug: undefined};
	this.entities   = ['&',     '<',    '>',    "'",      '"'     ];
	this.sanitaries = ['&amp;', '&lt;', '&gt;', '&apos;', '&quot;'];
}
AjaxClient.prototype.getXMLDomDocument = function() {

	if(window.ActiveXObject) {
		var prefixes = ['MSXML2', 'Microsoft', 'MSXML', 'MSXML3'];
		for(var i=0; i<prefixes.length; i++) {
			try {
				return new ActiveXObject(prefixes[i]+'.DomDocument');
			} catch(e) { };
		}
		throw new Error('-- Ajax Debugger --\nCould not find an installed XML parser.');
	} else if(document.implementation) {
		return document.implementation.createDocument('' , '' , null);
	} else {
		return null;
	}

};
AjaxClient.prototype.createAsyncRequest = function() {

	this.httpsready = true;
	clearTimeout(this.timer);

	var areq = new AsyncRequest(this);
	var client = this;

	areq.getPostData = function() {
		return client.data;
	};
	areq.getContentType = function() {
		return client.modeXML ? 'text/xml' : 'application/x-www-form-urlencoded';
	};
	areq.responseHandler = this.responseHandler;
	areq.execute();
};
AjaxClient.prototype.createXMLPostData = function(args) {
	try {
		var dom = this.getXMLDomDocument();
	} catch(e) {
		return null;
	}

	if(!dom) return null;

	if(window.ActiveXObject) {
		dom.async = 'false';
		dom.loadXML(this.requestSchema);
	} else {
		dom.appendChild(dom.createElement('request').appendChild(dom.createElement('command')));
	}
	var elmCommand = dom.getElementsByTagName('command')[0];
	elmCommand.setAttribute('name', this.htmlEntities(this.lastCall.command));

	elmArguments = dom.createElement('arguments');
	if(typeof(args) == 'object') {
		if(args[0]) {
			for(var i=0; i<args.length; i++) {
				if(typeof(args[i]) == 'object') {
					elmArgument = dom.createElement('argument');
					elmArgument.setAttribute('name', this.htmlEntities(i));
					elmArgument = this.crawlXMLArguments(args[i], dom);
					elmArguments.appendChild(elmArgument);
				} else {
					elmArgument = dom.createElement('argument');
					elmArgument.setAttribute('name', this.htmlEntities(i));
					elmArgument.setAttribute('value', this.htmlEntities(args[i]));
					elmArguments.appendChild(elmArgument);
				}
			}
		} else {
			for(var i in args) {
				if(typeof(args[i]) == 'object') {
					elmArgument = dom.createElement('argument');
					elmArgument.setAttribute('name', this.htmlEntities(i));
					elmArgument = this.crawlXMLArguments(args[i], dom);
					elmArguments.appendChild(elmArgument);
				} else {
					elmArgument = dom.createElement('argument');
					elmArgument.setAttribute('name', this.htmlEntities(i));
					elmArgument.setAttribute('value', this.htmlEntities(args[i]));
					elmArguments.appendChild(elmArgument);
				}
			}
		}
	} else {
		elmArgument = dom.createElement('argument');
		elmArgument.setAttribute('value', args);
		elmArguments.appendChild(elmArgument);
	}
	elmCommand.appendChild(elmArguments);

	return dom;
};
AjaxClient.prototype.crawlXMLArguments = function(argument, dom) {
	if(argument[0]) {
		for(var i=0; i<argument.length; i++) {
			elm = dom.createElement('argument');
			if(typeof(argument[i]) == 'object') {
				elm = this.crawlXMLArguments(argument[i], dom);
				elmArgument.appendChild(elm);
			} else {
				elm.setAttribute('value', this.htmlEntities(argument[i]));
				elmArgument.appendChild(elm);
			}
		}
	} else {
		for(var i in argument) {
			if(typeof(argument[i]) == 'object') {
				elm = dom.createElement('argument');
				elm.setAttribute('name', this.htmlEntities(i));
				elm = this.crawlXMLArguments(argument[i], dom);
				elmArgument.appendChild(elm);
			} else {
				elm = dom.createElement('argument');
				elm.setAttribute('name', this.htmlEntities(i));
				elm.setAttribute('value', this.htmlEntities(argument[i]));
				elmArgument.appendChild(elm);
			}
		}
	}
	return elmArgument;
};
AjaxClient.prototype.crawlXMLReturns = function(node, isArray) {
	var rerturns = isArray ? new Array() : new Object();
	for(var i=0; i<node.childNodes.length; i++) {
		var n = node.childNodes[i];
		if(n.hasChildNodes()) {
			rerturns[n.getAttribute('name')] = this.crawlXMLReturns(n, Number(n.firstChild.getAttribute('name')) == 0);
		} else {
			rerturns[n.getAttribute('name')] = this.htmlEntitiesDecode(n.getAttribute('value'));
		}
	}
	return rerturns;
};
AjaxClient.prototype.handleXMLResponse = function(response) {
	if(window.ActiveXObject) {
		var dom = this.getXMLDomDocument();
		dom.async = 'false';
		dom.loadXML(response);
		var de = dom.documentElement;
	} else if(document.implementation) {
		var de = xmlhttp.responseXML;
	}

	var elmReturns = de.getElementsByTagName('returns')[0];
	var len = elmReturns.childNodes.length;
	if(len == 1 && !elmReturns.childNodes[0].getAttribute('name')) {
		var rerturns = elmReturns.childNodes[0].getAttribute('value');
	} else {
		if(elmReturns.childNodes[0].getAttribute('name') == '0') {
			var rerturns = new Array();
		} else {
			var rerturns = new Object();
		}
		for(var i=0; i<len; i++) {
			var node = elmReturns.childNodes[i];
			if(elmReturns.childNodes[i].hasChildNodes()) {
				rerturns[node.getAttribute('name')] = this.crawlXMLReturns(node, Number(node.firstChild.getAttribute('name')) == 0);
			} else {
				rerturns[node.getAttribute('name')] = this.htmlEntitiesDecode(node.getAttribute('value'));
			}
		}
	}
	return rerturns;
};
AjaxClient.prototype.createMIMEPostData = function(args) {
	var strObject = 'array(';
	var strTemp   = '';
	if(typeof(args) == 'object') {
		if(args[0]) {
			for(var i=0; i<args.length; i++) {
				if(typeof(args[i]) == 'object') {
					strTemp += this.crawlMIMEArguments(args[i]);
				} else {
					strTemp += ',\''+i+'\'=>'+'\''+args[i]+'\'';
				}
			}
			strObject += strTemp.substring(1);
			strObject += ');';
		} else {
			for(var i in args) {
				if(typeof(args[i]) == 'object') {
					strTemp += this.crawlMIMEArguments(args[i]);
				} else {
					strTemp += ',\''+i+'\'=>'+'\''+args[i]+'\'';
				}
			}
			strObject += strTemp.substring(1);
			strObject += ');';
		}
	} else {
		strObject = '\''+args+'\'';
	}
	return strObject;
};
AjaxClient.prototype.crawlMIMEArguments = function(argument) {
	var strObject = ',array(';
	var strTemp   = '';
	if(argument[0]) {
		for(var i=0; i<argument.length; i++) {
			if(typeof(argument[i]) == 'object') {
				strTemp += this.crawlXMLArguments(argument[i]);
			} else {
				strTemp += ',\''+i+'\'=>'+'\''+argument[i]+'\'';
			}
		}
	} else {
		for(var i in argument) {
			if(typeof(argument[i]) == 'object') {
				strTemp += this.crawlMIMEArguments(argument[i]);
			} else {
				strTemp += ',\''+i+'\'=>'+'\''+argument[i]+'\'';
			}
		}
	}
	strObject += strTemp.substring(1);
	strObject += ')';
	return strObject;
};
AjaxClient.prototype.handleMIMEResponse = function(response) {
	if(response.charAt(0) == '{' || response.charAt(0) == '[') {
		eval('var responseObj = '+response);
		return responseObj;
	} else {
		return response;
	}
};
AjaxClient.prototype.call = function(command, args, callback, errorHandler, debug) {

	this.connecting = true;

	this.lastCall.command      = command;
	this.lastCall.args         = args;
	this.lastCall.callback     = callback;
	this.lastCall.errorHandler = errorHandler;
	this.lastCall.debug        = debug;

	this.data = null;
	if(this.modeXML) {
		this.data = this.createXMLPostData(args);
	}
	if(!this.data) {
		this.modeXML = false;
		this.data  = 'command='+escape(command)+'&';
		this.data += 'arguments='+escape(this.createMIMEPostData(args));
	}

	if(this.data.length < 1) {
		if(this.lastCall.errorHandler) eval(this.lastCall.errorHandler+'(this.lastCall.args);');
		else alert('-- Ajax Debugger --\Failed to create post data.');
		this.connecting = false;
		return;
	}

	if(this.gateway.indexOf('https') != -1) {
		var path = this.gateway.substring(this.gateway.indexOf('?'));
		if(!this[this.instanceName+'PIFrame']) {
			var trial = document.createElement('div');
			trial.setAttribute('id', this.instanceName+'PIFrame');
			trial.innerHTML = '<iframe src="'+path+'" style="display: none;" onload="'+this.instanceName+'.createAsyncRequest();" onerror="alert(\'iframe error\')"></iframe>';
			document.getElementsByTagName('body')[0].appendChild(trial);
			this[this.instanceName+'PIFrame'] = trial;
		}
		if(this[this.instanceName+'PIFrame'].src != path) {
			httpsready = false;
			this[this.instanceName+'PIFrame'].firstChild.src = this.gateway;
		}
	} else {
		this.httpsready = true;
		this.createAsyncRequest();
	}

};
AjaxClient.prototype.responseHandler = function(client, xmlhttp) {
	if(xmlhttp.readyState == 4) {
		var lc = client.lastCall;
		if(xmlhttp.status == 200) {
			if(lc.debug) alert('-- Ajax Debugger --\nServer Response(limit '+lc.debug+' chars):\n\n'+xmlhttp.responseText.substring(0, lc.debug));
			try {
				if(client.modeXML) {
					var rerturns = client.handleXMLResponse(xmlhttp.responseText);
				} else {
					var rerturns = client.handleMIMEResponse(xmlhttp.responseText);
				}
			} catch(e) {
				if(lc.errorHandler) {
					client.connecting = false;
					eval(lc.errorHandler+'(lc.args);');
					return;
				}
				else alert('-- Ajax Debugger --\nServer Error: \n\n'+xmlhttp.responseText);
			}
			eval(lc.callback+'(rerturns);');
		} else {
			client.createAsyncRequest();
			return;
			//if(lc.errorHandler) eval(lc.errorHandler+'(lc.args);');
			//else alert('-- Ajax Debugger --\nError occured: '+xmlhttp.status+': '+xmlhttp.statusText);
		}
		client.connecting = false;
	}
};
AjaxClient.prototype.htmlEntities = function(str) {
	var r = String(str);
	var e = this.entities;
	var s = this.sanitaries;
	for(var i=0; i<e.length; i++) {
		r = r.split(e[i]).join(s[i]);
	}
	return r;
};
AjaxClient.prototype.htmlEntitiesDecode = function(str) {
	var r = String(str);
	var e = this.entities;
	var s = this.sanitaries;
	for(var i=0; i<e.length; i++) {
		r = r.split(s[i]).join(e[i]);
	}
	return r;
};

function AsyncRequest(ajaxClient) {
	this.xmlhttp = null;
	this.responseHandler = null;
	this.method = 'POST';
	this.ajaxClient     = ajaxClient;
	this.gateway        = ajaxClient.gateway;
	this.hostName       = ajaxClient.hostName;
	this.secureHostName = ajaxClient.secureHostName;
}
AsyncRequest.prototype.execute = function() {
	var lc = this.ajaxClient.lastCall;
	var xmlhttp = this.getXmlHttpRequest();
	if(!xmlhttp) {
		if(lc.errorHandler) lc.errorHandler(lc.args);
		else alert('-- Ajax Debugger --\nThis browser does not support XMLHttpRequest.');
		this.ajaxClient.connecting = false;
		return;
	}

	xmlhttp.abort();

	var callback = this.responseHandler;
	var client   = this.ajaxClient;

	var ua = navigator.userAgent
	var safari = ua.indexOf('Safari') != -1;
	var konqueror = ua.indexOf('Konqueror') != -1;
	var mozes = ((a=navigator.userAgent.split('Gecko/')[1]) ? a.split(' ')[0]:0) >= 20011128;

	if(window.opera || safari || mozes) {
		xmlhttp.onload = function() {
			if(callback) callback(client, xmlhttp);
		};
	} else {
		xmlhttp.onreadystatechange = function() {
			if(callback) callback(client, xmlhttp);
		};
	}

	try {
		xmlhttp.open(this.method, this.gateway, true);
		xmlhttp.setRequestHeader('Content-Type', this.getContentType());
		if(MJA) xmlhttp.setRequestHeader('User-Agent', 'J. River Internet Reader/2.0 (compatible; Windows-Media-Player/10)');
		xmlhttp.send(this.getPostData());
	} catch(e) {
		try {
			xmlhttp.abort();
			if(window.opera || safari || mozes) {
				xmlhttp.onload = function() {
					if(callback) callback(client, xmlhttp);
				};
			} else {
				xmlhttp.onreadystatechange = function() {
					if(callback) callback(client, xmlhttp);
				};
			}
			xmlhttp.open(this.method, this.gateway.replace('https', 'http').replace(this.secureHostName, this.hostName), true);
			xmlhttp.setRequestHeader('Content-Type', this.getContentType());
			if(MJA) xmlhttp.setRequestHeader('User-Agent', 'J. River Internet Reader/2.0 (compatible; Windows-Media-Player/10)');
			xmlhttp.send(this.getPostData());
		} catch(e) {
			if(lc.errorHandler) eval(lc.errorHandler+'(lc.args);');
			else alert('-- Ajax Debugger --\nFatal Error: XMLHTTP couldn\'t open connection.');
			this.ajaxClient.connecting = false;
		}
	}
};
AsyncRequest.prototype.getXmlHttpRequest = function() {
	if(this.xmlhttp == null) {
		if(window.ActiveXObject) {
			var prefixes = ['MSXML2', 'Microsoft', 'MSXML', 'MSXML3'];
			for(var i=0; i<prefixes.length; i++) {
				try {
					return new ActiveXObject(prefixes[i]+'.XmlHttp');
				} catch(e) { };
			}
			throw new Error('-- Ajax Debugger --\nCould not find an installed XML parser.');
		} else if(window.XMLHttpRequest) {
			return new XMLHttpRequest();
		} else {
			return  null;
		}
	}
	return this.xmlhttp;
};
AsyncRequest.prototype.getPostData     = function() { return null; };
AsyncRequest.prototype.getContentType  = function() { return 'application/x-www-form-urlencoded'; };
AsyncRequest.prototype.responseHandler = function() { };

Ajax = new AjaxClient('Ajax');

