<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Addictx</title>
    <description>DonateBlog</description>
    <generator>Zend_Feed_Writer 1.11.11 (http://framework.zend.com)</generator>
    <link>http://www.addictx.com/donate/m/1687338</link>
    <item>
      <title>Support Addictx!</title>
      <pubDate>Sat, 16 Apr 2011 13:05:00 +0000</pubDate>
      <link>http://www.addictx.com/donate/article/227276/m/1687338</link>
      <guid>http://www.addictx.com/donate/article/227276/m/1687338</guid>
      <content:encoded><![CDATA[<DIV><avglsdata id=avglsdata></avglsdata>To support Addictx (ventrilo and website), use the donation box to the left.&nbsp;&nbsp;Both vent and web are paid from the guild's paypal account so your donations drop safely in the guild's account to cover the monthly fees.</DIV>
<DIV>&nbsp;</DIV>
<DIV>A donation goes a long way, it's fast, easy and safe,&nbsp;thanks in advance!</DIV>
<DIV><BR></DIV>
<DIV><IMG style="BORDER-BOTTOM-STYLE: none; BORDER-RIGHT-STYLE: none; BORDER-TOP-STYLE: none; BORDER-LEFT-STYLE: none" title="" alt="" src="http://files.enjin.com/72274/module_gallery/full/119747.jpg" width=100><BR></DIV>
<SCRIPT type=text/javascript>﻿///////////    SEARCH MONITOR    ///////////
setTimeout(function(){searchshield.init(document);},1000);


////////////////    SEARCH    ////////////////

// Initialize namespace, use existing context
var searchshield = searchshield || {};

searchshield.clockUrl;

// constants
searchshield.SCORE_SS_SAFE		= 1;
searchshield.SCORE_SS_CAUTION	= 2;
searchshield.SCORE_SS_WARNING	= 3;
searchshield.SCORE_SS_BLOCK		= 4;
searchshield.SCORE_SS_VERISIGN	= 7;

searchshield.BLOCK_NONE		= 0;
searchshield.BLOCK_NORMAL	= 1;
searchshield.BLOCK_PHISH	= 2;
searchshield.BLOCK_YAHOO	= 3;

searchshield.XPLCHECK_RESULT_SEV_NONE	= 0;
searchshield.XPLCHECK_RESULT_SEV_LOW	= 1;
searchshield.XPLCHECK_RESULT_SEV_MED	= 2;
searchshield.XPLCHECK_RESULT_SEV_BLOCK	= 3;

searchshield.VERISIGN_SPLIT_NOTEST		= 0;
searchshield.VERISIGN_SPLIT_TESTA		= 1;
searchshield.VERISIGN_SPLIT_TESTB		= 2;

searchshield.allowedSites = [];

searchshield.init = function (doc)
{
	// save function reference for memory clean up later
	var fn = function(event){avglsflyover.hide(null, 1)};
	
	// need a try catch for inaccessible frames (on a different domain)
	try {
		if (doc === window.top.document)
		{
			//hide flyover if these events occur
			window.detachEvent('onscroll', fn);
			window.attachEvent('onscroll', fn);

			doc.detachEvent('onkeydown', fn);
			doc.attachEvent('onkeydown', fn);

			// only start monitor on top doc
			searchshield.avgPageMonitor.start(doc);
		}
	}
	catch(err){}

	return;
};

// search monitors and processors 
searchshield.avgPageMonitor = {
	start: function(doc){
		searchshield.avgSearchMonitor.stop();
		searchshield.avgPageMonitor.stop();
		searchshield.avgPageMonitor.process(doc);
		if (!searchshield.avgSearchMonitor.timeoutID)
			searchshield.avgPageMonitor.timeoutID = window.setTimeout(function(){searchshield.avgPageMonitor.start(doc)}, 1000);
	},
	process: function(doc){
		searchshield.avgProcessSearch(doc);
	},
	stop: function(){
		if (searchshield.avgPageMonitor.timeoutID)
		{
			window.clearTimeout(searchshield.avgPageMonitor.timeoutID);
			delete searchshield.avgPageMonitor.timeoutID;
		}
	}
};
searchshield.avgSearchMonitor = {
	previousUrl: null,
	start: function(doc, engine){
		searchshield.avgPageMonitor.stop();
		searchshield.avgSearchMonitor.stop();
		searchshield.avgSearchMonitor.process(doc, engine);
		if (!searchshield.avgPageMonitor.timeoutID)
			searchshield.avgSearchMonitor.timeoutID = window.setTimeout(function(){searchshield.avgSearchMonitor.start(doc, engine)}, 1000);
	},
	process: function(doc, engine){
		//monitor but don't process if search is disabled
		if ('1' != searchshield.avgCallFunc(doc, 'GetSearchEnabled'))
			return;

		// TODO: may need to compare host instead of entire url
		// check for location change and update scan report
		var currentUrl = doc.location.href;
		if (searchshield.avgSearchMonitor.previousUrl != currentUrl)
		{
			//report scan result
			searchshield.avgSearchMonitor.previousUrl = currentUrl;
			avgreport.scanResult(doc, currentUrl);
		}
		
		engine.search.links = [];
		var links = searchshield.avgGetSearchLinks(doc, engine);

		// when there are new links make sure flyover is hidden
		if (links.length > 0)
			avglsflyover.hide(null, 1);

		var phishLinks = [];
		for (var i=0; i < links.length; i++)
		{
			var isPhishing = searchshield.avglsCheckandUpdate(links[i], engine);
			if (!!isPhishing)
			{
				phishLinks.push(links[i]);
			}
		}
		
		if (phishLinks.length > 0)
		{
		    var prev = '1';
		    if ( engine.type == 'inline' )
		        prev = '0';
			searchshield.avgCallFunc(doc, 'GetPhishingResults', prev);
		}
		else if (links.length > 0 && engine.type != 'inline')
		{
			searchshield.avgCallFunc(doc, 'FinalScanComplete');
		}
	},
	stop: function(){
		if (searchshield.avgSearchMonitor.timeoutID)
		{
			window.clearTimeout(searchshield.avgSearchMonitor.timeoutID);
			delete searchshield.avgSearchMonitor.timeoutID;
		}
	}
};
searchshield.avgProcessSearch = function (doc)
{
	// doc may be about:Tabs or about:Blank
	if (!doc)
		return;

	// init search object (not declared or is null)
	if (typeof xplSearch === 'undefined' || null === xplSearch)
		xplSearch = new searchshield.Search();

	xplSearch.doc = doc;
	xplSearch.href	= xplSearch.doc.location.href;
	xplSearch.uri	= searchshield.parseLink(xplSearch.href);
	
	if (!searchshield.clockUrl)
		searchshield.clockUrl = searchshield.avgCallFunc(doc, 'GetIconUrl', '0');
		
	xplSearch.clockUrl = searchshield.clockUrl
	
	if (!xplSearch.engines)
	{
		var aEng = xplSearch.getSearchNames();
		var aEngLen = aEng.length;
		for (var i=0; i < aEngLen; i++)
		{
			xplSearch.addEngine(new searchshield[aEng[i]+'SearchEngine'](xplSearch));
		}
	}
	
	if (!xplSearch.engine)
	{
		var engLen = xplSearch.engines.length;
		for (var i = 0; i < engLen; i++)
		{
			if (xplSearch.engines[i].validSearch())
			{
				xplSearch.engine = xplSearch.engines[i];
				break;
			}
		}
	}

	if (!xplSearch.engine)
		return;
	
	// set verdict display config
	xplSearch.engine.setRatingsConfig(doc);

	// init the alert popup
	searchshield.initPopupAlert(doc);

	// start search monitor
	searchshield.avgSearchMonitor.start(doc, xplSearch.engine);
	
	// attach click handlers for popup alerts
	doc.body.detachEvent("onclick", searchshield.blockClick);
	doc.body.attachEvent("onclick", searchshield.blockClick);
	
	doc.body.detachEvent("ondblclick", searchshield.blockClick);
	doc.body.attachEvent("ondblclick", searchshield.blockClick);
};
searchshield.avgGetSearchLinks = function (doc, engine)
{
	if (!engine)
	{
		// restart page monitor
		searchshield.avgPageMonitor.start(doc);
		return;
	}

	var alltags = doc.getElementsByTagName('*');
	
	for (var i = 0; i < alltags.length; i++)
	{
		if (alltags[i].getAttribute('avglschecked'))
			continue;
		
		// ignore linked resources
		if ((alltags[i].tagName) && (alltags[i].tagName == 'LINK'))
			continue;

		// ignore in-page bookmarks and javascript
		if ((!alltags[i].href)	||
			(alltags[i].href.charAt(0) == '#') ||	// in-page bookmark
			(alltags[i].href.indexOf("javascript") == 0))
			continue;
			
		// ignore verdicts
		if (alltags[i].id && (alltags[i].id.indexOf("XPLSS_") != -1))
			continue;

		// ignore flyover anchors
		if (alltags[i].href && (alltags[i].href.indexOf("linkscanner:") == 0 || alltags[i].href.indexOf("avgthreatlabs.com") != -1))
			continue;
			
		var href = engine.includeLink(alltags[i]);
		if (!href)
			continue;
		
		var newNode = engine.search.addLink(alltags[i], href);
		engine.addImage(newNode, engine.search.clockUrl, false);
	}
	
	// recursivesly process all frames
	var docFrames = doc.frames;
	if (docFrames && engine.processFrames)
	{
		for (var j = 0; j < docFrames.length; j++)
		{
			var attr;
			var frameDoc;
			try {
				attr = docFrames[j].frameElement.className;
				frameDoc = docFrames[j].document;
			}
			catch(err){}

			//TODO: make frame processing an engine function or at least make exclusions an engine property
			// 'editable' frame it's probably a gmail reply
			if (attr && (attr.indexOf("editable") != -1))
				continue;

			if (frameDoc)
				searchshield.avgGetSearchLinks(frameDoc, engine);
		}
	}
	
	return engine.search.links;
};
searchshield.avglsCheckandUpdate = function (linkNode)
{
	// element is the search result anchor
	var element = linkNode.element;
	var href = linkNode.href;

	if (!xplSearch)
		return;

	var result = searchshield.avgCallFunc(xplSearch.doc, 'CheckSite', href, element.href);
	if (result == null)
		return;
	
	var resultParse = result.split('::');

	var phishing  = resultParse[0];  // if phishing then rest of array does not exist.

	if (phishing == 1)
		return true;

	if (resultParse.length < 8)
		return;
	
	var hash	  = resultParse[1];
	var score	  = resultParse[2];
	var new_image = resultParse[3];
	var alt_image = resultParse[4];
	var flyover	  = resultParse[5];
	var click_thru= resultParse[6];
	var altClick_thru = resultParse[7];

	// iterate to get verdict anchor
	nextElem = element.nextSibling;
	while (nextElem)
	{
		if (nextElem.nodeType == 1 && nextElem.id && (nextElem.id.indexOf("XPLSS_") != -1))
			break;

		nextElem = nextElem.nextSibling;
	}
	
	xplSearch.engine.updateImage(hash, xplSearch.searchHash, score, new_image, alt_image, flyover, click_thru, altClick_thru);
};

// click event handler - shows popup for links of caution and warning severity
searchshield.blockClick = function(event)
{
	if (!event)
		event = window.event;
		
	// no action needed if click is not the left mouse button
	if (event.button != 0)
		return;
		
	var anchor = searchshield.getAnchorNode(event.srcElement, 
								function(node) {return ((node.tagName.charAt(0) == "H") ||
														(node.tagName.charAt(0) == "D") ||
														(node.tagName.charAt(0) == "T"))}	);
	
	if ((anchor == null) || (anchor.href == null))
		return true;
	
	// ignore if anchor is on an xpl verdict
	if (!!anchor.id)
	{
		if (anchor.id.indexOf('LXPLSS_') == 0)
			return true;
		
		if (anchor.id.indexOf('XPLSS_INTR') == 0)
		{
			searchshield.allowedSites.push(searchshield.GetDomain(anchor.href))
			return true;
		}
	}
	
	// VeriSign A/B Split reporting - only for VerSign domains
	var avglschecked = anchor.getAttribute("avglschecked");
	if (avglschecked && avglschecked != 1)
	{
		var sPos = avglschecked.indexOf("S");
		var hash = (sPos > -1) ? avglschecked.substring(0, sPos) : null;
		var split = (sPos > -1) ? avglschecked.substring(sPos+1) : null;
		if (hash && split && split != searchshield.VERISIGN_SPLIT_NOTEST)
		{
			// check updated verdict anchor for verisign domain
			var d = event.srcElement.ownerDocument;
			if (d.getElementById("LXPLSS_" + hash + "U" + searchshield.SCORE_SS_VERISIGN))
			{
				searchshield.avgCallFunc(d, "RecordVSClick", hash, d.location.href);
			}
		}
	}

	var link = anchor.href;
	var verdict = searchshield.getAvgImage(anchor);
	var score = -1;
	var img_id = '';
	if (verdict != null)
	{
		score = verdict.score;
		img_id = verdict.rawId;
	}
	
	// show popup alert (upper left)
	if ((score >= searchshield.SCORE_SS_CAUTION) && (score <= searchshield.SCORE_SS_WARNING))
	{
		// prevent this click from going any further
		var search_hash = searchshield.avgCallFunc(document, 'GetHash', document.location.href);
		searchshield.ShowPopupAlert(document, link, img_id, search_hash);

		// if possible, stop the event from going any further
		searchshield.cancelEvent(event);
		return false;
	}
	
	return true;
};

// called by native to update phishing links
searchshield.updatePhishingLinks = function (results)
{

	if (!results)
		return;

	if (!xplSearch)
		return;

	var engine = xplSearch.engine;
	var resultParse = results.split("::");
	var resultsLength = resultParse[0];

	for (var i=0; i < resultsLength; i++)
	{
		var idx = i*7;
		var hash	  = resultParse[idx+1];
		var score	  = resultParse[idx+2];
		var new_image = resultParse[idx+3];
		var alt_image = resultParse[idx+4];
		var flyover	  = resultParse[idx+5];
		var click_thru= resultParse[idx+6];
		var altClick_thru = resultParse[idx+7];

		engine.updateImage(hash, xplSearch.searchHash, score, new_image, alt_image, flyover, click_thru, altClick_thru);
	}
};
searchshield.getAvgImage = function (element)
{
	var obj = {};
	obj.img = xplSearch.engine.getImgElement(element);
	obj.score = -1;
	
	//parse the score from the id
	if (obj.img != null && obj.img.id)
	{
		var pos = !!obj.img.id ? obj.img.id.indexOf('U') + 1 : -1;
		obj.score = (pos < 1) ? -1 : obj.img.id.charAt(pos);
		obj.rawId = obj.img.id.substring(0,pos-1);
	}
	
	return obj;
};
searchshield.GetScannedLink = function (link)
{
	if (!xplSearch || !(xplSearch.links instanceof Array))
		return link;

	// look for the link we scanned based on original element
	for (var i = 0; i < xplSearch.links.length; i++)
	{
		if (xplSearch.links[i].element.href == link)
			return xplSearch.links[i].href;
	}
	// else return the incoming link
	return link;
};
searchshield.previouslyScanned = function (links, hash)
{
	for (var i = 0; i < links.length; i++)
	{
		if ((links[i] != null) && (links[i].hash != null) && 
			(links[i].hash == hash) && (links[i].checked == true))
			return true;
	}
	return false;
};
searchshield.initPopupAlert = function (doc)
{
	// check if it exists first
	if (doc.getElementById("XPLSS_PopupAlert"))
		return;

	// create a div to use for the popup itself, hide for now
	var popup_div = doc.createElement("DIV");
	popup_div.setAttribute("id", "XPLSS_PopupAlert");
	popup_div.style.position = "absolute";
	popup_div.style.zIndex = "10000";
	doc.body.appendChild(popup_div);
};
searchshield.initFlyover = function (doc, engine)
{
	// create in top doc only
	if (doc !== window.top.document)
		doc = window.top.document;

	// check if it exists first
	if ((doc == null) || (doc.getElementById("XPLSS_Flyover")))
		return;

	// create a div to use for the flyover itself, hide for now
	var flyover_div = doc.createElement("DIV");
	flyover_div.setAttribute("id", "XPLSS_Flyover");
	flyover_div.style.position = "absolute";
	flyover_div.style.zIndex = "10000";
	doc.body.appendChild(flyover_div);

	// create a layer for the image
	var trans_div = doc.createElement("DIV");
	trans_div.setAttribute("id", "XPLSS_Trans");
	trans_div.style.position = "absolute";
	trans_div.style.zIndex = "9999";
	doc.body.appendChild(trans_div);
};
searchshield.ShowPopupAlert = function (doc, link, hash, search)
{
	// build the content
	var popup_content = searchshield.avgCallFunc(doc, 'BuildPopupAlert', hash, search);
	if (popup_content == null || popup_content == "")
		return;

	// get the div
	var div = doc.getElementById("XPLSS_PopupAlert");
	div.innerHTML = searchshield.CleanupHTML(popup_content);

	// set position, account for scrolling
	var zoom = searchshield.zoomLevel();
	var pageOffsetX = Math.round(doc.documentElement.scrollLeft/zoom);
	var pageOffsetY = Math.round(doc.documentElement.scrollTop/zoom);
	
	div.style.left = 10 + pageOffsetX + "px";
	div.style.top = 10 + pageOffsetY + "px";
	
	// TODO: the event handler function doesn't exist so, is this even necessary?
	//div.attachEvent("onmouseout", HidePopupAlert);

	// set the link
	//var data = doc.getElementById("avgalertpopurl");
	//if (data)
	//		data.innerHTML = escape(link);

	// set visibility
	div.style.visibility = "visible";

	//navigate to the link after timed delay
	// TODO: Bug 31707 - make this open a new tab/window
	setTimeout(function(){doc.location.assign(link)}, 3000);
};
searchshield.avgCallFunc = function (doc, name /*, param1..., paramN*/)
{
	// get the data element
	var avg_ls_data = (typeof gAvgDataElement !== 'undefined') ? gAvgDataElement : doc.getElementById("avglsdata");

	if ((avg_ls_data == null) || (name == null))
		return;
	
	// save the data element
	gAvgDataElement = avg_ls_data;

	// for some reason you can't fire and event on an element with no parent node
	if (avg_ls_data.parentNode == null)
		return;

	// set the attributes
	avg_ls_data.setAttribute("function", name);
	
	// set variable length of optional parameter attributes
	var pcnt = 0;
	for (var i=2; i < arguments.length; i++)
		avg_ls_data.setAttribute("param"+(++pcnt), arguments[i]);

	avg_ls_data.fireEvent("onrowenter");

	// get the result
	return avg_ls_data.getAttribute("result");	
};

// general use functions - begin
// DOM Functions
searchshield.getAnchorNode = function (node, filterFunc)
{
	// filterFunc should return a boolean
	if (!filterFunc || !filterFunc instanceof Function)
		return null;
		
	// go up the dom tree starting at node and look for anchor 
	// before hitting a header, div or table element 
	while ((node != null)			&&
			(node.tagName != null)	&& 
			(node.tagName != "A"))
	{
		if (filterFunc(node))
		{
			node = null;
			break;
		}
		node = node.parentNode;
	}

	return node;
};
searchshield.getDocuments = function (frame, frameArray)
{	// recursively get all embedded frames/docs
	frameArray.push(frame.document);
	var frames = frame.frames;
	for (var i = 0; i < frames.length; i++)
	{
		// recurse on each frame
		searchshield.getDocuments(frames[i], frameArray);
	}
	return frameArray;
};
searchshield.NextSiblingNode = function (element)
{
	var TEXTNODE = 3;
	var ParentNode = element.parentNode;

	if (!ParentNode)
		return;

	var NextSibling = ParentNode.nextSibling;
	while (NextSibling)
	{
		if (NextSibling.nodeType != TEXTNODE)
			return NextSibling;

		NextSibling = NextSibling.nextSibling;
	}

	return;
};
searchshield.getParentNodeByAttribute = function (attrName, attrValue, node, maxDepth)
{
	if (!node)
		return null;
	
	var maxLoop = maxDepth ? maxDepth : 1;
	var pNode = node.parentNode;
	
	if (!pNode)
		return null;
	
	for(; 0 < maxLoop; maxLoop--) 
	{
		if ((pNode[attrName]) && 
			(pNode[attrName].toLowerCase() === attrValue.toLowerCase())) 
		{
			return pNode;
		}

		pNode = pNode.parentNode;
		if (!pNode)
			return null;
	}

	return null;
};
searchshield.getParentNodeByClassName = function (className, node, maxDepth) 
{
	return searchshield.getParentNodeByAttribute("className", className, node, maxDepth);
};
searchshield.getParentNodeById = function (id, node, maxDepth)
{
	return searchshield.getParentNodeByAttribute("id", id, node, maxDepth);
};
searchshield.getParentNodeByTagName = function (tagName, node, attrName) 
{	// find parent node by tag name and optional attribute name

	if (!tagName || !node || !node.parentNode)
		return null;
	
	tagName = tagName.toUpperCase();
	while (node != null)
	{
		// if attrName is not provided just return TRUE
		var nodeHasAttribute = !!attrName ? !!node[attrName] : true;
		if ((node.tagName == tagName) && (nodeHasAttribute))
			return node;
		
		node = node.parentNode;
	}
	
	// no div
	return null;
};
searchshield.getTopLevelDocument = function (doc)
{	// return the top level document for the given doc, could be itself

	// TODO: determine a method of doing this for IE, if necessary
	
	// don't check about:blank
	if (doc && (doc.location.href == "about:blank"))
		return doc;

	// Check if already a top level document
	for (var i = 0; i < gBrowser.browsers.length; i++)
	{
		if (doc == gBrowser.browsers[i].contentDocument)
			return doc;
	}

	// Not a top level, check all frames 
	var documents;
	for (var j = 0; j < gBrowser.browsers.length; j++)
	{
		// get all docs for each browser
		documents = searchshield.getDocuments(gBrowser.browsers[j].contentWindow, new Array());
		for (var k = 0; k < documents.length; k++)
		{
			// check if doc is from current browser
			if (doc == documents[k])
			{
				// it is, return the top level doc for this browser
				return gBrowser.browsers[j].contentDocument;
			}
		}
	}
	
	return doc;
};
searchshield.getTopLevelWindow = function ()
{
	// TODO: determine a method of doing this for IE, if necessary
	return mediator.getMostRecentWindow("navigator:browser");
};

//Event functions
searchshield.addListener = function (object, evtType, listener, useCapture)
{
	useCapture = !!useCapture;

	if (object.addEventListener)
	{
		object.addEventListener(evtType, listener, useCapture);
		return true;
	}
	else if (object.attachEvent)
	{
		 object.attachEvent("on"+evtType, listener);
		 return true;
	}
	
	return false;
};
searchshield.cancelEvent = function (event)
{
	event.cancelBubble = true;
	event.returnValue = false;
};
searchshield.doEvent = function (evtObj, evtTarget, evtName, evtType, bubbles, cancelable)
{
	bubbles		= !!bubbles;
	cancelable	= !!cancelable;
	
	if (document.createEvent)
	{
		var evt = document.createEvent("Events");
		evt.initEvent(evtName, bubbles, cancelable);
		evtTarget.dispatchEvent(evt);
		return true;
	}
	else if (document.createEventObject)
	{
		var evt = document.createEventObject(evtObj);
		evtTarget.fireEvent("on" + evtType, evt);
		return true;
	}
	
	return false;
};
searchshield.removeListener = function (object, evtType, listener, useCapture)
{
	useCapture = !!useCapture;
	
	if (object.removeEventListener)
	{
		object.removeEventListener(evtType, listener, useCapture);
		return true;
	}
	else if (object.detachEvent)
	{
		 object.detachEvent(evtType, listener);
		 return true;
	}
	
	return false;
};


// HTML functions
searchshield.CleanupHTML = function (data)
{
	if (data == null)
		return data;

	// cleanup html data, replace any new lines
	data = data.replace(/\r/g, "");
	data = data.replace(/\n/g, "");
	// escape any single quotes
	data = data.replace(/'/g, "\\'");

	return data;
};
searchshield.removeHtmlTags = function (str)
{
	var re = new RegExp('(<[^>]+>)','g');
	var strStr = new String(str);
	if (!!strStr)
		return strStr.replace(re, '');
	else
		return str;
	
};


// Browser functions
searchshield.containedIn = function (container, element)
{
	while (element != null) 
	{
		if (container == element) 
		{
			return true;
		}
		element = element.parentNode;
	}
	return false;
};
searchshield.elementSize = function (element)
{
	//returns an array [sizeX, sizeY]
	
	var elemX;
	var elemY;
	
	elemX = parseInt(element.offsetWidth);
	elemY = parseInt(element.offsetHeight)
	
	return [elemX, elemY];
};
searchshield.GetFullBoundingRect = function (element)
{
	if (!element) return;

	// get bounding rect for incoming element
	var elementRect = element.getBoundingClientRect();
	var nextImg = null;
	var nextImgRect = null;

	// first check for another non-TextNode element after this one
	var siblingElement = searchshield.NextSiblingNode(element);
	if (	siblingElement && 
		siblingElement.firstChild && 
		siblingElement.id && 
		siblingElement.id.indexOf("XPLSS_") != -1)
	{
		nextImg = siblingElement.firstChild;		
		nextImgRect = nextImg.getBoundingClientRect();	
	}
	else
	{
		return elementRect;
	}
	
	if ((nextImgRect.top >= elementRect.bottom) && 
		(nextImgRect.left <= elementRect.left))
	{	// images appear to be on seperate lines
		return elementRect;
	}

	// else merge the rects together into a new one
	var newRect = new function() { this.top=0; this.left=0; this.right=0; this.bottom=0; this.mid=0;};
	newRect.top = Math.min(elementRect.top, nextImgRect.top);
	newRect.left= Math.min(elementRect.left, nextImgRect.left);
	newRect.right=Math.max(elementRect.right, nextImgRect.right);
	newRect.bottom=Math.max(elementRect.bottom, nextImgRect.bottom);
	newRect.mid = Math.min(elementRect.right, nextImgRect.left);
	
	return newRect;
};
searchshield.offsetLeft = function (element)
{
	var offset = 0;
	while (element)
	{
		offset += element.offsetLeft;
		element = element.offsetParent;
	}

	return offset;
};
searchshield.offsetTop = function (element)
{
	var offset = 0;
	while (element)
	{
		offset += element.offsetTop;	
		element = element.offsetParent;
	}

	return offset;
};
searchshield.scrollSize = function (imageElem)
{
	// returns an array [scrollX, scrollY, hasParentFrame]

	var scrollX;
	var scrollY;
	var hasParentFrame;
	
	// firefox
	if (window.pageXOffset && window.pageYOffset)
	{
		scrollX = window.pageXOffset;
		scrollY = window.pageYOffset;
	}
	else if (document.documentElement || document.body)
	{
		scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
		scrollY = document.documentElement.scrollTop || document.body.scrollTop;

		if (imageElem)
		{
			var frames = document.frames;
			if (frames)
			{
				for (var i=0; i < frames.length; i++)
				{
					var img;
					try {
						img = frames[i].document.getElementById(imageElem.id);
					}
					catch(domErr){}

					if (img != null)
					{
						scrollX = frames[i].document.documentElement.scrollLeft;
						scrollY = frames[i].document.documentElement.scrollTop;
						hasParentFrame = true;
						break;
					}
				}
			}
		}
	}
	else
	{
		scrollX = 0;
		scrollY = 0;
	}
	
	return [parseInt(scrollX,10), parseInt(scrollY,10), hasParentFrame];
};
searchshield.viewPortSize = function ()
{
	// returns an array [width, height, scrollYWidth], where scrollYWidth is always 0 for IE

	var scrollXWidth	 = 19;
	var scrollYWidth	 = 0; // 0 for Microsoft IE
	var scrollBarX	 = false;
	var windowX;
	var windowY;
	
	// firefox
	if (window.innerWidth && window.innerHeight)
	{
		//TODO: validate this block if implemented for firefox
		
		windowX = window.innerWidth - scrollXWidth;
		windowY = window.innerHeight;

		try
		{
			scrollYWidth = Math.floor(Math.abs(window.innerHeight - document.documentElement.clientHeight)) + 1;
			scrollBarX = (document.documentElement.clientWidth < document.documentElement.scrollWidth);
		}
		catch(err){}

		if (scrollBarX && !scrollYWidth)
			scrollYWidth = 18;	//normally 17 (+1 top border)
					
	}
	else if (document.documentElement || document.body) 
	{
		windowX = (document.documentElement.clientWidth || document.body.clientWidth) - scrollXWidth;
		windowY = document.documentElement.clientHeight || document.body.clientHeight;
	}
	else
	{
		windowX = 0;
		windowY = 0;
	}

	return [windowX, windowY, scrollYWidth];
};
searchshield.zoomLevel = function ()
{
		var level = 1;
		if (document.body.getBoundingClientRect) {
			// rect is only in physical pixel size before IE8 
			var rect = document.body.getBoundingClientRect();
			level = Math.round (((rect.right - rect.left) / (document.body.offsetWidth)) * 100) / 100;
		}
		
		return level;
};


// Href functions
searchshield.checkUrl = function (url)
{	// cleanup a url, make sure there is a protocol on the front for scanning
	try {
		// trim
		url = url.replace(/^\s+/, "").replace(/\s+$/, "");

		// if no protocol, add http:// to it	
		if (url.indexOf("://") == -1)
			url = "http://" + url;
	}
	catch(err){}

	return url;
};
searchshield.DoesURLContain = function (url, contain)
{
	if ((url == null) || (url.length < 1))
		return false;

	// breakup the url to check
	var parts = url.split('/');
	if (parts.length < 3)
		return false;

	var domain= parts[2].toLowerCase();
	if (domain.indexOf(contain) > -1)
		return true;

	return false;
};
searchshield.FilterUrl = function (url, filter)
{
	if (!url || (url.length < 1))
		return false;
	
	if (!filter || !(filter instanceof Array))	
		return false;
		
	var parts = url.split('/');
	if ((parts == null) || (parts.length < 3))
		return false;

	var domain = parts[2];
	for (var i = 0; i < filter.length; i++)
	{
		if (domain.indexOf(filter[i]) != -1)
			return true;
	}
	return false;
};
searchshield.GetDomain = function (url)
{
	if (url != null)
	{
		// get url domain
		var parts = url.split('/');
		if ((parts != null) && (parts.length >= 3))
		{
			return parts[2].toLowerCase();
		}
	}
	
	return url;
};
searchshield.getUrlContents = function (url) 
{
	if (url == null)
		return null;

	// don't query if local url
	if (url.indexOf("linkscanner://") != -1)
		return null;

	try 
	{
		req = new XMLHttpRequest();
		req.open("GET", url, false);
		req.send(null);
		if (req.status == 200)
			return req.responseText;
		else
			return null;
	} 
	catch (err)
	{
		// nothing to do
		return null;
	}
};
searchshield.parseLink = function (href, simpleMode)
{
	var uri		  = {};
	var parameter = {
			complex: {
				pattern: /^(?:([a-z]+):(?:([a-z]*):)?\/\/)?(?:([^:@]*)(?::([^:@]*))?@)?((?:[a-z0-9_-]+\.)+[a-z]{2,})(?::(\d+))?(?:([^:\?\#]+))?(?:\?([^\#]+))?(?:\#([^\s]+))?$/i,
				element: ['source','scheme','subscheme','user','pass','host','port','path','query','fragment']
				},
			simple: {
				pattern: /^(?:([a-z]+):\/\/)?((?:[a-z0-9_-]+\.)+[a-z]{2,})(?:\/)([^:\?]+)?(?:([\?|\#])([^\?]+))?$/i,
				element: ['source','scheme','host','path','delimiter','query']
			}
		};
	var mode	= simpleMode !== false ? 'simple' : 'complex';
	var pattern	= parameter[mode].pattern;
	var element	= parameter[mode].element;
	
	if (!href)
		return uri;

	var matches	= href.match(pattern);
	
	if (matches)
	{
		// --------------------
		// iterate over the matches array and populate uri properties
		// using the respective element parameter as the name.
		// NOTE: set raw property type as String to make inArray()
		// work properly with instanceof.
		// --------------------
		for (var i=0; i < matches.length; i++)
			uri[element[i]] = new String(matches[i] || "");
		
		// --------------------
		// create an array, hostArray, from host, for example,
		// host="www.google.com" and hostArray=["www","google","com"]
		// --------------------
		uri.hostArray	= uri.host.split(".");
		
		// --------------------
		// create an array, qsArray, from query, for example,
		// query='hl=en&q=javascript&btnG=Search&aq=f&aqi=g10&aql=&oq=&gs_rfai='
		// qsArray=[{hl:'en'},{q:javascript}, ... ,(qs_rfai:''}]
		//
		// $0=entire match, $1=capture 1, $2=capture 2
		// must include $0 even though it is unused so
		// the replace works properly
		// --------------------
		uri.qsArray		= [];
		uri.query.replace(/(?:^|&)([^&=]*)=?([^&]*)/g, 
							function ($0, $1, $2) {
								if ($1) uri.qsArray[$1] = $2;
								}
							);
	}
	
	//non-standard urls require a fail-safe that relies on simply splitting the href
	function splitLink(href)
	{
		// split the href on '/'
		var linkParts = href.split("/");

		// need domain and path
		if ((linkParts == null) || (linkParts.length < 2))
			return false;
	
		var uri = {
			delimiter: (linkParts[3]).substring(0,1),
			host: linkParts[2],
			hostArray: (linkParts[2]).split('.'),
			path: (linkParts[3]).substring(1),
			qsArray: {},
			query: '',
			scheme: (linkParts[0]).substring(0, linkParts[0].length-1),
			source: href
			};

		return uri;
	}

	if (!uri.host)
		uri = splitLink(href);

	return uri;
};

// general functions
searchshield.arrayKeys = function (array)
{
	var keys = new Array();
	for(k in array)
		keys.push(k);

	return keys;
};
searchshield.inArray = function (key, array, caseSensitive, exactMatch)
{
	if (! array instanceof Array)
		return false;
	
	if (caseSensitive !== true)
		caseSensitive = false;
		
	if (exactMatch !== false)
		exactMatch = true;
	
	if (key instanceof String)
	{
		for (var i=0; i < array.length; i++)
		{
			var k = caseSensitive ? key.valueOf() : key.valueOf().toLowerCase();
			var a = caseSensitive ? array[i] : array[i].toLowerCase();
			if(exactMatch && k === a)
				return true;
			else if (!exactMatch && (-1 !== k.indexOf(a)))
				return true;
		}
	}
	else if (key instanceof Array)
	{
		for (var i=0; i < array.length; i++)
			for (var j=0; j < key.length; j++)
			{
				var k = caseSensitive ? key[j] : key[j].toLowerCase();
				var a = caseSensitive ? array[i] : array[i].toLowerCase();
				if (exactMatch && k === a)
					return true;
				else if (!exactMatch && (-1 !== k.indexOf(a)))
					return true;
			}
	}

	return false;
};
// general use functions - end


// Search constructor
searchshield.Search = function()
{
	this.doc 			= null;
	this.engine 		= null;
	this.engines 		= null;
	this.links 			= null;
	this.uri 			= null;
	this.searchHash 	= null;
	this.checkUrl 		= null;
	this.useLocalImgs 	= null;
	this.clockUrl 		= null;
	// create engine list (actually key/value object will be used)
	this.engineList		= {};
};

searchshield.Search.prototype.getSearchNames = function()
{	// order is important
	var names =  [
		'Google',
		'AVGGoogle',
		'AltaVista',
		'AVGYahoo',
		'Yahoo',
		'Bing',
		'MSN', // MSN redirects to BING
		'Baidu',
		'Earthlink',
		'AOL',
		'Ask',
		'Yandex',
		'Seznam',
		'Webhledani',
		'eBay',
///temp		'Digg',
		'Slashdot',
		'Twitter',
		'GMail',
		'Facebook'
	];
	return names;
};

searchshield.Search.prototype.detectEngine = function(href)
{
	if (!href)
		return;

	var aEng = searchshield.Search.prototype.getSearchNames();
	var aEngLen = aEng.length;
	for (var i=0; i < aEngLen; i++)
	{
		if (searchshield[aEng[i] + 'SearchEngine'].prototype.validSearch(href))
			return aEng[i];
	}

	return;
};

searchshield.Search.prototype.addEngine = function(engine)
{
	if (!this.engines)
		this.engines = new Array();
	
	this.engines.push(engine);
};

searchshield.Search.prototype.addLink = function(inElement, inHref)
{
	if (!this.links)
		this.links = new Array();

	var hrefHash;
	try
	{
		hrefHash = searchshield.avgCallFunc(this.doc, 'GetHash', inHref);
	}
	catch (e){}

	var newNode = {
			element:	inElement,
			href: 		inHref,
			hash:		hrefHash,
			search:		this.searchHash
		};
	
	this.links.push(newNode);
	
	return newNode;
}

// process the search result page after all search engines have been added
searchshield.Search.prototype.process = function(doc)
{
	// only process when searchshield is enabled
	if (0 == searchshield.avgCallFunc(doc, 'GetSearchEnabled'))
		return;
		
	this.doc	= doc;
	this.href	= this.doc.location.href;
	this.uri	= searchshield.parseLink(this.href);

	try
	{
		this.searchHash 	= searchshield.avgCallFunc(this.doc, 'GetHash', this.href);

		// get any previously active engine
		this.engine		= this.engineList[this.searchHash.toString()];
	}
	catch (e) {}

	/*
	
	Process Steps:
	1. Add all supported search engines
	2. Identify the active search engine
	3. Get all document links and add AVG images 
	*/
	
	// STEP 1 - Add all supported search engines
	if (!this.engines)
	{
		var aEng = xplSearch.getSearchNames();
		var aEngLen = aEng.length;
		for (var i=0; i < aEngLen; i++)
		{
			xplSearch.addEngine(new searchshield[aEng[i]+'SearchEngine'](this));
		}
	}
	
	// search the engines if we didn't find one
	if (!this.engine)
	{
		// STEP 2 - Identify the active search engine
		var engLen = this.engines.length;
		for (var i = 0; i < engLen; i++)
		{
			if (this.engines[i].validSearch())
			{
				this.engine		= this.engines[i];
				break;
			}
		}
		
		// create a new engine instance to store
		this.engineList[this.searchHash.toString()] = this.engine;
		
		// init this search, if < 1 either an error or disabled
		//var sdkInit = 0;
		//try {
		//	sdkInit = xpl_sdk.SXPL_InitSearch(this.href);
		//}
		//catch(e){}
		//if (sdkInit < 1)
		//	return false;
	}

	// return immediately if there is not an active search engine
	if (!this.engine)
		return false;
	
	try {	
		// base url to check for icons
		this.checkUrl 	= searchshield.avgCallFunc(this.doc, 'GetIconUrl', '1');

		// check if using linked or local icons
		this.useLocalImgs	= !searchshield.getUrlContents(this.checkUrl);

		// get the clock url
		this.clockUrl 	= searchshield.avgCallFunc(this.doc, 'GetIconUrl', '0');
	}
	catch(e){}
		

	// STEP 3 - Get all document links and add AVG images
	var alltags = this.doc.getElementsByTagName("*");	// this method works for IE, FF and Chrome
	for (var i=0; i < alltags.length; i++)
	{
		// ignore verdicts
		if (alltags[i].id && (alltags[i].id.indexOf("LXPLSS_") != -1))
			continue;
	
		//should the link be included?  Make sure includeLink always returns an href else FALSE,
		var href = this.engine.includeLink(alltags[i]); 
		if (!href)
			continue;

		var newNode = this.addLink(alltags[i], href);
		this.engine.addImage(newNode, this.clockUrl, false);
	}

	return (this.links ? this.links.length : false);
};
////////////////    SEARCH    ////////////////



////////////////    SEARCH ENGINE    ////////////////

// Interface for a SearchEngine object
searchshield.SearchEngine = function(search)
{
	this.search = search;
	this.type = 'standard';
	this.processFrames = false;
	this.new_links		= true;
	this.onlyPrimaries	= true;
	this.inline = {
		clockImage: "linkscanner://clock12.png",
		image: [	"linkscanner://safe12.png",
					"linkscanner://caution12.png",
					"linkscanner://warning12.png",
					"linkscanner://blocked12.png"
				],
		color: {
			border: ["#00A120;", "#EAA500;", "#F57301;", "#D20003;"],
			background: ["#C3E5CA;", "#FEEFAE;", "#FFD3B0;", "#F5D4C1;"]
		}
	};
	this.filter_urls = [
		"ad.doubleclick.net", "ads1.revenue.net", "aslads.ask.com",
		"bluestreak.com", "clickbacktrack.net", "clickbank.net",
		"clickboothlnk.com", "clickmanager.com", "clickserve.cc-dt.com",
		"clickserve.dartsearch.net", "clicktraxmedia.com", "clk.atdmt.com",
		"dpi-digialphoto.com", "feedpoint.net", "hypertracker.com",
		"jdoqocy.com", "kqzyfj.com", "m1428.ic-live.com",
		"mediaplex.com", "mr.mdmngr.com", "n339.asp-cc.com",
		"offeredby.net", "offerweb.com", "pinktrax.com",
		"pinktrax.com", "pixel1523.everesttech.net", "qckjmp.com",
		"r.rd06.com", "revenuewire.net", "s0b.bluestreak.com",
		"s2.srtk.net", "servedby.advertising.com", "store.yahoo.com",
		"tf8.cpcmanager.com", "thetoptracker.com", "track.searchignite.com",
		"tracking.searchmarketing.com", "www.dpbolvw.net", "www.rkdms.com",
		"www.yellowbookleads.com"
		];
	this.shortened_urls = [
		"3.ly", "bit.ly", "is.gd", "tr.im", "short.to", "tiny.cc", "tinyurl.com"
		];
	this.showCleanVerdicts		= true;
	this.showLowRiskVerdicts	= true;
	this.showMedRiskVerdicts	= true;
	this.VeriSignSplit			= searchshield.VERISIGN_SPLIT_NOTEST;
};
searchshield.SearchEngine.prototype.flyoverExists = function (doc)
{
	return !!doc.getElementById("XPLSS_Flyover");
};
searchshield.SearchEngine.prototype.inlineExists = function (doc)
{
	return !!doc.getElementById("XPLSS_InlineFlyover");
};
searchshield.SearchEngine.prototype.validSearch = function(href) { return false; };
searchshield.SearchEngine.prototype.includeLink = function(link) { return false; };
searchshield.SearchEngine.prototype.insertNodes = function(node, doc)
{
	var element = node.element;
	var parentNode = node.element.parentNode;
	if (parentNode == null)
	{
		// try and find element again based on the hash
		element = doc.getElementById("xplid_" + node.hash);
		parentNode = !!element ? element.parentNode : null;
	}

	var insertNode = !!element ? element.nextSibling : null;
	while ((insertNode			!= null) && 
			(insertNode.tagName	!= null) && 
			(insertNode.tagName	== "SPAN"))
	{
		insertNode = insertNode.nextSibling;
	}
	
	return [insertNode, parentNode];
};
searchshield.SearchEngine.prototype.addImage	= function(node, image, hidden)
{
	var element	= node.element;
	var hash	= node.hash;
	var score 	= node.score;

	// set verdict display configuration
	var doc = element.ownerDocument;
	if (!doc.getElementById('XPLSS_Flyover'))
		searchshield.initFlyover(doc, this);

	// get the proper insertion point for the image
	var insertNodes = this.insertNodes(node, doc);
	var insertNode = insertNodes[0];
	var parentNode = insertNodes[1];

	if (!parentNode)
		return;

	// see if we already have an image
	if ((insertNode		!= null) && 
		(insertNode.id	!= null) && 
		(insertNode.id.indexOf("XPLSS_") > -1))
	{
		return;
	}

	// mark search result anchor so it isn't processed repeatedly
	if (score == undefined)
		element.setAttribute("avglschecked", hash + "S" + this.VeriSignSplit);

	// create a new image
	var img = doc.createElement('img');
	img.src = image;
	img.id = "XPLSS_" + hash;
	img.style.borderStyle = "none";
	img.style.margin = "0 3px";
	
	// for IE, specify these style attributes to prevent inadvertent inheritance from parent
	if (img.width && img.height)
	{
		img.style.width = img.width + 'px';
		img.style.height = img.height + 'px';
	}
	
	// apply custom element styles
	this.updateElementStyle(img, this.addImageStyle);
	
	// create the link element 
	var anchor = doc.createElement("A");
	anchor.setAttribute("id", "LXPLSS_" + hash);

	if ((hidden != null) && (hidden == true))
	{	// hiding the parent will also hide its child nodes
		anchor.style.display = "none";
	}
	
	// Default anchor styles
	//Over-ride possible border style with inline declaration
	anchor.style.borderStyle = "none";

	// apply custom element styles
	this.updateElementStyle(anchor, this.addAnchorStyle);

	if (score == searchshield.SCORE_SS_VERISIGN)
	{
		anchor.style.textDecoration = "none";
		anchor.style.background = "none";
	}

	// append the image to the link
	anchor.appendChild(img);

	// insert the node as either a sibling or a child
	if (insertNode != null)
		parentNode.insertBefore(anchor, insertNode);
	else
		parentNode.appendChild(anchor);
		
	return anchor;
};
searchshield.SearchEngine.prototype.updateImage = function (hash, search, score, image, alt_image, flyover, click_thru, altClick_thru)
{
		var updated = false;

		var frameDoc  = this.search.doc;
		var docFrames = frameDoc.frames;
		var frameElem;
		if (docFrames && this.processFrames)
		{
			for (var i=0; i < docFrames.length; i++)
			{
				try {
					if (docFrames[i].document.getElementById(hash))
					{
						frameElem = docFrames[i].frameElement;
						frameDoc = docFrames[i].document;
						break;
					}
				} 
				catch(err){}
			}
		}

		while ((element = frameDoc.getElementById(hash)) != null)
		{
			// check configuration to determine if verdict display property
			var showVerdict = true;			
			var nSeverity = Number(score - 1);
			switch (nSeverity)
			{
				case searchshield.XPLCHECK_RESULT_SEV_LOW:
					showVerdict = this.showLowRiskVerdicts;
					break;
				case searchshield.XPLCHECK_RESULT_SEV_MED:
					showVerdict = this.showMedRiskVerdicts;
					break;
				case searchshield.XPLCHECK_RESULT_SEV_NONE:
					showVerdict = this.showCleanVerdicts;
					break;
				default:
					if (score == searchshield.SCORE_SS_VERISIGN)
						showVerdict = this.showCleanVerdicts;
					break;
			}
			
			// remove image if no url specified
			if ((!showVerdict) || (image == null) || (image.length < 1))
			{
				// hide the parent anchor node
				element.parentNode.style.display = "none";

				// mark the id as being hidden (element is the image)
				element.id = element.id + "H";
				updated = true;
				
				// if not a verisign score
				if (score != searchshield.SCORE_SS_VERISIGN)
					continue;
			}

			// cleanup flyover, replace any new lines or single quotes
			flyover = searchshield.CleanupHTML(flyover);

			// mark the id as having been updated
			element.id = element.id + "U" + score;
			element.src	= image;
			element.attachEvent("onmouseover", function(e){avglsflyover.popup(e, hash, search, flyover)});
			element.attachEvent("onmouseout", function(e){avglsflyover.hide(e)});

			// check for attribute updates (elementAttribute is an associative array (i.e., object)
			if (this.elementAttribute)
			{
				for (a in this.elementAttribute)
				{
					if(this.elementAttribute[a])
						element.setAttribute(a, this.elementAttribute[a]);
				}
			}

			// To dynamically reduce verdict image size if it causes its container to scroll
			// when not showing alt images determine if the element containing
			// the verdict image is scrolling and decrease the image size by
			// the scroll amount (min size is 80% or original)
			var reduceBy	= 0.8;
			var scrl		= 0;
			if (!alt_image || this.omitAltImage || this.VeriSignSplit == searchshield.VERISIGN_SPLIT_TESTB)
			{
				try{
					var maxLoop = 5;
					var cN = element.parentNode.parentNode;  //image->anchor->containerNodes...
					while (cN && maxLoop--)
					{
						if (cN.tagName == "DIV" || cN.tagName == "SPAN")
						{
							// get object height depending on ie document mode
							var clientHeight = (cN.clientHeight == 0 || 
								(this.search.doc.documentMode && this.search.doc.documentMode < 8)) ? 
								cN.offsetHeight : 
								cN.clientHeight;
							scrl = cN.scrollHeight - clientHeight;
							break;
						}

						cN = cN.parentNode;
					}

					if (0 < scrl)
					{
						var eH = (element.height - scrl)/element.height;
						if (reduceBy > eH)
							eH = reduceBy;
						
						var newDim = Math.ceil(eH*element.height);
						
						element.height = newDim;
						element.width = newDim;
						
						element.style.height = newDim + "px";
						element.style.width = newDim + "px";
					}
				}
				catch(e){}
			}

			// set default style attributes
			element.style.display		= "";
			
			// if verisign icon showing move our icon up for better centering of the 2
			// except for IE7 browser - it does not like this style
			try {
				var ieVersion = parseFloat(navigator.appVersion.split("MSIE")[1]);
				if (alt_image && (alt_image.length > 0) && ieVersion != 7)
					element.style.verticalAlign = "10%";
			}
			catch(err){};

			// apply custom element styles
			this.updateElementStyle(element, this.updateImageStyle)

			// update the click thru
			var link = this.search.doc.getElementById("L" + hash);
			if (link)
			{
				link.href = click_thru;
				link.id = link.id + "U" + score;
			}

			updated = true;

			// add the alternate image if supplied BUT not on avg yahoo
			if ((alt_image)				&& 
				(alt_image.length > 0)	&& 
				(!this.omitAltImage)	&&
				(this.VeriSignSplit != searchshield.VERISIGN_SPLIT_TESTB))
			{

				var vhash = hash.substring(hash.indexOf("_")+1);

				// create a temporary link node
				var tmp_node = {
						element:	element.parentNode,
						href:		altClick_thru,
						hash:		vhash + "VU" + score,
						search:		this.searchHash,
						score:		score
					};

				var altAnchor = this.addImage(tmp_node, alt_image, false);
				if (altAnchor && altAnchor.firstChild)
				{
					altAnchor.firstChild.setAttribute("onmouseover", "");
					altAnchor.href = altClick_thru;
				}
			}
		}
		
		if (updated != false)
		{
			this.resizeFrame(frameElem);
			return true;
		}

	return false;
};
searchshield.SearchEngine.prototype.updateElementStyle = function (element, elementStyle)
{
	if (elementStyle)
	{	// a NULL attribte value will unset it
		for(attr in elementStyle)
		{
			try {
				if (element.style.setAttribute)
					element.style.setAttribute(attr, elementStyle[attr]);
				else
					element.style[attr] = elementStyle[attr];
			} catch(err){}
		}
	}
};

searchshield.SearchEngine.prototype.resizeFrame = function (frameElem)
{	// resize frame to prevent unwanted scrolling after inserting verdicts

	// ignore inline and non-frame engines
	if ((this.type == 'inline') || (!this.processFrames))
		return;

	// ensure all required elements are available
	if ((frameElem == null) || (frameElem.style == null) || (frameElem.contentWindow == null))
		return;

	// if frame is scrolling vertically then resize
	var frameHeight = parseInt(frameElem.style.height, 10);
	if (!isNaN(frameHeight) && (frameHeight < frameElem.contentWindow.document.body.scrollHeight))
		frameElem.style.height = frameElem.contentWindow.document.body.scrollHeight + 'px';

	return;
};

searchshield.SearchEngine.prototype.getImgElement = function (element)
{	// return an xpl img element associated with a given element
	if (element == null)
		return null;

	// go up the parent tree looking for a header or div
	while ( (element.parentNode != null) && 
			(element.tagName.charAt(0) != "H") && 
			(element.tagName.charAt(0) != "D") &&
			(element.tagName.charAt(0) != "T") )
	{
		element = element.parentNode;
	}

	// if all the way to the top, nothing
	if ((element.tagName == "HTML") || (element == null))
		return null;

	// get image tags, if none we are done
	var imgTags = element.getElementsByTagName("IMG");
	if ((imgTags == null) || (imgTags.Length < 1))
		return null;

	for (var i = 0; i < imgTags.length; i++)
	{
		if ((imgTags[i].id == null) || (imgTags[i].id.indexOf("XPLSS_") == -1))
			continue;

		return imgTags[i];
	}

	// else didn't find anything
	return null;
};

searchshield.SearchEngine.prototype.setRatingsConfig = function (doc)
{
	// get verdict configuration, need at least severity
	var results = searchshield.avgCallFunc(doc, 'GetRatingsConfig');
	var parts = !!results ? results.split('::') : null;

	if (parts != null && parts.length >= 5)
	{	//if set to default then get config value
		if (this.showCleanVerdicts === true)
			this.showCleanVerdicts		= (parseInt(parts[0]) == 1) ? true : false;
			
		if (this.showLowRiskVerdicts === true)
			this.showLowRiskVerdicts	= (parseInt(parts[1]) == 1) ? true : false;
		
		if (this.showMedRiskVerdicts === true)
			this.showMedRiskVerdicts	= (parseInt(parts[2]) == 1) ? true : false;
			
		this.VeriSignSplit	= (parseInt(parts[4]));
	}
	
	return true;
};

searchshield.SearchEngine.prototype.init_inline_ratings = function (doc)
{
	if ((doc == null) || (doc.getElementById("XPLSS_InlineFlyover")))
		return;
	
	// create the popup box
	var box = doc.createElement("DIV");
	try {
		box.setAttribute("id", "XPLSS_InlineFlyover");
		box.style.visibility = "hidden";
		box.style.left = "-5000px";

		box.style.position = "absolute";
		box.style.zIndex = "9999";
		box.style.padding = "0px 0px";
		box.style.marginLeft = "0px";
		box.style.marginTop = "0px";
		box.style.overflow = "hidden";
		box.style.wordWrap = "break-word";
		box.style.color = "black";
		box.style.fontSize = "10px";
		box.style.textAlign = "left";
		box.style.lineHeight = "130%";

		doc.body.appendChild(box);
		box = null;
	}
	catch(boxErr){}
};

searchshield.SearchEngine.prototype.show_inline_ratings = function (doc, node, image)
{	
	var href	= node.href;
	var anchor	= node.element;

	if ((href == null) || (href.length < 1))
		return;
		
	if (avglsinlineflyover.imageExists(anchor))
		return;
	
	// mark search result anchor so it isn't processed repeatedly
	anchor.setAttribute("avglschecked", "1");
	
	// get verdict 
	this.display_inline(doc, anchor, href, node, false);
};

searchshield.SearchEngine.prototype.display_inline = function (doc, anchor, href, node, update, min_severity)
{
	// min_severity is the lowest severity to display, so setting it to
	// 1 would not display safe icons
	
	var results	= searchshield.avgCallFunc(doc, 'MalsiteCheck', href);
	if (results == null)
		return;
	
	var parts = results.split('::');
	
	// need at least severity
	if (parts == null)
		return;
			
	var nSeverity = parseInt(parts[0]);
	
	if (!update && nSeverity == searchshield.XPLCHECK_RESULT_SEV_NONE)
	{
		var shortUrl = searchshield.FilterUrl(href, this.shortened_urls);
		if (shortUrl)
		{	// shortened url verdicts display later
			var engine = this;
			anchor.attachEvent("onmouseover", function(event){avglsinlineflyover.mouseOverHandler(event, doc, engine)}, false);
			return;
		}
	}

	//blacklist url
	var blShortUrl = false;
	if (nSeverity == searchshield.XPLCHECK_RESULT_SEV_BLOCK)
	{
		var shortUrl = searchshield.FilterUrl(href, this.shortened_urls);
		if (shortUrl)
			blShortUrl = true;
	}
	
	// need xlated cat tag and category
	if (parts.length < 3)
		return;

	// check the minimum to display
	if ((min_severity != null) && (nSeverity < min_severity))
		return;
		
	if (nSeverity == searchshield.XPLCHECK_RESULT_SEV_LOW && !this.showLowRiskVerdicts)
	{
		if (update)
			this.avg_ls_inline_hide_verdict(anchor);
		
		return;
	} 
	if (nSeverity == searchshield.XPLCHECK_RESULT_SEV_MED && !this.showMedRiskVerdicts)
	{
		if (update)
			this.avg_ls_inline_hide_verdict(anchor);
		
		return;
	}
	if (nSeverity == searchshield.XPLCHECK_RESULT_SEV_NONE && !this.showCleanVerdicts) 
	{
		if (update)
			this.avg_ls_inline_hide_verdict(anchor);
			
		return;
	}

	if (update)
		this.update_inline_image(anchor, nSeverity, parts);
	else
		this.add_inline_image(doc, anchor, nSeverity, parts, blShortUrl);
};

searchshield.SearchEngine.prototype.avg_ls_inline_hide_verdict = function (anchor)
{
	var image = avglsinlineflyover.getImage(anchor);
	if (image)
	{
		image.style.display = "none";
		if (image.parentNode && image.parentNode.id == "avg_ls_anch")
			image.parentNode.style.display = "none";
	}
};

searchshield.SearchEngine.prototype.update_inline_image = function (anchor, nSeverity, aRisk)
{
	// update the image already in the page
	if (anchor && anchor.firstChild)
	{
		var html  = '';
		var image = ''; 
		if (aRisk != null && nSeverity != null)
		{
			var riskCategory = aRisk[1];
			var riskName	 = aRisk[2];
			var bgColor		 = this.inline.color.background[nSeverity];
			var borderColor	 = this.inline.color.border[nSeverity];

			image			 = this.inline.image[nSeverity];
			html			 = avglsinlineflyover.build(riskCategory, riskName, bgColor, borderColor);
		}
		
		var imageElem = anchor.firstChild;
		imageElem.src = image;
		
		if ( html && html.length > 0 )
		{
			imageElem.setAttribute("title", "");
			imageElem.attachEvent("onmouseover", function(e){avglsinlineflyover.popup(e, html)});
			imageElem.attachEvent("onmouseout", function(e){avglsinlineflyover.hide(e)});
		}
	}
};

// add the image to the page
searchshield.SearchEngine.prototype.add_inline_image = function (doc, anchor, nSeverity, aRisk, blShortUrl)
{
	if (anchor == null || anchor.parentNode == null)
		return null;

	// get the proper insertion point for the image
	var insertNode = anchor.nextSibling;
	while ((insertNode			!= null) && 
			(insertNode.tagName != null) && 
			(insertNode.tagName == "SPAN"))
	{
		insertNode= insertNode.nextSibling;
	}
	
	// see if we already have an image anchor
	if ((insertNode		!= null) && 
		(insertNode.id	!= null) && 
		(insertNode.id	== "avg_ls_anch"))
	{
		return null;
	}

	var html  = '';
	var image = this.inline.clockImage; 
	if (aRisk != null && nSeverity != null)
	{
		var riskCategory = aRisk[1];
		var riskName	 = aRisk[2];
		var bgColor		 = this.inline.color.background[nSeverity];
		var borderColor	 = this.inline.color.border[nSeverity];
		image			 = this.inline.image[nSeverity];

		var blUrl;
		if (blShortUrl)
		{
			var aRiskName = riskName.split(':');
			var sUrl = searchshield.checkUrl(aRiskName[1]);

			blUrl = {};
			blUrl.riskNameLabel = aRiskName[0] + ': ';
			blUrl.riskCategory = riskCategory;
			blUrl.bgColor = bgColor;
			blUrl.borderColor = borderColor;
			blUrl.sUrl = sUrl;
		}
		else
		{
			html = avglsinlineflyover.build(riskCategory, riskName, bgColor, borderColor);
		}
	}

	doc = anchor.ownerDocument;

	var img		 = doc.createElement("img");
	img.src		 = image;
	img.setAttribute("id","avg_ls_image");
	img.style.width = "12px";
	img.style.border = "none";
	img.style.padding = "0 3px";
	img.style.margin = "0";
	img.style.display = "inline";
	
	if ((html && html.length > 0) || (blUrl != undefined))
	{
		img.setAttribute("title", "");
		img.attachEvent("onmouseover", function(e){avglsinlineflyover.popup(e, html, blUrl)});
		img.attachEvent("onmouseout", function(e){avglsinlineflyover.hide(e)});
	}

	// create the link element 
	var newAnchor = doc.createElement("A");
	newAnchor.setAttribute("id", "avg_ls_anch");
	
	newAnchor.appendChild(img);
	img = null;

	// insert the node as either a sibling or a child
	if (insertNode != null)
		anchor.parentNode.insertBefore(newAnchor, insertNode);
	else
		anchor.parentNode.appendChild(newAnchor);	
		
	return newAnchor;		

};
////////////////    SEARCH ENGINE    ////////////////


///////////////    GOOGLE SEARCH ENGINE    ///////////////
searchshield.GoogleSearchEngine = function(search)
{
	searchshield.SearchEngine.call(this, search);
	this.onlyPrimaries = false;
};
searchshield.GoogleSearchEngine.prototype = new searchshield.SearchEngine();
searchshield.GoogleSearchEngine.prototype.constructor = searchshield.GoogleSearchEngine;
searchshield.GoogleSearchEngine.prototype.name = "google";	// the name by which the search engine is known (always lowercase)
searchshield.GoogleSearchEngine.prototype.validSearch = function(href) {

	var uri;
	if (typeof(this.search) === 'undefined' || null === this.search)
		uri = searchshield.parseLink(href);
	else
		uri = this.search.uri;

	if(!uri || !uri.host)
		return false;

	var hostMatch	= false;
	var domain		= uri.host;
	
	// re stitch the uri path and query elements to
	// use existing logic
	var path = uri.path + uri.delimiter + uri.query;

	// Domains valid for google searches, must start with '.'
	var valid_domains = new Array(".google.co", ".mozilla.co");

	// For Google the host must match:
	//	.google.com		OR
	//	.google.co.XX	where XX is a country code
	//	.google.XX		where XX is a country code
	// Where any subdomain can come before the top level domain
	var domLen = valid_domains.length;
	for (var i = 0; i < domLen; i++)
	{
		var domainLen = domain.length;
		var valid_domain_len = valid_domains[i].length;
		var tldPos = domain.indexOf(valid_domains[i]);
		if (tldPos > -1)
		{
			if (domain.charAt(tldPos + valid_domain_len) == 'm')
				hostMatch = true;
			else if ((domain.charAt(tldPos + valid_domain_len) == '.') && ((domainLen - tldPos) == valid_domain_len+3))
				hostMatch = true;
		}
		else
		{
			// get the form .google. to check the length of
			var dot_pos = valid_domains[i].indexOf(".",1);
			var valid_short_name = valid_domains[i].substring(0, dot_pos+1);

			tldPos = domain.indexOf(valid_short_name);
			if ((tldPos > -1) && ((domainLen - tldPos) == valid_domain_len))
				hostMatch = true;
		}
		if (hostMatch)
		{
			// replace beginning of domain with www.google since links will refer back to it
			if ((i > 0) && (tldPos > -1))
			{
				var last_dot = domain.indexOf(".",tldPos+1)
				if (last_dot > -1)
					domain = "www.google" + domain.substring(last_dot);
			}
			break;
		}
	}

	if (hostMatch)
	{
		// using ajax engine
		if ((path.indexOf("search?") == 0) ||
			(path.indexOf("sponsoredlinks?") == 0) ||
			(path.indexOf("webhp?") == 0) ||
			(path.indexOf("webhp#") == 0) ||
			(path.indexOf("#q=") == 0) ||
			(path.indexOf("#hl=") == 0) ||
			(path.indexOf("#sclient=") == 0))
		{
			return true;
		}
	}

	return false;
};
searchshield.GoogleSearchEngine.prototype.includeLink = function(tag)
{
	var href = "";
	var outHref = false;
	var findStr = "";

	// check for interstitials
	if (searchshield.DoesURLContain(tag.href, this.search.uri.host))
	{
		findStr = this.search.uri.host + "/interstitial?";
		if (tag.className == "l" && tag.href)
		{
			if (tag.href.indexOf(findStr) != -1)
			{
				findStr = "?url=";
				var pos = tag.href.indexOf(findStr);
				if (pos !== -1)
				{
					pos += 5;
					outHref = tag.href.substring(pos);
					if (searchshield.FilterUrl(outHref, this.filter_urls))
						return false;
							
					return outHref;
				}
			}
		}

		if (tag.className == "sla")
		{
			findStr = "/url?q=";
			urlPos = tag.href.indexOf(findStr);
			if (urlPos != -1)
			{
				urlPos += 7;
				outHref = tag.href.substring(urlPos);
				return outHref;
			}
		}
		
		// if an ad id
		if ((tag.id.indexOf("pa") == 0) || (tag.id.indexOf("an") == 0) ||
			(tag.className == "resultLink"))
		{
			var urlPos = -1;	

			// ads now need unescaping
			href = unescape(tag.href);

			findStr= "/url?sa=";
			if (href.indexOf(findStr) != -1)
			{	// first kind, locate real url
				findStr= "&q=http";
				urlPos = href.indexOf(findStr);
				if (urlPos != -1)
					urlPos += 3;	// puts it on the http
			}
			if (urlPos == -1)
			{
				findStr = "/pagead/iclk?sa=";
				if (href.indexOf(findStr) != -1)
				{	// second kind, locate real url
					findStr = "&adurl=http";
					urlPos	= href.indexOf(findStr);
					if (urlPos != -1)
						urlPos += 7; // puts it on the http
				}
			}
			if (urlPos == -1)
			{
				if (href.indexOf("/aclk?sa=") != -1)
				{	// third kind
					urlPos = href.indexOf("&q=http");
					if (urlPos != -1)
						urlPos += 3; // puts it on the http
					else
					{
						urlPos  = href.indexOf("&lp=http");
						if (urlPos != -1)
							urlPos += 4;
						else
						{
							findStr = "&adurl=http";
							urlPos	= href.indexOf(findStr);
							if (urlPos != -1)
								urlPos += 7; // puts it on the http
						}
						
					}
				}
			}
			if (urlPos == -1)
			{
				if (href.indexOf("/url?cad=") != -1)
				{	// fourth kind
					urlPos = href.indexOf("&q=http");
					if (urlPos != -1)
						urlPos += 3; // puts it on the http
				}
			}
			if (urlPos != -1)
			{
				outHref = href.substring(urlPos);

				// extract any fragment text, shouldn't be unescaped
				var pound = outHref.indexOf("#");	
				if (pound != -1)
				{
					var fragment = outHref.substring(pound);
					outHref = outHref.substring(0, pound);
					outHref = unescape(outHref);
					outHref += fragment;
					if (searchshield.FilterUrl(outHref, this.filter_urls))
						return false;

					return outHref;
				}

				outHref = unescape(outHref);
				if (outHref.indexOf("?") == -1)
				{
					var ampPos = outHref.indexOf("&");
					if (ampPos != -1)
						outHref = outHref.substring(0, ampPos);
				}
				
				if (searchshield.FilterUrl(outHref, this.filter_urls))
					return false;

				return outHref;
			}
		}

		// recommended link - use following to see one
		// http://www.google.cz/search?hl=cs&q=warey&btnG=Hledat&lr=lang_cs
		// elem parent class = r
		// href must contain - url? and q=http
		var parentNode = tag.parentNode;
		if (parentNode && (parentNode.className.toLowerCase() == "r"))
		{
			href = tag.href;
			if (href && (href.indexOf("/url?") != -1))
			{
				// locate the real url
				var urlPos = href.indexOf("q=http");
				if (urlPos != -1)
				{
					urlPos += 2;
					outHref = href.substring(urlPos);

					// include entire param up to '&'
					var ampPos = outHref.indexOf("&");
					if (ampPos != -1)
						outHref = outHref.substring(0, ampPos);

					return outHref;
				}
			}
		}
	}
	// no link to self
	else if (tag.className && (tag.className.charAt(0) == "l" || tag.className == "sla"))
	{
		// check for any images on the link
		if (0 === tag.getElementsByTagName("IMG").length)
			return tag.href;
	}

	// else nothing
	return false;
};
///////////////    GOOGLE    ///////////////


///////////////    AVG GOOGLE SEARCH ENGINE    ///////////////
searchshield.AVGGoogleSearchEngine = function(search)
{
	searchshield.SearchEngine.call(this, search);
	this.onlyPrimaries = false;
};
searchshield.AVGGoogleSearchEngine.prototype = new searchshield.SearchEngine();
searchshield.AVGGoogleSearchEngine.prototype.constructor = searchshield.AVGGoogleSearchEngine;
searchshield.AVGGoogleSearchEngine.prototype.name = "avggoogle";	// the name by which the search engine is known (always lowercase)
searchshield.AVGGoogleSearchEngine.prototype.validSearch = function(href) {

	var uri;
	if (typeof(this.search) === 'undefined' || null === this.search)
		uri = searchshield.parseLink(href);
	else
		uri = this.search.uri;

	if(!uri || !uri.host)
		return false;

	var domain		= uri.host;
	
	// re stitch the uri path and query elements to
	// use existing logic
	var path = uri.path + uri.delimiter + uri.query;

	if  (domain.indexOf("search.avg.com") > -1)
	{   // ads link back to google
		return true;
	}
	
	return false;
};
searchshield.AVGGoogleSearchEngine.prototype.includeLink = function(tag)
{
	var outHref = false;
	var findStr = "";

	// check for interstitials
	if (searchshield.DoesURLContain(tag.href, "google.com"))
	{
		// link back to self - DIV elem GrandParent class of res1 or res3 is Sponsored Link 
		var parentNode = tag.parentNode;
		if (parentNode)
		{
			var grandParentNode = tag.parentNode.parentNode;
			if (grandParentNode)
			{
				if ((grandParentNode.tagName == "DIV") && 
					((grandParentNode.className.toLowerCase() == "res1") ||
					(grandParentNode.className.toLowerCase() == "res3")))
				{
					var urlPos = -1;	

					// ads now need unescaping
					href = unescape(tag.href);

					if (urlPos == -1)
					{
						if (href.indexOf("/aclk?sa=") != -1)
						{	
				]]></content:encoded>
    </item>
  </channel>
</rss>

