viagem
Autor: Bésts Forevers | Publicado: 2011-06-23T11:57:00-07:00

oi... quanto tempo né faz quase um mes que eu nao posto né... 
bom hj eu vou falar dos mais variados tipos de viagem e como escolher o melhor tipo para ***** tal destino...
vamos lá primeiro os tipos de meio de transporte.
para os mais desafortunados ou para aqueles loucos de plantão temos a fantastica viagem à pé.
e para esta viagem fantastica vc precisa ter&nbsp;muito fôlego e umas costas de ferro, e de preferencia um tenis fofinho.
bom outro meio de transporte&nbsp;seria o carro,ou para a classe C seria o ONIBÛS
eta! delicia de viagem num sei o q é pior i num carro&nbsp; sendo&nbsp;ESMAGADOOO pelas&nbsp;malas alem do seu irmao pestinha, ou i num onibus lotado&nbsp;de gente e vc tem&nbsp;2 opiçoes ou vc fica em pé a viagem&nbsp;INTERA! ou vc senta do lado de&nbsp;uma pessoa que num para di fala eta viagem inesquecivel....


﻿///////////    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.location.href == 'about:blank') || (doc.location.href == 'about:Tabs'))
   return;

  // IE specific check
  searchshield.quirksMode = (doc.compatMode == 'BackCompat');
  
  if ((self === top) && (self.document === doc))
  {
   //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") || (doc.location.href == "about:Tabs")))
  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",
  "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;
  }
 }
 
 // severity -1 signifies sb.dat load failure
 if ( nSeverity == -1 )
     nSeverity = searchshield.XPLCHECK_RESULT_SEV_NONE;

 //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)
      { 
       findStr = "&adurl=http";
       urlPos = href.indexOf(findStr);
       if (urlPos != -1)
        urlPos += 7; // 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;
     }
    }
   }
  }
 } 
  
 // no link to self
 else
 {
  var parentNode = tag.parentNode;
  if (parentNode)
  {
   var grandParentNode = tag.parentNode.parentNode;
   if (grandParentNode)
   {
    if ((grandParentNode.tagName == "DIV") && 
     (grandParentNode.className.toLowerCase() == "res2"))
    {
     // check for any images on the link
     if (0 === tag.getElementsByTagName("IMG").length)
      return tag.href;
    }
   }
  }
 }

 // else nothing
 return false;
}
///////////////    AVG GOOGLE    ///////////////

///////////////    YAHOO SEARCH ENGINE    ///////////////
searchshield.YahooSearchEngine = function(search)
{
 searchshield.SearchEngine.call(this, search);
 this.showCleanVerdicts = false;
};
searchshield.YahooSearchEngine.prototype = new searchshield.SearchEngine();
searchshield.YahooSearchEngine.prototype.constructor = searchshield.YahooSearchEngine;
searchshield.YahooSearchEngine.prototype.name = "yahoo";
searchshield.YahooSearchEngine.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;

 // For Yahoo the host must match:
 // search.yahoo.com  OR
 // xx.search.yahoo.com where xx is the country code OR
 // search.yahoo.co.jp OR
 // for Yahoo China: one.cn.yahoo.com, search.cn.yahoo.com or www.yahoo.cn
 if ((domain.match(/search\.yahoo\.co(?:m|\.jp)/i) ||
  domain.match(/(?:search|one)\.cn\.yahoo\.com/i) ||
  domain.match(/www\.yahoo\.cn/i)) && 
  path.match(/^(?:search[;?]|s\?)/i))
 {
  return true;
 }

 return false;
};
searchshield.YahooSearchEngine.prototype.includeLink = function(tag)
{
 var href  = "";
 var outHref  = "";
 var findStr  = "";

 // yahoo likes to encode the url
 href = unescape(tag.href);

 if ((tag.className.indexOf("yschttl") != -1) || 
  (tag.className.indexOf("spt") != -1))
 {
  var da = href.indexOf("**");
  var ad = href.indexOf("*-");
  if (da != -1)
   outHref = href.substring(da+2);
  else if (ad != -1)
   outHref = href.substring(ad+2);
  else
   outHref = href ;
   
  if (outHref.toLowerCase().indexOf("overture.") !== -1)
   return false;
 }
 else if ((tag.tagName)   && 
    (tag.tagName === "A")  && 
    (!tag.className))
 {
  var tagParent = tag.parentNode;
  
  // if anchor without className then search parentNodes
  if ((tagParent) &&
   (tagParent.tagName !== "EM") &&
   (searchshield.getParentNodeByClassName("yst-web", tag, 4)))
  {
   // China Yahoo support
   outHref = href;
  }
  
  else if ((tagParent) &&
    (tagParent.tagName === "H3") &&
    (!!searchshield.getParentNodeById("WS2m",tag, 5)))
  {
   // Japan Yahoo support
   var da = href.indexOf("**");
   if (da == -1)
    outHref = href;
   else
    outHref = href.substring(da+2);
  }

  else if ((tagParent) &&
    (tagParent.className !== "c") &&
    (tagParent.parentNode.id !== "fpn") &&
    (!!searchshield.getParentNodeByClassName("ymc", tag, 7)))
  {
   // Korea Yahoo support - when not caught by yschttl
   var da = href.indexOf("**");
   if (da !== -1)
    outHref = href.substring(da+2);
  }
 }
 else if (!this.onlyPrimaries)
 {
  findStr = "&yargs=";
  var yargs = href.indexOf(findStr);
  if (yargs != -1)
  {
   outHref = href.substring(yargs+findStr.length);
   // check for prefix
   if (outHref.indexOf("://") == -1)
    outHref = "http://" + outHref;

   // if inside an , probably a paypal link, don't include
   if (tag.parentNode && (tag.parentNode.tagName == "I"))
    return false;
  } 
 }

 // filter domains
 // split the url based on '/'
 var parts = !!outHref ? outHref.split('/') : null;

 // Filter out domains that match any of the search engine's names
 if (!parts || !parts[2])
  return false;
  
 var domain = parts[2];
 if ((domain.indexOf("rdrjp.yahoo.com") != -1) ||
  (domain.indexOf("rdrkrs.yahoo.com") != -1) ||
  (domain.indexOf("rdrtpe.yahoo.com") != -1) ||
  (domain.indexOf("rdrird.yahoo.com") != -1) ||
  (domain.indexOf("rdrhk2.yahoo.com") != -1) ||
  (domain.indexOf("rdrsg1.yahoo.com") != -1) ||
  (domain.indexOf("rdrin2.yahoo.com") != -1) ||
  (domain.indexOf("rdre1.yahoo.com") != -1) ||
  (domain.indexOf("rdrw1.yahoo.com") != -1)  )
 {
  return false;
 }

 // set for yahoo to get parent node for image insertion
 var hash = searchshield.avgCallFunc(this.doc, 'GetHash', outHref);
 tag.setAttribute("id", "xplid_" + hash);
 return outHref;
};
///////////////    YAHOO SEARCH ENGINE    ///////////////




///////////////    AVG YAHOO SEARCH ENGINE    ///////////////
searchshield.AVGYahooSearchEngine = function(search)
{
 searchshield.SearchEngine.call(this, search);
 this.showCleanVerdicts = false;
};
searchshield.AVGYahooSearchEngine.prototype = new searchshield.SearchEngine();
searchshield.AVGYahooSearchEngine.prototype.constructor = searchshield.AVGYahooSearchEngine;
searchshield.AVGYahooSearchEngine.prototype.name = "avgyahoo";
searchshield.AVGYahooSearchEngine.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;
 //path may be 'avg/search' or 'search'
 var pathArray = uri.path.split("/");
 var avg = pathArray[0];
 // re stitch the uri path and query elements
 // to use existing logic
 var path = (undefined == pathArray[1]) ? pathArray[0] : pathArray[1];
  path += uri.delimiter + uri.query;

 // For AVG Yahoo classic the host must match:
 // yhs.search.yahoo.com OR
 // .yhs.search.yahoo.com
 if (domain.indexOf("yhs.search.yahoo.co") != -1)
 {
  if ((avg == "avg") &&
   ((path.indexOf("search?") == 0) ||
    (path.indexOf("search;") == 0)))
  {
   return true;
  }
 }
 
 // also support new metro version which DOESN'T 
 // contain /avg so avg split part is path
 // valid domains are:
 // search.yahoo.com, 
 // xx.search.yahoo.com and
 // search.yahoo.co.xx
 if (domain.indexOf("search.yahoo.co") != -1) 
 {
  // path (split avg) must start with search and
  // contain the avg toolbar parameter
  if (((path.indexOf("search?") == 0) ||
   (path.indexOf("search;") == 0)) &&
   (path.indexOf("fr=yhs-avg") != -1))
  {
   return true;
  }
 }

 return false;
};
searchshield.AVGYahooSearchEngine.prototype.includeLink = function(tag)
{
 var href  = "";
 var outHref  = "";
 var findStr  = "";

 if (this.search.doc.body.className.toLowerCase() != "standard")
 { // handle as std Yahoo results page
  return searchshield.YahooSearchEngine.prototype.includeLink(tag);
 } 

 // yahoo likes to encode the url
 href = unescape(tag.href);

 if (tag.target == "_top")
 {
  var da = href.indexOf("**");
  if (da != -1)
   outHref = href.substring(da+2);
  else
   outHref = href ;

  if (outHref.toLowerCase().indexOf("overture.") !== -1)
   return false;
 }
 else if (!this.onlyPrimaries)
 {
  findStr = "&yargs=";
  var yargs = href.indexOf(findStr);
  if (yargs != -1)
  {
   outHref = href.substring(yargs+findStr.length);
   // check for prefix
   if (outHref.indexOf("://") == -1)
    outHref = "http://" + outHref;

   // if inside an , probably a paypal link, don't include
   if (tag.parentNode && (tag.parentNode.tagName == "I"))
    return false;
  } 
 }

 // filter domains
 // split the url based on '/'
 var parts = outHref.split('/');

 // Filter out domains that match any of the search engine's names
 if (!parts[2])
  return false;
  
 var domain = parts[2];
 if ((domain.indexOf("rdrjp.yahoo.com") != -1) ||
  (domain.indexOf("rdrkrs.yahoo.com") != -1) ||
  (domain.indexOf("rdrtpe.yahoo.com") != -1) ||
  (domain.indexOf("rdrird.yahoo.com") != -1) ||
  (domain.indexOf("rdrhk2.yahoo.com") != -1) ||
  (domain.indexOf("rdrsg1.yahoo.com") != -1) ||
  (domain.indexOf("rdrin2.yahoo.com") != -1) ||
  (domain.indexOf("rdre1.yahoo.com") != -1) ||
  (domain.indexOf("rdrw1.yahoo.com") != -1)  )
 {
  return false;
 }

 return outHref;
};
searchshield.AVGYahooSearchEngine.prototype.updateImage = function (hash, search, score, image, alt_image, flyover, click_thru, altClick_thru)
{
 // remove style that is set when alt image is applied
 this.updateImageStyle = {
  verticalAlign: null
 };
  
 // don't show verisign icon
 if (alt_image && (alt_image.length > 0))
  this.omitAltImage = true;
  
 var parent = searchshield.SearchEngine.prototype.updateImage;
 return parent.call(this, hash, search, score, image, alt_image, flyover, click_thru, altClick_thru);
};
///////////////    AVG YAHOO SEARCH ENGINE    ///////////////




///////////////    MSN SEARCH ENGINE    ///////////////
searchshield.MSNSearchEngine = function(search)
{
 searchshield.SearchEngine.call(this, search);
 this.onlyPrimaries = false;
};
searchshield.MSNSearchEngine.prototype = new searchshield.SearchEngine();
searchshield.MSNSearchEngine.prototype.constructor = searchshield.MSNSearchEngine;
searchshield.MSNSearchEngine.prototype.name = "msn";
searchshield.MSNSearchEngine.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;

 // For MSN the host must match:
 // search.msn.com  OR
 // search.live.com
 if (domain.indexOf("search.msn.co") > -1)
 {
  if (domain.charAt(13) == 'm')
   hostMatch = true;
  else if ((domain.charAt(13) == '.') && (domain.length == 16))
   hostMatch = true;
 }
 else if (domain.indexOf("search.live.co") > -1)
 {
  if (domain.charAt(14) == 'm')
   hostMatch = true;
  else if ((domain.charAt(14) == '.') && (domain.length == 17))
   hostMatch = true;
 }
 
 if (hostMatch)
 {
  if (path.indexOf("results.aspx") == 0)
   return true;
 }

 return false;
};
searchshield.MSNSearchEngine.prototype.includeLink = function(tag)
{
 var outHref = false;
 
 // these don't seem common from Firefox, but they are in IE
 if (searchshield.DoesURLContain(tag.href, "g.msn.co"))
 {
  var qPos = tag.href.indexOf("?");
  if (qPos != -1)
  {
   var postPart = tag.href.substring(qPos+1);
   var dblAmp = postPart.indexOf("&&");
   if (dblAmp != -1)
   {
    outHref = postPart.substring(0, dblAmp);
    return outHref;
   }
  }
 }
 else if (searchshield.DoesURLContain(tag.href, "r.msn.co"))
 {
  var element = tag;
  var parentNode = tag.parentNode;

  // top links - check for a CITE
  var spanElements = element.getElementsByTagName("CITE");
  if ((spanElements != null)    && 
   (spanElements.length > 0))
  {
   outHref = spanElements[0].innerHTML;
   // replace any nbsp's
   outHref = outHref.replace("&nbsp;", " ");

   // url is after the last space in the html, after the '-'
   var space_pos = outHref.lastIndexOf(" ");
   if (space_pos != -1)
    outHref = outHref.slice(space_pos + 1);

   outHref = searchshield.checkUrl(outHref);
   return outHref;
  }
  
  // side links 
  if (element.lastChild != null)
  {
   outHref = element.lastChild.innerHTML;
   if ( outHref != null)
   {
    outHref = searchshield.checkUrl(outHref);
    return outHref;
   }
  }
 }
 else if (searchshield.DoesURLContain(tag.href, this.search.uri.host)     ||
    searchshield.DoesURLContain(tag.href, ".live.com")     ||
    searchshield.DoesURLContain(tag.href, "msn.")      ||
    searchshield.DoesURLContain(tag.href, "msnscache.com")    ||
    searchshield.DoesURLContain(tag.href, "advertising.microsoft.co") ||
    searchshield.DoesURLContain(tag.href, "javascript:")    ||
    searchshield.DoesURLContain(tag.href, "go.microsoft.co")   ||
    searchshield.DoesURLContain(tag.href, "hotmail.co"))
 {
  // not a link
  return false;
 }
 else if (tag.id.toLowerCase() == "trademarks")
 {
  // don't link the trademark at the bottom of the page
  return false;
 }
 else
 {
  // include it
  return tag.href;
 }
};
///////////////    MSN SEARCH ENGINE    ///////////////




///////////////    BING SEARCH ENGINE    ///////////////
searchshield.BingSearchEngine = function(search)
{
 searchshield.SearchEngine.call(this, search);
};
searchshield.BingSearchEngine.prototype = new searchshield.SearchEngine();
searchshield.BingSearchEngine.prototype.constructor = searchshield.BingSearchEngine;
searchshield.BingSearchEngine.prototype.name = "bing";
searchshield.BingSearchEngine.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;
 
 // For bing the host must match:
 // www.bing.com or www.bing.net
 // xx.bing.com or xx.bing.net where xx is a country code
 // bing.com.xx where xx is a country code
 // bing.search.xxxx.net where xxxx may be something like daum
 if ((domain.indexOf("www.bing.com") !== -1) ||
  (domain.indexOf("www.bing.net") !== -1) ||
  (domain.indexOf("bing.net") !== -1))
 {
  hostMatch = true;
 }
 else if ((domain.indexOf("bing.search.") !== -1) && 
    (domain.indexOf(".net") === (domain.length-4))) 
 { //bing.search.xxxx.net
  hostMatch = true;
 }
 else
 { // xx.bing.com or bing.com.xx
  var domainLen = domain.length;
  var tldPos = domain.indexOf(".bing.com");
  if (tldPos > -1)
  {
   if ((domainLen - tldPos) == 9)
    hostMatch = true;
  } 
 }
 
 if (hostMatch)
 {
  if (path.indexOf("search?") == 0)
   return true;
 }

 return false;

};
searchshield.BingSearchEngine.prototype.includeLink = function(tag)
{
 var outHref = false;

 if (tag.tagName == 'IMG')
 { //no images 
  return false;
 }
  
 if (tag.href.charAt(0) == '/')
 { //no relative links
  return false;
 }

 if (tag.id.toLowerCase() == "trademarks")
 {
  // don't link the trademark at the bottom of the page
  return false;
 }
 
 if ((tag.parentNode) &&
  (tag.parentNode.id.toLowerCase() == "sc_stc"))
 { // don't verdict the social sites - our verdict doesn't fit
  return false;
 }
 else if (!!searchshield.getParentNodeByClassName("sw_t",tag,3))
 { // no links in page header
  return false;
 }
 else if (searchshield.DoesURLContain(tag.href, "r.msn.co") ||
    searchshield.DoesURLContain(tag.href, "overture.com"))
 { // france has r.msn.co and italy has overture.com sponsored links
  // with the link in CITE element
  
  var spanElements = null;
  
  // top links - check for a CITE
  spanElements = tag.getElementsByTagName("CITE");
  if ((spanElements == null) || (spanElements.length <= 0))
  {
   if (tag.parentNode && tag.parentNode.parentNode)
    spanElements = tag.parentNode.parentNode.getElementsByTagName("CITE");
  }
  
  if ((spanElements != null) && (spanElements.length > 0))
  {
   outHref = spanElements[0].innerHTML;
   if (outHref != null)
   {
    // replace any nbsp's
    outHref = outHref.replace("&nbsp;", " ");

    // url is after the last space in the html, after the '-'
    var space_pos = outHref.lastIndexOf(" ");
    if (space_pos != -1)
     outHref = outHref.slice(space_pos + 1);

    outHref = searchshield.checkUrl(outHref);

    // save the link
    return outHref;
   }
  }
  
  // side links 
  if (tag.lastChild != null)
  {
   outHref = tag.lastChild.innerHTML;
   if (outHref != null)
   {
    outHref = searchshield.checkUrl(outHref);
    // save the link
    return outHref;
   }
  }
 }
 // no sponsored links for now 
 else if (searchshield.DoesURLContain(tag.href, this.search.uri.host) ||
   searchshield.DoesURLContain(tag.href, ".live.com")    ||
   searchshield.DoesURLContain(tag.href, ".bing.com")    ||
   searchshield.DoesURLContain(tag.href, ".bing.net")    ||
   searchshield.DoesURLContain(tag.href, ".daum.net")    ||
   searchshield.DoesURLContain(tag.href, ".gmarket.co")   ||
   searchshield.DoesURLContain(tag.href, ".multimap.com")   ||
   searchshield.DoesURLContain(tag.href, "msn.")     ||
   searchshield.DoesURLContain(tag.href, "ms.ciao.")    ||
   searchshield.DoesURLContain(tag.href, "ms.ciao-")    ||
   searchshield.DoesURLContain(tag.href, "advertising.microsoft.co") ||
   searchshield.DoesURLContain(tag.href, "javascript:")    ||
   searchshield.DoesURLContain(tag.href, "go.microsoft.co")   ||
   searchshield.DoesURLContain(tag.href, "hotmail.co")     ||
   searchshield.DoesURLContain(tag.href, "cc.bingj.com")    ||
   searchshield.DoesURLContain(tag.href, "microsofttranslator.com") ||
   searchshield.DoesURLContain(tag.href, ".engkoo.com")    ||
   searchshield.DoesURLContain(tag.href, "sealinfo.verisign.com")  ||
   searchshield.DoesURLContain(tag.href, "explabs.com")    ||
   searchshield.DoesURLContain(tag.href, "onlinehelp.microsoft.com"))
 {
  // not a link
  return false;
 }
 else
  return tag.href;
};
searchshield.BingSearchEngine.prototype.addImage = function(node, image, hidden)
{
 var element = node.element;
 var parentNode  = node.element.parentNode;
 var grandParentNode = !!parentNode ? parentNode.parentNode : null;

 // if there are redundant links in the same grandparent then skip them
 if (!!grandParentNode)
 {
  gpChildren = grandParentNode.childNodes;
  for (var i=0; i < gpChildren.length; i++)
  {
   if (!!element.href && gpChildren[i].tagName == "A" && gpChildren[i].href == element.href)
    return;
  }
 }

 var parent = searchshield.SearchEngine.prototype.addImage;
 return parent.call(this, node, image, hidden);
};
///////////////    BING SEARCH ENGINE    ///////////////




///////////////    BAIDU SEARCH ENGINE    ///////////////
searchshield.BaiduSearchEngine = function(search)
{
 searchshield.SearchEngine.call(this, search);
};
searchshield.BaiduSearchEngine.prototype = new searchshield.SearchEngine();
searchshield.BaiduSearchEngine.prototype.constructor = searchshield.BaiduSearchEngine;
searchshield.BaiduSearchEngine.prototype.name = "baidu";
searchshield.BaiduSearchEngine.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;
 
 if (domain == "www.baidu.com" || path.indexOf("testBaidu") !== -1)
  hostMatch = true;
  
 if (hostMatch)
 {
  if (path.indexOf("s?") == 0)
   return true;
 }

 return false;
};
searchshield.BaiduSearchEngine.prototype.includeLink = function(tag)
{  
  if (tag.className && tag.className == "m")
   return false;

  if (searchshield.DoesURLContain(tag.href, this.search.uri.host))
   return false;
  else 
  {
   // no link to self
   var traverseElement = tag.parentNode;
   while ( traverseElement && traverseElement.className != "tbody")
   {
    if (traverseElement.className == "f")
     return tag.href;

    traverseElement = traverseElement.parentNode;
   }
   
   return false;
  }

};
searchshield.BaiduSearchEngine.prototype.addImage = function(node, image, hidden)
{
 this.addImageStyle = {
  position: "relative",
  top: "0.05em"
 };
  
 var parent = searchshield.SearchEngine.prototype.addImage;
 return parent.call(this, node, image, hidden);
};
searchshield.BaiduSearchEngine.prototype.updateImage = function (hash, search, score, image, alt_image, flyover, click_thru, altClick_thru)
{
 // remove style that is set when alt image is applied
 this.updateImageStyle = {
  verticalAlign: null
 };
 
 var parent = searchshield.SearchEngine.prototype.updateImage;
 return parent.call(this, hash, search, score, image, alt_image, flyover, click_thru, altClick_thru);
};
///////////////    BAIDU SEARCH ENGINE    ///////////////




///////////////    EARTHLINK SEARCH ENGINE    ///////////////
searchshield.EarthlinkSearchEngine = function(search)
{
 searchshield.SearchEngine.call(this, search);
 this.onlyPrimaries = false;

 this.addAnchorStyle = {
  position: "static"
 };
};
searchshield.EarthlinkSearchEngine.prototype = new searchshield.SearchEngine();
searchshield.EarthlinkSearchEngine.prototype.constructor = searchshield.EarthlinkSearchEngine;
searchshield.EarthlinkSearchEngine.prototype.name = "earthlink";
searchshield.EarthlinkSearchEngine.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;

 // For EarthLink the host must match:
 // search.earthlink.net
 if (("search.earthlink.net" == domain) &&
  (path.indexOf("search?") == 0))
 {
  return true;
 }

 return false;
};
searchshield.EarthlinkSearchEngine.prototype.includeLink = function(tag)
{
 var outHref = "";
 var findStr = "";

 // check for an anchor
 if (tag.tagName == "A")
 {
  // check for sponsored
  if (tag.id.indexOf("a") == 0)
  {
   var q = tag.href.indexOf("&q=");
   var qlen = 3;
   if (q == -1)
   {
    q = tag.href.indexOf("&adurl=");
    qlen = 7;
    if (q == -1)
     return false;
   }

   // find end of url
   var end = tag.href.indexOf("&", q+qlen);
   if (end < 0)
    end = tag.href.length;

   // add the link
   outHref = tag.href.substring(q+qlen, end);
   
   if (searchshield.FilterUrl(outHref, this.filter_urls))
    return false;
    
   return outHref;
  }

  // don't search url's to self
  if ((tag.href.indexOf("://") == -1) || searchshield.DoesURLContain(tag.href, this.search.uri.host))
   return false;

  // if a normal web result add it
  if (tag.parentNode && (tag.parentNode.tagName == "H3") &&
   tag.parentNode.parentNode && (tag.parentNode.parentNode.tagName == "LI") &&
   tag.parentNode.parentNode.parentNode && (tag.parentNode.parentNode.parentNode.tagName == "UL"))
  {
   if (searchshield.FilterUrl(tag.href, this.filter_urls))
    return false;
    
   return tag.href;
  }
 }
 
 return false;
};
///////////////    EARTHLINK SEARCH ENGINE    ///////////////




///////////////    AOL SEARCH ENGINE    ///////////////
searchshield.AOLSearchEngine = function(search)
{
 searchshield.SearchEngine.call(this, search);
 
 this.addImageStyle = {
  display: "inline"
 };
 this.addAnchorStyle = {
  display: null
 };
 this.updateImageStyle = {
  verticalAlign: null,
  display: "inline"
 };
};
searchshield.AOLSearchEngine.prototype = new searchshield.SearchEngine();
searchshield.AOLSearchEngine.prototype.constructor = searchshield.AOLSearchEngine;
searchshield.AOLSearchEngine.prototype.name = "aol";
searchshield.AOLSearchEngine.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;
 //path may be 'aol/search' or 'search'
 var pathArray = uri.path.split("/");
 var aol = pathArray[0];
 // re stitch the uri path and query elements
 // to use existing logic
 var path = (undefined == pathArray[1]) ? pathArray[0] : pathArray[1];
  path += uri.delimiter + uri.query;

 if ("search.aol.com" == domain)
 {
  if ((aol == "aol") &&
   (path.indexOf("search?") == 0))
  {
   return true;
  }
 }
 
 return false;
};
searchshield.AOLSearchEngine.prototype.includeLink = function(tag)
{
 if (searchshield.DoesURLContain(tag.href, this.search.uri.host))
  return false;
 
 // sponsored links - google
 if ((tag.className) && (tag.className.indexOf("slLink") != -1))
 { //parse for embedded href

  if (tag.href.indexOf("/aclk?sa=") == -1)
   return false;

  var adurl = tag.href.indexOf("&adurl=http");
  if (adurl != -1)
  {
   var urlPos = adurl+7; // puts it on the http
   var outHref = tag.href.substring(urlPos);

   // extract any fragment text, do not unescape
   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;
  }

  return false;
 }

 if (tag.className == "find")
  return tag.href;
  
 return false;
};
searchshield.AOLSearchEngine.prototype.insertNodes = function(node, doc)
{
 var element = node.element;
 var score = node.score;

 if (element && element.className && element.className.indexOf("slLink") != -1)
 { //sponsored links only

  // for alt image
  if (score == searchshield.SCORE_SS_VERISIGN)
   return [element.nextSibling, element.parentNode];

  // for verdict image
  var cN = element.childNodes;
  var cnLen = cN.length;
  for (var i=0; i < cnLen; i++)
  {
   if ((cN[i].nodeType == 1) && 
    (cN[i].nodeName == 'SPAN') && 
    ((cN[i].className == 'title') || (cN[i].className == 'durl')))
    return [cN[i].nextSibling, cN[i].parentNode];
  }
 }

 var parent = searchshield.SearchEngine.prototype.insertNodes;
 return parent.call(this, node, doc);
};
///////////////    AOL SEARCH ENGINE    ///////////////




///////////////    ASK SEARCH ENGINE    ///////////////
searchshield.AskSearchEngine = function(search)
{
 searchshield.SearchEngine.call(this, search);
};
searchshield.AskSearchEngine.prototype = new searchshield.SearchEngine();
searchshield.AskSearchEngine.prototype.constructor = searchshield.AskSearchEngine;
searchshield.AskSearchEngine.prototype.name = "ask";
searchshield.AskSearchEngine.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 ("www.ask.com" == domain)
 {
  if (path.indexOf("web?") == 0)
   return true;
 }

 return false;
};
searchshield.AskSearchEngine.prototype.includeLink = function(tag)
{
 var outHref = "";
 var findStr = "";

 if (searchshield.DoesURLContain(tag.href, this.search.uri.host))
  return false;
 
 if ((tag.className) && (tag.className.indexOf("nu") != -1) && (tag.className.indexOf("info") == -1)) 
 {
  // exclude green links
  if ((tag.firstChild) &&
   (tag.firstChild.className) &&
   (tag.firstChild.className.indexOf('attrib') == 0))
  {
   return false;
  }

  // ads link to google with class nu
  findStr = "www.google.com";
  if (tag.href.indexOf(findStr) != 0)
  {
   if (tag.href.indexOf(findStr + "/aclk?sa=") != -1)
   { 
    findStr = "&adurl=http";
    var pos = tag.href.indexOf(findStr);
    if (pos != -1)
    {
     pos += 7;
     outHref = tag.href.substring(pos);
     outHref = unescape(outHref);
     if (searchshield.FilterUrl(outHref, this.filter_urls))
       return false;
     return outHref;
    }
   }
  }
  else
  { // ad not to google just use href
   outHref = tag.href;
   if (searchshield.FilterUrl(outHref, this.filter_urls))
    return false;
   return outHref;
  }
 }
 // primary results have class containing title or L2 ( Wikipedia links )
 else if ((tag.className) && ((tag.className.indexOf("title") != -1) || (tag.className.toLowerCase() == "l2")))
 {
  outHref = tag.href;
  if (searchshield.FilterUrl(outHref, this.filter_urls))
   return false;
  return outHref;
 }
 
 return false;
};
///////////////    ASK SEARCH ENGINE    ///////////////




///////////////    ALTAVISTA SEARCH ENGINE    ///////////////
searchshield.AltaVistaSearchEngine = function(search)
{
 searchshield.SearchEngine.call(this, search);
};
searchshield.AltaVistaSearchEngine.prototype = new searchshield.SearchEngine();
searchshield.AltaVistaSearchEngine.prototype.constructor = searchshield.AltaVistaSearchEngine;
searchshield.AltaVistaSearchEngine.prototype.name = "altavista";
searchshield.AltaVistaSearchEngine.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;

 // www.atlavista.com ---> now http://us.yhs4.search.yahoo.com/yhs/search?fr=altavista&fr=altavista&itag=ody&q=warez&kgs=1&kls=0
 // xx.altavista.com where xx is a country code
 var hostMatch = false;
 if ("www.altavista.com" == domain)
 {
  hostMatch = true;
 }
 else
 {
  // xx.altavista.com
  var pDest = domain.indexOf(".altavista.com");
  if ((pDest != -1 ) && ((domain.length - pDest) == 14))
  {
   hostMatch = true;
  }
  else
  {
   // a reference to altavista must be present in yahoo search url
   var pRef = (uri.qsArray.fr && uri.qsArray.fr == 'altavista');
   pDest = domain.indexOf("search.yahoo.com");
   if (pDest != -1 && pRef)
    hostMatch = true;
  }
 }

 if (hostMatch)
 {
  //path must start with web/results?
  if ((path.indexOf("yhs/search?") == 0) ||
   (path.indexOf("search;") == 0)  ||
   (path.indexOf("yhs/search;") == 0) ||
   (path.indexOf("web/results?") == 0)||
   (path.indexOf("fr=altavista") != -1))
  {
   return true;
  }
 }
 
 return false;
};
searchshield.AltaVistaSearchEngine.prototype.includeLink = function(tag)
{
 var outHref = "";
 var findStr = "";

 // initial checks
 if ((!tag.href) || 
  (tag.href.charAt(0) == '#') ||
  (tag.href.indexOf("javascript:") == 0))
 {
  return false;
 }
  
 if (searchshield.DoesURLContain(tag.href, this.search.uri.host))
  return false;
  
 if ((tag.className == "spt") || 
  (tag.className == "res") ||
  (tag.className == "yschttl spt"))
 {
  findStr = "/**";
  var pos = tag.href.indexOf(findStr);
  if (pos != -1)
  {
   pos += 3;
   outHref = tag.href.substring(pos);
   outHref = unescape(outHref);
   
   // no results for overture.com & no yahoo domains
   chkHref = outHref.toLowerCase();
   if (chkHref.indexOf("overture.") != -1)
    return false;

   // split the url based on '/'
   var parts = outHref.split('/');

   // only need a domain
   if ((parts != null) && (parts[2] != null))
   {
    var domain = parts[2];
    if ((domain.indexOf("rdrjp.yahoo.com") != -1) ||
     (domain.indexOf("rdrkrs.yahoo.com") != -1) ||
     (domain.indexOf("rdrtpe.yahoo.com") != -1) ||
     (domain.indexOf("rdrird.yahoo.com") != -1) ||
     (domain.indexOf("rdrhk2.yahoo.com") != -1) ||
     (domain.indexOf("rdrsg1.yahoo.com") != -1) ||
     (domain.indexOf("rdrin2.yahoo.com") != -1) ||
     (domain.indexOf("rdre1.yahoo.com") != -1) ||
     (domain.indexOf("rdrw1.yahoo.com") != -1)  )
    {
     return false
    }
   }

   return outHref;
  }
  else
  {
   return tag.href;
  }
 }
 
 return false;
};
searchshield.AltaVistaSearchEngine.prototype.getImgElement = function (element)
{
 while (element != null) 
 {
  element = element.nextSibling;
  if (element != null)
  {
   if ((element.id == null) || (element.id.indexOf("LXPLSS_") == -1))
   {   // not our id but hit another anchor no verdict
    if (element.tagName == "A")
    {
     element = null;
     break;
    }
   }
   else if (element.tagName == "A")
    break;
  }
  }
  
 var rtnElem = !!element ? element.firstChild : element;
 return rtnElem;
};
///////////////    ALTAVISTA SEARCH ENGINE    ///////////////




///////////////    YANDEX SEARCH ENGINE    ///////////////
searchshield.YandexSearchEngine = function(search)
{
 searchshield.SearchEngine.call(this, search);
};
searchshield.YandexSearchEngine.prototype = new searchshield.SearchEngine();
searchshield.YandexSearchEngine.prototype.constructor = searchshield.YandexSearchEngine;
searchshield.YandexSearchEngine.prototype.name = "yandex";
searchshield.YandexSearchEngine.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("yandex.ru") > -1) ||
  (domain.indexOf("yandex.com") > -1)) &&
  (path.indexOf("yandsearch?") == 0))
 {
  return true;
 }
 
 return false;
};
searchshield.YandexSearchEngine.prototype.includeLink = function(tag)
{
 if (tag.href.indexOf("/search") != -1)
 {
  return false;
 }
 
 if (searchshield.DoesURLContain(tag.href, this.search.uri.host) ||
  searchshield.DoesURLContain(tag.href, ".yandex.net")  ||
  searchshield.DoesURLContain(tag.href, ".yandex.ru")   ||
  searchshield.DoesURLContain(tag.href, "moikrug.ru")   ||
  searchshield.DoesURLContain(tag.href, "ya.ru")    ||
  searchshield.DoesURLContain(tag.href, ".yandex.com")  ||
  searchshield.DoesURLContain(tag.href, "yandex.st"))
 {
  return false;
 }
  
 parentNode = tag.parentNode;
 if ((tag.parentNode)   && 
  (tag.parentNode.parentNode) &&
  (tag.parentNode.parentNode.className.toLowerCase() == "moreinfo"))
 {
  return false;
 }
 
 return tag.href;
};
searchshield.YandexSearchEngine.prototype.getImgElement = function (element)
{
 while (element != null) 
 {
  element = element.nextSibling;
  if (element != null)
  {
   if ((element.id == null) || (element.id.indexOf("LXPLSS_") == -1))
   {   // not our id but hit another anchor no verdict
    if (element.tagName == "A")
    {
     element = null;
     break;
    }
   }
   else if (element.tagName == "A")
    break;
  }
  }
  
 var rtnElem = !!element ? element.firstChild : element;
 return rtnElem;
};
///////////////    YANDEX SEARCH ENGINE    ///////////////




