--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mmsengine/mmsmessage/src/mmsdrm.cpp Thu Dec 17 08:44:11 2009 +0200
@@ -0,0 +1,349 @@
+/*
+* Copyright (c) 2004-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:
+* Handles DRM attachments
+*
+*/
+
+
+
+// INCLUDE FILES
+
+#include "mmsdrm.h"
+
+// drm
+#include <e32base.h>
+#include <e32std.h>
+#include <f32file.h>
+
+#include <apmstd.h>
+
+#include <s32mem.h>
+#include <cmsvattachment.h>
+#include <cmsvmimeheaders.h>
+#include <msvstore.h>
+#include <DRMRights.h>
+#include <DrmPermission.h>
+#include <DrmConstraint.h>
+#include <DRMTypes.h>
+
+// mms private headers
+#include "mmsconst.h"
+#include "mmserrors.h"
+
+// CONSTANTS
+
+const TInt KMms2 = 2; // just get rid of codescammer complaints
+const TInt KMmsAssetLength = 1024; // just an estimate
+
+// LOCAL FUNCTION PROTOTYPES
+
+
+// ================= MEMBER FUNCTIONS =======================
+
+
+// ---------------------------------------------------------
+//
+// ---------------------------------------------------------
+//
+CMmsDrmCaf::CMmsDrmCaf()
+ {
+ }
+
+// ---------------------------------------------------------
+//
+// ---------------------------------------------------------
+//
+CMmsDrmCaf* CMmsDrmCaf::NewL()
+ {
+ CMmsDrmCaf* self = new (ELeave) CMmsDrmCaf();
+
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ CleanupStack::Pop( self );
+
+ return self;
+ }
+
+// ---------------------------------------------------------
+//
+// ---------------------------------------------------------
+//
+void CMmsDrmCaf::ConstructL()
+ {
+ }
+
+// ---------------------------------------------------------
+//
+// ---------------------------------------------------------
+//
+CMmsDrmCaf::~CMmsDrmCaf()
+ {
+ delete iAttachmentFilePath;
+ delete iSupplier;
+ delete iImportFile;
+ }
+
+// ---------------------------------------------------------
+//
+// ---------------------------------------------------------
+//
+TBool CMmsDrmCaf::RegisterL( const CMsvMimeHeaders& aMimeHeaders )
+ {
+ // We allocate the supplier only when needed
+ if( !iSupplier )
+ {
+ iSupplier = CSupplier::NewL();
+ }
+ TBool retValue = EFalse;
+ TInt length = Max( aMimeHeaders.ContentType().Length() +
+ aMimeHeaders.ContentSubType().Length() + 1, KMmsImportFileLength );
+
+ HBufC8* contentType = HBufC8::NewL( length );
+ CleanupStack::PushL( contentType );
+
+ contentType->Des().Copy( aMimeHeaders.ContentType() );
+ contentType->Des().Append( KMmsSlash8 );
+ contentType->Des().Append( aMimeHeaders.ContentSubType() );
+ contentType->Des().LowerCase();
+
+ TInt i = 0;
+ CMetaDataArray* metaData = NULL;
+
+ for ( i = 0; i < aMimeHeaders.ContentTypeParams().MdcaCount() - 1; i += KMms2 )
+ {
+ if ( aMimeHeaders.ContentTypeParams().MdcaPoint( i ).CompareF( KMmsForwardHeader ) == 0
+ && aMimeHeaders.ContentTypeParams().MdcaPoint( i + 1 ).CompareF( KMmsNoHeader ) == 0 )
+ {
+ metaData = CMetaDataArray::NewL();
+ CleanupStack::PushL( metaData );
+ metaData->AddL( KMmsContentTypeHeader , contentType->Des() );
+ contentType->Des().Copy( KMmsDrmImportFile );
+ }
+ else if ( aMimeHeaders.ContentTypeParams().MdcaPoint( i ).
+ CompareF( KMmsRingtoneHeader ) == 0
+ && aMimeHeaders.ContentTypeParams().MdcaPoint( i + 1 ).CompareF( KMmsNoHeader ) == 0 )
+ {
+ metaData = CMetaDataArray::NewL();
+ CleanupStack::PushL( metaData );
+ metaData->AddL( KMmsContentTypeHeader , contentType->Des() );
+ contentType->Des().Copy( KMmsDrmImportFile );
+ // Must also generate rights object and stream it into metadata
+ //create rights
+ CDRMRights* rights = CDRMRights::NewL();
+ CleanupStack::PushL( rights );
+
+ TInt size = 0;
+ // Asset contains the content id
+ // DrmAsset.h
+ CDRMAsset* asset = CDRMAsset::NewLC();
+ asset->iUid = KMmsHutchContentURI().AllocL(); // This will be freed by the assets destructor
+ // Set the asset to the rights class, it will duplicate the asset
+ rights->SetAssetL( *asset );
+ size += KMmsAssetLength; // This is a guess, we don't know asset length.
+
+ CleanupStack::PopAndDestroy( asset ); // Asset
+
+ // DRMPermission.h
+ CDRMPermission* permission = CDRMPermission::NewLC();
+ // DRMConstraint.h
+ // DRMTypes.h
+ permission->iPlay = CDRMConstraint::NewL();
+ permission->iDisplay = CDRMConstraint::NewL();
+ permission->iExecute = CDRMConstraint::NewL();
+ permission->iPrint = CDRMConstraint::NewL();
+ permission->iAvailableRights = ERightsPlay | ERightsDisplay |
+ ERightsExecute | ERightsPrint;
+ // major version for Oma 1 Rights Objects
+ permission->iRightsObjectVersion.iVersionMain = 1;
+
+ // "ringtone=no" present
+ permission->iInfoBits = ENoRingingTone;
+ permission->iOriginalInsertTime.UniversalTime();
+ // Set top level and export to empty ones
+ permission->iTopLevel = CDRMConstraint::NewL();
+ permission->iExport = CDRMConstraint::NewL();
+
+ // Set the permission to the rights class, it will duplicate the permission
+ rights->SetPermissionL( *permission );
+
+ size += permission->Size();
+
+ CleanupStack::PopAndDestroy( permission ); // Permission
+
+ // stream the rights into metadata
+
+ HBufC8* data = HBufC8::NewMaxLC( size );
+
+ RMemWriteStream stream( (TAny*)( data->Ptr() ), size );
+ CleanupClosePushL( stream );
+
+ rights->ExternalizeL( stream );
+ metaData->AddL( KOmaImportRightsField(), data->Des() );
+
+ CleanupStack::PopAndDestroy( &stream ); // close stream
+ CleanupStack::PopAndDestroy( data );
+
+ CleanupStack::PopAndDestroy( rights );
+ }
+ }
+
+ if ( iSupplier->IsImportSupported( contentType->Des() ) )
+ {
+ if ( !metaData )
+ {
+ metaData = CMetaDataArray::NewL();
+ CleanupStack::PushL( metaData );
+ }
+ for ( i = 0; i < aMimeHeaders.XTypeParams().MdcaCount() - 1; i+= KMms2 )
+ {
+ metaData->AddL( aMimeHeaders.XTypeParams().MdcaPoint( i ),
+ aMimeHeaders.XTypeParams().MdcaPoint( i + 1 ) );
+ }
+ // Prepare agent for writing data
+ if ( iImportFile )
+ {
+ // invalid state, previous process not finished
+ User::Leave( KErrArgument );
+ }
+ iImportFile = iSupplier->ImportFileL( contentType->Des(), *metaData );
+ retValue = ETrue;
+ }
+
+ if ( metaData )
+ {
+ CleanupStack::PopAndDestroy( metaData );
+ }
+ CleanupStack::PopAndDestroy( contentType );
+ return retValue;
+
+ }
+
+// ---------------------------------------------------------
+//
+// ---------------------------------------------------------
+//
+void CMmsDrmCaf::StartProcessingL(
+ RFile& aStartFile, const TDesC& aAttachmentFilePath, CMsvStore& aStore )
+ {
+ delete iAttachmentFilePath; // just in case the processing has been terminated incorreclty
+ iAttachmentFilePath = NULL;
+ iAttachmentFilePath = HBufC::NewL( aAttachmentFilePath.Length() );
+ iAttachmentFilePath->Des().Copy( aAttachmentFilePath );
+ iStore = &aStore;
+ // We duplicate the handle, the caller may close its own copy
+ iAttachmentFile.Duplicate( aStartFile );
+ }
+
+
+// ---------------------------------------------------------
+//
+// ---------------------------------------------------------
+//
+TInt CMmsDrmCaf::WriteData( const TDesC8& aData )
+ {
+ TInt error = KErrNone;
+
+ error = iImportFile->WriteData( aData );
+ if ( error != KErrCANewFileHandleRequired )
+ {
+ // either all went well or the data was corrupted
+ return error;
+ }
+
+ // We need a new file handle (error == KErrCANewFileHandleRequired)
+ if ( iAttachmentFile.SubSessionHandle() )
+ {
+ // Caller provided open file handle
+ error = iImportFile->ContinueWithNewOutputFile( iAttachmentFile,
+ iAttachmentFilePath->Des() );
+ // Close the caller's file handle as CAF has made a copy
+ iAttachmentFile.Close();
+ if ( error == KErrCANewFileHandleRequired )
+ {
+ TRAP( error, NewFileL() );
+ }
+ }
+ else
+ {
+ TRAP( error, NewFileL() );
+ }
+ // We hope all went well
+ return error;
+ }
+
+// ---------------------------------------------------------
+//
+// ---------------------------------------------------------
+//
+void CMmsDrmCaf::EndProcessingL()
+ {
+ TInt error = KErrNone;
+
+ error = iImportFile->WriteDataComplete();
+ if ( error == KErrCANewFileHandleRequired )
+ {
+ // CAF framework requires another file handle to finish the session
+ TRAP( error, NewFileL() );
+ }
+
+ // We clean everything even in case of error
+ delete iAttachmentFilePath;
+ iAttachmentFilePath = NULL;
+ // Terminate the session
+ delete iImportFile;
+ iImportFile = NULL;
+
+ User::LeaveIfError( error );
+ }
+
+// ---------------------------------------------------------
+//
+// ---------------------------------------------------------
+//
+void CMmsDrmCaf::NewFileL()
+ {
+ TInt error = KErrNone;
+ TFileName* filename = new( ELeave )TFileName;
+ CleanupStack::PushL( filename );
+
+ do
+ {
+ if ( iImportFile->GetSuggestedOutputFileName( *filename ) != KErrNone )
+ {
+ TFileName* extension = new( ELeave )TFileName;
+ CleanupStack::PushL( extension );
+ _LIT( KDefAttName, "drmatt");
+ *filename = KDefAttName;
+ if ( iImportFile->GetSuggestedOutputFileExtension( *extension ) == KErrNone )
+ {
+ (*filename).Append( *extension );
+ }
+ CleanupStack::PopAndDestroy( extension );
+ }
+ CMsvAttachment* attachment = CMsvAttachment::NewL( CMsvAttachment::EMsvFile );
+ RFile file;
+ iStore->CreateShareProtectedAttachmentL( *(filename), file, attachment );
+ error = iImportFile->ContinueWithNewOutputFile( file, attachment->FilePath() );
+ // import file duplicates the handle
+ file.Close();
+ } while ( error == KErrCANewFileHandleRequired );
+
+ CleanupStack::PopAndDestroy( filename );
+ User::LeaveIfError( error );
+ }
+
+
+// End of File
+