httpfilters/cookie/ManagerSrc/Cookie.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Mon, 21 Jun 2010 16:17:02 +0300
branchRCL_3
changeset 15 bdd8a827a7de
parent 11 8f055b80aa5b
permissions -rw-r--r--
Revision: 201022 Kit: 2010125

/*
* Copyright (c) 2002 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:  implementation of class CCookie
*               
*
*/


// INCLUDE FILES
	// System includes
#include <httpstringconstants.h>
#include <http/rhttpheaders.h>
#include <http/rhttpsession.h>
#include <uri8.h>

	// User includes
#include "cookie.h"
#include "CookieLogger.h"
#include "CookieCommonConstants.h"


const TUint8 KDayOfWeekSeparator    = ',';
// const TUint8 KTimeSeparator         = ':';

_LIT8 ( KUT, "UT" );
_LIT8 ( KGMT, "GMT" );
_LIT8 ( KEST, "EST" );
_LIT8 ( KEDT, "EDT" );
_LIT8 ( KCST, "CST" );
_LIT8 ( KCDT, "CDT" );
_LIT8 ( KMST, "MST" );
_LIT8 ( KMDT, "MDT" );
_LIT8 ( KPST, "PST" );
_LIT8 ( KPDT, "PDT" );

const TUint8 KLocalTimeZoneSeparator1        = '+';
const TUint8 KLocalTimeZoneSeparator2        = '-';

const TInt KDateTokenCount = 3;
const TInt KTimeTokenCount = 3;
const TInt KAsciiTokenCount = 4;

_LIT8( KLocalSeparators, " -");
_LIT8( KLocalTimeSeparator, ":");

_LIT8( KLocalMonthNames, "Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec" );

#ifdef __TEST_COOKIE_LOG__
static void LogCookieAttribute( const CCookie& aCookie, const RStringPool& aPool, TInt aId, const TDesC8& aTextName, CCookie::TCookieAttributeName aAttributeName )
    {
    _LIT(KDateFormat,"%D%M%Y%/0%1%/1%2%/2%3%/3 %:0%H%:1%T%:2%S.%C%:3");
    THTTPHdrVal fieldVal;

    const TInt attribErr = aCookie.Attribute( aAttributeName, fieldVal );
    if ( attribErr == KErrNone )
        {
        switch ( fieldVal.Type() )
            {
        case THTTPHdrVal::KTIntVal:
            CLOG( ( ECookie, 0, _L8( "{%3d}  [Int]  %S = (%d)"), aId, &aTextName, fieldVal.Int() ) );
            break;

        case THTTPHdrVal::KStrFVal:
            {
            RStringF fieldValStr = aPool.StringF( fieldVal.StrF() );
            const TDesC8& fieldValDesC = fieldValStr.DesC();
            CLOG( ( ECookie, 0, _L8( "{%3d}  [StrF] %S = (%S)"), aId, &aTextName, &fieldValDesC ) );
            }
            break;

        case THTTPHdrVal::KStrVal:
            {
            RString fieldValStr = aPool.String( fieldVal.Str() );
            const TDesC8& fieldValDesC = fieldValStr.DesC();
            CLOG( ( ECookie, 0, _L8( "{%3d}  [Str]  %S = (%S)"), aId, &aTextName, &fieldValDesC ) );
            }
            break;

        case THTTPHdrVal::KDateVal:
            {
            TDateTime date = fieldVal.DateTime();
            TBuf<40> dateTimeString;
            TTime t( date );
            TRAP_IGNORE( t.FormatL( dateTimeString, KDateFormat ) );
            TBuf8<40> dateTimeString8;
            dateTimeString8.Copy( dateTimeString );
            CLOG( ( ECookie, 0, _L8( "{%3d}  [Date] %S = (%S)"), aId, &aTextName, &dateTimeString8 ) );
            } 
            break;

        default:
            CLOG(( ECookie, 0, _L8("{%3d}  [????] %S = (%d)"), aId, &aTextName, fieldVal.Type() ));
            break;
            }
        }
    else
        {
        //CLOG( ( ECookie, 0, _L8( "{%3d}  LogCookie - absent: %S"), aId, &aTextName ) );
        }
    }
#endif

// ---------------------------------------------------------
// CCookie::Log
// ---------------------------------------------------------
//
void CCookie::Log( TInt aAssociatedId ) const
    {
	TInt associateId = aAssociatedId;
	CLOG( ( ECookie, 0, _L( "-> CCookie::Log() - Associate Id:%d"), associateId ) );
#ifdef __TEST_COOKIE_LOG__
    const TInt count = iAttributes.Count();
    CLOG( ( ECookie, 0, _L( "-> CCookie::Log() - %d attributes..."), count ) );
    for( TInt i=0; i<count; i++ )
        {
        // Calculating/fetching size is enough to generate usable logs
        const TCookieAttribute& attrib = iAttributes[ i ];
        const TInt size = attrib.Size();
        }

    LogCookieAttribute( *this, iStringPool, aAssociatedId, _L8("Name"), CCookie::EName );
    LogCookieAttribute( *this, iStringPool, aAssociatedId, _L8("Value"), CCookie::EValue );
    LogCookieAttribute( *this, iStringPool, aAssociatedId, _L8("Domain"), CCookie::EDomain );
    LogCookieAttribute( *this, iStringPool, aAssociatedId, _L8("Path"), CCookie::EPath );
    LogCookieAttribute( *this, iStringPool, aAssociatedId, _L8("Date"), CCookie::EDate );
    LogCookieAttribute( *this, iStringPool, aAssociatedId, _L8("Version"), CCookie::EVersion );
    LogCookieAttribute( *this, iStringPool, aAssociatedId, _L8("Expires"), CCookie::EExpires );
    LogCookieAttribute( *this, iStringPool, aAssociatedId, _L8("MaxAge"), CCookie::EMaxAge );
    LogCookieAttribute( *this, iStringPool, aAssociatedId, _L8("Discard"), CCookie::EDiscard );
    LogCookieAttribute( *this, iStringPool, aAssociatedId, _L8("Port"), CCookie::EPort );
    LogCookieAttribute( *this, iStringPool, aAssociatedId, _L8("Secure"), CCookie::ESecure );
    LogCookieAttribute( *this, iStringPool, aAssociatedId, _L8("Comment"), CCookie::EComment );
    LogCookieAttribute( *this, iStringPool, aAssociatedId, _L8("Comment URI"), CCookie::ECommentURI );
    CLOG( ( ECookie, 0, _L( "{%3d}         fromCookie2: %d, fromNetscapeVersion: %d"), aAssociatedId, FromCookie2(), FromNetscapeVersion() ) );
    CLOG( ( ECookie, 0, _L( "{%3d}         expired: %d, persists: %d, unknownVer: %d"), aAssociatedId, Expired(), Persistent(), IsUnknownVersion() ) );
    CLOG( ( ECookie, 0, _L( "<- CCookie::Log() - %d attributes..."), count ) );
#endif
    }


// ---------------------------------------------------------
// CCookie::NewL
// ---------------------------------------------------------
//
EXPORT_C CCookie* CCookie::NewL( RHTTPHeaders aRequestHeaders, TInt aPartIndex,
								RStringF aFieldName, RStringPool aStringPool,
								const TUriC8& aUri )
	{
	CCookie* self = new (ELeave) CCookie( aStringPool );

	CleanupStack::PushL( self );

	self->ConstructL( aRequestHeaders, aPartIndex, aFieldName, aUri );

	CleanupStack::Pop();	// self

	return self;
	}


// ---------------------------------------------------------
// CCookie::NewL
// ---------------------------------------------------------
//
EXPORT_C CCookie* CCookie::NewL( RStringPool aStringPool )
	{
	return new (ELeave) CCookie( aStringPool );
	}
// ---------------------------------------------------------
// CCookie::NewL
// ---------------------------------------------------------
//
CCookie* CCookie::CloneL( const CCookie& aCopy,const TDesC8& aDomain,const TDesC8& aPath, const TDesC8& aPort)
    {
    CCookie* self = new(ELeave) CCookie( aCopy.iStringPool );
    CleanupStack::PushL( self );
    self->CopyFromL( aCopy, aDomain, aPath, aPort);
    CleanupStack::Pop( self );
    return self;
    }
	