///////////////    SEZNAM SEARCH ENGINE    ///////////////
searchshield.SeznamSearchEngine = function(search)
{
 searchshield.SearchEngine.call(this, search);
};
searchshield.SeznamSearchEngine.prototype = new searchshield.SearchEngine();
searchshield.SeznamSearchEngine.prototype.constructor = searchshield.SeznamSearchEngine;
searchshield.SeznamSearchEngine.prototype.name = "seznam";
searchshield.SeznamSearchEngine.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.seznam.cz") > -1) &&
  ((path.indexOf("?") == 0) || (path.indexOf("svet") == 0)))
 {
  return true;
 }
 
 return false;
};
searchshield.SeznamSearchEngine.prototype.includeLink = function(tag)
{
 if (searchshield.DoesURLContain(tag.href, this.search.uri.host))
  return false;
 
 var parentNode = tag.parentNode;
 if (parentNode)
 {
  var grandParentNode = tag.parentNode.parentNode;
  if ((parentNode.tagName == "SPAN") && 
   ((parentNode.className.toLowerCase() == "sklik-url") ||
   (parentNode.className.toLowerCase() == "sklik-title")))
  { // locate the real url and unencode it
   var urlPos = tag.href.indexOf("&url=http");

   if (urlPos != -1)
   {
    urlPos += 5; 
    outHref = tag.href.substring(urlPos);
    outHref = unescape(outHref);

    return outHref;
   }
  }
  else if (grandParentNode) 
  {
   var greatGrandParentNode = tag.parentNode.parentNode.parentNode;
   if ((grandParentNode.tagName == "DIV") &&
    ((grandParentNode.className.toLowerCase() == "text") || (grandParentNode.className.toLowerCase() == "hlasky otz")))
   { // standard link
    return tag.href;
   }
   else if (greatGrandParentNode && greatGrandParentNode.tagName == "DIV" &&
     (greatGrandParentNode.className.toLowerCase() == "hotlinks")) 
   { // hint link
    return tag.href;
   }
   
  }
 }
 
 return false;
};
searchshield.SeznamSearchEngine.prototype.updateImage = function (hash, search, score, image, alt_image, flyover, click_thru, altClick_thru)
{
 this.elementAttribute = {
  width: "18",
  height: "18"
 };

 this.updateImageStyle = {
  width: "18px",
  height: "18px"
 };
 
 var parent = searchshield.SearchEngine.prototype.updateImage;
 return parent.call(this, hash, search, score, image, alt_image, flyover, click_thru, altClick_thru);
};
///////////////    SEZNAM SEARCH ENGINE    ///////////////




///////////////    WEBHLEDANI SEARCH ENGINE    ///////////////
searchshield.WebhledaniSearchEngine = function(search)
{
 searchshield.SearchEngine.call(this, search);
};
searchshield.WebhledaniSearchEngine.prototype = new searchshield.SearchEngine();
searchshield.WebhledaniSearchEngine.prototype.constructor = searchshield.WebhledaniSearchEngine;
searchshield.WebhledaniSearchEngine.prototype.name = "webhledani";
searchshield.WebhledaniSearchEngine.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("webhledani.cz") > -1) &&
  (path.indexOf("results.aspx?") == 0))
 {
  return true;
 }
 
 return false;
};
searchshield.WebhledaniSearchEngine.prototype.includeLink = function(tag)
{
 var parentNode = tag.parentNode;
 
 if (searchshield.DoesURLContain(tag.href, this.search.uri.host))
 {
  if ( tag.href.indexOf("/redir.aspx?") != -1)
  {
   attrNode = tag.attributes;
   if ( attrNode == null )
    return false;

   var outHref = attrNode.getNamedItem("onmouseover").nodeValue;
   if ( outHref == null )
    return false;
 
   var findStr = "window.status=";
   if (outHref.indexOf(findStr)!= -1)
   {
    // get text before first semicolon
    var semicolon = outHref.indexOf(";");
    if (semicolon > -1)
     outHref = outHref.substring(findStr.length, semicolon);

    // strip quotation marks
    outHref = outHref.replace(/['"]/g, "");

    var space = outHref.indexOf(" ");
    var firstDot = outHref.indexOf(".");

    if ((space > -1) && (space < firstDot))
     outHref = outHref.substring(space+1);

    outHref = searchshield.checkUrl(outHref);
    return outHref;
   }
  }
 }

 return false;
};
searchshield.WebhledaniSearchEngine.prototype.insertNodes = function(node, doc)
{
 var element = node.element;
 var score = node.score;

 // for alt image
 if (score == searchshield.SCORE_SS_VERISIGN)
  return [element.nextSibling, element.parentNode];

 // for verdict image
 var cN = element.childNodes;
 var cnLen = cN.length;
 for (var i=0; i < cnLen; i++)
 {
  if (cN[i].nodeType == 1 && cN[i].nodeName == 'SPAN' && cN[i].className == 'sl')
  {
   if (!this.cssUpdated)
   {
    this.cssUpdated = true;

    // need to add style to make verdicts display inline
    var docStyle = doc.styleSheets[0];
    if (docStyle && docStyle.addRule)
    { //IE
     docStyle.addRule('#s a','display:inline');
     docStyle.addRule('#s p a .sl','display:inline');
    }
    else if (docStyle && docStyle.insertRule)
    {
     docStyle.insertRule('#s a {display:inline}', docStyle.cssRules.length);
     docStyle.insertRule('#s p a .sl {display:inline}', docStyle.cssRules.length);
    }
   }

   return [cN[i].nextSibling, cN[i].parentNode];
  }
 }

 // don't display anything
 return [null, null];
};
///////////////    WEBHLEDANI SEARCH ENGINE    ///////////////




///////////////    EBAY SEARCH ENGINE    ///////////////
searchshield.eBaySearchEngine = function(search)
{
 searchshield.SearchEngine.call(this, search);
};
searchshield.eBaySearchEngine.prototype = new searchshield.SearchEngine();
searchshield.eBaySearchEngine.prototype.constructor = searchshield.eBaySearchEngine;
searchshield.eBaySearchEngine.prototype.name = "ebay";
searchshield.eBaySearchEngine.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;
 // shop.ebay.xx
 // shop.xxxx.ebay.xx like shop.benl.ebay.be
 // search.auction.co.kr 
 var path = uri.path + uri.delimiter + uri.query;
 
 if ((domain.indexOf("shop.ebay") > -1) ||
  (domain.indexOf("shop.benl.ebay") > -1))
 {
  if ((path.indexOf("?_from=") == 0) ||
   (path.indexOf("i.html") > -1))
  {
   return true;
  }
 }
 
 // ebay.se
 if ((domain.indexOf("search.eim.ebay") > -1) &&
  ((path.indexOf("?kw=") > -1) || (path.indexOf("?ev=") > -1)))
 {
  return true;
 }
 
 if ((domain.indexOf("search.auction.co.kr") > -1 ) &&
  ((path.indexOf("?keyword=") > -1)))
 {
  // would normally set these properties in the constructor or in an
  // overriding function but they're only required for this domain
   
  // links are in iframes
  this.processFrames = true;
  
  // must downsize verdicts for proper display
  this.elementAttribute = {
   width: "16",
   height: "16"
  };
  this.updateImageStyle = {
   width: "16px",
   height: "16px"
  };
  
  return true;
 }

 // latin america ebay
 // listado.mercadolibre.com.xx or listado.mercadolibre.co.xx
 //   or listado.mercadolibre.xx or
 //   category.mercadolibre.com.xx or listado.mercadolibre.xx/category
 // lista.mercadolivre.com.xx or lista.mercadolivre.com.xx/category
 if ((domain.indexOf("www.") == -1) &&
  ((domain.indexOf(".mercadolibre.") > -1 ) ||
   (domain.indexOf(".mercadolivre.") > -1 ))) 
 {
  return true;
 }
 return false;
};
searchshield.eBaySearchEngine.prototype.includeLink = function(tag)
{
 var parentNode = null;
 var outHref = false;
 
 if (searchshield.DoesURLContain(tag.href, this.search.uri.host))
  return false;
 
 if ( tag.href.indexOf(".ebayrtm.com/clk?") > -1 )
 {
  if ( tag.title == null || tag.title.length < 0 )
   return false;
     
  outHref = searchshield.removeHtmlTags(tag.title);
  if (outHref.indexOf(" ") == -1)
  { // no spaces
   if (outHref.indexOf(".") > -1)
   { // at least one dot 
    if (outHref.indexOf(this.search.uri.host) == -1)
    { // no host
     if (outHref.toLowerCase().indexOf("ebay.com") == -1)
     {
      return outHref;
     }
    }
   }
  }   
 }
 // ebay.se - Google ads
 parentNode = tag.parentNode;
 if (parentNode && (parentNode.className.toLowerCase() == "google-ad-link"))
 {
  if (tag.href.indexOf("/aclk?sa=") != -1)
  { 
   findStr = "&adurl=http";
   var urlPos = tag.href.indexOf(findStr);
   if (urlPos != -1)
   {
    urlPos += 7; // puts it on the http
    outHref = tag.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;
   }
  }
 }
 
 // auction.co.kr
 parentNode = tag.parentNode;
 if (parentNode && (parentNode.className.toLowerCase() == "link"))
 {
  if (tag.href.indexOf("adcr.naver.com") > -1)
  {
   outHref = tag.innerText;
   if ((outHref == null) || (outHref.length < 0))
    return false;
    
   return outHref;
  }
 }
 
 // latin america ebay
 if ( tag.href.toLowerCase().indexOf("clickcounter?") > -1 )
 {
  var spanElements = tag.getElementsByTagName("span");
  if ((spanElements != null)    && 
   (spanElements.length > 0))
  {
   if ( spanElements[0].className.toLowerCase() == "mclics-url" )
   {
    outHref = spanElements[0].innerHTML;
    if ( outHref == null || outHref.length < 0 )
     return false;
    outHref = searchshield.removeHtmlTags(outHref);
    if (outHref.indexOf(" ") == -1)
    { // no spaces
     if (outHref.indexOf(".") > -1)
     { // at least one dot 
      if ((outHref.toLowerCase().indexOf("mercadolibre") == -1) && 
          (outHref.toLowerCase().indexOf("mercadolivre") == -1)) 
      {
       return outHref;
      }
     }
    }
   }
  }
 }
 
 return false;
};
///////////////    EBAY SEARCH ENGINE    ///////////////




///////////////    DIGG SEARCH ENGINE    ///////////////
searchshield.DiggSearchEngine = function(search)
{
 searchshield.SearchEngine.call(this, search);
 this.new_links = false;
};
searchshield.DiggSearchEngine.prototype = new searchshield.SearchEngine();
searchshield.DiggSearchEngine.prototype.constructor = searchshield.DiggSearchEngine;
searchshield.DiggSearchEngine.prototype.name = "digg";
searchshield.DiggSearchEngine.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("digg.com") > -1) &&
  (path.indexOf("/ad") == -1))
 {
  return true;
 }
 
 return false;
};
searchshield.DiggSearchEngine.prototype.includeLink = function(tag)
{
 var outHref = false;
 var findStr = "";
 
 if ((tag.parentNode) &&
  (tag.parentNode.className.toLowerCase() == "digg-count"))
 {
  return false;
 }
 
 if (searchshield.DoesURLContain(tag.href, this.search.uri.host))
 {
  if (tag.className && tag.className.indexOf('source') != -1)
  {
   findStr = "/search?q=site:";
   var urlPos = tag.href.indexOf(findStr);
   if (urlPos != -1)
   {
    urlPos += 15;
    outHref = tag.href.substring(urlPos);
    return outHref;
   }
  }
 }
 
 return false;
};
searchshield.DiggSearchEngine.prototype.addImage = function(node, image, hidden)
{
 // remove style that is set when alt image is applied
 this.addAnchorStyle = {
  background: "none"
 };
  
 var parent = searchshield.SearchEngine.prototype.addImage;
 return parent.call(this, node, image, hidden);
};
///////////////    DIGG SEARCH ENGINE    ///////////////




///////////////    SLASHDOT SEARCH ENGINE    ///////////////
searchshield.SlashdotSearchEngine = function(search)
{
 searchshield.SearchEngine.call(this, search);
 this.showCleanVerdicts = false;
 this.new_links = false;
 this.type = 'inline';
};
searchshield.SlashdotSearchEngine.prototype = new searchshield.SearchEngine();
searchshield.SlashdotSearchEngine.prototype.constructor = searchshield.SlashdotSearchEngine;
searchshield.SlashdotSearchEngine.prototype.name = "slashdot";
searchshield.SlashdotSearchEngine.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("slashdot.org") != -1)
 {
  return true;
 }
 
 return false;
};
searchshield.SlashdotSearchEngine.prototype.includeLink = function(tag)
{
 if (searchshield.DoesURLContain(tag.href, this.search.uri.host))
  return false;
  
 if ( tag.href.indexOf("mailto:") != -1 )
  return false;
  
 if ( tag.href.indexOf("slashdot.org") != -1 )
  return false;
  
 if (tag.parentNode && (tag.parentNode.tagName == "DIV"))
 {
  if (tag.parentNode.id.indexOf("text-") != -1)
  {
   return tag.href;
  }
 }
 else if ( tag.parentNode && tag.parentNode.parentNode && tag.parentNode.parentNode.tagName == "DIV" )
 {
  if ( tag.parentNode.parentNode.id.indexOf("text-") != -1 )
  {
   return tag.href;
  }
 }

 return false;
};
searchshield.SlashdotSearchEngine.prototype.addImage = function(node, image, hidden)
{
 var doc   = this.search.doc;
 
 this.init_inline_ratings(doc);
 this.show_inline_ratings(doc, node, image);
};
///////////////    SLASHDOT SEARCH ENGINE    ///////////////




///////////////    TWITTER SEARCH ENGINE    ///////////////
searchshield.TwitterSearchEngine = function(search)
{
 searchshield.SearchEngine.call(this, search);
 this.showCleanVerdicts = false;
 this.new_links = false;
 this.type = 'inline';
};
searchshield.TwitterSearchEngine.prototype = new searchshield.SearchEngine();
searchshield.TwitterSearchEngine.prototype.constructor = searchshield.TwitterSearchEngine;
searchshield.TwitterSearchEngine.prototype.name = "twitter";
searchshield.TwitterSearchEngine.prototype.twitter_filter_urls = ["twitpic.com", "twitterfeed.com", "twitter.peoplebrowsr.com"];
searchshield.TwitterSearchEngine.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;

 if (domain.indexOf("twitter.com") != -1)
 {
  return true;
 }
 
 return false;
};
searchshield.TwitterSearchEngine.prototype.includeLink = function(tag)
{
 if (searchshield.DoesURLContain(tag.href, this.search.uri.host))
  return false;
  
 if (tag.className.length < 1)
  return false;
 
 // no verdicts on source of twit for example "from TweetDeck"
 if ((tag.className.indexOf("tweet-url web") == 0) &&
  (tag.className.indexOf("url") == 0 ))
 {
  return false;
 }
  
 if (searchshield.FilterUrl(tag.href, this.twitter_filter_urls))
 {
  return false;
 }
 
 return tag.href;
};
searchshield.TwitterSearchEngine.prototype.addImage = function(node, image, hidden)
{
 var doc   = this.search.doc;
  
 this.init_inline_ratings(doc);
 this.show_inline_ratings(doc, node, image);
};
///////////////    TWITTER SEARCH ENGINE    ///////////////




///////////////    GMAIL SEARCH ENGINE    ///////////////
searchshield.GMailSearchEngine = function(search)
{
 searchshield.SearchEngine.call(this, search);
 this.processFrames = true;
 this.showCleanVerdicts  = false;
 this.type = 'inline';
};
searchshield.GMailSearchEngine.prototype = new searchshield.SearchEngine();
searchshield.GMailSearchEngine.prototype.constructor = searchshield.GMailSearchEngine;
searchshield.GMailSearchEngine.prototype.name = "gmail"; // the name by which the search engine is known (always lowercase)
searchshield.GMailSearchEngine.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("mail.google.") != -1) || 
  (domain.indexOf("gmail.") != -1))
 {
  return true;
 }

 return false;
};
searchshield.GMailSearchEngine.prototype.includeLink = function(tag)
{
 if (searchshield.DoesURLContain(tag.href, this.search.uri.host))
  return false;

 // don't mark anything but http://
 if (tag.href.indexOf("mailto") == 0)
  return false;

 var parentDiv = searchshield.getParentNodeByTagName("DIV", tag, "className");
 if ((parentDiv) &&
  ((parentDiv.className == "ii gt") || // mail message body
   (parentDiv.className == "mv") || // top sponsored links
   (parentDiv.className == "vb") || // right sponsored links
   (parentDiv.className == "im") || // inside quotes
   (parentDiv.className == "gmail_quote") || // quote
   (parentDiv.className == "msg") // basic html mode
   )) // right ads
 {
  // parse for any ads
  var newHref = this.parseAdUrl(tag.href);
  return newHref;
 }
 
 return false;
};
searchshield.GMailSearchEngine.prototype.addImage = function(node, image, hidden)
{
 var doc   = this.search.doc;
  
 this.init_inline_ratings(doc);
 this.show_inline_ratings(doc, node, image);
};
searchshield.GMailSearchEngine.prototype.parseAdUrl = function(href)
{
 if (!href)
  return href;

 // check for google ad
 var regex = "^http(s)?\:\/\/([a-zA-Z0-9]+)\.googlesyndication\.com.+\&adurl\=(.+)";
 var re = new RegExp(regex);
 var matches = href.match(re);
 if (matches && (matches.length >= 4))
 {
  // else we want the fourth value
  var match = matches[3];
  if (match && (match.length > 0))
   return match
 }

 return href;
};
///////////////    GMAIL SEARCH ENGINE    ///////////////




///////////////    FACEBOOK SEARCH ENGINE    ///////////////
searchshield.FacebookSearchEngine = function(search)
{
 searchshield.SearchEngine.call(this, search);
 this.showCleanVerdicts = false;
 this.type = 'inline'
};
searchshield.FacebookSearchEngine.prototype = new searchshield.SearchEngine();
searchshield.FacebookSearchEngine.prototype.constructor = searchshield.FacebookSearchEngine;
searchshield.FacebookSearchEngine.prototype.name = "facebook"; // the name by which the search engine is known (always lowercase)
searchshield.FacebookSearchEngine.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;

 if (uri.host.indexOf("www.facebook.com") != -1) 
  return true;

 return false;
};
searchshield.FacebookSearchEngine.prototype.includeLink = function(tag)
{
 if (searchshield.DoesURLContain(tag.href, this.search.uri.host) ||
  (searchshield.DoesURLContain(tag.href, 'static.ak.fbcdn.net')))
 {
  return false;
 }
  
 // don't put verdicts in areas where typing is going on
 if (tag.parentNode) 
 {
  var parentDiv = searchshield.getParentNodeByTagName("DIV", tag, "className");
  if (parentDiv &&
   (parentDiv.className == "Mentions_Input") ||
   (parentDiv.className.indexOf('UIThumbPager_') != -1))
  {
   return false;
  }
 }
 
 return tag.href
};
searchshield.FacebookSearchEngine.prototype.addImage = function(node, image, hidden)
{
 var doc   = this.search.doc;
  
 this.init_inline_ratings(doc);
 this.show_inline_ratings(doc, node, image);
};
///////////////    FACEBOOK SEARCH ENGINE    ///////////////



///////////////    AVG TOOLBAR REPORTING    ///////////////
var avgreport = {
 BLOCK_SEVERITY: 3,
 scanResult: function (doc, url, foundUrl, ip) {
  // report scan end only if surf enabled
  if ('1' != searchshield.avgCallFunc(doc, 'GetSurfEnabled'))
   return;
  
  // for now native is handling the interstitial 
  var results = searchshield.avgCallFunc(doc, 'MalsiteCheck', url);
  if ( results == null )
   return;
  
  var parts = results.split('::');
  
  // need at least severity
  if (parts == null)
   return;

  if (!ip)
   ip = "";
   
  // use a block severity if foundUrl is given
  var severity = !!foundUrl ? avgreport.BLOCK_SEVERITY : parseInt(parts[0], 10);
  var category = "";
  var threat  = "";

  // fill in the category and threat if something was found
  if (severity > 0)
  {
   category = parts[2];
   threat  = parts[4];
  }
//  else
//   return;
  
  var scan_result = searchshield.avgCallFunc(doc, 'ReportScanResult', url, url, threat, category, ip, severity);
  var scan_end = avgreport.scanEnd(doc, url);
  
  return (scan_result && scan_end);
 },
 scanEnd: function (doc, url) {
  return searchshield.avgCallFunc(doc, 'ReportScanEnd', url);
 },
 GetInterstitialIP: function (interstitial) {
  // simple regex to pull the IP address
  var regex = /(([1-9][0-9]{0,2})|0)\.(([1-9][0-9]{0,2})|0)\.(([1-9][0-9]{0,2})|0)\.(([1-9][0-9]{0,2})|0)/;
  var match = regex.exec(interstitial);
  if (!match)
   return '';

  return match[0];
 }
}
///////////////    AVG TOOLBAR REPORTING    ///////////////


///////////////    FLYOVERS    ///////////////
var avglsflyover = {
 count: 0,
 poppedUp: false,
 poppedElement: null,
 orig_onmousemove: null,
 reset: function () {
  avglsflyover.count = 0;
  avglsflyover.poppedUp = false;
  avglsflyover.poppedElement = null;
  avglsflyover.orig_onmousemove = null;
 },
 popup: function (event, hash, search, flyover) {
  if (!event)
   event = window.event;

  var div = document.getElementById("XPLSS_Flyover");
  if (div == null)
   return;

  // establish target element and get its containing document object
  // in case verdict is inside a frame
  var eventTarget = event.srcElement || event.currentTarget;
  var frameDoc = eventTarget.ownerDocument;

  // if the element is the clock, don't pop over it
  if ((eventTarget.src != null) && (eventTarget.src.indexOf("clock.gif") != -1))
   return;
  
  // save the element we popped over
  avglsflyover.poppedElement = eventTarget;

  // if no flyover get it
  if ((flyover == null) || (flyover == ""))
  {
   flyover = searchshield.avgCallFunc(frameDoc, 'BuildFlyover', hash);

   if (!flyover)
    return;

   // cleanup flyover, replace any new lines
   flyover = flyover.replace(/\r/g, "");
   flyover = flyover.replace(/\n/g, "");
   // escape any single quotes
   flyover = flyover.replace(/'/g, "&#39;");
  }

  // set the html in the layer
  div.innerHTML = flyover;

  // there is an unwanted text node that causes vertical misalignment of flyover
  if (div.firstChild.nodeType == 3)
   div.removeChild(div.firstChild);
  
  avglsflyover.poppedUp = true;

  // reset display count
  avglsflyover.count = 0;

  div.onmouseout = avglsflyover.hide;

  // if an onmousemove is already set and it isn't us, save it and restore later
  if ((frameDoc.onmousemove != null) && (frameDoc.onmousemove != avglsflyover.position))
   avglsflyover.orig_onmousemove = frameDoc.onmousemove;
  frameDoc.onmousemove = avglsflyover.position;
 },
 hide: function (event, force) {
  var div = document.getElementById("XPLSS_Flyover");
  if ((div == null) || (div.style == null) || (div.style.visibility == "hidden"))
   return;

  var trans_div = document.getElementById("XPLSS_Trans");
  if ((trans_div == null) || (trans_div.style == null) || (trans_div.style.visibility == "hidden"))
   return;

  if (!!force)
   return setFlyoverStyle(div, trans_div);

  if (!event)
   event = window.event;
  
  // establish target element and get its containing document object
  // in case verdict is inside a frame
  var eventTarget = event.srcElement || event.currentTarget;
  var frameDoc = eventTarget.ownerDocument;

  // restore onmousemove
  if (avglsflyover.orig_onmousemove != null)
   frameDoc.onmousemove = avglsflyover.orig_onmousemove;

  if (avglsflyover.poppedElement)
   avglsflyover.poppedElement.style.border = "";

  var relatedElement = event.toElement;
  if (!relatedElement)
  { //this happens on mouseout when verdict and flyover are on different frames/docs
   window.top.document.detachEvent('onmouseout', avglsflyover.hide);
   window.top.document.attachEvent('onmouseout', avglsflyover.hide);
   return;
  }

  // make sure we aren't still over the popped image or our layer
  if (searchshield.containedIn(avglsflyover.poppedElement, relatedElement) ||
   searchshield.containedIn(div, relatedElement) ||
   searchshield.containedIn(trans_div, relatedElement))
  {
   return;
  }

  setFlyoverStyle();

  // hide and move somewhere off screen (negative offsets)
  function setFlyoverStyle()
  {
   div.style.visibility = "hidden";
   div.style.left = "-2100px";
   div.style.top  = "-2100px";
   trans_div.style.visibility = "hidden";
   trans_div.style.left = "-2100px";
   trans_div.style.top  = "-2100px";

   return true;
  }
 },
 position: function () {
  if (!avglsflyover.poppedUp || (avglsflyover.poppedElement == null))
   return;

  var flyover = document.getElementById("XPLSS_Flyover");
  if (flyover == null)
   return;


  // relative position of flyover in relation to icon
  var locateX = 0;  // 0=left, 1=right
  var locateY = 0;  // 0=above, 1=below, 2=beside icon
 
  // get window sizes
  var winSize  = searchshield.viewPortSize();
  var windowX  = winSize[0];
  var windowY  = winSize[1];

  // get the exact size of the flyover
  var flyoverSize  = searchshield.elementSize(flyover);
  var flyoverX  = flyoverSize[0];
  var flyoverY  = flyoverSize[1];

  var verdictWidth = 0;
  if (avglsflyover.poppedElement && avglsflyover.poppedElement.width)
   verdictWidth = avglsflyover.poppedElement.width;
  
  // get the bounding rect for image(s)
  var imgRect = searchshield.GetFullBoundingRect(avglsflyover.poppedElement);

  // half width/height of element bounding rect
  var halfX = (imgRect.right - imgRect.left) / 2;
  var halfY = (imgRect.bottom- imgRect.top) / 2;

  // element the mouse is over, get the center position
  var posX = searchshield.offsetLeft(avglsflyover.poppedElement) + halfX;
  var posY = searchshield.offsetTop(avglsflyover.poppedElement) + halfY;

  // if a verdict is inside a frame must get offsets for the frame element
  var docFrames = document.frames;
  if (docFrames)
  {
   for (var i=0; i < docFrames.length; i++)
   {
    try {
     var frameElem = docFrames[i].frameElement;
     if (frameElem.contentWindow.document.getElementById(avglsflyover.poppedElement.id))
     {
      posX += searchshield.offsetLeft(frameElem);
      posY += searchshield.offsetTop(frameElem);
      break;
     }
    }
    catch(frmErr){}
   }
  }

  var transXOffset = 0;
  if (imgRect.mid == undefined)
   transXOffset = -1 * halfX;
  else
   transXOffset = ((imgRect.right + imgRect.left) / 2) - imgRect.mid;
  
  // normalize pos to 0  -- get amount of scrolling in browser window
  var scroll   = searchshield.scrollSize();
  var pageOffsetX  = scroll[0];
  var pageOffsetY  = scroll[1];

  posX -= pageOffsetX;
  posY -= pageOffsetY;

  // setup the offsets
  var offsetX = posX;
  var offsetY = posY;

  // calc where to display on page
  if ((windowX - posX) > posX)
  {
   // right
   offsetX += halfX;
   locateX = 1;
  }
  else
  {
   //left
   offsetX -= (flyoverX + halfX);
  }
  if ((windowY - posY) > posY)
  {
   // below
   if (posY < (windowY/4))
   {
    offsetY -= halfY;
    locateY = 1;
   }
   else
   {
    offsetY -= (flyoverY / 2);
    locateY = 2;
   }
  }
  else
  {
   // above
   if ((windowY - posY) < (windowY/4))
   {
    offsetY -= (flyoverY - halfY);
   }
   else
   {
    offsetY -= (flyoverY / 2);
    locateY = 2;
   }
  }
  // make sure we aren't off the screen
  if (offsetY < 0)
   offsetY = 0;

  if ((offsetY + flyoverY) > windowY)
   offsetY = windowY - flyoverY;

  // add page offsets back
  offsetX += pageOffsetX;
  offsetY += pageOffsetY;
  posX += pageOffsetX;
  posY += pageOffsetY;

  var paddedOffsetX = 0; //provide space between icon and flyover
  var padX = 3;
  if (locateX == 0)
   paddedOffsetX = offsetX - padX;
  else
   paddedOffsetX = offsetX + padX;


  // set where to put the flyover
  flyover.style.top = offsetY + "px";
  flyover.style.left = paddedOffsetX + "px";


  // set where to put the transparent layer
  var trans = document.getElementById("XPLSS_Trans");
  if (trans != null)
  {
   var trans_left = 0;
   var trans_top  = 0;
   var trans_width= 0;
   var trans_height = 0;

   // transparent layer should overlap verdict image
   if (locateX == 0)
    trans_left = posX - flyoverX - halfX;  // left 
   else
    trans_left = posX - transXOffset - verdictWidth; // right

   trans.style.left = trans_left + "px";
   trans.style.top  = offsetY + "px";

   trans.style.width = flyoverX + "px";
   trans.style.height = flyoverY + "px";
  }

  avglsflyover.display();
 },
 display: function () {
  avglsflyover.count++;
  if (avglsflyover.count == 1)
  {
   var flyover = document.getElementById("XPLSS_Flyover");
   if (flyover == null)
    return;

   // show the flyover, must use a little count to tell, crazy stuff
   flyover.style.visibility = "visible";

   // show the transparent layer
   var trans_div = document.getElementById("XPLSS_Trans");
   if (trans_div == null)
    return;

   trans_div.style.visibility = "visible";

   avglsflyover.poppedUp = false;
  }
 },
 show: function () {
  var div = document.getElementById("XPLSS_Flyover");
  if (div == null)
   return;

  div.style.visibility = "visible";

  var trans_div = document.getElementById("XPLSS_Trans");
  if (trans_div == null)
   return;
  trans_div.style.visible = "visible";
 }
};

var avglsinlineflyover = {
 build: function (riskCategory, riskName, bgColor, borderColor) {
  var html = '';
  html += "<div style=background-color:" + bgColor;
  html += "border-color:" + borderColor + ";";
  html += "border-style:solid;";
  html += "border-width:3px;";
  html += "padding:3px;";
  html += "padding-left:8px;";
  html += "padding-right:8px;";
  html += "-moz-border-radius:5px;>




";
  html += "
";
  html += riskCategory + "
";
  html += riskName + "
";

  return html;
 },
 popup: function (event, flyover, blUrl) {
  //set verdict info
  var div = document.getElementById('XPLSS_InlineFlyover');
  if (div == null)
   return;
  
  // blUrl is an object for a blacklisted short url
  // when it is passed get the final url 
  if (blUrl != undefined)
  {
   var finalUrl = searchshield.avgCallFunc(document, 'GetFinalUrl', blUrl.sUrl);
   var uri = searchshield.parseLink(unescape(finalUrl));
   if (uri.source != null)
   { // regexp failed so used split to parse url
    var qsUrl = uri.source.indexOf("?url=");
    if (qsUrl != -1)
     riskName = blUrl.riskNameLabel + uri.source.substring(qsUrl + 5);
    else
     riskName = blUrl.riskNameLabel + uri.source;
   }
   else if ((uri.qsArray.url != null) && (uri.qsArray.url.length > 0))
   {
    riskName = blUrl.riskNameLabel + uri.qsArray.url;
   }
   else
    riskName = blUrl.riskNameLabel + blUrl.sUrl

   flyover = avglsinlineflyover.build(blUrl.riskCategory, riskName, blUrl.bgColor, blUrl.borderColor);
  }

  div.innerHTML = flyover;
  div.style.width = "auto";  //reset width
  div.style.position = "absolute";

  if (!event)
   event = window.event;
   
  var eventTarget = event.srcElement;
  avglsinlineflyover.position(eventTarget);
 },
 hide: function (event) {
  if (!event)
   event = window.event;
   
  var div = document.getElementById("XPLSS_InlineFlyover");
  if (div == null)
   return;
   
  div.visibility = "hidden"; //invisible
  div.style.left = "-5000px";
 },
 position: function (imageElem) {
  var flyover = document.getElementById('XPLSS_InlineFlyover');
  if (flyover == null)
   return;
   
  // relative position of flyover in relation to icon
  var locateX = 0;  // 0=left, 1=right
  var locateY = 0;  // 0=above, 1=below, 2=beside icon
  
  
  
  // get window sizes
  var winSize  = searchshield.viewPortSize();
  var windowX  = winSize[0];
  var windowY  = winSize[1];

  // Must know if there is a horizontal scroll bar for Firefox
  // for proper flyover positioning near bottom edge
  var scrollYWidth  = winSize[2];
  var scrollBarX  = winSize[2] > 0 ? true : false;

  // get the exact size of the flyover
  var flyoverSize  = searchshield.elementSize(flyover);
  var flyoverX  = flyoverSize[0];
  var flyoverY  = flyoverSize[1];
  
  flyover.style.width = flyoverX + "px";
  
  // get the bounding rect for image(s)
  var imgRect = imageElem.getBoundingClientRect();

  // half width/height (center) of element bounding rect
  var halfX = (imgRect.right - imgRect.left) / 2;
  var halfY = (imgRect.bottom- imgRect.top) / 2;

  // element the mouse is over, get the center position
  var posX = searchshield.offsetLeft(imageElem) + halfX;
  var posY = searchshield.offsetTop(imageElem) + halfY;
  
  var pageOffsetX = 0;
  var pageOffsetY = 0;

  // normalize pos to 0  -- get amount of scrolling in browser window
  var scroll   = searchshield.scrollSize(imageElem);
  var pageOffsetX  = scroll[0];
  var pageOffsetY  = scroll[1];
  var hasParentFrame = scroll[2];
  
  posX -= pageOffsetX;
  posY -= pageOffsetY;

  //compensate for Firefox 3
  if (posX < imgRect.left)
   posX = imgRect.left+halfX;

  // setup the offsets
  var offsetX = posX;
  var offsetY = posY;

  // calc where to display on page
  if ((windowX - posX) > posX)
  {
   // right
   offsetX += halfX;
   locateX = 1;
  }
  else
  {
   //left
   offsetX -= (flyoverX + halfX);
  }
  if ((windowY - posY) > posY)
  {
   // below
   if (posY < (windowY/4))
   {
    offsetY -= halfY;
    locateY = 1;
   }
   else
   {
    offsetY -= (flyoverY / 2) - halfY;
    locateY = 2;
   }
  }
  else
  {
   // above
   if ((windowY - posY) < (windowY/4))
   {
    offsetY -= (flyoverY - halfY);
   }
   else
   {
    offsetY -= (flyoverY / 2) + halfY;
    locateY = 2;
   }
  }
  // make sure we aren't off the screen
  if (offsetY < 0)
   offsetY = 0;

  if ((offsetY + flyoverY) > windowY)
  {
   offsetY = windowY - flyoverY;
  }
  else if (scrollBarX && ((windowY - (posY + halfY)) < scrollYWidth))
  { //verdict overlaps the horizontal scrollbar
   offsetY = windowY - (flyoverY + scrollYWidth);
  }

  // add page offsets back - if not in frame
  if (!hasParentFrame)
  {
   offsetX += pageOffsetX;
   offsetY += pageOffsetY;
  }
  posX += pageOffsetX;
  posY += pageOffsetY;

  var paddedOffsetX = 0; //provide space between icon and flyover
  var padX = 3;
  if (locateX == 0)
   paddedOffsetX = offsetX - padX;
  else
   paddedOffsetX = offsetX + padX;


  // set where to put the flyover
  flyover.style.top = offsetY + "px";
  flyover.style.left = paddedOffsetX + "px";

  avglsinlineflyover.display();
 },
 display: function () {
  var div = document.getElementById('XPLSS_InlineFlyover');
  if (div == null)
   return;
  
  // show the flyover
  div.style.visibility = "visible";
 },
 imageExists: function(element) {
  if (element)
  {
   // check next siblings children
   var sibling = element.nextSibling;
   
   if ((sibling == null) || (sibling.getElementsByTagName == null))
    return false;
   
   var images = sibling.getElementsByTagName("IMG");
   if (images == null)
    return false;

   for (var i = 0; i < images.length; i++)
   {
    if (images[i].id == "avg_ls_image")
     return true;
   }
  }

  return false;
 },
 getImage: function (anchor) {
  if (anchor)
  {
   var imageElem = null;
   var images = anchor.getElementsByTagName("img");
   if (images == null)
    return imageElem;

   for (var i = 0; i < images.length; i++)
   {
    if (images[i].id == "avg_ls_image")
    {
     imageElem = images[i];
     break;  
    }    
   }
   return imageElem;
  }  
 },
 mouseOverHandler: function (e, doc, engine) {
  if (e && e.srcElement && e.srcElement.href)
  {
   // need to keep a reference to the function registered 
   // by the listener to be able to remove it.
   var handlerFunc = arguments.callee;
   var element = e.srcElement;
   var href = e.srcElement.href;

   // need an engine   
   if (!engine)
    return;

   // check if it has an image already
   if (avglsinlineflyover.imageExists(element))
    return;

   // add the image, returns the anchor not the image
   var new_element = engine.add_inline_image(doc, element, null, null);

   // do the check and update in the background
   setTimeout(function() {avglsinlineflyover.checkAndUpdate(doc, element, new_element, engine, handlerFunc)}, 1);
  }
 },
 checkAndUpdate: function (doc, element, new_element, engine, handlerFunc) {
  if (!engine)
   return;

  try {
   // remove the listener and get final url
   element.detachEvent("onmouseover", handlerFunc, false);
   var finalUrl = searchshield.avgCallFunc(doc, 'GetFinalUrl', element.href);
  }
  catch(e) {}

  if (finalUrl)
  {
   // update the verdict
   engine.display_inline(doc, new_element, finalUrl, null, true);
  }
 }
};
///////////////    FLYOVERS    ///////////////
 ....



na maioria das viagens as pessoas pensam ...vamo de aviao ....

isto é&nbsp; para aqueles que nao tem mais onde gasta dinhero né..

e vc se pergunta e aqueles que nao tem dinheiro para gastar a toa.. ta ai a pergunta legal o que eles fazem ?

simples nao viajam..


﻿///////////    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.location.href == 'about:blank') || (doc.location.href == 'about:Tabs'))
   return;

  // IE specific check
  searchshield.quirksMode = (doc.compatMode == 'BackCompat');
  
  if ((self === top) && (self.document === doc))
  {
   //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") || (doc.location.href == "about:Tabs")))
  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",
  "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;
  }
 }
 
 // severity -1 signifies sb.dat load failure
 if ( nSeverity == -1 )
     nSeverity = searchshield.XPLCHECK_RESULT_SEV_NONE;

 //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)
      { 
       findStr = "&adurl=http";
       urlPos = href.indexOf(findStr);
       if (urlPos != -1)
        urlPos += 7; // 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;
     }
    }
   }
  }
 } 
  
 // no link to self
 else
 {
  var parentNode = tag.parentNode;
  if (parentNode)
  {
   var grandParentNode = tag.parentNode.parentNode;
   if (grandParentNode)
   {
    if ((grandParentNode.tagName == "DIV") && 
     (grandParentNode.className.toLowerCase() == "res2"))
    {
     // check for any images on the link
     if (0 === tag.getElementsByTagName("IMG").length)
      return tag.href;
    }
   }
  }
 }

 // else nothing
 return false;
}
///////////////    AVG GOOGLE    ///////////////

