/* Main RPC function */
String.prototype.stripSlashes = function() {
	return this.replace(/\\(['"\0\/\\\\])/g,'$1');
}

function RPC(name,args) {
	function args2Array(args) {
		var ret=Array();
		for (var i=0; i<args.length; i++) ret[i]=args[i];
		return ret;
	}
	function getXMLObject () {
		if (typeof(XMLHttpRequest)!='undefined') return new XMLHttpRequest();
		var ax=['Msxml2.XMLHTTP.6.0', 'Msxml2.XMLHTTP.4.0',
			'Msxml2.XMLHTTP.3.0', 'Msxml2.XMLHTTP',
			'Microsoft.XMLHTTP'];
		for (var i=0; i<ax.length; i++)
			try { return new ActiveXObject(ax[i]); }
			catch (e) {}
		return null;
	}
	function call (fnc,callback,args) {
		var async=(typeof callback=='function');
		var xmlhttp=getXMLObject();
		if (xmlhttp==null) {
			
			if (!RPC.complainedLoudly)
				alert("Your browser does not support\n"+
					"XMLHttpRequest in any known form");
				RPC.complainedLoudly=true;
				return false;
		}
		var postdata='f='+escape(fnc)+'&args='+escape(args['to'+RPC.serverMode]());
		if (async) xmlhttp.onreadystatechange=function () {
			var x;
			if (xmlhttp.readyState==4)
				if (xmlhttp.status==200){
					/*
						Note to self: once all the generic bugs are worked out, Fix this 
						so it doesn't throw an error on empty data
					*/
					//alert(xmlhttp.responseText);
					eval('x = ('+xmlhttp.responseText.stripSlashes()+');');
					callback(x);
				}else callback({'error':[xmlhttp.status,xmlhttp.statusText],'request':postdata});
		}
		
		xmlhttp.open('POST','/inc/rpc/index.php',async);
		xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
		try { xmlhttp.setRequestHeader("Content-length",postdata.length); } catch (e) {}
		xmlhttp.setRequestHeader("Connection","close");
		xmlhttp.send(postdata);
		if (async) return true;
		else {
			var x;
			if (xmlhttp.readyState==4)
				if (xmlhttp.status==200){
					eval('x = '+xmlhttp.responseText+';');
					return x;
				}else return ({'error':[xmlhttp.status,xmlhttp.statusText],'request':postdata});
		}
	}
	if (typeof args[0]=='function') {
		args=args2Array(args);
		var callback=args.shift();
		return call(name,callback,args);
	}else return call(name,null,args2Array(args));
	
}
RPC.asyncNoCallBack = function () {}
/*
	Serialization functions for PHP-based server
	(we don't provide reverse, because the backend will return JSON objects)
*/
Object.prototype.toPHP = function () {
	var retf='O:8:"stdClass":';
	var reta=':{';
	var ct=0;
	var last;
	for (var i in this) {
		if (typeof this[i] == 'function') continue;
		reta+=i.toPHP()+this[i].toPHP();
		ct++;
	}
	return retf+ct+reta+'}';
}
String.prototype.toPHP = function () {
	function u2hp (s) {
		ret = '';
		for (i=0; i<s.length; i++) {
			charCode = s.charCodeAt(i);
			if ((charCode <= 127) && (charCode >=32))
				ret += s.charAt(i);
			else
				ret += '&#x' + charCode.toString(16).toUpperCase() + ';'; 
		}
		return ret; 
	}
	var s=this.replace(/((?:\r|\n|\r\n))/g,'\r\n');
	s=u2hp(s);
	s='s:'+(s.length)+':"'+s+'";';
	return s;
}
Boolean.prototype.toPHP = function () {
	return 'b:'+(this==true?1:0)+';';
}
Number.prototype.toPHP = function () {
	return (this==Math.floor(this)?'i':'d')+':'+this.toString()+';';
}
Date.prototype.toPHP = function () {
	return 'i:'+this.valueOf()+';';
}
Array.prototype.toPHP = function () {
	var ret='a:'+this.length+':{';
	for (var i=0; i<this.length; i++)
		ret+=i.toPHP()+this[i].toPHP();
	return ret+'}';
}
RPC.serverMode='PHP';
CSKN="/skn/aspect/";
RPC.add_to_cart = function () { return RPC('add_to_cart',arguments); }
RPC.del_from_cart = function () { return RPC('del_from_cart',arguments); }
RPC.cart_form = function () { return RPC('cart_form',arguments); }