// ---------------------------------------------------------
// CCookie::~CCookie
// ---------------------------------------------------------
//
EXPORT_C CCookie::~CCookie()
	{
	// go through each attribute closing any attribute strings	
	TInt numAttributes = iAttributes.Count();
	Log();
	CLOG( ( ECookie, 0, _L( "-> CCookie::~CCookie - this: 0x%08x, numAttributes: %d"), this, numAttributes ) );
	for ( TInt ii = 0; ii < numAttributes; ++ii )
		{
		iAttributes[ii].Close();
		}

	iAttributes.Close();
	CLOG( ( ECookie, 0, _L( "<- CCookie::~CCookie - this: 0x%08x, count: %d"), this, numAttributes ) );
	}


// ---------------------------------------------------------
// CCookie::AddDefaultPathL
// ---------------------------------------------------------
//
void CCookie::AddDefaultPathL( const TUriC8& aUri )
	{
	CLOG( ( ECookie, 0, _L( "-> CCookie::AddDefaultPathL") ) );
	// RFC2965 : Defaults to the path of the request URL that generated the
	// Set-Cookie2 response, up to and including the right-most /.
	// Note : there is a contradiction as we must not include the right-most /
	// per RFC2109, which is obsolete. Decision : we support RFC2965.
	const TUint8 KCookiePathSeparator = '/';
	TPtrC8 requestPath;
	if ( aUri.IsPresent( EUriPath ) )
		{
		requestPath.Set( aUri.Extract( EUriPath ) );

		TInt sepPos = requestPath.LocateReverse( KCookiePathSeparator );
		// if / is not the last character
		if ( 0 <= sepPos && ( ( sepPos + 1 != requestPath.Length() ) ) )
			{
			// then remove characters after the right-most /
			requestPath.Set( requestPath.Left( sepPos + 1 ) );
			}
		}
	else
		{
		requestPath.Set( &KCookiePathSeparator,
						sizeof( KCookiePathSeparator ) );
		}

    RStringF defPath = iStringPool.OpenFStringL( requestPath );
    THTTPHdrVal defPathVal( defPath );
	SetAttribute( EPath, defPathVal, ETrue );// ignore the result 
    defPath.Close();
    CLOG( ( ECookie, 0, _L( "<- CCookie::AddDefaultPathL") ) );
	}

// ---------------------------------------------------------
// CCookie::AddToRequestL
// ---------------------------------------------------------
//
EXPORT_C void CCookie::AddToRequestL( RHTTPHeaders aRequestHeaders,
									 TInt aPartIndex ) const
	{
	CLOG( ( ECookie, 0, _L( "-> CCookie::AddToRequestL") ) );
	const TStringTable& commonStringTable = RHTTPSession::GetTable();

	// We're writing out the "Cookie:" string
	RStringF cookieString =
					iStringPool.StringF( HTTP::ECookie, commonStringTable );
	aRequestHeaders.SetFieldL( cookieString, THTTPHdrVal() );

	THTTPHdrVal hVal;

	// We're writing out the Version attribute - it is a serious error if this
	// attribute is missing
	if ( Attribute( CCookie::EVersion, hVal ) == KErrNone )
		{
		aRequestHeaders.SetParamL( cookieString, 
							iStringPool.StringF( HTTP::EVersion,
												commonStringTable ),
							hVal,
							aPartIndex );
		}
	else
		{
		CLOG( ( ECookie, 0, _L( "CCookie::AddToRequestL - version is missing! - iSetCookie2: %d"), iSetCookie2 ) );
		if ( iSetCookie2 )
			{
			// if this is a new-style cookie (it is from a Set-Cookie2 header),
			// then it must have a Version attribute.
			// TBD : or should we insert a '$Version=1' string instead?
			CLOG( ( ECookie, 0, _L( "<- CCookie::AddToRequestL - KErrCorrupt!") ) );
			User::Leave( KErrCorrupt );
			}
		}
	CLOG( ( ECookie, 0, _L( "CCookie::AddToRequestL - adding name...") ) );
	// We're writing out the NAME attribute - it is a serious error if this
	// attribute is missing
	User::LeaveIfError( Attribute( CCookie::EName, hVal ) );
	aRequestHeaders.SetParamL( cookieString,
							iStringPool.StringF( HTTP::ECookieName,
												commonStringTable ), 
							hVal,
							aPartIndex );

	CLOG( ( ECookie, 0, _L( "CCookie::AddToRequestL - adding value...") ) );
	// We're writing out the VALUE attribute - it is a serious error if this
	// attribute is missing
	User::LeaveIfError( Attribute( CCookie::EValue, hVal ) );
	aRequestHeaders.SetParamL( cookieString,
							iStringPool.StringF( HTTP::ECookieValue,
												commonStringTable ),
							hVal,
							aPartIndex );

	// Writing out the rest : domain, path and port. These are not mandatory,
	// thus we do not leave if they are missing.
	// Writing out Domain attribute
	if ( Attribute( CCookie::EDomain, hVal ) == KErrNone && hVal.StrF().DesC().Length() > 0 )
        {
        CLOG( ( ECookie, 0, _L( "CCookie::AddToRequestL - adding domain...") ) );
		aRequestHeaders.SetParamL( cookieString,
								iStringPool.StringF( HTTP::EDomain,
													commonStringTable ),
								hVal,
								aPartIndex );
        }

	// Writing out Path attribute
	if ( Attribute( CCookie::EPath, hVal ) == KErrNone )
        {
        CLOG( ( ECookie, 0, _L( "CCookie::AddToRequestL - adding path...") ) );
		aRequestHeaders.SetParamL( cookieString,
								iStringPool.StringF( HTTP::EPath,
													commonStringTable ),
								hVal,
								aPartIndex );
        }

	// Writing out Port attribute
	if ( Attribute( CCookie::EPort, hVal ) == KErrNone )
        {
        CLOG( ( ECookie, 0, _L( "CCookie::AddToRequestL - adding port...") ) );
		aRequestHeaders.SetParamL( cookieString,
								iStringPool.StringF( HTTP::ECookiePort,
													commonStringTable ),
								hVal,
								aPartIndex );
        }
	CLOG( ( ECookie, 0, _L( "<- CCookie::AddToRequestL") ) );
	}


// ---------------------------------------------------------
// CCookie::Attribute
// ---------------------------------------------------------
//
EXPORT_C TInt CCookie::Attribute
							( CCookie::TCookieAttributeName aAttributeName,
								THTTPHdrVal& aAttributeVal) const
	{
	CLOG( ( ECookie, 0, _L( "-> CCookie::Attribute") ) );
	TCookieAttribute attribute;
	if ( FindAttribute( aAttributeName, attribute ) != KErrNotFound )
		{
		aAttributeVal = attribute.Value();
		CLOG( ( ECookie, 0, _L( "<- CCookie::Attribute") ) );
		return KErrNone;
		}
	CLOG( ( ECookie, 0, _L( "<- CCookie::Attribute") ) );
	return KErrNotFound;
	}


// ---------------------------------------------------------
// CCookie::SetAttribute
// ---------------------------------------------------------
//
EXPORT_C TInt CCookie::SetAttribute
							( CCookie::TCookieAttributeName aAttributeName, 
								const THTTPHdrVal& aAttributeVal )
	{
	return SetAttribute( aAttributeName, aAttributeVal, EFalse );
	}



// ---------------------------------------------------------
// CCookie::Attribute
// ---------------------------------------------------------
//
TInt CCookie::Attribute( TCookieAttributeName aAttributeName,
						 THTTPHdrVal& aAttributeVal,
						 TBool& aDefaulted ) const
	{
	CLOG( ( ECookie, 0, _L( "-> CCookie::Attribute ") ) );
	TCookieAttribute attribute;
	if ( FindAttribute( aAttributeName, attribute ) != KErrNotFound )
		{
		aAttributeVal = attribute.Value();
		aDefaulted = attribute.Defaulted();
		CLOG( ( ECookie, 0, _L( "<- CCookie::Attribute KErrNone") ) );
		return KErrNone;
		}
	CLOG( ( ECookie, 0, _L( "<- CCookie::Attribute KErrNotFound") ) );
	return KErrNotFound;
	}