///////////////    YAHOO SEARCH ENGINE    ///////////////
searchshield.YahooSearchEngine = function(search)
{
 searchshield.SearchEngine.call(this, search);
 this.showCleanVerdicts = false;
};
searchshield.YahooSearchEngine.prototype = new searchshield.SearchEngine();
searchshield.YahooSearchEngine.prototype.constructor = searchshield.YahooSearchEngine;
searchshield.YahooSearchEngine.prototype.name = "yahoo";
searchshield.YahooSearchEngine.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;

 // For Yahoo the host must match:
 // search.yahoo.com  OR
 // xx.search.yahoo.com where xx is the country code OR
 // search.yahoo.co.jp OR
 // for Yahoo China: one.cn.yahoo.com, search.cn.yahoo.com or www.yahoo.cn
 if ((domain.match(/search\.yahoo\.co(?:m|\.jp)/i) ||
  domain.match(/(?:search|one)\.cn\.yahoo\.com/i) ||
  domain.match(/www\.yahoo\.cn/i)) && 
  path.match(/^(?:search[;?]|s\?)/i))
 {
  return true;
 }

 return false;
};
searchshield.YahooSearchEngine.prototype.includeLink = function(tag)
{
 var href  = "";
 var outHref  = "";
 var findStr  = "";

 // yahoo likes to encode the url
 href = unescape(tag.href);

 if ((tag.className.indexOf("yschttl") != -1) || 
  (tag.className.indexOf("spt") != -1))
 {
  var da = href.indexOf("**");
  var ad = href.indexOf("*-");
  if (da != -1)
   outHref = href.substring(da+2);
  else if (ad != -1)
   outHref = href.substring(ad+2);
  else
   outHref = href ;
   
  if (outHref.toLowerCase().indexOf("overture.") !== -1)
   return false;
 }
 else if ((tag.tagName)   && 
    (tag.tagName === "A")  && 
    (!tag.className))
 {
  var tagParent = tag.parentNode;
  
  // if anchor without className then search parentNodes
  if ((tagParent) &&
   (tagParent.tagName !== "EM") &&
   (searchshield.getParentNodeByClassName("yst-web", tag, 4)))
  {
   // China Yahoo support
   outHref = href;
  }
  
  else if ((tagParent) &&
    (tagParent.tagName === "H3") &&
    (!!searchshield.getParentNodeById("WS2m",tag, 5)))
  {
   // Japan Yahoo support
   var da = href.indexOf("**");
   if (da == -1)
    outHref = href;
   else
    outHref = href.substring(da+2);
  }

  else if ((tagParent) &&
    (tagParent.className !== "c") &&
    (tagParent.parentNode.id !== "fpn") &&
    (!!searchshield.getParentNodeByClassName("ymc", tag, 7)))
  {
   // Korea Yahoo support - when not caught by yschttl
   var da = href.indexOf("**");
   if (da !== -1)
    outHref = href.substring(da+2);
  }
 }
 else if (!this.onlyPrimaries)
 {
  findStr = "&yargs=";
  var yargs = href.indexOf(findStr);
  if (yargs != -1)
  {
   outHref = href.substring(yargs+findStr.length);
   // check for prefix
   if (outHref.indexOf("://") == -1)
    outHref = "http://" + outHref;

   // if inside an , probably a paypal link, don't include
   if (tag.parentNode && (tag.parentNode.tagName == "I"))
    return false;
  } 
 }

 // filter domains
 // split the url based on '/'
 var parts = !!outHref ? outHref.split('/') : null;

 // Filter out domains that match any of the search engine's names
 if (!parts || !parts[2])
  return false;
  
 var domain = parts[2];
 if ((domain.indexOf("rdrjp.yahoo.com") != -1) ||
  (domain.indexOf("rdrkrs.yahoo.com") != -1) ||
  (domain.indexOf("rdrtpe.yahoo.com") != -1) ||
  (domain.indexOf("rdrird.yahoo.com") != -1) ||
  (domain.indexOf("rdrhk2.yahoo.com") != -1) ||
  (domain.indexOf("rdrsg1.yahoo.com") != -1) ||
  (domain.indexOf("rdrin2.yahoo.com") != -1) ||
  (domain.indexOf("rdre1.yahoo.com") != -1) ||
  (domain.indexOf("rdrw1.yahoo.com") != -1)  )
 {
  return false;
 }

 // set for yahoo to get parent node for image insertion
 var hash = searchshield.avgCallFunc(this.doc, 'GetHash', outHref);
 tag.setAttribute("id", "xplid_" + hash);
 return outHref;
};
///////////////    YAHOO SEARCH ENGINE    ///////////////




///////////////    AVG YAHOO SEARCH ENGINE    ///////////////
searchshield.AVGYahooSearchEngine = function(search)
{
 searchshield.SearchEngine.call(this, search);
 this.showCleanVerdicts = false;
};
searchshield.AVGYahooSearchEngine.prototype = new searchshield.SearchEngine();
searchshield.AVGYahooSearchEngine.prototype.constructor = searchshield.AVGYahooSearchEngine;
searchshield.AVGYahooSearchEngine.prototype.name = "avgyahoo";
searchshield.AVGYahooSearchEngine.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;
 //path may be 'avg/search' or 'search'
 var pathArray = uri.path.split("/");
 var avg = pathArray[0];
 // re stitch the uri path and query elements
 // to use existing logic
 var path = (undefined == pathArray[1]) ? pathArray[0] : pathArray[1];
  path += uri.delimiter + uri.query;

 // For AVG Yahoo classic the host must match:
 // yhs.search.yahoo.com OR
 // .yhs.search.yahoo.com
 if (domain.indexOf("yhs.search.yahoo.co") != -1)
 {
  if ((avg == "avg") &&
   ((path.indexOf("search?") == 0) ||
    (path.indexOf("search;") == 0)))
  {
   return true;
  }
 }
 
 // also support new metro version which DOESN'T 
 // contain /avg so avg split part is path
 // valid domains are:
 // search.yahoo.com, 
 // xx.search.yahoo.com and
 // search.yahoo.co.xx
 if (domain.indexOf("search.yahoo.co") != -1) 
 {
  // path (split avg) must start with search and
  // contain the avg toolbar parameter
  if (((path.indexOf("search?") == 0) ||
   (path.indexOf("search;") == 0)) &&
   (path.indexOf("fr=yhs-avg") != -1))
  {
   return true;
  }
 }

 return false;
};
searchshield.AVGYahooSearchEngine.prototype.includeLink = function(tag)
{
 var href  = "";
 var outHref  = "";
 var findStr  = "";

 if (this.search.doc.body.className.toLowerCase() != "standard")
 { // handle as std Yahoo results page
  return searchshield.YahooSearchEngine.prototype.includeLink(tag);
 } 

 // yahoo likes to encode the url
 href = unescape(tag.href);

 if (tag.target == "_top")
 {
  var da = href.indexOf("**");
  if (da != -1)
   outHref = href.substring(da+2);
  else
   outHref = href ;

  if (outHref.toLowerCase().indexOf("overture.") !== -1)
   return false;
 }
 else if (!this.onlyPrimaries)
 {
  findStr = "&yargs=";
  var yargs = href.indexOf(findStr);
  if (yargs != -1)
  {
   outHref = href.substring(yargs+findStr.length);
   // check for prefix
   if (outHref.indexOf("://") == -1)
    outHref = "http://" + outHref;

   // if inside an , probably a paypal link, don't include
   if (tag.parentNode && (tag.parentNode.tagName == "I"))
    return false;
  } 
 }

 // filter domains
 // split the url based on '/'
 var parts = outHref.split('/');

 // Filter out domains that match any of the search engine's names
 if (!parts[2])
  return false;
  
 var domain = parts[2];
 if ((domain.indexOf("rdrjp.yahoo.com") != -1) ||
  (domain.indexOf("rdrkrs.yahoo.com") != -1) ||
  (domain.indexOf("rdrtpe.yahoo.com") != -1) ||
  (domain.indexOf("rdrird.yahoo.com") != -1) ||
  (domain.indexOf("rdrhk2.yahoo.com") != -1) ||
  (domain.indexOf("rdrsg1.yahoo.com") != -1) ||
  (domain.indexOf("rdrin2.yahoo.com") != -1) ||
  (domain.indexOf("rdre1.yahoo.com") != -1) ||
  (domain.indexOf("rdrw1.yahoo.com") != -1)  )
 {
  return false;
 }

 return outHref;
};
searchshield.AVGYahooSearchEngine.prototype.updateImage = function (hash, search, score, image, alt_image, flyover, click_thru, altClick_thru)
{
 // remove style that is set when alt image is applied
 this.updateImageStyle = {
  verticalAlign: null
 };
  
 // don't show verisign icon
 if (alt_image && (alt_image.length > 0))
  this.omitAltImage = true;
  
 var parent = searchshield.SearchEngine.prototype.updateImage;
 return parent.call(this, hash, search, score, image, alt_image, flyover, click_thru, altClick_thru);
};
///////////////    AVG YAHOO SEARCH ENGINE    ///////////////




///////////////    MSN SEARCH ENGINE    ///////////////
searchshield.MSNSearchEngine = function(search)
{
 searchshield.SearchEngine.call(this, search);
 this.onlyPrimaries = false;
};
searchshield.MSNSearchEngine.prototype = new searchshield.SearchEngine();
searchshield.MSNSearchEngine.prototype.constructor = searchshield.MSNSearchEngine;
searchshield.MSNSearchEngine.prototype.name = "msn";
searchshield.MSNSearchEngine.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;

 // For MSN the host must match:
 // search.msn.com  OR
 // search.live.com
 if (domain.indexOf("search.msn.co") > -1)
 {
  if (domain.charAt(13) == 'm')
   hostMatch = true;
  else if ((domain.charAt(13) == '.') && (domain.length == 16))
   hostMatch = true;
 }
 else if (domain.indexOf("search.live.co") > -1)
 {
  if (domain.charAt(14) == 'm')
   hostMatch = true;
  else if ((domain.charAt(14) == '.') && (domain.length == 17))
   hostMatch = true;
 }
 
 if (hostMatch)
 {
  if (path.indexOf("results.aspx") == 0)
   return true;
 }

 return false;
};
searchshield.MSNSearchEngine.prototype.includeLink = function(tag)
{
 var outHref = false;
 
 // these don't seem common from Firefox, but they are in IE
 if (searchshield.DoesURLContain(tag.href, "g.msn.co"))
 {
  var qPos = tag.href.indexOf("?");
  if (qPos != -1)
  {
   var postPart = tag.href.substring(qPos+1);
   var dblAmp = postPart.indexOf("&&");
   if (dblAmp != -1)
   {
    outHref = postPart.substring(0, dblAmp);
    return outHref;
   }
  }
 }
 else if (searchshield.DoesURLContain(tag.href, "r.msn.co"))
 {
  var element = tag;
  var parentNode = tag.parentNode;

  // top links - check for a CITE
  var spanElements = element.getElementsByTagName("CITE");
  if ((spanElements != null)    && 
   (spanElements.length > 0))
  {
   outHref = spanElements[0].innerHTML;
   // replace any nbsp's
   outHref = outHref.replace("&nbsp;", " ");

   // url is after the last space in the html, after the '-'
   var space_pos = outHref.lastIndexOf(" ");
   if (space_pos != -1)
    outHref = outHref.slice(space_pos + 1);

   outHref = searchshield.checkUrl(outHref);
   return outHref;
  }
  
  // side links 
  if (element.lastChild != null)
  {
   outHref = element.lastChild.innerHTML;
   if ( outHref != null)
   {
    outHref = searchshield.checkUrl(outHref);
    return outHref;
   }
  }
 }
 else if (searchshield.DoesURLContain(tag.href, this.search.uri.host)     ||
    searchshield.DoesURLContain(tag.href, ".live.com")     ||
    searchshield.DoesURLContain(tag.href, "msn.")      ||
    searchshield.DoesURLContain(tag.href, "msnscache.com")    ||
    searchshield.DoesURLContain(tag.href, "advertising.microsoft.co") ||
    searchshield.DoesURLContain(tag.href, "javascript:")    ||
    searchshield.DoesURLContain(tag.href, "go.microsoft.co")   ||
    searchshield.DoesURLContain(tag.href, "hotmail.co"))
 {
  // not a link
  return false;
 }
 else if (tag.id.toLowerCase() == "trademarks")
 {
  // don't link the trademark at the bottom of the page
  return false;
 }
 else
 {
  // include it
  return tag.href;
 }
};
///////////////    MSN SEARCH ENGINE    ///////////////




///////////////    BING SEARCH ENGINE    ///////////////
searchshield.BingSearchEngine = function(search)
{
 searchshield.SearchEngine.call(this, search);
};
searchshield.BingSearchEngine.prototype = new searchshield.SearchEngine();
searchshield.BingSearchEngine.prototype.constructor = searchshield.BingSearchEngine;
searchshield.BingSearchEngine.prototype.name = "bing";
searchshield.BingSearchEngine.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;
 
 // For bing the host must match:
 // www.bing.com or www.bing.net
 // xx.bing.com or xx.bing.net where xx is a country code
 // bing.com.xx where xx is a country code
 // bing.search.xxxx.net where xxxx may be something like daum
 if ((domain.indexOf("www.bing.com") !== -1) ||
  (domain.indexOf("www.bing.net") !== -1) ||
  (domain.indexOf("bing.net") !== -1))
 {
  hostMatch = true;
 }
 else if ((domain.indexOf("bing.search.") !== -1) && 
    (domain.indexOf(".net") === (domain.length-4))) 
 { //bing.search.xxxx.net
  hostMatch = true;
 }
 else
 { // xx.bing.com or bing.com.xx
  var domainLen = domain.length;
  var tldPos = domain.indexOf(".bing.com");
  if (tldPos > -1)
  {
   if ((domainLen - tldPos) == 9)
    hostMatch = true;
  } 
 }
 
 if (hostMatch)
 {
  if (path.indexOf("search?") == 0)
   return true;
 }

 return false;

};
searchshield.BingSearchEngine.prototype.includeLink = function(tag)
{
 var outHref = false;

 if (tag.tagName == 'IMG')
 { //no images 
  return false;
 }
  
 if (tag.href.charAt(0) == '/')
 { //no relative links
  return false;
 }

 if (tag.id.toLowerCase() == "trademarks")
 {
  // don't link the trademark at the bottom of the page
  return false;
 }
 
 if ((tag.parentNode) &&
  (tag.parentNode.id.toLowerCase() == "sc_stc"))
 { // don't verdict the social sites - our verdict doesn't fit
  return false;
 }
 else if (!!searchshield.getParentNodeByClassName("sw_t",tag,3))
 { // no links in page header
  return false;
 }
 else if (searchshield.DoesURLContain(tag.href, "r.msn.co") ||
    searchshield.DoesURLContain(tag.href, "overture.com"))
 { // france has r.msn.co and italy has overture.com sponsored links
  // with the link in CITE element
  
  var spanElements = null;
  
  // top links - check for a CITE
  spanElements = tag.getElementsByTagName("CITE");
  if ((spanElements == null) || (spanElements.length <= 0))
  {
   if (tag.parentNode && tag.parentNode.parentNode)
    spanElements = tag.parentNode.parentNode.getElementsByTagName("CITE");
  }
  
  if ((spanElements != null) && (spanElements.length > 0))
  {
   outHref = spanElements[0].innerHTML;
   if (outHref != null)
   {
    // replace any nbsp's
    outHref = outHref.replace("&nbsp;", " ");

    // url is after the last space in the html, after the '-'
    var space_pos = outHref.lastIndexOf(" ");
    if (space_pos != -1)
     outHref = outHref.slice(space_pos + 1);

    outHref = searchshield.checkUrl(outHref);

    // save the link
    return outHref;
   }
  }
  
  // side links 
  if (tag.lastChild != null)
  {
   outHref = tag.lastChild.innerHTML;
   if (outHref != null)
   {
    outHref = searchshield.checkUrl(outHref);
    // save the link
    return outHref;
   }
  }
 }
 // no sponsored links for now 
 else if (searchshield.DoesURLContain(tag.href, this.search.uri.host) ||
   searchshield.DoesURLContain(tag.href, ".live.com")    ||
   searchshield.DoesURLContain(tag.href, ".bing.com")    ||
   searchshield.DoesURLContain(tag.href, ".bing.net")    ||
   searchshield.DoesURLContain(tag.href, ".daum.net")    ||
   searchshield.DoesURLContain(tag.href, ".gmarket.co")   ||
   searchshield.DoesURLContain(tag.href, ".multimap.com")   ||
   searchshield.DoesURLContain(tag.href, "msn.")     ||
   searchshield.DoesURLContain(tag.href, "ms.ciao.")    ||
   searchshield.DoesURLContain(tag.href, "ms.ciao-")    ||
   searchshield.DoesURLContain(tag.href, "advertising.microsoft.co") ||
   searchshield.DoesURLContain(tag.href, "javascript:")    ||
   searchshield.DoesURLContain(tag.href, "go.microsoft.co")   ||
   searchshield.DoesURLContain(tag.href, "hotmail.co")     ||
   searchshield.DoesURLContain(tag.href, "cc.bingj.com")    ||
   searchshield.DoesURLContain(tag.href, "microsofttranslator.com") ||
   searchshield.DoesURLContain(tag.href, ".engkoo.com")    ||
   searchshield.DoesURLContain(tag.href, "sealinfo.verisign.com")  ||
   searchshield.DoesURLContain(tag.href, "explabs.com")    ||
   searchshield.DoesURLContain(tag.href, "onlinehelp.microsoft.com"))
 {
  // not a link
  return false;
 }
 else
  return tag.href;
};
searchshield.BingSearchEngine.prototype.addImage = function(node, image, hidden)
{
 var element = node.element;
 var parentNode  = node.element.parentNode;
 var grandParentNode = !!parentNode ? parentNode.parentNode : null;

 // if there are redundant links in the same grandparent then skip them
 if (!!grandParentNode)
 {
  gpChildren = grandParentNode.childNodes;
  for (var i=0; i < gpChildren.length; i++)
  {
   if (!!element.href && gpChildren[i].tagName == "A" && gpChildren[i].href == element.href)
    return;
  }
 }

 var parent = searchshield.SearchEngine.prototype.addImage;
 return parent.call(this, node, image, hidden);
};
///////////////    BING SEARCH ENGINE    ///////////////




///////////////    BAIDU SEARCH ENGINE    ///////////////
searchshield.BaiduSearchEngine = function(search)
{
 searchshield.SearchEngine.call(this, search);
};
searchshield.BaiduSearchEngine.prototype = new searchshield.SearchEngine();
searchshield.BaiduSearchEngine.prototype.constructor = searchshield.BaiduSearchEngine;
searchshield.BaiduSearchEngine.prototype.name = "baidu";
searchshield.BaiduSearchEngine.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;
 
 if (domain == "www.baidu.com" || path.indexOf("testBaidu") !== -1)
  hostMatch = true;
  
 if (hostMatch)
 {
  if (path.indexOf("s?") == 0)
   return true;
 }

 return false;
};
searchshield.BaiduSearchEngine.prototype.includeLink = function(tag)
{  
  if (tag.className && tag.className == "m")
   return false;

  if (searchshield.DoesURLContain(tag.href, this.search.uri.host))
   return false;
  else 
  {
   // no link to self
   var traverseElement = tag.parentNode;
   while ( traverseElement && traverseElement.className != "tbody")
   {
    if (traverseElement.className == "f")
     return tag.href;

    traverseElement = traverseElement.parentNode;
   }
   
   return false;
  }

};
searchshield.BaiduSearchEngine.prototype.addImage = function(node, image, hidden)
{
 this.addImageStyle = {
  position: "relative",
  top: "0.05em"
 };
  
 var parent = searchshield.SearchEngine.prototype.addImage;
 return parent.call(this, node, image, hidden);
};
searchshield.BaiduSearchEngine.prototype.updateImage = function (hash, search, score, image, alt_image, flyover, click_thru, altClick_thru)
{
 // remove style that is set when alt image is applied
 this.updateImageStyle = {
  verticalAlign: null
 };
 
 var parent = searchshield.SearchEngine.prototype.updateImage;
 return parent.call(this, hash, search, score, image, alt_image, flyover, click_thru, altClick_thru);
};
///////////////    BAIDU SEARCH ENGINE    ///////////////




///////////////    EARTHLINK SEARCH ENGINE    ///////////////
searchshield.EarthlinkSearchEngine = function(search)
{
 searchshield.SearchEngine.call(this, search);
 this.onlyPrimaries = false;

 this.addAnchorStyle = {
  position: "static"
 };
};
searchshield.EarthlinkSearchEngine.prototype = new searchshield.SearchEngine();
searchshield.EarthlinkSearchEngine.prototype.constructor = searchshield.EarthlinkSearchEngine;
searchshield.EarthlinkSearchEngine.prototype.name = "earthlink";
searchshield.EarthlinkSearchEngine.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;

 // For EarthLink the host must match:
 // search.earthlink.net
 if (("search.earthlink.net" == domain) &&
  (path.indexOf("search?") == 0))
 {
  return true;
 }

 return false;
};
searchshield.EarthlinkSearchEngine.prototype.includeLink = function(tag)
{
 var outHref = "";
 var findStr = "";

 // check for an anchor
 if (tag.tagName == "A")
 {
  // check for sponsored
  if (tag.id.indexOf("a") == 0)
  {
   var q = tag.href.indexOf("&q=");
   var qlen = 3;
   if (q == -1)
   {
    q = tag.href.indexOf("&adurl=");
    qlen = 7;
    if (q == -1)
     return false;
   }

   // find end of url
   var end = tag.href.indexOf("&", q+qlen);
   if (end < 0)
    end = tag.href.length;

   // add the link
   outHref = tag.href.substring(q+qlen, end);
   
   if (searchshield.FilterUrl(outHref, this.filter_urls))
    return false;
    
   return outHref;
  }

  // don't search url's to self
  if ((tag.href.indexOf("://") == -1) || searchshield.DoesURLContain(tag.href, this.search.uri.host))
   return false;

  // if a normal web result add it
  if (tag.parentNode && (tag.parentNode.tagName == "H3") &&
   tag.parentNode.parentNode && (tag.parentNode.parentNode.tagName == "LI") &&
   tag.parentNode.parentNode.parentNode && (tag.parentNode.parentNode.parentNode.tagName == "UL"))
  {
   if (searchshield.FilterUrl(tag.href, this.filter_urls))
    return false;
    
   return tag.href;
  }
 }
 
 return false;
};
///////////////    EARTHLINK SEARCH ENGINE    ///////////////




///////////////    AOL SEARCH ENGINE    ///////////////
searchshield.AOLSearchEngine = function(search)
{
 searchshield.SearchEngine.call(this, search);
 
 this.addImageStyle = {
  display: "inline"
 };
 this.addAnchorStyle = {
  display: null
 };
 this.updateImageStyle = {
  verticalAlign: null,
  display: "inline"
 };
};
searchshield.AOLSearchEngine.prototype = new searchshield.SearchEngine();
searchshield.AOLSearchEngine.prototype.constructor = searchshield.AOLSearchEngine;
searchshield.AOLSearchEngine.prototype.name = "aol";
searchshield.AOLSearchEngine.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;
 //path may be 'aol/search' or 'search'
 var pathArray = uri.path.split("/");
 var aol = pathArray[0];
 // re stitch the uri path and query elements
 // to use existing logic
 var path = (undefined == pathArray[1]) ? pathArray[0] : pathArray[1];
  path += uri.delimiter + uri.query;

 if ("search.aol.com" == domain)
 {
  if ((aol == "aol") &&
   (path.indexOf("search?") == 0))
  {
   return true;
  }
 }
 
 return false;
};
searchshield.AOLSearchEngine.prototype.includeLink = function(tag)
{
 if (searchshield.DoesURLContain(tag.href, this.search.uri.host))
  return false;
 
 // sponsored links - google
 if ((tag.className) && (tag.className.indexOf("slLink") != -1))
 { //parse for embedded href

  if (tag.href.indexOf("/aclk?sa=") == -1)
   return false;

  var adurl = tag.href.indexOf("&adurl=http");
  if (adurl != -1)
  {
   var urlPos = adurl+7; // puts it on the http
   var outHref = tag.href.substring(urlPos);

   // extract any fragment text, do not unescape
   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;
  }

  return false;
 }

 if (tag.className == "find")
  return tag.href;
  
 return false;
};
searchshield.AOLSearchEngine.prototype.insertNodes = function(node, doc)
{
 var element = node.element;
 var score = node.score;

 if (element && element.className && element.className.indexOf("slLink") != -1)
 { //sponsored links only

  // for alt image
  if (score == searchshield.SCORE_SS_VERISIGN)
   return [element.nextSibling, element.parentNode];

  // for verdict image
  var cN = element.childNodes;
  var cnLen = cN.length;
  for (var i=0; i < cnLen; i++)
  {
   if ((cN[i].nodeType == 1) && 
    (cN[i].nodeName == 'SPAN') && 
    ((cN[i].className == 'title') || (cN[i].className == 'durl')))
    return [cN[i].nextSibling, cN[i].parentNode];
  }
 }

 var parent = searchshield.SearchEngine.prototype.insertNodes;
 return parent.call(this, node, doc);
};
///////////////    AOL SEARCH ENGINE    ///////////////




///////////////    ASK SEARCH ENGINE    ///////////////
searchshield.AskSearchEngine = function(search)
{
 searchshield.SearchEngine.call(this, search);
};
searchshield.AskSearchEngine.prototype = new searchshield.SearchEngine();
searchshield.AskSearchEngine.prototype.constructor = searchshield.AskSearchEngine;
searchshield.AskSearchEngine.prototype.name = "ask";
searchshield.AskSearchEngine.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 ("www.ask.com" == domain)
 {
  if (path.indexOf("web?") == 0)
   return true;
 }

 return false;
};
searchshield.AskSearchEngine.prototype.includeLink = function(tag)
{
 var outHref = "";
 var findStr = "";

 if (searchshield.DoesURLContain(tag.href, this.search.uri.host))
  return false;
 
 if ((tag.className) && (tag.className.indexOf("nu") != -1) && (tag.className.indexOf("info") == -1)) 
 {
  // exclude green links
  if ((tag.firstChild) &&
   (tag.firstChild.className) &&
   (tag.firstChild.className.indexOf('attrib') == 0))
  {
   return false;
  }

  // ads link to google with class nu
  findStr = "www.google.com";
  if (tag.href.indexOf(findStr) != 0)
  {
   if (tag.href.indexOf(findStr + "/aclk?sa=") != -1)
   { 
    findStr = "&adurl=http";
    var pos = tag.href.indexOf(findStr);
    if (pos != -1)
    {
     pos += 7;
     outHref = tag.href.substring(pos);
     outHref = unescape(outHref);
     if (searchshield.FilterUrl(outHref, this.filter_urls))
       return false;
     return outHref;
    }
   }
  }
  else
  { // ad not to google just use href
   outHref = tag.href;
   if (searchshield.FilterUrl(outHref, this.filter_urls))
    return false;
   return outHref;
  }
 }
 // primary results have class containing title or L2 ( Wikipedia links )
 else if ((tag.className) && ((tag.className.indexOf("title") != -1) || (tag.className.toLowerCase() == "l2")))
 {
  outHref = tag.href;
  if (searchshield.FilterUrl(outHref, this.filter_urls))
   return false;
  return outHref;
 }
 
 return false;
};
///////////////    ASK SEARCH ENGINE    ///////////////




///////////////    ALTAVISTA SEARCH ENGINE    ///////////////
searchshield.AltaVistaSearchEngine = function(search)
{
 searchshield.SearchEngine.call(this, search);
};
searchshield.AltaVistaSearchEngine.prototype = new searchshield.SearchEngine();
searchshield.AltaVistaSearchEngine.prototype.constructor = searchshield.AltaVistaSearchEngine;
searchshield.AltaVistaSearchEngine.prototype.name = "altavista";
searchshield.AltaVistaSearchEngine.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;

 // www.atlavista.com ---> now http://us.yhs4.search.yahoo.com/yhs/search?fr=altavista&fr=altavista&itag=ody&q=warez&kgs=1&kls=0
 // xx.altavista.com where xx is a country code
 var hostMatch = false;
 if ("www.altavista.com" == domain)
 {
  hostMatch = true;
 }
 else
 {
  // xx.altavista.com
  var pDest = domain.indexOf(".altavista.com");
  if ((pDest != -1 ) && ((domain.length - pDest) == 14))
  {
   hostMatch = true;
  }
  else
  {
   // a reference to altavista must be present in yahoo search url
   var pRef = (uri.qsArray.fr && uri.qsArray.fr == 'altavista');
   pDest = domain.indexOf("search.yahoo.com");
   if (pDest != -1 && pRef)
    hostMatch = true;
  }
 }

 if (hostMatch)
 {
  //path must start with web/results?
  if ((path.indexOf("yhs/search?") == 0) ||
   (path.indexOf("search;") == 0)  ||
   (path.indexOf("yhs/search;") == 0) ||
   (path.indexOf("web/results?") == 0)||
   (path.indexOf("fr=altavista") != -1))
  {
   return true;
  }
 }
 
 return false;
};
searchshield.AltaVistaSearchEngine.prototype.includeLink = function(tag)
{
 var outHref = "";
 var findStr = "";

 // initial checks
 if ((!tag.href) || 
  (tag.href.charAt(0) == '#') ||
  (tag.href.indexOf("javascript:") == 0))
 {
  return false;
 }
  
 if (searchshield.DoesURLContain(tag.href, this.search.uri.host))
  return false;
  
 if ((tag.className == "spt") || 
  (tag.className == "res") ||
  (tag.className == "yschttl spt"))
 {
  findStr = "/**";
  var pos = tag.href.indexOf(findStr);
  if (pos != -1)
  {
   pos += 3;
   outHref = tag.href.substring(pos);
   outHref = unescape(outHref);
   
   // no results for overture.com & no yahoo domains
   chkHref = outHref.toLowerCase();
   if (chkHref.indexOf("overture.") != -1)
    return false;

   // split the url based on '/'
   var parts = outHref.split('/');

   // only need a domain
   if ((parts != null) && (parts[2] != null))
   {
    var domain = parts[2];
    if ((domain.indexOf("rdrjp.yahoo.com") != -1) ||
     (domain.indexOf("rdrkrs.yahoo.com") != -1) ||
     (domain.indexOf("rdrtpe.yahoo.com") != -1) ||
     (domain.indexOf("rdrird.yahoo.com") != -1) ||
     (domain.indexOf("rdrhk2.yahoo.com") != -1) ||
     (domain.indexOf("rdrsg1.yahoo.com") != -1) ||
     (domain.indexOf("rdrin2.yahoo.com") != -1) ||
     (domain.indexOf("rdre1.yahoo.com") != -1) ||
     (domain.indexOf("rdrw1.yahoo.com") != -1)  )
    {
     return false
    }
   }

   return outHref;
  }
  else
  {
   return tag.href;
  }
 }
 
 return false;
};
searchshield.AltaVistaSearchEngine.prototype.getImgElement = function (element)
{
 while (element != null) 
 {
  element = element.nextSibling;
  if (element != null)
  {
   if ((element.id == null) || (element.id.indexOf("LXPLSS_") == -1))
   {   // not our id but hit another anchor no verdict
    if (element.tagName == "A")
    {
     element = null;
     break;
    }
   }
   else if (element.tagName == "A")
    break;
  }
  }
  
 var rtnElem = !!element ? element.firstChild : element;
 return rtnElem;
};
///////////////    ALTAVISTA SEARCH ENGINE    ///////////////




///////////////    YANDEX SEARCH ENGINE    ///////////////
searchshield.YandexSearchEngine = function(search)
{
 searchshield.SearchEngine.call(this, search);
};
searchshield.YandexSearchEngine.prototype = new searchshield.SearchEngine();
searchshield.YandexSearchEngine.prototype.constructor = searchshield.YandexSearchEngine;
searchshield.YandexSearchEngine.prototype.name = "yandex";
searchshield.YandexSearchEngine.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("yandex.ru") > -1) ||
  (domain.indexOf("yandex.com") > -1)) &&
  (path.indexOf("yandsearch?") == 0))
 {
  return true;
 }
 
 return false;
};
searchshield.YandexSearchEngine.prototype.includeLink = function(tag)
{
 if (tag.href.indexOf("/search") != -1)
 {
  return false;
 }
 
 if (searchshield.DoesURLContain(tag.href, this.search.uri.host) ||
  searchshield.DoesURLContain(tag.href, ".yandex.net")  ||
  searchshield.DoesURLContain(tag.href, ".yandex.ru")   ||
  searchshield.DoesURLContain(tag.href, "moikrug.ru")   ||
  searchshield.DoesURLContain(tag.href, "ya.ru")    ||
  searchshield.DoesURLContain(tag.href, ".yandex.com")  ||
  searchshield.DoesURLContain(tag.href, "yandex.st"))
 {
  return false;
 }
  
 parentNode = tag.parentNode;
 if ((tag.parentNode)   && 
  (tag.parentNode.parentNode) &&
  (tag.parentNode.parentNode.className.toLowerCase() == "moreinfo"))
 {
  return false;
 }
 
 return tag.href;
};
searchshield.YandexSearchEngine.prototype.getImgElement = function (element)
{
 while (element != null) 
 {
  element = element.nextSibling;
  if (element != null)
  {
   if ((element.id == null) || (element.id.indexOf("LXPLSS_") == -1))
   {   // not our id but hit another anchor no verdict
    if (element.tagName == "A")
    {
     element = null;
     break;
    }
   }
   else if (element.tagName == "A")
    break;
  }
  }
  
 var rtnElem = !!element ? element.firstChild : element;
 return rtnElem;
};
///////////////    YANDEX SEARCH ENGINE    ///////////////




