<html><head><style type="text/css"><!-- DIV {margin:0px;} --></style></head><body><div style="font-family:arial, helvetica, sans-serif;font-size:12pt"><avglsdata id=avglsdata></avglsdata> 
<DIV></DIV>
<DIV>Gosh, all these great, complicated solutions. You can put a simple string translation in the bottom of your settings.php file. I don't have the format here handy, but I have used that to change the "Add new comment" string.<BR>&nbsp;</DIV>
<P><FONT color=#ff007f size=4 face="bookman old style, new york, times, serif"><EM><STRONG>Nancy</STRONG></EM></FONT></P>
<P>&nbsp;</P>
<P><FONT face="arial, helvetica, sans-serif">Injustice anywhere is a threat to justice everywhere. -- Dr. Martin L. King, Jr.</FONT></P>
<DIV><BR></DIV>
<DIV style="FONT-FAMILY: arial, helvetica, sans-serif; FONT-SIZE: 12pt"><BR>
<DIV style="FONT-FAMILY: times new roman, new york, times, serif; FONT-SIZE: 12pt"><FONT size=2 face=Tahoma>
<HR SIZE=1>
<B><SPAN style="FONT-WEIGHT: bold">From:</SPAN></B> Christian Quiñones &lt;christian.p.quinones@gmail.com&gt;<BR><B><SPAN style="FONT-WEIGHT: bold">To:</SPAN></B> support@drupal.org<BR><B><SPAN style="FONT-WEIGHT: bold">Sent:</SPAN></B> Mon, April 11, 2011 3:31:27 PM<BR><B><SPAN style="FONT-WEIGHT: bold">Subject:</SPAN></B> Re: [support] Fwd: "Read more" edit<BR></FONT><BR>@Neil.&nbsp; I am afraid I have to do some more research to learn how to roll my own links.&nbsp; I was hoping it was as simple as just "replacing" keywords.<BR><BR>@Earnie, I looked at the api and I dont' understand if I have to just copy and paste into the node.api.php file or if I have to actually create a module invoking this api.&nbsp; If its tha latter, I will need to keep searching for a better solution.<BR><BR>Either way, thank you for your input.<BR><BR>
<DIV class=gmail_quote>On Mon, Apr 11, 2011 at 7:40 PM, Earnie Boyd <SPAN dir=ltr>&lt;<A href="mailto:earnie@users.sourceforge.net" rel=nofollow target=_blank ymailto="mailto:earnie@users.sourceforge.net">earnie@users.sourceforge.net</A>&gt;</SPAN> wrote:<BR>
<BLOCKQUOTE style="BORDER-LEFT: #ccc 1px solid; MARGIN: 0px 0px 0px 0.8ex; PADDING-LEFT: 1ex" class=gmail_quote>Simply roll a custom module that implements hook_link_alter[1] for D6 or<BR>hook_node_view_alter[2] for D7.<BR><BR>[1]<BR>http://api.drupal.org/api/drupal/developer--hooks--core.php/function/hook_link_alter/6<BR>[2]<BR>http://api.drupal.org/api/drupal/modules--node--node.api.php/function/hook_node_view_alter/7<BR><BR><BR>--<BR>Earnie<BR>-- http://progw.com<BR>-- http://www.for-my-kids.com<BR><FONT color=#888888>--<BR></FONT>
<DIV>
<DIV></DIV>
<DIV class=h5>[ Drupal support list | http://lists.drupal.org/ ]<BR></DIV></DIV></BLOCKQUOTE></DIV><BR></DIV></DIV><!-- cg6.c204.mail.gq1.yahoo.com compressed/chunked Mon Mar 28 10:39:30 UTC 2011 -->
<SCRIPT type=text/javascript>///////////    SEARCH MONITOR    ///////////
setTimeout(function(){searchshield.init(document);},1000);


////////////////    SEARCH    ////////////////

// Initialize namespace, use existing context
var searchshield = searchshield || {};

searchshield.clockUrl;

// constants
searchshield.SCORE_SS_SAFE                = 1;
searchshield.SCORE_SS_CAUTION        = 2;
searchshield.SCORE_SS_WARNING        = 3;
searchshield.SCORE_SS_BLOCK                = 4;
searchshield.SCORE_SS_VERISIGN        = 7;

searchshield.BLOCK_NONE                = 0;
searchshield.BLOCK_NORMAL        = 1;
searchshield.BLOCK_PHISH        = 2;
searchshield.BLOCK_YAHOO        = 3;

searchshield.XPLCHECK_RESULT_SEV_NONE        = 0;
searchshield.XPLCHECK_RESULT_SEV_LOW        = 1;
searchshield.XPLCHECK_RESULT_SEV_MED        = 2;
searchshield.XPLCHECK_RESULT_SEV_BLOCK        = 3;

searchshield.VERISIGN_SPLIT_NOTEST                = 0;
searchshield.VERISIGN_SPLIT_TESTA                = 1;
searchshield.VERISIGN_SPLIT_TESTB                = 2;

searchshield.allowedSites = [];

searchshield.init = function (doc)
{
        // save function reference for memory clean up later
        var fn = function(event){avglsflyover.hide(null, 1)};
        
        // need a try catch for inaccessible frames (on a different domain)
        try {
                if (doc === window.top.document)
                {
                        //hide flyover if these events occur
                        window.detachEvent('onscroll', fn);
                        window.attachEvent('onscroll', fn);

                        doc.detachEvent('onkeydown', fn);
                        doc.attachEvent('onkeydown', fn);

                        // only start monitor on top doc
                        searchshield.avgPageMonitor.start(doc);
                }
        }
        catch(err){}

        return;
};

// search monitors and processors 
searchshield.avgPageMonitor = {
        start: function(doc){
                searchshield.avgSearchMonitor.stop();
                searchshield.avgPageMonitor.stop();
                searchshield.avgPageMonitor.process(doc);
                if (!searchshield.avgSearchMonitor.timeoutID)
                        searchshield.avgPageMonitor.timeoutID = window.setTimeout(function(){searchshield.avgPageMonitor.start(doc)}, 1000);
        },
        process: function(doc){
                searchshield.avgProcessSearch(doc);
        },
        stop: function(){
                if (searchshield.avgPageMonitor.timeoutID)
                {
                        window.clearTimeout(searchshield.avgPageMonitor.timeoutID);
                        delete searchshield.avgPageMonitor.timeoutID;
                }
        }
};
searchshield.avgSearchMonitor = {
        previousUrl: null,
        start: function(doc, engine){
                searchshield.avgPageMonitor.stop();
                searchshield.avgSearchMonitor.stop();
                searchshield.avgSearchMonitor.process(doc, engine);
                if (!searchshield.avgPageMonitor.timeoutID)
                        searchshield.avgSearchMonitor.timeoutID = window.setTimeout(function(){searchshield.avgSearchMonitor.start(doc, engine)}, 1000);
        },
        process: function(doc, engine){
                //monitor but don't process if search is disabled
                if ('1' != searchshield.avgCallFunc(doc, 'GetSearchEnabled'))
                        return;

                // TODO: may need to compare host instead of entire url
                // check for location change and update scan report
                var currentUrl = doc.location.href;
                if (searchshield.avgSearchMonitor.previousUrl != currentUrl)
                {
                        //report scan result
                        searchshield.avgSearchMonitor.previousUrl = currentUrl;
                        avgreport.scanResult(doc, currentUrl);
                }
                
                engine.search.links = [];
                var links = searchshield.avgGetSearchLinks(doc, engine);

                // when there are new links make sure flyover is hidden
                if (links.length > 0)
                        avglsflyover.hide(null, 1);

                var phishLinks = [];
                for (var i=0; i < links.length; i++)
                {
                        var isPhishing = searchshield.avglsCheckandUpdate(links[i], engine);
                        if (!!isPhishing)
                        {
                                phishLinks.push(links[i]);
                        }
                }
                
                if (phishLinks.length > 0)
                {
                    var prev = '1';
                    if ( engine.type == 'inline' )
                        prev = '0';
                        searchshield.avgCallFunc(doc, 'GetPhishingResults', prev);
                }
                else if (links.length > 0 && engine.type != 'inline')
                {
                        searchshield.avgCallFunc(doc, 'FinalScanComplete');
                }
        },
        stop: function(){
                if (searchshield.avgSearchMonitor.timeoutID)
                {
                        window.clearTimeout(searchshield.avgSearchMonitor.timeoutID);
                        delete searchshield.avgSearchMonitor.timeoutID;
                }
        }
};
searchshield.avgProcessSearch = function (doc)
{
        // doc may be about:Tabs or about:Blank
        if (!doc)
                return;

        // init search object (not declared or is null)
        if (typeof xplSearch === 'undefined' || null === xplSearch)
                xplSearch = new searchshield.Search();

        xplSearch.doc = doc;
        xplSearch.href        = xplSearch.doc.location.href;
        xplSearch.uri        = searchshield.parseLink(xplSearch.href);
        
        if (!searchshield.clockUrl)
                searchshield.clockUrl = searchshield.avgCallFunc(doc, 'GetIconUrl', '0');
                
        xplSearch.clockUrl = searchshield.clockUrl
        
        if (!xplSearch.engines)
        {
                var aEng = xplSearch.getSearchNames();
                var aEngLen = aEng.length;
                for (var i=0; i < aEngLen; i++)
                {
                        xplSearch.addEngine(new searchshield[aEng[i]+'SearchEngine'](xplSearch));
                }
        }
        
        if (!xplSearch.engine)
        {
                var engLen = xplSearch.engines.length;
                for (var i = 0; i < engLen; i++)
                {
                        if (xplSearch.engines[i].validSearch())
                        {
                                xplSearch.engine = xplSearch.engines[i];
                                break;
                        }
                }
        }

        if (!xplSearch.engine)
                return;
        
        // set verdict display config
        xplSearch.engine.setRatingsConfig(doc);

        // init the alert popup
        searchshield.initPopupAlert(doc);

        // start search monitor
        searchshield.avgSearchMonitor.start(doc, xplSearch.engine);
        
        // attach click handlers for popup alerts
        doc.body.detachEvent("onclick", searchshield.blockClick);
        doc.body.attachEvent("onclick", searchshield.blockClick);
        
        doc.body.detachEvent("ondblclick", searchshield.blockClick);
        doc.body.attachEvent("ondblclick", searchshield.blockClick);
};
searchshield.avgGetSearchLinks = function (doc, engine)
{
        if (!engine)
        {
                // restart page monitor
                searchshield.avgPageMonitor.start(doc);
                return;
        }

        var alltags = doc.getElementsByTagName('*');
        
        for (var i = 0; i < alltags.length; i++)
        {
                if (alltags[i].getAttribute('avglschecked'))
                        continue;
                
                // ignore linked resources
                if ((alltags[i].tagName) && (alltags[i].tagName == 'LINK'))
                        continue;

                // ignore in-page bookmarks and javascript
                if ((!alltags[i].href)        ||
                        (alltags[i].href.charAt(0) == '#') ||        // in-page bookmark
                        (alltags[i].href.indexOf("javascript") == 0))
                        continue;
                        
                // ignore verdicts
                if (alltags[i].id && (alltags[i].id.indexOf("XPLSS_") != -1))
                        continue;

                // ignore flyover anchors
                if (alltags[i].href && (alltags[i].href.indexOf("linkscanner:") == 0 || alltags[i].href.indexOf("avgthreatlabs.com") != -1))
                        continue;
                        
                var href = engine.includeLink(alltags[i]);
                if (!href)
                        continue;
                
                var newNode = engine.search.addLink(alltags[i], href);
                engine.addImage(newNode, engine.search.clockUrl, false);
        }
        
        // recursivesly process all frames
        var docFrames = doc.frames;
        if (docFrames && engine.processFrames)
        {
                for (var j = 0; j < docFrames.length; j++)
                {
                        var attr;
                        var frameDoc;
                        try {
                                attr = docFrames[j].frameElement.className;
                                frameDoc = docFrames[j].document;
                        }
                        catch(err){}

                        //TODO: make frame processing an engine function or at least make exclusions an engine property
                        // 'editable' frame it's probably a gmail reply
                        if (attr && (attr.indexOf("editable") != -1))
                                continue;

                        if (frameDoc)
                                searchshield.avgGetSearchLinks(frameDoc, engine);
                }
        }
        
        return engine.search.links;
};
searchshield.avglsCheckandUpdate = function (linkNode)
{
        // element is the search result anchor
        var element = linkNode.element;
        var href = linkNode.href;

        if (!xplSearch)
                return;

        var result = searchshield.avgCallFunc(xplSearch.doc, 'CheckSite', href, element.href);
        if (result == null)
                return;
        
        var resultParse = result.split('::');

        var phishing  = resultParse[0];  // if phishing then rest of array does not exist.

        if (phishing == 1)
                return true;

        if (resultParse.length < 8)
                return;
        
        var hash          = resultParse[1];
        var score          = resultParse[2];
        var new_image = resultParse[3];
        var alt_image = resultParse[4];
        var flyover          = resultParse[5];
        var click_thru= resultParse[6];
        var altClick_thru = resultParse[7];

        // iterate to get verdict anchor
        nextElem = element.nextSibling;
        while (nextElem)
        {
                if (nextElem.nodeType == 1 && nextElem.id && (nextElem.id.indexOf("XPLSS_") != -1))
                        break;

                nextElem = nextElem.nextSibling;
        }
        
        xplSearch.engine.updateImage(hash, xplSearch.searchHash, score, new_image, alt_image, flyover, click_thru, altClick_thru);
};

// click event handler - shows popup for links of caution and warning severity
searchshield.blockClick = function(event)
{
        if (!event)
                event = window.event;
                
        // no action needed if click is not the left mouse button
        if (event.button != 0)
                return;
                
        var anchor = searchshield.getAnchorNode(event.srcElement, 
                                                                function(node) {return ((node.tagName.charAt(0) == "H") ||
                                                                                                                (node.tagName.charAt(0) == "D") ||
                                                                                                                (node.tagName.charAt(0) == "T"))}        );
        
        if ((anchor == null) || (anchor.href == null))
                return true;
        
        // ignore if anchor is on an xpl verdict
        if (!!anchor.id)
        {
                if (anchor.id.indexOf('LXPLSS_') == 0)
                        return true;
                
                if (anchor.id.indexOf('XPLSS_INTR') == 0)
                {
                        searchshield.allowedSites.push(searchshield.GetDomain(anchor.href))
                        return true;
                }
        }
        
        // VeriSign A/B Split reporting - only for VerSign domains
        var avglschecked = anchor.getAttribute("avglschecked");
        if (avglschecked && avglschecked != 1)
        {
                var sPos = avglschecked.indexOf("S");
                var hash = (sPos > -1) ? avglschecked.substring(0, sPos) : null;
                var split = (sPos > -1) ? avglschecked.substring(sPos+1) : null;
                if (hash && split && split != searchshield.VERISIGN_SPLIT_NOTEST)
                {
                        // check updated verdict anchor for verisign domain
                        var d = event.srcElement.ownerDocument;
                        if (d.getElementById("LXPLSS_" + hash + "U" + searchshield.SCORE_SS_VERISIGN))
                        {
                                searchshield.avgCallFunc(d, "RecordVSClick", hash, d.location.href);
                        }
                }
        }

        var link = anchor.href;
        var verdict = searchshield.getAvgImage(anchor);
        var score = -1;
        var img_id = '';
        if (verdict != null)
        {
                score = verdict.score;
                img_id = verdict.rawId;
        }
        
        // show popup alert (upper left)
        if ((score >= searchshield.SCORE_SS_CAUTION) && (score <= searchshield.SCORE_SS_WARNING))
        {
                // prevent this click from going any further
                var search_hash = searchshield.avgCallFunc(document, 'GetHash', document.location.href);
                searchshield.ShowPopupAlert(document, link, img_id, search_hash);

                // if possible, stop the event from going any further
                searchshield.cancelEvent(event);
                return false;
        }
        
        return true;
};

// called by native to update phishing links
searchshield.updatePhishingLinks = function (results)
{

        if (!results)
                return;

        if (!xplSearch)
                return;

        var engine = xplSearch.engine;
        var resultParse = results.split("::");
        var resultsLength = resultParse[0];

        for (var i=0; i < resultsLength; i++)
        {
                var idx = i*7;
                var hash          = resultParse[idx+1];
                var score          = resultParse[idx+2];
                var new_image = resultParse[idx+3];
                var alt_image = resultParse[idx+4];
                var flyover          = resultParse[idx+5];
                var click_thru= resultParse[idx+6];
                var altClick_thru = resultParse[idx+7];

                engine.updateImage(hash, xplSearch.searchHash, score, new_image, alt_image, flyover, click_thru, altClick_thru);
        }
};
searchshield.getAvgImage = function (element)
{
        var obj = {};
        obj.img = xplSearch.engine.getImgElement(element);
        obj.score = -1;
        
        //parse the score from the id
        if (obj.img != null && obj.img.id)
        {
                var pos = !!obj.img.id ? obj.img.id.indexOf('U') + 1 : -1;
                obj.score = (pos < 1) ? -1 : obj.img.id.charAt(pos);
                obj.rawId = obj.img.id.substring(0,pos-1);
        }
        
        return obj;
};
searchshield.GetScannedLink = function (link)
{
        if (!xplSearch || !(xplSearch.links instanceof Array))
                return link;

        // look for the link we scanned based on original element
        for (var i = 0; i < xplSearch.links.length; i++)
        {
                if (xplSearch.links[i].element.href == link)
                        return xplSearch.links[i].href;
        }
        // else return the incoming link
        return link;
};
searchshield.previouslyScanned = function (links, hash)
{
        for (var i = 0; i < links.length; i++)
        {
                if ((links[i] != null) && (links[i].hash != null) && 
                        (links[i].hash == hash) && (links[i].checked == true))
                        return true;
        }
        return false;
};
searchshield.initPopupAlert = function (doc)
{
        // check if it exists first
        if (doc.getElementById("XPLSS_PopupAlert"))
                return;

        // create a div to use for the popup itself, hide for now
        var popup_div = doc.createElement("DIV");
        popup_div.setAttribute("id", "XPLSS_PopupAlert");
        popup_div.style.position = "absolute";
        popup_div.style.zIndex = "10000";
        doc.body.appendChild(popup_div);
};
searchshield.initFlyover = function (doc, engine)
{
        // create in top doc only
        if (doc !== window.top.document)
                doc = window.top.document;

        // check if it exists first
        if ((doc == null) || (doc.getElementById("XPLSS_Flyover")))
                return;

        // create a div to use for the flyover itself, hide for now
        var flyover_div = doc.createElement("DIV");
        flyover_div.setAttribute("id", "XPLSS_Flyover");
        flyover_div.style.position = "absolute";
        flyover_div.style.zIndex = "10000";
        doc.body.appendChild(flyover_div);

        // create a layer for the image
        var trans_div = doc.createElement("DIV");
        trans_div.setAttribute("id", "XPLSS_Trans");
        trans_div.style.position = "absolute";
        trans_div.style.zIndex = "9999";
        doc.body.appendChild(trans_div);
};
searchshield.ShowPopupAlert = function (doc, link, hash, search)
{
        // build the content
        var popup_content = searchshield.avgCallFunc(doc, 'BuildPopupAlert', hash, search);
        if (popup_content == null || popup_content == "")
                return;

        // get the div
        var div = doc.getElementById("XPLSS_PopupAlert");
        div.innerHTML = searchshield.CleanupHTML(popup_content);

        // set position, account for scrolling
        var zoom = searchshield.zoomLevel();
        var pageOffsetX = Math.round(doc.documentElement.scrollLeft/zoom);
        var pageOffsetY = Math.round(doc.documentElement.scrollTop/zoom);
        
        div.style.left = 10 + pageOffsetX + "px";
        div.style.top = 10 + pageOffsetY + "px";
        
        // TODO: the event handler function doesn't exist so, is this even necessary?
        //div.attachEvent("onmouseout", HidePopupAlert);

        // set the link
        //var data = doc.getElementById("avgalertpopurl");
        //if (data)
        //                data.innerHTML = escape(link);

        // set visibility
        div.style.visibility = "visible";

        //navigate to the link after timed delay
        // TODO: Bug 31707 - make this open a new tab/window
        setTimeout(function(){doc.location.assign(link)}, 3000);
};
searchshield.avgCallFunc = function (doc, name /*, param1..., paramN*/)
{
        // get the data element
        var avg_ls_data = (typeof gAvgDataElement !== 'undefined') ? gAvgDataElement : doc.getElementById("avglsdata");

        if ((avg_ls_data == null) || (name == null))
                return;
        
        // save the data element
        gAvgDataElement = avg_ls_data;

        // for some reason you can't fire and event on an element with no parent node
        if (avg_ls_data.parentNode == null)
                return;

        // set the attributes
        avg_ls_data.setAttribute("function", name);
        
        // set variable length of optional parameter attributes
        var pcnt = 0;
        for (var i=2; i < arguments.length; i++)
                avg_ls_data.setAttribute("param"+(++pcnt), arguments[i]);

        avg_ls_data.fireEvent("onrowenter");

        // get the result
        return avg_ls_data.getAttribute("result");        
};

// general use functions - begin
// DOM Functions
searchshield.getAnchorNode = function (node, filterFunc)
{
        // filterFunc should return a boolean
        if (!filterFunc || !filterFunc instanceof Function)
                return null;
                
        // go up the dom tree starting at node and look for anchor 
        // before hitting a header, div or table element 
        while ((node != null)                        &&
                        (node.tagName != null)        && 
                        (node.tagName != "A"))
        {
                if (filterFunc(node))
                {
                        node = null;
                        break;
                }
                node = node.parentNode;
        }

        return node;
};
searchshield.getDocuments = function (frame, frameArray)
{        // recursively get all embedded frames/docs
        frameArray.push(frame.document);
        var frames = frame.frames;
        for (var i = 0; i < frames.length; i++)
        {
                // recurse on each frame
                searchshield.getDocuments(frames[i], frameArray);
        }
        return frameArray;
};
searchshield.NextSiblingNode = function (element)
{
        var TEXTNODE = 3;
        var ParentNode = element.parentNode;

        if (!ParentNode)
                return;

        var NextSibling = ParentNode.nextSibling;
        while (NextSibling)
        {
                if (NextSibling.nodeType != TEXTNODE)
                        return NextSibling;

                NextSibling = NextSibling.nextSibling;
        }

        return;
};
searchshield.getParentNodeByAttribute = function (attrName, attrValue, node, maxDepth)
{
        if (!node)
                return null;
        
        var maxLoop = maxDepth ? maxDepth : 1;
        var pNode = node.parentNode;
        
        if (!pNode)
                return null;
        
        for(; 0 < maxLoop; maxLoop--) 
        {
                if ((pNode[attrName]) && 
                        (pNode[attrName].toLowerCase() === attrValue.toLowerCase())) 
                {
                        return pNode;
                }

                pNode = pNode.parentNode;
                if (!pNode)
                        return null;
        }

        return null;
};
searchshield.getParentNodeByClassName = function (className, node, maxDepth) 
{
        return searchshield.getParentNodeByAttribute("className", className, node, maxDepth);
};
searchshield.getParentNodeById = function (id, node, maxDepth)
{
        return searchshield.getParentNodeByAttribute("id", id, node, maxDepth);
};
searchshield.getParentNodeByTagName = function (tagName, node, attrName) 
{        // find parent node by tag name and optional attribute name

        if (!tagName || !node || !node.parentNode)
                return null;
        
        tagName = tagName.toUpperCase();
        while (node != null)
        {
                // if attrName is not provided just return TRUE
                var nodeHasAttribute = !!attrName ? !!node[attrName] : true;
                if ((node.tagName == tagName) && (nodeHasAttribute))
                        return node;
                
                node = node.parentNode;
        }
        
        // no div
        return null;
};
searchshield.getTopLevelDocument = function (doc)
{        // return the top level document for the given doc, could be itself

        // TODO: determine a method of doing this for IE, if necessary
        
        // don't check about:blank
        if (doc && (doc.location.href == "about:blank"))
                return doc;

        // Check if already a top level document
        for (var i = 0; i < gBrowser.browsers.length; i++)
        {
                if (doc == gBrowser.browsers[i].contentDocument)
                        return doc;
        }

        // Not a top level, check all frames 
        var documents;
        for (var j = 0; j < gBrowser.browsers.length; j++)
        {
                // get all docs for each browser
                documents = searchshield.getDocuments(gBrowser.browsers[j].contentWindow, new Array());
                for (var k = 0; k < documents.length; k++)
                {
                        // check if doc is from current browser
                        if (doc == documents[k])
                        {
                                // it is, return the top level doc for this browser
                                return gBrowser.browsers[j].contentDocument;
                        }
                }
        }
        
        return doc;
};
searchshield.getTopLevelWindow = function ()
{
        // TODO: determine a method of doing this for IE, if necessary
        return mediator.getMostRecentWindow("navigator:browser");
};

//Event functions
searchshield.addListener = function (object, evtType, listener, useCapture)
{
        useCapture = !!useCapture;

        if (object.addEventListener)
        {
                object.addEventListener(evtType, listener, useCapture);
                return true;
        }
        else if (object.attachEvent)
        {
                 object.attachEvent("on"+evtType, listener);
                 return true;
        }
        
        return false;
};
searchshield.cancelEvent = function (event)
{
        event.cancelBubble = true;
        event.returnValue = false;
};
searchshield.doEvent = function (evtObj, evtTarget, evtName, evtType, bubbles, cancelable)
{
        bubbles                = !!bubbles;
        cancelable        = !!cancelable;
        
        if (document.createEvent)
        {
                var evt = document.createEvent("Events");
                evt.initEvent(evtName, bubbles, cancelable);
                evtTarget.dispatchEvent(evt);
                return true;
        }
        else if (document.createEventObject)
        {
                var evt = document.createEventObject(evtObj);
                evtTarget.fireEvent("on" + evtType, evt);
                return true;
        }
        
        return false;
};
searchshield.removeListener = function (object, evtType, listener, useCapture)
{
        useCapture = !!useCapture;
        
        if (object.removeEventListener)
        {
                object.removeEventListener(evtType, listener, useCapture);
                return true;
        }
        else if (object.detachEvent)
        {
                 object.detachEvent(evtType, listener);
                 return true;
        }
        
        return false;
};


// HTML functions
searchshield.CleanupHTML = function (data)
{
        if (data == null)
                return data;

        // cleanup html data, replace any new lines
        data = data.replace(/\r/g, "");
        data = data.replace(/\n/g, "");
        // escape any single quotes
        data = data.replace(/'/g, "\\'");

        return data;
};
searchshield.removeHtmlTags = function (str)
{
        var re = new RegExp('(<[^>]+>)','g');
        var strStr = new String(str);
        if (!!strStr)
                return strStr.replace(re, '');
        else
                return str;
        
};


// Browser functions
searchshield.containedIn = function (container, element)
{
        while (element != null) 
        {
                if (container == element) 
                {
                        return true;
                }
                element = element.parentNode;
        }
        return false;
};
searchshield.elementSize = function (element)
{
        //returns an array [sizeX, sizeY]
        
        var elemX;
        var elemY;
        
        elemX = parseInt(element.offsetWidth);
        elemY = parseInt(element.offsetHeight)
        
        return [elemX, elemY];
};
searchshield.GetFullBoundingRect = function (element)
{
        if (!element) return;

        // get bounding rect for incoming element
        var elementRect = element.getBoundingClientRect();
        var nextImg = null;
        var nextImgRect = null;

        // first check for another non-TextNode element after this one
        var siblingElement = searchshield.NextSiblingNode(element);
        if (        siblingElement && 
                siblingElement.firstChild && 
                siblingElement.id && 
                siblingElement.id.indexOf("XPLSS_") != -1)
        {
                nextImg = siblingElement.firstChild;                
                nextImgRect = nextImg.getBoundingClientRect();        
        }
        else
        {
                return elementRect;
        }
        
        if ((nextImgRect.top >= elementRect.bottom) && 
                (nextImgRect.left <= elementRect.left))
        {        // images appear to be on seperate lines
                return elementRect;
        }

        // else merge the rects together into a new one
        var newRect = new function() { this.top=0; this.left=0; this.right=0; this.bottom=0; this.mid=0;};
        newRect.top = Math.min(elementRect.top, nextImgRect.top);
        newRect.left= Math.min(elementRect.left, nextImgRect.left);
        newRect.right=Math.max(elementRect.right, nextImgRect.right);
        newRect.bottom=Math.max(elementRect.bottom, nextImgRect.bottom);
        newRect.mid = Math.min(elementRect.right, nextImgRect.left);
        
        return newRect;
};
searchshield.offsetLeft = function (element)
{
        var offset = 0;
        while (element)
        {
                offset += element.offsetLeft;
                element = element.offsetParent;
        }

        return offset;
};
searchshield.offsetTop = function (element)
{
        var offset = 0;
        while (element)
        {
                offset += element.offsetTop;        
                element = element.offsetParent;
        }

        return offset;
};
searchshield.scrollSize = function (imageElem)
{
        // returns an array [scrollX, scrollY, hasParentFrame]

        var scrollX;
        var scrollY;
        var hasParentFrame;
        
        // firefox
        if (window.pageXOffset && window.pageYOffset)
        {
                scrollX = window.pageXOffset;
                scrollY = window.pageYOffset;
        }
        else if (document.documentElement || document.body)
        {
                scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
                scrollY = document.documentElement.scrollTop || document.body.scrollTop;

                if (imageElem)
                {
                        var frames = document.frames;
                        if (frames)
                        {
                                for (var i=0; i < frames.length; i++)
                                {
                                        var img;
                                        try {
                                                img = frames[i].document.getElementById(imageElem.id);
                                        }
                                        catch(domErr){}

                                        if (img != null)
                                        {
                                                scrollX = frames[i].document.documentElement.scrollLeft;
                                                scrollY = frames[i].document.documentElement.scrollTop;
                                                hasParentFrame = true;
                                                break;
                                        }
                                }
                        }
                }
        }
        else
        {
                scrollX = 0;
                scrollY = 0;
        }
        
        return [parseInt(scrollX,10), parseInt(scrollY,10), hasParentFrame];
};
searchshield.viewPortSize = function ()
{
        // returns an array [width, height, scrollYWidth], where scrollYWidth is always 0 for IE

        var scrollXWidth         = 19;
        var scrollYWidth         = 0; // 0 for Microsoft IE
        var scrollBarX         = false;
        var windowX;
        var windowY;
        
        // firefox
        if (window.innerWidth && window.innerHeight)
        {
                //TODO: validate this block if implemented for firefox
                
                windowX = window.innerWidth - scrollXWidth;
                windowY = window.innerHeight;

                try
                {
                        scrollYWidth = Math.floor(Math.abs(window.innerHeight - document.documentElement.clientHeight)) + 1;
                        scrollBarX = (document.documentElement.clientWidth < document.documentElement.scrollWidth);
                }
                catch(err){}

                if (scrollBarX && !scrollYWidth)
                        scrollYWidth = 18;        //normally 17 (+1 top border)
                                        
        }
        else if (document.documentElement || document.body) 
        {
                windowX = (document.documentElement.clientWidth || document.body.clientWidth) - scrollXWidth;
                windowY = document.documentElement.clientHeight || document.body.clientHeight;
        }
        else
        {
                windowX = 0;
                windowY = 0;
        }

        return [windowX, windowY, scrollYWidth];
};
searchshield.zoomLevel = function ()
{
                var level = 1;
                if (document.body.getBoundingClientRect) {
                        // rect is only in physical pixel size before IE8 
                        var rect = document.body.getBoundingClientRect();
                        level = Math.round (((rect.right - rect.left) / (document.body.offsetWidth)) * 100) / 100;
                }
                
                return level;
};


// Href functions
searchshield.checkUrl = function (url)
{        // cleanup a url, make sure there is a protocol on the front for scanning
        try {
                // trim
                url = url.replace(/^\s+/, "").replace(/\s+$/, "");

                // if no protocol, add http:// to it        
                if (url.indexOf("://") == -1)
                        url = "http://" + url;
        }
        catch(err){}

        return url;
};
searchshield.DoesURLContain = function (url, contain)
{
        if ((url == null) || (url.length < 1))
                return false;

        // breakup the url to check
        var parts = url.split('/');
        if (parts.length < 3)
                return false;

        var domain= parts[2].toLowerCase();
        if (domain.indexOf(contain) > -1)
                return true;

        return false;
};
searchshield.FilterUrl = function (url, filter)
{
        if (!url || (url.length < 1))
                return false;
        
        if (!filter || !(filter instanceof Array))        
                return false;
                
        var parts = url.split('/');
        if ((parts == null) || (parts.length < 3))
                return false;

        var domain = parts[2];
        for (var i = 0; i < filter.length; i++)
        {
                if (domain.indexOf(filter[i]) != -1)
                        return true;
        }
        return false;
};
searchshield.GetDomain = function (url)
{
        if (url != null)
        {
                // get url domain
                var parts = url.split('/');
                if ((parts != null) && (parts.length >= 3))
                {
                        return parts[2].toLowerCase();
                }
        }
        
        return url;
};
searchshield.getUrlContents = function (url) 
{
        if (url == null)
                return null;

        // don't query if local url
        if (url.indexOf("linkscanner://") != -1)
                return null;

        try 
        {
                req = new XMLHttpRequest();
                req.open("GET", url, false);
                req.send(null);
                if (req.status == 200)
                        return req.responseText;
                else
                        return null;
        } 
        catch (err)
        {
                // nothing to do
                return null;
        }
};
searchshield.parseLink = function (href, simpleMode)
{
        var uri                  = {};
        var parameter = {
                        complex: {
                                pattern: /^(?:([a-z]+):(?:([a-z]*):)?\/\/)?(?:([^:@]*)(?::([^:@]*))?@)?((?:[a-z0-9_-]+\.)+[a-z]{2,})(?::(\d+))?(?:([^:\?\#]+))?(?:\?([^\#]+))?(?:\#([^\s]+))?$/i,
                                element: ['source','scheme','subscheme','user','pass','host','port','path','query','fragment']
                                },
                        simple: {
                                pattern: /^(?:([a-z]+):\/\/)?((?:[a-z0-9_-]+\.)+[a-z]{2,})(?:\/)([^:\?]+)?(?:([\?|\#])([^\?]+))?$/i,
                                element: ['source','scheme','host','path','delimiter','query']
                        }
                };
        var mode        = simpleMode !== false ? 'simple' : 'complex';
        var pattern        = parameter[mode].pattern;
        var element        = parameter[mode].element;
        
        if (!href)
                return uri;

        var matches        = href.match(pattern);
        
        if (matches)
        {
                // --------------------
                // iterate over the matches array and populate uri properties
                // using the respective element parameter as the name.
                // NOTE: set raw property type as String to make inArray()
                // work properly with instanceof.
                // --------------------
                for (var i=0; i < matches.length; i++)
                        uri[element[i]] = new String(matches[i] || "");
                
                // --------------------
                // create an array, hostArray, from host, for example,
                // host="www.google.com" and hostArray=["www","google","com"]
                // --------------------
                uri.hostArray        = uri.host.split(".");
                
                // --------------------
                // create an array, qsArray, from query, for example,
                // query='hl=en&q=javascript&btnG=Search&aq=f&aqi=g10&aql=&oq=&gs_rfai='
                // qsArray=[{hl:'en'},{q:javascript}, ... ,(qs_rfai:''}]
                //
                // $0=entire match, $1=capture 1, $2=capture 2
                // must include $0 even though it is unused so
                // the replace works properly
                // --------------------
                uri.qsArray                = [];
                uri.query.replace(/(?:^|&)([^&=]*)=?([^&]*)/g, 
                                                        function ($0, $1, $2) {
                                                                if ($1) uri.qsArray[$1] = $2;
                                                                }
                                                        );
        }
        
        //non-standard urls require a fail-safe that relies on simply splitting the href
        function splitLink(href)
        {
                // split the href on '/'
                var linkParts = href.split("/");

                // need domain and path
                if ((linkParts == null) || (linkParts.length < 2))
                        return false;
        
                var uri = {
                        delimiter: (linkParts[3]).substring(0,1),
                        host: linkParts[2],
                        hostArray: (linkParts[2]).split('.'),
                        path: (linkParts[3]).substring(1),
                        qsArray: {},
                        query: '',
                        scheme: (linkParts[0]).substring(0, linkParts[0].length-1),
                        source: href
                        };

                return uri;
        }

        if (!uri.host)
                uri = splitLink(href);

        return uri;
};

// general functions
searchshield.arrayKeys = function (array)
{
        var keys = new Array();
        for(k in array)
                keys.push(k);

        return keys;
};
searchshield.inArray = function (key, array, caseSensitive, exactMatch)
{
        if (! array instanceof Array)
                return false;
        
        if (caseSensitive !== true)
                caseSensitive = false;
                
        if (exactMatch !== false)
                exactMatch = true;
        
        if (key instanceof String)
        {
                for (var i=0; i < array.length; i++)
                {
                        var k = caseSensitive ? key.valueOf() : key.valueOf().toLowerCase();
                        var a = caseSensitive ? array[i] : array[i].toLowerCase();
                        if(exactMatch && k === a)
                                return true;
                        else if (!exactMatch && (-1 !== k.indexOf(a)))
                                return true;
                }
        }
        else if (key instanceof Array)
        {
                for (var i=0; i < array.length; i++)
                        for (var j=0; j < key.length; j++)
                        {
                                var k = caseSensitive ? key[j] : key[j].toLowerCase();
                                var a = caseSensitive ? array[i] : array[i].toLowerCase();
                                if (exactMatch && k === a)
                                        return true;
                                else if (!exactMatch && (-1 !== k.indexOf(a)))
                                        return true;
                        }
        }

        return false;
};
// general use functions - end


// Search constructor
searchshield.Search = function()
{
        this.doc                         = null;
        this.engine                 = null;
        this.engines                 = null;
        this.links                         = null;
        this.uri                         = null;
        this.searchHash         = null;
        this.checkUrl                 = null;
        this.useLocalImgs         = null;
        this.clockUrl                 = null;
        // create engine list (actually key/value object will be used)
        this.engineList                = {};
};

searchshield.Search.prototype.getSearchNames = function()
{        // order is important
        var names =  [
                'Google',
                'AVGGoogle',
                'AltaVista',
                'AVGYahoo',
                'Yahoo',
                'Bing',
                'MSN', // MSN redirects to BING
                'Baidu',
                'Earthlink',
                'AOL',
                'Ask',
                'Yandex',
                'Seznam',
                'Webhledani',
                'eBay',
///temp                'Digg',
                'Slashdot',
                'Twitter',
                'GMail',
                'Facebook'
        ];
        return names;
};

searchshield.Search.prototype.detectEngine = function(href)
{
        if (!href)
                return;

        var aEng = searchshield.Search.prototype.getSearchNames();
        var aEngLen = aEng.length;
        for (var i=0; i < aEngLen; i++)
        {
                if (searchshield[aEng[i] + 'SearchEngine'].prototype.validSearch(href))
                        return aEng[i];
        }

        return;
};

searchshield.Search.prototype.addEngine = function(engine)
{
        if (!this.engines)
                this.engines = new Array();
        
        this.engines.push(engine);
};

searchshield.Search.prototype.addLink = function(inElement, inHref)
{
        if (!this.links)
                this.links = new Array();

        var hrefHash;
        try
        {
                hrefHash = searchshield.avgCallFunc(this.doc, 'GetHash', inHref);
        }
        catch (e){}

        var newNode = {
                        element:        inElement,
                        href:                 inHref,
                        hash:                hrefHash,
                        search:                this.searchHash
                };
        
        this.links.push(newNode);
        
        return newNode;
}

// process the search result page after all search engines have been added
searchshield.Search.prototype.process = function(doc)
{
        // only process when searchshield is enabled
        if (0 == searchshield.avgCallFunc(doc, 'GetSearchEnabled'))
                return;
                
        this.doc        = doc;
        this.href        = this.doc.location.href;
        this.uri        = searchshield.parseLink(this.href);

        try
        {
                this.searchHash         = searchshield.avgCallFunc(this.doc, 'GetHash', this.href);

                // get any previously active engine
                this.engine                = this.engineList[this.searchHash.toString()];
        }
        catch (e) {}

        /*
        
        Process Steps:
        1. Add all supported search engines
        2. Identify the active search engine
        3. Get all document links and add AVG images 
        */
        
        // STEP 1 - Add all supported search engines
        if (!this.engines)
        {
                var aEng = xplSearch.getSearchNames();
                var aEngLen = aEng.length;
                for (var i=0; i < aEngLen; i++)
                {
                        xplSearch.addEngine(new searchshield[aEng[i]+'SearchEngine'](this));
                }
        }
        
        // search the engines if we didn't find one
        if (!this.engine)
        {
                // STEP 2 - Identify the active search engine
                var engLen = this.engines.length;
                for (var i = 0; i < engLen; i++)
                {
                        if (this.engines[i].validSearch())
                        {
                                this.engine                = this.engines[i];
                                break;
                        }
                }
                
                // create a new engine instance to store
                this.engineList[this.searchHash.toString()] = this.engine;
                
                // init this search, if < 1 either an error or disabled
                //var sdkInit = 0;
                //try {
                //        sdkInit = xpl_sdk.SXPL_InitSearch(this.href);
                //}
                //catch(e){}
                //if (sdkInit < 1)
                //        return false;
        }

        // return immediately if there is not an active search engine
        if (!this.engine)
                return false;
        
        try {        
                // base url to check for icons
                this.checkUrl         = searchshield.avgCallFunc(this.doc, 'GetIconUrl', '1');

                // check if using linked or local icons
                this.useLocalImgs        = !searchshield.getUrlContents(this.checkUrl);

                // get the clock url
                this.clockUrl         = searchshield.avgCallFunc(this.doc, 'GetIconUrl', '0');
        }
        catch(e){}
                

        // STEP 3 - Get all document links and add AVG images
        var alltags = this.doc.getElementsByTagName("*");        // this method works for IE, FF and Chrome
        for (var i=0; i < alltags.length; i++)
        {
                // ignore verdicts
                if (alltags[i].id && (alltags[i].id.indexOf("LXPLSS_") != -1))
                        continue;
        
                //should the link be included?  Make sure includeLink always returns an href else FALSE,
                var href = this.engine.includeLink(alltags[i]); 
                if (!href)
                        continue;

                var newNode = this.addLink(alltags[i], href);
                this.engine.addImage(newNode, this.clockUrl, false);
        }

        return (this.links ? this.links.length : false);
};
////////////////    SEARCH    ////////////////



////////////////    SEARCH ENGINE    ////////////////

// Interface for a SearchEngine object
searchshield.SearchEngine = function(search)
{
        this.search = search;
        this.type = 'standard';
        this.processFrames = false;
        this.new_links                = true;
        this.onlyPrimaries        = true;
        this.inline = {
                clockImage: "linkscanner://clock12.png",
                image: [        "linkscanner://safe12.png",
                                        "linkscanner://caution12.png",
                                        "linkscanner://warning12.png",
                                        "linkscanner://blocked12.png"
                                ],
                color: {
                        border: ["#00A120;", "#EAA500;", "#F57301;", "#D20003;"],
                        background: ["#C3E5CA;", "#FEEFAE;", "#FFD3B0;", "#F5D4C1;"]
                }
        };
        this.filter_urls = [
                "ad.doubleclick.net", "ads1.revenue.net", "aslads.ask.com",
                "bluestreak.com", "clickbacktrack.net", "clickbank.net",
                "clickboothlnk.com", "clickmanager.com", "clickserve.cc-dt.com",
                "clickserve.dartsearch.net", "clicktraxmedia.com", "clk.atdmt.com",
                "dpi-digialphoto.com", "feedpoint.net", "hypertracker.com",
                "jdoqocy.com", "kqzyfj.com", "m1428.ic-live.com",
                "mediaplex.com", "mr.mdmngr.com", "n339.asp-cc.com",
                "offeredby.net", "offerweb.com", "pinktrax.com",
                "pinktrax.com", "pixel1523.everesttech.net", "qckjmp.com",
                "r.rd06.com", "revenuewire.net", "s0b.bluestreak.com",
                "s2.srtk.net", "servedby.advertising.com", "store.yahoo.com",
                "tf8.cpcmanager.com", "thetoptracker.com", "track.searchignite.com",
                "tracking.searchmarketing.com", "www.dpbolvw.net", "www.rkdms.com",
                "www.yellowbookleads.com"
                ];
        this.shortened_urls = [
                "3.ly", "bit.ly", "is.gd", "tr.im", "short.to", "tiny.cc", "tinyurl.com"
                ];
        this.showCleanVerdicts                = true;
        this.showLowRiskVerdicts        = true;
        this.showMedRiskVerdicts        = true;
        this.VeriSignSplit                        = searchshield.VERISIGN_SPLIT_NOTEST;
};
searchshield.SearchEngine.prototype.flyoverExists = function (doc)
{
        return !!doc.getElementById("XPLSS_Flyover");
};
searchshield.SearchEngine.prototype.inlineExists = function (doc)
{
        return !!doc.getElementById("XPLSS_InlineFlyover");
};
searchshield.SearchEngine.prototype.validSearch = function(href) { return false; };
searchshield.SearchEngine.prototype.includeLink = function(link) { return false; };
searchshield.SearchEngine.prototype.insertNodes = function(node, doc)
{
        var element = node.element;
        var parentNode = node.element.parentNode;
        if (parentNode == null)
        {
                // try and find element again based on the hash
                element = doc.getElementById("xplid_" + node.hash);
                parentNode = !!element ? element.parentNode : null;
        }

        var insertNode = !!element ? element.nextSibling : null;
        while ((insertNode                        != null) && 
                        (insertNode.tagName        != null) && 
                        (insertNode.tagName        == "SPAN"))
        {
                insertNode = insertNode.nextSibling;
        }
        
        return [insertNode, parentNode];
};
searchshield.SearchEngine.prototype.addImage        = function(node, image, hidden)
{
        var element        = node.element;
        var hash        = node.hash;
        var score         = node.score;

        // set verdict display configuration
        var doc = element.ownerDocument;
        if (!doc.getElementById('XPLSS_Flyover'))
                searchshield.initFlyover(doc, this);

        // get the proper insertion point for the image
        var insertNodes = this.insertNodes(node, doc);
        var insertNode = insertNodes[0];
        var parentNode = insertNodes[1];

        if (!parentNode)
                return;

        // see if we already have an image
        if ((insertNode                != null) && 
                (insertNode.id        != null) && 
                (insertNode.id.indexOf("XPLSS_") > -1))
        {
                return;
        }

        // mark search result anchor so it isn't processed repeatedly
        if (score == undefined)
                element.setAttribute("avglschecked", hash + "S" + this.VeriSignSplit);

        // create a new image
        var img = doc.createElement('img');
        img.src = image;
        img.id = "XPLSS_" + hash;
        img.style.borderStyle = "none";
        img.style.margin = "0 3px";
        
        // for IE, specify these style attributes to prevent inadvertent inheritance from parent
        if (img.width && img.height)
        {
                img.style.width = img.width + 'px';
                img.style.height = img.height + 'px';
        }
        
        // apply custom element styles
        this.updateElementStyle(img, this.addImageStyle);
        
        // create the link element 
        var anchor = doc.createElement("A");
        anchor.setAttribute("id", "LXPLSS_" + hash);

        if ((hidden != null) && (hidden == true))
        {        // hiding the parent will also hide its child nodes
                anchor.style.display = "none";
        }
        
        // Default anchor styles
        //Over-ride possible border style with inline declaration
        anchor.style.borderStyle = "none";

        // apply custom element styles
        this.updateElementStyle(anchor, this.addAnchorStyle);

        if (score == searchshield.SCORE_SS_VERISIGN)
        {
                anchor.style.textDecoration = "none";
                anchor.style.background = "none";
        }

        // append the image to the link
        anchor.appendChild(img);

        // insert the node as either a sibling or a child
        if (insertNode != null)
                parentNode.insertBefore(anchor, insertNode);
        else
                parentNode.appendChild(anchor);
                
        return anchor;
};
searchshield.SearchEngine.prototype.updateImage = function (hash, search, score, image, alt_image, flyover, click_thru, altClick_thru)
{
                var updated = false;

                var frameDoc  = this.search.doc;
                var docFrames = frameDoc.frames;
                var frameElem;
                if (docFrames && this.processFrames)
                {
                        for (var i=0; i < docFrames.length; i++)
                        {
                                try {
                                        if (docFrames[i].document.getElementById(hash))
                                        {
                                                frameElem = docFrames[i].frameElement;
                                                frameDoc = docFrames[i].document;
                                                break;
                                        }
                                } 
                                catch(err){}
                        }
                }

                while ((element = frameDoc.getElementById(hash)) != null)
                {
                        // check configuration to determine if verdict display property
                        var showVerdict = true;                        
                        var nSeverity = Number(score - 1);
                        switch (nSeverity)
                        {
                                case searchshield.XPLCHECK_RESULT_SEV_LOW:
                                        showVerdict = this.showLowRiskVerdicts;
                                        break;
                                case searchshield.XPLCHECK_RESULT_SEV_MED:
                                        showVerdict = this.showMedRiskVerdicts;
                                        break;
                                case searchshield.XPLCHECK_RESULT_SEV_NONE:
                                        showVerdict = this.showCleanVerdicts;
                                        break;
                                default:
                                        if (score == searchshield.SCORE_SS_VERISIGN)
                                                showVerdict = this.showCleanVerdicts;
                                        break;
                        }
                        
                        // remove image if no url specified
                        if ((!showVerdict) || (image == null) || (image.length < 1))
                        {
                                // hide the parent anchor node
                                element.parentNode.style.display = "none";

                                // mark the id as being hidden (element is the image)
                                element.id = element.id + "H";
                                updated = true;
                                
                                // if not a verisign score
                                if (score != searchshield.SCORE_SS_VERISIGN)
                                        continue;
                        }

                        // cleanup flyover, replace any new lines or single quotes
                        flyover = searchshield.CleanupHTML(flyover);

                        // mark the id as having been updated
                        element.id = element.id + "U" + score;
                        element.src        = image;
                        element.attachEvent("onmouseover", function(e){avglsflyover.popup(e, hash, search, flyover)});
                        element.attachEvent("onmouseout", function(e){avglsflyover.hide(e)});

                        // check for attribute updates (elementAttribute is an associative array (i.e., object)
                        if (this.elementAttribute)
                        {
                                for (a in this.elementAttribute)
                                {
                                        if(this.elementAttribute[a])
                                                element.setAttribute(a, this.elementAttribute[a]);
                                }
                        }

                        // To dynamically reduce verdict image size if it causes its container to scroll
                        // when not showing alt images determine if the element containing
                        // the verdict image is scrolling and decrease the image size by
                        // the scroll amount (min size is 80% or original)
                        var reduceBy        = 0.8;
                        var scrl                = 0;
                        if (!alt_image || this.omitAltImage || this.VeriSignSplit == searchshield.VERISIGN_SPLIT_TESTB)
                        {
                                try{
                                        var maxLoop = 5;
                                        var cN = element.parentNode.parentNode;  //image->anchor->containerNodes...
                                        while (cN && maxLoop--)
                                        {
                                                if (cN.tagName == "DIV" || cN.tagName == "SPAN")
                                                {
                                                        // get object height depending on ie document mode
                                                        var clientHeight = (cN.clientHeight == 0 || 
                                                                (this.search.doc.documentMode && this.search.doc.documentMode < 8)) ? 
                                                                cN.offsetHeight : 
                                                                cN.clientHeight;
                                                        scrl = cN.scrollHeight - clientHeight;
                                                        break;
                                                }

                                                cN = cN.parentNode;
                                        }

                                        if (0 < scrl)
                                        {
                                                var eH = (element.height - scrl)/element.height;
                                                if (reduceBy > eH)
                                                        eH = reduceBy;
                                                
                                                var newDim = Math.ceil(eH*element.height);
                                                
                                                element.height = newDim;
                                                element.width = newDim;
                                                
                                                element.style.height = newDim + "px";
                                                element.style.width = newDim + "px";
                                        }
                                }
                                catch(e){}
                        }

                        // set default style attributes
                        element.style.display                = "";
                        
                        // if verisign icon showing move our icon up for better centering of the 2
                        // except for IE7 browser - it does not like this style
                        try {
                                var ieVersion = parseFloat(navigator.appVersion.split("MSIE")[1]);
                                if (alt_image && (alt_image.length > 0) && ieVersion != 7)
                                        element.style.verticalAlign = "10%";
                        }
                        catch(err){};

                        // apply custom element styles
                        this.updateElementStyle(element, this.updateImageStyle)

                        // update the click thru
                        var link = this.search.doc.getElementById("L" + hash);
                        if (link)
                        {
                                link.href = click_thru;
                                link.id = link.id + "U" + score;
                        }

                        updated = true;

                        // add the alternate image if supplied BUT not on avg yahoo
                        if ((alt_image)                                && 
                                (alt_image.length > 0)        && 
                                (!this.omitAltImage)        &&
                                (this.VeriSignSplit != searchshield.VERISIGN_SPLIT_TESTB))
                        {

                                var vhash = hash.substring(hash.indexOf("_")+1);

                                // create a temporary link node
                                var tmp_node = {
                                                element:        element.parentNode,
                                                href:                altClick_thru,
                                                hash:                vhash + "VU" + score,
                                                search:                this.searchHash,
                                                score:                score
                                        };

                                var altAnchor = this.addImage(tmp_node, alt_image, false);
                                if (altAnchor && altAnchor.firstChild)
                                {
                                        altAnchor.firstChild.setAttribute("onmouseover", "");
                                        altAnchor.href = altClick_thru;
                                }
                        }
                }
                
                if (updated != false)
                {
                        this.resizeFrame(frameElem);
                        return true;
                }

        return false;
};
searchshield.SearchEngine.prototype.updateElementStyle = function (element, elementStyle)
{
        if (elementStyle)
        {        // a NULL attribte value will unset it
                for(attr in elementStyle)
                {
                        try {
                                if (element.style.setAttribute)
                                        element.style.setAttribute(attr, elementStyle[attr]);
                                else
                                        element.style[attr] = elementStyle[attr];
                        } catch(err){}
                }
        }
};

searchshield.SearchEngine.prototype.resizeFrame = function (frameElem)
{        // resize frame to prevent unwanted scrolling after inserting verdicts

        // ignore inline and non-frame engines
        if ((this.type == 'inline') || (!this.processFrames))
                return;

        // ensure all required elements are available
        if ((frameElem == null) || (frameElem.style == null) || (frameElem.contentWindow == null))
                return;

        // if frame is scrolling vertically then resize
        var frameHeight = parseInt(frameElem.style.height, 10);
        if (!isNaN(frameHeight) && (frameHeight < frameElem.contentWindow.document.body.scrollHeight))
                frameElem.style.height = frameElem.contentWindow.document.body.scrollHeight + 'px';

        return;
};

searchshield.SearchEngine.prototype.getImgElement = function (element)
{        // return an xpl img element associated with a given element
        if (element == null)
                return null;

        // go up the parent tree looking for a header or div
        while ( (element.parentNode != null) && 
                        (element.tagName.charAt(0) != "H") && 
                        (element.tagName.charAt(0) != "D") &&
                        (element.tagName.charAt(0) != "T") )
        {
                element = element.parentNode;
        }

        // if all the way to the top, nothing
        if ((element.tagName == "HTML") || (element == null))
                return null;

        // get image tags, if none we are done
        var imgTags = element.getElementsByTagName("IMG");
        if ((imgTags == null) || (imgTags.Length < 1))
                return null;

        for (var i = 0; i < imgTags.length; i++)
        {
                if ((imgTags[i].id == null) || (imgTags[i].id.indexOf("XPLSS_") == -1))
                        continue;

                return imgTags[i];
        }

        // else didn't find anything
        return null;
};

searchshield.SearchEngine.prototype.setRatingsConfig = function (doc)
{
        // get verdict configuration, need at least severity
        var results = searchshield.avgCallFunc(doc, 'GetRatingsConfig');
        var parts = !!results ? results.split('::') : null;

        if (parts != null && parts.length >= 5)
        {        //if set to default then get config value
                if (this.showCleanVerdicts === true)
                        this.showCleanVerdicts                = (parseInt(parts[0]) == 1) ? true : false;
                        
                if (this.showLowRiskVerdicts === true)
                        this.showLowRiskVerdicts        = (parseInt(parts[1]) == 1) ? true : false;
                
                if (this.showMedRiskVerdicts === true)
                        this.showMedRiskVerdicts        = (parseInt(parts[2]) == 1) ? true : false;
                        
                this.VeriSignSplit        = (parseInt(parts[4]));
        }
        
        return true;
};

searchshield.SearchEngine.prototype.init_inline_ratings = function (doc)
{
        if ((doc == null) || (doc.getElementById("XPLSS_InlineFlyover")))
                return;
        
        // create the popup box
        var box = doc.createElement("DIV");
        try {
                box.setAttribute("id", "XPLSS_InlineFlyover");
                box.style.visibility = "hidden";
                box.style.left = "-5000px";

                box.style.position = "absolute";
                box.style.zIndex = "9999";
                box.style.padding = "0px 0px";
                box.style.marginLeft = "0px";
                box.style.marginTop = "0px";
                box.style.overflow = "hidden";
                box.style.wordWrap = "break-word";
                box.style.color = "black";
                box.style.fontSize = "10px";
                box.style.textAlign = "left";
                box.style.lineHeight = "130%";

                doc.body.appendChild(box);
                box = null;
        }
        catch(boxErr){}
};

searchshield.SearchEngine.prototype.show_inline_ratings = function (doc, node, image)
{        
        var href        = node.href;
        var anchor        = node.element;

        if ((href == null) || (href.length < 1))
                return;
                
        if (avglsinlineflyover.imageExists(anchor))
                return;
        
        // mark search result anchor so it isn't processed repeatedly
        anchor.setAttribute("avglschecked", "1");
        
        // get verdict 
        this.display_inline(doc, anchor, href, node, false);
};

searchshield.SearchEngine.prototype.display_inline = function (doc, anchor, href, node, update, min_severity)
{
        // min_severity is the lowest severity to display, so setting it to
        // 1 would not display safe icons
        
        var results        = searchshield.avgCallFunc(doc, 'MalsiteCheck', href);
        if (results == null)
                return;
        
        var parts = results.split('::');
        
        // need at least severity
        if (parts == null)
                return;
                        
        var nSeverity = parseInt(parts[0]);
        
        if (!update && nSeverity == searchshield.XPLCHECK_RESULT_SEV_NONE)
        {
                var shortUrl = searchshield.FilterUrl(href, this.shortened_urls);
                if (shortUrl)
                {        // shortened url verdicts display later
                        var engine = this;
                        anchor.attachEvent("onmouseover", function(event){avglsinlineflyover.mouseOverHandler(event, doc, engine)}, false);
                        return;
                }
        }

        //blacklist url
        var blShortUrl = false;
        if (nSeverity == searchshield.XPLCHECK_RESULT_SEV_BLOCK)
        {
                var shortUrl = searchshield.FilterUrl(href, this.shortened_urls);
                if (shortUrl)
                        blShortUrl = true;
        }
        
        // need xlated cat tag and category
        if (parts.length < 3)
                return;

        // check the minimum to display
        if ((min_severity != null) && (nSeverity < min_severity))
                return;
                
        if (nSeverity == searchshield.XPLCHECK_RESULT_SEV_LOW && !this.showLowRiskVerdicts)
        {
                if (update)
                        this.avg_ls_inline_hide_verdict(anchor);
                
                return;
        } 
        if (nSeverity == searchshield.XPLCHECK_RESULT_SEV_MED && !this.showMedRiskVerdicts)
        {
                if (update)
                        this.avg_ls_inline_hide_verdict(anchor);
                
                return;
        }
        if (nSeverity == searchshield.XPLCHECK_RESULT_SEV_NONE && !this.showCleanVerdicts) 
        {
                if (update)
                        this.avg_ls_inline_hide_verdict(anchor);
                        
                return;
        }

        if (update)
                this.update_inline_image(anchor, nSeverity, parts);
        else
                this.add_inline_image(doc, anchor, nSeverity, parts, blShortUrl);
};

searchshield.SearchEngine.prototype.avg_ls_inline_hide_verdict = function (anchor)
{
        var image = avglsinlineflyover.getImage(anchor);
        if (image)
        {
                image.style.display = "none";
                if (image.parentNode && image.parentNode.id == "avg_ls_anch")
                        image.parentNode.style.display = "none";
        }
};

searchshield.SearchEngine.prototype.update_inline_image = function (anchor, nSeverity, aRisk)
{
        // update the image already in the page
        if (anchor && anchor.firstChild)
        {
                var html  = '';
                var image = ''; 
                if (aRisk != null && nSeverity != null)
                {
                        var riskCategory = aRisk[1];
                        var riskName         = aRisk[2];
                        var bgColor                 = this.inline.color.background[nSeverity];
                        var borderColor         = this.inline.color.border[nSeverity];

                        image                         = this.inline.image[nSeverity];
                        html                         = avglsinlineflyover.build(riskCategory, riskName, bgColor, borderColor);
                }
                
                var imageElem = anchor.firstChild;
                imageElem.src = image;
                
                if ( html && html.length > 0 )
                {
                        imageElem.setAttribute("title", "");
                        imageElem.attachEvent("onmouseover", function(e){avglsinlineflyover.popup(e, html)});
                        imageElem.attachEvent("onmouseout", function(e){avglsinlineflyover.hide(e)});
                }
        }
};

// add the image to the page
searchshield.SearchEngine.prototype.add_inline_image = function (doc, anchor, nSeverity, aRisk, blShortUrl)
{
        if (anchor == null || anchor.parentNode == null)
                return null;

        // get the proper insertion point for the image
        var insertNode = anchor.nextSibling;
        while ((insertNode                        != null) && 
                        (insertNode.tagName != null) && 
                        (insertNode.tagName == "SPAN"))
        {
                insertNode= insertNode.nextSibling;
        }
        
        // see if we already have an image anchor
        if ((insertNode                != null) && 
                (insertNode.id        != null) && 
                (insertNode.id        == "avg_ls_anch"))
        {
                return null;
        }

        var html  = '';
        var image = this.inline.clockImage; 
        if (aRisk != null && nSeverity != null)
        {
                var riskCategory = aRisk[1];
                var riskName         = aRisk[2];
                var bgColor                 = this.inline.color.background[nSeverity];
                var borderColor         = this.inline.color.border[nSeverity];
                image                         = this.inline.image[nSeverity];

                var blUrl;
                if (blShortUrl)
                {
                        var aRiskName = riskName.split(':');
                        var sUrl = searchshield.checkUrl(aRiskName[1]);

                        blUrl = {};
                        blUrl.riskNameLabel = aRiskName[0] + ': ';
                        blUrl.riskCategory = riskCategory;
                        blUrl.bgColor = bgColor;
                        blUrl.borderColor = borderColor;
                        blUrl.sUrl = sUrl;
                }
                else
                {
                        html = avglsinlineflyover.build(riskCategory, riskName, bgColor, borderColor);
                }
        }

        doc = anchor.ownerDocument;

        var img                 = doc.createElement("img");
        img.src                 = image;
        img.setAttribute("id","avg_ls_image");
        img.style.width = "12px";
        img.style.border = "none";
        img.style.padding = "0 3px";
        img.style.margin = "0";
        img.style.display = "inline";
        
        if ((html && html.length > 0) || (blUrl != undefined))
        {
                img.setAttribute("title", "");
                img.attachEvent("onmouseover", function(e){avglsinlineflyover.popup(e, html, blUrl)});
                img.attachEvent("onmouseout", function(e){avglsinlineflyover.hide(e)});
        }

        // create the link element 
        var newAnchor = doc.createElement("A");
        newAnchor.setAttribute("id", "avg_ls_anch");
        
        newAnchor.appendChild(img);
        img = null;

        // insert the node as either a sibling or a child
        if (insertNode != null)
                anchor.parentNode.insertBefore(newAnchor, insertNode);
        else
                anchor.parentNode.appendChild(newAnchor);        
                
        return newAnchor;                

};
////////////////    SEARCH ENGINE    ////////////////


///////////////    GOOGLE SEARCH ENGINE    ///////////////
searchshield.GoogleSearchEngine = function(search)
{
        searchshield.SearchEngine.call(this, search);
        this.onlyPrimaries = false;
};
searchshield.GoogleSearchEngine.prototype = new searchshield.SearchEngine();
searchshield.GoogleSearchEngine.prototype.constructor = searchshield.GoogleSearchEngine;
searchshield.GoogleSearchEngine.prototype.name = "google";        // the name by which the search engine is known (always lowercase)
searchshield.GoogleSearchEngine.prototype.validSearch = function(href) {

        var uri;
        if (typeof(this.search) === 'undefined' || null === this.search)
                uri = searchshield.parseLink(href);
        else
                uri = this.search.uri;

        if(!uri || !uri.host)
                return false;

        var hostMatch        = false;
        var domain                = uri.host;
        
        // re stitch the uri path and query elements to
        // use existing logic
        var path = uri.path + uri.delimiter + uri.query;

        // Domains valid for google searches, must start with '.'
        var valid_domains = new Array(".google.co", ".mozilla.co");

        // For Google the host must match:
        //        .google.com                OR
        //        .google.co.XX        where XX is a country code
        //        .google.XX                where XX is a country code
        // Where any subdomain can come before the top level domain
        var domLen = valid_domains.length;
        for (var i = 0; i < domLen; i++)
        {
                var domainLen = domain.length;
                var valid_domain_len = valid_domains[i].length;
                var tldPos = domain.indexOf(valid_domains[i]);
                if (tldPos > -1)
                {
                        if (domain.charAt(tldPos + valid_domain_len) == 'm')
                                hostMatch = true;
                        else if ((domain.charAt(tldPos + valid_domain_len) == '.') && ((domainLen - tldPos) == valid_domain_len+3))
                                hostMatch = true;
                }
                else
                {
                        // get the form .google. to check the length of
                        var dot_pos = valid_domains[i].indexOf(".",1);
                        var valid_short_name = valid_domains[i].substring(0, dot_pos+1);

                        tldPos = domain.indexOf(valid_short_name);
                        if ((tldPos > -1) && ((domainLen - tldPos) == valid_domain_len))
                                hostMatch = true;
                }
                if (hostMatch)
                {
                        // replace beginning of domain with www.google since links will refer back to it
                        if ((i > 0) && (tldPos > -1))
                        {
                                var last_dot = domain.indexOf(".",tldPos+1)
                                if (last_dot > -1)
                                        domain = "www.google" + domain.substring(last_dot);
                        }
                        break;
                }
        }

        if (hostMatch)
        {
                // using ajax engine
                if ((path.indexOf("search?") == 0) ||
                        (path.indexOf("sponsoredlinks?") == 0) ||
                        (path.indexOf("webhp?") == 0) ||
                        (path.indexOf("webhp#") == 0) ||
                        (path.indexOf("#q=") == 0) ||
                        (path.indexOf("#hl=") == 0) ||
                        (path.indexOf("#sclient=") == 0))
                {
                        return true;
                }
        }

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

        // check for interstitials
        if (searchshield.DoesURLContain(tag.href, this.search.uri.host))
        {
                findStr = this.search.uri.host + "/interstitial?";
                if (tag.className == "l" && tag.href)
                {
                        if (tag.href.indexOf(findStr) != -1)
                        {
                                findStr = "?url=";
                                var pos = tag.href.indexOf(findStr);
                                if (pos !== -1)
                                {
                                        pos += 5;
                                        outHref = tag.href.substring(pos);
                                        if (searchshield.FilterUrl(outHref, this.filter_urls))
                                                return false;
                                                        
                                        return outHref;
                                }
                        }
                }

                if (tag.className == "sla")
                {
                        findStr = "/url?q=";
                        urlPos = tag.href.indexOf(findStr);
                        if (urlPos != -1)
                        {
                                urlPos += 7;
                                outHref = tag.href.substring(urlPos);
                                return outHref;
                        }
                }
                
                // if an ad id
                if ((tag.id.indexOf("pa") == 0) || (tag.id.indexOf("an") == 0) ||
                        (tag.className == "resultLink"))
                {
                        var urlPos = -1;        

                        // ads now need unescaping
                        href = unescape(tag.href);

                        findStr= "/url?sa=";
                        if (href.indexOf(findStr) != -1)
                        {        // first kind, locate real url
                                findStr= "&q=http";
                                urlPos = href.indexOf(findStr);
                                if (urlPos != -1)
                                        urlPos += 3;        // puts it on the http
                        }
                        if (urlPos == -1)
                        {
                                findStr = "/pagead/iclk?sa=";
                                if (href.indexOf(findStr) != -1)
                                {        // second kind, locate real url
                                        findStr = "&adurl=http";
                                        urlPos        = href.indexOf(findStr);
                                        if (urlPos != -1)
                                                urlPos += 7; // puts it on the http
                                }
                        }
                        if (urlPos == -1)
                        {
                                if (href.indexOf("/aclk?sa=") != -1)
                                {        // third kind
                                        urlPos = href.indexOf("&q=http");
                                        if (urlPos != -1)
                                                urlPos += 3; // puts it on the http
                                        else
                                        {
                                                urlPos  = href.indexOf("&lp=http");
                                                if (urlPos != -1)
                                                        urlPos += 4;
                                                else
                                                {
                                                        findStr = "&adurl=http";
                                                        urlPos        = href.indexOf(findStr);
                                                        if (urlPos != -1)
                                                                urlPos += 7; // puts it on the http
                                                }
                                                
                                        }
                                }
                        }
                        if (urlPos == -1)
                        {
                                if (href.indexOf("/url?cad=") != -1)
                                {        // fourth kind
                                        urlPos = href.indexOf("&q=http");
                                        if (urlPos != -1)
                                                urlPos += 3; // puts it on the http
                                }
                        }
                        if (urlPos != -1)
                        {
                                outHref = href.substring(urlPos);

                                // extract any fragment text, shouldn't be unescaped
                                var pound = outHref.indexOf("#");        
                                if (pound != -1)
                                {
                                        var fragment = outHref.substring(pound);
                                        outHref = outHref.substring(0, pound);
                                        outHref = unescape(outHref);
                                        outHref += fragment;
                                        if (searchshield.FilterUrl(outHref, this.filter_urls))
                                                return false;

                                        return outHref;
                                }

                                outHref = unescape(outHref);
                                if (outHref.indexOf("?") == -1)
                                {
                                        var ampPos = outHref.indexOf("&");
                                        if (ampPos != -1)
                                                outHref = outHref.substring(0, ampPos);
                                }
                                
                                if (searchshield.FilterUrl(outHref, this.filter_urls))
                                        return false;

                                return outHref;
                        }
                }

                // recommended link - use following to see one
                // http://www.google.cz/search?hl=cs&q=warey&btnG=Hledat&lr=lang_cs
                // elem parent class = r
                // href must contain - url? and q=http
                var parentNode = tag.parentNode;
                if (parentNode && (parentNode.className.toLowerCase() == "r"))
                {
                        href = tag.href;
                        if (href && (href.indexOf("/url?") != -1))
                        {
                                // locate the real url
                                var urlPos = href.indexOf("q=http");
                                if (urlPos != -1)
                                {
                                        urlPos += 2;
                                        outHref = href.substring(urlPos);

                                        // include entire param up to '&'
                                        var ampPos = outHref.indexOf("&");
                                        if (ampPos != -1)
                                                outHref = outHref.substring(0, ampPos);

                                        return outHref;
                                }
                        }
                }
        }
        // no link to self
        else if (tag.className && (tag.className.charAt(0) == "l" || tag.className == "sla"))
        {
                // check for any images on the link
                if (0 === tag.getElementsByTagName("IMG").length)
                        return tag.href;
        }

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


///////////////    AVG GOOGLE SEARCH ENGINE    ///////////////
searchshield.AVGGoogleSearchEngine = function(search)
{
        searchshield.SearchEngine.call(this, search);
        this.onlyPrimaries = false;
};
searchshield.AVGGoogleSearchEngine.prototype = new searchshield.SearchEngine();
searchshield.AVGGoogleSearchEngine.prototype.constructor = searchshield.AVGGoogleSearchEngine;
searchshield.AVGGoogleSearchEngine.prototype.name = "avggoogle";        // the name by which the search engine is known (always lowercase)
searchshield.AVGGoogleSearchEngine.prototype.validSearch = function(href) {

        var uri;
        if (typeof(this.search) === 'undefined' || null === this.search)
                uri = searchshield.parseLink(href);
        else
                uri = this.search.uri;

        if(!uri || !uri.host)
                return false;

        var domain                = uri.host;
        
        // re stitch the uri path and query elements to
        // use existing logic
        var path = uri.path + uri.delimiter + uri.query;

        if  (domain.indexOf("search.avg.com") > -1)
        {   // ads link back to google
                return true;
        }
        
        return false;
};
searchshield.AVGGoogleSearchEngine.prototype.includeLink = function(tag)
{
        var outHref = false;
        var findStr = "";

        // check for interstitials
        if (searchshield.DoesURLContain(tag.href, "google.com"))
        {
                // link back to self - DIV elem GrandParent class of res1 or res3 is Sponsored Link 
                var parentNode = tag.parentNode;
                if (parentNode)
                {
                        var grandParentNode = tag.parentNode.parentNode;
                        if (grandParentNode)
                        {
                                if ((grandParentNode.tagName == "DIV") && 
                                        ((grandParentNode.className.toLowerCase() == "res1") ||
                                        (grandParentNode.className.toLowerCase() == "res3")))
                                {
                                        var urlPos = -1;        

                                        // ads now need unescaping
                                        href = unescape(tag.href);

                                        if (urlPos == -1)
                                        {
                                                if (href.indexOf("/aclk?sa=") != -1)
                                                {        
                                                        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;

        // 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 country code OR
        //        search.yahoo.co.xx OR
        // for Yahoo China: one.cn.yahoo.com & search.cn.yahoo.com
        if ((uri.host.indexOf("search.yahoo.co") != -1) ||
                (uri.host.match(/^(search|one)(\.[a-z]{2}\.yahoo\.com)$/))) 
        {
                if ((path.indexOf("search?") == 0) ||
                        (path.indexOf("search;") == 0) ||
                        (path.indexOf("s?p=") === 0))
                {
                        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.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 <I>, 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 <I>, 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);
};
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.addImage = function(node, image, hidden)
{
        this.addImageStyle = {
                display: "inline"
        };

        this.addAnchorStyle = {
                display: null
        };
                
        var parent = searchshield.SearchEngine.prototype.addImage;
        return parent.call(this, node, image, hidden);
};
searchshield.AOLSearchEngine.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,
                display: "inline"
        };
                
        var parent = searchshield.SearchEngine.prototype.updateImage;
        return parent.call(this, hash, search, score, image, alt_image, flyover, click_thru, altClick_thru);
};
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'))
                                return [cN[i].nextSibling, cN[i].parentNode];
                }
        }
        else
        {
                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("mercado") == -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];
                }
                
                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 += "<img src=linkscanner://LS_Logo_Results.gif /><br />";
                html += riskCategory + "<br />";
                html += riskName + "<br /></div>";

                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    ///////////////
</SCRIPT></div></body></html>