// ---------------------------------------------------------
// CCookie::SetAttribute
// ---------------------------------------------------------
//
TInt CCookie::SetAttribute(  TCookieAttributeName aAttributeName,
							const THTTPHdrVal& aAttributeVal,
							TBool aDefaulted )
{
    CLOG( ( ECookie, 0, _L( "-> CCookie::SetAttribute") ) );
	TInt result( KErrNone );

	TCookieAttribute attribute;
	TInt index = FindAttribute( aAttributeName, attribute );
	if ( index != KErrNotFound )
		{
		result = KErrAlreadyExists;
		}
	else
		{
		TCookieAttribute newAttribute( aAttributeName, 
									   aAttributeVal, aDefaulted );

		result = iAttributes.Append( newAttribute );
		if ( result == KErrNone )
			{
			iSize += ( KCookieAttributePrefixLength + newAttribute.Size() + 
                       KCookieAttributeDefaultedLength + 
                       KCookieAttributeFoundLength );
			}
		else
			{
			newAttribute.Close();
			}
		}
	CLOG( ( ECookie, 0, _L( "<- CCookie::SetAttribute result: %d"),result ) );
	return result;
}

// ---------------------------------------------------------
// CCookie::CopyFromL
// ---------------------------------------------------------
//
void CCookie::CopyFromL( const CCookie& aCopyFrom, const TDesC8& aDomain, const TDesC8& aPath, const TDesC8& aPort  )
    {
    CLOG( ( ECookie, 0, _L( "-> CCookie::CopyFromL ") ) );
    TBool defaultDiscard( EFalse );
    THTTPHdrVal attributevalue;
    TBool defaulted( EFalse );
    iSetCookie2 = aCopyFrom.iSetCookie2;
    if ( aCopyFrom.Attribute( EName, attributevalue, defaulted ) != KErrNotFound )
        {
        if ( attributevalue.Type() != THTTPHdrVal::KStrVal )
             {
             RString correctedStringType = iStringPool.OpenStringL( attributevalue.StrF().DesC() );
             attributevalue.SetStr( correctedStringType );
             SetAttribute( EName, attributevalue, defaulted );
             correctedStringType.Close();
             const TPtrC8 pVal( attributevalue.Str().DesC() );
             CLOG( ( ECookie, 0, _L8( "CCookie::CopyFromL - attribute EName Value : %S" ), &pVal ) );
             }
        else 
            {
            SetAttribute( EName, attributevalue, defaulted );    
            const TPtrC8 pVal( attributevalue.Str().DesC() );
            CLOG( ( ECookie, 0, _L8( "CCookie::CopyFromL - attribute EName Value : %S" ), &pVal ) );
            }
        }

    if ( aCopyFrom.Attribute( EValue, attributevalue, defaulted ) != KErrNotFound )
        {
         if ( attributevalue.Type() != THTTPHdrVal::KStrVal )
            {
            RString correctedStringType = iStringPool.OpenStringL( attributevalue.StrF().DesC() );
            attributevalue.SetStr( correctedStringType );
            SetAttribute( EValue, attributevalue, defaulted );
            correctedStringType.Close();
            const TPtrC8 pVal( attributevalue.Str().DesC() );
            CLOG( ( ECookie, 0, _L8( "CCookie::CopyFromL - attribute EValue value: %S" ), &pVal ) );
            }
         else
             {
             SetAttribute( EValue, attributevalue, defaulted );
             const TPtrC8 pVal( attributevalue.Str().DesC() );
             CLOG( ( ECookie, 0, _L8( "CCookie::CopyFromL - attribute EValue Value : %S" ), &pVal ) );
             }
        }
    if ( aCopyFrom.Attribute( EVersion, attributevalue, defaulted ) != KErrNotFound )
        {
        SetAttribute( EVersion, attributevalue, defaulted );    
        SetFromNetscape( EFalse );
        }
    else
        {
        SetFromNetscape( ETrue );
        }

    if ( aCopyFrom.Attribute( EPath, attributevalue, defaulted ) != KErrNotFound )
        {
         if ( attributevalue.Type() != THTTPHdrVal::KStrFVal )
             {
             SetAttribute( EPath, attributevalue, defaulted );    
             }
        }
    else
        {
        // defaulting
        RStringF defPath = iStringPool.OpenFStringL( aPath );
        THTTPHdrVal defPathVal( defPath );
        SetAttribute( EPath, defPathVal, ETrue );// ignore the result 
        defPath.Close();
        }
    if ( aCopyFrom.Attribute( EDomain, attributevalue, defaulted ) != KErrNotFound )
          {
          if ( attributevalue.Type() != THTTPHdrVal::KStrFVal )
              {
              SetAttribute( EDomain, attributevalue, defaulted );    
              }
          }
    else
       {
         // Default handling 
         // in this case the default is the effective request host        
         RStringF defDomain = iStringPool.OpenFStringL( aDomain );
         THTTPHdrVal defdomVal( defDomain );
         SetAttribute( EDomain, defdomVal, ETrue );// ignore the result 
         defDomain.Close();
       }
  
    
    if ( aCopyFrom.Attribute( ESecure, attributevalue, defaulted ) != KErrNotFound )
	      {
            SetAttribute( ESecure, attributevalue, defaulted );    
	      }
    if (iNetscape)
         {
         if ( aCopyFrom.Attribute( EExpires, attributevalue, defaulted ) != KErrNotFound )
              {
                  SetAttribute( EExpires, attributevalue, defaulted );    
              }
         else if ( aCopyFrom.Attribute( EComment, attributevalue, defaulted ) != KErrNotFound ||
                           aCopyFrom.Attribute( EMaxAge, attributevalue, defaulted ) != KErrNotFound )
             {
             iNetscape = EFalse;
             }
         }
     if ( aCopyFrom.Attribute( EDate, attributevalue, defaulted ) != KErrNotFound )
          {
          TDateTime attrTime = attributevalue.DateTime();
          THTTPHdrVal attributeVal( attrTime );
          SetAttribute( CCookie::EDate, attributeVal, defaulted );
          }
     else
         {
           TTime nowTime;
           nowTime.UniversalTime();
           TDateTime attrTime = nowTime.DateTime();
           THTTPHdrVal attributeVal( attrTime );
           SetAttribute( EDate, attributeVal, defaulted );
         }
     if (iNetscape == EFalse)
         {
         if ( aCopyFrom.Attribute( EComment, attributevalue, defaulted ) != KErrNotFound )
             {
             SetAttribute( EComment, attributevalue );
             }
         else
             {
             
             }
         if ( aCopyFrom.Attribute( EMaxAge, attributevalue, defaulted ) != KErrNotFound)
             {
             SetAttribute( EMaxAge, attributevalue );
             }
         else
             {
              if(iSetCookie2)
                  {
                  defaultDiscard = ETrue;
                  }
             }
         if(iSetCookie2)
             {
             if ( aCopyFrom.Attribute( ECommentURI, attributevalue, defaulted ) != KErrNotFound )
                 {
                 SetAttribute( ECommentURI, attributevalue, defaulted );
                 }
             else
                 {
                 
                 }
             if ( aCopyFrom.Attribute( EDiscard, attributevalue, defaulted ) != KErrNotFound )
                  {
                      SetAttribute( EDiscard, attributevalue, defaulted );    
                  }
             else
                {
                 if (defaultDiscard)
                     {
                     RStringF emptyStr = iStringPool.OpenFStringL( KNullDesC8() );
                     THTTPHdrVal emptyVal( emptyStr );
                     SetAttribute( EDiscard, emptyVal, ETrue );
                     emptyStr.Close();
                     }
                 if (aCopyFrom.Attribute( EPort, attributevalue, defaulted ) != KErrNotFound)
                     {
                     SetAttribute( EPort, attributevalue, ETrue );    // ignore the result of this method
                     }
                 else
                     {
                     RStringF requestPort;
                     if(!aPort.Compare(KNullDesC8()))
                         {
                         requestPort = iStringPool.OpenFStringL( aPort );
                         }
                     else
                         {
                         requestPort = iStringPool.OpenFStringL( KCookieDefaultRequestPort() );
                         }
                     THTTPHdrVal portVal( requestPort );
                     SetAttribute( EPort, portVal, ETrue );
                     requestPort.Close();
                     }
                }
             
             }
             
         }
	

    //SetCookie2( aCopyFrom.FromCookie2() );
    // Other properties
    
    iSize = aCopyFrom.iSize;
    iReceivedTime = aCopyFrom.iReceivedTime;
    CLOG( ( ECookie, 0, _L( "<- CCookie::CopyFromL ") ) );
    }