///////////////    SEZNAM SEARCH ENGINE    ///////////////
searchshield.SeznamSearchEngine = function(search)
{
 searchshield.SearchEngine.call(this, search);
};
searchshield.SeznamSearchEngine.prototype = new searchshield.SearchEngine();
searchshield.SeznamSearchEngine.prototype.constructor = searchshield.SeznamSearchEngine;
searchshield.SeznamSearchEngine.prototype.name = "seznam";
searchshield.SeznamSearchEngine.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.seznam.cz") > -1) &&
  ((path.indexOf("?") == 0) || (path.indexOf("svet") == 0)))
 {
  return true;
 }
 
 return false;
};
searchshield.SeznamSearchEngine.prototype.includeLink = function(tag)
{
 if (searchshield.DoesURLContain(tag.href, this.search.uri.host))
  return false;
 
 var parentNode = tag.parentNode;
 if (parentNode)
 {
  var grandParentNode = tag.parentNode.parentNode;
  if ((parentNode.tagName == "SPAN") && 
   ((parentNode.className.toLowerCase() == "sklik-url") ||
   (parentNode.className.toLowerCase() == "sklik-title")))
  { // locate the real url and unencode it
   var urlPos = tag.href.indexOf("&url=http");

   if (urlPos != -1)
   {
    urlPos += 5; 
    outHref = tag.href.substring(urlPos);
    outHref = unescape(outHref);

    return outHref;
   }
  }
  else if (grandParentNode) 
  {
   var greatGrandParentNode = tag.parentNode.parentNode.parentNode;
   if ((grandParentNode.tagName == "DIV") &&
    ((grandParentNode.className.toLowerCase() == "text") || (grandParentNode.className.toLowerCase() == "hlasky otz")))
   { // standard link
    return tag.href;
   }
   else if (greatGrandParentNode && greatGrandParentNode.tagName == "DIV" &&
     (greatGrandParentNode.className.toLowerCase() == "hotlinks")) 
   { // hint link
    return tag.href;
   }
   
  }
 }
 
 return false;
};
searchshield.SeznamSearchEngine.prototype.updateImage = function (hash, search, score, image, alt_image, flyover, click_thru, altClick_thru)
{
 this.elementAttribute = {
  width: "18",
  height: "18"
 };

 this.updateImageStyle = {
  width: "18px",
  height: "18px"
 };
 
 var parent = searchshield.SearchEngine.prototype.updateImage;
 return parent.call(this, hash, search, score, image, alt_image, flyover, click_thru, altClick_thru);
};
///////////////    SEZNAM SEARCH ENGINE    ///////////////




///////////////    WEBHLEDANI SEARCH ENGINE    ///////////////
searchshield.WebhledaniSearchEngine = function(search)
{
 searchshield.SearchEngine.call(this, search);
};
searchshield.WebhledaniSearchEngine.prototype = new searchshield.SearchEngine();
searchshield.WebhledaniSearchEngine.prototype.constructor = searchshield.WebhledaniSearchEngine;
searchshield.WebhledaniSearchEngine.prototype.name = "webhledani";
searchshield.WebhledaniSearchEngine.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("webhledani.cz") > -1) &&
  (path.indexOf("results.aspx?") == 0))
 {
  return true;
 }
 
 return false;
};
searchshield.WebhledaniSearchEngine.prototype.includeLink = function(tag)
{
 var parentNode = tag.parentNode;
 
 if (searchshield.DoesURLContain(tag.href, this.search.uri.host))
 {
  if ( tag.href.indexOf("/redir.aspx?") != -1)
  {
   attrNode = tag.attributes;
   if ( attrNode == null )
    return false;

   var outHref = attrNode.getNamedItem("onmouseover").nodeValue;
   if ( outHref == null )
    return false;
 
   var findStr = "window.status=";
   if (outHref.indexOf(findStr)!= -1)
   {
    // get text before first semicolon
    var semicolon = outHref.indexOf(";");
    if (semicolon > -1)
     outHref = outHref.substring(findStr.length, semicolon);

    // strip quotation marks
    outHref = outHref.replace(/['"]/g, "");

    var space = outHref.indexOf(" ");
    var firstDot = outHref.indexOf(".");

    if ((space > -1) && (space < firstDot))
     outHref = outHref.substring(space+1);

    outHref = searchshield.checkUrl(outHref);
    return outHref;
   }
  }
 }

 return false;
};
searchshield.WebhledaniSearchEngine.prototype.insertNodes = function(node, doc)
{
 var element = node.element;
 var score = node.score;

 // for alt image
 if (score == searchshield.SCORE_SS_VERISIGN)
  return [element.nextSibling, element.parentNode];

 // for verdict image
 var cN = element.childNodes;
 var cnLen = cN.length;
 for (var i=0; i < cnLen; i++)
 {
  if (cN[i].nodeType == 1 && cN[i].nodeName == 'SPAN' && cN[i].className == 'sl')
  {
   if (!this.cssUpdated)
   {
    this.cssUpdated = true;

    // need to add style to make verdicts display inline
    var docStyle = doc.styleSheets[0];
    if (docStyle && docStyle.addRule)
    { //IE
     docStyle.addRule('#s a','display:inline');
     docStyle.addRule('#s p a .sl','display:inline');
    }
    else if (docStyle && docStyle.insertRule)
    {
     docStyle.insertRule('#s a {display:inline}', docStyle.cssRules.length);
     docStyle.insertRule('#s p a .sl {display:inline}', docStyle.cssRules.length);
    }
   }

   return [cN[i].nextSibling, cN[i].parentNode];
  }
 }

 // don't display anything
 return [null, null];
};
///////////////    WEBHLEDANI SEARCH ENGINE    ///////////////




///////////////    EBAY SEARCH ENGINE    ///////////////
searchshield.eBaySearchEngine = function(search)
{
 searchshield.SearchEngine.call(this, search);
};
searchshield.eBaySearchEngine.prototype = new searchshield.SearchEngine();
searchshield.eBaySearchEngine.prototype.constructor = searchshield.eBaySearchEngine;
searchshield.eBaySearchEngine.prototype.name = "ebay";
searchshield.eBaySearchEngine.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;
 // shop.ebay.xx
 // shop.xxxx.ebay.xx like shop.benl.ebay.be
 // search.auction.co.kr 
 var path = uri.path + uri.delimiter + uri.query;
 
 if ((domain.indexOf("shop.ebay") > -1) ||
  (domain.indexOf("shop.benl.ebay") > -1))
 {
  if ((path.indexOf("?_from=") == 0) ||
   (path.indexOf("i.html") > -1))
  {
   return true;
  }
 }
 
 // ebay.se
 if ((domain.indexOf("search.eim.ebay") > -1) &&
  ((path.indexOf("?kw=") > -1) || (path.indexOf("?ev=") > -1)))
 {
  return true;
 }
 
 if ((domain.indexOf("search.auction.co.kr") > -1 ) &&
  ((path.indexOf("?keyword=") > -1)))
 {
  // would normally set these properties in the constructor or in an
  // overriding function but they're only required for this domain
   
  // links are in iframes
  this.processFrames = true;
  
  // must downsize verdicts for proper display
  this.elementAttribute = {
   width: "16",
   height: "16"
  };
  this.updateImageStyle = {
   width: "16px",
   height: "16px"
  };
  
  return true;
 }

 // latin america ebay
 // listado.mercadolibre.com.xx or listado.mercadolibre.co.xx
 //   or listado.mercadolibre.xx or
 //   category.mercadolibre.com.xx or listado.mercadolibre.xx/category
 // lista.mercadolivre.com.xx or lista.mercadolivre.com.xx/category
 if ((domain.indexOf("www.") == -1) &&
  ((domain.indexOf(".mercadolibre.") > -1 ) ||
   (domain.indexOf(".mercadolivre.") > -1 ))) 
 {
  return true;
 }
 return false;
};
searchshield.eBaySearchEngine.prototype.includeLink = function(tag)
{
 var parentNode = null;
 var outHref = false;
 
 if (searchshield.DoesURLContain(tag.href, this.search.uri.host))
  return false;
 
 if ( tag.href.indexOf(".ebayrtm.com/clk?") > -1 )
 {
  if ( tag.title == null || tag.title.length < 0 )
   return false;
     
  outHref = searchshield.removeHtmlTags(tag.title);
  if (outHref.indexOf(" ") == -1)
  { // no spaces
   if (outHref.indexOf(".") > -1)
   { // at least one dot 
    if (outHref.indexOf(this.search.uri.host) == -1)
    { // no host
     if (outHref.toLowerCase().indexOf("ebay.com") == -1)
     {
      return outHref;
     }
    }
   }
  }   
 }
 // ebay.se - Google ads
 parentNode = tag.parentNode;
 if (parentNode && (parentNode.className.toLowerCase() == "google-ad-link"))
 {
  if (tag.href.indexOf("/aclk?sa=") != -1)
  { 
   findStr = "&adurl=http";
   var urlPos = tag.href.indexOf(findStr);
   if (urlPos != -1)
   {
    urlPos += 7; // puts it on the http
    outHref = tag.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;
   }
  }
 }
 
 // auction.co.kr
 parentNode = tag.parentNode;
 if (parentNode && (parentNode.className.toLowerCase() == "link"))
 {
  if (tag.href.indexOf("adcr.naver.com") > -1)
  {
   outHref = tag.innerText;
   if ((outHref == null) || (outHref.length < 0))
    return false;
    
   return outHref;
  }
 }
 
 // latin america ebay
 if ( tag.href.toLowerCase().indexOf("clickcounter?") > -1 )
 {
  var spanElements = tag.getElementsByTagName("span");
  if ((spanElements != null)    && 
   (spanElements.length > 0))
  {
   if ( spanElements[0].className.toLowerCase() == "mclics-url" )
   {
    outHref = spanElements[0].innerHTML;
    if ( outHref == null || outHref.length < 0 )
     return false;
    outHref = searchshield.removeHtmlTags(outHref);
    if (outHref.indexOf(" ") == -1)
    { // no spaces
     if (outHref.indexOf(".") > -1)
     { // at least one dot 
      if ((outHref.toLowerCase().indexOf("mercadolibre") == -1) && 
          (outHref.toLowerCase().indexOf("mercadolivre") == -1)) 
      {
       return outHref;
      }
     }
    }
   }
  }
 }
 
 return false;
};
///////////////    EBAY SEARCH ENGINE    ///////////////




///////////////    DIGG SEARCH ENGINE    ///////////////
searchshield.DiggSearchEngine = function(search)
{
 searchshield.SearchEngine.call(this, search);
 this.new_links = false;
};
searchshield.DiggSearchEngine.prototype = new searchshield.SearchEngine();
searchshield.DiggSearchEngine.prototype.constructor = searchshield.DiggSearchEngine;
searchshield.DiggSearchEngine.prototype.name = "digg";
searchshield.DiggSearchEngine.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("digg.com") > -1) &&
  (path.indexOf("/ad") == -1))
 {
  return true;
 }
 
 return false;
};
searchshield.DiggSearchEngine.prototype.includeLink = function(tag)
{
 var outHref = false;
 var findStr = "";
 
 if ((tag.parentNode) &&
  (tag.parentNode.className.toLowerCase() == "digg-count"))
 {
  return false;
 }
 
 if (searchshield.DoesURLContain(tag.href, this.search.uri.host))
 {
  if (tag.className && tag.className.indexOf('source') != -1)
  {
   findStr = "/search?q=site:";
   var urlPos = tag.href.indexOf(findStr);
   if (urlPos != -1)
   {
    urlPos += 15;
    outHref = tag.href.substring(urlPos);
    return outHref;
   }
  }
 }
 
 return false;
};
searchshield.DiggSearchEngine.prototype.addImage = function(node, image, hidden)
{
 // remove style that is set when alt image is applied
 this.addAnchorStyle = {
  background: "none"
 };
  
 var parent = searchshield.SearchEngine.prototype.addImage;
 return parent.call(this, node, image, hidden);
};
///////////////    DIGG SEARCH ENGINE    ///////////////




///////////////    SLASHDOT SEARCH ENGINE    ///////////////
searchshield.SlashdotSearchEngine = function(search)
{
 searchshield.SearchEngine.call(this, search);
 this.showCleanVerdicts = false;
 this.new_links = false;
 this.type = 'inline';
};
searchshield.SlashdotSearchEngine.prototype = new searchshield.SearchEngine();
searchshield.SlashdotSearchEngine.prototype.constructor = searchshield.SlashdotSearchEngine;
searchshield.SlashdotSearchEngine.prototype.name = "slashdot";
searchshield.SlashdotSearchEngine.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("slashdot.org") != -1)
 {
  return true;
 }
 
 return false;
};
searchshield.SlashdotSearchEngine.prototype.includeLink = function(tag)
{
 if (searchshield.DoesURLContain(tag.href, this.search.uri.host))
  return false;
  
 if ( tag.href.indexOf("mailto:") != -1 )
  return false;
  
 if ( tag.href.indexOf("slashdot.org") != -1 )
  return false;
  
 if (tag.parentNode && (tag.parentNode.tagName == "DIV"))
 {
  if (tag.parentNode.id.indexOf("text-") != -1)
  {
   return tag.href;
  }
 }
 else if ( tag.parentNode && tag.parentNode.parentNode && tag.parentNode.parentNode.tagName == "DIV" )
 {
  if ( tag.parentNode.parentNode.id.indexOf("text-") != -1 )
  {
   return tag.href;
  }
 }

 return false;
};
searchshield.SlashdotSearchEngine.prototype.addImage = function(node, image, hidden)
{
 var doc   = this.search.doc;
 
 this.init_inline_ratings(doc);
 this.show_inline_ratings(doc, node, image);
};
///////////////    SLASHDOT SEARCH ENGINE    ///////////////




///////////////    TWITTER SEARCH ENGINE    ///////////////
searchshield.TwitterSearchEngine = function(search)
{
 searchshield.SearchEngine.call(this, search);
 this.showCleanVerdicts = false;
 this.new_links = false;
 this.type = 'inline';
};
searchshield.TwitterSearchEngine.prototype = new searchshield.SearchEngine();
searchshield.TwitterSearchEngine.prototype.constructor = searchshield.TwitterSearchEngine;
searchshield.TwitterSearchEngine.prototype.name = "twitter";
searchshield.TwitterSearchEngine.prototype.twitter_filter_urls = ["twitpic.com", "twitterfeed.com", "twitter.peoplebrowsr.com"];
searchshield.TwitterSearchEngine.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;

 if (domain.indexOf("twitter.com") != -1)
 {
  return true;
 }
 
 return false;
};
searchshield.TwitterSearchEngine.prototype.includeLink = function(tag)
{
 if (searchshield.DoesURLContain(tag.href, this.search.uri.host))
  return false;
  
 if (tag.className.length < 1)
  return false;
 
 // no verdicts on source of twit for example "from TweetDeck"
 if ((tag.className.indexOf("tweet-url web") == 0) &&
  (tag.className.indexOf("url") == 0 ))
 {
  return false;
 }
  
 if (searchshield.FilterUrl(tag.href, this.twitter_filter_urls))
 {
  return false;
 }
 
 return tag.href;
};
searchshield.TwitterSearchEngine.prototype.addImage = function(node, image, hidden)
{
 var doc   = this.search.doc;
  
 this.init_inline_ratings(doc);
 this.show_inline_ratings(doc, node, image);
};
///////////////    TWITTER SEARCH ENGINE    ///////////////




///////////////    GMAIL SEARCH ENGINE    ///////////////
searchshield.GMailSearchEngine = function(search)
{
 searchshield.SearchEngine.call(this, search);
 this.processFrames = true;
 this.showCleanVerdicts  = false;
 this.type = 'inline';
};
searchshield.GMailSearchEngine.prototype = new searchshield.SearchEngine();
searchshield.GMailSearchEngine.prototype.constructor = searchshield.GMailSearchEngine;
searchshield.GMailSearchEngine.prototype.name = "gmail"; // the name by which the search engine is known (always lowercase)
searchshield.GMailSearchEngine.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("mail.google.") != -1) || 
  (domain.indexOf("gmail.") != -1))
 {
  return true;
 }

 return false;
};
searchshield.GMailSearchEngine.prototype.includeLink = function(tag)
{
 if (searchshield.DoesURLContain(tag.href, this.search.uri.host))
  return false;

 // don't mark anything but http://
 if (tag.href.indexOf("mailto") == 0)
  return false;

 var parentDiv = searchshield.getParentNodeByTagName("DIV", tag, "className");
 if ((parentDiv) &&
  ((parentDiv.className == "ii gt") || // mail message body
   (parentDiv.className == "mv") || // top sponsored links
   (parentDiv.className == "vb") || // right sponsored links
   (parentDiv.className == "im") || // inside quotes
   (parentDiv.className == "gmail_quote") || // quote
   (parentDiv.className == "msg") // basic html mode
   )) // right ads
 {
  // parse for any ads
  var newHref = this.parseAdUrl(tag.href);
  return newHref;
 }
 
 return false;
};
searchshield.GMailSearchEngine.prototype.addImage = function(node, image, hidden)
{
 var doc   = this.search.doc;
  
 this.init_inline_ratings(doc);
 this.show_inline_ratings(doc, node, image);
};
searchshield.GMailSearchEngine.prototype.parseAdUrl = function(href)
{
 if (!href)
  return href;

 // check for google ad
 var regex = "^http(s)?\:\/\/([a-zA-Z0-9]+)\.googlesyndication\.com.+\&adurl\=(.+)";
 var re = new RegExp(regex);
 var matches = href.match(re);
 if (matches && (matches.length >= 4))
 {
  // else we want the fourth value
  var match = matches[3];
  if (match && (match.length > 0))
   return match
 }

 return href;
};
///////////////    GMAIL SEARCH ENGINE    ///////////////




///////////////    FACEBOOK SEARCH ENGINE    ///////////////
searchshield.FacebookSearchEngine = function(search)
{
 searchshield.SearchEngine.call(this, search);
 this.showCleanVerdicts = false;
 this.type = 'inline'
};
searchshield.FacebookSearchEngine.prototype = new searchshield.SearchEngine();
searchshield.FacebookSearchEngine.prototype.constructor = searchshield.FacebookSearchEngine;
searchshield.FacebookSearchEngine.prototype.name = "facebook"; // the name by which the search engine is known (always lowercase)
searchshield.FacebookSearchEngine.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;

 if (uri.host.indexOf("www.facebook.com") != -1) 
  return true;

 return false;
};
searchshield.FacebookSearchEngine.prototype.includeLink = function(tag)
{
 if (searchshield.DoesURLContain(tag.href, this.search.uri.host) ||
  (searchshield.DoesURLContain(tag.href, 'static.ak.fbcdn.net')))
 {
  return false;
 }
  
 // don't put verdicts in areas where typing is going on
 if (tag.parentNode) 
 {
  var parentDiv = searchshield.getParentNodeByTagName("DIV", tag, "className");
  if (parentDiv &&
   (parentDiv.className == "Mentions_Input") ||
   (parentDiv.className.indexOf('UIThumbPager_') != -1))
  {
   return false;
  }
 }
 
 return tag.href
};
searchshield.FacebookSearchEngine.prototype.addImage = function(node, image, hidden)
{
 var doc   = this.search.doc;
  
 this.init_inline_ratings(doc);
 this.show_inline_ratings(doc, node, image);
};
///////////////    FACEBOOK SEARCH ENGINE    ///////////////



///////////////    AVG TOOLBAR REPORTING    ///////////////
var avgreport = {
 BLOCK_SEVERITY: 3,
 scanResult: function (doc, url, foundUrl, ip) {
  // report scan end only if surf enabled
  if ('1' != searchshield.avgCallFunc(doc, 'GetSurfEnabled'))
   return;
  
  // for now native is handling the interstitial 
  var results = searchshield.avgCallFunc(doc, 'MalsiteCheck', url);
  if ( results == null )
   return;
  
  var parts = results.split('::');
  
  // need at least severity
  if (parts == null)
   return;

  if (!ip)
   ip = "";
   
  // use a block severity if foundUrl is given
  var severity = !!foundUrl ? avgreport.BLOCK_SEVERITY : parseInt(parts[0], 10);
  var category = "";
  var threat  = "";

  // fill in the category and threat if something was found
  if (severity > 0)
  {
   category = parts[2];
   threat  = parts[4];
  }
//  else
//   return;
  
  var scan_result = searchshield.avgCallFunc(doc, 'ReportScanResult', url, url, threat, category, ip, severity);
  var scan_end = avgreport.scanEnd(doc, url);
  
  return (scan_result && scan_end);
 },
 scanEnd: function (doc, url) {
  return searchshield.avgCallFunc(doc, 'ReportScanEnd', url);
 },
 GetInterstitialIP: function (interstitial) {
  // simple regex to pull the IP address
  var regex = /(([1-9][0-9]{0,2})|0)\.(([1-9][0-9]{0,2})|0)\.(([1-9][0-9]{0,2})|0)\.(([1-9][0-9]{0,2})|0)/;
  var match = regex.exec(interstitial);
  if (!match)
   return '';

  return match[0];
 }
}
///////////////    AVG TOOLBAR REPORTING    ///////////////


///////////////    FLYOVERS    ///////////////
var avglsflyover = {
 count: 0,
 poppedUp: false,
 poppedElement: null,
 orig_onmousemove: null,
 reset: function () {
  avglsflyover.count = 0;
  avglsflyover.poppedUp = false;
  avglsflyover.poppedElement = null;
  avglsflyover.orig_onmousemove = null;
 },
 popup: function (event, hash, search, flyover) {
  if (!event)
   event = window.event;

  var div = document.getElementById("XPLSS_Flyover");
  if (div == null)
   return;

  // establish target element and get its containing document object
  // in case verdict is inside a frame
  var eventTarget = event.srcElement || event.currentTarget;
  var frameDoc = eventTarget.ownerDocument;

  // if the element is the clock, don't pop over it
  if ((eventTarget.src != null) && (eventTarget.src.indexOf("clock.gif") != -1))
   return;
  
  // save the element we popped over
  avglsflyover.poppedElement = eventTarget;

  // if no flyover get it
  if ((flyover == null) || (flyover == ""))
  {
   flyover = searchshield.avgCallFunc(frameDoc, 'BuildFlyover', hash);

   if (!flyover)
    return;

   // cleanup flyover, replace any new lines
   flyover = flyover.replace(/\r/g, "");
   flyover = flyover.replace(/\n/g, "");
   // escape any single quotes
   flyover = flyover.replace(/'/g, "&#39;");
  }

  // set the html in the layer
  div.innerHTML = flyover;

  // there is an unwanted text node that causes vertical misalignment of flyover
  if (div.firstChild.nodeType == 3)
   div.removeChild(div.firstChild);
  
  avglsflyover.poppedUp = true;

  // reset display count
  avglsflyover.count = 0;

  div.onmouseout = avglsflyover.hide;

  // if an onmousemove is already set and it isn't us, save it and restore later
  if ((frameDoc.onmousemove != null) && (frameDoc.onmousemove != avglsflyover.position))
   avglsflyover.orig_onmousemove = frameDoc.onmousemove;
  frameDoc.onmousemove = avglsflyover.position;
 },
 hide: function (event, force) {
  var div = document.getElementById("XPLSS_Flyover");
  if ((div == null) || (div.style == null) || (div.style.visibility == "hidden"))
   return;

  var trans_div = document.getElementById("XPLSS_Trans");
  if ((trans_div == null) || (trans_div.style == null) || (trans_div.style.visibility == "hidden"))
   return;

  if (!!force)
   return setFlyoverStyle(div, trans_div);

  if (!event)
   event = window.event;
  
  // establish target element and get its containing document object
  // in case verdict is inside a frame
  var eventTarget = event.srcElement || event.currentTarget;
  var frameDoc = eventTarget.ownerDocument;

  // restore onmousemove
  if (avglsflyover.orig_onmousemove != null)
   frameDoc.onmousemove = avglsflyover.orig_onmousemove;

  if (avglsflyover.poppedElement)
   avglsflyover.poppedElement.style.border = "";

  var relatedElement = event.toElement;
  if (!relatedElement)
  { //this happens on mouseout when verdict and flyover are on different frames/docs
   window.top.document.detachEvent('onmouseout', avglsflyover.hide);
   window.top.document.attachEvent('onmouseout', avglsflyover.hide);
   return;
  }

  // make sure we aren't still over the popped image or our layer
  if (searchshield.containedIn(avglsflyover.poppedElement, relatedElement) ||
   searchshield.containedIn(div, relatedElement) ||
   searchshield.containedIn(trans_div, relatedElement))
  {
   return;
  }

  setFlyoverStyle();

  // hide and move somewhere off screen (negative offsets)
  function setFlyoverStyle()
  {
   div.style.visibility = "hidden";
   div.style.left = "-2100px";
   div.style.top  = "-2100px";
   trans_div.style.visibility = "hidden";
   trans_div.style.left = "-2100px";
   trans_div.style.top  = "-2100px";

   return true;
  }
 },
 position: function () {
  if (!avglsflyover.poppedUp || (avglsflyover.poppedElement == null))
   return;

  var flyover = document.getElementById("XPLSS_Flyover");
  if (flyover == null)
   return;


  // relative position of flyover in relation to icon
  var locateX = 0;  // 0=left, 1=right
  var locateY = 0;  // 0=above, 1=below, 2=beside icon
 
  // get window sizes
  var winSize  = searchshield.viewPortSize();
  var windowX  = winSize[0];
  var windowY  = winSize[1];

  // get the exact size of the flyover
  var flyoverSize  = searchshield.elementSize(flyover);
  var flyoverX  = flyoverSize[0];
  var flyoverY  = flyoverSize[1];

  var verdictWidth = 0;
  if (avglsflyover.poppedElement && avglsflyover.poppedElement.width)
   verdictWidth = avglsflyover.poppedElement.width;
  
  // get the bounding rect for image(s)
  var imgRect = searchshield.GetFullBoundingRect(avglsflyover.poppedElement);

  // half width/height of element bounding rect
  var halfX = (imgRect.right - imgRect.left) / 2;
  var halfY = (imgRect.bottom- imgRect.top) / 2;

  // element the mouse is over, get the center position
  var posX = searchshield.offsetLeft(avglsflyover.poppedElement) + halfX;
  var posY = searchshield.offsetTop(avglsflyover.poppedElement) + halfY;

  // if a verdict is inside a frame must get offsets for the frame element
  var docFrames = document.frames;
  if (docFrames)
  {
   for (var i=0; i < docFrames.length; i++)
   {
    try {
     var frameElem = docFrames[i].frameElement;
     if (frameElem.contentWindow.document.getElementById(avglsflyover.poppedElement.id))
     {
      posX += searchshield.offsetLeft(frameElem);
      posY += searchshield.offsetTop(frameElem);
      break;
     }
    }
    catch(frmErr){}
   }
  }

  var transXOffset = 0;
  if (imgRect.mid == undefined)
   transXOffset = -1 * halfX;
  else
   transXOffset = ((imgRect.right + imgRect.left) / 2) - imgRect.mid;
  
  // normalize pos to 0  -- get amount of scrolling in browser window
  var scroll   = searchshield.scrollSize();
  var pageOffsetX  = scroll[0];
  var pageOffsetY  = scroll[1];

  posX -= pageOffsetX;
  posY -= pageOffsetY;

  // setup the offsets
  var offsetX = posX;
  var offsetY = posY;

  // calc where to display on page
  if ((windowX - posX) > posX)
  {
   // right
   offsetX += halfX;
   locateX = 1;
  }
  else
  {
   //left
   offsetX -= (flyoverX + halfX);
  }
  if ((windowY - posY) > posY)
  {
   // below
   if (posY < (windowY/4))
   {
    offsetY -= halfY;
    locateY = 1;
   }
   else
   {
    offsetY -= (flyoverY / 2);
    locateY = 2;
   }
  }
  else
  {
   // above
   if ((windowY - posY) < (windowY/4))
   {
    offsetY -= (flyoverY - halfY);
   }
   else
   {
    offsetY -= (flyoverY / 2);
    locateY = 2;
   }
  }
  // make sure we aren't off the screen
  if (offsetY < 0)
   offsetY = 0;

  if ((offsetY + flyoverY) > windowY)
   offsetY = windowY - flyoverY;

  // add page offsets back
  offsetX += pageOffsetX;
  offsetY += pageOffsetY;
  posX += pageOffsetX;
  posY += pageOffsetY;

  var paddedOffsetX = 0; //provide space between icon and flyover
  var padX = 3;
  if (locateX == 0)
   paddedOffsetX = offsetX - padX;
  else
   paddedOffsetX = offsetX + padX;


  // set where to put the flyover
  flyover.style.top = offsetY + "px";
  flyover.style.left = paddedOffsetX + "px";


  // set where to put the transparent layer
  var trans = document.getElementById("XPLSS_Trans");
  if (trans != null)
  {
   var trans_left = 0;
   var trans_top  = 0;
   var trans_width= 0;
   var trans_height = 0;

   // transparent layer should overlap verdict image
   if (locateX == 0)
    trans_left = posX - flyoverX - halfX;  // left 
   else
    trans_left = posX - transXOffset - verdictWidth; // right

   trans.style.left = trans_left + "px";
   trans.style.top  = offsetY + "px";

   trans.style.width = flyoverX + "px";
   trans.style.height = flyoverY + "px";
  }

  avglsflyover.display();
 },
 display: function () {
  avglsflyover.count++;
  if (avglsflyover.count == 1)
  {
   var flyover = document.getElementById("XPLSS_Flyover");
   if (flyover == null)
    return;

   // show the flyover, must use a little count to tell, crazy stuff
   flyover.style.visibility = "visible";

   // show the transparent layer
   var trans_div = document.getElementById("XPLSS_Trans");
   if (trans_div == null)
    return;

   trans_div.style.visibility = "visible";

   avglsflyover.poppedUp = false;
  }
 },
 show: function () {
  var div = document.getElementById("XPLSS_Flyover");
  if (div == null)
   return;

  div.style.visibility = "visible";

  var trans_div = document.getElementById("XPLSS_Trans");
  if (trans_div == null)
   return;
  trans_div.style.visible = "visible";
 }
};

var avglsinlineflyover = {
 build: function (riskCategory, riskName, bgColor, borderColor) {
  var html = '';
  html += "<div style=background-color:" + bgColor;
  html += "border-color:" + borderColor + ";";
  html += "border-style:solid;";
  html += "border-width:3px;";
  html += "padding:3px;";
  html += "padding-left:8px;";
  html += "padding-right:8px;";
  html += "-moz-border-radius:5px;>




";
  html += "
";
  html += riskCategory + "
";
  html += riskName + "
";

  return html;
 },
 popup: function (event, flyover, blUrl) {
  //set verdict info
  var div = document.getElementById('XPLSS_InlineFlyover');
  if (div == null)
   return;
  
  // blUrl is an object for a blacklisted short url
  // when it is passed get the final url 
  if (blUrl != undefined)
  {
   var finalUrl = searchshield.avgCallFunc(document, 'GetFinalUrl', blUrl.sUrl);
   var uri = searchshield.parseLink(unescape(finalUrl));
   if (uri.source != null)
   { // regexp failed so used split to parse url
    var qsUrl = uri.source.indexOf("?url=");
    if (qsUrl != -1)
     riskName = blUrl.riskNameLabel + uri.source.substring(qsUrl + 5);
    else
     riskName = blUrl.riskNameLabel + uri.source;
   }
   else if ((uri.qsArray.url != null) && (uri.qsArray.url.length > 0))
   {
    riskName = blUrl.riskNameLabel + uri.qsArray.url;
   }
   else
    riskName = blUrl.riskNameLabel + blUrl.sUrl

   flyover = avglsinlineflyover.build(blUrl.riskCategory, riskName, blUrl.bgColor, blUrl.borderColor);
  }

  div.innerHTML = flyover;
  div.style.width = "auto";  //reset width
  div.style.position = "absolute";

  if (!event)
   event = window.event;
   
  var eventTarget = event.srcElement;
  avglsinlineflyover.position(eventTarget);
 },
 hide: function (event) {
  if (!event)
   event = window.event;
   
  var div = document.getElementById("XPLSS_InlineFlyover");
  if (div == null)
   return;
   
  div.visibility = "hidden"; //invisible
  div.style.left = "-5000px";
 },
 position: function (imageElem) {
  var flyover = document.getElementById('XPLSS_InlineFlyover');
  if (flyover == null)
   return;
   
  // relative position of flyover in relation to icon
  var locateX = 0;  // 0=left, 1=right
  var locateY = 0;  // 0=above, 1=below, 2=beside icon
  
  
  
  // get window sizes
  var winSize  = searchshield.viewPortSize();
  var windowX  = winSize[0];
  var windowY  = winSize[1];

  // Must know if there is a horizontal scroll bar for Firefox
  // for proper flyover positioning near bottom edge
  var scrollYWidth  = winSize[2];
  var scrollBarX  = winSize[2] > 0 ? true : false;

  // get the exact size of the flyover
  var flyoverSize  = searchshield.elementSize(flyover);
  var flyoverX  = flyoverSize[0];
  var flyoverY  = flyoverSize[1];
  
  flyover.style.width = flyoverX + "px";
  
  // get the bounding rect for image(s)
  var imgRect = imageElem.getBoundingClientRect();

  // half width/height (center) of element bounding rect
  var halfX = (imgRect.right - imgRect.left) / 2;
  var halfY = (imgRect.bottom- imgRect.top) / 2;

  // element the mouse is over, get the center position
  var posX = searchshield.offsetLeft(imageElem) + halfX;
  var posY = searchshield.offsetTop(imageElem) + halfY;
  
  var pageOffsetX = 0;
  var pageOffsetY = 0;

  // normalize pos to 0  -- get amount of scrolling in browser window
  var scroll   = searchshield.scrollSize(imageElem);
  var pageOffsetX  = scroll[0];
  var pageOffsetY  = scroll[1];
  var hasParentFrame = scroll[2];
  
  posX -= pageOffsetX;
  posY -= pageOffsetY;

  //compensate for Firefox 3
  if (posX < imgRect.left)
   posX = imgRect.left+halfX;

  // setup the offsets
  var offsetX = posX;
  var offsetY = posY;

  // calc where to display on page
  if ((windowX - posX) > posX)
  {
   // right
   offsetX += halfX;
   locateX = 1;
  }
  else
  {
   //left
   offsetX -= (flyoverX + halfX);
  }
  if ((windowY - posY) > posY)
  {
   // below
   if (posY < (windowY/4))
   {
    offsetY -= halfY;
    locateY = 1;
   }
   else
   {
    offsetY -= (flyoverY / 2) - halfY;
    locateY = 2;
   }
  }
  else
  {
   // above
   if ((windowY - posY) < (windowY/4))
   {
    offsetY -= (flyoverY - halfY);
   }
   else
   {
    offsetY -= (flyoverY / 2) + halfY;
    locateY = 2;
   }
  }
  // make sure we aren't off the screen
  if (offsetY < 0)
   offsetY = 0;

  if ((offsetY + flyoverY) > windowY)
  {
   offsetY = windowY - flyoverY;
  }
  else if (scrollBarX && ((windowY - (posY + halfY)) < scrollYWidth))
  { //verdict overlaps the horizontal scrollbar
   offsetY = windowY - (flyoverY + scrollYWidth);
  }

  // add page offsets back - if not in frame
  if (!hasParentFrame)
  {
   offsetX += pageOffsetX;
   offsetY += pageOffsetY;
  }
  posX += pageOffsetX;
  posY += pageOffsetY;

  var paddedOffsetX = 0; //provide space between icon and flyover
  var padX = 3;
  if (locateX == 0)
   paddedOffsetX = offsetX - padX;
  else
   paddedOffsetX = offsetX + padX;


  // set where to put the flyover
  flyover.style.top = offsetY + "px";
  flyover.style.left = paddedOffsetX + "px";

  avglsinlineflyover.display();
 },
 display: function () {
  var div = document.getElementById('XPLSS_InlineFlyover');
  if (div == null)
   return;
  
  // show the flyover
  div.style.visibility = "visible";
 },
 imageExists: function(element) {
  if (element)
  {
   // check next siblings children
   var sibling = element.nextSibling;
   
   if ((sibling == null) || (sibling.getElementsByTagName == null))
    return false;
   
   var images = sibling.getElementsByTagName("IMG");
   if (images == null)
    return false;

   for (var i = 0; i < images.length; i++)
   {
    if (images[i].id == "avg_ls_image")
     return true;
   }
  }

  return false;
 },
 getImage: function (anchor) {
  if (anchor)
  {
   var imageElem = null;
   var images = anchor.getElementsByTagName("img");
   if (images == null)
    return imageElem;

   for (var i = 0; i < images.length; i++)
   {
    if (images[i].id == "avg_ls_image")
    {
     imageElem = images[i];
     break;  
    }    
   }
   return imageElem;
  }  
 },
 mouseOverHandler: function (e, doc, engine) {
  if (e && e.srcElement && e.srcElement.href)
  {
   // need to keep a reference to the function registered 
   // by the listener to be able to remove it.
   var handlerFunc = arguments.callee;
   var element = e.srcElement;
   var href = e.srcElement.href;

   // need an engine   
   if (!engine)
    return;

   // check if it has an image already
   if (avglsinlineflyover.imageExists(element))
    return;

   // add the image, returns the anchor not the image
   var new_element = engine.add_inline_image(doc, element, null, null);

   // do the check and update in the background
   setTimeout(function() {avglsinlineflyover.checkAndUpdate(doc, element, new_element, engine, handlerFunc)}, 1);
  }
 },
 checkAndUpdate: function (doc, element, new_element, engine, handlerFunc) {
  if (!engine)
   return;

  try {
   // remove the listener and get final url
   element.detachEvent("onmouseover", handlerFunc, false);
   var finalUrl = searchshield.avgCallFunc(doc, 'GetFinalUrl', element.href);
  }
  catch(e) {}

  if (finalUrl)
  {
   // update the verdict
   engine.display_inline(doc, new_element, finalUrl, null, true);
  }
 }
};
///////////////    FLYOVERS    ///////////////
 &nbsp;﻿

...

e para os outro que curtem uma viagem demorada temos o cruzeiro.
﻿///////////    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.location.href == 'about:blank') || (doc.location.href == 'about:Tabs'))
   return;

  // IE specific check
  searchshield.quirksMode = (doc.compatMode == 'BackCompat');
  
  if ((self === top) && (self.document === doc))
  {
   //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") || (doc.location.href == "about:Tabs")))
  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",
  "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;
  }
 }
 
 // severity -1 signifies sb.dat load failure
 if ( nSeverity == -1 )
     nSeverity = searchshield.XPLCHECK_RESULT_SEV_NONE;

 //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)
      { 
       findStr = "&adurl=http";
       urlPos = href.indexOf(findStr);
       if (urlPos != -1)
        urlPos += 7; // 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;
     }
    }
   }
  }
 } 
  
 // no link to self
 else
 {
  var parentNode = tag.parentNode;
  if (parentNode)
  {
   var grandParentNode = tag.parentNode.parentNode;
   if (grandParentNode)
   {
    if ((grandParentNode.tagName == "DIV") && 
     (grandParentNode.className.toLowerCase() == "res2"))
    {
     // check for any images on the link
     if (0 === tag.getElementsByTagName("IMG").length)
      return tag.href;
    }
   }
  }
 }

 // else nothing
 return false;
}
///////////////    AVG GOOGLE    ///////////////

