
     /*
     *  Ident Engine
     *  0.1.7
     *  Copyright 2009, Glenn Jones
     *  Licensed under the MIT license
     *  http://identengine.com/license/
     *  More information on this file: http://identengine.com/
     */


    ident = new function(){};
    
    // Public use
    ident.version = "0.1.7";
    ident.useInwardEdges = true;
    ident.identities = new Array();    
    ident.domains = new Array();
    ident.history = new Array();
    ident.ufParser = null;
    ident.rssParser = null; 
    ident.atomParser = null;
    ident.iconPath = "ident/icons/";
    ident.addPrimaryURL = true;

    
    // Internal use
    ident._startUrl = '';
    ident._apiReturnCount = 0;
    ident._usernames =  new Array();
    ident._primaryCalled = false; 
    ident._secondaryCalled = false; 

    // A updated version of this JSON data can be found at: http://identengine.com/
    ident._endPoints = {"sites": []} // Object stucture now built from compact array
    ident._endPointsArray = [["12seconds tv", "12seconds.tv", [["12seconds.tv/channel/{username}", "hCard", "Profile", "h"], ["12seconds.tv/followers/{username}", "hCard", "Friends", "h"], ["12seconds.tv/followers/{username}?page={pagenumber}", "hCard", "Friends", "h"], ["12seconds.tv/channel/{username}", "hAtom", "Video", "h"]]], ["43things", "43things.com", [["www.43things.com/person/{username}", "None", "None", "h"], ["www.43things.com/rss/uber/author?username={username}", "Rss", "Activity", "r"]]], ["43people", "43people.com", [["{username}.43people.com/", "None", "None", "h"], ["www.43people.com/rss/uber/person?person={username}", "Rss", "Activity", "r"]]], ["43places", "43places.com", [["{username}.43places.com/", "None", "None", "h"]]], ["Backnetwork", "backnetwork.com", []], ["Backtype", "backtype.com", [["www.backtype.com/{username}/", "None", "Profile", "h"], ["feeds.backtype.com/{username}", "Rss", "Activity", "r"]]], ["BarCamp Brighton 3", "barcampbrighton3.backnetwork.com", [["barcampbrighton3.backnetwork.com/people/person.aspx?personid={username}", "hCard", "Profile", "h"], ["barcampbrighton3.backnetwork.com/people/person.aspx?personid={username}", "XFN-hCard", "Friends", "h"]]], ["BarCamp London 5", "barcamplondon5.backnetwork.com", [["barcamplondon5.backnetwork.com/people/person.aspx?personid={username}", "hCard", "Profile", "h"], ["barcamplondon5.backnetwork.com/people/person.aspx?personid={username}", "XFN-hCard", "Friends", "h"]]], ["Blip.fm", "blip.fm", [["blip.fm/profile/{username}/", "None", "None", "h"], ["blip.fm/feed/{username}", "Atom", "Audio", "a"]]], ["Blip.tv", "blip.tv", [["{username}.blip.tv/", "None", "Profile", "h"]]], ["Blippr", "blippr.com", [["www.blippr.com/profiles{username}", "None", "Profile", "h"], ["www.blippr.com/profiles/{username}/feed.rss", "Atom", "Activity", "a"]]], ["BlogSpot", "blogspot.com", []], ["Blogger", "blogger.com", [["www.blogger.com/profile/{userid}", "None", "Profile", "h"]]], ["Brightkite", "brightkite.com", [["brightkite.com/people/{username}", "hCard", "Profile", "h"], ["brightkite.com/people/{username}/friends?page={pagenumber}", "None", "Friends", "h"], ["brightkite.com/people/{username}/objects.rss", "Atom", "Activity", "a"]]], ["ClaimId", "claimid.com", [["claimid.com/{username}", "hCard", "Profile", "h"]]], ["CoComment", "cocomment.com", [["www.cocomment.com/comments/{username}", "None", "None", "h"], ["www.cocomment.com/webRssUser/{username}.rss", "Rss", "Activity", "r"]]], ["Corkd", "corkd.com", [["corkd.com/people/{username}", "hCard", "Profile", "h"], ["corkd.com/people/{username}/buddies?page={pagenumber}", "XFN", "Friends", "h"]]], ["Cliqset", "cliqset.com", [["cliqset.com/user/{username}", "None", "Profile", "h"], ["cliqset.com/feed/atom?uid={username}", "Atom", "Activity", "a"]]], ["d.construct 08", "dconstruct08.backnetwork.com", [["dconstruct08.backnetwork.com/people/person.aspx?personid={username}", "hCard", "Profile", "h"], ["dconstruct08.backnetwork.com/people/person.aspx?personid={username}", "XFN-hCard", "Friends", "h"]]], ["Delicious", "del.icio.us", [["feeds.delicious.com/v2/rss/{username}?count=20", "Atom", "Bookmarks", "a"], ["del.icio.us/rss/{username}", "Rss", "Bookmarks", "r"], ["del.icio.us/{username}#bundle-tags", "rel-tag", "Interests", "h"], ["del.icio.us/{username}", "None", "Profile", "h"], ["delicious.com/{username}", "None", "Profile", "h"]]], ["Digg", "digg.com", [["digg.com/users/{username}", "hCard", "Profile", "h"], ["digg.com/users/{username}/friends/view/page{pagenumber}", "XFN-hCard", "Friends", "h"]]], ["Disqus", "disqus.com", [["www.disqus.com/people/{username}/", "None", "Profile", "h"], ["www.disqus.com/people/{username}/comments.rss", "Rss", "Lifestream", "r"]]], ["Django People", "djangopeople.net", [["djangopeople.net/{username}/", "hCard", "Profile", "h"], ["djangopeople.net/{username}/", "XFN", "Services", "h"]]], ["Dopplr", "dopplr.com", [["www.dopplr.com/traveller/{username}", "hCard", "Profile", "h"]]], ["Edenbee", "edenbee.com", [["www.edenbee.com/users/{username}", "hCard", "Profile", "h"], ["www.edenbee.com/users/{username}/relationships?page=(pagenumber}", "hCard", "Friends", "h"], ["www.edenbee.com/users/{username}/relationships", "hCard", "Friends", "h"], ["edenbee.com/users/{username}", "None", "None", "h"]]], ["Emberapp", "emberapp.com", [["emberapp.com/{username}", "None", "Profile", "h"], ["emberapp.com/{username}/images.rss", "None", "Images", "r"]]], ["Facebook", "facebook.com", [["www.facebook.com/{username}", "hCard", "Profile", "html"], ["www.facebook.com/{username}", "XFN", "Friends", "html"]]], ["FFFFound", "ffffound.com", [["ffffound.com/home/{username}/found/feed", "Rss", "Images", "r"], ["ffffound.com/home/{username}/found/", "None", "None", "h"]]], ["Flickr", "flickr.com", [["www.flickr.com/people/{username}/", "hCard", "Profile", "h"], ["api.flickr.com/services/feeds/photos_public.gne?id={userid}&format=rss_200", "Rss", "Images", "r"], ["api.flickr.com/services/feeds/photos_public.gne?id={userid}&format=atom", "Atom", "Images", "a"], ["www.flickr.com/photos/{username}/", "None", "Images", "h"], ["flickr.com/photos/{username}/", "None", "Images", "h"], ["www.flickr.com/people/{username}/contacts/?page={pagenumber}", "None", "Friends", "h"]]], ["FOTB 08", "fotb08.backnetwork.com", [["fotb08.backnetwork.com/people/person.aspx?personid={username}", "hCard", "Profile", "h"], ["fotb08.backnetwork.com/people/person.aspx?personid={username}", "XFN-hCard", "Friends", "h"]]], ["Fotolog", "fotolog.com", [["www.fotolog.com/{username}", "None", "Profile", "h"]]], ["FriendFeed", "friendfeed.com", [["friendfeed.com/{username}", "hCard", "Profile", "h"], ["friendfeed.com/{username}/services", "XFN", "Services", "h"], ["friendfeed.com/{username}?format=atom", "Atom", "Lifestream", "a"]]], ["GetSatisfaction", "getsatisfaction.com", [["getsatisfaction.com/people/{username}", "hCard", "Profile", "h"], ["getsatisfaction.com/people/{username}.rss", "Rss", "Activity", "r"]]], ["Github", "github.com", [["github.com/{_usernames}/", "hCard", "Profile", "h"], ["github.com/{username}.atom", "Atom", "Activity", "a"]]], ["Google", "google.com", [["www.google.com/profiles/{username}", "hCard", "Profile", "h"], ["www.google.com/profiles/{username}", "XFN", "Services", "h"], ["www.google.com/profiles/{userid}", "XFN", "Services", "h"], ["www.google.com/profiles/{userid}", "hCard", "Profile", "h"]]], ["Google Reader", "google.com", [["www.google.com/reader/shared/{username}", "None", "Profile", "h"]]], ["hi5", "hi5.com", []], ["Huffduffer", "huffduffer.com", [["huffduffer.com/{username}", "hCard", "Profile", "h"], ["huffduffer.com/{username}/rss", "Rss", "Audio", "r"], ["huffduffer.com/{username}", "hAtom", "Audio", "h"]]], ["Identica", "identi.ca", [["identi.ca/{username}", "hCard", "Profile", "h"], ["identi.ca/{username}/foaf", "FOAF", "Profile", "Xml"], ["identi.ca/{username}/subscriptions?page={pagenumber}", "hCard", "Friends", "h"], ["identi.ca/{username}", "hAtom", "Status", "h"], ["identi.ca/{username}", "rel-tag", "Interests", "h"], ["identi.ca/{username}/all", "hAtom", "Friends Status", "h"]]], ["Jaiku", "jaiku.com", [["{username}.jaiku.com/", "hCard", "Profile", "h"]]], ["JPG", "jpgmag.com", [["www.jpgmag.com/people/{username}/photos", "hCard", "Profile", "h"], ["www.jpgmag.com/people/{username}/rss", "Rss", "Images", "r"], ["www.jpgmag.com/people/{username}/stories/rss", "Rss", "Entries", "r"], ["www.jpgmag.com/people/{username}/stories", "None", "None", "h"]]], ["Joost", "joost.com", [["www.joost.com/users/{username}/", "None", "Profile", "h"], ["www.joost.com/api/events/get/{username}?fmt=atom", "Atom", "Video", "a"]]], ["krop", "krop.com", [["www.krop.com/{username}/resume/", "None", "Resume", "h"], ["www.krop.com/{username}/portfolio/", "None", "Profile", "h"]]], ["Last.fm", "last.fm", [["www.last.fm/user/{username}", "hCard", "Profile", "h"], ["www.last.fm/user/{username}/friends?page={pagenumber}", "hCard", "Friends", "h"], ["ws.audioscrobbler.com/1.0/user/{username}/recenttracks.rss", "Rss", "Activity", "r"], ["www.last.fm/user/{username}", "hCalendar", "Events", "h"], ["ws.audioscrobbler.com/1.0/user/{username}/events.rss", "Rss", "Events", "r"]]], ["Linked-in", "linkedin.com", [["www.linkedin.com/in/{username}", "hCard", "Profile", "h"], ["www.linkedin.com/in/{username}", "hResume", "Resume", "h"], ["www.linkedin.com/pub/{username}", "hCard", "Profile", "h"], ["www.linkedin.com/pub/{username}", "hResume", "Resume", "h"]]], ["Livejournal", "livejournal.com", [["{username}.livejournal.com/", "None", "Profile", "h"]]], ["MadgexLab", "ufapi.lab.madgex.com", [["ufapi.lab.madgex.com/profile/{username}", "hCard", "Profile", "h"]]], ["Mashed 08", "mashed08.backnetwork.com", [["mashed08.backnetwork.com/people/person.aspx?personid={username}", "hCard", "Profile", "h"], ["mashed08.backnetwork.com/people/person.aspx?personid={username}", "XFN-hCard", "Friends", "h"]]], ["Meetup", "meetup.com", []], ["Microformats.org", "microformats.org", [["microformats.org/wiki/User:{username}", "hCard", "Profile", undefined]]], ["Mybloglog", "mybloglog.com", [["www.mybloglog.com/buzz/members/{username}/hcard", "hCard", "Profile", "h"], ["www.mybloglog.com/buzz/members/{username}/", "None", "None", "h"], ["www.mybloglog.com/buzz/members/{username}/me/rss.xml", "Atom", "Lifestream", "a"]]], ["mytvshows", "mytvshows.org", [["www.mytvshows.org/user/{username}/", "hCard", "Profile", "h"], ["www.mytvshows.org/rss/user/{username}/", "Rss", "Activity", "r"]]], ["My Name is E", "mynameise.com", [["www.mynameise.com/{username}", "None", "Profile", "h"], ["mynameise.com/{username}", "None", "Profile", "h"], ["mynameise.com/{username}", "XFN", "Services", "h"]]], ["MyOpenid", "myopenid.com", [["{username}.myopenid.com/", "None", "None", "h"]]], ["MySpace", "myspace.com", [["myspace.com/{username)", "hCard", "Profile", "h"], ["www.myspace.com/{username)", "hCard", "Profile", "h"]]], ["Netvibes", "netvibes.com", [["www.netvibes.com/{username)", "hCard", "Profile", "h"], ["www.netvibes.com/{username)/activities?format=atom", "Atom", "Activity", "a"]]], ["Newsvine", "newsvine.com", [["{username}.newsvine.com/", "None", "None", "h"]]], ["Odeo", "odeo.com", [["odeo.com/users/{username}", "None", "None", "h"]]], ["Orkut", "orkut.com", [["www.orkut.com/Profile.aspx?uid={userid}", "None", "None", "h"]]], ["Picasa", "picasaweb.google.com", [["picasaweb.google.com/{username}", "None", "Profile", "h"], ["picasaweb.google.com/data/feed/base/user/{username}?alt=rss&kind=album&hl=en_US&access=public", "Rss", "Images", "r"]]], ["Plaxo", "plaxo.com", [["{username}.myplaxo.com/", "hCard", "Profile", "h"]]], ["Plazes", "plazes.com", [["plazes.com/whereis/{username}", "hCard", "Profile", "h"], ["plazes.com/whereis/{username}", "hCalendar", "Events", "h"]]], ["Plurk", "plurk.com", [["www.plurk.com/{username}", "None", "Profile", "h"], ["www.plurk.com/{username}.xml", "Atom", "Events", "a"]]], ["Profilactic", "profilactic.com", [["www.profilactic.com/profile/{username}", "None", "Profile", "h"]]], ["Readernaut", "readernaut.com", [["readernaut.com/{username}", "None", "Profile", "h"], ["readernaut.com/feeds/rss/{username}", "Rss", "Activity", "r"]]], ["Seesmic", "seesmic.com", [["new.seesmic.com/{username}", "hCard", "Profile", "h"], ["feeds.seesmic.com/user.{username}.atom", "Atom", "Video", "a"]]], ["Slideshare", "slideshare.net", [["www.slideshare.net/rss/user/{username}", "Rss", "Slides", "r"], ["www.slideshare.net/{username}", "hCard", "Profile", "h"], ["slideshare.net/{username}", "None", "Profile", "h"], ["www.slideshare.net/{username}/followers/{pagenumber}", "hCard", "Friends", "h"]]], ["Soup.io", "soup.io", [["{username}.soup.io/", "hCard", "Profile", "h"], ["{username}.soup.io/", "XFN", "Services", "h"], ["{username}.soup.io/rss", "Rss", "Lifestream", "r"]]], ["Smugmug", "smugmug.com", [["{username}.smugmug.com/", "None", "Profile", "h"], ["{username}.smugmug.com/hack/feed.mg?Type=nickname&Data={username}&format=atom10", "Atom", "Photos", "a"]]], ["Stumbleupon", "stumbleupon.com", [["www.stumbleupon.com/stumbler/{username}", "None", "Profile", "h"], ["rss.stumbleupon.com/user/{username}/favorites", "Rss", "Bookmarks", "r"]]], ["Technorati", "technorati.com", [["technorati.com/people/technorati/{username}", "hCard", "Profile", "h"]]], ["Threadless", "threadless.com", []], ["Times People", "timespeople.nytimes.com", [["timespeople.nytimes.com/view/user/{username}/", "None", "Profile", "h"], ["timespeople.nytimes.com/view/user/{username}/rss.xml", "Rss", "Activity", "r"]]], ["Tumblr", "tumblr.com", [["{username}.tumblr.com/", "None", "None", "h"], ["{username}.tumblr.com/rss", "Rss", "Lifestream", "r"]]], ["Twitter", "twitter.com", [["twitter.com/{username}", "hCard", "Profile", "h"], ["twitter.com/{username}#people", "XFN-hCard", "Friends", "h"], ["twitter.com/{username}", "hAtom", "Status", "h"]]], ["Twitpic", "twitpic.com", [["www.twitpic.com/photos/{username}", "None", "Profile", "h"], ["twitpic.com/photos/{username}/feed.rss", "Rss", "Photos", "r"]]], ["Upcoming", "upcoming.yahoo.com", [["upcoming.yahoo.com/user/{userid}/", "hCard", "Profile", "h"], ["upcoming.yahoo.com/user/{userid}/", "hCalendar", "Events", "h"], ["upcoming.yahoo.com/user/{userid}/past/", "hCalendar", "Events", "h"], ["upcoming.yahoo.com/syndicate/v2/my_events/{userid}", "Rss", "Events", "r"]]], ["Ustream", "ustream.tv", [["www.ustream.tv/{username}", "None", "Profile", "h"]]], ["Viddler", "viddler.com", [["www.viddler.com/explore/{username}", "None", "Profile", "h"], ["www.viddler.com/explore/{username}/videos/feed/", "Rss", "Video", "r"]]], ["Vimeo", "vimeo.com", [["www.vimeo.com/{username}", "hCard", "Profile", "h"], ["www.vimeo.com/{username}/contacts/sort:newest/page:{pagenumber}", "None", "Friends", "h"], ["vimeo.com/{username}/videos/rss", "Atom", "Video", "a"]]], ["Vox", "vox.com", [["{username}.vimeo.com/profile/", "hCard", "Profile", "h"]]], ["Windows Live", "spaces.live.com", [["{username}.spaces.live.com/", "None", "Profile", "h"]]], ["Wordpress", "wordpress.com", [["{username}.wordpress.com/", "None", "Profile", "h"], ["{username}.wordpress.com/feed/atom/", "Atom", "Lifestream", "a"]]], ["Xing", "xing.com", [["www.xing.com/profile/{username}", "hCard", "Profile", "h"], ["www.xing.com/profile/{username}", "hResume", "Friends", "h"]]], ["Yahoo", "profiles.yahoo.com", [["profiles.yahoo.com/{username}", "hCard", "Profile", "h"]]], ["YIID", "yiid.com", [["{username}.yiid.com/", "hCard", "Profile", "h"], ["{username}.yiid.com/", "rel-tag", "Interests", "h"], ["{username}.yiid.com/contacts/{pagenumber}", "hCard", "Friends", "h"], ["{username}.yiid.com/identities", "XFN", "Services", "h"], ["{username}.yiid.com/cv", "hResume", "Resume", "h"], ["{username}.yiid.com/xml/atom_user", "Atom", "Lifestream", "a"]]], ["Yelp", "yelp.com", []], ["Youtube", "youtube.com", [["gdata.youtube.com/feeds/base/users/{username}/uploads?alt=rss&v=2", "Atom", "Video", "a"], ["youtube.com/rss/user/{username}/videos.rss", "Rss", "Video", "r"], ["youtube.com/user/{username}", "None", "Profile", "h"], ["www.youtube.com/profile?user={username}", "None", "Profile", "h"], ["www.youtube.com/user/{username}", "None", "Profile", "h"]]]];        
    ident._excludeDomains = ["pownce.com","ma.gnolia.com","huff-duff.com","lastfm.com.br","lastfm.com.tr","lastfm.de","lastfm.es","lastfm.fr","lastfm.it","lastfm.jp","lastfm.pl","lastfm.ru","lastfm.se","cn.last.fm","radio.aol.fr"];
    ident._excludeUrls = ["twitter.com/#replies","twitter.com/#inbox","twitter.com/#favorites","twitter.com/following","twitter.com/followers","identi.ca/group","identi.ca/tag","identi.ca/featured","identi.ca/favorited"];
    
    
    // Describes a profile node for identities collection
    ident.profile = function(url,domain){
        this.name = '';
        this.domain = '';
        this.username = new Array();
        this.profileUrl = domain;
        this.iconUrl = '';
        this.spriteClass = '';
    };
    
    // Describes a domain node
    ident.domain = function(url,domain){
        this.name = '';
        this.urls = new Array();
        this.domain = domain;
        this.accounts = new Array();
        this.hashCard = false;
        this.hashResume = false;
    };
    
    // Describes a identity node of a domain
    ident.account = function(sgn,verified,profile,resume,ident,pk){
        this.sgn = sgn;
        this.verified = verified;
        this.profile = profile;
        this.resume = resume;
        this.ident = ident;
        this.pk = pk;
    };
    
    // Describes a API call event
    ident.historyItem = function(url,apiurl){
        this.url = url;
        this.apiurl = apiurl;
        this.domain = ''; 
        this.name = '';
        this.contentType = ''; 
        this.schema = ''; 
        this.rawJSON = '';
    }
    
    // Describes a username object
    ident.username = function(){
        this.name = '';
        this.rank = 0;
    }
    
    // The main public function for startings a search
    ident.search = function(url) {
        ident.reset();
          
        var urls = new Array();
        if(url.indexOf(',') > -1)
            urls = url.split(',');
        else
            urls[0] = url;
        
        for(var x = 0; x <= urls.length-1; x++){
            if(x < 49){
            
            	urls[x]
                var item = ident.convertShorthandAddress(urls[x]);
                
                if(ident.isUrl(item) || ident.isEmail(item)){
                    if(ident.isExcludedUrl(item) == false){
                        ident._startUrl += item + ',';
                    }else{
                        ident.error('Sorry web addresses have to represent a person like profile page or a blog i.e. "http://twitter.com/<strong>glennjones</strong>"');
                        ident._startUrl = '';
                        break;
                    }
                }else{
                    ident.error('Sorry there seem to be a problem with the format of the web address you entered: "' + url + '"');
                    ident._startUrl = '';
                    break;
                }
            }  
        }
        
        ident.apiManager();
    }
    
    // Controls identity API request
    ident.apiManager = function(json, historyItem) {
       
       if(ident._startUrl != ''){
       
            if(json != null){
                // Parse return data
                ident.parseSGN(json, historyItem);
                ident.statusUpdateEvent(['data-change']);
            }
            
            // Thrid call
            if(ident._primaryCalled == true && ident._secondaryCalled == true ){
                // If the profile module is present
                // To do - Add friendfeed.com, mybloglog.com and blog if found;
            } 
            
            // Second call - using edgeOut and edgeIn
            if(ident._primaryCalled == true && ident._secondaryCalled == false ){
                // Call if we want to use inward edges
                if( ident.useInwardEdges == true ){
                    ident._secondaryCalled = true;
                    ident.getSocialGraphData(ident._startUrl, 1 ); 
                }
            } 
            
            // First call - using edgeOut
            if(ident._primaryCalled == false){
                ident._primaryCalled = true;
                ident.getSocialGraphData(ident._startUrl, 0 );    
            } 
            
        }else{
            ident.error('Sorry web addresses have to represent a person like profile page or a blog i.e. "http://twitter.com/<strong>glennjones</strong>"');
        }
             
    }
    
    ident.webFingerManager = function(json, historyItem) {
    	ident._apiReturnCount ++;
    	if(json != null){
    		historyItem.rawJSON = json;
    		if(json[0].links){
	    		for(var x = 0; x <= json[0].links.length-1; x++){
					if(json[0].links[x].rel == "http://microformats.org/profile/hcard" || json[0].links[x].rel == "http://webfinger.net/rel/profile-page"){
						ident._startUrl = json[0].links[x].href;
						ident.apiManager();
						break;
					}
				}
	    	}
    	}
    }
    
    // Resets properties and page elements so they can be reused
    ident.reset = function(){
        ident.domains = new Array();
        ident.history = new Array();
        ident.profiles = new Array();
        ident._startUrl = '';
        ident._apiReturnCount = 0;
        ident._primaryCalled = false; 
        ident._secondaryCalled = false; 
        ident._usernames =  new Array();
        ident.resetTrigger();
    }
    
    
    // Assigns the best parser to use
    ident.registerParser = function(parser){
        if( (parser.parseUf > 0 && ident.ufParser == null) || ( ident.ufParser != null && parser.parseUf > ident.ufParser.parseUf  ))
            ident.ufParser = parser;
            
        if( (parser.parseRss > 0 && ident.rssParser == null ) || ( ident.rssParser != null && parser.parseRss > ident.rssParser.parseRss  ))
            ident.rssParser = parser;
            
        if( (parser.parseAtom > 0 && ident.atomParser == null ) || ( ident.atomParser != null && parser.parseAtom > ident.atomParser.parseAtom  ))
            ident.atomParser = parser; 
          
    }
    
    

    // Fires request to Google Social Graph API for data in JSON format
    ident.getSocialGraphData = function(url, edgeIn ){
            
         // Remove options - only inward bound edges - update code
         var apiurl = "http://socialgraph.apis.google.com/lookup?q=" + encodeURIComponent(url) + "&fme=1&edo=1&edi=" + edgeIn + "&sgn=1&pretty=1&jme=1"; 
            
         var historyItem = new ident.historyItem(url,apiurl);
         historyItem.apiName = 'googlesoicalgraph'; 
         ident.history[ident.history.length] = historyItem;

         ident.GoogleGraphAPICall( apiurl, historyItem );
    };

    

    // Parses the returned JSON data from Google Social Graph API
    ident.parseSGN = function(json, historyItem) {

        // Record the returned API call
        ident._apiReturnCount ++;

        if(json != null)
        {
           historyItem.rawJSON = json;
           
           var queryUrl = ''; 
           for(var item in json.canonical_mapping)
                queryUrl = item; // Canonical url
                
            //First - Load all the sgn nodes 
            for(var item in json.nodes){
                if(item.indexOf('sgn://') > -1){
                    var node = json.nodes[item];
                    var profileUrl = '';
                    var nodeUrl = '';
          
                    if(node['attributes']['profile'] != null)
                        profileUrl = node['attributes']['profile'];
                        
                    if(node['attributes']['url'] != null)
                        nodeUrl = node['attributes']['url'];
                
                    ident.appendDomainNode(item,nodeUrl,true,profileUrl);
                    ident.processClaimedNodes(node);
                }
            }
            
            //Second - Load all non sgn nodes
            for(var item in json.nodes){
                if(item.indexOf('http://') > -1){
                    var node = json.nodes[item];
                    ident.appendDomainNode('',item,false,'');
                    ident.processClaimedNodes(node);
                } 
            }
        }
        
        ident.postProcessDomainNode();
       
    };
    
    
    ident.processClaimedNodes = function(node){
    
        if(node["claimed_nodes"] != null){
            // Load sgn's first
            for(var x = 0; x <= node["claimed_nodes"].length-1; x++){
                var tempNode = node["claimed_nodes"][x];
                if(tempNode.indexOf('sgn://') > -1){
                    ident.appendDomainNode(tempNode,'',true,'');
                }
            }
            // Load http's second
            for(var x = 0; x <= node["claimed_nodes"].length-1; x++){
                var tempNode = node["claimed_nodes"][x];
                if(tempNode.indexOf('http://') > -1){
                    ident.appendDomainNode('',tempNode,true,'');
                }
            } 
        }
        
        // Finds unverified claimed nodes when your check in and out edges
        if(node["unverified_claiming_nodes"] != null){
            // Load sgn's first
            for(var x = 0; x <= node["unverified_claiming_nodes"].length-1; x++){
                var tempNode = node["unverified_claiming_nodes"][x];
                if(tempNode.indexOf('sgn://') > -1){
                    ident.appendDomainNode(tempNode,'',false,'');
                }
            }
            // Load http's second
            for(var x = 0; x <= node["unverified_claiming_nodes"].length-1; x++){
                var tempNode = node["unverified_claiming_nodes"][x];
                if(tempNode.indexOf('http://') > -1){
                    ident.appendDomainNode('',tempNode,false,'');
                }
            }
        }
    
    }
    
    
    // Post processes any domain to find addition hits
    ident.postProcessDomainNode = function(sgn, uri, verified, profile) {
        
        // Loop all the found domains and call the append custom data method
        for (var i = 0; i < ident.domains.length; i++){
            ident.appendCustomSGNData(ident.domains[i]);
        }
        ident.disambiguateNodes();
        
        // Sort the collection of domains into order
        ident.domains.sort(ident.sortByName);
        
        ident.buildIdentitiesCollection();
        
        // After all processing trigger custom update event 
        ident.statusUpdateEvent(['data-change']);  
    };
    
    
    // Post processes any domain to find addition hits
    ident.buildIdentitiesCollection = function() {
          
        ident.identities = new Array(); 
        ident.disambiguateNodes();
            
        // Display top URL if its not in social media sites - often blog 
        if(ident.addPrimaryURL){
            
            var topDeclaredUrl = ''; 
            // Function comes from profile parsing plug-in
            if(ident.topDeclaredProfileUrl())
                topDeclaredUrl = ident.topDeclaredProfileUrl();
                
            if(topDeclaredUrl != ''){
                var topDeclaredDomain = ident.parseDomainFromURL( topDeclaredUrl );
                var found = false;
                // Check its not a known soical media site
                for (var y = 0; y < ident._endPoints.sites.length; y++) {
                    if(ident.compareRootDomains(topDeclaredDomain,ident._endPoints.sites[y].domain))
                        found = true;
                }
                if(!found){
                    var profile = new ident.profile();
                    profile.name = '';
                    profile.domain = topDeclaredDomain; 
                    profile.iconUrl = ident.iconPath + 'website.png'; 
                    profile.spriteClass = "icon-website"; 
                    profile.profileUrl = topDeclaredUrl; 
                    ident.identities[ident.identities.length] = profile; 
                }  
            }
        }
            
        // Loop for profiles
        for (var x = 0; x < ident.domains.length; x++) {
            // If we have a named social media site list it
            if( ident.domains[x].name ){ 
               
               // Sort accounts so that ident or before pk
               	ident.domains[x].accounts.sort(ident.sortBySGN);
               	
                for (var y = 0; y < ident.domains[x].accounts.length; y++) {
                   var profile = new ident.profile();
               
                   // Find username/id
                   profile.username = ident.domains[x].accounts[y].ident;
                   if( ident.domains[x].accounts[y].ident == '')
                       profile.username = ident.domains[x].accounts[y].pk;
                       
                   profile.name = ident.domains[x].name;
                   profile.domain = ident.domains[x].domain; 
                   profile.iconUrl = ident.iconPath + ident.domains[x].name.replace(/[\-,., ]/g,'').toLowerCase() + '.png';
                   profile.spriteClass = "icon-" + ident.domains[x].name.replace(/[\-,., ]/g,'').toLowerCase();  
                   
                   if(ident.domains[x].accounts[y].profile != '' ){
                        profile.profileUrl = ident.domains[x].accounts[y].profile;
                   }else{
                        // If we have no profile link find any url containing correct username
                        if(ident.domains[x].urls)
                            profile.profileUrl = ident.findUserNameBasedURL(ident.domains[x].urls,profile.username)
                   }
                   
					// Only take first account  
                   if(profile.profileUrl != '' && profile.username != ''){
                        ident.identities[ident.identities.length] = profile;
                        break;
                   }
               }
            }
        } 
    };
    
    
    // Appends a new domain or/and identity node to collection
    ident.appendDomainNode = function(sgn, uri, verified, profile) {
        var domain = '';
        
        // Get the domain
        if(uri.indexOf('http://') == 0)
            domain = ident.parseDomainFromURL(uri);
       
        if(sgn != '')
            if(sgn.indexOf('sgn://') == 0)
                domain = ident.parseDomainFromSGN(sgn);     
            
               
        if(domain.length > 0)
        {   
            // Have we already got an object for this domain
            found = null;
            for (var i = 0; i < ident.domains.length; i++) {
                if (ident.compareRootDomains(domain, ident.domains[i].domain)) {
                    found = ident.domains[i];
                    break;
                }
            }
            
            // Don't use any domain on the exclude list
            var excludeIt = ident.domainIsExcluded(domain);
            
            // Exclude if its mail info
            if(domain == 'mboxsha1')
                excludeIt = true;
            
            if( excludeIt == false)
            {
                if(found == null){
                    // Create a new domain node
                    var newDomain = new ident.domain('','');
                    newDomain.domain = domain.replace('www.','');
                    ident.domains[ident.domains.length] = newDomain;
                    found = newDomain;
                }
                
                // Append url to the domain array of urls
                if(uri != '')
                    ident.appendUrl(found.urls,uri);

                
                if( sgn != ''){
  
                    // Append identity node
                    var identity = new ident.account('','','','','',''); 
                    identity.verified = verified;
                    identity.profile = profile;
                    identity.sgn = sgn;
                    
                    // Find ident and pk from sgn
                    if(identity.sgn != ''){
                        var parts = new Array();
                        if(identity.sgn.indexOf('/?ident=') > -1){
                            parts = identity.sgn.split('/?ident=');
                            if(parts.length == 2){
                                ident.appendUsername(parts[1]);
                                identity.ident = parts[1];
                            } 
                        }
                        
                        if(identity.sgn.indexOf('/?pk=') > -1){
                           parts = identity.sgn.split('/?pk=');
                           if(parts.length == 2)
                                identity.pk = parts[1]; 
                       }
                     }
                     
                     ident.appendUniqueIdentityNode(found,identity);
                 }       
            }  
        }  
    };
    
    // Find and resolve issue of disambiguity in identity nodes
    ident.disambiguateNodes = function(){
    
        for (var i = 0; i < ident.domains.length; i++) {
            // If we have more then one identity node
            if(ident.domains[i].accounts.length > 1){
                var userBaseNodeCount = 0;
                // Count different _usernames
                for(var z = 0; z <= ident.domains[i].accounts.length-1; z++){
                    if(ident.domains[i].accounts[z].ident != '')
                        userBaseNodeCount ++;
                }
                // If we have more than one username based identity node
                if( userBaseNodeCount > 1){
                    var tempArray = new Array();
                    var topName = ident.topUsername();
                    for(var z = 0; z <= ident.domains[i].accounts.length-1; z++){
                        // Add the username node which matches the most common username
                        if(ident.domains[i].accounts[z].ident == topName )
                            tempArray[tempArray.length] = ident.domains[i].accounts[z];
                        // Add all id based nodes
                        if(ident.domains[i].accounts[z].pk != '' )
                            tempArray[tempArray.length] = ident.domains[i].accounts[z];
                    }
                    ident.domains[i].accounts = tempArray;   
                }
            }
        }
    }
    
    // Search through an array of URLs for the first one containing the username
    ident.findUserNameBasedURL = function(urls, username){
        for (var i = 0; i < urls.length; i++) {
            if(urls[i].indexOf(username) > -1){
                return urls[i];
            }
        }
        return '';
    };
    
    
    // Does domains array contain a given domain object
    ident.domainNodeContains = function(domain){
        found = false;
        for (var i = 0; i < ident.domains.length; i++) {
            if(ident.compareRootDomains(domain, ident.domains[i].domain)){
                found = true;
                break;
            }
        }
        return found;
    }
    
    // Finds out if domain is on the exclude list
    ident.domainIsExcluded = function(domain){
        var excludeIt = false;
        for (var i = 0; i < ident._excludeDomains.length; i++) {
            if (ident.compareRootDomains(domain, ident._excludeDomains[i])) {
                excludeIt = true;
                break;
            }
        }
        return excludeIt;
    }
    
    
    // Checks to see if we have already made a API call
    ident.hasAPIBeenCalled = function(url, schema, apiurl){
        var found = false;
        for (var i = 0; i < ident.history.length; i++) {
            if(apiurl != '')
                if(ident.history[i].apiurl == apiurl)
                    found = true;
            if(url != '' && schema != '' && ident.history[i].schema != '')
                if(ident.history[i].url == url && ident.history[i].schema.indexOf(schema) > -1 )
                    found = true;
        }
        return found;
    };
    
    
    // Sorts objects into order using the name property
    ident.sortByName = function(a, b) {
        var x = a.name.toLowerCase();
        var y = b.name.toLowerCase();
        return ((x < y) ? -1 : ((x > y) ? 1 : 0));
    };
    
    // Sorts objects into order using the domain property
    ident.sortByDomain = function(a, b) {
        var x = a.domain.toLowerCase();
        var y = b.domain.toLowerCase();
        return ((x < y) ? -1 : ((x > y) ? 1 : 0));
    };
    
    // Sorts objects into order using the sgn property
    ident.sortBySGN = function(a, b) {
        var x = a.sgn.toLowerCase();
        var y = b.sgn.toLowerCase();
        return ((x < y) ? -1 : ((x > y) ? 1 : 0));
    };

    
    
    // Parse the username or userid from SGN
    ident.parseUserFromSGN = function(siteNode) {
        var sgn = siteNode.sgn.substring(6,siteNode.sgn.length);
        parts = sgn.split('?');
    
        if(parts[1].indexOf('ident=') > -1){
            siteNode.username =  parts[1].replace('ident=','');
        }
        else{
            siteNode.userid =  parts[1].replace('pk=','');
        }
    };
    
    
    // Append url to collection
    ident.appendUrl = function(urls,url) {    
        var found = false;
        for(var x = 0; x <= urls.length-1; x++){
            if(urls[x] == url){
                found = true;
                break
            }
        }
        if(found == false)
            urls[urls.length] = url;
    };
    
    
    // Append username to collection or up ranking if it exisits
    ident.appendUsername = function(username) {    
        var found = false;
        for(var x = 0; x <= ident._usernames.length-1; x++){
            if(ident._usernames[x].name == username){
                
                found = true;
                ident._usernames[x].rank ++;
                break
            }
        }
        if(found == false)
        {
            var user = new ident.username();
            user.name = username;
            ident._usernames[ident._usernames.length] = user;
        }
    };
    
    
    // Find custom SGN data and append it to collection
    ident.appendCustomSGNData = function(domain) {    
 
        for(var x = 0; x <= ident._endPoints.sites.length-1; x++){
            var testdomain = ident._endPoints.sites[x].domain.replace(' ', '');
             
            if(ident.compareRootDomains(domain.domain,testdomain) ){
                domain.name = ident._endPoints.sites[x].name;
                ident.createCustomSGN(domain, ident._endPoints.sites[x]);
            }
        }
    };
                

    
    // Given a site description from the custom SGN data 
    // Append extra data into collection 
    ident.createCustomSGN = function(domain, siteDescription) {
        
        // Append all the url mapping for this domain
        domain.urlmappings = siteDescription.urlmappings;
      
        // Loop the found urls for this domain and find new sgn's;
        for(var z = 0; z <= domain.urls.length-1; z++){
            
             var url = domain.urls[z];
            
             // Loop all the urlmappings for site description
             for(var y = 0; y <= siteDescription.urlmappings.length-1; y++){
                
                var urlmapping = siteDescription.urlmappings[y];
                var urltemplate = urlmapping.urltemplate;
                
                // The urltemplate contains a username or userid parse it
                if (urltemplate != "" && (urltemplate.indexOf("{username}") > -1 || urltemplate.indexOf("{userid}") > -1)) {
                    // Find the char number where the username/userid starts
                    var start = 0;
                    if( urltemplate.indexOf("{username}") > -1 )
                        start = urltemplate.indexOf("{username}");

                    if (urltemplate.indexOf("{userid}") > -1)
                        start = urltemplate.indexOf("{userid}");
                     
                    var parts = new Array(2); 
                     
                    if (start != 0){
                        parts[0] = urltemplate.toLowerCase().substring(0, start);
                        if (urltemplate.indexOf("{username}"))
                            parts[1] = urltemplate.toLowerCase().substring(start + 10);
                        else
                            parts[1] = urltemplate.toLowerCase().substring(start + 8); 
                    }            
        
                    startMatch = false;
                    endMatch = false;
                    user = url;

                    // Romove unneeded front section of url
                    if (url.indexOf(parts[0]) == 0){
                        startMatch = true;
                        part = parts[0];
                        user = user.substring(part.length, user.length);
                    }
                    
                    // Romove end element
                    if (parts.length == 2){
                        if (parts[1].length > 0){
                            if (ident.endsWith(url,parts[1]) ){
                                endMatch = true;
                                user = user.replace(parts[1], "");
                            }
                            else if (ident.endsWith(url,parts[1] + "/"))
                            {
                                endMatch = true;
                                user = user.replace(parts[1] + "/", "");
                            }
                        }
                        else
                        {
                            endMatch = true;
                        }
                    }
                    
                    // Romove any trailing /
                    if (ident.endsWith(user,"/"))
                        user = user.substring(0, user.length - 1);

                    // If the user contain anymore /
                    if (user.indexOf("/") > -1)
                        endMatch = false;

                    // Remove any querystring additions
                    if (user.indexOf("?") > -1){
                        userParts = user.split('?');
                        user = userParts[0];
                    }
                    
                    // Remove any name additions
                    if (user.indexOf("#") > -1){
                        userParts = user.split('#');
                        user = userParts[0];
                    }
                    
                    if (startMatch && endMatch){
                    
                        var identity = new ident.account('','','','','',''); 
                        identity.verified = false;
                        identity.profile = '';
                           
                        if (urlmapping.urltemplate.indexOf("{username}") > -1){
                            identity.ident = user;
                            ident.appendUsername(user);
                            identity.sgn = "sgn://" + domain.domain + "/?ident=" + user;
                        }

                        if (urlmapping.urltemplate.indexOf("{userid}") > -1){
                            identity.pk = user;
                            identity.sgn = "sgn://" + domain.domain + "/?pk=" + user;
                        }
                        
                        ident.appendProfileData(siteDescription.urlmappings, identity, url, domain);
                        
                        if(ident.domainIsExcluded( domain.domain ) == false)
                            ident.appendUniqueIdentityNode(domain,identity);
                        
                     }                       
                } 
            }
        }  
        
        // Loop all identity nodes to find addional sgn's information 
        for(var z = 0; z <= domain.accounts.length-1; z++){
            ident.appendProfileData(siteDescription.urlmappings,domain.accounts[z], '', domain);
        }
          
    } 
    
    // Looks at current identity nodes and work weather a new one needs appending
    ident.appendUniqueIdentityNode = function(domain,identity)
    {
        var found = null;
        
        // Find any node with sgn
        for(var y = 0; y <= domain.accounts.length-1; y++){
            if(domain.accounts[y].sgn == identity.sgn){
                found = domain.accounts[y];
                break;
            }
        }
             
        if(found == null)
            domain.accounts[domain.accounts.length] = identity;
             
    }
    
    
    // Adds a profile and resume mapping date to identity
    // Pre processed for fast excution for identity and profiles 
    ident.appendProfileData = function(urlmappings, identity, url, domain) {
        
           identity.profile = ident.getAPIEndPoint('Profile','hCard',urlmappings, identity);
           identity.resume = ident.getAPIEndPoint('Resume','hResume',urlmappings, identity);
           
           if(identity.profile != '')
                domain.hashCard = true;
                
           if(identity.resume != '')
                domain.hashResume = true;
    }
    
    
    ident.getAPIEndPoint = function(type, schema, urlmappings, identity, page) {
         var url = '';
         if(urlmappings != undefined){
             if(urlmappings.length){
                 for(var y = 0; y <= urlmappings.length-1; y++){
                    var urlmapping = urlmappings[y];

                    if( urlmapping.contenttype == type && urlmapping.schema == schema ){
                        var found = false;
                        url = urlmapping.urltemplate;
                         
                        if(identity.ident != '' && url.indexOf('{username}') > -1){
                            url = url.replace('{username}',identity.ident);
                            found = true; 
                        }
            
                        if(identity.pk != '' && url.indexOf('{userid}') > -1){
                            url = url.replace('{userid}',identity.pk);
                            found = true; 
                        }

                        // Add page number    
                        if(page != undefined)
                            url = url.replace('{pagenumber}',page);
                            
                        if(!found)
                            url = '';      
               
                    }
                    
                    if(url != '')
                        break;
                }
            }
        }
        return url;
    }
    
    
    
    // Finds the top username by rank
    ident.topUsername = function(){
        var top = new ident.username();
        for(var x = 0; x <= ident._usernames.length-1; x++){
            if(ident._usernames[x].rank > top.rank)
                top = ident._usernames[x];
        }
        return top.name;
    }
 
    // Have all the API calls returned 
    ident.isSearching = function(){
        if(ident._apiReturnCount >= ident.history.length){
            return false;
        }else{
            return true;
        }
    }
    
    // Add top level domain pages to excluded urls list
    ident.buildExcludeUrlList = function(){
        for(var x = 0; x <= ident._endPoints.sites.length-1; x++){
            ident._excludeUrls[ident._excludeUrls.length] = ident._endPoints.sites[x].domain; 
        }
    }
    ident.buildExcludeUrlList();
    
    // Decompresses compact array version into objects
    ident.buildEndPointList = function(){
        var sites = new Array();
        for(var x = 0; x <= ident._endPointsArray.length-1; x++){
            var site = new Object();
            site.name = ident._endPointsArray[x][0];
            site.domain = ident._endPointsArray[x][1];
            
            // Temp fix for googles profile domain issue
            if(site.name == "Google")
        		site.domain = "google.com|profiles";

            site.urlmappings = new Array();
            for(var i = 0; i <= ident._endPointsArray[x][2].length-1; i++){
                var mapping = new Object();
                mapping.urltemplate = ident._endPointsArray[x][2][i][0];
                mapping.schema = ident._endPointsArray[x][2][i][1];
                mapping.contenttype = ident._endPointsArray[x][2][i][2];
                mapping.mediatype = ident._endPointsArray[x][2][i][3];
                site.urlmappings[site.urlmappings.length] = mapping;
                
                if(mapping.urltemplate.indexOf('//') == -1)
                    mapping.urltemplate = "http://" + mapping.urltemplate;
                    
                switch(mapping.mediatype){
                    case "h":
                      mapping.mediatype = "Html"
                      break;
                    case "r":
                      mapping.mediatype = "Rss"
                      break;
                    case "a":
                      mapping.mediatype = "Atom"
                      break
                }     
            }
            sites[sites.length] = site;
        }
        ident._endPoints = {'sites': sites };
    }
    ident.buildEndPointList();
    
    
    ident.isExcludedUrl = function(url){
        for(var x = 0; x <= ident._excludeUrls.length-1; x++){
            if(ident.compareUrl(url, 'http://' + ident._excludeUrls[x]))
                return true;
        }
        return false;
    }
    
    // Finds shorthand address
    ident.convertShorthandAddress = function(url){
        var foundUrl = '';
        
        if(url != ''){
            url = url.replace('acct:','');
            url = ident.trim(url,' ');
            var parts = new Array();
            
            // format: glennjones@twitter.com i.e. WebFinger style
            if(ident.isEmail(url)){ 
            	// Look for webfinger
            	url = ident.trim(url);
		         var apiurl = "http://webfingerclient-dclinton.appspot.com/lookup?identifier=" + encodeURIComponent(url) + "&format=json&pretty=true";   
		         var historyItem = new ident.historyItem(url,apiurl);
		         historyItem.apiName = 'webfinger'; 
		         ident.history[ident.history.length] = historyItem;
		         ident.WebFingerAPICall( apiurl, historyItem );

 
               // parts = url.split('@');
               // parts = [parts[1],parts[0]]
            }
            
            // format: twitter.com/glennjones or twitter/glennjones
            if(url.match(/\//g) != null ){  
                if(url.match(/\//g).length == 1 ){  
                    parts = url.split('\\');
                }
            }
            
            // format: twitter.com glennjones or twitter glennjones
            if(url.indexOf(' ') > -1){ 
                parts = url.split(' ');
            } 
            
            // format: twitter.com glennjones or twitter glennjones
            if(parts.length == 2){   
                var identity = new Object();
                var domainPart = ident.trim(parts[0].toLowerCase(),' ');
                var username = ident.trim(parts[1].toLowerCase(),' ');
                identity.ident = username;
                identity.pk = username;
                for(var x = 0; x <= ident._endPoints.sites.length-1; x++){
                    if(domainPart == ident._endPoints.sites[x].domain){
                       foundUrl = ident.getAPIEndPoint('Profile','hCard',ident._endPoints.sites[x].urlmappings, identity);
                       if(foundUrl == '')
                            foundUrl = ident.getAPIEndPoint('Profile','None',ident._endPoints.sites[x].urlmappings, identity);
                            
                    }

                    if(domainPart == ident._endPoints.sites[x].name.toLowerCase().replace(/\s/g, '')){
                       if(foundUrl == '')
                            foundUrl = ident.getAPIEndPoint('Profile','hCard',ident._endPoints.sites[x].urlmappings, identity);
                                if(foundUrl == '')
                                     foundUrl = ident.getAPIEndPoint('Profile','None',ident._endPoints.sites[x].urlmappings, identity);
                    }
                    
                    if(foundUrl != '')
                       break;
                }
            }
            if(foundUrl != '')
                url = foundUrl;
        }
        
        return url;
    }
 
 
    // Utility functions
    // ----------------------------------------------------
 
 
    // Compares a full domain from url to a root domain
    // ie www.twitter.com to twitter.com = true
    ident.compareRootDomains = function(fullDomain, rootDomain ) {
        var same = false;
        if(fullDomain != '' || rootDomain != ''){
            //Remove common subdomain
            fullDomain = fullDomain.toLowerCase().replace('www.','');
            // Look for full match
            if(fullDomain == rootDomain){
                same = true;
            }
        }
        return same;
    };
    
    

    
    
    // Compares urls for match
    // ie www.twitter.com/glennjones = twitter.com/GlennJones/ 
    ident.compareUrl = function(urlA, urlB) {
        var same = false;
        
        // Remove url fragments
        if( urlA.indexOf('#') > -1)
            urlA = urlA.split('#')[0];
       
        if( urlB.indexOf('#') > -1)
            urlB = urlB.split('#')[0];
        
        if(urlA != '' || urlB != ''){
            //Remove common subdomain
            urlA = urlA.toLowerCase().replace('www.','');
            urlB = urlB.toLowerCase().replace('www.','');
            
            // Make sure anything ends with / 
            if( ident.endsWith(urlA,'/') == false)
                urlA = urlA + '/';
                
            if( ident.endsWith(urlB,'/') == false)
                urlB = urlB + '/';    
                
            // Look for full match
            if(urlA.toLowerCase() == urlB.toLowerCase())
                same = true;
           
        }
        return same;
    };
 
     // Parses the domain name from a given URL
    ident.parseDomainFromURL = function(url) {
        var domain = "";
        if(url != undefined && url != '')
        {
            if (url.indexOf("//") > 0 ){ 
                var parts = url.split("/");
                domain = parts[2];
            }
        }
        return domain;
    };
    
    // Parses the domain name from a given SGN
    // Structure of sgn - sgn://twitter.com/?pk=12497 or sgn://twitter.com/?ident=glennjones
    ident.parseDomainFromSGN = function(sgn) {
        var domain = "";
        // Temp fix for googles profile domain issue
        sgn = sgn.replace("profiles.google.com","google.com|profiles");
        sgn = sgn.substring(6,sgn.length);
        var parts = sgn.split('/');
        if(parts[0].length > -1)
            domain = parts[0];
        return domain;
    };
    
 
    // Very simple endsWith function. Use with care
    ident.endsWith = function(str,test)
    {
        var lastIndex = str.lastIndexOf(test);
        return (lastIndex != -1) && (lastIndex + test.length == str.length);
    }
    
    
    // Returns true/false if obj is a object
    ident.isObject =  function(obj) {
        return (typeof obj == "object");
    };
    
    // Returns true/false if obj is a array
    ident.isArray = function(obj) {
       if (obj.constructor.toString().indexOf("Array") == -1)
          return false;
       else
          return true;
    };
    
    // Returns true/false if obj is a string
    ident.isString = function(obj) {
        return typeof obj == 'string';
    };
    
    // Returns true/false if a string is in an array
    ident.contains = function (array, string) {
        var found = false;
        for (var i = 0; i < array.length; i++) {
            if (array[i] == string) {
                found = true;
                break;
            }
        }
        return found;
    };
    
    ident.isUrl = function(string) {
	    var regexp = /(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/
	    return regexp.test(string);
	 };
	 
	ident.isEmail = function(string) {
	    var regexp = /^.+\@.+\..+$/
	    return regexp.test(string);
	 };

	 
 
    // Returns a string value what every is paased
    ident.tidyString = function(str){
        var output = "";
        if(ident.isString(str)){
            if(str != undefined){
                if(str != null){
                    output = ident.trim( str )
                }else{
                    output = '';
                }
            }else{
               output = '';
            }
        }
        return output;
    };
    
    
    ident.trim = function(str, chars) {
        if(str != '' && chars != '')
	        return ident.ltrim(ident.rtrim(str, chars), chars);
	    else
	        return '';
    };
 
    ident.ltrim = function(str, chars) {
	    chars = chars || "\\s";
	    return str.replace(new RegExp("^[" + chars + "]+", "g"), "");
    };
 
    ident.rtrim = function(str, chars) {
	    chars = chars || "\\s";
	    return str.replace(new RegExp("[" + chars + "]+$", "g"), "");
    };
    
    // Checks string is Null or Empty
    ident.isNullorEmpty = function(string){
        if (string == null || string == undefined || string == '' )
            return true
        else
            return false
    };
    
     
    // A helper function to finds a value of a given JSON property
    ident.getNodeVaue = function( test, obj ) {
        // Gets a value from a JSON object
        // vcard[0].url[0]
        var output = null;
        try{
            var currentOject = obj;
            var arrayDots = test.split(".");
            for (var i = 0; i < arrayDots.length; i++) {
                if( arrayDots[i].indexOf('[') > -1 )
                {
                    var arrayAB = arrayDots[i].split("[");
                    var arrayName = arrayAB[0];
                    var arrayPosition = Number( arrayAB[1].substring(0,arrayAB[1].length-1) );
		            
		            if( currentOject[arrayName] != null || currentOject[arrayName] != 'undefined' ) {
		                if( currentOject[arrayName][arrayPosition] != null || currentOject[arrayName][arrayPosition] != 'undefined' )
                   	        currentOject = currentOject[arrayName][arrayPosition];
                   	           
                    }
                    else {
                        currentObject = null; 
                    }    
                }
                else
                {
	                if( currentOject[arrayDots[i]] != null || currentOject[arrayDots[i]] != 'undefined'   )
                	    currentOject = currentOject[arrayDots[i]];    
                }
            }
            output = currentOject;
        }catch(err){
            output = null;
        }
        return output;
    }
    





    // jQuery functions
    // ------------------------------------------------------
    
    ident.GoogleGraphAPICall = function( apiurl, historyItem ){
        jQuery.getJSON(apiurl + "&callback=?", function(json){
            ident.apiManager( json, historyItem );
        });
    }
    
    ident.WebFingerAPICall = function( apiurl, historyItem ){
        jQuery.getJSON(apiurl + "&callback=?", function(json){
            ident.webFingerManager( json, historyItem );
        });
    }


    
    ident.resetTrigger = function(){
        jQuery(document).trigger('ident:reset');
    }

    ident.statusUpdateEvent = function(){
        if(arguments.length > -1)
            jQuery(document).trigger('ident:update', arguments[0]);
        else
            jQuery(document).trigger('ident:update');
    }
    
    ident.error = function(){
        if(arguments.length > -1)
            jQuery(document).trigger('ident:error', arguments[0]);
        else
            jQuery(document).trigger('ident:error');
            
        ident.reset();     
    }
    
    
   