// ---------------------------------------------------------
// CCookie::StringPool
// ---------------------------------------------------------
//
RStringPool CCookie::StringPool()
    {
    return iStringPool;
    }



// ---------------------------------------------------------
// CCookie::Expired
// ---------------------------------------------------------
//
TBool CCookie::Expired() const
	{
	CLOG( ( ECookie, 0, _L( "-> CCookie::Expired ") ) );
    // the cookie has expired if:
    // 1. it's Age > Max-Age
    // 2. current_date > expires
    // Expires is in Netscape cookie only !!!

    TBool retval( EFalse );
	THTTPHdrVal attrVal;
    TInt err( KErrNone );

	if ( FromNetscapeVersion() && ( Attribute( CCookie::EExpires, attrVal ) == KErrNone ))
        {
	    if ( attrVal.Type() == THTTPHdrVal::KDateVal )
		    {
            TDateTime expires;
		    expires = attrVal.DateTime();
            TTime Expirytime( expires );
            TTime NowTime;
            NowTime.UniversalTime();
            if ( Expirytime <= NowTime )
                { // EXPIRED !!!!
                retval = ETrue;
                }
            }
        else
            {
		    if ( attrVal.Type() == THTTPHdrVal::KStrFVal )
                {
                TRAP_IGNORE( retval = ExpiredNetscapeL( attrVal ) );
                // The only real error is KErrNoMemory, 
                // so we simply ignore the error here
                }
            }
		}
    else
        {
        if ( Attribute( CCookie::EMaxAge, attrVal ) == KErrNone )
            {
            TInt MaxAge(0);
            if ( attrVal.Type() == THTTPHdrVal::KTIntVal )
                {
                MaxAge = attrVal.Int();
                }
            else
                {
                TPtrC8 MaxAgePtr=CCookie::RemoveQuotes( attrVal.StrF().DesC() );
                TLex8 lex( MaxAgePtr );
                err = lex.Val( MaxAge );
                }
            if ( err == KErrNone )
                {
                        // it's Age > Max-Age?
                        // Age = ( now_time - EDate )
                        // TTime.SecondsFrom(TTime)
                        // UniversalTime.SecondsFrom( EDate_time ): real age
                        TTime NowTime;
                        NowTime.UniversalTime();
                        TTimeIntervalSeconds CurrAgeInterval;
                        err = NowTime.SecondsFrom( iReceivedTime, CurrAgeInterval );
                        // now compare to specified Max-Age
                        if ( MaxAge <= CurrAgeInterval.Int() )
                            { // EXPIRED !!!!
                            retval = ETrue;
                            }
                        
                    
                }
			}
		}
	CLOG( ( ECookie, 0, _L( "<- CCookie::Expired retval : %d"),retval ) );
	return retval;
	}
// ---------------------------------------------------------
// CCookie::RemoveQuotes
// ---------------------------------------------------------
//
 TPtrC8 CCookie::RemoveQuotes( const TDesC8& aDes ) 
	{
	CLOG( ( ECookie, 0, _L( "-> CCookie::RemoveQuotes ") ) );
	TInt firstChar = 0;					// position of the first character
	TInt lastChar = aDes.Length() - 1;	// position of the last character
	TPtrC8 result;
	if ( lastChar < 0 )	// that is, aDes has a length of zero
		{
		result.Set( aDes );	// the result is the same
		}
	else
		{
		TUint8 quotationMark = '"';

		if ( aDes[ firstChar ] == quotationMark )
			{
			firstChar++;
			}

		if ( aDes[ lastChar ] == quotationMark )
			{
			lastChar--;
			}

		if ( lastChar < firstChar )
			{
			result.Set( KNullDesC8() );
			}
		else
			{
			result.Set( aDes.Mid( firstChar, lastChar - firstChar + 1 ) );
			}
		}
	CLOG( ( ECookie, 0, _L( "<- CCookie::RemoveQuotes result : %d "),result ) );
    return result;
	}



// ---------------------------------------------------------
// CCookie::ExpiredNetscapeL
// ---------------------------------------------------------
//
TBool CCookie::ExpiredNetscapeL( THTTPHdrVal aAttrVal) const
    {
    CLOG( ( ECookie, 0, _L( "-> CCookie::ExpiredNetscapeL ") ) );
    TBool retval( EFalse );
    TPtrC8 datePtr8( aAttrVal.StrF().DesC() );
    TInt dateLen( datePtr8.Length() );
    if( dateLen == 0 )
        {
        // blank "expires" attribute evaluate as not expired
        // additional check is done in Persistent() function
        return EFalse;
        }
    HBufC8* temp1 = HBufC8::NewLC( dateLen );
    TPtr8 temp1Des( temp1->Des() );
    temp1Des.Copy( datePtr8 );
    HBufC8* temp2;
    HBufC8 *desDate;
    
    // ascii time format
    // asctime-date = wkday SP date3 SP time SP 4DIGIT
    // date3        = month SP ( 2DIGIT | ( SP 1DIGIT ))
    TBool asciiTime = EFalse;
    
    if(KErrNotFound == temp1->Locate( KDayOfWeekSeparator ))
    {
       asciiTime=ETrue;
    }
    
    if(asciiTime)  
    {
       temp2 = HBufC8::NewLC( temp1->Length() );
       temp2 = temp1;
    }
    else
    {
       temp2 = GetCleanedDateTimeLC( temp1 );		
    }
    
    TInt cleanupNum( 2 );  // temp1, temp2
    TPtr8 temp2Des( temp2->Des() );
    temp2Des.Trim();

    TDateTime tempDate( 1997, EJanuary, 1, 0, 0, 0, 0 );
    TLex8 lex;
    TInt error( KErrNone );
    TInt tempInt;
    TInt sepPos[4];

    // date string is formatted as: "DD-Mon-YYYY HH:MM:SS"
    // and must be evaluated as a GMT time

    // parsing Date
    // find token's position
    TInt token = FindTokens( temp2Des, KLocalSeparators, asciiTime?KAsciiTokenCount:KDateTokenCount, sepPos );
    
    if( token < (asciiTime?KAsciiTokenCount:KDateTokenCount -1) )
       	{
       	CleanupStack::PopAndDestroy( cleanupNum ); // temp1, temp2
       	return ETrue;
       	}
       	
    if(!asciiTime)
		{
    	if( token == KDateTokenCount - 1 )   // if no Time is specified
        	{
        	sepPos[2] = temp2Des.Length();
        	}
    	}

    // initizalize Date
    
    if(asciiTime)
    	{
    	desDate=temp2Des.AllocLC();
    	}
    else
    	{
    	desDate = temp2Des.Left( sepPos[2] ).AllocLC();
    	}
   
    cleanupNum++;  // temp1, temp2, desDate
    desDate->Des().Trim();

    // day
    if(asciiTime)
    	{
    	lex = desDate->Des().Mid( sepPos[1]+1,sepPos[2]- sepPos[1] - 1);		
    	}
    else
    	{
    	lex = desDate->Des().Left( sepPos[0] );	
    	}
    
    error += lex.Val( tempInt );
    error += tempDate.SetDay( tempInt - 1 );  // day's offset is 0!

    // year
	if(asciiTime)
		{
		lex = desDate->Des().Right( desDate->Length() - sepPos[3] - 1 );	
		}
	else
		{
		lex = desDate->Des().Right( desDate->Length() - sepPos[1] - 1 );		
		}
    error += lex.Val( tempInt );
    if(tempInt < 100)  // make sure it has four digit length
        {
        tempInt += 2000;
        }
    error += tempDate.SetYear( tempInt );

    // month
    TPtrC8 monthPtr = desDate->Des().Mid( sepPos[0] + 1, sepPos[1] - sepPos[0] - 1 );
    TPtrC8 monthNamesPtr( KLocalMonthNames );
    TInt monthNum = monthNamesPtr.Find( monthPtr );
    if( monthNum == KErrNotFound )
        {
        // probably using digits for month rather than its English name
        lex = monthPtr;
        error += lex.Val( monthNum );
        monthNum--; // month's offset is 0!
        if ( (monthNum < 0) || (monthNum > 11) )
            // invalid month, cookie must be removed
            {
            CleanupStack::PopAndDestroy( cleanupNum ); // temp1, temp2, desDate
            return ETrue;
            }
        }
    // now we have a position for month's English name
    else if( (monthNum % 4 ) != 0 )
        // something strange happened, cookie must be removed
        {
        CleanupStack::PopAndDestroy( cleanupNum ); // temp1, temp2, desDate
        return ETrue;
        }
    else
        {
        // divide by 4 to convert from index into month's English name to month number, zero relative
        monthNum >>= 2;
        }
    error += tempDate.SetMonth( TMonth( monthNum ) );  // month's offset is 0!

    // parsing Time
    if( (sepPos[2] != temp2Des.Length()) &&  // Time is present
        (error == KErrNone) )  // and no error yet
        {
        	HBufC8 *desTime;
        // initialize Time
    if(asciiTime)
    	{
    	desTime=temp2Des.Mid( sepPos[2] + 1, sepPos[3] - sepPos[2] - 1 ).AllocLC();
    	}
    else
        {
    	desTime = temp2Des.Right( temp2Des.Length() - sepPos[2] - 1 ).AllocLC();
        }
        cleanupNum++;  // 4
        desTime->Des().Trim();

        token = FindTokens( desTime->Des(), KLocalTimeSeparator, KTimeTokenCount, sepPos );
        if(token >= KTimeTokenCount - 1)  // 2, 3 tokens found
            {
            // hour
            lex = desTime->Des().Left( sepPos[0] );
            error += lex.Val( tempInt );
            error += tempDate.SetHour( tempInt );

            // second
            lex = desTime->Des().Right( desTime->Length() - sepPos[1] - 1 );
            error += lex.Val( tempInt );
            error += tempDate.SetSecond( tempInt );

            // minute
            lex = desTime->Des().Mid( sepPos[0] + 1, sepPos[1] - sepPos[0] - 1 );
            error += lex.Val( tempInt );
            error += tempDate.SetMinute( tempInt );
            }
        }

    // is parsing OK?
    if( error == KErrNone )
        {
        TTime expiryTime( tempDate );
        THTTPHdrVal aAttributeVal;
    	TCookieAttribute attribute;
    	TDateTime ResponseDate;
		if ( FindAttribute( EDate, attribute ) != KErrNotFound )
			{
			aAttributeVal = attribute.Value();
			ResponseDate=aAttributeVal.DateTime();
			}
        TTime RespTime(ResponseDate);
        TTimeIntervalMicroSeconds diffMsec=expiryTime.MicroSecondsFrom(RespTime);
        TTime nowTime;
        nowTime.UniversalTime();
//        TDateTime temptime2;
        TTime newexpiryTime = iReceivedTime + diffMsec;
//        temptime2 = nowTime.DateTime();
        if( newexpiryTime <= nowTime )
            { // EXPIRED !!!!
            retval = ETrue;
            }
        }
    else  // invalid Date is expired!
        {
        retval = ETrue;
        }
    CleanupStack::PopAndDestroy( cleanupNum ); // temp1, temp2, desDate, desTime
    CLOG( ( ECookie, 0, _L( "<- CCookie::ExpiredNetscapeL retval : %d "),retval ) );
    return retval;
    }