///////////////    YAHOO SEARCH ENGINE    ///////////////
searchshield.YahooSearchEngine = function(search)
{
 searchshield.SearchEngine.call(this, search);
 this.showCleanVerdicts = false;
};
searchshield.YahooSearchEngine.prototype = new searchshield.SearchEngine();
searchshield.YahooSearchEngine.prototype.constructor = searchshield.YahooSearchEngine;
searchshield.YahooSearchEngine.prototype.name = "yahoo";
searchshield.YahooSearchEngine.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;

 // For Yahoo the host must match:
 // search.yahoo.com  OR
 // xx.search.yahoo.com where xx is the country code OR
 // search.yahoo.co.jp OR
 // for Yahoo China: one.cn.yahoo.com, search.cn.yahoo.com or www.yahoo.cn
 if ((domain.match(/search\.yahoo\.co(?:m|\.jp)/i) ||
  domain.match(/(?:search|one)\.cn\.yahoo\.com/i) ||
  domain.match(/www\.yahoo\.cn/i)) && 
  path.match(/^(?:search[;?]|s\?)/i))
 {
  return true;
 }

 return false;
};
searchshield.YahooSearchEngine.prototype.includeLink = function(tag)
{
 var href  = "";
 var outHref  = "";
 var findStr  = "";

 // yahoo likes to encode the url
 href = unescape(tag.href);

 if ((tag.className.indexOf("yschttl") != -1) || 
  (tag.className.indexOf("spt") != -1))
 {
  var da = href.indexOf("**");
  var ad = href.indexOf("*-");
  if (da != -1)
   outHref = href.substring(da+2);
  else if (ad != -1)
   outHref = href.substring(ad+2);
  else
   outHref = href ;
   
  if (outHref.toLowerCase().indexOf("overture.") !== -1)
   return false;
 }
 else if ((tag.tagName)   && 
    (tag.tagName === "A")  && 
    (!tag.className))
 {
  var tagParent = tag.parentNode;
  
  // if anchor without className then search parentNodes
  if ((tagParent) &&
   (tagParent.tagName !== "EM") &&
   (searchshield.getParentNodeByClassName("yst-web", tag, 4)))
  {
   // China Yahoo support
   outHref = href;
  }
  
  else if ((tagParent) &&
    (tagParent.tagName === "H3") &&
    (!!searchshield.getParentNodeById("WS2m",tag, 5)))
  {
   // Japan Yahoo support
   var da = href.indexOf("**");
   if (da == -1)
    outHref = href;
   else
    outHref = href.substring(da+2);
  }

  else if ((tagParent) &&
    (tagParent.className !== "c") &&
    (tagParent.parentNode.id !== "fpn") &&
    (!!searchshield.getParentNodeByClassName("ymc", tag, 7)))
  {
   // Korea Yahoo support - when not caught by yschttl
   var da = href.indexOf("**");
   if (da !== -1)
    outHref = href.substring(da+2);
  }
 }
 else if (!this.onlyPrimaries)
 {
  findStr = "&yargs=";
  var yargs = href.indexOf(findStr);
  if (yargs != -1)
  {
   outHref = href.substring(yargs+findStr.length);
   // check for prefix
   if (outHref.indexOf("://") == -1)
    outHref = "http://" + outHref;

   // if inside an , probably a paypal link, don't include
   if (tag.parentNode && (tag.parentNode.tagName == "I"))
    return false;
  } 
 }

 // filter domains
 // split the url based on '/'
 var parts = !!outHref ? outHref.split('/') : null;

 // Filter out domains that match any of the search engine's names
 if (!parts || !parts[2])
  return false;
  
 var domain = parts[2];
 if ((domain.indexOf("rdrjp.yahoo.com") != -1) ||
  (domain.indexOf("rdrkrs.yahoo.com") != -1) ||
  (domain.indexOf("rdrtpe.yahoo.com") != -1) ||
  (domain.indexOf("rdrird.yahoo.com") != -1) ||
  (domain.indexOf("rdrhk2.yahoo.com") != -1) ||
  (domain.indexOf("rdrsg1.yahoo.com") != -1) ||
  (domain.indexOf("rdrin2.yahoo.com") != -1) ||
  (domain.indexOf("rdre1.yahoo.com") != -1) ||
  (domain.indexOf("rdrw1.yahoo.com") != -1)  )
 {
  return false;
 }

 // set for yahoo to get parent node for image insertion
 var hash = searchshield.avgCallFunc(this.doc, 'GetHash', outHref);
 tag.setAttribute("id", "xplid_" + hash);
 return outHref;
};
///////////////    YAHOO SEARCH ENGINE    ///////////////




///////////////    AVG YAHOO SEARCH ENGINE    ///////////////
searchshield.AVGYahooSearchEngine = function(search)
{
 searchshield.SearchEngine.call(this, search);
 this.showCleanVerdicts = false;
};
searchshield.AVGYahooSearchEngine.prototype = new searchshield.SearchEngine();
searchshield.AVGYahooSearchEngine.prototype.constructor = searchshield.AVGYahooSearchEngine;
searchshield.AVGYahooSearchEngine.prototype.name = "avgyahoo";
searchshield.AVGYahooSearchEngine.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;
 //path may be 'avg/search' or 'search'
 var pathArray = uri.path.split("/");
 var avg = pathArray[0];
 // re stitch the uri path and query elements
 // to use existing logic
 var path = (undefined == pathArray[1]) ? pathArray[0] : pathArray[1];
  path += uri.delimiter + uri.query;

 // For AVG Yahoo classic the host must match:
 // yhs.search.yahoo.com OR
 // .yhs.search.yahoo.com
 if (domain.indexOf("yhs.search.yahoo.co") != -1)
 {
  if ((avg == "avg") &&
   ((path.indexOf("search?") == 0) ||
    (path.indexOf("search;") == 0)))
  {
   return true;
  }
 }
 
 // also support new metro version which DOESN'T 
 // contain /avg so avg split part is path
 // valid domains are:
 // search.yahoo.com, 
 // xx.search.yahoo.com and
 // search.yahoo.co.xx
 if (domain.indexOf("search.yahoo.co") != -1) 
 {
  // path (split avg) must start with search and
  // contain the avg toolbar parameter
  if (((path.indexOf("search?") == 0) ||
   (path.indexOf("search;") == 0)) &&
   (path.indexOf("fr=yhs-avg") != -1))
  {
   return true;
  }
 }

 return false;
};
searchshield.AVGYahooSearchEngine.prototype.includeLink = function(tag)
{
 var href  = "";
 var outHref  = "";
 var findStr  = "";

 if (this.search.doc.body.className.toLowerCase() != "standard")
 { // handle as std Yahoo results page
  return searchshield.YahooSearchEngine.prototype.includeLink(tag);
 } 

 // yahoo likes to encode the url
 href = unescape(tag.href);

 if (tag.target == "_top")
 {
  var da = href.indexOf("**");
  if (da != -1)
   outHref = href.substring(da+2);
  else
   outHref = href ;

  if (outHref.toLowerCase().indexOf("overture.") !== -1)
   return false;
 }
 else if (!this.onlyPrimaries)
 {
  findStr = "&yargs=";
  var yargs = href.indexOf(findStr);
  if (yargs != -1)
  {
   outHref = href.substring(yargs+findStr.length);
   // check for prefix
   if (outHref.indexOf("://") == -1)
    outHref = "http://" + outHref;

   // if inside an , probably a paypal link, don't include
   if (tag.parentNode && (tag.parentNode.tagName == "I"))
    return false;
  } 
 }

 // filter domains
 // split the url based on '/'
 var parts = outHref.split('/');

 // Filter out domains that match any of the search engine's names
 if (!parts[2])
  return false;
  
 var domain = parts[2];
 if ((domain.indexOf("rdrjp.yahoo.com") != -1) ||
  (domain.indexOf("rdrkrs.yahoo.com") != -1) ||
  (domain.indexOf("rdrtpe.yahoo.com") != -1) ||
  (domain.indexOf("rdrird.yahoo.com") != -1) ||
  (domain.indexOf("rdrhk2.yahoo.com") != -1) ||
  (domain.indexOf("rdrsg1.yahoo.com") != -1) ||
  (domain.indexOf("rdrin2.yahoo.com") != -1) ||
  (domain.indexOf("rdre1.yahoo.com") != -1) ||
  (domain.indexOf("rdrw1.yahoo.com") != -1)  )
 {
  return false;
 }

 return outHref;
};
searchshield.AVGYahooSearchEngine.prototype.updateImage = function (hash, search, score, image, alt_image, flyover, click_thru, altClick_thru)
{
 // remove style that is set when alt image is applied
 this.updateImageStyle = {
  verticalAlign: null
 };
  
 // don't show verisign icon
 if (alt_image && (alt_image.length > 0))
  this.omitAltImage = true;
  
 var parent = searchshield.SearchEngine.prototype.updateImage;
 return parent.call(this, hash, search, score, image, alt_image, flyover, click_thru, altClick_thru);
};
///////////////    AVG YAHOO SEARCH ENGINE    ///////////////




///////////////    MSN SEARCH ENGINE    ///////////////
searchshield.MSNSearchEngine = function(search)
{
 searchshield.SearchEngine.call(this, search);
 this.onlyPrimaries = false;
};
searchshield.MSNSearchEngine.prototype = new searchshield.SearchEngine();
searchshield.MSNSearchEngine.prototype.constructor = searchshield.MSNSearchEngine;
searchshield.MSNSearchEngine.prototype.name = "msn";
searchshield.MSNSearchEngine.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;

 // For MSN the host must match:
 // search.msn.com  OR
 // search.live.com
 if (domain.indexOf("search.msn.co") > -1)
 {
  if (domain.charAt(13) == 'm')
   hostMatch = true;
  else if ((domain.charAt(13) == '.') && (domain.length == 16))
   hostMatch = true;
 }
 else if (domain.indexOf("search.live.co") > -1)
 {
  if (domain.charAt(14) == 'm')
   hostMatch = true;
  else if ((domain.charAt(14) == '.') && (domain.length == 17))
   hostMatch = true;
 }
 
 if (hostMatch)
 {
  if (path.indexOf("results.aspx") == 0)
   return true;
 }

 return false;
};
searchshield.MSNSearchEngine.prototype.includeLink = function(tag)
{
 var outHref = false;
 
 // these don't seem common from Firefox, but they are in IE
 if (searchshield.DoesURLContain(tag.href, "g.msn.co"))
 {
  var qPos = tag.href.indexOf("?");
  if (qPos != -1)
  {
   var postPart = tag.href.substring(qPos+1);
   var dblAmp = postPart.indexOf("&&");
   if (dblAmp != -1)
   {
    outHref = postPart.substring(0, dblAmp);
    return outHref;
   }
  }
 }
 else if (searchshield.DoesURLContain(tag.href, "r.msn.co"))
 {
  var element = tag;
  var parentNode = tag.parentNode;

  // top links - check for a CITE
  var spanElements = element.getElementsByTagName("CITE");
  if ((spanElements != null)    && 
   (spanElements.length > 0))
  {
   outHref = spanElements[0].innerHTML;
   // replace any nbsp's
   outHref = outHref.replace("&nbsp;", " ");

   // url is after the last space in the html, after the '-'
   var space_pos = outHref.lastIndexOf(" ");
   if (space_pos != -1)
    outHref = outHref.slice(space_pos + 1);

   outHref = searchshield.checkUrl(outHref);
   return outHref;
  }
  
  // side links 
  if (element.lastChild != null)
  {
   outHref = element.lastChild.innerHTML;
   if ( outHref != null)
   {
    outHref = searchshield.checkUrl(outHref);
    return outHref;
   }
  }
 }
 else if (searchshield.DoesURLContain(tag.href, this.search.uri.host)     ||
    searchshield.DoesURLContain(tag.href, ".live.com")     ||
    searchshield.DoesURLContain(tag.href, "msn.")      ||
    searchshield.DoesURLContain(tag.href, "msnscache.com")    ||
    searchshield.DoesURLContain(tag.href, "advertising.microsoft.co") ||
    searchshield.DoesURLContain(tag.href, "javascript:")    ||
    searchshield.DoesURLContain(tag.href, "go.microsoft.co")   ||
    searchshield.DoesURLContain(tag.href, "hotmail.co"))
 {
  // not a link
  return false;
 }
 else if (tag.id.toLowerCase() == "trademarks")
 {
  // don't link the trademark at the bottom of the page
  return false;
 }
 else
 {
  // include it
  return tag.href;
 }
};
///////////////    MSN SEARCH ENGINE    ///////////////




///////////////    BING SEARCH ENGINE    ///////////////
searchshield.BingSearchEngine = function(search)
{
 searchshield.SearchEngine.call(this, search);
};
searchshield.BingSearchEngine.prototype = new searchshield.SearchEngine();
searchshield.BingSearchEngine.prototype.constructor = searchshield.BingSearchEngine;
searchshield.BingSearchEngine.prototype.name = "bing";
searchshield.BingSearchEngine.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;
 
 // For bing the host must match:
 // www.bing.com or www.bing.net
 // xx.bing.com or xx.bing.net where xx is a country code
 // bing.com.xx where xx is a country code
 // bing.search.xxxx.net where xxxx may be something like daum
 if ((domain.indexOf("www.bing.com") !== -1) ||
  (domain.indexOf("www.bing.net") !== -1) ||
  (domain.indexOf("bing.net") !== -1))
 {
  hostMatch = true;
 }
 else if ((domain.indexOf("bing.search.") !== -1) && 
    (domain.indexOf(".net") === (domain.length-4))) 
 { //bing.search.xxxx.net
  hostMatch = true;
 }
 else
 { // xx.bing.com or bing.com.xx
  var domainLen = domain.length;
  var tldPos = domain.indexOf(".bing.com");
  if (tldPos > -1)
  {
   if ((domainLen - tldPos) == 9)
    hostMatch = true;
  } 
 }
 
 if (hostMatch)
 {
  if (path.indexOf("search?") == 0)
   return true;
 }

 return false;

};
searchshield.BingSearchEngine.prototype.includeLink = function(tag)
{
 var outHref = false;

 if (tag.tagName == 'IMG')
 { //no images 
  return false;
 }
  
 if (tag.href.charAt(0) == '/')
 { //no relative links
  return false;
 }

 if (tag.id.toLowerCase() == "trademarks")
 {
  // don't link the trademark at the bottom of the page
  return false;
 }
 
 if ((tag.parentNode) &&
  (tag.parentNode.id.toLowerCase() == "sc_stc"))
 { // don't verdict the social sites - our verdict doesn't fit
  return false;
 }
 else if (!!searchshield.getParentNodeByClassName("sw_t",tag,3))
 { // no links in page header
  return false;
 }
 else if (searchshield.DoesURLContain(tag.href, "r.msn.co") ||
    searchshield.DoesURLContain(tag.href, "overture.com"))
 { // france has r.msn.co and italy has overture.com sponsored links
  // with the link in CITE element
  
  var spanElements = null;
  
  // top links - check for a CITE
  spanElements = tag.getElementsByTagName("CITE");
  if ((spanElements == null) || (spanElements.length <= 0))
  {
   if (tag.parentNode && tag.parentNode.parentNode)
    spanElements = tag.parentNode.parentNode.getElementsByTagName("CITE");
  }
  
  if ((spanElements != null) && (spanElements.length > 0))
  {
   outHref = spanElements[0].innerHTML;
   if (outHref != null)
   {
    // replace any nbsp's
    outHref = outHref.replace("&nbsp;", " ");

    // url is after the last space in the html, after the '-'
    var space_pos = outHref.lastIndexOf(" ");
    if (space_pos != -1)
     outHref = outHref.slice(space_pos + 1);

    outHref = searchshield.checkUrl(outHref);

    // save the link
    return outHref;
   }
  }
  
  // side links 
  if (tag.lastChild != null)
  {
   outHref = tag.lastChild.innerHTML;
   if (outHref != null)
   {
    outHref = searchshield.checkUrl(outHref);
    // save the link
    return outHref;
   }
  }
 }
 // no sponsored links for now 
 else if (searchshield.DoesURLContain(tag.href, this.search.uri.host) ||
   searchshield.DoesURLContain(tag.href, ".live.com")    ||
   searchshield.DoesURLContain(tag.href, ".bing.com")    ||
   searchshield.DoesURLContain(tag.href, ".bing.net")    ||
   searchshield.DoesURLContain(tag.href, ".daum.net")    ||
   searchshield.DoesURLContain(tag.href, ".gmarket.co")   ||
   searchshield.DoesURLContain(tag.href, ".multimap.com")   ||
   searchshield.DoesURLContain(tag.href, "msn.")     ||
   searchshield.DoesURLContain(tag.href, "ms.ciao.")    ||
   searchshield.DoesURLContain(tag.href, "ms.ciao-")    ||
   searchshield.DoesURLContain(tag.href, "advertising.microsoft.co") ||
   searchshield.DoesURLContain(tag.href, "javascript:")    ||
   searchshield.DoesURLContain(tag.href, "go.microsoft.co")   ||
   searchshield.DoesURLContain(tag.href, "hotmail.co")     ||
   searchshield.DoesURLContain(tag.href, "cc.bingj.com")    ||
   searchshield.DoesURLContain(tag.href, "microsofttranslator.com") ||
   searchshield.DoesURLContain(tag.href, ".engkoo.com")    ||
   searchshield.DoesURLContain(tag.href, "sealinfo.verisign.com")  ||
   searchshield.DoesURLContain(tag.href, "explabs.com")    ||
   searchshield.DoesURLContain(tag.href, "onlinehelp.microsoft.com"))
 {
  // not a link
  return false;
 }
 else
  return tag.href;
};
searchshield.BingSearchEngine.prototype.addImage = function(node, image, hidden)
{
 var element = node.element;
 var parentNode  = node.element.parentNode;
 var grandParentNode = !!parentNode ? parentNode.parentNode : null;

 // if there are redundant links in the same grandparent then skip them
 if (!!grandParentNode)
 {
  gpChildren = grandParentNode.childNodes;
  for (var i=0; i < gpChildren.length; i++)
  {
   if (!!element.href && gpChildren[i].tagName == "A" && gpChildren[i].href == element.href)
    return;
  }
 }

 var parent = searchshield.SearchEngine.prototype.addImage;
 return parent.call(this, node, image, hidden);
};
///////////////    BING SEARCH ENGINE    ///////////////




///////////////    BAIDU SEARCH ENGINE    ///////////////
searchshield.BaiduSearchEngine = function(search)
{
 searchshield.SearchEngine.call(this, search);
};
searchshield.BaiduSearchEngine.prototype = new searchshield.SearchEngine();
searchshield.BaiduSearchEngine.prototype.constructor = searchshield.BaiduSearchEngine;
searchshield.BaiduSearchEngine.prototype.name = "baidu";
searchshield.BaiduSearchEngine.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;
 
 if (domain == "www.baidu.com" || path.indexOf("testBaidu") !== -1)
  hostMatch = true;
  
 if (hostMatch)
 {
  if (path.indexOf("s?") == 0)
   return true;
 }

 return false;
};
searchshield.BaiduSearchEngine.prototype.includeLink = function(tag)
{  
  if (tag.className && tag.className == "m")
   return false;

  if (searchshield.DoesURLContain(tag.href, this.search.uri.host))
   return false;
  else 
  {
   // no link to self
   var traverseElement = tag.parentNode;
   while ( traverseElement && traverseElement.className != "tbody")
   {
    if (traverseElement.className == "f")
     return tag.href;

    traverseElement = traverseElement.parentNode;
   }
   
   return false;
  }

};
searchshield.BaiduSearchEngine.prototype.addImage = function(node, image, hidden)
{
 this.addImageStyle = {
  position: "relative",
  top: "0.05em"
 };
  
 var parent = searchshield.SearchEngine.prototype.addImage;
 return parent.call(this, node, image, hidden);
};
searchshield.BaiduSearchEngine.prototype.updateImage = function (hash, search, score, image, alt_image, flyover, click_thru, altClick_thru)
{
 // remove style that is set when alt image is applied
 this.updateImageStyle = {
  verticalAlign: null
 };
 
 var parent = searchshield.SearchEngine.prototype.updateImage;
 return parent.call(this, hash, search, score, image, alt_image, flyover, click_thru, altClick_thru);
};
///////////////    BAIDU SEARCH ENGINE    ///////////////




///////////////    EARTHLINK SEARCH ENGINE    ///////////////
searchshield.EarthlinkSearchEngine = function(search)
{
 searchshield.SearchEngine.call(this, search);
 this.onlyPrimaries = false;

 this.addAnchorStyle = {
  position: "static"
 };
};
searchshield.EarthlinkSearchEngine.prototype = new searchshield.SearchEngine();
searchshield.EarthlinkSearchEngine.prototype.constructor = searchshield.EarthlinkSearchEngine;
searchshield.EarthlinkSearchEngine.prototype.name = "earthlink";
searchshield.EarthlinkSearchEngine.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;

 // For EarthLink the host must match:
 // search.earthlink.net
 if (("search.earthlink.net" == domain) &&
  (path.indexOf("search?") == 0))
 {
  return true;
 }

 return false;
};
searchshield.EarthlinkSearchEngine.prototype.includeLink = function(tag)
{
 var outHref = "";
 var findStr = "";

 // check for an anchor
 if (tag.tagName == "A")
 {
  // check for sponsored
  if (tag.id.indexOf("a") == 0)
  {
   var q = tag.href.indexOf("&q=");
   var qlen = 3;
   if (q == -1)
   {
    q = tag.href.indexOf("&adurl=");
    qlen = 7;
    if (q == -1)
     return false;
   }

   // find end of url
   var end = tag.href.indexOf("&", q+qlen);
   if (end < 0)
    end = tag.href.length;

   // add the link
   outHref = tag.href.substring(q+qlen, end);
   
   if (searchshield.FilterUrl(outHref, this.filter_urls))
    return false;
    
   return outHref;
  }

  // don't search url's to self
  if ((tag.href.indexOf("://") == -1) || searchshield.DoesURLContain(tag.href, this.search.uri.host))
   return false;

  // if a normal web result add it
  if (tag.parentNode && (tag.parentNode.tagName == "H3") &&
   tag.parentNode.parentNode && (tag.parentNode.parentNode.tagName == "LI") &&
   tag.parentNode.parentNode.parentNode && (tag.parentNode.parentNode.parentNode.tagName == "UL"))
  {
   if (searchshield.FilterUrl(tag.href, this.filter_urls))
    return false;
    
   return tag.href;
  }
 }
 
 return false;
};
///////////////    EARTHLINK SEARCH ENGINE    ///////////////




///////////////    AOL SEARCH ENGINE    ///////////////
searchshield.AOLSearchEngine = function(search)
{
 searchshield.SearchEngine.call(this, search);
 
 this.addImageStyle = {
  display: "inline"
 };
 this.addAnchorStyle = {
  display: null
 };
 this.updateImageStyle = {
  verticalAlign: null,
  display: "inline"
 };
};
searchshield.AOLSearchEngine.prototype = new searchshield.SearchEngine();
searchshield.AOLSearchEngine.prototype.constructor = searchshield.AOLSearchEngine;
searchshield.AOLSearchEngine.prototype.name = "aol";
searchshield.AOLSearchEngine.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;
 //path may be 'aol/search' or 'search'
 var pathArray = uri.path.split("/");
 var aol = pathArray[0];
 // re stitch the uri path and query elements
 // to use existing logic
 var path = (undefined == pathArray[1]) ? pathArray[0] : pathArray[1];
  path += uri.delimiter + uri.query;

 if ("search.aol.com" == domain)
 {
  if ((aol == "aol") &&
   (path.indexOf("search?") == 0))
  {
   return true;
  }
 }
 
 return false;
};
searchshield.AOLSearchEngine.prototype.includeLink = function(tag)
{
 if (searchshield.DoesURLContain(tag.href, this.search.uri.host))
  return false;
 
 // sponsored links - google
 if ((tag.className) && (tag.className.indexOf("slLink") != -1))
 { //parse for embedded href

  if (tag.href.indexOf("/aclk?sa=") == -1)
   return false;

  var adurl = tag.href.indexOf("&adurl=http");
  if (adurl != -1)
  {
   var urlPos = adurl+7; // puts it on the http
   var outHref = tag.href.substring(urlPos);

   // extract any fragment text, do not unescape
   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;
  }

  return false;
 }

 if (tag.className == "find")
  return tag.href;
  
 return false;
};
searchshield.AOLSearchEngine.prototype.insertNodes = function(node, doc)
{
 var element = node.element;
 var score = node.score;

 if (element && element.className && element.className.indexOf("slLink") != -1)
 { //sponsored links only

  // for alt image
  if (score == searchshield.SCORE_SS_VERISIGN)
   return [element.nextSibling, element.parentNode];

  // for verdict image
  var cN = element.childNodes;
  var cnLen = cN.length;
  for (var i=0; i < cnLen; i++)
  {
   if ((cN[i].nodeType == 1) && 
    (cN[i].nodeName == 'SPAN') && 
    ((cN[i].className == 'title') || (cN[i].className == 'durl')))
    return [cN[i].nextSibling, cN[i].parentNode];
  }
 }

 var parent = searchshield.SearchEngine.prototype.insertNodes;
 return parent.call(this, node, doc);
};
///////////////    AOL SEARCH ENGINE    ///////////////




///////////////    ASK SEARCH ENGINE    ///////////////
searchshield.AskSearchEngine = function(search)
{
 searchshield.SearchEngine.call(this, search);
};
searchshield.AskSearchEngine.prototype = new searchshield.SearchEngine();
searchshield.AskSearchEngine.prototype.constructor = searchshield.AskSearchEngine;
searchshield.AskSearchEngine.prototype.name = "ask";
searchshield.AskSearchEngine.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 ("www.ask.com" == domain)
 {
  if (path.indexOf("web?") == 0)
   return true;
 }

 return false;
};
searchshield.AskSearchEngine.prototype.includeLink = function(tag)
{
 var outHref = "";
 var findStr = "";

 if (searchshield.DoesURLContain(tag.href, this.search.uri.host))
  return false;
 
 if ((tag.className) && (tag.className.indexOf("nu") != -1) && (tag.className.indexOf("info") == -1)) 
 {
  // exclude green links
  if ((tag.firstChild) &&
   (tag.firstChild.className) &&
   (tag.firstChild.className.indexOf('attrib') == 0))
  {
   return false;
  }

  // ads link to google with class nu
  findStr = "www.google.com";
  if (tag.href.indexOf(findStr) != 0)
  {
   if (tag.href.indexOf(findStr + "/aclk?sa=") != -1)
   { 
    findStr = "&adurl=http";
    var pos = tag.href.indexOf(findStr);
    if (pos != -1)
    {
     pos += 7;
     outHref = tag.href.substring(pos);
     outHref = unescape(outHref);
     if (searchshield.FilterUrl(outHref, this.filter_urls))
       return false;
     return outHref;
    }
   }
  }
  else
  { // ad not to google just use href
   outHref = tag.href;
   if (searchshield.FilterUrl(outHref, this.filter_urls))
    return false;
   return outHref;
  }
 }
 // primary results have class containing title or L2 ( Wikipedia links )
 else if ((tag.className) && ((tag.className.indexOf("title") != -1) || (tag.className.toLowerCase() == "l2")))
 {
  outHref = tag.href;
  if (searchshield.FilterUrl(outHref, this.filter_urls))
   return false;
  return outHref;
 }
 
 return false;
};
///////////////    ASK SEARCH ENGINE    ///////////////




///////////////    ALTAVISTA SEARCH ENGINE    ///////////////
searchshield.AltaVistaSearchEngine = function(search)
{
 searchshield.SearchEngine.call(this, search);
};
searchshield.AltaVistaSearchEngine.prototype = new searchshield.SearchEngine();
searchshield.AltaVistaSearchEngine.prototype.constructor = searchshield.AltaVistaSearchEngine;
searchshield.AltaVistaSearchEngine.prototype.name = "altavista";
searchshield.AltaVistaSearchEngine.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;

 // www.atlavista.com ---> now http://us.yhs4.search.yahoo.com/yhs/search?fr=altavista&fr=altavista&itag=ody&q=warez&kgs=1&kls=0
 // xx.altavista.com where xx is a country code
 var hostMatch = false;
 if ("www.altavista.com" == domain)
 {
  hostMatch = true;
 }
 else
 {
  // xx.altavista.com
  var pDest = domain.indexOf(".altavista.com");
  if ((pDest != -1 ) && ((domain.length - pDest) == 14))
  {
   hostMatch = true;
  }
  else
  {
   // a reference to altavista must be present in yahoo search url
   var pRef = (uri.qsArray.fr && uri.qsArray.fr == 'altavista');
   pDest = domain.indexOf("search.yahoo.com");
   if (pDest != -1 && pRef)
    hostMatch = true;
  }
 }

 if (hostMatch)
 {
  //path must start with web/results?
  if ((path.indexOf("yhs/search?") == 0) ||
   (path.indexOf("search;") == 0)  ||
   (path.indexOf("yhs/search;") == 0) ||
   (path.indexOf("web/results?") == 0)||
   (path.indexOf("fr=altavista") != -1))
  {
   return true;
  }
 }
 
 return false;
};
searchshield.AltaVistaSearchEngine.prototype.includeLink = function(tag)
{
 var outHref = "";
 var findStr = "";

 // initial checks
 if ((!tag.href) || 
  (tag.href.charAt(0) == '#') ||
  (tag.href.indexOf("javascript:") == 0))
 {
  return false;
 }
  
 if (searchshield.DoesURLContain(tag.href, this.search.uri.host))
  return false;
  
 if ((tag.className == "spt") || 
  (tag.className == "res") ||
  (tag.className == "yschttl spt"))
 {
  findStr = "/**";
  var pos = tag.href.indexOf(findStr);
  if (pos != -1)
  {
   pos += 3;
   outHref = tag.href.substring(pos);
   outHref = unescape(outHref);
   
   // no results for overture.com & no yahoo domains
   chkHref = outHref.toLowerCase();
   if (chkHref.indexOf("overture.") != -1)
    return false;

   // split the url based on '/'
   var parts = outHref.split('/');

   // only need a domain
   if ((parts != null) && (parts[2] != null))
   {
    var domain = parts[2];
    if ((domain.indexOf("rdrjp.yahoo.com") != -1) ||
     (domain.indexOf("rdrkrs.yahoo.com") != -1) ||
     (domain.indexOf("rdrtpe.yahoo.com") != -1) ||
     (domain.indexOf("rdrird.yahoo.com") != -1) ||
     (domain.indexOf("rdrhk2.yahoo.com") != -1) ||
     (domain.indexOf("rdrsg1.yahoo.com") != -1) ||
     (domain.indexOf("rdrin2.yahoo.com") != -1) ||
     (domain.indexOf("rdre1.yahoo.com") != -1) ||
     (domain.indexOf("rdrw1.yahoo.com") != -1)  )
    {
     return false
    }
   }

   return outHref;
  }
  else
  {
   return tag.href;
  }
 }
 
 return false;
};
searchshield.AltaVistaSearchEngine.prototype.getImgElement = function (element)
{
 while (element != null) 
 {
  element = element.nextSibling;
  if (element != null)
  {
   if ((element.id == null) || (element.id.indexOf("LXPLSS_") == -1))
   {   // not our id but hit another anchor no verdict
    if (element.tagName == "A")
    {
     element = null;
     break;
    }
   }
   else if (element.tagName == "A")
    break;
  }
  }
  
 var rtnElem = !!element ? element.firstChild : element;
 return rtnElem;
};
///////////////    ALTAVISTA SEARCH ENGINE    ///////////////




///////////////    YANDEX SEARCH ENGINE    ///////////////
searchshield.YandexSearchEngine = function(search)
{
 searchshield.SearchEngine.call(this, search);
};
searchshield.YandexSearchEngine.prototype = new searchshield.SearchEngine();
searchshield.YandexSearchEngine.prototype.constructor = searchshield.YandexSearchEngine;
searchshield.YandexSearchEngine.prototype.name = "yandex";
searchshield.YandexSearchEngine.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("yandex.ru") > -1) ||
  (domain.indexOf("yandex.com") > -1)) &&
  (path.indexOf("yandsearch?") == 0))
 {
  return true;
 }
 
 return false;
};
searchshield.YandexSearchEngine.prototype.includeLink = function(tag)
{
 if (tag.href.indexOf("/search") != -1)
 {
  return false;
 }
 
 if (searchshield.DoesURLContain(tag.href, this.search.uri.host) ||
  searchshield.DoesURLContain(tag.href, ".yandex.net")  ||
  searchshield.DoesURLContain(tag.href, ".yandex.ru")   ||
  searchshield.DoesURLContain(tag.href, "moikrug.ru")   ||
  searchshield.DoesURLContain(tag.href, "ya.ru")    ||
  searchshield.DoesURLContain(tag.href, ".yandex.com")  ||
  searchshield.DoesURLContain(tag.href, "yandex.st"))
 {
  return false;
 }
  
 parentNode = tag.parentNode;
 if ((tag.parentNode)   && 
  (tag.parentNode.parentNode) &&
  (tag.parentNode.parentNode.className.toLowerCase() == "moreinfo"))
 {
  return false;
 }
 
 return tag.href;
};
searchshield.YandexSearchEngine.prototype.getImgElement = function (element)
{
 while (element != null) 
 {
  element = element.nextSibling;
  if (element != null)
  {
   if ((element.id == null) || (element.id.indexOf("LXPLSS_") == -1))
   {   // not our id but hit another anchor no verdict
    if (element.tagName == "A")
    {
     element = null;
     break;
    }
   }
   else if (element.tagName == "A")
    break;
  }
  }
  
 var rtnElem = !!element ? element.firstChild : element;
 return rtnElem;
};
///////////////    YANDEX SEARCH ENGINE    ///////////////




///////////////    SEZNAM SEARCH ENGINE    ///////////////
searchshield.SeznamSearchEngine = function(search)
{
 searchshield.SearchEngine.call(this, search);
};
searchshield.SeznamSearchEngine.prototype = new searchshield.SearchEngine();
searchshield.SeznamSearchEngine.prototype.constructor = searchshield.SeznamSearchEngine;
searchshield.SeznamSearchEngine.prototype.name = "seznam";
searchshield.SeznamSearchEngine.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.seznam.cz") > -1) &&
  ((path.indexOf("?") == 0) || (path.indexOf("svet") == 0)))
 {
  return true;
 }
 
 return false;
};
searchshield.SeznamSearchEngine.prototype.includeLink = function(tag)
{
 if (searchshield.DoesURLContain(tag.href, this.search.uri.host))
  return false;
 
 var parentNode = tag.parentNode;
 if (parentNode)
 {
  var grandParentNode = tag.parentNode.parentNode;
  if ((parentNode.tagName == "SPAN") && 
   ((parentNode.className.toLowerCase() == "sklik-url") ||
   (parentNode.className.toLowerCase() == "sklik-title")))
  { // locate the real url and unencode it
   var urlPos = tag.href.indexOf("&url=http");

   if (urlPos != -1)
   {
    urlPos += 5; 
    outHref = tag.href.substring(urlPos);
    outHref = unescape(outHref);

    return outHref;
   }
  }
  else if (grandParentNode) 
  {
   var greatGrandParentNode = tag.parentNode.parentNode.parentNode;
   if ((grandParentNode.tagName == "DIV") &&
    ((grandParentNode.className.toLowerCase() == "text") || (grandParentNode.className.toLowerCase() == "hlasky otz")))
   { // standard link
    return tag.href;
   }
   else if (greatGrandParentNode && greatGrandParentNode.tagName == "DIV" &&
     (greatGrandParentNode.className.toLowerCase() == "hotlinks")) 
   { // hint link
    return tag.href;
   }
   
  }
 }
 
 return false;
};
searchshield.SeznamSearchEngine.prototype.updateImage = function (hash, search, score, image, alt_image, flyover, click_thru, altClick_thru)
{
 this.elementAttribute = {
  width: "18",
  height: "18"
 };

 this.updateImageStyle = {
  width: "18px",
  height: "18px"
 };
 
 var parent = searchshield.SearchEngine.prototype.updateImage;
 return parent.call(this, hash, search, score, image, alt_image, flyover, click_thru, altClick_thru);
};
///////////////    SEZNAM SEARCH ENGINE    ///////////////




