
function getXml(sXML)
	{
		try
			{
				var X=new ActiveXObject("Microsoft.XMLDOM");
				X.resolveExternals = false;
				//X.validateOnParse = true;
				X.async=false;
				if (sXML)
					X.loadXML(sXML)
			}
		catch(e)
			{
				if (top.Message)
					top.Message(e.description, null, 0x2 | 0x400, null, null, 450, 300);
				else
					alert(e.description)
			}
		finally
			{
				return X;
			}
	}

xHttp={
	max_concurrent_requests: 1,
	max_que: 20,
	is_quiet: false,
	requests:[],
	query:[],

	getRequest:	function(sSrc, sQuery)
		{
			var i=0, result;
			for(; i < xHttp.requests.length; i++)
				{
					if (xHttp.requests[i].status=='free')
						{
							result=xHttp.requests[i];
							break;
						}
				}

			if (result)
				{
					result.query=null;
					result.src=null;
					result.async=true;
					result.handler=null;
					result.timer=0;
					result.data=null;
					result.responseData=null;
					result.xObj=undefined;
					result.isXml=false;
					result.que_index=0;
					result.headers={};
				}
			else
				{
					var i=0, id=xHttp.requests.length;
					if (id > xHttp.max_que)
						return false;
					result={
						id: id,
						data: null,
						query: null,
						src: null,
						async: true,
						status: 'free',
						headers: {},
						que_index: 0,
						isXml: false,
						handler: null,
						responseData: null,
						responseStatus: null,
						timer: null,						
						xObj: null,
						execute: xHttp.execute,
						cancel: xHttp.cancel
					}
					xHttp.requests[result.id]=result;
				}
			if (result.xObj = xHttp.getXmlObject())
				{
					result.xObj.onreadystatechange=new Function('xHttp.response_handler('+result.id+');');
					result.query = sQuery ? String(sQuery) : false;
					result.src = sSrc ? String(sSrc) : false;
					return result;
				}
			return false;
		},
	
	getXmlObject : function()
		{
			try
				{
      				var oObject;
      				if (window.ActiveXObject)
	      				return ((oObject = new ActiveXObject('Msxml2.XMLHTTP')) || (oObject = new ActiveXObject('Microsoft.XMLHTTP')) || false);
	      			else
	      				 return ((oObject = new XMLHttpRequest()) || false);
      			}
      		catch(e)
      			{
      				return false;
      			}
		},

	execute: function()
		{
			try
				{
					this.status='queued';
					xHttp.query[this.que_index=xHttp.query.length]=this;
					xHttp.process();
					//xHttp.debugState();
				}
			catch(e)
				{
					if (!xHttp.is_quiet)
						{
							if (top.Message)
								top.Message(e.description, null, 0x2 | 0x400, null, null, 450, 300);
							else
								alert(e.description)
						}
					return false;
				}
			return true;
		},

	response_handler: function(id)
		{
			if (!xHttp.requests[id])
				return false;
			var o=xHttp.requests[id];
			if (o.xObj.readyState===4)
				{
					if (o.timer)
						clearTimeout(this.timer)
					o.status='free';
					if (o.isXml)
						o.responseData=o.xObj.responseXml;
					else
						o.responseData=o.xObj.responseText;
					if (o.handler && typeof(o.handler)=='function')
						{
							try
								{
									o.handler(o);
								}
							catch(e)
								{
									o.cancel();
									xHttp.process();
									if ((e.number & 0xFFFF)!=5011)
										throw(e);
								}
						}
					o.cancel();
					xHttp.process();
				}
		},
	
	process: function()
		{
			var i=0, current=0, next=null;
			for( ; i < xHttp.query.length && current < xHttp.max_concurrent_requests; i++)
				{
					switch (xHttp.query[i].status)
						{
							case 'sending':
								current++;
								break;
							case 'queued':
								if (!next)
									next=xHttp.query[i];
								
						}
				}
			if (current < xHttp.max_concurrent_requests && next && next.src)
				{
					next.xObj.open(next.query ? 'POST' : 'GET', next.src, next.async ? true : false);
					next.xObj.setRequestHeader('Content-Type', 'text/plain; charset=UTF-8');
					for(i in next.headers)
						{
							
							next.xObj.setRequestHeader(i, next.headers[i]);
						}
					next.xObj.send(next.query);
					next.status='sending';
				}
		},
	
	cancel: function()
		{
			var i;
			for(i=0; i<xHttp.query.length; i++)
				{
					if (xHttp.query[i].id===this.id)
						{
							if (this.status=='sending')
								this.xObj.abort();
							this.status='free';
							xHttp.query.splice(i, 1);
							break;
						}
				}
		},
	
	cancelAll: function()
		{
			for(i=0; i<xHttp.query.length; i++)
				{
					if (xHttp.query[i].status=='sending')
						{
							xHttp.query[i].xObj.abort();
							xHttp.query[i].status='free';
						}
				}
		},

	debugState: function()
		{
			var i=0, cond='requests:\n';
			for(; i<xHttp.requests.length; i++)
				cond+=xHttp.requests[i].id+': '+xHttp.requests[i].status+"\n";
			alert(cond);
		}
}