// ---------------------------------------------------------
// CCookie::FindTokens
// ---------------------------------------------------------
//
TInt CCookie::FindTokens( const TDesC8& aString, 
                         const TDesC8& aTokenSeparators, 
                         const TInt aTokenCount, 
                         TInt* aTokens ) const
    {
    CLOG( ( ECookie, 0, _L( "-> CCookie::FindTokens ") ) );
    TLex8 lex = aString;
    TChar ch;
    TInt tokenCount( 0 ), ii;
    for(ii=0; ii<aTokenCount; aTokens[ii++] = KErrNotFound) ;

    while( !( (tokenCount==aTokenCount) || lex.Eos() ) )
        {
        ch = lex.Get();
        if( aTokenSeparators.Locate( ch ) != KErrNotFound ) 
            {
            aTokens[tokenCount++] = lex.Offset()-1;
            }
        }
    CLOG( ( ECookie, 0, _L( "<- CCookie::FindTokens tokenCount : %d"),tokenCount ) );
    return tokenCount;
    }

// ---------------------------------------------------------
// CCookie::Persistent
// ---------------------------------------------------------
//
TBool CCookie::Persistent() const
    {
    CLOG( ( ECookie, 0, _L( "-> CCookie::Persistent ") ) );
    TBool result( EFalse );
	THTTPHdrVal attrVal;

    if ( FromNetscapeVersion() )
        {
        if ( Attribute( CCookie::EExpires, attrVal ) == KErrNone )
            {
            // blank "expires" attribute evaluate as expired.
            // check only for string type attribute
            if ( attrVal.Type() == THTTPHdrVal::KStrFVal )
                {
                if( attrVal.StrF().DesC().Length() > 0 )
                    {
                    result = ETrue;
                    }
                }
            else
                {
                result = ETrue;
                }
            }
        }
    else
        {
        if ( Attribute( CCookie::EDiscard, attrVal ) == KErrNotFound )
            {
            if ( Attribute( CCookie::EMaxAge, attrVal ) == KErrNone )
                { // has max age, to be stored until it expires...
                // check if MaxAge is 0, in that case, discard immediatelly.
                TInt MaxAge(0);
                if ( attrVal.Type() == THTTPHdrVal::KTIntVal )
                    {
                    MaxAge = attrVal.Int();
                    }
                else
                    {
                    TPtrC8 MaxAgePtr( attrVal.StrF().DesC() );
                    TLex8 lex( MaxAgePtr );
                    lex.Val( MaxAge );
                    }
                if ( MaxAge > 0)
                    {
                    result = ETrue;
                    }
                }
            }
        }
    CLOG( ( ECookie, 0, _L( "<- CCookie::Persistent result : %d"),result ) );
    return result;
    }

// ---------------------------------------------------------
// CCookie::IsUnknownVersion
// ---------------------------------------------------------
//
TBool CCookie::IsUnknownVersion() const
    {
    CLOG( ( ECookie, 0, _L( "-> CCookie::IsUnknownVersion ") ) );
    TBool unknownVersion( EFalse );
    THTTPHdrVal attrVal;
    if( Attribute( CCookie::EVersion, attrVal ) != KErrNotFound )
        {
        if( attrVal.StrF().DesC().Compare( KCookieKnownVersion() ) != 0 )
            {
            unknownVersion = ETrue;
            }
        }
    CLOG( ( ECookie, 0, _L( "<- CCookie::IsUnknownVersion unknownVersion : %d"),unknownVersion ) );
    return unknownVersion;
    }

// ---------------------------------------------------------
// CCookie::CCookie
// ---------------------------------------------------------
//
CCookie::CCookie( RStringPool aStringPool )
: iStringPool( aStringPool ), iSetCookie2( EFalse ), iNetscape( EFalse )
	{
	CLOG( ( ECookie, 0, _L( "-> CCookie::CCookie ") ) );
	iReceivedTime.UniversalTime();
	CLOG( ( ECookie, 0, _L( "<- CCookie::CCookie ") ) );
	}