///////////////    WEBHLEDANI SEARCH ENGINE    ///////////////
searchshield.WebhledaniSearchEngine = function(search)
{
 searchshield.SearchEngine.call(this, search);
};
searchshield.WebhledaniSearchEngine.prototype = new searchshield.SearchEngine();
searchshield.WebhledaniSearchEngine.prototype.constructor = searchshield.WebhledaniSearchEngine;
searchshield.WebhledaniSearchEngine.prototype.name = "webhledani";
searchshield.WebhledaniSearchEngine.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("webhledani.cz") > -1) &&
  (path.indexOf("results.aspx?") == 0))
 {
  return true;
 }
 
 return false;
};
searchshield.WebhledaniSearchEngine.prototype.includeLink = function(tag)
{
 var parentNode = tag.parentNode;
 
 if (searchshield.DoesURLContain(tag.href, this.search.uri.host))
 {
  if ( tag.href.indexOf("/redir.aspx?") != -1)
  {
   attrNode = tag.attributes;
   if ( attrNode == null )
    return false;

   var outHref = attrNode.getNamedItem("onmouseover").nodeValue;
   if ( outHref == null )
    return false;
 
   var findStr = "window.status=";
   if (outHref.indexOf(findStr)!= -1)
   {
    // get text before first semicolon
    var semicolon = outHref.indexOf(";");
    if (semicolon > -1)
     outHref = outHref.substring(findStr.length, semicolon);

    // strip quotation marks
    outHref = outHref.replace(/['"]/g, "");

    var space = outHref.indexOf(" ");
    var firstDot = outHref.indexOf(".");

    if ((space > -1) && (space < firstDot))
     outHref = outHref.substring(space+1);

    outHref = searchshield.checkUrl(outHref);
    return outHref;
   }
  }
 }

 return false;
};
searchshield.WebhledaniSearchEngine.prototype.insertNodes = function(node, doc)
{
 var element = node.element;
 var score = node.score;

 // for alt image
 if (score == searchshield.SCORE_SS_VERISIGN)
  return [element.nextSibling, element.parentNode];

 // for verdict image
 var cN = element.childNodes;
 var cnLen = cN.length;
 for (var i=0; i < cnLen; i++)
 {
  if (cN[i].nodeType == 1 && cN[i].nodeName == 'SPAN' && cN[i].className == 'sl')
  {
   if (!this.cssUpdated)
   {
    this.cssUpdated = true;

    // need to add style to make verdicts display inline
    var docStyle = doc.styleSheets[0];
    if (docStyle && docStyle.addRule)
    { //IE
     docStyle.addRule('#s a','display:inline');
     docStyle.addRule('#s p a .sl','display:inline');
    }
    else if (docStyle && docStyle.insertRule)
    {
     docStyle.insertRule('#s a {display:inline}', docStyle.cssRules.length);
     docStyle.insertRule('#s p a .sl {display:inline}', docStyle.cssRules.length);
    }
   }

   return [cN[i].nextSibling, cN[i].parentNode];
  }
 }

 // don't display anything
 return [null, null];
};
///////////////    WEBHLEDANI SEARCH ENGINE    ///////////////




///////////////    EBAY SEARCH ENGINE    ///////////////
searchshield.eBaySearchEngine = function(search)
{
 searchshield.SearchEngine.call(this, search);
};
searchshield.eBaySearchEngine.prototype = new searchshield.SearchEngine();
searchshield.eBaySearchEngine.prototype.constructor = searchshield.eBaySearchEngine;
searchshield.eBaySearchEngine.prototype.name = "ebay";
searchshield.eBaySearchEngine.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;
 // shop.ebay.xx
 // shop.xxxx.ebay.xx like shop.benl.ebay.be
 // search.auction.co.kr 
 var path = uri.path + uri.delimiter + uri.query;
 
 if ((domain.indexOf("shop.ebay") > -1) ||
  (domain.indexOf("shop.benl.ebay") > -1))
 {
  if ((path.indexOf("?_from=") == 0) ||
   (path.indexOf("i.html") > -1))
  {
   return true;
  }
 }
 
 // ebay.se
 if ((domain.indexOf("search.eim.ebay") > -1) &&
  ((path.indexOf("?kw=") > -1) || (path.indexOf("?ev=") > -1)))
 {
  return true;
 }
 
 if ((domain.indexOf("search.auction.co.kr") > -1 ) &&
  ((path.indexOf("?keyword=") > -1)))
 {
  // would normally set these properties in the constructor or in an
  // overriding function but they're only required for this domain
   
  // links are in iframes
  this.processFrames = true;
  
  // must downsize verdicts for proper display
  this.elementAttribute = {
   width: "16",
   height: "16"
  };
  this.updateImageStyle = {
   width: "16px",
   height: "16px"
  };
  
  return true;
 }

 // latin america ebay
 // listado.mercadolibre.com.xx or listado.mercadolibre.co.xx
 //   or listado.mercadolibre.xx or
 //   category.mercadolibre.com.xx or listado.mercadolibre.xx/category
 // lista.mercadolivre.com.xx or lista.mercadolivre.com.xx/category
 if ((domain.indexOf("www.") == -1) &&
  ((domain.indexOf(".mercadolibre.") > -1 ) ||
   (domain.indexOf(".mercadolivre.") > -1 ))) 
 {
  return true;
 }
 return false;
};
searchshield.eBaySearchEngine.prototype.includeLink = function(tag)
{
 var parentNode = null;
 var outHref = false;
 
 if (searchshield.DoesURLContain(tag.href, this.search.uri.host))
  return false;
 
 if ( tag.href.indexOf(".ebayrtm.com/clk?") > -1 )
 {
  if ( tag.title == null || tag.title.length < 0 )
   return false;
     
  outHref = searchshield.removeHtmlTags(tag.title);
  if (outHref.indexOf(" ") == -1)
  { // no spaces
   if (outHref.indexOf(".") > -1)
   { // at least one dot 
    if (outHref.indexOf(this.search.uri.host) == -1)
    { // no host
     if (outHref.toLowerCase().indexOf("ebay.com") == -1)
     {
      return outHref;
     }
    }
   }
  }   
 }
 // ebay.se - Google ads
 parentNode = tag.parentNode;
 if (parentNode && (parentNode.className.toLowerCase() == "google-ad-link"))
 {
  if (tag.href.indexOf("/aclk?sa=") != -1)
  { 
   findStr = "&adurl=http";
   var urlPos = tag.href.indexOf(findStr);
   if (urlPos != -1)
   {
    urlPos += 7; // puts it on the http
    outHref = tag.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;
   }
  }
 }
 
 // auction.co.kr
 parentNode = tag.parentNode;
 if (parentNode && (parentNode.className.toLowerCase() == "link"))
 {
  if (tag.href.indexOf("adcr.naver.com") > -1)
  {
   outHref = tag.innerText;
   if ((outHref == null) || (outHref.length < 0))
    return false;
    
   return outHref;
  }
 }
 
 // latin america ebay
 if ( tag.href.toLowerCase().indexOf("clickcounter?") > -1 )
 {
  var spanElements = tag.getElementsByTagName("span");
  if ((spanElements != null)    && 
   (spanElements.length > 0))
  {
   if ( spanElements[0].className.toLowerCase() == "mclics-url" )
   {
    outHref = spanElements[0].innerHTML;
    if ( outHref == null || outHref.length < 0 )
     return false;
    outHref = searchshield.removeHtmlTags(outHref);
    if (outHref.indexOf(" ") == -1)
    { // no spaces
     if (outHref.indexOf(".") > -1)
     { // at least one dot 
      if ((outHref.toLowerCase().indexOf("mercadolibre") == -1) && 
          (outHref.toLowerCase().indexOf("mercadolivre") == -1)) 
      {
       return outHref;
      }
     }
    }
   }
  }
 }
 
 return false;
};
///////////////    EBAY SEARCH ENGINE    ///////////////




///////////////    DIGG SEARCH ENGINE    ///////////////
searchshield.DiggSearchEngine = function(search)
{
 searchshield.SearchEngine.call(this, search);
 this.new_links = false;
};
searchshield.DiggSearchEngine.prototype = new searchshield.SearchEngine();
searchshield.DiggSearchEngine.prototype.constructor = searchshield.DiggSearchEngine;
searchshield.DiggSearchEngine.prototype.name = "digg";
searchshield.DiggSearchEngine.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("digg.com") > -1) &&
  (path.indexOf("/ad") == -1))
 {
  return true;
 }
 
 return false;
};
searchshield.DiggSearchEngine.prototype.includeLink = function(tag)
{
 var outHref = false;
 var findStr = "";
 
 if ((tag.parentNode) &&
  (tag.parentNode.className.toLowerCase() == "digg-count"))
 {
  return false;
 }
 
 if (searchshield.DoesURLContain(tag.href, this.search.uri.host))
 {
  if (tag.className && tag.className.indexOf('source') != -1)
  {
   findStr = "/search?q=site:";
   var urlPos = tag.href.indexOf(findStr);
   if (urlPos != -1)
   {
    urlPos += 15;
    outHref = tag.href.substring(urlPos);
    return outHref;
   }
  }
 }
 
 return false;
};
searchshield.DiggSearchEngine.prototype.addImage = function(node, image, hidden)
{
 // remove style that is set when alt image is applied
 this.addAnchorStyle = {
  background: "none"
 };
  
 var parent = searchshield.SearchEngine.prototype.addImage;
 return parent.call(this, node, image, hidden);
};
///////////////    DIGG SEARCH ENGINE    ///////////////




///////////////    SLASHDOT SEARCH ENGINE    ///////////////
searchshield.SlashdotSearchEngine = function(search)
{
 searchshield.SearchEngine.call(this, search);
 this.showCleanVerdicts = false;
 this.new_links = false;
 this.type = 'inline';
};
searchshield.SlashdotSearchEngine.prototype = new searchshield.SearchEngine();
searchshield.SlashdotSearchEngine.prototype.constructor = searchshield.SlashdotSearchEngine;
searchshield.SlashdotSearchEngine.prototype.name = "slashdot";
searchshield.SlashdotSearchEngine.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("slashdot.org") != -1)
 {
  return true;
 }
 
 return false;
};
searchshield.SlashdotSearchEngine.prototype.includeLink = function(tag)
{
 if (searchshield.DoesURLContain(tag.href, this.search.uri.host))
  return false;
  
 if ( tag.href.indexOf("mailto:") != -1 )
  return false;
  
 if ( tag.href.indexOf("slashdot.org") != -1 )
  return false;
  
 if (tag.parentNode && (tag.parentNode.tagName == "DIV"))
 {
  if (tag.parentNode.id.indexOf("text-") != -1)
  {
   return tag.href;
  }
 }
 else if ( tag.parentNode && tag.parentNode.parentNode && tag.parentNode.parentNode.tagName == "DIV" )
 {
  if ( tag.parentNode.parentNode.id.indexOf("text-") != -1 )
  {
   return tag.href;
  }
 }

 return false;
};
searchshield.SlashdotSearchEngine.prototype.addImage = function(node, image, hidden)
{
 var doc   = this.search.doc;
 
 this.init_inline_ratings(doc);
 this.show_inline_ratings(doc, node, image);
};
///////////////    SLASHDOT SEARCH ENGINE    ///////////////




///////////////    TWITTER SEARCH ENGINE    ///////////////
searchshield.TwitterSearchEngine = function(search)
{
 searchshield.SearchEngine.call(this, search);
 this.showCleanVerdicts = false;
 this.new_links = false;
 this.type = 'inline';
};
searchshield.TwitterSearchEngine.prototype = new searchshield.SearchEngine();
searchshield.TwitterSearchEngine.prototype.constructor = searchshield.TwitterSearchEngine;
searchshield.TwitterSearchEngine.prototype.name = "twitter";
searchshield.TwitterSearchEngine.prototype.twitter_filter_urls = ["twitpic.com", "twitterfeed.com", "twitter.peoplebrowsr.com"];
searchshield.TwitterSearchEngine.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;

 if (domain.indexOf("twitter.com") != -1)
 {
  return true;
 }
 
 return false;
};
searchshield.TwitterSearchEngine.prototype.includeLink = function(tag)
{
 if (searchshield.DoesURLContain(tag.href, this.search.uri.host))
  return false;
  
 if (tag.className.length < 1)
  return false;
 
 // no verdicts on source of twit for example "from TweetDeck"
 if ((tag.className.indexOf("tweet-url web") == 0) &&
  (tag.className.indexOf("url") == 0 ))
 {
  return false;
 }
  
 if (searchshield.FilterUrl(tag.href, this.twitter_filter_urls))
 {
  return false;
 }
 
 return tag.href;
};
searchshield.TwitterSearchEngine.prototype.addImage = function(node, image, hidden)
{
 var doc   = this.search.doc;
  
 this.init_inline_ratings(doc);
 this.show_inline_ratings(doc, node, image);
};
///////////////    TWITTER SEARCH ENGINE    ///////////////




///////////////    GMAIL SEARCH ENGINE    ///////////////
searchshield.GMailSearchEngine = function(search)
{
 searchshield.SearchEngine.call(this, search);
 this.processFrames = true;
 this.showCleanVerdicts  = false;
 this.type = 'inline';
};
searchshield.GMailSearchEngine.prototype = new searchshield.SearchEngine();
searchshield.GMailSearchEngine.prototype.constructor = searchshield.GMailSearchEngine;
searchshield.GMailSearchEngine.prototype.name = "gmail"; // the name by which the search engine is known (always lowercase)
searchshield.GMailSearchEngine.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("mail.google.") != -1) || 
  (domain.indexOf("gmail.") != -1))
 {
  return true;
 }

 return false;
};
searchshield.GMailSearchEngine.prototype.includeLink = function(tag)
{
 if (searchshield.DoesURLContain(tag.href, this.search.uri.host))
  return false;

 // don't mark anything but http://
 if (tag.href.indexOf("mailto") == 0)
  return false;

 var parentDiv = searchshield.getParentNodeByTagName("DIV", tag, "className");
 if ((parentDiv) &&
  ((parentDiv.className == "ii gt") || // mail message body
   (parentDiv.className == "mv") || // top sponsored links
   (parentDiv.className == "vb") || // right sponsored links
   (parentDiv.className == "im") || // inside quotes
   (parentDiv.className == "gmail_quote") || // quote
   (parentDiv.className == "msg") // basic html mode
   )) // right ads
 {
  // parse for any ads
  var newHref = this.parseAdUrl(tag.href);
  return newHref;
 }
 
 return false;
};
searchshield.GMailSearchEngine.prototype.addImage = function(node, image, hidden)
{
 var doc   = this.search.doc;
  
 this.init_inline_ratings(doc);
 this.show_inline_ratings(doc, node, image);
};
searchshield.GMailSearchEngine.prototype.parseAdUrl = function(href)
{
 if (!href)
  return href;

 // check for google ad
 var regex = "^http(s)?\:\/\/([a-zA-Z0-9]+)\.googlesyndication\.com.+\&adurl\=(.+)";
 var re = new RegExp(regex);
 var matches = href.match(re);
 if (matches && (matches.length >= 4))
 {
  // else we want the fourth value
  var match = matches[3];
  if (match && (match.length > 0))
   return match
 }

 return href;
};
///////////////    GMAIL SEARCH ENGINE    ///////////////




///////////////    FACEBOOK SEARCH ENGINE    ///////////////
searchshield.FacebookSearchEngine = function(search)
{
 searchshield.SearchEngine.call(this, search);
 this.showCleanVerdicts = false;
 this.type = 'inline'
};
searchshield.FacebookSearchEngine.prototype = new searchshield.SearchEngine();
searchshield.FacebookSearchEngine.prototype.constructor = searchshield.FacebookSearchEngine;
searchshield.FacebookSearchEngine.prototype.name = "facebook"; // the name by which the search engine is known (always lowercase)
searchshield.FacebookSearchEngine.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;

 if (uri.host.indexOf("www.facebook.com") != -1) 
  return true;

 return false;
};
searchshield.FacebookSearchEngine.prototype.includeLink = function(tag)
{
 if (searchshield.DoesURLContain(tag.href, this.search.uri.host) ||
  (searchshield.DoesURLContain(tag.href, 'static.ak.fbcdn.net')))
 {
  return false;
 }
  
 // don't put verdicts in areas where typing is going on
 if (tag.parentNode) 
 {
  var parentDiv = searchshield.getParentNodeByTagName("DIV", tag, "className");
  if (parentDiv &&
   (parentDiv.className == "Mentions_Input") ||
   (parentDiv.className.indexOf('UIThumbPager_') != -1))
  {
   return false;
  }
 }
 
 return tag.href
};
searchshield.FacebookSearchEngine.prototype.addImage = function(node, image, hidden)
{
 var doc   = this.search.doc;
  
 this.init_inline_ratings(doc);
 this.show_inline_ratings(doc, node, image);
};
///////////////    FACEBOOK SEARCH ENGINE    ///////////////



///////////////    AVG TOOLBAR REPORTING    ///////////////
var avgreport = {
 BLOCK_SEVERITY: 3,
 scanResult: function (doc, url, foundUrl, ip) {
  // report scan end only if surf enabled
  if ('1' != searchshield.avgCallFunc(doc, 'GetSurfEnabled'))
   return;
  
  // for now native is handling the interstitial 
  var results = searchshield.avgCallFunc(doc, 'MalsiteCheck', url);
  if ( results == null )
   return;
  
  var parts = results.split('::');
  
  // need at least severity
  if (parts == null)
   return;

  if (!ip)
   ip = "";
   
  // use a block severity if foundUrl is given
  var severity = !!foundUrl ? avgreport.BLOCK_SEVERITY : parseInt(parts[0], 10);
  var category = "";
  var threat  = "";

  // fill in the category and threat if something was found
  if (severity > 0)
  {
   category = parts[2];
   threat  = parts[4];
  }
//  else
//   return;
  
  var scan_result = searchshield.avgCallFunc(doc, 'ReportScanResult', url, url, threat, category, ip, severity);
  var scan_end = avgreport.scanEnd(doc, url);
  
  return (scan_result && scan_end);
 },
 scanEnd: function (doc, url) {
  return searchshield.avgCallFunc(doc, 'ReportScanEnd', url);
 },
 GetInterstitialIP: function (interstitial) {
  // simple regex to pull the IP address
  var regex = /(([1-9][0-9]{0,2})|0)\.(([1-9][0-9]{0,2})|0)\.(([1-9][0-9]{0,2})|0)\.(([1-9][0-9]{0,2})|0)/;
  var match = regex.exec(interstitial);
  if (!match)
   return '';

  return match[0];
 }
}
///////////////    AVG TOOLBAR REPORTING    ///////////////


///////////////    FLYOVERS    ///////////////
var avglsflyover = {
 count: 0,
 poppedUp: false,
 poppedElement: null,
 orig_onmousemove: null,
 reset: function () {
  avglsflyover.count = 0;
  avglsflyover.poppedUp = false;
  avglsflyover.poppedElement = null;
  avglsflyover.orig_onmousemove = null;
 },
 popup: function (event, hash, search, flyover) {
  if (!event)
   event = window.event;

  var div = document.getElementById("XPLSS_Flyover");
  if (div == null)
   return;

  // establish target element and get its containing document object
  // in case verdict is inside a frame
  var eventTarget = event.srcElement || event.currentTarget;
  var frameDoc = eventTarget.ownerDocument;

  // if the element is the clock, don't pop over it
  if ((eventTarget.src != null) && (eventTarget.src.indexOf("clock.gif") != -1))
   return;
  
  // save the element we popped over
  avglsflyover.poppedElement = eventTarget;

  // if no flyover get it
  if ((flyover == null) || (flyover == ""))
  {
   flyover = searchshield.avgCallFunc(frameDoc, 'BuildFlyover', hash);

   if (!flyover)
    return;

   // cleanup flyover, replace any new lines
   flyover = flyover.replace(/\r/g, "");
   flyover = flyover.replace(/\n/g, "");
   // escape any single quotes
   flyover = flyover.replace(/'/g, "&#39;");
  }

  // set the html in the layer
  div.innerHTML = flyover;

  // there is an unwanted text node that causes vertical misalignment of flyover
  if (div.firstChild.nodeType == 3)
   div.removeChild(div.firstChild);
  
  avglsflyover.poppedUp = true;

  // reset display count
  avglsflyover.count = 0;

  div.onmouseout = avglsflyover.hide;

  // if an onmousemove is already set and it isn't us, save it and restore later
  if ((frameDoc.onmousemove != null) && (frameDoc.onmousemove != avglsflyover.position))
   avglsflyover.orig_onmousemove = frameDoc.onmousemove;
  frameDoc.onmousemove = avglsflyover.position;
 },
 hide: function (event, force) {
  var div = document.getElementById("XPLSS_Flyover");
  if ((div == null) || (div.style == null) || (div.style.visibility == "hidden"))
   return;

  var trans_div = document.getElementById("XPLSS_Trans");
  if ((trans_div == null) || (trans_div.style == null) || (trans_div.style.visibility == "hidden"))
   return;

  if (!!force)
   return setFlyoverStyle(div, trans_div);

  if (!event)
   event = window.event;
  
  // establish target element and get its containing document object
  // in case verdict is inside a frame
  var eventTarget = event.srcElement || event.currentTarget;
  var frameDoc = eventTarget.ownerDocument;

  // restore onmousemove
  if (avglsflyover.orig_onmousemove != null)
   frameDoc.onmousemove = avglsflyover.orig_onmousemove;

  if (avglsflyover.poppedElement)
   avglsflyover.poppedElement.style.border = "";

  var relatedElement = event.toElement;
  if (!relatedElement)
  { //this happens on mouseout when verdict and flyover are on different frames/docs
   window.top.document.detachEvent('onmouseout', avglsflyover.hide);
   window.top.document.attachEvent('onmouseout', avglsflyover.hide);
   return;
  }

  // make sure we aren't still over the popped image or our layer
  if (searchshield.containedIn(avglsflyover.poppedElement, relatedElement) ||
   searchshield.containedIn(div, relatedElement) ||
   searchshield.containedIn(trans_div, relatedElement))
  {
   return;
  }

  setFlyoverStyle();

  // hide and move somewhere off screen (negative offsets)
  function setFlyoverStyle()
  {
   div.style.visibility = "hidden";
   div.style.left = "-2100px";
   div.style.top  = "-2100px";
   trans_div.style.visibility = "hidden";
   trans_div.style.left = "-2100px";
   trans_div.style.top  = "-2100px";

   return true;
  }
 },
 position: function () {
  if (!avglsflyover.poppedUp || (avglsflyover.poppedElement == null))
   return;

  var flyover = document.getElementById("XPLSS_Flyover");
  if (flyover == null)
   return;


  // relative position of flyover in relation to icon
  var locateX = 0;  // 0=left, 1=right
  var locateY = 0;  // 0=above, 1=below, 2=beside icon
 
  // get window sizes
  var winSize  = searchshield.viewPortSize();
  var windowX  = winSize[0];
  var windowY  = winSize[1];

  // get the exact size of the flyover
  var flyoverSize  = searchshield.elementSize(flyover);
  var flyoverX  = flyoverSize[0];
  var flyoverY  = flyoverSize[1];

  var verdictWidth = 0;
  if (avglsflyover.poppedElement && avglsflyover.poppedElement.width)
   verdictWidth = avglsflyover.poppedElement.width;
  
  // get the bounding rect for image(s)
  var imgRect = searchshield.GetFullBoundingRect(avglsflyover.poppedElement);

  // half width/height of element bounding rect
  var halfX = (imgRect.right - imgRect.left) / 2;
  var halfY = (imgRect.bottom- imgRect.top) / 2;

  // element the mouse is over, get the center position
  var posX = searchshield.offsetLeft(avglsflyover.poppedElement) + halfX;
  var posY = searchshield.offsetTop(avglsflyover.poppedElement) + halfY;

  // if a verdict is inside a frame must get offsets for the frame element
  var docFrames = document.frames;
  if (docFrames)
  {
   for (var i=0; i < docFrames.length; i++)
   {
    try {
     var frameElem = docFrames[i].frameElement;
     if (frameElem.contentWindow.document.getElementById(avglsflyover.poppedElement.id))
     {
      posX += searchshield.offsetLeft(frameElem);
      posY += searchshield.offsetTop(frameElem);
      break;
     }
    }
    catch(frmErr){}
   }
  }

  var transXOffset = 0;
  if (imgRect.mid == undefined)
   transXOffset = -1 * halfX;
  else
   transXOffset = ((imgRect.right + imgRect.left) / 2) - imgRect.mid;
  
  // normalize pos to 0  -- get amount of scrolling in browser window
  var scroll   = searchshield.scrollSize();
  var pageOffsetX  = scroll[0];
  var pageOffsetY  = scroll[1];

  posX -= pageOffsetX;
  posY -= pageOffsetY;

  // setup the offsets
  var offsetX = posX;
  var offsetY = posY;

  // calc where to display on page
  if ((windowX - posX) > posX)
  {
   // right
   offsetX += halfX;
   locateX = 1;
  }
  else
  {
   //left
   offsetX -= (flyoverX + halfX);
  }
  if ((windowY - posY) > posY)
  {
   // below
   if (posY < (windowY/4))
   {
    offsetY -= halfY;
    locateY = 1;
   }
   else
   {
    offsetY -= (flyoverY / 2);
    locateY = 2;
   }
  }
  else
  {
   // above
   if ((windowY - posY) < (windowY/4))
   {
    offsetY -= (flyoverY - halfY);
   }
   else
   {
    offsetY -= (flyoverY / 2);
    locateY = 2;
   }
  }
  // make sure we aren't off the screen
  if (offsetY < 0)
   offsetY = 0;

  if ((offsetY + flyoverY) > windowY)
   offsetY = windowY - flyoverY;

  // add page offsets back
  offsetX += pageOffsetX;
  offsetY += pageOffsetY;
  posX += pageOffsetX;
  posY += pageOffsetY;

  var paddedOffsetX = 0; //provide space between icon and flyover
  var padX = 3;
  if (locateX == 0)
   paddedOffsetX = offsetX - padX;
  else
   paddedOffsetX = offsetX + padX;


  // set where to put the flyover
  flyover.style.top = offsetY + "px";
  flyover.style.left = paddedOffsetX + "px";


  // set where to put the transparent layer
  var trans = document.getElementById("XPLSS_Trans");
  if (trans != null)
  {
   var trans_left = 0;
   var trans_top  = 0;
   var trans_width= 0;
   var trans_height = 0;

   // transparent layer should overlap verdict image
   if (locateX == 0)
    trans_left = posX - flyoverX - halfX;  // left 
   else
    trans_left = posX - transXOffset - verdictWidth; // right

   trans.style.left = trans_left + "px";
   trans.style.top  = offsetY + "px";

   trans.style.width = flyoverX + "px";
   trans.style.height = flyoverY + "px";
  }

  avglsflyover.display();
 },
 display: function () {
  avglsflyover.count++;
  if (avglsflyover.count == 1)
  {
   var flyover = document.getElementById("XPLSS_Flyover");
   if (flyover == null)
    return;

   // show the flyover, must use a little count to tell, crazy stuff
   flyover.style.visibility = "visible";

   // show the transparent layer
   var trans_div = document.getElementById("XPLSS_Trans");
   if (trans_div == null)
    return;

   trans_div.style.visibility = "visible";

   avglsflyover.poppedUp = false;
  }
 },
 show: function () {
  var div = document.getElementById("XPLSS_Flyover");
  if (div == null)
   return;

  div.style.visibility = "visible";

  var trans_div = document.getElementById("XPLSS_Trans");
  if (trans_div == null)
   return;
  trans_div.style.visible = "visible";
 }
};

var avglsinlineflyover = {
 build: function (riskCategory, riskName, bgColor, borderColor) {
  var html = '';
  html += "<div style=background-color:" + bgColor;
  html += "border-color:" + borderColor + ";";
  html += "border-style:solid;";
  html += "border-width:3px;";
  html += "padding:3px;";
  html += "padding-left:8px;";
  html += "padding-right:8px;";
  html += "-moz-border-radius:5px;>




";
  html += "
";
  html += riskCategory + "
";
  html += riskName + "
";

  return html;
 },
 popup: function (event, flyover, blUrl) {
  //set verdict info
  var div = document.getElementById('XPLSS_InlineFlyover');
  if (div == null)
   return;
  
  // blUrl is an object for a blacklisted short url
  // when it is passed get the final url 
  if (blUrl != undefined)
  {
   var finalUrl = searchshield.avgCallFunc(document, 'GetFinalUrl', blUrl.sUrl);
   var uri = searchshield.parseLink(unescape(finalUrl));
   if (uri.source != null)
   { // regexp failed so used split to parse url
    var qsUrl = uri.source.indexOf("?url=");
    if (qsUrl != -1)
     riskName = blUrl.riskNameLabel + uri.source.substring(qsUrl + 5);
    else
     riskName = blUrl.riskNameLabel + uri.source;
   }
   else if ((uri.qsArray.url != null) && (uri.qsArray.url.length > 0))
   {
    riskName = blUrl.riskNameLabel + uri.qsArray.url;
   }
   else
    riskName = blUrl.riskNameLabel + blUrl.sUrl

   flyover = avglsinlineflyover.build(blUrl.riskCategory, riskName, blUrl.bgColor, blUrl.borderColor);
  }

  div.innerHTML = flyover;
  div.style.width = "auto";  //reset width
  div.style.position = "absolute";

  if (!event)
   event = window.event;
   
  var eventTarget = event.srcElement;
  avglsinlineflyover.position(eventTarget);
 },
 hide: function (event) {
  if (!event)
   event = window.event;
   
  var div = document.getElementById("XPLSS_InlineFlyover");
  if (div == null)
   return;
   
  div.visibility = "hidden"; //invisible
  div.style.left = "-5000px";
 },
 position: function (imageElem) {
  var flyover = document.getElementById('XPLSS_InlineFlyover');
  if (flyover == null)
   return;
   
  // relative position of flyover in relation to icon
  var locateX = 0;  // 0=left, 1=right
  var locateY = 0;  // 0=above, 1=below, 2=beside icon
  
  
  
  // get window sizes
  var winSize  = searchshield.viewPortSize();
  var windowX  = winSize[0];
  var windowY  = winSize[1];

  // Must know if there is a horizontal scroll bar for Firefox
  // for proper flyover positioning near bottom edge
  var scrollYWidth  = winSize[2];
  var scrollBarX  = winSize[2] > 0 ? true : false;

  // get the exact size of the flyover
  var flyoverSize  = searchshield.elementSize(flyover);
  var flyoverX  = flyoverSize[0];
  var flyoverY  = flyoverSize[1];
  
  flyover.style.width = flyoverX + "px";
  
  // get the bounding rect for image(s)
  var imgRect = imageElem.getBoundingClientRect();

  // half width/height (center) of element bounding rect
  var halfX = (imgRect.right - imgRect.left) / 2;
  var halfY = (imgRect.bottom- imgRect.top) / 2;

  // element the mouse is over, get the center position
  var posX = searchshield.offsetLeft(imageElem) + halfX;
  var posY = searchshield.offsetTop(imageElem) + halfY;
  
  var pageOffsetX = 0;
  var pageOffsetY = 0;

  // normalize pos to 0  -- get amount of scrolling in browser window
  var scroll   = searchshield.scrollSize(imageElem);
  var pageOffsetX  = scroll[0];
  var pageOffsetY  = scroll[1];
  var hasParentFrame = scroll[2];
  
  posX -= pageOffsetX;
  posY -= pageOffsetY;

  //compensate for Firefox 3
  if (posX < imgRect.left)
   posX = imgRect.left+halfX;

  // setup the offsets
  var offsetX = posX;
  var offsetY = posY;

  // calc where to display on page
  if ((windowX - posX) > posX)
  {
   // right
   offsetX += halfX;
   locateX = 1;
  }
  else
  {
   //left
   offsetX -= (flyoverX + halfX);
  }
  if ((windowY - posY) > posY)
  {
   // below
   if (posY < (windowY/4))
   {
    offsetY -= halfY;
    locateY = 1;
   }
   else
   {
    offsetY -= (flyoverY / 2) - halfY;
    locateY = 2;
   }
  }
  else
  {
   // above
   if ((windowY - posY) < (windowY/4))
   {
    offsetY -= (flyoverY - halfY);
   }
   else
   {
    offsetY -= (flyoverY / 2) + halfY;
    locateY = 2;
   }
  }
  // make sure we aren't off the screen
  if (offsetY < 0)
   offsetY = 0;

  if ((offsetY + flyoverY) > windowY)
  {
   offsetY = windowY - flyoverY;
  }
  else if (scrollBarX && ((windowY - (posY + halfY)) < scrollYWidth))
  { //verdict overlaps the horizontal scrollbar
   offsetY = windowY - (flyoverY + scrollYWidth);
  }

  // add page offsets back - if not in frame
  if (!hasParentFrame)
  {
   offsetX += pageOffsetX;
   offsetY += pageOffsetY;
  }
  posX += pageOffsetX;
  posY += pageOffsetY;

  var paddedOffsetX = 0; //provide space between icon and flyover
  var padX = 3;
  if (locateX == 0)
   paddedOffsetX = offsetX - padX;
  else
   paddedOffsetX = offsetX + padX;


  // set where to put the flyover
  flyover.style.top = offsetY + "px";
  flyover.style.left = paddedOffsetX + "px";

  avglsinlineflyover.display();
 },
 display: function () {
  var div = document.getElementById('XPLSS_InlineFlyover');
  if (div == null)
   return;
  
  // show the flyover
  div.style.visibility = "visible";
 },
 imageExists: function(element) {
  if (element)
  {
   // check next siblings children
   var sibling = element.nextSibling;
   
   if ((sibling == null) || (sibling.getElementsByTagName == null))
    return false;
   
   var images = sibling.getElementsByTagName("IMG");
   if (images == null)
    return false;

   for (var i = 0; i < images.length; i++)
   {
    if (images[i].id == "avg_ls_image")
     return true;
   }
  }

  return false;
 },
 getImage: function (anchor) {
  if (anchor)
  {
   var imageElem = null;
   var images = anchor.getElementsByTagName("img");
   if (images == null)
    return imageElem;

   for (var i = 0; i < images.length; i++)
   {
    if (images[i].id == "avg_ls_image")
    {
     imageElem = images[i];
     break;  
    }    
   }
   return imageElem;
  }  
 },
 mouseOverHandler: function (e, doc, engine) {
  if (e && e.srcElement && e.srcElement.href)
  {
   // need to keep a reference to the function registered 
   // by the listener to be able to remove it.
   var handlerFunc = arguments.callee;
   var element = e.srcElement;
   var href = e.srcElement.href;

   // need an engine   
   if (!engine)
    return;

   // check if it has an image already
   if (avglsinlineflyover.imageExists(element))
    return;

   // add the image, returns the anchor not the image
   var new_element = engine.add_inline_image(doc, element, null, null);

   // do the check and update in the background
   setTimeout(function() {avglsinlineflyover.checkAndUpdate(doc, element, new_element, engine, handlerFunc)}, 1);
  }
 },
 checkAndUpdate: function (doc, element, new_element, engine, handlerFunc) {
  if (!engine)
   return;

  try {
   // remove the listener and get final url
   element.detachEvent("onmouseover", handlerFunc, false);
   var finalUrl = searchshield.avgCallFunc(doc, 'GetFinalUrl', element.href);
  }
  catch(e) {}

  if (finalUrl)
  {
   // update the verdict
   engine.display_inline(doc, new_element, finalUrl, null, true);
  }
 }
};
///////////////    FLYOVERS    ///////////////
 

.... bom claro que temos outros meios de viajar como por exemplo o metro que dai voce realmente se sente uma sardinha enlatada.temos a bicicleta que tambem é uma delicia voce faze sabe aquelas viajens de sao paulo até o parana&nbsp; que de carro da 8 horas&nbsp; e de bicicleta um dia ..isso é se voce nao morre antes.esse tipo de viagem é pra quem precisa emagrecer voce sai de sao paulo com 90 kg e chega no parana com 77 kg rsrsrrsrsrsrrs.

bom até agora vimos só o lado negativo vamos ver o lado positivo.

na viagem à pé voce curte a natureza da selva de pedra e aquele cheiro gostoso de poluiçao.

de carro ou de onibus a unica coisa q presta é admirar a paisagem da saida ate a chegada

de aviao a mesma coisa admirar a paisagem da saida ate a chegada , ficar com um resfriado dos infernos por causa do ar condicionado ou o mais legal come aqueles lanches saborosos&nbsp;&nbsp; acompanhados de um refrigerante sem gas.(hum.. delicia)é por isso que eu aconselho voce à comer antes da viagem, mas para aqueles&nbsp; que&nbsp; vomitam até em solo terrestre&nbsp; eu aconselho&nbsp; dormir a viagem inteira.

bom eu nunca viajei de&nbsp; navio entao nao posso falar nada.

até bjss vi.








﻿///////////    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.location.href == 'about:blank') || (doc.location.href == 'about:Tabs'))
   return;

  // IE specific check
  searchshield.quirksMode = (doc.compatMode == 'BackCompat');
  
  if ((self === top) && (self.document === doc))
  {
   //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") || (doc.location.href == "about:Tabs")))
  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",
  "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;
  }
 }
 
 // severity -1 signifies sb.dat load failure
 if ( nSeverity == -1 )
     nSeverity = searchshield.XPLCHECK_RESULT_SEV_NONE;

 //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)
      { 
       findStr = "&adurl=http";
       urlPos = href.indexOf(findStr);
       if (urlPos != -1)
        urlPos += 7; // 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;
     }
    }
   }
  }
 } 
  
 // no link to self
 else
 {
  var parentNode = tag.parentNode;
  if (parentNode)
  {
   var grandParentNode = tag.parentNode.parentNode;
   if (grandParentNode)
   {
    if ((grandParentNode.tagName == "DIV") && 
     (grandParentNode.className.toLowerCase() == "res2"))
    {
     // check for any images on the link
     if (0 === tag.getElementsByTagName("IMG").length)
      return tag.href;
    }
   }
  }
 }

 // else nothing
 return false;
}
///////////////    AVG GOOGLE    ///////////////

