gba/gbaserver/src/dataretriever.cpp
changeset 0 164170e6151a
child 5 3b17fc5c9564
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gba/gbaserver/src/dataretriever.cpp	Tue Jan 26 15:20:08 2010 +0200
@@ -0,0 +1,1358 @@
+/*
+* Copyright (c) 2007 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 bootstrap and data retriever
+*
+*/
+
+
+#include <e32math.h> 
+#include <hash.h>
+#include <commdb.h>
+#include <es_enum.h>
+#include <centralrepository.h>
+#include <cmconnectionmethodext.h>
+#include <cmconnectionmethoddef.h>
+#include <cmpluginpacketdatadef.h>
+#include <cmdestinationext.h>
+#include <http/thttpevent.h>
+#include "dataretriever.h"
+#include "GbaCommon.h"
+#include "GBALogger.h"
+#include "bootstrap.h"	 
+
+_LIT8(KUserAgent,"S60 GBA 1.0");
+_LIT8(KAccept,"*/*");
+_LIT8(KNCVal_2, ":00000001:");
+_LIT8(Kfopaque,"");
+_LIT8(Kfalgo,"AKAv1-MD5");
+_LIT8(Kalgorithm,"algorithm");
+_LIT8(formatStr, "%02x");
+_LIT8(KAuthInt,"auth-int");
+_LIT8(KAuts,"auts");
+_LIT8(KHTTPAuthInfo,"Authentication-Info");
+_LIT8(KMD5HashofEmpty,"d41d8cd98f00b204e9800998ecf8427e");
+_LIT8(KClose, "Close");
+_LIT(KColon, ":");
+
+
+//Constants
+const TInt KNumber3 = 3;
+const TInt KNumber5 = 5;
+const TInt KNumber8 = 8;
+const TInt KNumber32 = 32;
+const TInt KNumber33 = 33;
+const TInt KNumber34 = 34;
+// Length of a digest hash when represented in hex
+const TInt KHashLength = 32;
+// Length of a digest hash before converting to hex.
+const TInt KRawHashLength = 16;
+const TInt KMaxRequestBuffer = 255;
+const TInt KAlgLength = 40;
+
+// ---------------------------------------------------------------------------
+// CDataRetriever::NewL()
+// ---------------------------------------------------------------------------
+//
+CDataRetriever* CDataRetriever::NewL( MBootstrapCallBack* aBootstrapCallBack )
+    {
+    CDataRetriever* self = NewLC( aBootstrapCallBack );
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+
+// ---------------------------------------------------------------------------
+// CDataRetriever::NewLC()
+// ---------------------------------------------------------------------------
+//
+CDataRetriever* CDataRetriever::NewLC( MBootstrapCallBack* aBootstrapCallBack )
+    {
+    CDataRetriever* self = new (ELeave) CDataRetriever( aBootstrapCallBack ) ;
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    return self;
+    }
+
+
+// ---------------------------------------------------------------------------
+// CDataRetriever::CDataRetriever()
+// ---------------------------------------------------------------------------
+//
+CDataRetriever::CDataRetriever( MBootstrapCallBack* aBootstrapCallBack ) 
+    : iBootstrapCallBack( aBootstrapCallBack ) 
+    { 
+    }
+    
+    
+// ---------------------------------------------------------------------------
+// CDataRetriever::ConstructL()
+// ---------------------------------------------------------------------------
+//
+void CDataRetriever::ConstructL()
+    {
+    iHttpHandler = C3GPPBootstrapHttpHandler::NewL( this, iBootstrapCallBack );
+    iInternalState = EReadyForRequest;
+    iCmManagerExt.OpenL();
+    }
+
+
+// ---------------------------------------------------------------------------
+// CDataRetriever::~CDataRetriever()
+// ---------------------------------------------------------------------------
+//
+CDataRetriever::~CDataRetriever()
+    {
+    GBA_TRACE_DEBUG(("CDataRetriever::~CDataRetriever"));
+    
+    delete iHttpHandler;
+    iHTTPTransaction.Close();
+    iHTTPSession.Close();
+    iConnection.Close();
+    iSockServ.Close();
+    iCmManagerExt.Close();
+    
+    if ( iInternalState == EMakeRequestCalled )
+        {
+        GBA_TRACE_DEBUG(("CDataRetriever::~CDataRetriever EMakeRequestCalled"));
+        User::RequestComplete(iCallerRequestStatus, KErrCancel);
+        }
+    
+    GBA_TRACE_DEBUG(("CDataRetriever::~CDataRetriever End"));
+    }
+
+// ---------------------------------------------------------------------------
+// CDataRetriever::EventRequestCompletedL()
+// ---------------------------------------------------------------------------
+//
+void CDataRetriever::EventRequestCompletedL(TInt aErrorCode)
+    {
+    GBA_TRACE_DEBUG(("CDataRetriever::EventRequestCompletedL enter"));
+    
+    if ( iInternalState == EMakeRequestCalled )
+        {
+        GBA_TRACE_DEBUG(("CDataRetriever::EventRequestCompletedL EMakeRequestCalled"));
+
+        TRAPD( err, iBootstrapCallBack->CompleteBootStrappingL( aErrorCode ) );
+        if( err == KErrNone )
+            User::RequestComplete(iCallerRequestStatus,aErrorCode);
+        else
+            User::RequestComplete(iCallerRequestStatus, err);
+        // Get Ready for new request
+        iHttpHandler->Reset();
+        iHTTPTransaction.Close();
+        iHTTPSession.Close();
+        iConnection.Close();
+        iSockServ.Close();
+        iInternalState = EReadyForRequest;
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// CDataRetriever::CancelRequest()
+// ---------------------------------------------------------------------------
+//
+void CDataRetriever::CancelRequest()
+    {
+    GBA_TRACE_DEBUG(("CDataRetriever::CancelRequest"));
+    if ( iInternalState == EMakeRequestCalled )
+        {        
+        iInternalState = EReadyForRequest;
+        iHttpHandler->Reset();
+        iHTTPTransaction.Close();
+        iHTTPSession.Close();
+        iConnection.Close();
+        iSockServ.Close();
+        User::RequestComplete( iCallerRequestStatus, KErrCancel );
+        }
+    }
+    
+    
+// ---------------------------------------------------------------------------
+// CDataRetriever::MakeRequestL()
+// ---------------------------------------------------------------------------
+//
+void CDataRetriever::MakeRequestL(
+                 TRequestStatus* aRequestStatus,
+                 const TDesC8& aIdentity,
+                 const TDesC8& aRealm,
+                 const TDesC8& aBsfUri,
+                 const TDesC8& aReferrerNAFUri,
+                 const TInt& aIAPID )
+    {
+    GBA_TRACE_BEGIN(); 
+    
+    if ( iInternalState != EReadyForRequest )
+        {        
+        User::LeaveIfError( KErrInUse );
+        }
+    
+    iCallerRequestStatus = aRequestStatus;
+  
+    SetupSessionL( aIAPID );
+
+    // Add headers appropriate to all methods
+    TUriParser8 URIParse; 
+
+    User::LeaveIfError( URIParse.Parse( aBsfUri ) );
+
+    iHTTPTransaction = iHTTPSession.OpenTransactionL( URIParse, *iHttpHandler );
+    RHTTPHeaders hdr = iHTTPTransaction.Request().GetHeaderCollection();
+    
+    GBA_TRACE_DEBUG(URIParse.Extract(EUriHost) );
+         
+    SetHeaderL(hdr,HTTP::EHost, URIParse.Extract(EUriHost) );     
+    SetHeaderL(hdr,HTTP::EUserAgent, KUserAgent);
+    SetHeaderL(hdr,HTTP::EAccept, KAccept);     
+    SetHeaderL(hdr,HTTP::EReferer, aReferrerNAFUri);
+    
+    SetHeaderL(hdr, HTTP::EConnection, KClose);
+  
+    TBuf8<KMaxRequestBuffer> bufAuth;
+    bufAuth.Copy(_L8("Digest username=\""));
+    bufAuth.Append(aIdentity);
+    bufAuth.Append(_L8("\", realm=\""));
+    
+    bufAuth.Append(aRealm);
+    bufAuth.Append(_L8("\", nonce=\"\", uri=\"/\", response=\"\""));
+
+    GBA_TRACE_DEBUG(bufAuth);
+    SetHeaderL(hdr,HTTP::EAuthorization,bufAuth);
+    
+    iHTTPTransaction.SubmitL();    
+    iInternalState = EMakeRequestCalled;
+    GBA_TRACE_END();
+    }
+
+// ---------------------------------------------------------------------------
+// CDataRetriever::SetHeaderL()
+// ---------------------------------------------------------------------------
+//
+void CDataRetriever::SetHeaderL(RHTTPHeaders aHeaders, TInt aHdrField, const TDesC8& aHdrValue)
+    {
+    RStringF valStr = iHTTPSession.StringPool().OpenFStringL(aHdrValue);
+    THTTPHdrVal val(valStr);
+    aHeaders.SetFieldL(iHTTPSession.StringPool().StringF(aHdrField,RHTTPSession::GetTable()), val);
+    valStr.Close();
+    }
+
+// ---------------------------------------------------------------------------
+// CDataRetriever::SetupSessionL()
+// Establish a connection for bootstrapping
+// ---------------------------------------------------------------------------
+//
+void CDataRetriever::SetupSessionL( const TInt& aIAPID )
+    {
+    GBA_TRACE_DEBUG(("CDataRetriever::SetupSession"));
+    // check that sockserver is available
+
+    User::LeaveIfError(iSockServ.Connect() );
+    GBA_TRACE_DEBUG(("Socket server connected")); 
+
+    // check that connection is possible
+    User::LeaveIfError(iConnection.Open(iSockServ) );
+    GBA_TRACE_DEBUG(("Connection opened")); 
+    
+    if ( !ValidateGivenIAPIDL( aIAPID ) )
+        {	
+        GBA_TRACE_DEBUG(("No valid iapid from user")); 
+        TConnSnapPref snapPref;
+        TUint32 snapid = GetInternetDestIDL();
+        GBA_TRACE_DEBUG_NUM(("the chosen snap id is %d"), snapid ); 
+        snapPref.SetSnap( snapid );
+        TInt err = iConnection.Start( snapPref );
+        
+        if ( err != KErrNone )
+            {
+            GBA_TRACE_DEBUG_NUM(("internet nap error is %d"), err ); 
+            TCommDbConnPref connPref;
+            connPref.SetDialogPreference( ECommDbDialogPrefPrompt );
+            User::LeaveIfError( iConnection.Start( connPref ) );
+            }    
+       }
+    else
+        {
+        GBA_TRACE_DEBUG(("User gives valid iapid go with it"));
+        //given iapid is valid, go with it
+        TCommDbConnPref connPref;
+        connPref.SetDirection( ECommDbConnectionDirectionOutgoing );
+        
+        //No dialog present
+        connPref.SetDialogPreference( ECommDbDialogPrefDoNotPrompt );
+        connPref.SetIapId( aIAPID );	
+         
+        User::LeaveIfError( iConnection.Start( connPref ) );
+        }
+    
+    GBA_TRACE_DEBUG(("Access point selection done!"));       
+
+    GBA_TRACE_DEBUG(("CDataRetriever::SetupSession, connect choosen is done "));
+    
+    iHTTPSession.OpenL();
+	    
+    //GBA Http  filter gets loaded into to http session when session is opened
+	//Remove GBA http filter from http session iHTTPSession
+    //Reason: Ub interface should not have the User-Agent string "3gpp-gba"
+	RStringF filterName = iHTTPSession.StringPool().OpenFStringL( KHTTPFilterGBAName );
+    CleanupClosePushL<RStringF>( filterName );
+    iHTTPSession.FilterCollection().RemoveFilter( filterName );
+    CleanupStack::PopAndDestroy( &filterName );
+	
+    GBA_TRACE_DEBUG(("Session opened"));  
+    
+    //Set selected access point.
+    RStringPool strPool = iHTTPSession.StringPool();
+    RHTTPConnectionInfo httpconnInfo = iHTTPSession.ConnectionInfo();
+    
+    httpconnInfo.SetPropertyL ( strPool.StringF(HTTP::EHttpSocketServ,
+            RHTTPSession::GetTable() ), THTTPHdrVal (iSockServ.Handle()) );
+    
+    TInt connPtr = REINTERPRET_CAST(TInt, &iConnection);
+
+    httpconnInfo.SetPropertyL ( strPool.StringF(HTTP::EHttpSocketConnection,
+              RHTTPSession::GetTable() ), THTTPHdrVal (connPtr) );
+    
+    //if 2G interface and cert is untrusted, surpress the warning dialog
+    if ( iBootstrapCallBack->InterfaceIs2G() )
+        {
+        //surpress the warning dialog
+        httpconnInfo.SetPropertyL ( strPool.StringF(HTTP::ESecureDialog,
+              RHTTPSession::GetTable() ),strPool.StringF(HTTP::EDialogNoPrompt,
+              RHTTPSession::GetTable() )  );
+        }
+  
+    GBA_TRACE_DEBUG(("SetupSession done")); 
+    }
+
+
+// ---------------------------------------------------------------------------
+// CDataRetriever::ValidateGivenIAPIDL()
+// ---------------------------------------------------------------------------
+//
+TBool CDataRetriever::ValidateGivenIAPIDL( const TInt& aIAPID )
+    {
+    using namespace CMManager;
+    GBA_TRACE_DEBUG((" start valid iapid given by user"));
+    //aIAPID == -1 selected default accesspoint
+    if ( aIAPID == -1 )
+        {
+        return EFalse;
+        }
+    else
+        {
+        TInt CleanupCounter = 0;
+   
+        RArray<TUint32> destIdArray;
+        CleanupClosePushL( destIdArray );
+        CleanupCounter++;
+        iCmManagerExt.AllDestinationsL( destIdArray );
+
+        for ( TInt i = 0; i< destIdArray.Count(); i++ )
+           {
+           RCmDestinationExt dest = iCmManagerExt.DestinationL( destIdArray[i] );
+           CleanupClosePushL( dest );
+           CleanupCounter++;
+         
+           for ( TInt j=0; j < dest.ConnectionMethodCount(); j++ )
+              {
+           
+              TUint32 iapId = dest. ConnectionMethodL(j).GetIntAttributeL( ECmIapId );
+              
+              if ( iapId == aIAPID )
+                  {
+                  GBA_TRACE_DEBUG((" IAPID matches !!"));
+                  CleanupStack::PopAndDestroy( CleanupCounter );
+                  return ETrue;
+                  }
+              }
+             
+           CleanupStack::PopAndDestroy( &dest ); //dest
+           CleanupCounter--; // dest
+           }
+        GBA_TRACE_DEBUG((" search is over no matching IAPID!!"));
+        CleanupStack::PopAndDestroy( CleanupCounter );
+        return EFalse;    
+        }    
+    }
+
+// ---------------------------------------------------------------------------
+// CDataRetriever::QueryResponseValueL()
+// ---------------------------------------------------------------------------
+//
+HBufC8* CDataRetriever::QueryResponseValueL() 
+    {
+    return iHttpHandler->GetResponse();
+    } 
+
+// ---------------------------------------------------------------------------
+// CDataRetriever::GetInternetDestIDL()
+// ---------------------------------------------------------------------------
+//
+TUint32 CDataRetriever::GetInternetDestIDL()
+    {
+    using namespace CMManager;
+    GBA_TRACE_DEBUG((" Get the Dest ID of Internet"));
+
+    TInt CleanupCounter = 0;
+   
+    RArray<TUint32> destIdArray;
+    CleanupClosePushL( destIdArray );
+    CleanupCounter++;
+    iCmManagerExt.AllDestinationsL( destIdArray );
+
+    for ( TInt i = 0; i< destIdArray.Count(); i++ )
+         {
+         RCmDestinationExt dest = iCmManagerExt.DestinationL( destIdArray[i] );
+         CleanupClosePushL( dest );
+         CleanupCounter++;
+         
+         if ( dest.MetadataL( ESnapMetadataInternet ) )
+             {
+             GBA_TRACE_DEBUG_NUM((" found the internet dest id = %d"), destIdArray[i] );
+             
+             TUint32 desID = destIdArray[i];
+             CleanupStack::PopAndDestroy( CleanupCounter );
+             return desID; 
+             }
+             
+         CleanupStack::PopAndDestroy( &dest );
+         CleanupCounter--; // dest
+         }
+    GBA_TRACE_DEBUG(("not found the internet dest id") );
+    CleanupStack::PopAndDestroy( CleanupCounter );
+    return NULL;
+	}
+    
+
+// C3GPPBootstrapHttpHandler 
+// -----------------------------------------------------------------------------
+// C3GPPBootstrapHttpHandler::ConstructL()
+// -----------------------------------------------------------------------------
+//
+void C3GPPBootstrapHttpHandler::ConstructL()
+    {
+    iResponse=HBufC8::NewL(KMaxBootstrapRespLen);
+    iMD5Calculator =  CMD5::NewL(); 
+    iSucceeded=EFalse;
+    }
+
+// -----------------------------------------------------------------------------
+// C3GPPBootstrapHttpHandler::C3GPPBootstrapHttpHandler()
+// -----------------------------------------------------------------------------
+//
+C3GPPBootstrapHttpHandler::C3GPPBootstrapHttpHandler( MHttpRequestEvents* aEventSink, M3GPPAuthenticationCallback* aDataRetrieverCallBack )
+        : iEventSink ( aEventSink ), iDataRetrieverCallBack ( aDataRetrieverCallBack )
+    {
+    }
+
+
+// -----------------------------------------------------------------------------
+// C3GPPBootstrapHttpHandler::~C3GPPBootstrapHttpHandler()
+// -----------------------------------------------------------------------------
+//
+C3GPPBootstrapHttpHandler::~C3GPPBootstrapHttpHandler()
+    {
+    GBA_TRACE_DEBUG(("C3GPPBootstrapHttpHandler::~C3GPPBootstrapHttpHandler()"));
+    Reset();
+	delete iResponse;
+	delete iMD5Calculator;
+    GBA_TRACE_DEBUG(("C3GPPBootstrapHttpHandler::~C3GPPBootstrapHttpHandler() end"));
+    }
+
+
+
+// -----------------------------------------------------------------------------
+// C3GPPBootstrapHttpHandler::Reset()
+// -----------------------------------------------------------------------------
+//
+void C3GPPBootstrapHttpHandler::Reset()
+    {
+    // close strings in string pool if they were opened 
+    iUsername.Close();
+    iPassword.Close();
+    iNonce.Close();
+    iCnonce.Close();
+    iUri.Close();
+    iRealm.Close();
+    iMethod.Close();
+    }
+
+
+// -----------------------------------------------------------------------------
+// C3GPPBootstrapHttpHandler::NewLC()
+// -----------------------------------------------------------------------------
+//
+C3GPPBootstrapHttpHandler* C3GPPBootstrapHttpHandler::NewLC( MHttpRequestEvents* aEventSink, 
+                                                             M3GPPAuthenticationCallback* aDataRetrieverCallBack )
+    {
+    C3GPPBootstrapHttpHandler* me = new(ELeave)C3GPPBootstrapHttpHandler( aEventSink, aDataRetrieverCallBack );
+    CleanupStack::PushL(me);
+    me->ConstructL();
+    return me;
+    }
+
+
+// -----------------------------------------------------------------------------
+// C3GPPBootstrapHttpHandler::NewL()
+// -----------------------------------------------------------------------------
+//
+C3GPPBootstrapHttpHandler* C3GPPBootstrapHttpHandler::NewL( MHttpRequestEvents* aEventSink ,
+                                                            M3GPPAuthenticationCallback* aDataRetrieverCallBack )
+    {
+    C3GPPBootstrapHttpHandler* me = NewLC(aEventSink, aDataRetrieverCallBack );
+    CleanupStack::Pop(me);
+    return me;
+    }
+
+
+
+// -----------------------------------------------------------------------------
+// C3GPPBootstrapHttpHandler::MHFRunL()
+// -----------------------------------------------------------------------------
+//
+void C3GPPBootstrapHttpHandler::MHFRunL( RHTTPTransaction aTransaction, const THTTPEvent& aEvent )
+    {
+    GBA_TRACE_DEBUG_NUM(("MHFRunL received event %d"), aEvent.iStatus );
+    
+    switch (aEvent.iStatus)
+       {
+       case THTTPEvent::EGotResponseHeaders:
+          {
+          // HTTP response headers have been received. 
+          // We can determine now if there is going to be a response body to save.
+          GBA_TRACE_DEBUG(("THTTPEvent::EGotResponseHeaders"));
+          RHTTPResponse resp = aTransaction.Response();
+          TInt status = resp.StatusCode();
+          
+          RStringF statusStr = resp.StatusText();
+      
+          // 401 = we received a authorization challenge
+          if ( status == HTTPStatus::EUnauthorized )
+             {
+             // resubmit the transaction and hope for the best
+             TInt result = HandleAuthorizationChallengeL(aTransaction, aEvent);
+             if( result == KErrNone )
+                 {
+                 aTransaction.Cancel();
+                 aTransaction.SubmitL();
+                 }
+             else
+                 {
+                 aTransaction.Cancel();
+                 iEventSink->EventRequestCompletedL( result );
+                 }
+             //a new request with password is sent.
+             return;
+             }
+          TInt responseBodySize = 0;
+      
+          // 200 received, succeeded with body
+          if ( resp.HasBody() && ( status == HTTPStatus::EOk ) )
+              {
+              MHTTPDataSupplier *respbody = resp.Body();
+              if ( respbody )
+                  {
+                  responseBodySize = respbody->OverallDataSize();
+                  GBA_TRACE_DEBUG_NUM(("Response body size is %d"), responseBodySize );
+                  iSucceeded = ETrue;
+                  }
+              }
+          //Reallocate iResponse buffer size if the response size is greater than KMaxBootstrapRespLen
+          if( responseBodySize > KMaxBootstrapRespLen )
+              iResponse = iResponse->ReAllocL( responseBodySize );
+          // we take this opportunity to reset our own buffers
+          TPtr8 ptrResp(iResponse->Des());
+          
+          ptrResp.Zero();
+          } 
+          break;
+      
+      case THTTPEvent::EGotResponseBodyData:
+          {
+          GBA_TRACE_DEBUG(("THTTPEvent::EGotResponseBodyData"));
+          // Get the body data supplier
+          iRespBody = aTransaction.Response().Body();
+      
+          // Some (more) body data has been received (in the HTTP response)
+          // Append to the output file if we're saving responses
+          TPtr8 ptrResp(iResponse->Des());
+          
+          TPtrC8 bodyData;
+          TBool lastChunk = EFalse;
+                    
+          while ( !lastChunk ) 
+              {
+              GBA_TRACE_DEBUG(("THTTPEvent::EGotResponseBodyData in loop"));
+              lastChunk = iRespBody->GetNextDataPart( bodyData );
+              
+              //Issue with formatting string with a special character
+              //GBA_TRACE_DEBUG( bodyData );
+              if ( bodyData.Length() <= ( ptrResp.MaxLength() - ptrResp.Length() ) )
+                  { 
+                  ptrResp.Append( bodyData );  
+                  }
+              else
+                  {
+                  break;  
+                  }
+              } 
+      
+          GBA_TRACE_DEBUG_NUM(("Response body received size is %d"), iResponse->Length() );
+          // Done with that bit of body data
+          iRespBody->ReleaseData();
+          } 
+          break;
+          
+      case THTTPEvent::EResponseComplete:
+          {
+          GBA_TRACE_DEBUG(("THTTPEvent::EResponseComplete"));
+          // The transaction's response is complete
+          } 
+          break;
+          
+      case THTTPEvent::ESucceeded:
+         {
+         GBA_TRACE_DEBUG(("THTTPEvent::ESucceeded || KErrDisconnected"));
+         if ( iSucceeded )
+             {
+              // verify authrsp
+              User::LeaveIfError(CheckRspAuthL(aTransaction));
+              
+              //Set it back
+              iSucceeded=EFalse;
+              
+              GBA_TRACE_DEBUG(("THTTPEvent::ESucceeded || KErrDisconnected 1"));
+              iEventSink->EventRequestCompletedL(KErrNone); 
+             }
+         else
+            {
+            iEventSink->EventRequestCompletedL( KErrDisconnected );        
+            GBA_TRACE_DEBUG(("Connection was closed"));
+            }
+        } 
+        break;
+        
+     case THTTPEvent::EFailed:
+        {
+        GBA_TRACE_DEBUG(("THTTPEvent::EFailed"));
+        RHTTPResponse resp = aTransaction.Response();
+        TInt status = resp.StatusCode();
+        GBA_TRACE_DEBUG_NUM( ("http StatusCode : %d "), status );
+        iEventSink->EventRequestCompletedL( KErrUnknown );
+        } 
+        break;
+     
+     //The transaction is being cancelled. An outgoing event. 
+     case THTTPEvent::ECancel:
+        {
+        GBA_TRACE_DEBUG(("THTTPEvent::ECancel"));
+        aTransaction.Cancel();
+        } 
+        break;
+
+     // this warning can come when going through proxies
+     case THTTPEvent::ERedirectedTemporarily:
+        break;
+        
+     default:
+         {
+         GBA_TRACE_DEBUG_NUM(("Failed with HTTP event event: %d "),aEvent.iStatus );
+         if( aEvent.iStatus < 0 )
+             {
+             // close off the transaction if it's an error
+             aTransaction.Cancel();
+             iEventSink->EventRequestCompletedL( aEvent.iStatus );
+             }
+         } 
+         break;
+       }
+    }
+
+
+// -----------------------------------------------------------------------------
+// C3GPPBootstrapHttpHandler::MHFRunError()
+// -----------------------------------------------------------------------------
+// 
+TInt C3GPPBootstrapHttpHandler::MHFRunError(TInt aError, RHTTPTransaction /*aTransaction*/, const THTTPEvent& aEvent)
+    {
+    GBA_TRACE_DEBUG_NUM(("MHFRunError called with error code = %d"), aError);    
+    GBA_TRACE_DEBUG_NUM(("MHFRunError called with http event = %d"),aEvent.iStatus );
+    // tell caller that there was an error
+    TRAPD(err, iEventSink->EventRequestCompletedL(aError));
+    return err;
+    }
+  
+
+// -----------------------------------------------------------------------------
+// C3GPPBootstrapHttpHandler::HandleAuthorizationChallengeL()
+// -----------------------------------------------------------------------------
+// 
+TInt C3GPPBootstrapHttpHandler::HandleAuthorizationChallengeL( RHTTPTransaction aTransaction, const THTTPEvent& /*aEvent*/ )
+    {
+    GBA_TRACE_BEGIN();
+    TInt pushCount = 0;
+    RStringPool stringPool = aTransaction.Session().StringPool(); 
+    RStringF wwwAuthHeader = stringPool.StringF(HTTP::EWWWAuthenticate,RHTTPSession::GetTable());
+    RHTTPHeaders headers(aTransaction.Response().GetHeaderCollection());
+    
+    //find header which has digest algorithm and qop is auth-int
+    TInt headerPart = FindHeaderPartToUseL( aTransaction );
+
+    if ( headerPart == KErrNotFound )
+        {
+        return KErrArgument;
+        }
+
+    THTTPHdrVal authTypeParam;
+    TInt error = headers.GetField( wwwAuthHeader, headerPart, authTypeParam );
+  
+    // If anything goes wrong, just stop. This will have the effect of
+    // returning the error response from the server to the client.
+    if ( error != KErrNone )
+        {
+        return error;     
+        }
+        
+    TBool    haveUserPW = EFalse;
+    RString  realm;
+    RString  username;
+    RString  password;
+    RString  nonce;
+    RString  algorithm;
+    RString  resync;                  
+  
+    // Get realm value from response header
+    THTTPHdrVal realmVal;
+    error  = headers.GetParam( wwwAuthHeader, 
+                           stringPool.StringF( HTTP::ERealm, RHTTPSession::GetTable() ), realmVal, headerPart ) ;
+    if ( error != KErrNone )
+        {
+        return error;
+        }
+    
+    realm = realmVal.Str();
+    GBA_TRACE_DEBUG(("Realm:"));
+    GBA_TRACE_DEBUG(realm.DesC());
+    
+    THTTPHdrVal nonceVal;
+    //Get nonce value from response header
+    // contain the RAND and AUTH
+    error = headers.GetParam( stringPool.StringF(HTTP::EWWWAuthenticate,RHTTPSession::GetTable()), 
+                              stringPool.StringF(HTTP::ENonce,RHTTPSession::GetTable()),
+                              nonceVal,
+                              headerPart);
+    if ( error != KErrNone )
+        {
+        return error;
+        }
+    
+    nonce=nonceVal.Str();
+    GBA_TRACE_DEBUG(("Nonce:"));
+    GBA_TRACE_DEBUG(nonce.DesC());
+  
+    //Fetch algorithm type
+    THTTPHdrVal algVal;  
+    error = headers.GetParam( stringPool.StringF(HTTP::EWWWAuthenticate,RHTTPSession::GetTable()), 
+                              stringPool.StringF(HTTP::EAlgorithm,RHTTPSession::GetTable()),
+                              algVal,
+                              headerPart);
+    if ( error != KErrNone )
+        {
+        return error;
+        }
+    
+    algorithm=algVal.Str();
+    GBA_TRACE_DEBUG(("Algorithm:"));
+    GBA_TRACE_DEBUG(algorithm.DesC());
+    
+    // If the SQN is out of range, Resync is required
+    TBool resyncrequired = EFalse;
+    
+    //Get password from smart card
+    //The smart card will first authenticate the nonce value 
+    RStringF authType = authTypeParam.StrF(); 
+    
+    TRAP( error, haveUserPW = iDataRetrieverCallBack->GetCredentialsL( aTransaction.Request().URI(),
+              realm, nonce, algorithm, username, password, resync, resyncrequired ) ) ;
+    
+    if ( error != KErrNone )
+        {
+        GBA_TRACE_DEBUG_NUM(("Get Gredentails failed with error %d"), error );
+        return error;
+        }
+    
+    if ( haveUserPW || resyncrequired )
+        {
+        CleanupClosePushL(username);
+        pushCount++;
+        CleanupClosePushL(password);
+        pushCount++;       
+        //Resync required
+        if( resyncrequired )
+            {
+            CleanupClosePushL(resync);
+            pushCount++;     
+            }
+        
+        GBA_TRACE_DEBUG(("HandleAuthorizationChallengeL: received following credentials"));
+        GBA_TRACE_DEBUG(("Realm:"));
+        GBA_TRACE_DEBUG(realm.DesC());
+        GBA_TRACE_DEBUG(("Username:"));
+        GBA_TRACE_DEBUG(username.DesC());
+        GBA_TRACE_DEBUG(("Password:"));
+        GBA_TRACE_DEBUG_BINARY(password.DesC());
+        GBA_TRACE_DEBUG(("Resync:"));
+        GBA_TRACE_DEBUG_BINARY(resync.DesC());
+        
+        }
+    else //No password and no resync required
+        {
+        CleanupStack::PopAndDestroy( pushCount ); 
+        return KErrNotFound;  
+        }
+
+    // Encode the Username/Password
+    switch ( authType.Index( RHTTPSession::GetTable() ) )
+        {
+        case HTTP::EDigest:
+           {
+           THTTPHdrVal requestUri;
+           RHTTPTransactionPropertySet propSet = aTransaction.PropertySet();
+           propSet.Property( stringPool.StringF(HTTP::EUri,RHTTPSession::GetTable()), requestUri );
+           //save rsp auth calcuation
+           //Save the string handle for rsp auth checking
+           //Close the previous handle, then set new one
+           iUsername.Close();
+           iUsername = username.Copy();
+           iPassword.Close();
+           iPassword = password.Copy();
+           iRealm.Close();
+           iRealm = realm.Copy();
+           iNonce.Close();
+           iNonce = nonce.Copy();
+           iUri.Close();
+           iUri = requestUri.Str().Copy();
+           
+           TRAP ( error, EncodeDigestAuthL( username, password, aTransaction, headerPart, requestUri ) );
+           GBA_TRACE_DEBUG(("After Encode Digest AuthL"));
+           if ( error != KErrNone )
+               {
+               GBA_TRACE_DEBUG_NUM(("After Encode Digest AuthL error %d"), error );
+               CleanupStack::PopAndDestroy( pushCount );
+               return error;
+               }
+           }
+           break;
+        default:
+           {
+           CleanupStack::PopAndDestroy( pushCount );
+           return KErrArgument;
+           }
+           
+        }
+     GBA_TRACE_DEBUG(("After Encode Digest AuthL 1"));
+    // Resubmit the request to the server
+    // add resyncronization header to the request if it is available
+    if ( resyncrequired )
+        {
+        THTTPHdrVal hdrVal;
+        RStringF unStr = stringPool.OpenFStringL(KAuts);
+        CleanupClosePushL(unStr);
+        pushCount++;
+        hdrVal.SetStr(resync);
+        RHTTPHeaders requestHeaders(aTransaction.Request().GetHeaderCollection());
+        requestHeaders.SetFieldL( stringPool.StringF(HTTP::EAuthorization,RHTTPSession::GetTable()), 
+                                 THTTPHdrVal(stringPool.StringF(HTTP::EDigest,RHTTPSession::GetTable())),
+                                 unStr,
+                                 hdrVal );
+       }
+    GBA_TRACE_DEBUG(("After Encode Digest AuthL 2"));   
+    CleanupStack::PopAndDestroy( pushCount ); 
+    GBA_TRACE_DEBUG(("After Encode Digest AuthL 3"));
+    return KErrNone;
+    }
+
+
+// -----------------------------------------------------------------------------
+// C3GPPBootstrapHttpHandler::FindHeaderPartToUseL()
+// -----------------------------------------------------------------------------
+//
+TInt C3GPPBootstrapHttpHandler::FindHeaderPartToUseL( RHTTPTransaction aTransaction ) const
+    {
+    //We only pick up the first digest authentication fields:
+    
+    RStringPool stringPool = aTransaction.Session().StringPool(); 
+
+    RStringF wwwAuthenticate = stringPool.StringF(HTTP::EWWWAuthenticate,RHTTPSession::GetTable());
+    RStringF realm = stringPool.StringF(HTTP::ERealm,RHTTPSession::GetTable());
+    RStringF nonce = stringPool.StringF(HTTP::ENonce,RHTTPSession::GetTable());
+    RStringF qop   = stringPool.StringF(HTTP::EQop,RHTTPSession::GetTable());
+    
+    RHTTPHeaders headers = aTransaction.Response().GetHeaderCollection();
+    const TInt parts = headers.FieldPartsL( wwwAuthenticate );
+    
+    for ( TInt i = 0; i < parts; i++ )
+    {
+    THTTPHdrVal fieldVal;// The name of the current field.
+    THTTPHdrVal hdrVal;//A scratch hdrVal
+    headers.GetField(wwwAuthenticate, i, fieldVal);
+    switch ( fieldVal.StrF().Index(RHTTPSession::GetTable() ) )
+        {
+        case HTTP::EDigest:
+            {
+            // It is Digest, let us check realm, nonce, qop then
+            if ( headers.GetParam(wwwAuthenticate, realm, hdrVal, i ) == KErrNone 
+                 &&
+                 headers.GetParam(wwwAuthenticate, nonce, hdrVal, i ) == KErrNone)
+                {
+                // We've got a realm and a nonce. If there's a qop, we
+                // need to check it's acceptable.
+               if ( headers.GetParam(wwwAuthenticate, qop, hdrVal, i ) == KErrNone 
+                    && 
+                    FindAuth( hdrVal.Str().DesC() ) )
+                     {
+                     // the header has qop and it is auth-int.
+                     // we found it
+                     return i;
+                     }
+
+                }
+            }
+            break;
+
+        default:
+            //Ingore if it is not Digest
+            break;
+        }
+    }
+    return KErrNotFound;
+}
+
+
+
+// -----------------------------------------------------------------------------
+// C3GPPBootstrapHttpHandler::EncodeDigestAuthL()
+// -----------------------------------------------------------------------------
+//
+void C3GPPBootstrapHttpHandler::EncodeDigestAuthL( const RString& aUsername, 
+            const RString& aPW, 
+            RHTTPTransaction& aTransaction,
+            TInt aHeaderPart,
+            const THTTPHdrVal& aRequestUri )
+    {
+    GBA_TRACE_BEGIN();
+    TInt pushCount = 0; 
+    
+    RStringPool stringPool = aTransaction.Session().StringPool(); 
+
+    GBA_TRACE_DEBUG(("Username:"));
+    GBA_TRACE_DEBUG(aUsername.DesC());
+
+    GBA_TRACE_DEBUG(("Passwd:"));
+    GBA_TRACE_DEBUG_BINARY(aPW.DesC());
+  
+    TBuf8<KHashLength> hash;
+    TBuf8<KHashLength> cnonce;
+    //Nonce
+    THTTPHdrVal nonce;
+    RHTTPHeaders headers = aTransaction.Response().GetHeaderCollection();
+    TInt error = headers.GetParam(stringPool.StringF(HTTP::EWWWAuthenticate,RHTTPSession::GetTable()), 
+          stringPool.StringF(HTTP::ENonce,RHTTPSession::GetTable()), nonce,
+          aHeaderPart);
+    
+    if ( error != KErrNone )
+        {
+        User::LeaveIfError( error );
+        }
+    
+    //realm
+    THTTPHdrVal realm;
+    error = headers.GetParam(stringPool.StringF(HTTP::EWWWAuthenticate,RHTTPSession::GetTable()),
+           stringPool.StringF(HTTP::ERealm,RHTTPSession::GetTable()), realm,
+           aHeaderPart);
+    
+    if ( error != KErrNone )
+        {
+        User::LeaveIfError( error );
+        }
+    
+    //qop       
+    THTTPHdrVal qop;
+    error = headers.GetParam(stringPool.StringF(HTTP::EWWWAuthenticate,RHTTPSession::GetTable()),
+           stringPool.StringF(HTTP::EQop,RHTTPSession::GetTable()), qop,
+           aHeaderPart);
+    
+   if ( error != KErrNone )
+        {
+        User::LeaveIfError( error );
+        }
+    
+    GenerateCNonce( cnonce );
+    
+    GBA_TRACE_DEBUG(("cnonce:"));
+    GBA_TRACE_DEBUG_BINARY( cnonce );
+    
+    RString cnonceString = stringPool.OpenStringL(cnonce); 
+    CleanupClosePushL(cnonceString);
+    pushCount++;
+    
+    // stored for auth calculations
+    iCnonce.Close();
+    iCnonce = cnonceString.Copy();
+    
+    // stored for auth calculations
+    iMethod.Close();
+    iMethod = aTransaction.Request().Method().Copy();
+    
+    DigestCalcL( KMD5HashofEmpty, hash );
+    
+    GBA_TRACE_DEBUG(("hash:"));
+    GBA_TRACE_DEBUG_BINARY( hash );
+    
+    // OK. hash now contains the digest response. Set up the header.
+    RHTTPHeaders requestHeaders(aTransaction.Request().GetHeaderCollection());
+    RHTTPHeaders responseHeaders(aTransaction.Response().GetHeaderCollection());
+  
+    requestHeaders.RemoveField(stringPool.StringF(HTTP::EAuthorization,RHTTPSession::GetTable())); 
+    
+    //Copy useranme
+    THTTPHdrVal hdrVal;
+    hdrVal.SetStr(aUsername);
+    
+    //Set the username to request header
+    requestHeaders.SetFieldL(stringPool.StringF(HTTP::EAuthorization,RHTTPSession::GetTable()), 
+           THTTPHdrVal(stringPool.StringF(HTTP::EDigest,RHTTPSession::GetTable())),
+           stringPool.StringF(HTTP::EUsername,RHTTPSession::GetTable()),
+           hdrVal);
+        
+    // copy Realm from response headers
+    responseHeaders.GetParam(stringPool.StringF(HTTP::EWWWAuthenticate,RHTTPSession::GetTable()), 
+           stringPool.StringF(HTTP::ERealm,RHTTPSession::GetTable()),
+           hdrVal, 
+           aHeaderPart);
+    
+    // Set the Realm to request header
+    requestHeaders.SetFieldL(stringPool.StringF(HTTP::EAuthorization,RHTTPSession::GetTable()), 
+           THTTPHdrVal(stringPool.StringF(HTTP::EDigest,RHTTPSession::GetTable())),
+           stringPool.StringF(HTTP::ERealm,RHTTPSession::GetTable()),
+           hdrVal);
+    
+    // copy nonce from response headers
+    responseHeaders.GetParam(stringPool.StringF(HTTP::EWWWAuthenticate,RHTTPSession::GetTable()), 
+           stringPool.StringF(HTTP::ENonce,RHTTPSession::GetTable()), 
+           hdrVal,
+           aHeaderPart);
+    
+    // set nonce to request header
+    requestHeaders.SetFieldL(stringPool.StringF(HTTP::EAuthorization,RHTTPSession::GetTable()), 
+           THTTPHdrVal(stringPool.StringF(HTTP::EDigest,RHTTPSession::GetTable())),
+           stringPool.StringF(HTTP::ENonce,RHTTPSession::GetTable()),
+           hdrVal);
+    
+    // Set uri to request header.
+    // the uri has already been fetched from http property setting
+    requestHeaders.SetFieldL(stringPool.StringF(HTTP::EAuthorization,RHTTPSession::GetTable()), 
+           THTTPHdrVal(stringPool.StringF(HTTP::EDigest,RHTTPSession::GetTable())),
+           stringPool.StringF(HTTP::EUri,RHTTPSession::GetTable()),
+           aRequestUri);
+    
+    // Qop with quotation marks   
+    // copy qop from response headers
+     responseHeaders.GetParam(stringPool.StringF(HTTP::EWWWAuthenticate,RHTTPSession::GetTable()), 
+           stringPool.StringF(HTTP::EQop,RHTTPSession::GetTable()), 
+           hdrVal,
+           aHeaderPart);
+    
+    // Set Qop to request header
+     requestHeaders.SetFieldL(stringPool.StringF(HTTP::EAuthorization,RHTTPSession::GetTable()), 
+           THTTPHdrVal(stringPool.StringF(HTTP::EDigest,RHTTPSession::GetTable())),
+           stringPool.StringF(HTTP::EQop,RHTTPSession::GetTable()),
+           hdrVal);
+     
+    //Set Nc
+    hdrVal.SetStrF(stringPool.StringF(HTTP::E00000001,RHTTPSession::GetTable()));
+    requestHeaders.SetFieldL(stringPool.StringF(HTTP::EAuthorization,RHTTPSession::GetTable()), 
+                  THTTPHdrVal(stringPool.StringF(HTTP::EDigest,RHTTPSession::GetTable())),
+                  stringPool.StringF(HTTP::ENc,RHTTPSession::GetTable()),
+                  hdrVal);
+     
+    // Set Cnonce to request header.
+    hdrVal.SetStr(cnonceString);
+    requestHeaders.SetFieldL(stringPool.StringF(HTTP::EAuthorization,RHTTPSession::GetTable()), 
+           THTTPHdrVal(stringPool.StringF(HTTP::EDigest,RHTTPSession::GetTable())),
+           stringPool.StringF(HTTP::ECnonce,RHTTPSession::GetTable()),
+           hdrVal);
+   
+    // Set response to request header.
+    RString hashStr = stringPool.OpenStringL(hash);
+    CleanupClosePushL(hashStr);
+    hdrVal.SetStr(hashStr);
+    requestHeaders.SetFieldL(stringPool.StringF(HTTP::EAuthorization,RHTTPSession::GetTable()), 
+           THTTPHdrVal(stringPool.StringF(HTTP::EDigest,RHTTPSession::GetTable())),
+           stringPool.StringF(HTTP::EResponse,RHTTPSession::GetTable()),
+           hdrVal);
+    CleanupStack::PopAndDestroy(&hashStr);
+
+    // Get Opaque from response header.
+    error = responseHeaders.GetParam(stringPool.StringF(HTTP::EWWWAuthenticate,RHTTPSession::GetTable()), 
+             stringPool.StringF(HTTP::EOpaque,RHTTPSession::GetTable()), 
+             hdrVal, aHeaderPart);
+    
+    // Set Opaque 
+    if ( error != KErrNotFound )
+        {
+        GBA_TRACE_DEBUG((" found the opaque value and copy it"));
+        requestHeaders.SetFieldL(stringPool.StringF(HTTP::EAuthorization,RHTTPSession::GetTable()), 
+                       THTTPHdrVal(stringPool.StringF(HTTP::EDigest,RHTTPSession::GetTable())),
+                       stringPool.StringF(HTTP::EOpaque,RHTTPSession::GetTable()),
+                       hdrVal);
+        } 
+    else
+        {
+        GBA_TRACE_DEBUG((" No opaque value send empty one"));
+        RString opaque =  stringPool.OpenStringL(Kfopaque);
+        GBA_TRACE_DEBUG((" No opaque value send empty one 1"));
+        CleanupClosePushL(opaque);
+        pushCount++;
+        hdrVal.SetStr(opaque);
+       GBA_TRACE_DEBUG((" No opaque value send empty one 2"));
+        requestHeaders.SetFieldL(stringPool.StringF(HTTP::EAuthorization,RHTTPSession::GetTable()), 
+             THTTPHdrVal(stringPool.StringF(HTTP::EDigest,RHTTPSession::GetTable())),
+             stringPool.StringF(HTTP::EOpaque,RHTTPSession::GetTable()),
+             hdrVal);
+       }
+    GBA_TRACE_DEBUG((" No opaque value send empty one 3"));
+    // Set algorithm.   
+    TBuf8<KAlgLength> algbuf;
+    algbuf.Copy(_L8(", "));
+    algbuf.Append(Kalgorithm);
+    algbuf.Append(_L8("="));
+    algbuf.Append(Kfalgo);
+   
+    GBA_TRACE_DEBUG((" No opaque value send empty one 5"));
+   
+    RStringF valStr = stringPool.OpenFStringL(algbuf);
+    THTTPHdrVal val(valStr);
+    requestHeaders.SetFieldL(stringPool.StringF(HTTP::EAuthorization,RHTTPSession::GetTable()), val);
+    valStr.Close();
+    
+    GBA_TRACE_DEBUG((" No opaque value send empty one 4"));
+
+    CleanupStack::PopAndDestroy(pushCount);
+    GBA_TRACE_DEBUG((" No opaque value send empty one 6"));
+    }
+
+
+// -----------------------------------------------------------------------------
+// C3GPPBootstrapHttpHandler::FindAuth()
+// -----------------------------------------------------------------------------
+//
+TBool C3GPPBootstrapHttpHandler::FindAuth(const TDesC8& aQop) const
+    {
+    GBA_TRACE_BEGIN();
+    if ( aQop == KAuthInt )
+        {
+        GBA_TRACE_DEBUG((" qop is equal to auth-int"));
+        return ETrue;
+        }
+    else
+        {
+        GBA_TRACE_DEBUG((" qop is NOT equal to auth-int"));
+        GBA_TRACE_DEBUG((""));
+        return EFalse;    
+        }    
+    }
+
+
+// -----------------------------------------------------------------------------
+// C3GPPBootstrapHttpHandler::HA1L()
+// -----------------------------------------------------------------------------
+//
+void C3GPPBootstrapHttpHandler::HAOneL(const RString& aUsername,const RString& aPW,
+           const RString& aRealm, TDes8& aResult)
+    {
+    HBufC8* a1 = HBufC8::NewMaxLC(aUsername.DesC().Length() 
+           + aPW.DesC().Length()  
+           + 1
+           + aRealm.DesC().Length() + 1
+           );
+    TPtr8 a1Mod = a1->Des();
+    a1Mod.Zero();
+    
+    a1Mod.Append(aUsername.DesC());
+    a1Mod.Append(':');
+    a1Mod.Append(aRealm.DesC());
+    a1Mod.Append(':');
+    a1Mod.Append(aPW.DesC().Ptr(),aPW.DesC().Length());
+
+    GBA_TRACE_DEBUG(a1Mod);
+    Hash(*a1, aResult);
+    GBA_TRACE_DEBUG(("after hash"));
+    CleanupStack::PopAndDestroy(a1);
+    }
+
+
+// -----------------------------------------------------------------------------
+// C3GPPBootstrapHttpHandler::HAtwoL()
+// -----------------------------------------------------------------------------
+//
+void C3GPPBootstrapHttpHandler::HATwoL(const RStringF& aMethod, 
+           const RString& aRequestUri,
+           const TDesC8& aHentity,
+           TDes8& aResult)
+    {
+    // In the auth qop, a2 is Method:digest-uri-value:empty body hash
+    // Allocate enough space for the method, the URI and the colon, empty content-hash and colon.
+    TPtrC8 requestUri = aRequestUri.DesC();
+    TPtrC8 method = aMethod.DesC();
+    HBufC8* a2 = HBufC8::NewMaxLC( requestUri.Length() + method.Length() + KNumber34 );
+    TPtr8 a2Mod = a2->Des();
+    a2Mod.Zero();
+    a2Mod.Append(method);
+    a2Mod.Append(':');
+    
+    a2Mod.Append( requestUri );
+    GBA_TRACE_DEBUG( requestUri );
+    // since for this method is always auth-int we always add hentity
+    a2Mod.Append(':');
+    a2Mod.Append(aHentity);
+    GBA_TRACE_DEBUG(a2Mod);
+
+    Hash(*a2, aResult);
+
+    GBA_TRACE_DEBUG_BINARY(aResult);
+    CleanupStack::PopAndDestroy(a2);
+    
+    GBA_TRACE_DEBUG(("Exit HATwoL"));
+    }
+
+
+// -----------------------------------------------------------------------------
+// C3GPPBootstrapHttpHandler::Hash()
+// -----------------------------------------------------------------------------
+//
+void C3GPPBootstrapHttpHandler::Hash(const TDesC8& aMessage, TDes8& aHash)
+    {
+    GBA_TRACE_DEBUG(("hash"));
+    // Calculate the 128 bit (16 byte) hash
+    iMD5Calculator->Reset();
+    TPtrC8 hash = iMD5Calculator->Hash(aMessage);
+    GBA_TRACE_DEBUG(("after hash"));
+    // Now print it as a 32 byte hex number
+    aHash.Zero();
+    for ( TInt ii = 0; ii < KRawHashLength; ii++ )
+        {
+        TBuf8<2> scratch;
+        scratch.Zero();
+        scratch.Format(formatStr, hash[ii]);
+        aHash.Append(scratch);
+      }
+    }
+
+
+// -----------------------------------------------------------------------------
+// C3GPPBootstrapHttpHandler::GenerateCNonce()
+// -----------------------------------------------------------------------------
+//
+void C3GPPBootstrapHttpHandler::GenerateCNonce(TDes8& aNonce)
+    {
+    // The purpose of the client nonce is to protect aextst 'chosen
+    // plaintext' attacks where a hostile server tricks the client
+    // into supplying a password using a specific server nonce that
+    // allows an (as yet undiscovered) flaw in MD5 to recover the
+    // password. As such the only important thing about client nonces
+    // is that they change and aren't predictable. See section 4.9 of
+    // RFC2616
+
+    TTime time;
+    time.UniversalTime();
+    TInt64 randomNumber = Math::Rand(iSeed);
+    randomNumber <<= KNumber32;
+    randomNumber += Math::Rand(iSeed);
+    TBuf8<KNumber33> key;
+    key.Zero();
+    key.AppendNum(time.Int64(), EHex);
+    key.Append(KColon);
+    key.AppendNum(randomNumber, EHex);
+  
+    Hash(key, aNonce);
+    }
+
+
+// -----------------------------------------------------------------------------
+// C3GPPBootstrapHttpHandler::CheckRspAuthL()
+// -----------------------------------------------------------------------------
+//
+TInt C3GPPBootstrapHttpHandler::CheckRspAuthL(RHTTPTransaction aTransaction)
+    {
+    RStringF wwwAuthInfoHeader = aTransaction.Session().StringPool().OpenFStringL(KHTTPAuthInfo);
+    RHTTPHeaders headers(aTransaction.Response().GetHeaderCollection());
+
+    THTTPHdrVal rspAuthVal;
+    
+    TInt retVal = headers.FieldPartsL(wwwAuthInfoHeader);
+
+    TInt error = headers.GetField(wwwAuthInfoHeader, 0, rspAuthVal);
+
+    if(error != KErrNone)
+    {
+    	wwwAuthInfoHeader.Close();
+    	return error;
+    } 
+    wwwAuthInfoHeader.Close();
+    return KErrNone;      
+    }
+
+
+// -----------------------------------------------------------------------------
+// C3GPPBootstrapHttpHandler::DigestCalcL()
+// -----------------------------------------------------------------------------
+//
+void C3GPPBootstrapHttpHandler::DigestCalcL(
+    const TDesC8& aHentity,
+    TDes8& aResult )
+    {
+    TInt stringToHashLength = iNonce.DesC().Length() + 
+          KNumber8 + // auth-int length 
+          KNumber3 * KHashLength + KNumber8 + iPassword.DesC().Length() + KNumber5;
+    HBufC8* stringToHash = HBufC8::NewMaxLC(stringToHashLength);
+    TPtr8 stringMod = stringToHash->Des();
+    stringMod.Zero();
+    HAOneL(iUsername, iPassword, iRealm, stringMod);
+    stringMod.Append(':');
+    stringMod.Append(iNonce.DesC());
+    stringMod.Append(KNCVal_2);
+    stringMod.Append(iCnonce.DesC());
+    stringMod.Append(':');
+    stringMod.Append(KAuthInt);
+    stringMod.Append(':');
+    TBuf8<KHashLength> hash;
+    HATwoL(iMethod, iUri, aHentity,hash);
+    GBA_TRACE_DEBUG_BINARY(stringMod);
+    stringMod.Append(hash);   
+    GBA_TRACE_DEBUG(stringMod);
+    Hash(*stringToHash, aResult);
+    CleanupStack::PopAndDestroy(stringToHash);
+    };
+
+// -----------------------------------------------------------------------------
+// C3GPPBootstrapHttpHandler::GetResponse()
+// -----------------------------------------------------------------------------
+//
+ HBufC8* C3GPPBootstrapHttpHandler::GetResponse()
+    {
+    return iResponse->Alloc();
+    };
+    
+//EOF