// ---------------------------------------------------------
// CCookie::ConstructL
// ---------------------------------------------------------
//
void CCookie::ConstructL( RHTTPHeaders aRequestHeaders, TInt aPartIndex,
						RStringF aFieldName, const TUriC8& aUri )
	{
	CLOG( ( ECookie, 0, _L( "-> CCookie::ConstructL ") ) );
	const TStringTable& commonStringTable = RHTTPSession::GetTable();

	// Determining if this object is constructed from a Set-Cookie2 HTTP header
	RStringF setCookie2Name = iStringPool.StringF( HTTP::ESetCookie2,
                                                   commonStringTable );

	iSetCookie2 = ( aFieldName == setCookie2Name );

    TBool defaultDiscard( EFalse );

	THTTPHdrVal hVal;

	// Retrieval of NAME attribute
    // ---------------------------------------------------------
	// retrieving Name atribute
    // ---------------------------------------------------------
	if ( aRequestHeaders.GetParam( aFieldName,
									iStringPool.StringF( HTTP::ECookieName,
														commonStringTable ),
									hVal,
									aPartIndex ) == KErrNone )
		{
		SetAttribute( EName, hVal );	// ignore the result of this method
		}

    // ---------------------------------------------------------
	// retrieving Value atribute
    // ---------------------------------------------------------
	if ( aRequestHeaders.GetParam( aFieldName,
									iStringPool.StringF( HTTP::ECookieValue,
														commonStringTable ),
									hVal,
									aPartIndex ) == KErrNone )
		{
		SetAttribute( EValue, hVal );	// ignore the result of this method
		}

    // now get the VERSION attribute.
    // if it is there, then it is either RFC 2109 or RFC 2965
    // if it is not there, then it is NETSCAPE style cookie
    // ---------------------------------------------------------
	// retrieving Version atribute
    // ---------------------------------------------------------
	if ( aRequestHeaders.GetParam(
                        aFieldName, 
                        iStringPool.StringF( HTTP::EVersion,
											commonStringTable ), 
                        hVal, aPartIndex ) == KErrNone )
        {
        iNetscape = EFalse;
		SetAttribute( EVersion, hVal );	// ignore the result of this method
        }
    else
        {
        iNetscape = ETrue;
        }

    // now get common attributes for all
    // that is, Path, Domain, Secure
	// Add Path attribute if it exists + defaulting
    // ---------------------------------------------------------
	// retrieving Path atribute
    // ---------------------------------------------------------
    if ( aRequestHeaders.GetParam(
                            aFieldName, 
                            iStringPool.StringF( HTTP::EPath,
												commonStringTable ), 
                            hVal, aPartIndex ) == KErrNone )
        {
		SetAttribute( EPath, hVal );	// ignore the result of this method
        }
    else
        {
		// defaulting
		AddDefaultPathL( aUri );
        }

    // ---------------------------------------------------------
	// retrieving Domain atribute
    // ---------------------------------------------------------
	if ( aRequestHeaders.GetParam(
                            aFieldName, 
                            iStringPool.StringF( HTTP::EDomain,
												commonStringTable ), 
                            hVal, aPartIndex ) == KErrNone && hVal.StrF().DesC().Length() > 0)
        {
		SetAttribute( EDomain, hVal );	// ignore the result of this method
        }
    else
        { // Default handling 
        // in this case the default is the effective request host        
        RStringF defDomain =
						iStringPool.OpenFStringL( aUri.Extract( EUriHost ) );
        THTTPHdrVal defdomVal( defDomain );
		SetAttribute( EDomain, defdomVal, ETrue );// ignore the result 
        defDomain.Close();
        }

    // ---------------------------------------------------------
	// retrieving Secure atribute
    // ---------------------------------------------------------
	if ( aRequestHeaders.GetParam( 
                        aFieldName, 
                        iStringPool.StringF( HTTP::ESecure,
											commonStringTable ), 
                        hVal, aPartIndex ) == KErrNone )
        {
		SetAttribute( ESecure, hVal );	// ignore the result of this method
        }
    else
        { // Default handling if applies
		// if not present, then cookie is not 'secure'
		// no action here as if attribute is not present, 
		// cookie might be sended by default.
        }


    // now if it is Netscape, get Netscape specific parts
    if ( iNetscape )
        {
        // that is, Expires
        // ---------------------------------------------------------
	    // retrieving Expires atribute
        // ---------------------------------------------------------
        if ( aRequestHeaders.GetParam(
                            aFieldName, 
                            iStringPool.StringF( HTTP::EExpires,
											    commonStringTable ), 
                            hVal, aPartIndex ) == KErrNone )
            {
		    SetAttribute( EExpires, hVal );	// ignore the result of this method
            }
        //----------------------------------------------------------- 
        // Default handling is does not applies.
		// Reference: error ID:ESAN-6XWHRL
		// If "version" is not present but "max-age/comment" is present
		// then we can considere cookie as RFC 2109 or RFC 2965 type 
        else if(( aRequestHeaders.GetParam( aFieldName, 
								iStringPool.StringF( HTTP::EComment,
	                            commonStringTable ), 
	                            hVal, aPartIndex ) == KErrNone ) ||
	           ( aRequestHeaders.GetParam( aFieldName, 
	                            iStringPool.StringF( HTTP::EMaxAge,
								commonStringTable ),
	                            hVal, aPartIndex ) == KErrNone ))
				{
					// Not a NETSCAPE style cookie
					iNetscape = EFalse;
				}
        }
		
    // ---------------------------------------------------------
    // retrieving Date atribute
    // ---------------------------------------------------------
	// get the Date header field name 
	RStringF dateFieldName = iStringPool.StringF( HTTP::EDate,
                                                  commonStringTable );
    if ( aRequestHeaders.GetField( dateFieldName, 0, hVal) == KErrNone ) 

        {
	    SetAttribute( EDate, hVal );	// ignore the result of this method
        }
    else 

    // as the expiration comparison is based on the UniversalTime,
    // we use the curreent (arriving time) for the cookie's born time too. :-)
        { // Add default handling if applies
        TTime nowTime;
        nowTime.UniversalTime();
        // TDateTime dateTime( nowTime.DateTime() );
        hVal.SetDateTime( nowTime.DateTime() );
        SetAttribute( EDate, hVal );
        }
    if( EFalse == iNetscape )
        {
        // now get RFC SetCookie and SetCookie2 common parts
        // that is, Comment, Max-Age
        // get EDate to be able to calculate cookie age if needed.
        // ---------------------------------------------------------
	    // retrieving Comment atribute
        // ---------------------------------------------------------
	    if ( aRequestHeaders.GetParam( aFieldName, 
                                       iStringPool.StringF( HTTP::EComment, 
                                                            commonStringTable ), 
                                       hVal, aPartIndex ) == KErrNone )
            {
		    SetAttribute( EComment, hVal );	// ignore the result of this method
            }
        else
            { // Add default handling if applies
		    // no defaulting for EComment
            }
        
        // ---------------------------------------------------------
	    // retrieving Max-Age atribute
        // ---------------------------------------------------------
        if ( aRequestHeaders.GetParam( 
                                aFieldName, 
                                iStringPool.StringF( HTTP::EMaxAge,
												    commonStringTable ),
                                hVal, aPartIndex ) == KErrNone )
            {
		    SetAttribute( EMaxAge, hVal );	// ignore the result of this method
            }
        else
            { // Add default handling if applies
            // Defaults to Discard, discard the cookie on agent termination
            // -> transient cookie
            // in case of SetCookie2, also set Discard, defaulted
            if ( iSetCookie2 )
                {
                defaultDiscard = ETrue;
                }
           }

        // now if it is SetCookie2, than get SetCookie2 specific parts
        if ( iSetCookie2 )
            {
            // that is, CommentUrl, Discard, Port
            // ---------------------------------------------------------
	        // retrieving CommentURL atribute
            // ---------------------------------------------------------
	        if ( aRequestHeaders.GetParam( aFieldName, 
                                           iStringPool.StringF( HTTP::ECommentURL, 
                                                                commonStringTable ), 
                                           hVal, aPartIndex ) == KErrNone )
                {
		        SetAttribute( ECommentURI, hVal );	// ignore the result of this method
                }
            else
                { // Add default handling if applies
		        // no defaulting for ECommentURL
                }

            // ---------------------------------------------------------
	        // retrieving Discard atribute
            // ---------------------------------------------------------
	        if ( aRequestHeaders.GetParam( 
                                    aFieldName, 
                                    iStringPool.StringF( HTTP::EDiscard,
												        commonStringTable ),
                                    hVal, aPartIndex ) == KErrNone )
                {
		        SetAttribute( EDiscard, hVal );	// ignore the result of this method
                }
            else
                { // Add default handling if applies
		        // no defaulting for EDiscard
                // only if it is caused by MAx-Age beeing not supplied
                if ( defaultDiscard )
                    {
		            RStringF emptyStr = iStringPool.OpenFStringL( KNullDesC8() );
                    THTTPHdrVal emptyVal( emptyStr );
    		        SetAttribute( EDiscard, emptyVal, ETrue );
	    	        emptyStr.Close();
                    }
                }

	        // Add Port attribute if it exists + defaulting
            // ---------------------------------------------------------
	        // retrieving Port atribute
            // ---------------------------------------------------------
	        if ( aRequestHeaders.GetParam( aFieldName, 
								        iStringPool.StringF( HTTP::ECookiePort,
													        commonStringTable ),
								        hVal,
								        aPartIndex ) == KErrNone )
                {
		        // if it is a string and contains at least 1 character, then store it
		        if ( ( hVal.Type() == THTTPHdrVal::KStrFVal &&
				        hVal.StrF().DesC().Length() ) ||
			        ( hVal.Type() == THTTPHdrVal::KStrVal &&
				        hVal.Str().DesC().Length() ) )
			        {
			        SetAttribute( EPort, hVal, ETrue );	// ignore the result of this method
			        }
		        else	// the Port attrib is either empty or incorrect
			        {
			        RStringF requestPort;
			        if ( aUri.IsPresent( EUriPort ) )
				        {
				        requestPort =
						        iStringPool.OpenFStringL( aUri.Extract( EUriPort ) );
				        }
			        else
				        {
				        requestPort = iStringPool.OpenFStringL
											        ( KCookieDefaultRequestPort() );
				        }

			        THTTPHdrVal reqPort( requestPort );

			        SetAttribute( EPort, reqPort, ETrue ); // ignore the result 

			        requestPort.Close();
			        }
                }
            else
                {
		        // if the Port attrib does not exist, leave it blank
                }
            }
        }
    CLOG( ( ECookie, 0, _L( "<- CCookie::ConstructL ") ) );
	}