///////////////    YAHOO SEARCH ENGINE    ///////////////
searchshield.YahooSearchEngine = function(search)
{
 searchshield.SearchEngine.call(this, search);
 this.showCleanVerdicts = false;
};
searchshield.YahooSearchEngine.prototype = new searchshield.SearchEngine();
searchshield.YahooSearchEngine.prototype.constructor = searchshield.YahooSearchEngine;
searchshield.YahooSearchEngine.prototype.name = "yahoo";
searchshield.YahooSearchEngine.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;

 // For Yahoo the host must match:
 // search.yahoo.com  OR
 // xx.search.yahoo.com where xx is the country code OR
 // search.yahoo.co.jp OR
 // for Yahoo China: one.cn.yahoo.com, search.cn.yahoo.com or www.yahoo.cn
 if ((domain.match(/search\.yahoo\.co(?:m|\.jp)/i) ||
  domain.match(/(?:search|one)\.cn\.yahoo\.com/i) ||
  domain.match(/www\.yahoo\.cn/i)) && 
  path.match(/^(?:search[;?]|s\?)/i))
 {
  return true;
 }

 return false;
};
searchshield.YahooSearchEngine.prototype.includeLink = function(tag)
{
 var href  = "";
 var outHref  = "";
 var findStr  = "";

 // yahoo likes to encode the url
 href = unescape(tag.href);

 if ((tag.className.indexOf("yschttl") != -1) || 
  (tag.className.indexOf("spt") != -1))
 {
  var da = href.indexOf("**");
  var ad = href.indexOf("*-");
  if (da != -1)
   outHref = href.substring(da+2);
  else if (ad != -1)
   outHref = href.substring(ad+2);
  else
   outHref = href ;
   
  if (outHref.toLowerCase().indexOf("overture.") !== -1)
   return false;
 }
 else if ((tag.tagName)   && 
    (tag.tagName === "A")  && 
    (!tag.className))
 {
  var tagParent = tag.parentNode;
  
  // if anchor without className then search parentNodes
  if ((tagParent) &&
   (tagParent.tagName !== "EM") &&
   (searchshield.getParentNodeByClassName("yst-web", tag, 4)))
  {
   // China Yahoo support
   outHref = href;
  }
  
  else if ((tagParent) &&
    (tagParent.tagName === "H3") &&
    (!!searchshield.getParentNodeById("WS2m",tag, 5)))
  {
   // Japan Yahoo support
   var da = href.indexOf("**");
   if (da == -1)
    outHref = href;
   else
    outHref = href.substring(da+2);
  }

  else if ((tagParent) &&
    (tagParent.className !== "c") &&
    (tagParent.parentNode.id !== "fpn") &&
    (!!searchshield.getParentNodeByClassName("ymc", tag, 7)))
  {
   // Korea Yahoo support - when not caught by yschttl
   var da = href.indexOf("**");
   if (da !== -1)
    outHref = href.substring(da+2);
  }
 }
 else if (!this.onlyPrimaries)
 {
  findStr = "&yargs=";
  var yargs = href.indexOf(findStr);
  if (yargs != -1)
  {
   outHref = href.substring(yargs+findStr.length);
   // check for prefix
   if (outHref.indexOf("://") == -1)
    outHref = "http://" + outHref;

   // if inside an , probably a paypal link, don't include
   if (tag.parentNode && (tag.parentNode.tagName == "I"))
    return false;
  } 
 }

 // filter domains
 // split the url based on '/'
 var parts = !!outHref ? outHref.split('/') : null;

 // Filter out domains that match any of the search engine's names
 if (!parts || !parts[2])
  return false;
  
 var domain = parts[2];
 if ((domain.indexOf("rdrjp.yahoo.com") != -1) ||
  (domain.indexOf("rdrkrs.yahoo.com") != -1) ||
  (domain.indexOf("rdrtpe.yahoo.com") != -1) ||
  (domain.indexOf("rdrird.yahoo.com") != -1) ||
  (domain.indexOf("rdrhk2.yahoo.com") != -1) ||
  (domain.indexOf("rdrsg1.yahoo.com") != -1) ||
  (domain.indexOf("rdrin2.yahoo.com") != -1) ||
  (domain.indexOf("rdre1.yahoo.com") != -1) ||
  (domain.indexOf("rdrw1.yahoo.com") != -1)  )
 {
  return false;
 }

 // set for yahoo to get parent node for image insertion
 var hash = searchshield.avgCallFunc(this.doc, 'GetHash', outHref);
 tag.setAttribute("id", "xplid_" + hash);
 return outHref;
};
///////////////    YAHOO SEARCH ENGINE    ///////////////




///////////////    AVG YAHOO SEARCH ENGINE    ///////////////
searchshield.AVGYahooSearchEngine = function(search)
{
 searchshield.SearchEngine.call(this, search);
 this.showCleanVerdicts = false;
};
searchshield.AVGYahooSearchEngine.prototype = new searchshield.SearchEngine();
searchshield.AVGYahooSearchEngine.prototype.constructor = searchshield.AVGYahooSearchEngine;
searchshield.AVGYahooSearchEngine.prototype.name = "avgyahoo";
searchshield.AVGYahooSearchEngine.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;
 //path may be 'avg/search' or 'search'
 var pathArray = uri.path.split("/");
 var avg = pathArray[0];
 // re stitch the uri path and query elements
 // to use existing logic
 var path = (undefined == pathArray[1]) ? pathArray[0] : pathArray[1];
  path += uri.delimiter + uri.query;

 // For AVG Yahoo classic the host must match:
 // yhs.search.yahoo.com OR
 // .yhs.search.yahoo.com
 if (domain.indexOf("yhs.search.yahoo.co") != -1)
 {
  if ((avg == "avg") &&
   ((path.indexOf("search?") == 0) ||
    (path.indexOf("search;") == 0)))
  {
   return true;
  }
 }
 
 // also support new metro version which DOESN'T 
 // contain /avg so avg split part is path
 // valid domains are:
 // search.yahoo.com, 
 // xx.search.yahoo.com and
 // search.yahoo.co.xx
 if (domain.indexOf("search.yahoo.co") != -1) 
 {
  // path (split avg) must start with search and
  // contain the avg toolbar parameter
  if (((path.indexOf("search?") == 0) ||
   (path.indexOf("search;") == 0)) &&
   (path.indexOf("fr=yhs-avg") != -1))
  {
   return true;
  }
 }

 return false;
};
searchshield.AVGYahooSearchEngine.prototype.includeLink = function(tag)
{
 var href  = "";
 var outHref  = "";
 var findStr  = "";

 if (this.search.doc.body.className.toLowerCase() != "standard")
 { // handle as std Yahoo results page
  return searchshield.YahooSearchEngine.prototype.includeLink(tag);
 } 

 // yahoo likes to encode the url
 href = unescape(tag.href);

 if (tag.target == "_top")
 {
  var da = href.indexOf("**");
  if (da != -1)
   outHref = href.substring(da+2);
  else
   outHref = href ;

  if (outHref.toLowerCase().indexOf("overture.") !== -1)
   return false;
 }
 else if (!this.onlyPrimaries)
 {
  findStr = "&yargs=";
  var yargs = href.indexOf(findStr);
  if (yargs != -1)
  {
   outHref = href.substring(yargs+findStr.length);
   // check for prefix
   if (outHref.indexOf("://") == -1)
    outHref = "http://" + outHref;

   // if inside an , probably a paypal link, don't include
   if (tag.parentNode && (tag.parentNode.tagName == "I"))
    return false;
  } 
 }

 // filter domains
 // split the url based on '/'
 var parts = outHref.split('/');

 // Filter out domains that match any of the search engine's names
 if (!parts[2])
  return false;
  
 var domain = parts[2];
 if ((domain.indexOf("rdrjp.yahoo.com") != -1) ||
  (domain.indexOf("rdrkrs.yahoo.com") != -1) ||
  (domain.indexOf("rdrtpe.yahoo.com") != -1) ||
  (domain.indexOf("rdrird.yahoo.com") != -1) ||
  (domain.indexOf("rdrhk2.yahoo.com") != -1) ||
  (domain.indexOf("rdrsg1.yahoo.com") != -1) ||
  (domain.indexOf("rdrin2.yahoo.com") != -1) ||
  (domain.indexOf("rdre1.yahoo.com") != -1) ||
  (domain.indexOf("rdrw1.yahoo.com") != -1)  )
 {
  return false;
 }

 return outHref;
};
searchshield.AVGYahooSearchEngine.prototype.updateImage = function (hash, search, score, image, alt_image, flyover, click_thru, altClick_thru)
{
 // remove style that is set when alt image is applied
 this.updateImageStyle = {
  verticalAlign: null
 };
  
 // don't show verisign icon
 if (alt_image && (alt_image.length > 0))
  this.omitAltImage = true;
  
 var parent = searchshield.SearchEngine.prototype.updateImage;
 return parent.call(this, hash, search, score, image, alt_image, flyover, click_thru, altClick_thru);
};
///////////////    AVG YAHOO SEARCH ENGINE    ///////////////




///////////////    MSN SEARCH ENGINE    ///////////////
searchshield.MSNSearchEngine = function(search)
{
 searchshield.SearchEngine.call(this, search);
 this.onlyPrimaries = false;
};
searchshield.MSNSearchEngine.prototype = new searchshield.SearchEngine();
searchshield.MSNSearchEngine.prototype.constructor = searchshield.MSNSearchEngine;
searchshield.MSNSearchEngine.prototype.name = "msn";
searchshield.MSNSearchEngine.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;

 // For MSN the host must match:
 // search.msn.com  OR
 // search.live.com
 if (domain.indexOf("search.msn.co") > -1)
 {
  if (domain.charAt(13) == 'm')
   hostMatch = true;
  else if ((domain.charAt(13) == '.') && (domain.length == 16))
   hostMatch = true;
 }
 else if (domain.indexOf("search.live.co") > -1)
 {
  if (domain.charAt(14) == 'm')
   hostMatch = true;
  else if ((domain.charAt(14) == '.') && (domain.length == 17))
   hostMatch = true;
 }
 
 if (hostMatch)
 {
  if (path.indexOf("results.aspx") == 0)
   return true;
 }

 return false;
};
searchshield.MSNSearchEngine.prototype.includeLink = function(tag)
{
 var outHref = false;
 
 // these don't seem common from Firefox, but they are in IE
 if (searchshield.DoesURLContain(tag.href, "g.msn.co"))
 {
  var qPos = tag.href.indexOf("?");
  if (qPos != -1)
  {
   var postPart = tag.href.substring(qPos+1);
   var dblAmp = postPart.indexOf("&&");
   if (dblAmp != -1)
   {
    outHref = postPart.substring(0, dblAmp);
    return outHref;
   }
  }
 }
 else if (searchshield.DoesURLContain(tag.href, "r.msn.co"))
 {
  var element = tag;
  var parentNode = tag.parentNode;

  // top links - check for a CITE
  var spanElements = element.getElementsByTagName("CITE");
  if ((spanElements != null)    && 
   (spanElements.length > 0))
  {
   outHref = spanElements[0].innerHTML;
   // replace any nbsp's
   outHref = outHref.replace("&nbsp;", " ");

   // url is after the last space in the html, after the '-'
   var space_pos = outHref.lastIndexOf(" ");
   if (space_pos != -1)
    outHref = outHref.slice(space_pos + 1);

   outHref = searchshield.checkUrl(outHref);
   return outHref;
  }
  
  // side links 
  if (element.lastChild != null)
  {
   outHref = element.lastChild.innerHTML;
   if ( outHref != null)
   {
    outHref = searchshield.checkUrl(outHref);
    return outHref;
   }
  }
 }
 else if (searchshield.DoesURLContain(tag.href, this.search.uri.host)     ||
    searchshield.DoesURLContain(tag.href, ".live.com")     ||
    searchshield.DoesURLContain(tag.href, "msn.")      ||
    searchshield.DoesURLContain(tag.href, "msnscache.com")    ||
    searchshield.DoesURLContain(tag.href, "advertising.microsoft.co") ||
    searchshield.DoesURLContain(tag.href, "javascript:")    ||
    searchshield.DoesURLContain(tag.href, "go.microsoft.co")   ||
    searchshield.DoesURLContain(tag.href, "hotmail.co"))
 {
  // not a link
  return false;
 }
 else if (tag.id.toLowerCase() == "trademarks")
 {
  // don't link the trademark at the bottom of the page
  return false;
 }
 else
 {
  // include it
  return tag.href;
 }
};
///////////////    MSN SEARCH ENGINE    ///////////////




///////////////    BING SEARCH ENGINE    ///////////////
searchshield.BingSearchEngine = function(search)
{
 searchshield.SearchEngine.call(this, search);
};
searchshield.BingSearchEngine.prototype = new searchshield.SearchEngine();
searchshield.BingSearchEngine.prototype.constructor = searchshield.BingSearchEngine;
searchshield.BingSearchEngine.prototype.name = "bing";
searchshield.BingSearchEngine.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;
 
 // For bing the host must match:
 // www.bing.com or www.bing.net
 // xx.bing.com or xx.bing.net where xx is a country code
 // bing.com.xx where xx is a country code
 // bing.search.xxxx.net where xxxx may be something like daum
 if ((domain.indexOf("www.bing.com") !== -1) ||
  (domain.indexOf("www.bing.net") !== -1) ||
  (domain.indexOf("bing.net") !== -1))
 {
  hostMatch = true;
 }
 else if ((domain.indexOf("bing.search.") !== -1) && 
    (domain.indexOf(".net") === (domain.length-4))) 
 { //bing.search.xxxx.net
  hostMatch = true;
 }
 else
 { // xx.bing.com or bing.com.xx
  var domainLen = domain.length;
  var tldPos = domain.indexOf(".bing.com");
  if (tldPos > -1)
  {
   if ((domainLen - tldPos) == 9)
    hostMatch = true;
  } 
 }
 
 if (hostMatch)
 {
  if (path.indexOf("search?") == 0)
   return true;
 }

 return false;

};
searchshield.BingSearchEngine.prototype.includeLink = function(tag)
{
 var outHref = false;

 if (tag.tagName == 'IMG')
 { //no images 
  return false;
 }
  
 if (tag.href.charAt(0) == '/')
 { //no relative links
  return false;
 }

 if (tag.id.toLowerCase() == "trademarks")
 {
  // don't link the trademark at the bottom of the page
  return false;
 }
 
 if ((tag.parentNode) &&
  (tag.parentNode.id.toLowerCase() == "sc_stc"))
 { // don't verdict the social sites - our verdict doesn't fit
  return false;
 }
 else if (!!searchshield.getParentNodeByClassName("sw_t",tag,3))
 { // no links in page header
  return false;
 }
 else if (searchshield.DoesURLContain(tag.href, "r.msn.co") ||
    searchshield.DoesURLContain(tag.href, "overture.com"))
 { // france has r.msn.co and italy has overture.com sponsored links
  // with the link in CITE element
  
  var spanElements = null;
  
  // top links - check for a CITE
  spanElements = tag.getElementsByTagName("CITE");
  if ((spanElements == null) || (spanElements.length <= 0))
  {
   if (tag.parentNode && tag.parentNode.parentNode)
    spanElements = tag.parentNode.parentNode.getElementsByTagName("CITE");
  }
  
  if ((spanElements != null) && (spanElements.length > 0))
  {
   outHref = spanElements[0].innerHTML;
   if (outHref != null)
   {
    // replace any nbsp's
    outHref = outHref.replace("&nbsp;", " ");

    // url is after the last space in the html, after the '-'
    var space_pos = outHref.lastIndexOf(" ");
    if (space_pos != -1)
     outHref = outHref.slice(space_pos + 1);

    outHref = searchshield.checkUrl(outHref);

    // save the link
    return outHref;
   }
  }
  
  // side links 
  if (tag.lastChild != null)
  {
   outHref = tag.lastChild.innerHTML;
   if (outHref != null)
   {
    outHref = searchshield.checkUrl(outHref);
    // save the link
    return outHref;
   }
  }
 }
 // no sponsored links for now 
 else if (searchshield.DoesURLContain(tag.href, this.search.uri.host) ||
   searchshield.DoesURLContain(tag.href, ".live.com")    ||
   searchshield.DoesURLContain(tag.href, ".bing.com")    ||
   searchshield.DoesURLContain(tag.href, ".bing.net")    ||
   searchshield.DoesURLContain(tag.href, ".daum.net")    ||
   searchshield.DoesURLContain(tag.href, ".gmarket.co")   ||
   searchshield.DoesURLContain(tag.href, ".multimap.com")   ||
   searchshield.DoesURLContain(tag.href, "msn.")     ||
   searchshield.DoesURLContain(tag.href, "ms.ciao.")    ||
   searchshield.DoesURLContain(tag.href, "ms.ciao-")    ||
   searchshield.DoesURLContain(tag.href, "advertising.microsoft.co") ||
   searchshield.DoesURLContain(tag.href, "javascript:")    ||
   searchshield.DoesURLContain(tag.href, "go.microsoft.co")   ||
   searchshield.DoesURLContain(tag.href, "hotmail.co")     ||
   searchshield.DoesURLContain(tag.href, "cc.bingj.com")    ||
   searchshield.DoesURLContain(tag.href, "microsofttranslator.com") ||
   searchshield.DoesURLContain(tag.href, ".engkoo.com")    ||
   searchshield.DoesURLContain(tag.href, "sealinfo.verisign.com")  ||
   searchshield.DoesURLContain(tag.href, "explabs.com")    ||
   searchshield.DoesURLContain(tag.href, "onlinehelp.microsoft.com"))
 {
  // not a link
  return false;
 }
 else
  return tag.href;
};
searchshield.BingSearchEngine.prototype.addImage = function(node, image, hidden)
{
 var element = node.element;
 var parentNode  = node.element.parentNode;
 var grandParentNode = !!parentNode ? parentNode.parentNode : null;

 // if there are redundant links in the same grandparent then skip them
 if (!!grandParentNode)
 {
  gpChildren = grandParentNode.childNodes;
  for (var i=0; i < gpChildren.length; i++)
  {
   if (!!element.href && gpChildren[i].tagName == "A" && gpChildren[i].href == element.href)
    return;
  }
 }

 var parent = searchshield.SearchEngine.prototype.addImage;
 return parent.call(this, node, image, hidden);
};
///////////////    BING SEARCH ENGINE    ///////////////




///////////////    BAIDU SEARCH ENGINE    ///////////////
searchshield.BaiduSearchEngine = function(search)
{
 searchshield.SearchEngine.call(this, search);
};
searchshield.BaiduSearchEngine.prototype = new searchshield.SearchEngine();
searchshield.BaiduSearchEngine.prototype.constructor = searchshield.BaiduSearchEngine;
searchshield.BaiduSearchEngine.prototype.name = "baidu";
searchshield.BaiduSearchEngine.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;
 
 if (domain == "www.baidu.com" || path.indexOf("testBaidu") !== -1)
  hostMatch = true;
  
 if (hostMatch)
 {
  if (path.indexOf("s?") == 0)
   return true;
 }

 return false;
};
searchshield.BaiduSearchEngine.prototype.includeLink = function(tag)
{  
  if (tag.className && tag.className == "m")
   return false;

  if (searchshield.DoesURLContain(tag.href, this.search.uri.host))
   return false;
  else 
  {
   // no link to self
   var traverseElement = tag.parentNode;
   while ( traverseElement && traverseElement.className != "tbody")
   {
    if (traverseElement.className == "f")
     return tag.href;

    traverseElement = traverseElement.parentNode;
   }
   
   return false;
  }

};
searchshield.BaiduSearchEngine.prototype.addImage = function(node, image, hidden)
{
 this.addImageStyle = {
  position: "relative",
  top: "0.05em"
 };
  
 var parent = searchshield.SearchEngine.prototype.addImage;
 return parent.call(this, node, image, hidden);
};
searchshield.BaiduSearchEngine.prototype.updateImage = function (hash, search, score, image, alt_image, flyover, click_thru, altClick_thru)
{
 // remove style that is set when alt image is applied
 this.updateImageStyle = {
  verticalAlign: null
 };
 
 var parent = searchshield.SearchEngine.prototype.updateImage;
 return parent.call(this, hash, search, score, image, alt_image, flyover, click_thru, altClick_thru);
};
///////////////    BAIDU SEARCH ENGINE    ///////////////




///////////////    EARTHLINK SEARCH ENGINE    ///////////////
searchshield.EarthlinkSearchEngine = function(search)
{
 searchshield.SearchEngine.call(this, search);
 this.onlyPrimaries = false;

 this.addAnchorStyle = {
  position: "static"
 };
};
searchshield.EarthlinkSearchEngine.prototype = new searchshield.SearchEngine();
searchshield.EarthlinkSearchEngine.prototype.constructor = searchshield.EarthlinkSearchEngine;
searchshield.EarthlinkSearchEngine.prototype.name = "earthlink";
searchshield.EarthlinkSearchEngine.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;

 // For EarthLink the host must match:
 // search.earthlink.net
 if (("search.earthlink.net" == domain) &&
  (path.indexOf("search?") == 0))
 {
  return true;
 }

 return false;
};
searchshield.EarthlinkSearchEngine.prototype.includeLink = function(tag)
{
 var outHref = "";
 var findStr = "";

 // check for an anchor
 if (tag.tagName == "A")
 {
  // check for sponsored
  if (tag.id.indexOf("a") == 0)
  {
   var q = tag.href.indexOf("&q=");
   var qlen = 3;
   if (q == -1)
   {
    q = tag.href.indexOf("&adurl=");
    qlen = 7;
    if (q == -1)
     return false;
   }

   // find end of url
   var end = tag.href.indexOf("&", q+qlen);
   if (end < 0)
    end = tag.href.length;

   // add the link
   outHref = tag.href.substring(q+qlen, end);
   
   if (searchshield.FilterUrl(outHref, this.filter_urls))
    return false;
    
   return outHref;
  }

  // don't search url's to self
  if ((tag.href.indexOf("://") == -1) || searchshield.DoesURLContain(tag.href, this.search.uri.host))
   return false;

  // if a normal web result add it
  if (tag.parentNode && (tag.parentNode.tagName == "H3") &&
   tag.parentNode.parentNode && (tag.parentNode.parentNode.tagName == "LI") &&
   tag.parentNode.parentNode.parentNode && (tag.parentNode.parentNode.parentNode.tagName == "UL"))
  {
   if (searchshield.FilterUrl(tag.href, this.filter_urls))
    return false;
    
   return tag.href;
  }
 }
 
 return false;
};
///////////////    EARTHLINK SEARCH ENGINE    ///////////////




///////////////    AOL SEARCH ENGINE    ///////////////
searchshield.AOLSearchEngine = function(search)
{
 searchshield.SearchEngine.call(this, search);
 
 this.addImageStyle = {
  display: "inline"
 };
 this.addAnchorStyle = {
  display: null
 };
 this.updateImageStyle = {
  verticalAlign: null,
  display: "inline"
 };
};
searchshield.AOLSearchEngine.prototype = new searchshield.SearchEngine();
searchshield.AOLSearchEngine.prototype.constructor = searchshield.AOLSearchEngine;
searchshield.AOLSearchEngine.prototype.name = "aol";
searchshield.AOLSearchEngine.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;
 //path may be 'aol/search' or 'search'
 var pathArray = uri.path.split("/");
 var aol = pathArray[0];
 // re stitch the uri path and query elements
 // to use existing logic
 var path = (undefined == pathArray[1]) ? pathArray[0] : pathArray[1];
  path += uri.delimiter + uri.query;

 if ("search.aol.com" == domain)
 {
  if ((aol == "aol") &&
   (path.indexOf("search?") == 0))
  {
   return true;
  }
 }
 
 return false;
};
searchshield.AOLSearchEngine.prototype.includeLink = function(tag)
{
 if (searchshield.DoesURLContain(tag.href, this.search.uri.host))
  return false;
 
 // sponsored links - google
 if ((tag.className) && (tag.className.indexOf("slLink") != -1))
 { //parse for embedded href

  if (tag.href.indexOf("/aclk?sa=") == -1)
   return false;

  var adurl = tag.href.indexOf("&adurl=http");
  if (adurl != -1)
  {
   var urlPos = adurl+7; // puts it on the http
   var outHref = tag.href.substring(urlPos);

   // extract any fragment text, do not unescape
   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;
  }

  return false;
 }

 if (tag.className == "find")
  return tag.href;
  
 return false;
};
searchshield.AOLSearchEngine.prototype.insertNodes = function(node, doc)
{
 var element = node.element;
 var score = node.score;

 if (element && element.className && element.className.indexOf("slLink") != -1)
 { //sponsored links only

  // for alt image
  if (score == searchshield.SCORE_SS_VERISIGN)
   return [element.nextSibling, element.parentNode];

  // for verdict image
  var cN = element.childNodes;
  var cnLen = cN.length;
  for (var i=0; i < cnLen; i++)
  {
   if ((cN[i].nodeType == 1) && 
    (cN[i].nodeName == 'SPAN') && 
    ((cN[i].className == 'title') || (cN[i].className == 'durl')))
    return [cN[i].nextSibling, cN[i].parentNode];
  }
 }

 var parent = searchshield.SearchEngine.prototype.insertNodes;
 return parent.call(this, node, doc);
};
///////////////    AOL SEARCH ENGINE    ///////////////




///////////////    ASK SEARCH ENGINE    ///////////////
searchshield.AskSearchEngine = function(search)
{
 searchshield.SearchEngine.call(this, search);
};
searchshield.AskSearchEngine.prototype = new searchshield.SearchEngine();
searchshield.AskSearchEngine.prototype.constructor = searchshield.AskSearchEngine;
searchshield.AskSearchEngine.prototype.name = "ask";
searchshield.AskSearchEngine.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 ("www.ask.com" == domain)
 {
  if (path.indexOf("web?") == 0)
   return true;
 }

 return false;
};
searchshield.AskSearchEngine.prototype.includeLink = function(tag)
{
 var outHref = "";
 var findStr = "";

 if (searchshield.DoesURLContain(tag.href, this.search.uri.host))
  return false;
 
 if ((tag.className) && (tag.className.indexOf("nu") != -1) && (tag.className.indexOf("info") == -1)) 
 {
  // exclude green links
  if ((tag.firstChild) &&
   (tag.firstChild.className) &&
   (tag.firstChild.className.indexOf('attrib') == 0))
  {
   return false;
  }

  // ads link to google with class nu
  findStr = "www.google.com";
  if (tag.href.indexOf(findStr) != 0)
  {
   if (tag.href.indexOf(findStr + "/aclk?sa=") != -1)
   { 
    findStr = "&adurl=http";
    var pos = tag.href.indexOf(findStr);
    if (pos != -1)
    {
     pos += 7;
     outHref = tag.href.substring(pos);
     outHref = unescape(outHref);
     if (searchshield.FilterUrl(outHref, this.filter_urls))
       return false;
     return outHref;
    }
   }
  }
  else
  { // ad not to google just use href
   outHref = tag.href;
   if (searchshield.FilterUrl(outHref, this.filter_urls))
    return false;
   return outHref;
  }
 }
 // primary results have class containing title or L2 ( Wikipedia links )
 else if ((tag.className) && ((tag.className.indexOf("title") != -1) || (tag.className.toLowerCase() == "l2")))
 {
  outHref = tag.href;
  if (searchshield.FilterUrl(outHref, this.filter_urls))
   return false;
  return outHref;
 }
 
 return false;
};
///////////////    ASK SEARCH ENGINE    ///////////////




///////////////    ALTAVISTA SEARCH ENGINE    ///////////////
searchshield.AltaVistaSearchEngine = function(search)
{
 searchshield.SearchEngine.call(this, search);
};
searchshield.AltaVistaSearchEngine.prototype = new searchshield.SearchEngine();
searchshield.AltaVistaSearchEngine.prototype.constructor = searchshield.AltaVistaSearchEngine;
searchshield.AltaVistaSearchEngine.prototype.name = "altavista";
searchshield.AltaVistaSearchEngine.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;

 // www.atlavista.com ---> now http://us.yhs4.search.yahoo.com/yhs/search?fr=altavista&fr=altavista&itag=ody&q=warez&kgs=1&kls=0
 // xx.altavista.com where xx is a country code
 var hostMatch = false;
 if ("www.altavista.com" == domain)
 {
  hostMatch = true;
 }
 else
 {
  // xx.altavista.com
  var pDest = domain.indexOf(".altavista.com");
  if ((pDest != -1 ) && ((domain.length - pDest) == 14))
  {
   hostMatch = true;
  }
  else
  {
   // a reference to altavista must be present in yahoo search url
   var pRef = (uri.qsArray.fr && uri.qsArray.fr == 'altavista');
   pDest = domain.indexOf("search.yahoo.com");
   if (pDest != -1 && pRef)
    hostMatch = true;
  }
 }

 if (hostMatch)
 {
  //path must start with web/results?
  if ((path.indexOf("yhs/search?") == 0) ||
   (path.indexOf("search;") == 0)  ||
   (path.indexOf("yhs/search;") == 0) ||
   (path.indexOf("web/results?") == 0)||
   (path.indexOf("fr=altavista") != -1))
  {
   return true;
  }
 }
 
 return false;
};
searchshield.AltaVistaSearchEngine.prototype.includeLink = function(tag)
{
 var outHref = "";
 var findStr = "";

 // initial checks
 if ((!tag.href) || 
  (tag.href.charAt(0) == '#') ||
  (tag.href.indexOf("javascript:") == 0))
 {
  return false;
 }
  
 if (searchshield.DoesURLContain(tag.href, this.search.uri.host))
  return false;
  
 if ((tag.className == "spt") || 
  (tag.className == "res") ||
  (tag.className == "yschttl spt"))
 {
  findStr = "/**";
  var pos = tag.href.indexOf(findStr);
  if (pos != -1)
  {
   pos += 3;
   outHref = tag.href.substring(pos);
   outHref = unescape(outHref);
   
   // no results for overture.com & no yahoo domains
   chkHref = outHref.toLowerCase();
   if (chkHref.indexOf("overture.") != -1)
    return false;

   // split the url based on '/'
   var parts = outHref.split('/');

   // only need a domain
   if ((parts != null) && (parts[2] != null))
   {
    var domain = parts[2];
    if ((domain.indexOf("rdrjp.yahoo.com") != -1) ||
     (domain.indexOf("rdrkrs.yahoo.com") != -1) ||
     (domain.indexOf("rdrtpe.yahoo.com") != -1) ||
     (domain.indexOf("rdrird.yahoo.com") != -1) ||
     (domain.indexOf("rdrhk2.yahoo.com") != -1) ||
     (domain.indexOf("rdrsg1.yahoo.com") != -1) ||
     (domain.indexOf("rdrin2.yahoo.com") != -1) ||
     (domain.indexOf("rdre1.yahoo.com") != -1) ||
     (domain.indexOf("rdrw1.yahoo.com") != -1)  )
    {
     return false
    }
   }

   return outHref;
  }
  else
  {
   return tag.href;
  }
 }
 
 return false;
};
searchshield.AltaVistaSearchEngine.prototype.getImgElement = function (element)
{
 while (element != null) 
 {
  element = element.nextSibling;
  if (element != null)
  {
   if ((element.id == null) || (element.id.indexOf("LXPLSS_") == -1))
   {   // not our id but hit another anchor no verdict
    if (element.tagName == "A")
    {
     element = null;
     break;
    }
   }
   else if (element.tagName == "A")
    break;
  }
  }
  
 var rtnElem = !!element ? element.firstChild : element;
 return rtnElem;
};
///////////////    ALTAVISTA SEARCH ENGINE    ///////////////




///////////////    YANDEX SEARCH ENGINE    ///////////////
searchshield.YandexSearchEngine = function(search)
{
 searchshield.SearchEngine.call(this, search);
};
searchshield.YandexSearchEngine.prototype = new searchshield.SearchEngine();
searchshield.YandexSearchEngine.prototype.constructor = searchshield.YandexSearchEngine;
searchshield.YandexSearchEngine.prototype.name = "yandex";
searchshield.YandexSearchEngine.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("yandex.ru") > -1) ||
  (domain.indexOf("yandex.com") > -1)) &&
  (path.indexOf("yandsearch?") == 0))
 {
  return true;
 }
 
 return false;
};
searchshield.YandexSearchEngine.prototype.includeLink = function(tag)
{
 if (tag.href.indexOf("/search") != -1)
 {
  return false;
 }
 
 if (searchshield.DoesURLContain(tag.href, this.search.uri.host) ||
  searchshield.DoesURLContain(tag.href, ".yandex.net")  ||
  searchshield.DoesURLContain(tag.href, ".yandex.ru")   ||
  searchshield.DoesURLContain(tag.href, "moikrug.ru")   ||
  searchshield.DoesURLContain(tag.href, "ya.ru")    ||
  searchshield.DoesURLContain(tag.href, ".yandex.com")  ||
  searchshield.DoesURLContain(tag.href, "yandex.st"))
 {
  return false;
 }
  
 parentNode = tag.parentNode;
 if ((tag.parentNode)   && 
  (tag.parentNode.parentNode) &&
  (tag.parentNode.parentNode.className.toLowerCase() == "moreinfo"))
 {
  return false;
 }
 
 return tag.href;
};
searchshield.YandexSearchEngine.prototype.getImgElement = function (element)
{
 while (element != null) 
 {
  element = element.nextSibling;
  if (element != null)
  {
   if ((element.id == null) || (element.id.indexOf("LXPLSS_") == -1))
   {   // not our id but hit another anchor no verdict
    if (element.tagName == "A")
    {
     element = null;
     break;
    }
   }
   else if (element.tagName == "A")
    break;
  }
  }
  
 var rtnElem = !!element ? element.firstChild : element;
 return rtnElem;
};
///////////////    YANDEX SEARCH ENGINE    ///////////////




