/**
 * Retrieve cookie information for the current URL
 * @type cookieMonster_CookieInfo
 */
cookieMonsterBys1tony.cookieInfo =
{
    choice: null,
    _bundle: null,
    _isExactPerm: false,
    _isEffectiveTLDService: false,
    _tempAllowList: null,
    _globalOverrideList: null,
    _nsICookiePermission: Components.interfaces.nsICookiePermission,
    _nsiPermissionManager: Components.interfaces.nsIPermissionManager,
    _cm: cookieMonsterBys1tony,

    init: function()
    {
        // Declare instance of cookie permission and
        // query an nsICookiePermission interface
        this.choice = Components.classes["@mozilla.org/cookie/permission;1"].createInstance();
        this.choice.QueryInterface(this._nsICookiePermission);

        this._bundle = document.getElementById("cookiemonster-s1tony-menu-labels");
        
        // Check if the method testExactPermission is available
        // in the version of the Moz engine being used
        // Note:  Currently, testExactPermission is not available
        // in Moz 1.8 (FF2), but is available in Moz 1.9 (FF3)
        var accessString = CM_COOKIE_ACCESS_DEFAULT;
        var permissionManager = Components.classes["@mozilla.org/permissionmanager;1"]
            .getService(this._nsiPermissionManager);

        if (permissionManager.testExactPermission)
        {
        	this._isExactPerm = true;
        }
 
        // Check if the service nsIEffectiveTLDService is available
        // in the version of the Moz engine being used
        // Note:  Currently, testExactPermission is not available
        // in Moz 1.8 (FF2), but is available in Moz 1.9 (FF3)
        if (Components.classes["@mozilla.org/network/effective-tld-service;1"])
        {
        	this._isEffectiveTLDService = true;
        }
        
		// Initialize TempAllow
        this._cm.tempAllow.init();
		
        // Check if CM_PREFERENCE_TYPE_GLOBAL_OVERRIDE contains
        // any URLs and if so, add to _globalOverrideList
        this._globalOverrideList = this._cm.nsPreferences.getStringPrefArray(CM_PREFERENCE_TYPE_GLOBAL_OVERRIDE);
    },

    isExactPermissions: function()
    {
    	return this._isExactPerm;
    },

    getGlobalOverrideList: function()
    {
    	return this._globalOverrideList;
    },

    setGlobalOverrideList: function()
    {
        this._globalOverrideList = this._cm.nsPreferences.getStringPrefArray(CM_PREFERENCE_TYPE_GLOBAL_OVERRIDE);
    },
    
    // Check the cookie access level for the URI and
    // return this value
    checkCookieAccess:  function(aRequest, aURI)
    {
        aRequest.QueryInterface(Components.interfaces.nsIChannel);
        return this.choice.canAccess(aURI , aRequest.originalURI , aRequest);
    },

    // Check the cookie access level for the URI and
    // return a string representation of this value
    checkCookieAccessString:  function(aRequest, aURI)
    {
        var accessString = CM_COOKIE_ACCESS_DEFAULT;
        aRequest.QueryInterface(Components.interfaces.nsIChannel);

        switch (this.choice.canAccess(aURI , aRequest.originalURI , aRequest))
        {
            case CM_CA_LEVEL_DEFAULT:
                accessString = CM_COOKIE_ACCESS_DEFAULT;
                break;
            case this._nsiPermissionManager.ALLOW_ACTION:
                accessString = CM_COOKIE_ACCESS_ALLOW;
                break;
            case this._nsiPermissionManager.DENY_ACTION:
                accessString = CM_COOKIE_ACCESS_DENY;
                break;
            case this._nsiPermissionManager.ACCESS_SESSION:
                accessString = CM_COOKIE_ACCESS_SESSION;
                break;
            default:
                accessString = CM_COOKIE_ACCESS_DEFAULT;
                break;
        }

        return accessString;
    },

    // Check the permission access level for the URI and
    // return a string representation of this value
    checkPermissionString:  function(aURI, aType)
    {
        var accessString = CM_COOKIE_ACCESS_DEFAULT;
        var permissionManager = Components.classes["@mozilla.org/permissionmanager;1"]
            .getService(this._nsiPermissionManager);

        switch (permissionManager.testPermission(aURI ,aType))
        {
            case 0:
                accessString = CM_COOKIE_ACCESS_DEFAULT;
                break;
            case permissionManager.ALLOW_ACTION:
                accessString = CM_COOKIE_ACCESS_ALLOW;
                break;
            case permissionManager.DENY_ACTION:
                accessString = CM_COOKIE_ACCESS_DENY;
                break;
            case this._nsICookiePermission.ACCESS_SESSION:
                accessString = CM_COOKIE_ACCESS_SESSION;
                break;
            default:
                accessString = CM_COOKIE_ACCESS_DEFAULT;
                break;
        }

        return accessString;
    },

    // Check the exact permission access level for the URI and
    // return an array of string representation of the values
    // for both the top level and 2nd level domain,
    // plus a standard testPermission on the URI
    // testExactPermission requires an exact hostname match - subdomains are not a match
    checkPermissionArray:  function(aURI, aType)
    {
        var accessStringTop = CM_COOKIE_ACCESS_DEFAULT;
        var accessStringSecond = CM_COOKIE_ACCESS_DEFAULT;
        var accessString = CM_COOKIE_ACCESS_DEFAULT;
        var accessArray = new Array(accessStringTop, accessStringSecond, accessString);
        var secondURI  = this.getSecondLevelURI(aURI);
        var tempURIIndex = -1;

        var permissionManager = Components.classes["@mozilla.org/permissionmanager;1"]
            .getService(this._nsiPermissionManager);
        
        // Determine what test permission method to use based
        // on the value of _isExactPermission
        if (this._isExactPerm)
        {
	        // Top level domain
	        switch (permissionManager.testExactPermission(aURI ,aType))
	        {
	            case CM_CA_LEVEL_DEFAULT:
	                accessStringTop = CM_COOKIE_ACCESS_DEFAULT;
	                break;
	            case permissionManager.ALLOW_ACTION:
	                accessStringTop = CM_COOKIE_ACCESS_ALLOW;
	                break;
	            case permissionManager.DENY_ACTION:
	                accessStringTop = CM_COOKIE_ACCESS_DENY;
	                break;
	            case this._nsICookiePermission.ACCESS_SESSION:
	                accessStringTop = CM_COOKIE_ACCESS_SESSION;
	                break;
	            default:
	                accessStringTop = CM_COOKIE_ACCESS_DEFAULT;
	                break;
	        }
	
	        // Second level domain
	        switch (permissionManager.testExactPermission(secondURI ,aType))
	        {
	            case CM_CA_LEVEL_DEFAULT:
	                accessStringSecond = CM_COOKIE_ACCESS_DEFAULT;
	                break;
	            case permissionManager.ALLOW_ACTION:
	                accessStringSecond = CM_COOKIE_ACCESS_ALLOW;
	                break;
	            case permissionManager.DENY_ACTION:
	                accessStringSecond = CM_COOKIE_ACCESS_DENY;
	                break;
	            case this._nsICookiePermission.ACCESS_SESSION:
	                accessStringSecond = CM_COOKIE_ACCESS_SESSION;
	                break;
	            default:
	                accessStringSecond = CM_COOKIE_ACCESS_DEFAULT;
	                break;
	        }        	
        }
        else
        {
	        // Second level domain
	        switch (permissionManager.testPermission(secondURI ,aType))
	        {
	            case CM_CA_LEVEL_DEFAULT:
	                accessStringSecond = CM_COOKIE_ACCESS_DEFAULT;
	                break;
	            case permissionManager.ALLOW_ACTION:
	                accessStringSecond = CM_COOKIE_ACCESS_ALLOW;
	                break;
	            case permissionManager.DENY_ACTION:
	                accessStringSecond = CM_COOKIE_ACCESS_DENY;
	                break;
	            case this._nsICookiePermission.ACCESS_SESSION:
	                accessStringSecond = CM_COOKIE_ACCESS_SESSION;
	                break;
	            default:
	                accessStringSecond = CM_COOKIE_ACCESS_DEFAULT;
	                break;
	        }
	        
	        // Top level domain
	        switch (permissionManager.testPermission(aURI ,aType))
	        {
	            case CM_CA_LEVEL_DEFAULT:
	                accessStringTop = CM_COOKIE_ACCESS_DEFAULT;
	                break;
	            case permissionManager.ALLOW_ACTION:
	                accessStringTop = CM_COOKIE_ACCESS_ALLOW;
	                break;
	            case permissionManager.DENY_ACTION:
	                accessStringTop = CM_COOKIE_ACCESS_DENY;
	                break;
	            case this._nsICookiePermission.ACCESS_SESSION:
	                accessStringTop = CM_COOKIE_ACCESS_SESSION;
	                break;
	            default:
	                accessStringTop = CM_COOKIE_ACCESS_DEFAULT;
	                break;
	        }
        }

        // Standard testPermission for URI (End Result)
        switch (permissionManager.testPermission(aURI ,aType))
        {
            case CM_CA_LEVEL_DEFAULT:
                accessString = CM_COOKIE_ACCESS_DEFAULT;
                break;
            case permissionManager.ALLOW_ACTION:
                accessString = CM_COOKIE_ACCESS_ALLOW;
                break;
            case permissionManager.DENY_ACTION:
                accessString = CM_COOKIE_ACCESS_DENY;
                break;
            case this._nsICookiePermission.ACCESS_SESSION:
                accessString = CM_COOKIE_ACCESS_SESSION;
                break;
            default:
                accessString = CM_COOKIE_ACCESS_DEFAULT;
                break;
        }

        // Lastly check to see if this is a temporary permission
        //tempURIIndex = this._tempAllowList.indexOf(aURI.asciiHost);
        //if (tempURIIndex > -1)
        if (this._cm.tempAllow.isTempPermission(aURI))
        {       
        	accessStringTop = CM_COOKIE_ACCESS_TEMP_ALLOW;
        	accessString = CM_COOKIE_ACCESS_TEMP_ALLOW;
        }

        //tempURIIndex = this._tempAllowList.indexOf(secondURI.asciiHost);
        //if (tempURIIndex > -1)
        if (this._cm.tempAllow.isTempPermission(secondURI))
        {       
        	accessStringSecond = CM_COOKIE_ACCESS_TEMP_ALLOW;
        	accessString = CM_COOKIE_ACCESS_TEMP_ALLOW;
        	
        	// If not ExactPerm and second level is temporary,
        	// then if top level is allow, change to temporary
        	// because any cookies will be deleted upon exit
	        if (!this._isExactPerm && (accessStringTop == CM_COOKIE_ACCESS_ALLOW))
	        {
        		accessStringTop = CM_COOKIE_ACCESS_TEMP_ALLOW;	      		
	        }
        }
        
        accessArray[CM_TOP_LEVEL] = accessStringTop;
        accessArray[CM_SECOND_LEVEL] = accessStringSecond;
        accessArray[CM_URL_STANDARD_LEVEL] = accessString;
        
        return accessArray;
    },

    // Input the numeric permission level and
    // return a string representation of this value
    getPermissionString:  function(aValue)
    {
        var accessString = CM_COOKIE_ACCESS_DEFAULT;

        switch (aValue*1)
        {
            case CM_CA_LEVEL_DEFAULT:
                accessString = CM_COOKIE_ACCESS_DEFAULT;
                break;
            case this._nsiPermissionManager.ALLOW_ACTION:
                accessString = CM_COOKIE_ACCESS_ALLOW;
                break;
            case this._nsiPermissionManager.DENY_ACTION:
                accessString = CM_COOKIE_ACCESS_DENY;
                break;
            case this._nsICookiePermission.ACCESS_SESSION:
                accessString = CM_COOKIE_ACCESS_SESSION;
                break;
            case CM_CA_LEVEL_TEMP_ALLOW:
                accessString = CM_COOKIE_ACCESS_TEMP_ALLOW;
                break;
            default:
                accessString = CM_COOKIE_ACCESS_DEFAULT;
                break;
        }

        return accessString;
    },

    // Input the string representation
    // of the permission level and
    // return the numeric representation of this value
    getPermissionValue:  function(aValue)
    {
        var accessValue = CM_CA_LEVEL_DEFAULT;

        switch (aValue)
        {
            case CM_COOKIE_ACCESS_DEFAULT:
                accessValue = CM_CA_LEVEL_DEFAULT;
                break;
            case CM_COOKIE_ACCESS_ALLOW:
                accessValue = this._nsiPermissionManager.ALLOW_ACTION;
                break;
            case CM_COOKIE_ACCESS_DENY:
                accessValue = this._nsiPermissionManager.DENY_ACTION;
                break;
            case CM_COOKIE_ACCESS_SESSION:
                accessValue = this._nsICookiePermission.ACCESS_SESSION;
                break;
            case CM_COOKIE_ACCESS_TEMP_ALLOW:
                accessValue = CM_CA_LEVEL_TEMP_ALLOW;
                break;
            default:
                accessValue = CM_CA_LEVEL_DEFAULT;
                break;
        }

        return accessValue;
    },

    // Set override for hosts cookie access
    // To process both http and https, set aProcessBoth to true
    setCookieAccess: function (aURI, aAccess, aDomainType/* , aProcessBoth */)
    {
        var hostURI = null;
        var alternateSchemeURI = null;
        var accessLevel = null;
        var tempHostIndex = -1;

        var aProcessBoth = false || Boolean(arguments[3]);

        if (aDomainType == CM_SECOND_LEVEL)
        {
            hostURI = this.getSecondLevelURI(aURI);
        }
        else
        {
        	hostURI = aURI;
        }

        // If processing both, create a URI for whatever
        // scheme hostURI is not, either http or https
        if (aProcessBoth)
        {
            alternateSchemeURI = this.getOtherSchemeURI(hostURI);
        }

        // Check if temporary access
        if (aAccess == CM_CA_LEVEL_TEMP_ALLOW)
        {
        	// Check if URI already has a non-default cookie access
            this._cm.tempAllow.add(hostURI);

            if (aProcessBoth)
            {
                this._cm.tempAllow.add(alternateSchemeURI);
            }

        	aAccess = this._nsiPermissionManager.ALLOW_ACTION;
        }
        else if (this._cm.tempAllow.isTempPermission(hostURI))
    	{
            this._cm.tempAllow.remove(hostURI);

            if (aProcessBoth)
            {
                this._cm.tempAllow.remove(alternateSchemeURI);
            }
    		
    		// If the updated permission is Deny or Default, where Default
    		// is Deny, then delete any cookies set for this host
	        if ((aAccess == this._nsiPermissionManager.DENY_ACTION) ||
	            ((aAccess == 0) && (this._cm.prefObserver.getCookiePrefString() == this._bundle.getString("rejected"))))
	        {
	        	//alert("aAccess = " + aAccess);
		    	// Set aUseBaseDomain to true
		        this.deleteHostCookies(aURI.asciiHost, true);
	        }        		
        }
        
        this.choice.setAccess(hostURI, aAccess);

        if (aProcessBoth)
        {
            this.choice.setAccess(alternateSchemeURI, aAccess);
        }

        // If new access is deny and the preference
        // deletecookiesondeny is true
        // then delete existing cookies for this host
        if ((aAccess == this._nsiPermissionManager.DENY_ACTION) &&
            this._cm.nsPreferences.getBoolPref("deletecookiesondeny", false))
        {
            this.deleteHostCookies(hostURI.asciiHost, false);
        }
    },

    // Create a URI from aURI,
    // but with the scheme it is not
    // (i.e. if http, then create one with https)
    getOtherSchemeURI: function(aURI)
    {
        var scheme = aURI.schemeIs("http") ? "https" : "http";
        var newHostString = this._cm.cookieMonster.getPrePath(aURI.asciiHost, scheme);
        return this._cm.utils.createURIFromHostName(newHostString, true);
    },

    // Convert URI to Second Level Domain
    // (i.e. groups.yahoo.com to yahoo.com)
    getSecondLevelURI: function(aURI)
    {
        // Parse the host string
        var hostString = aURI.asciiHost;
        var newHostString = null;
        var newHost = aURI;

        if (this._isEffectiveTLDService)
        {
            try
            {
                var eTLDService = Components.classes["@mozilla.org/network/effective-tld-service;1"]
		                  .getService(Components.interfaces.nsIEffectiveTLDService);

                newHostString = eTLDService.getBaseDomain(aURI);
            }
            catch (e)
            {
                newHostString = hostString;
            }
        }
        else
        {
            newHostString = this.getSecondLevelHost(hostString);
        }

        newHost = aURI.clone();

        if (newHostString)
        {
            newHost.host = newHostString;
        }

        //newHost = this._cm.utils.createURIFromHostName(newHostString);

        return newHost;
    },

    // Convert Host String to Second Level Domain
    // (i.e. groups.yahoo.com to yahoo.com)
    getSecondLevelHost: function(aHost)
    {
        // Parse the host string
        var checkExp = /^com|^net|^org|^edu/i;
        var checkSpecialTwo = /^au|^uk|^tw|^br/i;
        var newHostString = null;

        // First check if IPv6
        if (aHost.split(":").length > 1)
        {
            // We're probably ipv6
            newHostString = "[" + aHost + "]";
        }
        else if (this._isEffectiveTLDService)
        {
            // Is the effective-tld-service available
            try
            {
                var eTLDService = Components.classes["@mozilla.org/network/effective-tld-service;1"]
		                  .getService(Components.interfaces.nsIEffectiveTLDService);

                newHostString = eTLDService.getBaseDomainFromHost(aHost);
            }
            catch (e)
            {
                newHostString = aHost;
            }
        }
        else
        {
            // Is this the special case where
            // the URI ends in two characters
            var hostParts = aHost.split(".");

            // Do not parse if hostParts.length < 3
            if (hostParts.length >= 3)
            {
                // Normal URI
                if (hostParts[hostParts.length - 1].length > 2)
                {
                    newHostString = hostParts[hostParts.length - 2] + "." +
	                    hostParts[hostParts.length - 1];
                }
                    // Check to see if special
                    // (e.g. www.domain.com.au)/com|net|org|edu/
                else if ((checkExp.test(hostParts[hostParts.length - 2]) &&
	                hostParts[hostParts.length - 1].length <= 2) ||
	                checkSpecialTwo.test(hostParts[hostParts.length - 1]))
                {

                    newHostString = hostParts[hostParts.length - 3] + "." +
	                    hostParts[hostParts.length - 2] + "." +
	                    hostParts[hostParts.length - 1];
                }
                else
                {
                    newHostString = hostParts[hostParts.length - 2] + "." +
	                    hostParts[hostParts.length - 1];
                }
            }
            else
            {
                newHostString = aHost;
            }
        }
        
        return newHostString;
    },

    // Get Override Global cookie permissions for URI
    checkOverrideGlobal: function(aURI)
    {
    	var overrideArray = new Array(false, false);
    	var secondURI  = this.getSecondLevelURI(aURI);
    	var tempURIIndex = -1;
        
        // Check both top level and second level URI's
        tempURIIndex = this._globalOverrideList.indexOf(aURI.asciiHost);
        overrideArray[CM_TOP_LEVEL] = (tempURIIndex > -1);

        tempURIIndex = this._globalOverrideList.indexOf(secondURI.asciiHost);
        overrideArray[CM_SECOND_LEVEL] = (tempURIIndex > -1);
        
        return overrideArray;
    },
    
    // Add URI asciihost to Override Global cookie permissions list
    addOverrideGlobal: function(aHost, aDomainType)
    {
        var hostDomain = aHost;

        if (aDomainType == CM_SECOND_LEVEL)
        {
            hostDomain = this.getSecondLevelHost(aHost);
        }

        this._globalOverrideList.push(hostDomain);
        this._cm.nsPreferences.setAppendToStringPref(CM_PREFERENCE_TYPE_GLOBAL_OVERRIDE, hostDomain);    	
    },

    // Remove URI asciihost from Override Global cookie permissions list
    removeOverrideGlobal: function(aHost, aDomainType)
    {
		var hostDomain = aHost;
        var overrideHostIndex = -1;
        
        if (aDomainType == CM_SECOND_LEVEL)
        {
            hostDomain = this.getSecondLevelHost(aHost);
        }

        overrideHostIndex = this._globalOverrideList.indexOf(hostDomain);

    	if (overrideHostIndex > -1)
    	{
    		this._globalOverrideList.splice(overrideHostIndex, 1);
    		this._cm.nsPreferences.setStringPrefArray(CM_PREFERENCE_TYPE_GLOBAL_OVERRIDE, this._globalOverrideList);      		
    	}  	
    },

    // Remove all URI asciihosts from Override Global cookie permissions list
    removeAllOverrideGlobal: function()
    {
    	this._globalOverrideList = new Array();
    	this._cm.nsPreferences.clearUserPref(CM_PREFERENCE_TYPE_GLOBAL_OVERRIDE);
    	
    	// Reset any global override permissions in place
    	this._cm.cookieMonster.extResetGlobalCookiePref();
    },
    
    // Delete cookies from host
    deleteHostCookies: function(aHost, aUseBaseDomain)
    {
    	var deleteHost = aHost;
        var cookieManager = Components.classes["@mozilla.org/cookiemanager;1"]
            .getService(Components.interfaces.nsICookieManager);

        // If checking 2nd level domain names, make sure
        // deleteHost is a 2nd level domain of aHost
        if (aUseBaseDomain)
        {
        	deleteHost = this.getSecondLevelHost(aHost);
        }
        
        var iter = cookieManager.enumerator;

        while (iter.hasMoreElements())
        {
            var cookie = iter.getNext();

            if (cookie instanceof Components.interfaces.nsICookie)
            {
                // Delete cookies matching aHost
                var cookieHost = (cookie.host.charAt(0) == ".") ? cookie.host.substring(1,cookie.host.length) : cookie.host;

                // If checking 2nd level domain names, make sure
    			// cookieHost is a 2nd level domain of the cookie
        		if (aUseBaseDomain)
        		{
        			cookieHost = this.getSecondLevelHost(cookieHost);
        		}

                if (cookieHost == deleteHost)
                {
                    //alert("Delete: " + cookie.host);
                    cookieManager.remove(cookie.host , cookie.name , cookie.path , 0);
                }
            }
        }
    }
}
