xdmprotocols/XcapProtocol/XcapHttpTransport/src/XcapHttpResponse.cpp
changeset 0 c8caa15ef882
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xdmprotocols/XcapProtocol/XcapHttpTransport/src/XcapHttpResponse.cpp	Tue Feb 02 01:05:17 2010 +0200
@@ -0,0 +1,442 @@
+/*
+* Copyright (c) 2003 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:   CXcapHttpResponse
+*
+*/
+
+
+
+
+// INCLUDE FILES
+#include <XdmErrors.h>
+#include "XdmCredentials.h"
+#include "XcapHttpRequest.h"
+#include "XcapHttpResponse.h"
+#include "XcapHttpTransport.h"
+#include "XcapHttpAuthManager.h"
+
+const TUint KMaxRetryCount = 3;
+
+// ================= MEMBER FUNCTIONS =======================
+//
+
+
+// ----------------------------------------------------------
+// CXcapHttpResponse::CXcapHttpResponse
+// 
+// ----------------------------------------------------------
+//
+CXcapHttpResponse::CXcapHttpResponse( CXcapHttpRequest* aHttpRequest,
+                                      CXcapHttpTransport& aTransportMain ) :
+                                      iAuthPending( EFalse ),
+                                      iHttpRequest( aHttpRequest ),
+                                      iTransportMain( aTransportMain ),
+                                      iAuthManager( iHttpRequest->AuthManager() )                                       
+    {
+    }
+
+// ----------------------------------------------------
+// CXcapHttpResponse::NewL
+// 
+// ----------------------------------------------------
+//
+CXcapHttpResponse* CXcapHttpResponse::NewL( CXcapHttpRequest* aHttpRequest,
+                                            CXcapHttpTransport& aTransportMain )
+    {
+    CXcapHttpResponse* self = new ( ELeave ) CXcapHttpResponse( aHttpRequest, aTransportMain );
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    CleanupStack::Pop();  //self
+    return self;
+    }
+    
+// ----------------------------------------------------
+// CXcapHttpResponse::ConstructL
+// 
+// ----------------------------------------------------
+//
+void CXcapHttpResponse::ConstructL()
+    {
+    }
+    
+// ----------------------------------------------------
+// CXcapHttpResponse::~CXcapHttpResponse()
+// Destructor
+// ----------------------------------------------------
+//
+CXcapHttpResponse::~CXcapHttpResponse()
+    {
+    }
+
+// ----------------------------------------------------
+// CXcapHttpResponse::MHFRunL
+// 
+// ----------------------------------------------------
+//
+void CXcapHttpResponse::MHFRunL( RHTTPTransaction aTransaction, const THTTPEvent& aEvent )
+    {
+    TInt status = aTransaction.Response().StatusCode();
+    #ifdef _DEBUG
+        iTransportMain.WriteToLog( _L8( "CXcapHttpResponse::MHFRunL()" ) );
+        iTransportMain.WriteToLog( _L8( "  HTTP status:  %d" ), status );
+		iTransportMain.WriteToLog( _L8( "  Event status: %d" ), aEvent.iStatus );
+        iTransportMain.WriteToLog( _L8( "  TransID:      %d " ), aTransaction.Id() );
+    #endif
+    switch( aEvent.iStatus )
+        {
+        case THTTPEvent::EGotResponseHeaders:
+            #ifdef _DEBUG
+                DumpHeadersL( aTransaction.Response().GetHeaderCollection(), aTransaction.Id() );
+                //DumpHeadersL( aTransaction.Request().GetHeaderCollection(), aTransaction.Id() );
+            #endif
+            TInt authType;
+            if( IsUnauthRequest( aTransaction, authType ) )
+                {
+                // If server keeps on sending 401 resposenses. Will stop
+                // sending new requests after 3 trys.
+                if ( KMaxRetryCount == iUnauthRequestCounter )
+                    {
+                    #ifdef _DEBUG
+                        iTransportMain.WriteToLog(
+                        _L8( "  Max retry count. Stop sending auth requests to server." ) );
+                    #endif   
+                    iHttpRequest->FinaliseRequestL( KErrCancel );
+                    aTransaction.Cancel();                   
+                    }                
+                //We only support Digest => If Basic is defined, stop.
+                else if( iAuthManager.ParseHeaderL( aTransaction, authType ) )
+                    {
+                    iHttpRequest->ResendWithAuthL( authType );
+                    iAuthPending = ETrue;
+                    }
+                else
+                    {
+                    #ifdef _DEBUG
+                        iTransportMain.WriteToLog( _L8( " Basic authentication not supported" ) );
+                    #endif
+                    iHttpRequest->FinaliseRequestL( KXcapErrorAuthentication );
+                    aTransaction.Cancel();
+                    }
+                }
+            else if( iAuthPending && ( status != 401 && status != 403 ) )
+                {
+                iAuthPending = EFalse;
+                iAuthManager.SetAuthorized( ETrue );
+                }
+            else if( !CheckAuthInfoHeaderL( aTransaction.Response().GetHeaderCollection() ) )
+                {
+                //This means that something was wrong with the Authentication-Info header
+                //the server returned. Do not take any chances here, but stop.
+                #ifdef _DEBUG
+                    iTransportMain.WriteToLog( _L8( " Something's wrong with Authentication-Info => STOP" ) );
+                #endif
+                iHttpRequest->FinaliseRequestL( KXcapErrorAuthentication );
+                aTransaction.Cancel();
+                }
+            break;
+        case THTTPEvent::EGotResponseBodyData:
+            #ifdef _DEBUG
+                iTransportMain.WriteToLog( _L8( "MHFRunL() - A body part received" ) );
+            #endif
+            HandleReceivedBodyDataL( aTransaction );
+            break;
+        case THTTPEvent::EResponseComplete:
+            #ifdef _DEBUG
+                iTransportMain.WriteToLog( _L8( " * Transaction complete") );
+            #endif
+            break;
+        case THTTPEvent::ESucceeded:
+            #ifdef _DEBUG
+                iTransportMain.WriteToLog( _L8( " * Transaction succeeded") );
+            #endif
+            iHttpRequest->FinaliseRequestL( KErrNone );
+            break;
+        case THTTPEvent::EFailed:
+            {
+            TInt completion = aEvent.iStatus < 0 ? aEvent.iStatus : KErrNone;
+            #ifdef _DEBUG
+                iTransportMain.WriteToLog( _L8( " * Transaction failed - Completion: %d"), completion );
+            #endif
+            iHttpRequest->FinaliseRequestL( completion );
+            }
+            break;
+        case THTTPEvent::ERedirectedPermanently:
+            break;
+        case THTTPEvent::ERedirectedTemporarily:
+            break;
+        default:
+            {
+            if( aEvent.iStatus < KErrNone )
+                {
+                #ifdef _DEBUG
+                    iTransportMain.WriteToLog( _L8( "  * Transaction failed, stop" ) );
+                #endif
+                iHttpRequest->FinaliseRequestL( aEvent.iStatus );
+                }
+            else
+                {
+                #ifdef _DEBUG
+                    iTransportMain.WriteToLog( _L8( "  * Unknown status, stop" ) );
+                #endif
+                iHttpRequest->FinaliseRequestL( KErrUnknown );
+                }
+            }
+            break;
+        }  
+    }
+
+// ----------------------------------------------------------
+// CXcapHttpAuthManager::CheckAuthInfoHeaderL
+// 
+// ----------------------------------------------------------
+//
+TBool CXcapHttpResponse::CheckAuthInfoHeaderL( RHTTPHeaders aHeaders )
+    {
+    #ifdef _DEBUG
+        iTransportMain.WriteToLog( _L8( "CXcapHttpResponse::CheckAuthInfoHeaderL()" ) );
+    #endif
+    THTTPHdrVal fieldVal;
+    TBool authOk = ETrue;
+    TPtrC8 rawData( _L8( "" ) );
+    RStringPool spool = iHttpRequest->Session().StringPool();
+    RStringF authInfo = spool.OpenFStringL( TPtrC8( KAuthInfoParamArray[ENfoAuthInfo] ) );
+    CleanupClosePushL( authInfo );
+    RStringF prxAuthInfo = spool.OpenFStringL( TPtrC8( KAuthInfoParamArray[ENfoPrxAuthInfo] ) );
+    CleanupClosePushL( prxAuthInfo );
+    if( aHeaders.GetRawField( authInfo, rawData ) == KErrNone ||
+        aHeaders.GetRawField( prxAuthInfo, rawData ) == KErrNone )
+        {
+        TInt length = 0;
+        HBufC8* tempCopy = rawData.AllocLC();
+        TPtr8 modDesc( tempCopy->Des() );
+        while( authOk && modDesc.Length() > 0 )
+            {
+            TPtrC8 value;
+            TAuthInfoParam name = ( TAuthInfoParam )-1;
+            if( ParseAuthInfoParam( length, name, value, modDesc ) )
+                authOk = iAuthManager.ConsumeAuthInfoParamL( name, value );
+            modDesc.Delete( 0, length );
+            modDesc.TrimLeft();
+            }
+        CleanupStack::PopAndDestroy();  //tempCopy
+        }
+    CleanupStack::PopAndDestroy( 2 );  //prxAuthInfo, authInfo
+    return authOk;
+    }
+
+// ----------------------------------------------------------
+// CXcapHttpAuthManager::ParseAuthInfoParam
+// 
+// ----------------------------------------------------------
+//
+TBool CXcapHttpResponse::ParseAuthInfoParam( TInt& aLength, TAuthInfoParam& aName, TPtrC8& aValue, TPtr8& aParam )
+    {
+    TBool found = EFalse;
+    TInt delim = aParam.Locate( ',' );
+    TPtrC8 param( delim > 0 ? aParam.Left( delim ) : aParam );
+    TInt index = param.Locate( '=' );
+    if( index > 0 )
+        {
+        TPtrC8 name( param.Left( index ) );
+        TPtrC8 value( param.Mid( index + 1 ) );
+        const TInt count = sizeof( KAuthInfoParamArray ) / sizeof( KAuthInfoParamArray[0] );
+        for( TInt i = 0;!found && i < count;i++ )
+            {
+            if( name.CompareF( TPtrC8( KAuthInfoParamArray[i] ) ) == 0 )
+                {
+                aValue.Set( value );
+                aName = ( TAuthInfoParam )i;
+                found = ETrue;
+                }
+            }
+        }
+    aLength = delim > 0 ? delim + 1 : aParam.Length();
+    return found;
+    }
+
+               
+// ----------------------------------------------------------
+// CXcapHttpResponse::IsUnauthRequest
+// 
+// ----------------------------------------------------------
+//
+TBool CXcapHttpResponse::IsUnauthRequest( RHTTPTransaction aTransaction, TInt& aAuthType )
+    {
+    iUnauthRequestCounter++;
+    TInt status = aTransaction.Response().StatusCode();
+    switch( status )
+        {
+        case 401:  //Normal authentication
+            aAuthType = 401;
+            return ETrue;
+        case 407:  //Proxy authentication
+            aAuthType = 407;
+            return ETrue;
+        default:
+            return EFalse;
+        }
+    }
+       
+// ----------------------------------------------------------
+// CXcapHttpResponse::HandleReceivedBodyDataL
+// 
+// ----------------------------------------------------------
+//
+TBool CXcapHttpResponse::HandleReceivedBodyDataL( const RHTTPTransaction aTransaction )
+    {
+    #ifdef _DEBUG
+        iTransportMain.WriteToLog( _L8( "CXcapHttpResponse::HandleReceivedBodyDataL()") );
+    #endif
+    TPtrC8 bodyData;
+    MHTTPDataSupplier* respBody = aTransaction.Response().Body();
+    TBool lastChunk = respBody->GetNextDataPart( bodyData );
+    iHttpRequest->AppendDataL( bodyData );
+    respBody->ReleaseData();
+    return lastChunk;
+    }
+
+// ----------------------------------------------------------
+// CImpsHttpTransactionSender::ContentLengthL
+// 
+// ----------------------------------------------------------
+//
+TInt CXcapHttpResponse::ContentLengthL() const
+    {
+    TInt retVal = KMaxTInt;
+    THTTPHdrVal fieldValue;
+    _LIT8( KContentLength, "Content-Length" );
+    RHTTPHeaders headers = ResponseHeaderCollection();
+    RStringPool stringPool = iHttpRequest->Session().StringPool();
+    RStringF lengthString = stringPool.OpenFStringL( KContentLength );
+    headers.GetField( lengthString, 0, fieldValue );
+    lengthString.Close();
+    if( fieldValue.Type() == THTTPHdrVal::KTIntVal )
+        retVal = fieldValue.Int();
+    return retVal;
+    }
+    
+// ----------------------------------------------------
+// CXcapHttpResponse::HeaderCollection
+// 
+// ----------------------------------------------------
+//
+RHTTPHeaders CXcapHttpResponse::ResponseHeaderCollection() const
+    {
+    return iHttpRequest->Transaction().Response().GetHeaderCollection();
+    }
+
+// ----------------------------------------------------
+// CXcapHttpResponse::HeaderCollection
+// 
+// ----------------------------------------------------
+//
+RHTTPHeaders CXcapHttpResponse::RequestHeaderCollection() const
+    {
+    return iHttpRequest->Transaction().Request().GetHeaderCollection();
+    }
+
+// ----------------------------------------------------
+// CXcapHttpResponse::MHFRunError
+// HTTP Stack callback interface
+// ----------------------------------------------------
+//
+TInt CXcapHttpResponse::MHFRunError( TInt /*aInt*/, RHTTPTransaction /*aTransaction*/,
+                                    const THTTPEvent& /*aEvent*/ )
+    {
+    return KErrNone;
+    }
+    
+#ifdef _DEBUG
+// ----------------------------------------------------
+// CXcapHttpResponse::DumpHeadersL
+// 
+// ----------------------------------------------------
+//
+void CXcapHttpResponse::DumpHeadersL( RHTTPHeaders aHeaders, TInt aId )
+    {
+    iTransportMain.WriteToLog( _L( "--------------------") );
+    iTransportMain.WriteToLog( _L( "Headers of the transaction %d: "), aId );
+    RStringPool strP = iHttpRequest->Session().StringPool();
+    THTTPHdrFieldIter it = aHeaders.Fields();
+    TBuf<KMaxHeaderNameLen>  fieldName16;
+    TBuf<KMaxHeaderValueLen> fieldVal16;
+
+    while( it.AtEnd() == EFalse )
+        {
+        RStringTokenF fieldName = it();
+        RStringF fieldNameStr = strP.StringF( fieldName );
+        THTTPHdrVal fieldVal;
+        if( aHeaders.GetField( fieldNameStr, 0, fieldVal ) == KErrNone )
+            {
+            const TDesC8& fieldNameDesC = fieldNameStr.DesC();
+            fieldName16.Copy( fieldNameDesC.Left( KMaxHeaderNameLen ) );
+            switch( fieldVal.Type() )
+                {
+            case THTTPHdrVal::KTIntVal:
+                iTransportMain.WriteToLog( _L("%S: %d"), &fieldName16, fieldVal.Int() );
+                break;
+            case THTTPHdrVal::KStrFVal:
+                {
+                RStringF fieldValStr = strP.StringF( fieldVal.StrF() );
+                const TDesC8& fieldValDesC = fieldValStr.DesC();
+                fieldVal16.Copy( fieldValDesC.Left( KMaxHeaderValueLen ) );
+                iTransportMain.WriteToLog( _L( "%S: %S" ), &fieldName16, &fieldVal16 );
+                }
+                break;
+            case THTTPHdrVal::KStrVal:
+                {
+                RString fieldValStr = strP.String(fieldVal.Str());
+                const TDesC8& fieldValDesC = fieldValStr.DesC();
+                fieldVal16.Copy( fieldValDesC.Left( KMaxHeaderValueLen ) );
+                iTransportMain.WriteToLog( _L( "%S: %S" ), &fieldName16, &fieldVal16 );
+                }
+                break;
+            case THTTPHdrVal::KDateVal:
+                {
+                TDateTime date = fieldVal.DateTime();
+                TBuf<40> dateTimeString;
+                TTime t(date);
+                t.FormatL( dateTimeString,KTransportDateFormat );
+                iTransportMain.WriteToLog( _L( "%S: %S" ), &fieldName16, &dateTimeString );
+                } 
+                break;
+            default:
+                iTransportMain.WriteToLog( _L( "%S: <unrecognised value type>" ), &fieldName16 );
+                break;
+                }
+            // Display realm for WWW-Authenticate header
+            RStringF wwwAuth = strP.StringF( HTTP::EWWWAuthenticate, RHTTPSession::GetTable() );
+            if( fieldNameStr == wwwAuth )
+                {
+                // check the auth scheme is 'basic'
+                RStringF basic = strP.StringF( HTTP::EBasic,RHTTPSession::GetTable() );
+                RStringF realm = strP.StringF( HTTP::ERealm,RHTTPSession::GetTable() );
+                THTTPHdrVal realmVal;
+                if ( (fieldVal.StrF() == basic ) && 
+                    ( !aHeaders.GetParam(wwwAuth, realm, realmVal) ) )
+                    {
+                    RStringF realmValStr = strP.StringF( realmVal.StrF() );
+                    fieldVal16.Copy( realmValStr.DesC() );
+                    iTransportMain.WriteToLog( _L( "Realm is: %S" ), &fieldVal16 );
+                    }
+                }
+            }
+        ++it;
+        }
+        iTransportMain.WriteToLog( _L( "--------------------") );
+    }
+    #endif
+
+// End of File  
+