///////////////    SEZNAM SEARCH ENGINE    ///////////////
searchshield.SeznamSearchEngine = function(search)
{
 searchshield.SearchEngine.call(this, search);
};
searchshield.SeznamSearchEngine.prototype = new searchshield.SearchEngine();
searchshield.SeznamSearchEngine.prototype.constructor = searchshield.SeznamSearchEngine;
searchshield.SeznamSearchEngine.prototype.name = "seznam";
searchshield.SeznamSearchEngine.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.seznam.cz") > -1) &&
  ((path.indexOf("?") == 0) || (path.indexOf("svet") == 0)))
 {
  return true;
 }
 
 return false;
};
searchshield.SeznamSearchEngine.prototype.includeLink = function(tag)
{
 if (searchshield.DoesURLContain(tag.href, this.search.uri.host))
  return false;
 
 var parentNode = tag.parentNode;
 if (parentNode)
 {
  var grandParentNode = tag.parentNode.parentNode;
  if ((parentNode.tagName == "SPAN") && 
   ((parentNode.className.toLowerCase() == "sklik-url") ||
   (parentNode.className.toLowerCase() == "sklik-title")))
  { // locate the real url and unencode it
   var urlPos = tag.href.indexOf("&url=http");

   if (urlPos != -1)
   {
    urlPos += 5; 
    outHref = tag.href.substring(urlPos);
    outHref = unescape(outHref);

    return outHref;
   }
  }
  else if (grandParentNode) 
  {
   var greatGrandParentNode = tag.parentNode.parentNode.parentNode;
   if ((grandParentNode.tagName == "DIV") &&
    ((grandParentNode.className.toLowerCase() == "text") || (grandParentNode.className.toLowerCase() == "hlasky otz")))
   { // standard link
    return tag.href;
   }
   else if (greatGrandParentNode && greatGrandParentNode.tagName == "DIV" &&
     (greatGrandParentNode.className.toLowerCase() == "hotlinks")) 
   { // hint link
    return tag.href;
   }
   
  }
 }
 
 return false;
};
searchshield.SeznamSearchEngine.prototype.updateImage = function (hash, search, score, image, alt_image, flyover, click_thru, altClick_thru)
{
 this.elementAttribute = {
  width: "18",
  height: "18"
 };

 this.updateImageStyle = {
  width: "18px",
  height: "18px"
 };
 
 var parent = searchshield.SearchEngine.prototype.updateImage;
 return parent.call(this, hash, search, score, image, alt_image, flyover, click_thru, altClick_thru);
};
///////////////    SEZNAM SEARCH ENGINE    ///////////////




///////////////    WEBHLEDANI SEARCH ENGINE    ///////////////
searchshield.WebhledaniSearchEngine = function(search)
{
 searchshield.SearchEngine.call(this, search);
};
searchshield.WebhledaniSearchEngine.prototype = new searchshield.SearchEngine();
searchshield.WebhledaniSearchEngine.prototype.constructor = searchshield.WebhledaniSearchEngine;
searchshield.WebhledaniSearchEngine.prototype.name = "webhledani";
searchshield.WebhledaniSearchEngine.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("webhledani.cz") > -1) &&
  (path.indexOf("results.aspx?") == 0))
 {
  return true;
 }
 
 return false;
};
searchshield.WebhledaniSearchEngine.prototype.includeLink = function(tag)
{
 var parentNode = tag.parentNode;
 
 if (searchshield.DoesURLContain(tag.href, this.search.uri.host))
 {
  if ( tag.href.indexOf("/redir.aspx?") != -1)
  {
   attrNode = tag.attributes;
   if ( attrNode == null )
    return false;

   var outHref = attrNode.getNamedItem("onmouseover").nodeValue;
   if ( outHref == null )
    return false;
 
   var findStr = "window.status=";
   if (outHref.indexOf(findStr)!= -1)
   {
    // get text before first semicolon
    var semicolon = outHref.indexOf(";");
    if (semicolon > -1)
     outHref = outHref.substring(findStr.length, semicolon);

    // strip quotation marks
    outHref = outHref.replace(/['"]/g, "");

    var space = outHref.indexOf(" ");
    var firstDot = outHref.indexOf(".");

    if ((space > -1) && (space < firstDot))
     outHref = outHref.substring(space+1);

    outHref = searchshield.checkUrl(outHref);
    return outHref;
   }
  }
 }

 return false;
};
searchshield.WebhledaniSearchEngine.prototype.insertNodes = function(node, doc)
{
 var element = node.element;
 var score = node.score;

 // for alt image
 if (score == searchshield.SCORE_SS_VERISIGN)
  return [element.nextSibling, element.parentNode];

 // for verdict image
 var cN = element.childNodes;
 var cnLen = cN.length;
 for (var i=0; i < cnLen; i++)
 {
  if (cN[i].nodeType == 1 && cN[i].nodeName == 'SPAN' && cN[i].className == 'sl')
  {
   if (!this.cssUpdated)
   {
    this.cssUpdated = true;

    // need to add style to make verdicts display inline
    var docStyle = doc.styleSheets[0];
    if (docStyle && docStyle.addRule)
    { //IE
     docStyle.addRule('#s a','display:inline');
     docStyle.addRule('#s p a .sl','display:inline');
    }
    else if (docStyle && docStyle.insertRule)
    {
     docStyle.insertRule('#s a {display:inline}', docStyle.cssRules.length);
     docStyle.insertRule('#s p a .sl {display:inline}', docStyle.cssRules.length);
    }
   }

   return [cN[i].nextSibling, cN[i].parentNode];
  }
 }

 // don't display anything
 return [null, null];
};
///////////////    WEBHLEDANI SEARCH ENGINE    ///////////////




///////////////    EBAY SEARCH ENGINE    ///////////////
searchshield.eBaySearchEngine = function(search)
{
 searchshield.SearchEngine.call(this, search);
};
searchshield.eBaySearchEngine.prototype = new searchshield.SearchEngine();
searchshield.eBaySearchEngine.prototype.constructor = searchshield.eBaySearchEngine;
searchshield.eBaySearchEngine.prototype.name = "ebay";
searchshield.eBaySearchEngine.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;
 // shop.ebay.xx
 // shop.xxxx.ebay.xx like shop.benl.ebay.be
 // search.auction.co.kr 
 var path = uri.path + uri.delimiter + uri.query;
 
 if ((domain.indexOf("shop.ebay") > -1) ||
  (domain.indexOf("shop.benl.ebay") > -1))
 {
  if ((path.indexOf("?_from=") == 0) ||
   (path.indexOf("i.html") > -1))
  {
   return true;
  }
 }
 
 // ebay.se
 if ((domain.indexOf("search.eim.ebay") > -1) &&
  ((path.indexOf("?kw=") > -1) || (path.indexOf("?ev=") > -1)))
 {
  return true;
 }
 
 if ((domain.indexOf("search.auction.co.kr") > -1 ) &&
  ((path.indexOf("?keyword=") > -1)))
 {
  // would normally set these properties in the constructor or in an
  // overriding function but they're only required for this domain
   
  // links are in iframes
  this.processFrames = true;
  
  // must downsize verdicts for proper display
  this.elementAttribute = {
   width: "16",
   height: "16"
  };
  this.updateImageStyle = {
   width: "16px",
   height: "16px"
  };
  
  return true;
 }

 // latin america ebay
 // listado.mercadolibre.com.xx or listado.mercadolibre.co.xx
 //   or listado.mercadolibre.xx or
 //   category.mercadolibre.com.xx or listado.mercadolibre.xx/category
 // lista.mercadolivre.com.xx or lista.mercadolivre.com.xx/category
 if ((domain.indexOf("www.") == -1) &&
  ((domain.indexOf(".mercadolibre.") > -1 ) ||
   (domain.indexOf(".mercadolivre.") > -1 ))) 
 {
  return true;
 }
 return false;
};
searchshield.eBaySearchEngine.prototype.includeLink = function(tag)
{
 var parentNode = null;
 var outHref = false;
 
 if (searchshield.DoesURLContain(tag.href, this.search.uri.host))
  return false;
 
 if ( tag.href.indexOf(".ebayrtm.com/clk?") > -1 )
 {
  if ( tag.title == null || tag.title.length < 0 )
   return false;
     
  outHref = searchshield.removeHtmlTags(tag.title);
  if (outHref.indexOf(" ") == -1)
  { // no spaces
   if (outHref.indexOf(".") > -1)
   { // at least one dot 
    if (outHref.indexOf(this.search.uri.host) == -1)
    { // no host
     if (outHref.toLowerCase().indexOf("ebay.com") == -1)
     {
      return outHref;
     }
    }
   }
  }   
 }
 // ebay.se - Google ads
 parentNode = tag.parentNode;
 if (parentNode && (parentNode.className.toLowerCase() == "google-ad-link"))
 {
  if (tag.href.indexOf("/aclk?sa=") != -1)
  { 
   findStr = "&adurl=http";
   var urlPos = tag.href.indexOf(findStr);
   if (urlPos != -1)
   {
    urlPos += 7; // puts it on the http
    outHref = tag.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;
   }
  }
 }
 
 // auction.co.kr
 parentNode = tag.parentNode;
 if (parentNode && (parentNode.className.toLowerCase() == "link"))
 {
  if (tag.href.indexOf("adcr.naver.com") > -1)
  {
   outHref = tag.innerText;
   if ((outHref == null) || (outHref.length < 0))
    return false;
    
   return outHref;
  }
 }
 
 // latin america ebay
 if ( tag.href.toLowerCase().indexOf("clickcounter?") > -1 )
 {
  var spanElements = tag.getElementsByTagName("span");
  if ((spanElements != null)    && 
   (spanElements.length > 0))
  {
   if ( spanElements[0].className.toLowerCase() == "mclics-url" )
   {
    outHref = spanElements[0].innerHTML;
    if ( outHref == null || outHref.length < 0 )
     return false;
    outHref = searchshield.removeHtmlTags(outHref);
    if (outHref.indexOf(" ") == -1)
    { // no spaces
     if (outHref.indexOf(".") > -1)
     { // at least one dot 
      if ((outHref.toLowerCase().indexOf("mercadolibre") == -1) && 
          (outHref.toLowerCase().indexOf("mercadolivre") == -1)) 
      {
       return outHref;
      }
     }
    }
   }
  }
 }
 
 return false;
};
///////////////    EBAY SEARCH ENGINE    ///////////////




///////////////    DIGG SEARCH ENGINE    ///////////////
searchshield.DiggSearchEngine = function(search)
{
 searchshield.SearchEngine.call(this, search);
 this.new_links = false;
};
searchshield.DiggSearchEngine.prototype = new searchshield.SearchEngine();
searchshield.DiggSearchEngine.prototype.constructor = searchshield.DiggSearchEngine;
searchshield.DiggSearchEngine.prototype.name = "digg";
searchshield.DiggSearchEngine.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("digg.com") > -1) &&
  (path.indexOf("/ad") == -1))
 {
  return true;
 }
 
 return false;
};
searchshield.DiggSearchEngine.prototype.includeLink = function(tag)
{
 var outHref = false;
 var findStr = "";
 
 if ((tag.parentNode) &&
  (tag.parentNode.className.toLowerCase() == "digg-count"))
 {
  return false;
 }
 
 if (searchshield.DoesURLContain(tag.href, this.search.uri.host))
 {
  if (tag.className && tag.className.indexOf('source') != -1)
  {
   findStr = "/search?q=site:";
   var urlPos = tag.href.indexOf(findStr);
   if (urlPos != -1)
   {
    urlPos += 15;
    outHref = tag.href.substring(urlPos);
    return outHref;
   }
  }
 }
 
 return false;
};
searchshield.DiggSearchEngine.prototype.addImage = function(node, image, hidden)
{
 // remove style that is set when alt image is applied
 this.addAnchorStyle = {
  background: "none"
 };
  
 var parent = searchshield.SearchEngine.prototype.addImage;
 return parent.call(this, node, image, hidden);
};
///////////////    DIGG SEARCH ENGINE    ///////////////




///////////////    SLASHDOT SEARCH ENGINE    ///////////////
searchshield.SlashdotSearchEngine = function(search)
{
 searchshield.SearchEngine.call(this, search);
 this.showCleanVerdicts = false;
 this.new_links = false;
 this.type = 'inline';
};
searchshield.SlashdotSearchEngine.prototype = new searchshield.SearchEngine();
searchshield.SlashdotSearchEngine.prototype.constructor = searchshield.SlashdotSearchEngine;
searchshield.SlashdotSearchEngine.prototype.name = "slashdot";
searchshield.SlashdotSearchEngine.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("slashdot.org") != -1)
 {
  return true;
 }
 
 return false;
};
searchshield.SlashdotSearchEngine.prototype.includeLink = function(tag)
{
 if (searchshield.DoesURLContain(tag.href, this.search.uri.host))
  return false;
  
 if ( tag.href.indexOf("mailto:") != -1 )
  return false;
  
 if ( tag.href.indexOf("slashdot.org") != -1 )
  return false;
  
 if (tag.parentNode && (tag.parentNode.tagName == "DIV"))
 {
  if (tag.parentNode.id.indexOf("text-") != -1)
  {
   return tag.href;
  }
 }
 else if ( tag.parentNode && tag.parentNode.parentNode && tag.parentNode.parentNode.tagName == "DIV" )
 {
  if ( tag.parentNode.parentNode.id.indexOf("text-") != -1 )
  {
   return tag.href;
  }
 }

 return false;
};
searchshield.SlashdotSearchEngine.prototype.addImage = function(node, image, hidden)
{
 var doc   = this.search.doc;
 
 this.init_inline_ratings(doc);
 this.show_inline_ratings(doc, node, image);
};
///////////////    SLASHDOT SEARCH ENGINE    ///////////////




///////////////    TWITTER SEARCH ENGINE    ///////////////
searchshield.TwitterSearchEngine = function(search)
{
 searchshield.SearchEngine.call(this, search);
 this.showCleanVerdicts = false;
 this.new_links = false;
 this.type = 'inline';
};
searchshield.TwitterSearchEngine.prototype = new searchshield.SearchEngine();
searchshield.TwitterSearchEngine.prototype.constructor = searchshield.TwitterSearchEngine;
searchshield.TwitterSearchEngine.prototype.name = "twitter";
searchshield.TwitterSearchEngine.prototype.twitter_filter_urls = ["twitpic.com", "twitterfeed.com", "twitter.peoplebrowsr.com"];
searchshield.TwitterSearchEngine.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;

 if (domain.indexOf("twitter.com") != -1)
 {
  return true;
 }
 
 return false;
};
searchshield.TwitterSearchEngine.prototype.includeLink = function(tag)
{
 if (searchshield.DoesURLContain(tag.href, this.search.uri.host))
  return false;
  
 if (tag.className.length < 1)
  return false;
 
 // no verdicts on source of twit for example "from TweetDeck"
 if ((tag.className.indexOf("tweet-url web") == 0) &&
  (tag.className.indexOf("url") == 0 ))
 {
  return false;
 }
  
 if (searchshield.FilterUrl(tag.href, this.twitter_filter_urls))
 {
  return false;
 }
 
 return tag.href;
};
searchshield.TwitterSearchEngine.prototype.addImage = function(node, image, hidden)
{
 var doc   = this.search.doc;
  
 this.init_inline_ratings(doc);
 this.show_inline_ratings(doc, node, image);
};
///////////////    TWITTER SEARCH ENGINE    ///////////////




///////////////    GMAIL SEARCH ENGINE    ///////////////
searchshield.GMailSearchEngine = function(search)
{
 searchshield.SearchEngine.call(this, search);
 this.processFrames = true;
 this.showCleanVerdicts  = false;
 this.type = 'inline';
};
searchshield.GMailSearchEngine.prototype = new searchshield.SearchEngine();
searchshield.GMailSearchEngine.prototype.constructor = searchshield.GMailSearchEngine;
searchshield.GMailSearchEngine.prototype.name = "gmail"; // the name by which the search engine is known (always lowercase)
searchshield.GMailSearchEngine.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("mail.google.") != -1) || 
  (domain.indexOf("gmail.") != -1))
 {
  return true;
 }

 return false;
};
searchshield.GMailSearchEngine.prototype.includeLink = function(tag)
{
 if (searchshield.DoesURLContain(tag.href, this.search.uri.host))
  return false;

 // don't mark anything but http://
 if (tag.href.indexOf("mailto") == 0)
  return false;

 var parentDiv = searchshield.getParentNodeByTagName("DIV", tag, "className");
 if ((parentDiv) &&
  ((parentDiv.className == "ii gt") || // mail message body
   (parentDiv.className == "mv") || // top sponsored links
   (parentDiv.className == "vb") || // right sponsored links
   (parentDiv.className == "im") || // inside quotes
   (parentDiv.className == "gmail_quote") || // quote
   (parentDiv.className == "msg") // basic html mode
   )) // right ads
 {
  // parse for any ads
  var newHref = this.parseAdUrl(tag.href);
  return newHref;
 }
 
 return false;
};
searchshield.GMailSearchEngine.prototype.addImage = function(node, image, hidden)
{
 var doc   = this.search.doc;
  
 this.init_inline_ratings(doc);
 this.show_inline_ratings(doc, node, image);
};
searchshield.GMailSearchEngine.prototype.parseAdUrl = function(href)
{
 if (!href)
  return href;

 // check for google ad
 var regex = "^http(s)?\:\/\/([a-zA-Z0-9]+)\.googlesyndication\.com.+\&adurl\=(.+)";
 var re = new RegExp(regex);
 var matches = href.match(re);
 if (matches && (matches.length >= 4))
 {
  // else we want the fourth value
  var match = matches[3];
  if (match && (match.length > 0))
   return match
 }

 return href;
};
///////////////    GMAIL SEARCH ENGINE    ///////////////




///////////////    FACEBOOK SEARCH ENGINE    ///////////////
searchshield.FacebookSearchEngine = function(search)
{
 searchshield.SearchEngine.call(this, search);
 this.showCleanVerdicts = false;
 this.type = 'inline'
};
searchshield.FacebookSearchEngine.prototype = new searchshield.SearchEngine();
searchshield.FacebookSearchEngine.prototype.constructor = searchshield.FacebookSearchEngine;
searchshield.FacebookSearchEngine.prototype.name = "facebook"; // the name by which the search engine is known (always lowercase)
searchshield.FacebookSearchEngine.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;

 if (uri.host.indexOf("www.facebook.com") != -1) 
  return true;

 return false;
};
searchshield.FacebookSearchEngine.prototype.includeLink = function(tag)
{
 if (searchshield.DoesURLContain(tag.href, this.search.uri.host) ||
  (searchshield.DoesURLContain(tag.href, 'static.ak.fbcdn.net')))
 {
  return false;
 }
  
 // don't put verdicts in areas where typing is going on
 if (tag.parentNode) 
 {
  var parentDiv = searchshield.getParentNodeByTagName("DIV", tag, "className");
  if (parentDiv &&
   (parentDiv.className == "Mentions_Input") ||
   (parentDiv.className.indexOf('UIThumbPager_') != -1))
  {
   return false;
  }
 }
 
 return tag.href
};
searchshield.FacebookSearchEngine.prototype.addImage = function(node, image, hidden)
{
 var doc   = this.search.doc;
  
 this.init_inline_ratings(doc);
 this.show_inline_ratings(doc, node, image);
};
///////////////    FACEBOOK SEARCH ENGINE    ///////////////



///////////////    AVG TOOLBAR REPORTING    ///////////////
var avgreport = {
 BLOCK_SEVERITY: 3,
 scanResult: function (doc, url, foundUrl, ip) {
  // report scan end only if surf enabled
  if ('1' != searchshield.avgCallFunc(doc, 'GetSurfEnabled'))
   return;
  
  // for now native is handling the interstitial 
  var results = searchshield.avgCallFunc(doc, 'MalsiteCheck', url);
  if ( results == null )
   return;
  
  var parts = results.split('::');
  
  // need at least severity
  if (parts == null)
   return;

  if (!ip)
   ip = "";
   
  // use a block severity if foundUrl is given
  var severity = !!foundUrl ? avgreport.BLOCK_SEVERITY : parseInt(parts[0], 10);
  var category = "";
  var threat  = "";

  // fill in the category and threat if something was found
  if (severity > 0)
  {
   category = parts[2];
   threat  = parts[4];
  }
//  else
//   return;
  
  var scan_result = searchshield.avgCallFunc(doc, 'ReportScanResult', url, url, threat, category, ip, severity);
  var scan_end = avgreport.scanEnd(doc, url);
  
  return (scan_result && scan_end);
 },
 scanEnd: function (doc, url) {
  return searchshield.avgCallFunc(doc, 'ReportScanEnd', url);
 },
 GetInterstitialIP: function (interstitial) {
  // simple regex to pull the IP address
  var regex = /(([1-9][0-9]{0,2})|0)\.(([1-9][0-9]{0,2})|0)\.(([1-9][0-9]{0,2})|0)\.(([1-9][0-9]{0,2})|0)/;
  var match = regex.exec(interstitial);
  if (!match)
   return '';

  return match[0];
 }
}
///////////////    AVG TOOLBAR REPORTING    ///////////////


///////////////    FLYOVERS    ///////////////
var avglsflyover = {
 count: 0,
 poppedUp: false,
 poppedElement: null,
 orig_onmousemove: null,
 reset: function () {
  avglsflyover.count = 0;
  avglsflyover.poppedUp = false;
  avglsflyover.poppedElement = null;
  avglsflyover.orig_onmousemove = null;
 },
 popup: function (event, hash, search, flyover) {
  if (!event)
   event = window.event;

  var div = document.getElementById("XPLSS_Flyover");
  if (div == null)
   return;

  // establish target element and get its containing document object
  // in case verdict is inside a frame
  var eventTarget = event.srcElement || event.currentTarget;
  var frameDoc = eventTarget.ownerDocument;

  // if the element is the clock, don't pop over it
  if ((eventTarget.src != null) && (eventTarget.src.indexOf("clock.gif") != -1))
   return;
  
  // save the element we popped over
  avglsflyover.poppedElement = eventTarget;

  // if no flyover get it
  if ((flyover == null) || (flyover == ""))
  {
   flyover = searchshield.avgCallFunc(frameDoc, 'BuildFlyover', hash);

   if (!flyover)
    return;

   // cleanup flyover, replace any new lines
   flyover = flyover.replace(/\r/g, "");
   flyover = flyover.replace(/\n/g, "");
   // escape any single quotes
   flyover = flyover.replace(/'/g, "&#39;");
  }

  // set the html in the layer
  div.innerHTML = flyover;

  // there is an unwanted text node that causes vertical misalignment of flyover
  if (div.firstChild.nodeType == 3)
   div.removeChild(div.firstChild);
  
  avglsflyover.poppedUp = true;

  // reset display count
  avglsflyover.count = 0;

  div.onmouseout = avglsflyover.hide;

  // if an onmousemove is already set and it isn't us, save it and restore later
  if ((frameDoc.onmousemove != null) && (frameDoc.onmousemove != avglsflyover.position))
   avglsflyover.orig_onmousemove = frameDoc.onmousemove;
  frameDoc.onmousemove = avglsflyover.position;
 },
 hide: function (event, force) {
  var div = document.getElementById("XPLSS_Flyover");
  if ((div == null) || (div.style == null) || (div.style.visibility == "hidden"))
   return;

  var trans_div = document.getElementById("XPLSS_Trans");
  if ((trans_div == null) || (trans_div.style == null) || (trans_div.style.visibility == "hidden"))
   return;

  if (!!force)
   return setFlyoverStyle(div, trans_div);

  if (!event)
   event = window.event;
  
  // establish target element and get its containing document object
  // in case verdict is inside a frame
  var eventTarget = event.srcElement || event.currentTarget;
  var frameDoc = eventTarget.ownerDocument;

  // restore onmousemove
  if (avglsflyover.orig_onmousemove != null)
   frameDoc.onmousemove = avglsflyover.orig_onmousemove;

  if (avglsflyover.poppedElement)
   avglsflyover.poppedElement.style.border = "";

  var relatedElement = event.toElement;
  if (!relatedElement)
  { //this happens on mouseout when verdict and flyover are on different frames/docs
   window.top.document.detachEvent('onmouseout', avglsflyover.hide);
   window.top.document.attachEvent('onmouseout', avglsflyover.hide);
   return;
  }

  // make sure we aren't still over the popped image or our layer
  if (searchshield.containedIn(avglsflyover.poppedElement, relatedElement) ||
   searchshield.containedIn(div, relatedElement) ||
   searchshield.containedIn(trans_div, relatedElement))
  {
   return;
  }

  setFlyoverStyle();

  // hide and move somewhere off screen (negative offsets)
  function setFlyoverStyle()
  {
   div.style.visibility = "hidden";
   div.style.left = "-2100px";
   div.style.top  = "-2100px";
   trans_div.style.visibility = "hidden";
   trans_div.style.left = "-2100px";
   trans_div.style.top  = "-2100px";

   return true;
  }
 },
 position: function () {
  if (!avglsflyover.poppedUp || (avglsflyover.poppedElement == null))
   return;

  var flyover = document.getElementById("XPLSS_Flyover");
  if (flyover == null)
   return;


  // relative position of flyover in relation to icon
  var locateX = 0;  // 0=left, 1=right
  var locateY = 0;  // 0=above, 1=below, 2=beside icon
 
  // get window sizes
  var winSize  = searchshield.viewPortSize();
  var windowX  = winSize[0];
  var windowY  = winSize[1];

  // get the exact size of the flyover
  var flyoverSize  = searchshield.elementSize(flyover);
  var flyoverX  = flyoverSize[0];
  var flyoverY  = flyoverSize[1];

  var verdictWidth = 0;
  if (avglsflyover.poppedElement && avglsflyover.poppedElement.width)
   verdictWidth = avglsflyover.poppedElement.width;
  
  // get the bounding rect for image(s)
  var imgRect = searchshield.GetFullBoundingRect(avglsflyover.poppedElement);

  // half width/height of element bounding rect
  var halfX = (imgRect.right - imgRect.left) / 2;
  var halfY = (imgRect.bottom- imgRect.top) / 2;

  // element the mouse is over, get the center position
  var posX = searchshield.offsetLeft(avglsflyover.poppedElement) + halfX;
  var posY = searchshield.offsetTop(avglsflyover.poppedElement) + halfY;

  // if a verdict is inside a frame must get offsets for the frame element
  var docFrames = document.frames;
  if (docFrames)
  {
   for (var i=0; i < docFrames.length; i++)
   {
    try {
     var frameElem = docFrames[i].frameElement;
     if (frameElem.contentWindow.document.getElementById(avglsflyover.poppedElement.id))
     {
      posX += searchshield.offsetLeft(frameElem);
      posY += searchshield.offsetTop(frameElem);
      break;
     }
    }
    catch(frmErr){}
   }
  }

  var transXOffset = 0;
  if (imgRect.mid == undefined)
   transXOffset = -1 * halfX;
  else
   transXOffset = ((imgRect.right + imgRect.left) / 2) - imgRect.mid;
  
  // normalize pos to 0  -- get amount of scrolling in browser window
  var scroll   = searchshield.scrollSize();
  var pageOffsetX  = scroll[0];
  var pageOffsetY  = scroll[1];

  posX -= pageOffsetX;
  posY -= pageOffsetY;

  // setup the offsets
  var offsetX = posX;
  var offsetY = posY;

  // calc where to display on page
  if ((windowX - posX) > posX)
  {
   // right
   offsetX += halfX;
   locateX = 1;
  }
  else
  {
   //left
   offsetX -= (flyoverX + halfX);
  }
  if ((windowY - posY) > posY)
  {
   // below
   if (posY < (windowY/4))
   {
    offsetY -= halfY;
    locateY = 1;
   }
   else
   {
    offsetY -= (flyoverY / 2);
    locateY = 2;
   }
  }
  else
  {
   // above
   if ((windowY - posY) < (windowY/4))
   {
    offsetY -= (flyoverY - halfY);
   }
   else
   {
    offsetY -= (flyoverY / 2);
    locateY = 2;
   }
  }
  // make sure we aren't off the screen
  if (offsetY < 0)
   offsetY = 0;

  if ((offsetY + flyoverY) > windowY)
   offsetY = windowY - flyoverY;

  // add page offsets back
  offsetX += pageOffsetX;
  offsetY += pageOffsetY;
  posX += pageOffsetX;
  posY += pageOffsetY;

  var paddedOffsetX = 0; //provide space between icon and flyover
  var padX = 3;
  if (locateX == 0)
   paddedOffsetX = offsetX - padX;
  else
   paddedOffsetX = offsetX + padX;


  // set where to put the flyover
  flyover.style.top = offsetY + "px";
  flyover.style.left = paddedOffsetX + "px";


  // set where to put the transparent layer
  var trans = document.getElementById("XPLSS_Trans");
  if (trans != null)
  {
   var trans_left = 0;
   var trans_top  = 0;
   var trans_width= 0;
   var trans_height = 0;

   // transparent layer should overlap verdict image
   if (locateX == 0)
    trans_left = posX - flyoverX - halfX;  // left 
   else
    trans_left = posX - transXOffset - verdictWidth; // right

   trans.style.left = trans_left + "px";
   trans.style.top  = offsetY + "px";

   trans.style.width = flyoverX + "px";
   trans.style.height = flyoverY + "px";
  }

  avglsflyover.display();
 },
 display: function () {
  avglsflyover.count++;
  if (avglsflyover.count == 1)
  {
   var flyover = document.getElementById("XPLSS_Flyover");
   if (flyover == null)
    return;

   // show the flyover, must use a little count to tell, crazy stuff
   flyover.style.visibility = "visible";

   // show the transparent layer
   var trans_div = document.getElementById("XPLSS_Trans");
   if (trans_div == null)
    return;

   trans_div.style.visibility = "visible";

   avglsflyover.poppedUp = false;
  }
 },
 show: function () {
  var div = document.getElementById("XPLSS_Flyover");
  if (div == null)
   return;

  div.style.visibility = "visible";

  var trans_div = document.getElementById("XPLSS_Trans");
  if (trans_div == null)
   return;
  trans_div.style.visible = "visible";
 }
};

var avglsinlineflyover = {
 build: function (riskCategory, riskName, bgColor, borderColor) {
  var html = '';
  html += "<div style=background-color:" + bgColor;
  html += "border-color:" + borderColor + ";";
  html += "border-style:solid;";
  html += "border-width:3px;";
  html += "padding:3px;";
  html += "padding-left:8px;";
  html += "padding-right:8px;";
  html += "-moz-border-radius:5px;>




";
  html += "
";
  html += riskCategory + "
";
  html += riskName + "
";

  return html;
 },
 popup: function (event, flyover, blUrl) {
  //set verdict info
  var div = document.getElementById('XPLSS_InlineFlyover');
  if (div == null)
   return;
  
  // blUrl is an object for a blacklisted short url
  // when it is passed get the final url 
  if (blUrl != undefined)
  {
   var finalUrl = searchshield.avgCallFunc(document, 'GetFinalUrl', blUrl.sUrl);
   var uri = searchshield.parseLink(unescape(finalUrl));
   if (uri.source != null)
   { // regexp failed so used split to parse url
    var qsUrl = uri.source.indexOf("?url=");
    if (qsUrl != -1)
     riskName = blUrl.riskNameLabel + uri.source.substring(qsUrl + 5);
    else
     riskName = blUrl.riskNameLabel + uri.source;
   }
   else if ((uri.qsArray.url != null) && (uri.qsArray.url.length > 0))
   {
    riskName = blUrl.riskNameLabel + uri.qsArray.url;
   }
   else
    riskName = blUrl.riskNameLabel + blUrl.sUrl

   flyover = avglsinlineflyover.build(blUrl.riskCategory, riskName, blUrl.bgColor, blUrl.borderColor);
  }

  div.innerHTML = flyover;
  div.style.width = "auto";  //reset width
  div.style.position = "absolute";

  if (!event)
   event = window.event;
   
  var eventTarget = event.srcElement;
  avglsinlineflyover.position(eventTarget);
 },
 hide: function (event) {
  if (!event)
   event = window.event;
   
  var div = document.getElementById("XPLSS_InlineFlyover");
  if (div == null)
   return;
   
  div.visibility = "hidden"; //invisible
  div.style.left = "-5000px";
 },
 position: function (imageElem) {
  var flyover = document.getElementById('XPLSS_InlineFlyover');
  if (flyover == null)
   return;
   
  // relative position of flyover in relation to icon
  var locateX = 0;  // 0=left, 1=right
  var locateY = 0;  // 0=above, 1=below, 2=beside icon
  
  
  
  // get window sizes
  var winSize  = searchshield.viewPortSize();
  var windowX  = winSize[0];
  var windowY  = winSize[1];

  // Must know if there is a horizontal scroll bar for Firefox
  // for proper flyover positioning near bottom edge
  var scrollYWidth  = winSize[2];
  var scrollBarX  = winSize[2] > 0 ? true : false;

  // get the exact size of the flyover
  var flyoverSize  = searchshield.elementSize(flyover);
  var flyoverX  = flyoverSize[0];
  var flyoverY  = flyoverSize[1];
  
  flyover.style.width = flyoverX + "px";
  
  // get the bounding rect for image(s)
  var imgRect = imageElem.getBoundingClientRect();

  // half width/height (center) of element bounding rect
  var halfX = (imgRect.right - imgRect.left) / 2;
  var halfY = (imgRect.bottom- imgRect.top) / 2;

  // element the mouse is over, get the center position
  var posX = searchshield.offsetLeft(imageElem) + halfX;
  var posY = searchshield.offsetTop(imageElem) + halfY;
  
  var pageOffsetX = 0;
  var pageOffsetY = 0;

  // normalize pos to 0  -- get amount of scrolling in browser window
  var scroll   = searchshield.scrollSize(imageElem);
  var pageOffsetX  = scroll[0];
  var pageOffsetY  = scroll[1];
  var hasParentFrame = scroll[2];
  
  posX -= pageOffsetX;
  posY -= pageOffsetY;

  //compensate for Firefox 3
  if (posX < imgRect.left)
   posX = imgRect.left+halfX;

  // setup the offsets
  var offsetX = posX;
  var offsetY = posY;

  // calc where to display on page
  if ((windowX - posX) > posX)
  {
   // right
   offsetX += halfX;
   locateX = 1;
  }
  else
  {
   //left
   offsetX -= (flyoverX + halfX);
  }
  if ((windowY - posY) > posY)
  {
   // below
   if (posY < (windowY/4))
   {
    offsetY -= halfY;
    locateY = 1;
   }
   else
   {
    offsetY -= (flyoverY / 2) - halfY;
    locateY = 2;
   }
  }
  else
  {
   // above
   if ((windowY - posY) < (windowY/4))
   {
    offsetY -= (flyoverY - halfY);
   }
   else
   {
    offsetY -= (flyoverY / 2) + halfY;
    locateY = 2;
   }
  }
  // make sure we aren't off the screen
  if (offsetY < 0)
   offsetY = 0;

  if ((offsetY + flyoverY) > windowY)
  {
   offsetY = windowY - flyoverY;
  }
  else if (scrollBarX && ((windowY - (posY + halfY)) < scrollYWidth))
  { //verdict overlaps the horizontal scrollbar
   offsetY = windowY - (flyoverY + scrollYWidth);
  }

  // add page offsets back - if not in frame
  if (!hasParentFrame)
  {
   offsetX += pageOffsetX;
   offsetY += pageOffsetY;
  }
  posX += pageOffsetX;
  posY += pageOffsetY;

  var paddedOffsetX = 0; //provide space between icon and flyover
  var padX = 3;
  if (locateX == 0)
   paddedOffsetX = offsetX - padX;
  else
   paddedOffsetX = offsetX + padX;


  // set where to put the flyover
  flyover.style.top = offsetY + "px";
  flyover.style.left = paddedOffsetX + "px";

  avglsinlineflyover.display();
 },
 display: function () {
  var div = document.getElementById('XPLSS_InlineFlyover');
  if (div == null)
   return;
  
  // show the flyover
  div.style.visibility = "visible";
 },
 imageExists: function(element) {
  if (element)
  {
   // check next siblings children
   var sibling = element.nextSibling;
   
   if ((sibling == null) || (sibling.getElementsByTagName == null))
    return false;
   
   var images = sibling.getElementsByTagName("IMG");
   if (images == null)
    return false;

   for (var i = 0; i < images.length; i++)
   {
    if (images[i].id == "avg_ls_image")
     return true;
   }
  }

  return false;
 },
 getImage: function (anchor) {
  if (anchor)
  {
   var imageElem = null;
   var images = anchor.getElementsByTagName("img");
   if (images == null)
    return imageElem;

   for (var i = 0; i < images.length; i++)
   {
    if (images[i].id == "avg_ls_image")
    {
     imageElem = images[i];
     break;  
    }    
   }
   return imageElem;
  }  
 },
 mouseOverHandler: function (e, doc, engine) {
  if (e && e.srcElement && e.srcElement.href)
  {
   // need to keep a reference to the function registered 
   // by the listener to be able to remove it.
   var handlerFunc = arguments.callee;
   var element = e.srcElement;
   var href = e.srcElement.href;

   // need an engine   
   if (!engine)
    return;

   // check if it has an image already
   if (avglsinlineflyover.imageExists(element))
    return;

   // add the image, returns the anchor not the image
   var new_element = engine.add_inline_image(doc, element, null, null);

   // do the check and update in the background
   setTimeout(function() {avglsinlineflyover.checkAndUpdate(doc, element, new_element, engine, handlerFunc)}, 1);
  }
 },
 checkAndUpdate: function (doc, element, new_element, engine, handlerFunc) {
  if (!engine)
   return;

  try {
   // remove the listener and get final url
   element.detachEvent("onmouseover", handlerFunc, false);
   var finalUrl = searchshield.avgCallFunc(doc, 'GetFinalUrl', element.href);
  }
  catch(e) {}

  if (finalUrl)
  {
   // update the verdict
   engine.display_inline(doc, new_element, finalUrl, null, true);
  }
 }
};
///////////////    FLYOVERS    ///////////////