function Cads() {	
	//this.xhrObjects = new Array();
	this.options = new Object();
	this.options.adZones = new Array();
	
	this.handleException = function(e) {
		alert(e);	
	}
	
	this.init = function () {
		for(var zIndex = 0; zIndex < this.options.adZones.length; zIndex++)
		{
			try {
				this.getAdverts(this.options.adZones[zIndex]);	
			}
			catch(e) {
				this.handleException(e);	
			}
		}
	}
	
	this.newXhr = function() {
		var xhr;
		
		if(typeof ActiveXObject != "undefined") {
			xhr = new ActiveXObject("MSXML2.XMLHTTP");
			//alert(xhr);
		} else {
			xhr = new XMLHttpRequest();
		}
			
		return xhr;
	}
	
	this.getAdverts = function(zone) {
		//this.xhrObjects.push(this.newXhr());
		//var xhrIndex = this.xhrObjects.length -1;		
		var xhr = this.newXhr();//= this.xhrObjects[xhrIndex];
		var supor = this;
		xhr.onreadystatechange = function() {
			supor.requestStateChanged(xhr);
		};
		xhr.open("get", (typeof(this.options.xhrProxyAddress) == 'undefined' ? 'http://ads.cybacat.com/get/xml/' : this.options.xhrProxyAddress)+zone.zoneID, true);
		xhr.send("");
	}

	this.requestStateChanged = function(xhr) {
		//alert("cads__requestStateChanged("+xhrIndex+")");
		
		if(xhr.readyState == 4) {
			if(xhr.status==200) {
				this.processAdverts(xhr);
			}
			else {
				//Something's  gone wrong!
				alert(xhr.responseText);
			}
		}
	}
	
	this.processAdverts = function(transport) {
		//try {
			var xml = transport.responseXML;
			var advertsTag = xml.getElementsByTagName("adverts")[0];
			var zoneId = xml.getElementsByTagName("zone_id")[0].firstChild.data;
			var zoneElement = document.getElementById("adzone_"+zoneId);
			if(zoneElement == null) {
				//alert('Couldn\'t find '+"adzone_"+zoneId);
				return;
			}
			
			//need to find the local object for this zone.
			var zoneObj = null;
			var z = 0;
			do {
				if(this.options.adZones[z].zoneID ==  zoneId) zoneObj = this.options.adZones[z];
				z++;
			} while(zoneObj == null && z < this.options.adZones.length)
			
			var adClass = (zoneObj == null || (typeof zoneObj.className == 'undefined')) ? '' : zoneObj.className;
			
			for(var i = 0; i < advertsTag.childNodes.length; i++)
			{
				if(advertsTag.childNodes[i].tagName != "advert") continue;
				
				this.processAdvert(advertsTag.childNodes[i], zoneElement, adClass);
			}
		//}
		//catch(e) {
		//	this.handleException(e);	
		//}
	}
	
	this.processAdvert = function(advertTag, zoneElement, adClass) {
		//try {
				
			var contDiv = document.createElement("div");
			contDiv.className = adClass;
			zoneElement.appendChild(contDiv);
			
			switch(advertTag.getAttribute("type")) {
				case "image/gif":
				case "image/jpeg":
				case "image/png":
					var aTag = document.createElement("a");
					aTag.href = advertTag.getAttribute("href");
					aTag.target = "_blank";
					//aTag.style.position = "relative";
					contDiv.appendChild(aTag);
					this.processImageAdvert(advertTag, aTag);
				break;
				
				case "application/x-shockwave-flash":
					if(advertTag.getAttribute("href") != null && advertTag.getAttribute("href").length > 0) {
						var aTag = document.createElement("a");
						aTag.href = advertTag.getAttribute("href");
						aTag.target = "_blank";
						aTag.style.position = "relative";
						contDiv.appendChild(aTag);
						this.processFlashAdvert(advertTag, aTag);
					}
					else this.processFlashAdvert(advertTag, contDiv);
				break;
				
				case "application/google-adsense":
					this.processAdsenseAdvert(advertTag, contDiv);
				break;	
			}
		//}
		//catch(e) {
		//	alert(zoneElement);
		//	this.handleException(e);	
		//}
	}
	
	this.processImageAdvert = function (advertTag, element) {
		var imgTag = document.createElement("img");
		imgTag.src = advertTag.getAttribute("src");
		imgTag.width = advertTag.getAttribute("width");
		imgTag.height = advertTag.getAttribute("height");
		imgTag.alt = (advertTag.getAttribute("alt") != null) ? advertTag.getAttribute("alt") : "";
		imgTag.border = "0";
	
		element.appendChild(imgTag);
	}
	
	this.processFlashAdvert = function (advertTag, element) {
		/**
		* This was all hacked about from using DOM to
		* the dreaded innerHTML in several attempts to
		* solve issues with buggy flash elements not
		* propagating onclick events to the browser.
		*/		
		var html = "";
		if(element.tagName.toLowerCase() == "a") html +=
		"<img src=\"http://ads.cybacat.com/images/transparent.gif\" \
			width=\""+advertTag.getAttribute("width")+"\" height=\""+advertTag.getAttribute("height")+"\" \
			border=\"0\" style=\"z-index:100; position:absolute;\" />";
		html += 
		"<object width=\""+advertTag.getAttribute("width")+"\" height=\""+advertTag.getAttribute("height")+"\" \
			codebase=\"http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0\" \
			classid=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\" > \
			<param name=\"src\" value=\""+advertTag.getAttribute("src")+"\" /> \
			<param name=\"wmode\" value=\"opaque\" /> \
			\
			<embed src=\""+advertTag.getAttribute("src")+"\" width=\""+advertTag.getAttribute("width")+"\" height=\""+advertTag.getAttribute("height")+"\" \
				wmode=\"opaque\" type=\"application/x-shockwave-flash\" pluginspage=\"application/x-shockwave-flash\" /> \
		</object>";
		element.innerHTML += html;
		
		//we need the <embed> or <object> element for the following
		//fallback code to work correctly.
		var fallbackParentTag = null;
		var eTags = element.getElementsByTagName("embed");
		var oTags = element.getElementsByTagName("object");
		if(eTags.length > 0) fallbackParentTag = eTags[0];
		else if(oTags.length > 0) fallbackParentTag = oTags[0];
		
		var fallbacks = advertTag.getElementsByTagName("advert");
		for(var fI = 0; fallbackParentTag != null && fI < fallbacks.length; fI++)
		{
			try {
				this.processAdvert(fallbacks[fI], fallbackParentTag);
			}
			catch(e) {
				this.handleException(e);	
			}
		}
	}
	
	this.processAdsenseAdvert = function(advertTag, element) {
		if(document.referrer != "http://www.teachingtimes.com/adtest.htm") return;
			
		var code = advertTag.getAttribute("code");
		code = code.replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&quot;/g, '"');
		//alert(code);
		/**
		* Code can contain several <script> elements,
		* of the form :
		* <script type="x">
		* some js;
		* more js;
		* </script>
		* or
		* <script type="x" src="url">/\w/</script>
		*/
		//<script\s*(type="[a-z_/]+"\s*|src="([a-z0-9_:/?$.-]+)"\s*){1,2}>\s*</script\s*>
		var linkMatcher = new RegExp(/<script\s*(?:type="[a-z_\/]+"\s*|src="([a-z0-9_:\/?$.-]+)"\s*){1,2}>\s*<\/script\s*>/g);
		var linkScripts = linkMatcher.exec(code);
			
		//<script\s*(?:type="[a-z_/]+")?\s*>((?:[a-z0-9_/\\%^&$£)(><}{[\]!=*,;:"'-]|\s)+)</script\s*>
		var inlineMatcher = new RegExp(/<script\s*(?:type="[a-z_\/]+")?\s*>((?:[a-z0-9_\/\\%^&$£)(><}{[\]!=*,;:"'-]|\s)+)<\/script\s*>/g);
		var inlineScripts = inlineMatcher.exec(code);
		
		for(var i = 1; i < inlineScripts.length; i++) {
			inlineScripts[i] = inlineScripts[i].replace(/^<!--.*$/igm, "");
			alert("Inline script:\n"+inlineScripts[i]);
			var scriptElem = document.createElement("script");
			scriptElem.type = "text/javascript";
			scriptElem.innerHTML = inlineScripts[i];		
			element.appendChild(scriptElem);
		}
		
		for(var i = 1; i < linkScripts.length; i++) {
			alert("Linked script: '"+linkScripts[i]+"'");
			var linkElem = document.createElement("script");
			linkElem.type = "text/javascript";				
			linkElem.src = linkScripts[i];			
			element.appendChild(linkElem);	
		}
	}

}