// ---------------------------------------------------------
// CCookie::FindAttribute
// ---------------------------------------------------------
//
TInt CCookie::FindAttribute( TCookieAttributeName aAttributeName,
							TCookieAttribute& aAttribute ) const
	{
	CLOG( ( ECookie, 0, _L( "-> CCookie::FindAttribute ") ) );
	const TInt numAttributes = iAttributes.Count();
	for ( TInt index = 0; index < numAttributes; ++index )
		{
		if ( iAttributes[index].Name() == aAttributeName )
			{
			aAttribute = iAttributes[index];
			CLOG( ( ECookie, 0, _L( "<- CCookie::FindAttribute index : %d"),index ) );
			return index;
			}
		}
	CLOG( ( ECookie, 0, _L( "<- CCookie::FindAttribute KErrNotFound") ) );
	return KErrNotFound;
	}

// ---------------------------------------------------------
// CCookie::RemoveAttribute
// ---------------------------------------------------------
//
void CCookie::RemoveAttribute( TInt aIndex )
	{
	CLOG( ( ECookie, 0, _L( "-> CCookie::RemoveAttribute aIndex : %d"),aIndex ) );
	iSize -= ( KCookieAttributePrefixLength + iAttributes[ aIndex ].Size() + 
               KCookieAttributeDefaultedLength + 
               KCookieAttributeFoundLength );
	iAttributes[ aIndex ].Close();
	iAttributes.Remove( aIndex );
	CLOG( ( ECookie, 0, _L( "<- CCookie::RemoveAttribute aIndex : %d"),aIndex ) );
	}

// ---------------------------------------------------------
// CCookie::RemoveAttribute
// ---------------------------------------------------------
//
void CCookie::RemoveAttribute( TCookieAttributeName aAttributeName )
    {
    CLOG( ( ECookie, 0, _L( "-> CCookie::RemoveAttribute - name: %d"), aAttributeName ) );
    TCookieAttribute attribute;
    TInt index( FindAttribute( aAttributeName, attribute ) );
    if( index != KErrNotFound )
        {
        RemoveAttribute( index );
        }
    CLOG( ( ECookie, 0, _L( "<- CCookie::RemoveAttribute - name: %d, index: %d"), aAttributeName, index ) );
    }

// ---------------------------------------------------------
// CCookie::GetLocalOffset
// ---------------------------------------------------------
//
TInt CCookie::GetLocalOffset( HBufC8* aDate, TInt& aHour, 
                         TInt& aMinute, TInt& aLength ) const
    {
    CLOG( ( ECookie, 0, _L( "-> CCookie::GetLocalOffset ") ) );
    TInt retval( 0 );
    TInt pos(0);
//    TInt fwspos(0);
//    TBool plus( ETrue );
    TPtrC8 datePtr( aDate->Des() );


    TLex8 lex( datePtr );
    TInt oldoffset( 0 );
    TInt curroffset( 0 );
    TInt i( 0 );
    TInt tokencount( 0 );
    TInt deltaoffset( 0 );
    // firstoffset is to store the first token length/endposition
    TInt firstoffset( 0 );
    TBool repeat( ETrue );
    do
        {
        lex.SkipCharacters();
        curroffset = lex.Offset();
        deltaoffset = curroffset-oldoffset;
        if ( deltaoffset )
            {
            if ( !tokencount )
                {
                firstoffset = deltaoffset;
                }
            for(i=0; i<deltaoffset; i++)
                {
                lex.Get();
                }
            tokencount++;
/*
            if ( deltaoffset != aDate->Length() )
                {
                tokencount++;
                }
*/
            oldoffset = curroffset;
            }
        else
            { // end of string, oldoffset1 holds position
            repeat = EFalse;
            }
        }while (repeat);



    pos = aDate->LocateReverse( KLocalTimeZoneSeparator1 );

    if ( pos > 0 )
        { // found at least one "+"        
//        plus = ETrue;
        }
    else
        {
        pos = aDate->LocateReverse( KLocalTimeZoneSeparator2 );
        if ( pos > 0 )
            { // found at least one "-"
            // now check if it is in the date...
            // if it is in the date part, then we did found only one tokens...
            // and the position MUST be larger than the end of 
            // the first token (date)...
            if ( ( tokencount > 1) && ( firstoffset < pos ) )
                {
//                plus = EFalse;
                }
            else
                {
                pos = KErrNotFound;
                retval = KErrNotFound;
                }
            }
        else
            {
            retval = KErrNotFound;
            }
        }
    if ( pos > 0 )
        {
        // get the length
        aLength = aDate->Length()-pos;
        // now get the offset
        HBufC8* temp = aDate->Right( aLength ).AllocLC();
        temp->Des().Trim();
        TLex8 lex(temp->Left(2));
        lex.Val( aHour );
        TLex8 lex1(temp->Right(2));
        lex1.Val( aMinute );
        CleanupStack::PopAndDestroy( temp ); // temp
        }
    CLOG( ( ECookie, 0, _L( "<- CCookie::GetLocalOffset retval : %d "),retval ) );
    return retval;
    }




// ---------------------------------------------------------
// CCookie::GetMilitaryOffset
// ---------------------------------------------------------
//
TInt CCookie::GetMilitaryOffset( HBufC8* /*aDate*/, TInt& aHour ) const
    {
    CLOG( ( ECookie, 0, _L( "-> CCookie::GetMilitaryOffset  ") ) );
    // TODO: Add military timezone handling here...
    TInt retval( KErrNotFound );
    aHour = 0;
    CLOG( ( ECookie, 0, _L( "<- CCookie::GetMilitaryOffset retval : %d "),retval ) );
    return retval;
    }



