

	/* ----------------------------------------------------------------------------------------
	 * Copyright 2008 ADsignum
	 * Developed by Niels Fröhling
	 */

	/* ----------------------------------------------------------------------------------------- */
	var waitstate = 0;

	function clrWState() {
		waitstate = 0;
		document.body.style.cursor = 'auto';
	}

	function incWState() {
		if ((waitstate = Math.min(65535, waitstate + 1)) >  0)
			document.body.style.cursor = 'wait';
	}

	function decWState() {
		if ((waitstate = Math.max(    0, waitstate - 1)) <= 0)
			document.body.style.cursor = 'auto';
	}

	/* ----------------------------------------------------------------------------------------- */
	function constructGET(parameters) {
		var fullurl = '';
		var baseurl = '';
		var switchl = 0;

		if (parameters && (parameters.length > 0)) {
			for (var p = 0; p < parameters.length; p++) {
				/* skip values with null parameter-value */
				if (!switchl &&
					((parameters[p + 1] ==  null ) ||	// how I understand it
					 (parameters[p + 1] == 'null') ||	// how MICROSUCK understand it
					 (parameters[p + 1] == ''    ))) {	// how MOZILLA understand it
					p++; continue; }

				/* switch start/continue */
				if (!switchl)
					if (fullurl == '')
						fullurl += '?';
					else
						fullurl += '&';
				else
					fullurl += '=';

				/* append parameter */
				fullurl += parameters[p];
				/* switch &= */
				switchl ^= 1;
			}
		}

		return encodeURI(fullurl);
	}

	function constructPOST(parameters) {
		var fullurl = '';

		if (parameters) {
			for (var p in parameters) {
				if (typeof parameters[p] == 'function')
					continue;

				if (fullurl != '')
					fullurl += '&';

				/* append parameter */
				fullurl += p + '=' + parameters[p];
			}
		}

		return encodeURI(fullurl);
	}

	/* -----------------------------------------------------------------------------------------
	 * the base object
	 *
	 *  num		-	position in array
	 *  request	-	the allocated request
	 *	func	-	a possible hook
	 *	data	-	data for the hook
	 */
	function aioObject(request, func, data, num) {
		this.num     = num;

		this.request = request;

		this.func    = func;
		this.data    = data;
	}

	var aion/*; if (!aios) aion */ = 0;
	var aios/*; if (!aios) aois */ = new Array();

	/* ----------------------------------------------------------------------------------------- */
	function getAsyncIOPrefix() {
		if (getAsyncIOPrefix.prefix != null)
			return getAsyncIOPrefix.prefix;

		var prefixes = ['MSXML3', 'MSXML2', 'MSXML', 'Microsoft'];
		var versions = ['.5.0', '.4.0', '.3.0', ''];
		for (var i = 0; i < prefixes.length; i++)
		for (var j = 0; j < versions.length; j++) {
			try {
				// try to create the objects
				var o = new ActiveXObject(prefixes[i] + '.XmlHttp' + versions[j]);
				return (getAsyncIOPrefix.prefix = prefixes[i]);
			}
			catch (ex) {};
		}

		throw new Error('Could not find an installed XML parser');
	}

	function getAsyncIORequest() {
		var aio;
		var aioc;

		/* get MS-Request */
		try {
			aio = new ActiveXObject(getAsyncIOPrefix() + '.XmlHttp');
		} catch (e) {
			aio = null;
			if (MSIE)
				alert('You have deactivated the execution of ActiveX-Controls!' + "\n" +
					  'Please include this site into your list of trustfull sites, and activate ActiveX-Controls for them.');
		}

		// for mozilla and firefox
		try {
			netscape.security.PrivilegeManager.enablePrivilege('UniversalBrowserRead');
			netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
		} catch (e) {
		//	alert('Permission UniversalBrowserRead denied.');
		}

		if (!aio && typeof XMLHttpRequest != "undefined")
			aio = new XMLHttpRequest();

		if (aio != null) {
			aioc = new aioObject(aio, null, null, aion);
			aios[aion++] = aioc;
		}
		else
			aioc = null;

		return aioc;
	}

	/* -----------------------------------------------------------------------------------------
	 */
	function getXMLDOMPrefix() {
		if (getXMLDOMPrefix.prefix != null)
			return getXMLDOMPrefix.prefix;

		var prefixes = ['MSXML3', 'MSXML2', 'MSXML', 'Microsoft'];
		var versions = ['.5.0', '.4.0', '.3.0', ''];
		for (var i = 0; i < prefixes.length; i++)
		for (var j = 0; j < versions.length; j++) {
			try {
				// try to create the objects
				var o = new ActiveXObject(prefixes[i] + '.DomDocument' + versions[j]);
				return (getXMLDOMPrefix.prefix = prefixes[i]);
			}
			catch (ex) {};
		}

		throw new Error('Could not find an installed XML Document');
	}

	function getXMLDOM(xml) {
		var xdm;

		/* get MS-Request */
		try {
			xdm = new ActiveXObject(getXMLDOMPrefix() + '.DomDocument');
		} catch (e) {
			xdm = null;
		}

		if (!xdm && document.implementation && document.implementation.createDocument)
			xdm = document.implementation.createDocument("", "", null);

		if (xdm != null)
			xdm.loadXML(xml.xml == null ? xml : xml.xml);

		return xdm;
	}

	/* -----------------------------------------------------------------------------------------
	 * baseurl	-	base uri to be called
	 * parameters	-	an array of parameters to transmit
	 * datas	-	special datas to transmit (DOM-data!)
	 * triggerfunc	-	the function to be called, after completing request
	 * triggerdata	-	the data to pass to the triggerfunc
	 */
	function doAsyncHEADRequest(baseurl, parameters, datas, triggerfunc, triggerdata) {
		var aioc;

		/* got one */
		if ((aioc = getAsyncIORequest()) != null) {
			var aio = aioc.request;

			/* save additional infos */
			aioc.func = triggerfunc;
			aioc.data = triggerdata;

			try {
				/* construct url */
				var fullurl = baseurl + constructGET(parameters);

				incWState();

				/* prepare parameters */
				aio.open("HEAD", fullurl, true);
				aio.onreadystatechange = function() {
					var aioo = aios[aioc.num];
					var aiol = aioo.request;

					if (aiol.readyState == 4) {
						decWState();

						/* if the server doesn't exists, status/statusText throw exceptions */
//						if (aiol.status != 200)
//							alert(aiol.statusText);

//						alert(aiol.responseStream);
//						alert(aiol.responseBody);
//						alert(aiol.responseText);
//						alert(aiol.responseXML);
//						alert(aiol.status);
//						alert(aiol.statusText);

						aioo.func(aioo.data, aiol);
					}
				};

				/* throw it out */
				aio.send(datas);
			}
			catch(e) {
				var aioo = aios[aioc.num];
				var aiol = aioo.request;

				decWState();

				aioo.func(aioo.data, aiol);
			}
		}

		return aioc;
	}

	/* -----------------------------------------------------------------------------------------
	 * baseurl	-	base uri to be called
	 * parameters	-	an array of parameters to transmit
	 * datas	-	special datas to transmit (DOM-data!)
	 * triggerfunc	-	the function to be called, after completing request
	 * triggerdata	-	the data to pass to the triggerfunc
	 */
	function doAsyncGETRequest(baseurl, parameters, datas, triggerfunc, triggerdata) {
		var aioc;

		/* got one */
		if ((aioc = getAsyncIORequest()) != null) {
			var aio = aioc.request;

			/* save additional infos */
			aioc.func = triggerfunc;
			aioc.data = triggerdata;

			try {
				/* construct url */
				var fullurl = baseurl + constructGET(parameters);

				incWState();

				/* prepare parameters */
				aio.open("GET", fullurl, true);
				aio.onreadystatechange = function() {
					var aioo = aios[aioc.num];
					var aiol = aioo.request;

					if (aiol.readyState == 4) {
						decWState();

						/* if the server doesn't exists, status/statusText throw exceptions */
//						if (aiol.status != 200)
//							alert(aiol.statusText);

//						alert(aiol.responseStream);
//						alert(aiol.responseBody);
//						alert(aiol.responseText);
//						alert(aiol.responseXML);
//						alert(aiol.status);
//						alert(aiol.statusText);

						aioo.func(aioo.data, aiol);
					}
				};

				/* throw it out */
				aio.send(datas);
			}
			catch(e) {
				var aioo = aios[aioc.num];
				var aiol = aioo.request;

				decWState();

				aioo.func(aioo.data, aiol);
			}
		}

		return aioc;
	}

	/* -----------------------------------------------------------------------------------------
	 * baseurl	-	base uri to be called
	 * parameters	-	an array of parameters to transmit
	 * datas	-	special datas to transmit (DOM-data!)
	 * triggerfunc	-	the function to be called, after completing request
	 * triggerdata	-	the data to pass to the triggerfunc
	 */
	function doAsyncPOSTRequest(baseurl, parameters, datas, triggerfunc, triggerdata) {
		var aioc;

		/* got one */
		if ((aioc = getAsyncIORequest()) != null) {
			var aio = aioc.request;

			/* save additional infos */
			aioc.func = triggerfunc;
			aioc.data = triggerdata;

			try {
				/* construct url */
				var fullurl = baseurl; datas = constructPOST(parameters)/*.split('?')[1]*/;

				incWState();

				/* prepare parameters */
				aio.open("POST", fullurl, true);
				aio.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
				aio.onreadystatechange = function() {
					var aioo = aios[aioc.num];
					var aiol = aioo.request;

					if (aiol.readyState == 4) {
						decWState();

						/* if the server doesn't exists, status/statusText throw exceptions */
//						if (aiol.status != 200)
//							alert(aiol.statusText);

//						alert(aiol.responseStream);
//						alert(aiol.responseBody);
//						alert(aiol.responseText);
//						alert(aiol.responseXML);
//						alert(aiol.status);
//						alert(aiol.statusText);

						aioo.func(aioo.data, aiol);
					}
				};

				/* throw it out */
				aio.send(datas);
			}
			catch(e) {
				var aioo = aios[aioc.num];
				var aiol = aioo.request;

				decWState();

				aioo.func(aioo.data, aiol);
			}
		}

		return aioc;
	}

	/* -----------------------------------------------------------------------------------------
	 */
	function doAsyncAbortRequest(aioc) {
		if ((     aioc      != null) &&
		    (aios[aioc.num] != null)) {
			var aioo = aios[aioc.num];
			var aiol = aioo.request;

			aios[aioc.num] = null;

/*			aiol.statusText = 'abort';
			aiol.status     = 300;
			aiol.readyState = 4;*/
			aiol.abort();

			decWState();
		}
	}

	/* -----------------------------------------------------------------------------------------
	 * standard trigger functions:
	 *  triggerDebug		-	for getting debug-infos only
	 *  copyContentToID		-	associates requested content with an id
	 */
	function triggerDebug(data, plain, xml) {
		alert(data + '/' + plain + '/' + xml);
	}

	/* -----------------------------------------------------------------------------------------
	 * Create the loadXML method and xml getter for Mozilla
	 */
	if (window.DOMParser) {
		/* XMLDocument did not extend the Document interface in some versions
		 * of Mozilla. Extend both!
		 */
	//	XMLDocument.prototype.loadXML =
		Document.prototype.loadXML = function (s) {

			// parse the string to a new doc
			var doc2 = (new DOMParser()).parseFromString(s, "text/xml");

			// remove all initial children
			while (this.hasChildNodes())
				this.removeChild(this.lastChild);

			// insert and import nodes
			for (var i = 0; i < doc2.childNodes.length; i++)
				this.appendChild(this.importNode(doc2.childNodes[i], true));
		};
	}

	function getTextVersion(XMLnode) {
		var text;

		try {
			//serialization to string DOM Browser
			var serializer = new XMLSerializer();
			text = serializer.serializeToString(XMLnode);
		}
		catch (e) {
			// serialization of an XML to String (IE only)
			text = XMLnode.xml;
		}

		return text;
	}

	function getElementByIdLocal(fragment, tag, id) {
		var elm = null;

		if ((fragment.tagName && fragment.id) &&
		    (fragment.tagName.toUpperCase() == tag.toUpperCase()) &&
		    (fragment.id == id))
			return fragment;

		if (fragment.childNodes && fragment.childNodes.length)
			for (var c = 0; c < fragment.childNodes.length; c++)
				if ((elm = getElementByIdLocal(fragment.childNodes[c], tag, id)))
					break;

		return elm;
	}

	function getElementByIdXML(XMLdoc, tag, id) {
		var elm = '';
	//	var doc = getXMLDOM(XMLdoc);

		if ((XMLdoc.readyState == 4) && (XMLdoc.status == 200) && XMLdoc.responseText) {
			var srch = null;
			var mtch = null;

			switch (tag) {
				case 'lang':
					/* with 'g', we want to find all matches, even across newlines */
					srch = new RegExp('<' + 'html' + '.*?lang="([\\s\\S]*?)".*?>', 'ig');
					/* no 'g', we want to exclude the tag-definition */
					mtch = new RegExp('lang="([\\s\\S]*?)"', 'i');
					break;
				case 'link':
				case 'meta':
					/* with 'g', we want to find all matches, even across newlines */
					srch = new RegExp('<' + tag + '.*?\/>', 'ig');
					/* no 'g', we want to exclude the tag-definition */
					mtch = new RegExp('<' + tag + '.*?\/>', 'i');
					break;
				case 'head':
				case 'title':
				case 'script':
					/* with 'g', we want to find all matches, even across newlines */
					srch = new RegExp('<' + tag + '.*?>([\\s\\S]*?)<\/' + tag + '>', 'ig');
					/* no 'g', we want to exclude the tag-definition */
					mtch = new RegExp('<' + tag + '.*?>([\\s\\S]*?)<\/' + tag + '>', 'i');
					break;
				default:
					srch = new RegExp('<' + 'body' + '.*?>([\\s\\S]*?)<\/' + 'body' + '>', 'i');
					break;
			}

			/* we search first for the content */
			var elms = XMLdoc.responseText.match(srch);
		//	for (var e = 0; e < elms.length; e++)
		//		elms[e] = elms[e];

			/* none found */
			if (!elms || !elms.length)
				return '';

			/* we match rather than search */
			if (mtch) {
				/* give me a specific one */
				if (id >= 0)
					return elms[0] ? elms[0].match(mtch)[id] : '';

				/* give me all */
				return elms;
			}

			/* don't make all the serializer-stuff */
			var tmp = document.createElement('div');
			tmp.innerHTML = elms[1];
			elm = getElementByIdLocal(tmp, tag, id);
		}

		return elm;
	}
