function ActiveXRecentProgID(ids)
{
	if (!window.ActiveXObject)
		return null;
	var found = false;
	for (var i = 0; i < ids.length; i++)
	{
		try
		{
			var obj = new ActiveXObject(ids[i]);
			found = true;
			break;
		}
		catch (e) { }
	}
	if (!found)
		throw "Could not retreive a valid progID of Class: " + ids[ids.length - 1];
	return ids[i];
}
var XMLHTTP_PROGID = ActiveXRecentProgID(["Msxml2.XMLHTTP", "Microsoft.XMLHTTP", "Msxml2.XMLHTTP.5.0", "Msxml2.XMLHTTP.4.0", "MSXML2.XMLHTTP.3.0"]);
function CreateXmlHttp()
{
	if (window.XMLHttpRequest)
		return new XMLHttpRequest();
	else
		return new ActiveXObject(XMLHTTP_PROGID);
}
function XmlHttpRequest(url, callback, method, userData)
{
	var xmlHttp;
	var requestHeaders = new Array();
	var async = callback ? true : false;
	this.Username = null;
	this.Password = null;
	this.SetRequestHeader = function(name, value)
	{
		requestHeaders.push([name, value]);
	}
	this.Response = null;
	this.Send = function(data)
	{
		if (!method)
			method = "GET";
		xmlHttp = CreateXmlHttp();
		xmlHttp.open(method, url, async, this.Username, this.Password);
		for (var i = 0; i < requestHeaders.length; i++)
			xmlHttp.setRequestHeader(requestHeaders[i][0], requestHeaders[i][1]);
		if (_callback)
			xmlHttp.onreadystatechange = _callback;
		xmlHttp.send(data);
		if (!async)
			return _callback();
	}
	function _callback()
	{
		if (xmlHttp.readyState == 4)
		{
			var response =
			{
				status: xmlHttp.status,
				statusText: xmlHttp.statusText,
				text: xmlHttp.responseText,
				xml: xmlHttp.responseXML,
				userData: userData
			};
			if (callback)
				callback(response);
			else
				return response;
			xmlHttp = null;
		}
	}
}
function RemoteScriptingProxy(url)
{
	this.Serialize = function(obj)
	{
		var type = typeof(obj);
		if (type == "object")
			if (obj == null)
				type = "null";
			else if (obj instanceof Date)
				type = "date";
			else if (obj instanceof Array)
				type = "array";
			else
				type = obj.constructor.toString().toLowerCase();
		switch (type)
		{
			case "number":
				obj = obj.toString();
				break;
			case "string":
				break;
			case "boolean":
				obj = obj ? "1" : "0";
				break;
			case "date":
				obj = obj.getTime().toString();
				break;
			case "array":
				if (obj.length && typeof(obj[0]) == "string")
					type = "array-s";
				else
					type = "array-n";
				obj = obj.join(",");
				break;
			default:
				obj = "";
				break;
		}
		return {type: type, value: obj}
	}
	this.Call = function(callback, method, params, userData)
	{
		var values = new Array();
		var value, type;
		var types = new Array();
		if (params)
		{
			for (var param in params)
			{
				value = this.Serialize(params[param]);
				if (!value) continue;
				type = value.type;
				value = value.value;
				values.push(param + "=" + escape(value));
				types.push(type);
			}
		}
		var request = new XmlHttpRequest(url + "?method=" + method + "&types=" + types.join(","), _callback, "POST", userData);
		request.SetRequestHeader("Content-Type", "application/x-www-form-urlencoded");
		request.Send(values.join("&"));

		function _callback(response)
		{
			if (!callback)
				return;
			response.method = method;
			response.params = params;
			try
			{
				response.value = eval(response.text);
			}
			catch(e) { }
			callback(response);
		}
	}
}