// ---------------------------------------------------------
// CCookie::GetTimeZone
// ---------------------------------------------------------
//
TInt CCookie::GetTimeZone( HBufC8* aDate, TInt& aHour, 
                         TInt& aLength ) const
    {
    CLOG( ( ECookie, 0, _L( "-> CCookie::GetTimeZone  ") ) );
    TInt retval( 0 );
    TInt zonepos = aDate->Find( KUT() );
    if ( zonepos != KErrNotFound )
        {
        aHour = 0;
        }
    else
        {
        zonepos = aDate->Find( KGMT );
        if ( zonepos  != KErrNotFound )
            {
            aHour = 0;
            }
        else
            {
            zonepos = aDate->Find( KEST );
            if ( zonepos  != KErrNotFound )
                {
                aHour = -5;
                }
            else
                {
                zonepos = aDate->Find( KEDT );
                if ( zonepos  != KErrNotFound )
                    {
                    aHour = -4;
                    }
                else
                    {
                    zonepos = aDate->Find( KCST );
                    if ( zonepos  != KErrNotFound )
                        {
                        aHour = -6;
                        }
                    else
                        {
                        zonepos = aDate->Find( KCDT );
                        if ( zonepos  != KErrNotFound )
                            {
                            aHour = -5;
                            }
                        else
                            {
                            zonepos = aDate->Find( KMST );
                            if ( zonepos  != KErrNotFound )
                                {
                                aHour = -7;
                                }
                            else
                                {
                                zonepos = aDate->Find( KMDT );
                                if ( zonepos  != KErrNotFound )
                                    {
                                    aHour = -6;
                                    }
                                else
                                    {
                                    zonepos = aDate->Find( KPST );
                                    if ( zonepos  != KErrNotFound )
                                        {
                                        aHour = -8;
                                        }
                                    else
                                        {
                                        zonepos = aDate->Find( KPDT );
                                        if ( zonepos  != KErrNotFound )
                                            {
                                            aHour = -7;
                                            }
                                        else
                                            { 
                                            retval = KErrNotFound;
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

    if ( zonepos != KErrNotFound )
        {
        // get the length
        aLength = aDate->Length() - zonepos;
        }
    CLOG( ( ECookie, 0, _L( "<- CCookie::GetTimeZone retval :%d "),retval ) );
    return retval;
    }



// ---------------------------------------------------------
// CCookie::GetCleanedDateTimeLC
// ---------------------------------------------------------
//
HBufC8* CCookie::GetCleanedDateTimeLC( HBufC8* aDate ) const
    {
    CLOG( ( ECookie, 0, _L( "-> CCookie::GetCleanedDateTimeLC ") ) );
    // as http time might contain a "DayOfWeek," optional part
    // which is not understood by the parser, we need to 
    // remove it 
    TInt pos = aDate->Locate( KDayOfWeekSeparator );
    if ( pos < 0 )
        {
        pos = 0;
        }
    else 
        {
        if ( pos )
            {
            pos++;
            }
        }
    
    HBufC8* result = HBufC8::NewLC( aDate->Length() ); 
    HBufC8* temp = aDate->Mid( pos ).AllocLC();
    // reduce multiple spaces
    temp->Des().TrimAll();

    // now try to remove time zone values...    
    TInt hour( 0 );
    TInt minute( 0 );
    TInt length( 0 );

    // Accordign to RFC 2822, the correct date-time syntax:
    // [dayofweek","] date FWS time [CFWS]
    // where:
    // date :   day month year
    // time :   time-of-day FWS zone
    //
    // zone :   (( "+" / "-" ) 4DIGIT) / obs-zone
    // obs-zone : "GMT", "UT", "EST", "EDT", "CST", "CDT", 
    //            "MST", "MDT", "PST", "PDT"
    //           and the military 1 letter version
    // so first try to get the +/-hhmm format...
    // check if time is locale offset in +/- HHMM form
    if ( GetLocalOffset( temp, hour, minute, length ) == KErrNotFound )
        { 
        // not a local offset, check if it is one of the 
        // known 2 or three digit ones
        if ( GetTimeZone( temp, hour, length ) == KErrNotFound )
            {
            //Not, check if it is Military, 
            //which is a one digit ALPHA
            if ( GetMilitaryOffset( temp, hour ) == KErrNotFound )
                {
                // not a military one, 
                // error, unknown time zone or none...
                }
            else
                { // Military offset
                length = 1;
                }
            }
        else
            {// other know one
            }
        }
    else
        { // locale offset
        }
    *result = temp->Left( temp->Length() - length);
    // return ( temp->Left( temp->Length() - length).AllocLC() );
    CleanupStack::PopAndDestroy( temp );
    CLOG( ( ECookie, 0, _L( "-> CCookie::GetCleanedDateTimeLC result : %d"),result ) );
    return result;
    }






// ---------------------------------------------------------
// CCookie::TCookieAttribute::TCookieAttribute
// ---------------------------------------------------------
//
CCookie::TCookieAttribute::TCookieAttribute( TCookieAttributeName aName,
											const THTTPHdrVal& aHdrVal, 
											TBool aDefaulted )
: iName( aName ),
iDefaulted( aDefaulted )
	{
	CLOG( ( ECookie, 0, _L( "-> CCookie::TCookieAttribute") ) );
	iValue = aHdrVal.Copy();
	

	switch ( iValue.Type() )
		{
		case THTTPHdrVal::KTIntVal :
			{
			iSize = sizeof( TInt );
			CLOG( ( ECookie, 0, _L( "-> CCookie::TCookieAttribute iSize :%d "),iSize ) );
			break;
			}
		case THTTPHdrVal::KStrVal :
			{
			iSize = iValue.Str().DesC().Length();
			CLOG( ( ECookie, 0, _L( "-> CCookie::TCookieAttribute iSize :%d "),iSize ) );
			break;
			}
		case THTTPHdrVal::KDateVal :
			{
			iSize = sizeof( TDateTime );
			CLOG( ( ECookie, 0, _L( "-> CCookie::TCookieAttribute iSize :%d "),iSize ) );
			break;
			}
		case THTTPHdrVal::KStrFVal :
			{
			iSize = iValue.StrF().DesC().Length();
			CLOG( ( ECookie, 0, _L( "-> CCookie::TCookieAttribute iSize :%d "),iSize ) );
			break;
			}
		default :	// THTTPHdrVal::KNoType
			{
			iSize = 0;
			CLOG( ( ECookie, 0, _L( "-> CCookie::TCookieAttribute iSize :%d "),iSize ) );
			}
		}
	CLOG( ( ECookie, 0, _L( "<- CCookie::TCookieAttribute  ") ) );
	}


// ---------------------------------------------------------
// CCookie::TCookieAttribute::TCookieAttribute
// ---------------------------------------------------------
//
CCookie::TCookieAttribute::TCookieAttribute()
	{
	CLOG( ( ECookie, 0, _L( "-> CCookie::TCookieAttribute  ") ) );
	CLOG( ( ECookie, 0, _L( "<- CCookie::TCookieAttribute  ") ) );
	}


// ---------------------------------------------------------
// CCookie::TCookieAttribute::Close
// ---------------------------------------------------------
//
void CCookie::TCookieAttribute::Close()
	{
	CLOG( ( ECookie, 0, _L( "-> CCookie::Close  ") ) );
	THTTPHdrVal::THTTPValType type = iValue.Type();
	if ( type == THTTPHdrVal::KStrVal )
		{
		CLOG( ( ECookie, 0, _L( "-> CCookie::Close  KStrVal") ) );
		iValue.Str().Close();
		}
	else if ( type == THTTPHdrVal::KStrFVal )
		{
		CLOG( ( ECookie, 0, _L( "-> CCookie::Close  KStrFVal") ) );
		iValue.StrF().Close();
		}

	// TBD : iValue = THTTPHdrVal();?
	iSize = 0;
	CLOG( ( ECookie, 0, _L( "<- CCookie::Close  ") ) );
	}


// ---------------------------------------------------------
// CCookie::TCookieAttribute::Name
// ---------------------------------------------------------
//
CCookie::TCookieAttributeName CCookie::TCookieAttribute::Name() const
	{
	return iName;
	}

// ---------------------------------------------------------
// CCookie::TCookieAttribute::Size
// ---------------------------------------------------------
//
TInt CCookie::TCookieAttribute::Size() const
	{
	return iSize;
	}


// ---------------------------------------------------------
// CCookie::TCookieAttribute::Defaulted
// ---------------------------------------------------------
//
TBool CCookie::TCookieAttribute::Defaulted() const
	{
	return iDefaulted;
	}

// ---------------------------------------------------------
// CCookie::TCookieAttribute::Value
// ---------------------------------------------------------
//
const THTTPHdrVal& CCookie::TCookieAttribute::Value() const
	{
	return iValue;
	}