--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dvrengine/CommonRecordingEngine/src/CCRRTSPCommand.cpp Wed Sep 01 12:20:37 2010 +0100
@@ -0,0 +1,761 @@
+/*
+* 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 the License "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: RTSP command parser and producer*
+*/
+
+
+
+
+// INCLUDE FILES
+#include "CCRRtspCommand.h"
+#include "CCRSock.h"
+#include <imcvcodc.h>
+#include <Hash.h>
+#include "videoserviceutilsLogger.h"
+
+// CONSTANTS
+const TReal KRealZero( 0.0 );
+const TReal KRealMinusOne( -1.0 );
+// Length of a digest hash before converting to hex.
+const TInt KCRRawHashLength( 16 );
+// Length of a digest hash when represented in hex
+const TInt KCRHashLength( 32 );
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CCRRtspCommand::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CCRRtspCommand* CCRRtspCommand::NewL()
+ {
+ CCRRtspCommand* self = new( ELeave ) CCRRtspCommand();
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ CleanupStack::Pop( self );
+ return self;
+ }
+
+// -----------------------------------------------------------------------------
+// CCRRtspCommand::CCRRtspCommand
+// C++ default constructor can NOT contain any code, that might leave.
+// -----------------------------------------------------------------------------
+//
+CCRRtspCommand::CCRRtspCommand()
+ : iCommand( ERTSPCommandNOCOMMAND )
+ {
+ // None
+ }
+
+// -----------------------------------------------------------------------------
+// CCRRtspCommand::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CCRRtspCommand::ConstructL()
+ {
+ }
+
+// -----------------------------------------------------------------------------
+// CCRRtspCommand::~CCRRtspCommand
+// Destructor.
+// -----------------------------------------------------------------------------
+//
+CCRRtspCommand::~CCRRtspCommand()
+ {
+ LOG( "CCRRtspCommand::~CCRRtspCommand" );
+
+ // iRtspText is deleted in base class destructor
+ delete iAuthHeader;
+ delete iMD5Calculator;
+ delete iUserAgent;
+ delete iWapProfile;
+ }
+
+// -----------------------------------------------------------------------------
+// CCRRtspCommand::TryParseL
+//
+// -----------------------------------------------------------------------------
+//
+void CCRRtspCommand::TryParseL( const TDesC8 &aString )
+ {
+ // try to find out if end of the command has been received
+ // "RTSP/1.0 XXX\r\n\r\n" at least..
+ const TInt KDVRMinCommandLen( 14 );
+ TInt replyEndOffSet( ( aString.Length() < KDVRMinCommandLen )?
+ KDVRMinCommandLen: aString.Find( KCR2NewLines() ) );
+ if ( replyEndOffSet == KErrNotFound )
+ {
+ // need to have more, do nothing yet
+ LOG( "CCRRtspCommand::TryParseL() out because response not complete" );
+ User::Leave( KErrUnderflow );
+ }
+
+ // copy the stuff into local variable:
+ delete iRtspText; iRtspText = NULL;
+ iRtspText = aString.AllocL();
+ iCommand = ERTSPCommandNOCOMMAND;
+
+ // try each command in order:
+ if ( iRtspText->Find( KCROPTIONS() ) == 0 )
+ {
+ // it was OPTIONS command
+ LOG( "CCRRtspCommand::TryParseL() -> OPTIONS" );
+ iCommand = ERTSPCommandOPTIONS;
+ }
+ else if ( iRtspText->Find( KCRDESCRIBE() ) == 0 )
+ {
+ LOG( "CCRRtspCommand::TryParseL() -> DESCRIBE" );
+ iCommand = ERTSPCommandDESCRIBE;
+ }
+ else if ( iRtspText->Find( KCRTEARDOWN() ) == 0 )
+ {
+ LOG( "CCRRtspCommand::TryParseL() -> TEARDOWN" );
+ iCommand = ERTSPCommandTEARDOWN;
+ }
+ else if ( iRtspText->Find( KCRPAUSE() ) == 0 )
+ {
+ LOG( "CCRRtspCommand::TryParseL() -> PAUSE" );
+ iCommand = ERTSPCommandPAUSE;
+ }
+ else if ( iRtspText->Find( KCRSETUP() ) == 0 )
+ {
+ LOG( "CCRRtspCommand::TryParseL() -> SETUP" );
+ iCommand = ERTSPCommandSETUP;
+ }
+ else if ( iRtspText->Find( KCRPLAY() ) == 0 )
+ {
+ LOG( "CCRRtspCommand::TryParseL() -> PLAY" );
+ iCommand = ERTSPCommandPLAY;
+ }
+ else
+ {
+ User::Leave( KErrNotSupported );
+ }
+
+ // then find CSeq
+ FindCSeqL();
+ // then find session id
+ FindSessionIdL();
+ // then find possible content. for commands it is usually not there
+ FindContentL();
+ // find URL
+ FindURLL();
+ // find possible transport method
+ // IMPORTANT: should be done before parsing client port
+ FindTransport();
+ // find possible client port
+ FindClientPorts();
+ // find possible range-header
+ ParseRange();
+ }
+
+// -----------------------------------------------------------------------------
+// CCRRtspCommand::FindURLL
+// in rtsp the URL is between first and second whitespace.
+// -----------------------------------------------------------------------------
+//
+void CCRRtspCommand::FindURLL( void )
+ {
+#ifdef _DEBUG
+ _LIT( KPanicStr, "RTSPCommon" );
+ __ASSERT_DEBUG( iRtspText,
+ User::Panic( KPanicStr, KErrBadHandle ) );
+#endif
+
+ iURL.Set( NULL, 0 );
+ TInt spaceOffset( iRtspText->Locate( ' ' ) );
+ if ( spaceOffset < 0 )
+ {
+ User::Leave( KErrNotSupported );
+ }
+
+ TPtrC8 beginningFromUrl( iRtspText->Right( iRtspText->Length() -
+ ( spaceOffset + 1 ) ) ) ;
+ spaceOffset = beginningFromUrl.Locate( ' ' );
+ if ( spaceOffset < 0 )
+ {
+ User::Leave( KErrNotSupported );
+ }
+
+ iURL.Set( beginningFromUrl.Left( spaceOffset ) );
+ }
+
+// -----------------------------------------------------------------------------
+// CCRRtspCommand::URL
+//
+// method that returns URL
+// -----------------------------------------------------------------------------
+//
+TInt CCRRtspCommand::URL( TPtrC8& aURL )
+ {
+ if ( iURL.Ptr() != NULL )
+ {
+ aURL.Set ( iURL );
+ return KErrNone;
+ }
+
+ return KErrNotFound;
+ }
+
+// -----------------------------------------------------------------------------
+// CCRRtspCommand::SetURL
+//
+// -----------------------------------------------------------------------------
+//
+void CCRRtspCommand::SetURL ( const TDesC8& aURL )
+ {
+ iURL.Set ( aURL );
+ }
+
+// -----------------------------------------------------------------------------
+// CCRRtspCommand::SetAuthentication
+//
+// -----------------------------------------------------------------------------
+//
+void CCRRtspCommand::SetAuthentication( TBool aAuth )
+ {
+ iAuthenticationNeeded = aAuth;
+ }
+
+// -----------------------------------------------------------------------------
+// CCRRtspCommand::SetUserAgentL
+//
+// -----------------------------------------------------------------------------
+//
+void CCRRtspCommand::SetUserAgentL( const TDesC8& aUserAgent )
+ {
+ delete iUserAgent; iUserAgent = NULL;
+ iUserAgent = aUserAgent.AllocL();
+ }
+
+// -----------------------------------------------------------------------------
+// CCRRtspCommand::SetBandwidth
+//
+// -----------------------------------------------------------------------------
+//
+void CCRRtspCommand::SetBandwidth( TInt aBandwidth )
+ {
+ iBandwidth = aBandwidth;
+ iBandwidthAvailable = ETrue;
+ }
+
+// -----------------------------------------------------------------------------
+// CCRRtspCommand::SetWapProfileL
+//
+// -----------------------------------------------------------------------------
+//
+void CCRRtspCommand::SetWapProfileL( const TDesC8& aWapProfile )
+ {
+ delete iWapProfile; iWapProfile = NULL;
+ iWapProfile = aWapProfile.AllocL();
+ }
+
+// -----------------------------------------------------------------------------
+// CCRRtspCommand::SetCommand
+//
+// -----------------------------------------------------------------------------
+//
+void CCRRtspCommand::SetCommand( TCommand aCommand )
+ {
+ iCommand = aCommand;
+ }
+
+// -----------------------------------------------------------------------------
+// CCRRtspCommand::Command
+//
+// -----------------------------------------------------------------------------
+//
+CCRRtspCommand::TCommand CCRRtspCommand::Command( void ) const
+ {
+ return iCommand;
+ }
+
+// -----------------------------------------------------------------------------
+// CCRRtspCommand::ProduceL
+//
+// -----------------------------------------------------------------------------
+//
+TPtrC8& CCRRtspCommand::ProduceL( void )
+ {
+ // First common part for all commands, except actual command
+ delete iRtspText; iRtspText = NULL;
+ iRtspText = HBufC8::NewL( KMaxName );
+ iRtspText->Des().Zero();
+
+ switch ( iCommand )
+ {
+ case ERTSPCommandOPTIONS:
+ AppendL( iRtspText, KCROPTIONS );
+ break;
+
+ case ERTSPCommandDESCRIBE:
+ AppendL( iRtspText, KCRDESCRIBE );
+ break;
+
+ case ERTSPCommandTEARDOWN:
+ AppendL( iRtspText, KCRTEARDOWN );
+ break;
+
+ case ERTSPCommandPAUSE:
+ AppendL( iRtspText, KCRPAUSE );
+ break;
+
+ case ERTSPCommandSETUP:
+ AppendL( iRtspText, KCRSETUP );
+ break;
+
+ case ERTSPCommandPLAY :
+ AppendL( iRtspText, KCRPLAY );
+ break;
+
+ default:
+ User::Leave( KErrNotSupported );
+ break;
+ }
+
+ AppendL( iRtspText, iURL );
+ AppendL( iRtspText, KCRSpace );
+ AppendL( iRtspText, KCRRTSP10 );
+ AppendL( iRtspText, KCRNewLine );
+ AppendL( iRtspText, KCRCSeq );
+ AppendNumL( iRtspText, iCSeq );
+ AppendL( iRtspText, KCRNewLine );
+
+ if ( iUserAgent )
+ {
+ TPtrC8 useragent( iUserAgent->Des() );
+ AppendFormatL( iRtspText, KCRRTSPUserAgentHeader, &useragent );
+ }
+
+ // then variable tail depending on command
+ switch ( iCommand )
+ {
+ case ERTSPCommandOPTIONS:
+ if ( iSessionId.Ptr() != NULL )
+ {
+ AppendL( iRtspText, KCRSessionStr() );
+ AppendL( iRtspText, iSessionId ); // now only session number
+ AppendL( iRtspText, KCRNewLine );
+ }
+ break;
+
+ case ERTSPCommandDESCRIBE:
+ {
+ AppendL( iRtspText, KCRAcceptSDP );
+ if ( iWapProfile )
+ {
+ TPtrC8 profile = iWapProfile->Des();
+ AppendFormatL( iRtspText, KCRRTSPXWapProfile, &profile );
+ }
+ if ( iBandwidthAvailable )
+ {
+ AppendFormatL( iRtspText, KCRRTSPBandwidth, iBandwidth );
+ }
+ }
+ break;
+
+ case ERTSPCommandTEARDOWN:
+ if ( iSessionId.Ptr() != NULL )
+ {
+ AppendL( iRtspText, KCRSessionStr() );
+ AppendL( iRtspText, iSessionId ); // now only session number
+ AppendL( iRtspText, KCRNewLine );
+ }
+ break;
+
+ case ERTSPCommandPAUSE:
+ if ( iSessionId.Ptr() != NULL )
+ {
+ AppendL( iRtspText, KCRSessionStr() );
+ AppendL( iRtspText, iSessionId ); // now only session number
+ AppendL( iRtspText, KCRNewLine );
+ }
+ break;
+
+ case ERTSPCommandSETUP:
+ {
+ // build transport header according to chosen method
+ switch ( iTransport )
+ {
+ case ERTPOverUDP:
+ AppendFormatL( iRtspText, KCRTransportHeaderUDP,
+ iClientPort, iClientPort + 1 );
+ break;
+ case ERTPOverTCP:
+ AppendFormatL( iRtspText, KCRTransportHeaderTCP,
+ iClientPort, iClientPort + 1 );
+ break;
+
+ case ERTPOverMulticast:
+ AppendL( iRtspText, KCRTransportHeaderMulticast );
+ break;
+ }
+
+ // Session: 5273458854096827704
+ if ( iSessionId.Ptr() != NULL )
+ {
+ AppendL( iRtspText, KCRSessionStr );
+ AppendL( iRtspText, iSessionId ); // now only session number
+ AppendL( iRtspText, KCRNewLine );
+ }
+ if ( iWapProfile )
+ {
+ TPtrC8 profile( iWapProfile->Des() );
+ AppendFormatL( iRtspText, KCRRTSPXWapProfile, &profile );
+ }
+ }
+ break;
+
+ case ERTSPCommandPLAY:
+ {
+ if ( !( iLowerRange == KRealZero && iUpperRange == KRealMinusOne ) )
+ {
+ // Range was something else than 0,-1
+ TBuf8<KMaxName> buf( KCRRangeHeader );
+ TRealFormat format( 10, 3 );
+ format.iTriLen = 0;
+ format.iPoint = '.';
+ buf.AppendNum( iLowerRange, format );
+ buf.Append( '-' );
+ if ( iUpperRange > KRealZero )
+ {
+ buf.AppendNum( iUpperRange, format );
+ }
+
+ buf.Append( KCRNewLine );
+ AppendL( iRtspText, buf );
+ }
+ if ( iSessionId.Ptr() != NULL )
+ {
+ AppendL( iRtspText, KCRSessionStr() );
+ AppendL( iRtspText, iSessionId ); // now only session number
+ AppendL( iRtspText, KCRNewLine );
+ }
+ }
+ break;
+
+ default:
+ User::Leave( KErrNotSupported );
+ break;
+ }
+
+ if ( iAuthenticationNeeded )
+ {
+ TBool useDigest( EFalse );
+
+ if ( iAuthType && ( iAuthType->FindC( KCRAuthDigest ) != KErrNotFound ) )
+ {
+ useDigest = ETrue;
+ }
+
+ switch ( iCommand )
+ {
+ case ERTSPCommandOPTIONS :
+ useDigest ? CalculateDigestResponseL( KCROPTIONSNoSpace ) :
+ CalculateBasicResponseL( KCROPTIONSNoSpace );
+
+ if ( iAuthHeader )
+ {
+ AppendL( iRtspText, iAuthHeader->Des() );
+ }
+ break;
+
+ case ERTSPCommandDESCRIBE :
+ useDigest ? CalculateDigestResponseL( KCRDESCRIBENoSpace ) :
+ CalculateBasicResponseL( KCRDESCRIBENoSpace );
+
+ if ( iAuthHeader )
+ {
+ AppendL( iRtspText, iAuthHeader->Des() );
+ }
+ break;
+
+ case ERTSPCommandTEARDOWN :
+ useDigest ? CalculateDigestResponseL( KCRTEARDOWNNoSpace ) :
+ CalculateBasicResponseL( KCRTEARDOWNNoSpace );
+
+ if ( iAuthHeader )
+ {
+ AppendL( iRtspText, iAuthHeader->Des() );
+ }
+ break;
+
+ case ERTSPCommandPAUSE :
+ useDigest ? CalculateDigestResponseL( KCRPAUSENoSpace ) :
+ CalculateBasicResponseL( KCRPAUSENoSpace );
+
+ if ( iAuthHeader )
+ {
+ AppendL( iRtspText, iAuthHeader->Des() );
+ }
+ break;
+
+ case ERTSPCommandSETUP :
+ useDigest ? CalculateDigestResponseL( KCRSETUPNoSpace ) :
+ CalculateBasicResponseL( KCRSETUPNoSpace );
+
+ if ( iAuthHeader )
+ {
+ AppendL( iRtspText, iAuthHeader->Des() );
+ }
+ break;
+
+ case ERTSPCommandPLAY :
+ useDigest ? CalculateDigestResponseL( KCRPLAYNoSpace ) :
+ CalculateBasicResponseL( KCRPLAYNoSpace );
+
+ if ( iAuthHeader )
+ {
+ AppendL( iRtspText, iAuthHeader->Des() );
+ }
+ break;
+
+ default:
+ User::Leave( KErrNotSupported );
+ break;
+ }
+ }
+
+ AppendL( iRtspText, KCRNewLine );
+ iProductDescriptor.Set( *iRtspText );
+ return iProductDescriptor;
+ }
+
+// -----------------------------------------------------------------------------
+// CCRRtspCommand::AppendL
+//
+// -----------------------------------------------------------------------------
+//
+void CCRRtspCommand::AppendL( HBufC8*& aBuffer, const TDesC8& aStr )
+ {
+ TPtr8 ptr( aBuffer->Des() );
+ if ( ( ptr.Length() + aStr.Length() ) >= ptr.MaxLength() )
+ {
+ const TInt newLength( ptr.Length() + aStr.Length() + KMaxName );
+ aBuffer = aBuffer->ReAllocL( newLength );
+ ptr.Set( aBuffer->Des() );
+ }
+
+ ptr.Append( aStr );
+ }
+
+// -----------------------------------------------------------------------------
+// CCRRtspCommand::AppendNumL
+//
+// -----------------------------------------------------------------------------
+//
+void CCRRtspCommand::AppendNumL( HBufC8*& aBuffer, const TInt aNum )
+ {
+ TPtr8 ptr( aBuffer->Des() );
+ if ( ( ptr.Length() + KMaxInfoName ) >= ptr.MaxLength() )
+ {
+ const TInt newLength( ptr.Length() + KMaxInfoName + KMaxName );
+ aBuffer = aBuffer->ReAllocL( newLength );
+ ptr.Set( aBuffer->Des() );
+ }
+
+ ptr.AppendNum( aNum );
+ }
+
+// -----------------------------------------------------------------------------
+// CCRRtspCommand::AppendFormatL
+//
+// -----------------------------------------------------------------------------
+//
+void CCRRtspCommand::AppendFormatL(
+ HBufC8*& aBuffer,
+ TRefByValue<const TDesC8> aFmt, ... )
+ {
+ VA_LIST list;
+ VA_START( list, aFmt );
+ HBufC8* buf = HBufC8::NewLC( KMaxDataSize );
+ buf->Des().FormatList( aFmt, list );
+ VA_END( list );
+
+ TPtr8 ptr( aBuffer->Des() );
+ if ( ( ptr.Length() + buf->Length() ) >= ptr.MaxLength() )
+ {
+ const TInt newLength( ptr.Length() + buf->Length() + KMaxName );
+ aBuffer = aBuffer->ReAllocL( newLength );
+ ptr.Set( aBuffer->Des() );
+ }
+
+ ptr.Append( *buf );
+ CleanupStack::PopAndDestroy( buf );
+ }
+
+// -----------------------------------------------------------------------------
+// CCRRtspCommand::Hash
+// Calculates hash value ( from S60 HttpFilters )
+// -----------------------------------------------------------------------------
+//
+void CCRRtspCommand::HashL( const TDesC8& aMessage, TDes8& aHash )
+ {
+ LOG( "CCRRtspCommand::HashL() in" );
+ // check if md5 calculator is already constructed
+ if ( !iMD5Calculator )
+ {
+ iMD5Calculator = CMD5::NewL();
+ }
+ // Calculate the 128 bit (16 byte) hash
+ iMD5Calculator->Reset();
+ TPtrC8 hash = iMD5Calculator->Hash( aMessage );
+
+ // Now print it as a 32 byte hex number
+ aHash.Zero();
+ _LIT8( formatStr, "%02x" );
+ TBuf8<2> scratch;
+ for ( TInt i( 0 ); i < KCRRawHashLength; i++ )
+ {
+ scratch.Zero();
+ scratch.Format( formatStr, hash[i] );
+ aHash.Append( scratch );
+ }
+
+ LOG( "CCRRtspCommand::HashL() out" );
+ }
+
+// -----------------------------------------------------------------------------
+// CCRRtspCommand::CalculateBasicResponseL
+//
+// -----------------------------------------------------------------------------
+//
+void CCRRtspCommand::CalculateBasicResponseL( const TDesC8& /*aMethod*/ )
+ {
+ LOG( "CCRRtspCommand::CalculateBasicResponseL() in" );
+
+ if ( !( iUserName && iPassword ) )
+ {
+ LOG( "CCRRtspCommand::CalculateBasicResponseL() out, username or password not set" );
+ delete iAuthHeader;
+ iAuthHeader = NULL;
+ return; // no can do
+ }
+
+ HBufC8* plainData = HBufC8::NewL( iUserName->Length() + 1 + // ':'
+ iPassword->Length() );
+
+ CleanupStack::PushL( plainData );
+
+ plainData->Des().Append( *iUserName );
+ plainData->Des().Append( ':' );
+ plainData->Des().Append( *iPassword );
+
+ // Max size = ((Bytes + 3 - (Bytes MOD 3)) /3) x 4
+ TInt base64MaxSize = ( ( plainData->Length() + 3 -
+ ( plainData->Length() % 3 ) ) / 3 ) * 4;
+
+ HBufC8* encodedData = HBufC8::NewL( base64MaxSize );
+ TPtr8 dataPrt( encodedData->Des() );
+ CleanupStack::PushL( encodedData );
+
+ TImCodecB64 b64enc;
+ b64enc.Initialise();
+ b64enc.Encode( *plainData, dataPrt );
+
+ delete iAuthHeader;
+ iAuthHeader = NULL;
+ iAuthHeader = HBufC8::NewL( KCRAuthorizationBasicHeader().Length() + encodedData->Length() );
+ iAuthHeader->Des().Format( KCRAuthorizationBasicHeader, encodedData );
+
+ CleanupStack::PopAndDestroy( encodedData );
+ CleanupStack::PopAndDestroy( plainData );
+
+ LOG( "CCRRtspCommand::CalculateBasicResponseL() out" );
+ }
+
+// -----------------------------------------------------------------------------
+// CCRRtspCommand::CalculateDigestResponseL
+//
+// -----------------------------------------------------------------------------
+//
+void CCRRtspCommand::CalculateDigestResponseL( const TDesC8& aMethod )
+ {
+ LOG( "CCRRtspCommand::CalculateDigestResponseL() in" );
+
+ if ( !( iUserName && iPassword && iNonce && iOpaque && iRealm && iUri ) )
+ {
+ LOG( "CCRRtspCommand::CalculateDigestResponseL() out, username or password not set" );
+ delete iAuthHeader; iAuthHeader = NULL;
+ return; // no can do
+ }
+
+ TBuf8<KCRHashLength> hash1;
+ TBuf8<KCRHashLength> hash2;
+ TBuf8<KCRHashLength> finalHash;
+
+ // calculate the hash1 using "username:realm:password"
+ HBufC8* hashPtr = HBufC8::NewL ( iUserName->Length() + 1 + // ':'
+ iRealm->Length() + 1 + // ':'
+ iPassword->Length() );
+ hashPtr->Des().Append( *iUserName );
+ hashPtr->Des().Append( ':' );
+ hashPtr->Des().Append( *iRealm );
+ hashPtr->Des().Append( ':' );
+ hashPtr->Des().Append( *iPassword );
+
+ HashL( *hashPtr, hash1 );
+ delete hashPtr; hashPtr = NULL;
+
+ // calculate hash2 using "Method:uri"
+ HBufC8* hashPtr2 = HBufC8::NewL(aMethod.Length() + 1 + iUri->Length() );
+ hashPtr2->Des().Append( aMethod );
+ hashPtr2->Des().Append( ':' );
+ hashPtr2->Des().Append( *iUri );
+
+ HashL( *hashPtr2, hash2 );
+ delete hashPtr2; hashPtr2 = NULL;
+
+ // calculate finalHash to be sent to remote server using
+ // hash1 + ":" + nonce + ":" + hash2
+ HBufC8* hashPtr3 = HBufC8::NewL( hash1.Length() + 1 + // ':'
+ iNonce->Length() + 1 + // ':'
+ hash2.Length() );
+ hashPtr3->Des().Append( hash1 );
+ hashPtr3->Des().Append( ':' );
+ hashPtr3->Des().Append( *iNonce );
+ hashPtr3->Des().Append( ':' );
+ hashPtr3->Des().Append( hash2 );
+
+ HashL( *hashPtr3, finalHash );
+ delete hashPtr3; hashPtr3 = NULL;
+
+ // generate the authentication header
+ if ( iOpaque->Length() )
+ {
+ delete iAuthHeader; iAuthHeader = NULL;
+ iAuthHeader = HBufC8::NewL( KCRAuthorizationHeader().Length() +
+ iUserName->Length() + iRealm->Length() + iNonce->Length() +
+ iUri->Length() + finalHash.Length() + iOpaque->Length() );
+
+ iAuthHeader->Des().Format( KCRAuthorizationHeader, iUserName,
+ iRealm, iNonce, iUri, &finalHash, iOpaque );
+ }
+ else
+ {
+ delete iAuthHeader; iAuthHeader = NULL;
+ iAuthHeader = HBufC8::NewL( KCRAuthorizationHeaderNoOpaque().Length() +
+ iUserName->Length() + iRealm->Length() + iNonce->Length() +
+ iUri->Length() + finalHash.Length() );
+
+ iAuthHeader->Des().Format( KCRAuthorizationHeaderNoOpaque, iUserName,
+ iRealm, iNonce, iUri, &finalHash );
+ }
+
+ LOG( "CCRRtspCommand::CalculateDigestResponseL() out" );
+ }
+
+// End of File