--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/omadrm/drmplugins/drmfilter/src/HTTPFilterDRM.cpp Thu Dec 17 08:52:27 2009 +0200
@@ -0,0 +1,737 @@
+/*
+ * Copyright (c) 2006 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 the DRM Filter HTTP Filter
+ *
+ */
+
+#include <http/rhttptransaction.h>
+#include <http/rhttpheaders.h>
+#include <http/rhttpresponse.h>
+#include <httpstringconstants.h>
+#include <httperr.h>
+#include <bautils.h>
+#include <drmmessageparser.h>
+
+#include "httpfilterdrm.h"
+
+// LOCAL CONSTANTS
+_LIT8( KDRMString1, "application/vnd.oma.drm.message" );
+// FL or CD
+
+_LIT8( KDRMString3, "application/vnd.oma.drm.content" );
+// SD only
+
+_LIT8( KJADString, "text/vnd.sun.j2me.app-descriptor" );
+// Jad files
+
+_LIT8( KXOmaFieldName, "x-oma-drm-separate-delivery");
+// Estimated arrival time for rights of the SD content
+
+_LIT8( KDRMOldContentType, "x-drm-old-content-type");
+// old content type header to be added
+
+_LIT8( KHTTPFilterDRMName, "DRM");
+// Name of filter
+
+_LIT8( KCFMRingtoneStr, "ringtone");
+// cfm ringtone string
+
+_LIT8( KCFMFwdStr, "fwd");
+// cfm forward string
+
+_LIT8( KCFMValStr, "no");
+// cfm negative value string
+
+const TInt KXOmaDefaultValue = 25;
+//default value for the 'x-oma-drm-separate-delivery' header
+
+const TInt KCFMFieldMaxLength( 200 );
+const TInt KBadMimeType( -12002 ); // common error code
+const TInt NW_STAT_FAILURE( -20000 ); // common error code
+
+// format for output of data/time values
+#if defined (_DEBUG) && defined (_LOGGING)
+_LIT(KDateFormat,"%D%M%Y%/0%1%/1%2%/2%3%/3 %:0%H%:1%T%:2%S.%C%:3");
+#endif
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CHTTPFilterDRM::CHTTPFilterDRM
+// Constructor
+// -----------------------------------------------------------------------------
+//
+CHTTPFilterDRM::CHTTPFilterDRM( RHTTPSession aSession ) :
+ iSession( aSession )
+ {
+ iDataSups.Reset();
+ }
+
+// -----------------------------------------------------------------------------
+// CHTTPFilterDRM::InstallFilterL
+// Initialize the filter and register it to sesssion's filter collection
+// -----------------------------------------------------------------------------
+//
+CEComFilter* CHTTPFilterDRM::InstallFilterL( TAny* aSession )
+ {
+ RHTTPSession* session = REINTERPRET_CAST(RHTTPSession*, aSession);
+ CHTTPFilterDRM* filter = new ( ELeave ) CHTTPFilterDRM( *session );
+ CleanupStack::PushL( filter );
+
+ filter->ConstructL( *session );
+ CleanupStack::Pop( filter );
+
+ return filter;
+ }
+
+// -----------------------------------------------------------------------------
+// CHTTPFilterDRM::ConstructL
+// Memory and resource allocation, leaves
+// -----------------------------------------------------------------------------
+//
+void CHTTPFilterDRM::ConstructL( RHTTPSession aSession )
+ {
+ iStringPool = aSession.StringPool();
+
+ const TInt KPriorityDelta( 10 );
+ // register the filter
+ RStringF filterName = iStringPool.OpenFStringL( KHTTPFilterDRMName );
+ CleanupClosePushL( filterName );
+ iSession.FilterCollection().AddFilterL( *this,
+ THTTPEvent::EGotResponseHeaders, // Any transaction event
+ MHTTPFilter::EProtocolHandler + KPriorityDelta, // Priority of filter
+ filterName ); // Name of filter
+ iSession.FilterCollection().AddFilterL( *this,
+ THTTPEvent::EGotResponseBodyData,
+ MHTTPFilter::EProtocolHandler + KPriorityDelta,
+ filterName );
+ iSession.FilterCollection().AddFilterL( *this,
+ THTTPEvent::EResponseComplete,
+ MHTTPFilter::EProtocolHandler + KPriorityDelta,
+ filterName );
+ iSession.FilterCollection().AddFilterL( *this,
+ THTTPEvent::EFailed,
+ MHTTPFilter::EProtocolHandler + KPriorityDelta,
+ filterName );
+ iSession.FilterCollection().AddFilterL( *this,
+ THTTPEvent::EClosed,
+ MHTTPFilter::EProtocolHandler + KPriorityDelta,
+ filterName );
+ CleanupStack::PopAndDestroy( &filterName );
+
+ // log file
+ __OPEN_LOG( "DRM.LOG" );
+ __LOG( _L ( "--Initialize DRM Filter---\n" ) );
+
+ }
+
+//------------------------------------------------------------------------
+// CHTTPFilterDRM::~CHTTPFilterDRM
+// Destructor
+//------------------------------------------------------------------------
+//
+CHTTPFilterDRM::~CHTTPFilterDRM()
+ {
+ // If we've been destroyed from the cleanup stack during creation
+ // of the object, it might still be loaded. So check. (Normaly the
+ // delete is initiated by the 'delete this' in MHFUnload)
+ if ( iLoadCount )
+ {
+ // As we're already in a destructor, MHFUnload must not delete us again
+ iLoadCount = -1;
+ RStringF filterName;
+ TRAPD( error, ( filterName = iStringPool.OpenFStringL( KHTTPFilterDRMName ) ) );
+ if ( error == KErrNone )
+ iSession.FilterCollection().RemoveFilter( filterName );
+ filterName.Close();
+ }
+
+ CleanupAll();
+ iDataSups.Close();
+ }
+
+//------------------------------------------------------------------------
+// CHTTPFilterDRM::DeleteDataSupplier
+//------------------------------------------------------------------------
+//
+void CHTTPFilterDRM::DeleteDataSupplier( TInt aTransId )
+ {
+ __LOG( _L ( "CHTTPFilterDRM::DeleteDataSupplier" ) );
+ TInt idx( KErrNotFound );
+ for ( TInt i = 0; idx == KErrNotFound && i < iDataSups.Count(); ++i )
+ {
+ if ( iDataSups[i]->GetTransId() == aTransId )
+ {
+ idx = i;
+ }
+ }
+
+ if ( idx != KErrNotFound )
+ {
+ __LOG1( _L ( "CHTTPFilterDRM::DeleteDataSupplier: deleting transaction %d." ), aTransId );
+ // remove the problematic data supplier
+ CHTTPFilterDRMDataSupplier* sup = iDataSups[idx];
+ iDataSups.Remove( idx );
+ delete sup;
+ sup = NULL;
+ }
+ }
+
+//------------------------------------------------------------------------
+// CHTTPFilterDRM::MHFLoad
+// See MHTTPFilterBase::MHFRunL
+//------------------------------------------------------------------------
+//
+void CHTTPFilterDRM::MHFLoad( RHTTPSession, THTTPFilterHandle )
+ {
+ __LOG( _L ( "--Load DRM Filter---\n" ) );
+ ++iLoadCount;
+ }
+
+//------------------------------------------------------------------------
+// CHTTPFilterDRM::MHFUnload
+// See MHTTPFilterBase::MHFRunError
+//------------------------------------------------------------------------
+//
+void CHTTPFilterDRM::MHFUnload( RHTTPSession, THTTPFilterHandle )
+ {
+ __LOG( _L ( "--Unload DRM Filter---\n" ) );
+ if ( --iLoadCount )
+ {
+ return;
+ }
+
+ delete this;
+ }
+
+//------------------------------------------------------------------------
+// CHTTPFilterDRM::MHFRunL
+// See MHTTPFilterBase::MHFRunL
+//------------------------------------------------------------------------
+//
+void CHTTPFilterDRM::MHFRunL( RHTTPTransaction aTransaction,
+ const THTTPEvent& aEvent )
+ {
+ if ( aEvent.iUID != KHTTPUid )
+ return;
+
+ switch ( aEvent.iStatus )
+ {
+ case THTTPEvent::EGotResponseHeaders:
+ {
+ __LOG( _L ( "Event: EGotResponseHeaders\n" ) );
+ CheckHeadersL( aTransaction );
+ }
+ break;
+ case THTTPEvent::EGotResponseBodyData:
+ {
+ __LOG( _L ( "Event: EGotResponseBodyData\n" ) );
+ TInt idx = GetDRMTransIdx( aTransaction );
+ if ( idx != KErrNotFound )
+ {
+ // for x-oma-drm-separate-delivery purpose
+ if ( iXOmaHeaderVal )
+ {
+ iDataSups[idx]->SetEstimatedArrivalTime( iXOmaHeaderVal );
+ iXOmaHeaderVal = 0;
+
+ //remove the DataSuuplier
+ delete iDataSups[idx];
+ iDataSups.Remove( idx );
+ }
+ else
+ {
+ iDataSups[idx]->ProcessDataPartL();
+ }
+ }
+ }
+ break;
+ case THTTPEvent::EResponseComplete:
+ {
+ __LOG( _L ( "Event: EResponseComplete\n" ) );
+ }
+ break;
+ case THTTPEvent::EFailed:
+ {
+ __LOG( _L ( "Event: EFailed\n" ) );
+ Cleanup( aTransaction );
+ }
+ break;
+ case THTTPEvent::EClosed:
+ {
+ __LOG( _L ( "Event: EClosed\n" ) );
+ }
+ break;
+ default:
+ {
+ __LOG1( _L ( "Unknow Event: ID - %d\n" ), aEvent.iStatus );
+ }
+ break;
+ }
+ }
+
+const static TInt KGlobalErrs[] =
+ {
+ NW_STAT_FAILURE,
+ KBadMimeType,
+ KBadMimeType,
+ NW_STAT_FAILURE,
+ KBadMimeType,
+ KBadMimeType,
+ KBadMimeType,
+ KBadMimeType,
+ KBadMimeType
+ };
+
+//------------------------------------------------------------------------
+// CHTTPFilterDRM::MHFRunError
+// See MHTTPFilterBase::MHFRunError
+//------------------------------------------------------------------------
+//
+TInt CHTTPFilterDRM::MHFRunError( TInt aError, RHTTPTransaction aTransaction,
+ const THTTPEvent& )
+ {
+ TInt error = 0;
+ TInt error2 = KErrNone;
+ // map aError to global error message
+
+ if ( aError >= DRMCommon::EInvalidRights && aError
+ <= DRMCommon::EGeneralError )
+ error = KGlobalErrs[DRMCommon::EGeneralError - aError];
+ else
+ error = aError;
+
+ //to map caf errors and KErrCorrupt to display
+ switch ( aError )
+ {
+ case KErrCANotSupported:
+ case KErrCANoPermission:
+ case KErrCANoRights:
+ case KErrCorrupt:
+ {
+ error = NW_STAT_FAILURE; //Unable to perform operation
+ }
+ break;
+ case KErrArgument:
+ {
+ error = KBadMimeType;
+ }
+ break;
+ case KErrCANoAgent:
+ case KErrCAOutOfRange:
+ case KErrCAPendingRights:
+ case KErrCASizeNotDetermined:
+ case KErrCANewFileHandleRequired:
+ {
+ error = NW_STAT_FAILURE;
+ }
+ break;
+ default:
+ {
+ error = NW_STAT_FAILURE;
+ }
+ break;
+ }
+
+ // pass the errorcode forward
+ THTTPEvent httpEvent( error );
+ TRAP( error2, aTransaction.SendEventL(httpEvent, THTTPEvent::EIncoming, THTTPFilterHandle::ECurrentFilter ));
+
+ return error2;
+ }
+
+//------------------------------------------------------------------------
+// CHTTPFilterDRM::MHFSessionRunL
+// See MHTTPFilterBase::MHFSessionRunL
+//------------------------------------------------------------------------
+//
+void CHTTPFilterDRM::MHFSessionRunL( const THTTPSessionEvent& )
+ {
+ // do nothing
+ }
+
+//------------------------------------------------------------------------
+// CHTTPFilterDRM::MHFSessionRunL
+// See MHTTPFilterBase::MHFSessionRunL
+//------------------------------------------------------------------------
+//
+TInt CHTTPFilterDRM::MHFSessionRunError( TInt aError,
+ const THTTPSessionEvent& )
+ {
+ // session problem, need to close DRM engine
+ CleanupAll();
+ return aError;
+ }
+
+//------------------------------------------------------------------------
+// CHTTPFilterDRM::DumpResponseHeadersL
+// Dump the response headers to LOG file
+//------------------------------------------------------------------------
+//
+#if defined (_DEBUG) && defined (_LOGGING)
+void CHTTPFilterDRM::DumpResponseHeadersL( RHTTPResponse& aResponse )
+ {
+ __LOG( _L ( "Dump the header...\n" ) );
+
+ RHTTPHeaders headers = aResponse.GetHeaderCollection();
+ RStringPool strP = iSession.StringPool();
+ THTTPHdrFieldIter it = headers.Fields();
+
+ while ( it.AtEnd() == EFalse )
+ {
+ RStringTokenF fieldName = it();
+ RStringF fieldNameStr = strP.StringF( fieldName );
+ THTTPHdrVal fieldVal;
+ TInt fieldParts = 0; // For the case if next the call fails.
+ TRAPD( ignoreErr, fieldParts = headers.FieldPartsL( fieldNameStr ) );
+
+ // dump the first part of a header field
+ for ( TInt ii = 0; ii < fieldParts; ii++ )
+ {
+ if ( headers.GetField( fieldNameStr, ii, fieldVal ) == KErrNone )
+ {
+ const TDesC8& fieldNameDesC = fieldNameStr.DesC();
+ __DUMPBIN( fieldNameDesC );
+ __LOG( _L ( " : " ) );
+
+ switch ( fieldVal.Type() )
+ {
+ case THTTPHdrVal::KTIntVal:
+ {
+ __LOG1( _L ( "%d" ), fieldVal.Int() );
+ }
+ break;
+ case THTTPHdrVal::KStrFVal:
+ {
+ RStringF fieldValStr = strP.StringF( fieldVal.StrF() );
+ const TDesC8& fieldValDesC = fieldValStr.DesC();
+ __DUMPBIN( fieldValDesC );
+ }
+ break;
+ case THTTPHdrVal::KStrVal:
+ {
+ RString fieldValStr = strP.String( fieldVal.Str() );
+ const TDesC8& fieldValDesC = fieldValStr.DesC();
+ __DUMPBIN( fieldValDesC );
+ }
+ break;
+ case THTTPHdrVal::KDateVal:
+ {
+ const TInt KDateTimeMaxLength( 40 );
+ TDateTime date = fieldVal.DateTime();
+ TBuf<KDateTimeMaxLength> dateTimeString;
+ TTime t( date );
+ t.FormatL( dateTimeString, KDateFormat );
+ TBuf8<KDateTimeMaxLength> dtStr;
+ dtStr.Copy( dateTimeString.Left( KDateTimeMaxLength ) );
+ __DUMPBIN( dtStr );
+ }
+ break;
+ case THTTPHdrVal::KNoType:
+ default:
+ {
+ __LOG( _L ( "Unrecognized value type.\n" ) );
+ }
+ break;
+ }
+
+ __LOG( _L ( "\n" ) );
+ }
+ }
+
+ ++it;
+ }
+ __LOG( _L ( "Header is Dumped already...\n" ) );
+
+ }
+#endif
+
+//------------------------------------------------------------------------
+// CHTTPFilterDRM::CheckHeadersL
+// Check HTTP headers and extract MIME type
+//------------------------------------------------------------------------
+//
+void CHTTPFilterDRM::CheckHeadersL( const RHTTPTransaction& aTrans )
+ {
+ // read the header data and check the MIME type here
+ // check the status and body
+ RHTTPResponse response = aTrans.Response();
+ TInt status = response.StatusCode();
+
+#if defined (_DEBUG) && defined (_LOGGING)
+ DumpResponseHeadersL( response );
+#endif
+
+ THTTPHdrVal fieldVal;
+ // check if the content type is application/vnd.oma.drm.message
+ if ( ( status >= HTTPStatus::EOk ) &&
+ ( status < HTTPStatus::EMultipleChoices ) &&
+ ( status != HTTPStatus::ENoContent ) )
+ {
+ const TBuf8<sizeof( KDRMString1 )> DRMStringBuf1( KDRMString1 );
+ const TBuf8<sizeof( KDRMString3 )> DRMStringBuf3( KDRMString3 );
+ const TBuf8<sizeof( KDRMOldContentType )> DRMHeaderName(
+ KDRMOldContentType );
+
+ RHTTPHeaders headers = response.GetHeaderCollection();
+ RStringPool strP = iSession.StringPool();
+ RStringF fieldNameStr = strP.StringF( HTTP::EContentType,
+ RHTTPSession::GetTable() );
+
+ if ( headers.GetField( fieldNameStr, 0, fieldVal ) == KErrNone )
+ {
+ RStringF fieldValStr = strP.StringF( fieldVal.StrF() );
+
+ RStringF DRMValue1 = strP.OpenFStringL( DRMStringBuf1 );
+ CleanupClosePushL( DRMValue1 );
+
+ RStringF DRMValue3 = strP.OpenFStringL( DRMStringBuf3 );
+ CleanupClosePushL( DRMValue3 );
+
+ RStringF DRMHeaderNameF = strP.OpenFStringL( DRMHeaderName );
+ CleanupClosePushL( DRMHeaderNameF );
+
+ // DRM message
+ if ( DRMValue1 == fieldValStr )
+ {
+ __LOG( _L ("DRM content exists, a new dummy data supplier is created!\n" ) );
+
+ CHTTPFilterDRMDataSupplier* drmData = 0;
+
+ drmData = CHTTPFilterDRMDataSupplier::NewL( aTrans.Id(),
+ response.Body(), const_cast<CHTTPFilterDRM*> ( this ) );
+ /** Support for Hutchinson's content protection scheme, CFM
+ *
+ */
+ drmData->SetProcessedContentType( EStandardDRMContent );
+ /**
+ *
+ */
+ iDataSups.Append( drmData );
+ response.SetBody( *drmData );
+
+ // change the mime type to "application/vnd.oma.drm.content"
+ headers.RemoveField( fieldNameStr );
+ headers.SetFieldL( fieldNameStr, THTTPHdrVal( DRMValue3 ) );
+
+ // add the new header
+ headers.SetFieldL( DRMHeaderNameF, THTTPHdrVal( DRMValue1 ) );
+
+ }
+ else if ( DRMValue3 == fieldValStr )
+ {
+ RStringF xOmaFieldName = strP.OpenFStringL( KXOmaFieldName );
+ if ( headers.GetField( xOmaFieldName, 0, fieldVal )
+ == KErrNone )
+ {
+ iXOmaHeaderVal = KXOmaDefaultValue;
+
+ switch ( fieldVal.Type() )
+ {
+ case THTTPHdrVal::KStrFVal:
+ {
+ TLex8 lexer( fieldVal.StrF().DesC() );
+ lexer.Val( iXOmaHeaderVal );
+ }
+ break;
+ case THTTPHdrVal::KStrVal:
+ {
+ TLex8 lexer( fieldVal.Str().DesC() );
+ lexer.Val( iXOmaHeaderVal );
+ }
+ break;
+ case THTTPHdrVal::KTIntVal:
+ {
+ iXOmaHeaderVal = fieldVal.Int();
+ }
+ break;
+ }
+ }
+ xOmaFieldName.Close();
+ if ( iXOmaHeaderVal ) //if header has value of 0 then will be ignored
+ {
+ CHTTPFilterDRMDataSupplier* drmData = 0;
+ drmData
+ = CHTTPFilterDRMDataSupplier::NewL( aTrans.Id(),
+ response.Body(),
+ const_cast<CHTTPFilterDRM*> ( this ) );
+ iDataSups.Append( drmData );
+ }
+
+ }
+
+ CleanupStack::PopAndDestroy( &DRMHeaderNameF );
+ CleanupStack::PopAndDestroy( &DRMValue3 );
+ CleanupStack::PopAndDestroy( &DRMValue1 );
+
+ // dump the header after modification
+#if defined (_DEBUG) && defined (_LOGGING)
+ __LOG( _L ("--- HEADER AFTER CHANGE ---\n") );
+ DumpResponseHeadersL( response );
+#endif
+ }
+
+ // CFM Content protection:
+ //========================
+
+ TInt idx = GetDRMTransIdx( aTrans );
+ if ( idx != KErrNotFound )
+ return;
+
+ TProcessedContentType currentContentType = EUnknownContent;
+
+ RStringF cfmValStr = strP.OpenFStringL( KCFMValStr );
+ CleanupClosePushL( cfmValStr );
+
+ // check "fwd=no"
+ RStringF cfmFwdStr = strP.OpenFStringL( KCFMFwdStr );
+ CleanupClosePushL( cfmFwdStr );
+ if ( headers.GetParam( fieldNameStr, cfmFwdStr, fieldVal )
+ != KErrNotFound )
+ {
+ RStringF fieldValStr = strP.StringF( fieldVal.StrF() );
+ TBufC8<KCFMFieldMaxLength> buf1 = fieldValStr.DesC();
+ if ( fieldValStr == cfmValStr )
+ {
+ currentContentType = EHutchinsonCFMNoFirstChunk;
+ }
+ }
+ CleanupStack::PopAndDestroy( &cfmFwdStr );
+
+ // check "ringtone=no"
+ RStringF cfmRingtoneStr = strP.OpenFStringL( KCFMRingtoneStr );
+ CleanupClosePushL( cfmRingtoneStr );
+
+ if ( headers.GetParam( fieldNameStr, cfmRingtoneStr, fieldVal )
+ != KErrNotFound )
+ {
+ RStringF fieldValStr = strP.StringF( fieldVal.StrF() );
+ TBufC8<KCFMFieldMaxLength> buf1 = fieldValStr.DesC();
+ if ( fieldValStr == cfmValStr )
+ {
+ currentContentType
+ = EHutchinsonCFMWithRingingToneNoFirstChunk;
+ }
+ }
+ CleanupStack::PopAndDestroy( &cfmRingtoneStr );
+ CleanupStack::PopAndDestroy( &cfmValStr );
+
+ // Do not encrypt JAD files:
+ if ( headers.GetField( fieldNameStr, 0, fieldVal ) == KErrNone )
+ {
+ // If it is a JAD always ignore any of the above:
+ const TBuf8<sizeof( KJADString )> JADStringBuf( KJADString );
+ RStringF JADValue = strP.OpenFStringL( JADStringBuf );
+ CleanupClosePushL( JADValue );
+
+ RStringF jadFieldValStr = strP.StringF( fieldVal.StrF() );
+ if ( JADValue == jadFieldValStr )
+ {
+ currentContentType = EUnknownContent;
+ }
+ CleanupStack::PopAndDestroy( &JADValue );
+ }
+
+ // Protect the content
+ if ( currentContentType != EUnknownContent ) // content protected
+ {
+ CHTTPFilterDRMDataSupplier* drmData = 0;
+ drmData = CHTTPFilterDRMDataSupplier::NewL( aTrans.Id(),
+ response.Body(), EHutchinsonCFMWithRingingToneNoFirstChunk,
+ const_cast<CHTTPFilterDRM*> ( this ) );
+ drmData->SetProcessedContentType( currentContentType );
+
+ if ( headers.GetField( fieldNameStr, 0, fieldVal ) == KErrNone )
+ {
+ drmData->SetContentMimeTypeL( fieldVal.StrF().DesC() );
+ }
+ else
+ {
+ delete drmData;
+ User::Leave( KErrUnknown );
+ }
+
+ iDataSups.Append( drmData );
+ response.SetBody( *drmData );
+
+ ///
+ RStringF DRMValue1 = strP.OpenFStringL( DRMStringBuf1 );
+ CleanupClosePushL( DRMValue1 );
+
+ RStringF DRMValue3 = strP.OpenFStringL( DRMStringBuf3 );
+ CleanupClosePushL( DRMValue3 );
+
+ RStringF DRMHeaderNameF = strP.OpenFStringL( DRMHeaderName );
+ CleanupClosePushL( DRMHeaderNameF );
+
+ // change the mime type to "application/vnd.oma.drm.content"
+
+ headers.RemoveField( fieldNameStr );
+ headers.SetFieldL( fieldNameStr, THTTPHdrVal( DRMValue3 ) );
+
+ // add the new header
+ headers.SetFieldL( DRMHeaderNameF, THTTPHdrVal( DRMValue1 ) );
+
+ CleanupStack::PopAndDestroy( &DRMHeaderNameF );
+ CleanupStack::PopAndDestroy( &DRMValue3 );
+ CleanupStack::PopAndDestroy( &DRMValue1 );
+ }
+ }
+ }
+
+//-----------------------------------------------------------------------------
+// CHTTPFilterDRM::GetDRMTransIdx
+// Retrieve the DRM datasupplier
+//-----------------------------------------------------------------------------
+//
+TInt CHTTPFilterDRM::GetDRMTransIdx( const RHTTPTransaction& aTrans ) const
+ {
+ for ( TInt i = 0; i < iDataSups.Count(); ++i )
+ {
+ if ( iDataSups[i]->GetTransId() == aTrans.Id() )
+ {
+ return i;
+ }
+ }
+ return KErrNotFound;
+ }
+
+//-----------------------------------------------------------------------------
+// CHTTPFilterDRM::Cleanup
+// Cleanup the resource related with a transaction
+//-----------------------------------------------------------------------------
+//
+void CHTTPFilterDRM::Cleanup( const RHTTPTransaction& aTrans )
+ {
+ TInt idx = GetDRMTransIdx( aTrans );
+ if ( idx != KErrNotFound )
+ {
+ // remove the problematic data supplier
+ CHTTPFilterDRMDataSupplier* sup = iDataSups[idx];
+ iDataSups.Remove( idx );
+ delete sup;
+ sup = NULL;
+ }
+ }
+
+//-----------------------------------------------------------------------------
+// CHTTPFilterDRM::CleanupAll
+// Cleanup all the DRM transactions, in case a session error happens or a session
+// is closed.
+//-----------------------------------------------------------------------------
+//
+void CHTTPFilterDRM::CleanupAll()
+ {
+ iDataSups.ResetAndDestroy();
+ }