diff -r 000000000000 -r 95b198f216e5 omadrm/drmengine/server/src/DRMRightsData.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/omadrm/drmengine/server/src/DRMRightsData.cpp Thu Dec 17 08:52:27 2009 +0200 @@ -0,0 +1,849 @@ +/* +* Copyright (c) 2004 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: Datatype for Rights Constraint +* +*/ + + + +// INCLUDE FILES +#include +#include +#include + +#include "DRMPointerArray.h" +#include "DRMCommonData.h" +#include "DRMPermission.h" +#include "DRMRightsData.h" + +// EXTERNAL DATA STRUCTURES + +// EXTERNAL FUNCTION PROTOTYPES + +// CONSTANTS +const TInt KEncryptionKeySize = 16; + +// MACROS + +// LOCAL CONSTANTS AND MACROS + +// MODULE DATA STRUCTURES + +// LOCAL FUNCTION PROTOTYPES + +// FORWARD DECLARATIONS + +class TPermData + { + public: // Constructor + TPermData( HBufC8* aParentId, const TInt aIndex, TBool aIsValid ) : + iParentId( aParentId ), + iIndex( aIndex ), + iIsValid( aIsValid ) { }; + + public: // Member variables + HBufC8* iParentId; + TInt iIndex; + TBool iIsValid; + }; + + +// ============================= LOCAL FUNCTIONS =============================== +// ============================ MEMBER FUNCTIONS =============================== + +// ----------------------------------------------------------------------------- +// CDRMRightsData::NewLC +// ----------------------------------------------------------------------------- +// +CDRMRightsData* CDRMRightsData::NewLC( CDRMCommonData* aData, + const TDesC8& aKey, + const TFileName& aRightsFile, + RFs& aFileServer ) + { + CDRMRightsData* self = new( ELeave ) CDRMRightsData( aData, aFileServer ); + CleanupStack::PushL( self ); + self->ConstructL( aRightsFile, aKey ); + + return self; + }; + +// ----------------------------------------------------------------------------- +// CDRMRightsData::NewL +// ----------------------------------------------------------------------------- +// +CDRMRightsData* CDRMRightsData::NewL( CDRMCommonData* aData, + const TDesC8& aKey, + const TFileName& aRightsFile, + RFs& aFileServer ) + { + CDRMRightsData* self = NewLC( aData, aKey, aRightsFile, aFileServer ); + CleanupStack::Pop(); + + return self; + }; + +// ----------------------------------------------------------------------------- +// CDRMRightsData::OpenLC +// ----------------------------------------------------------------------------- +// +CDRMRightsData* CDRMRightsData::OpenLC( const TFileName& aRightsFile, + RFs& aFileServer ) + { + CDRMCommonData* common = CDRMCommonData::NewL(); + + CDRMRightsData* self = new( ELeave ) CDRMRightsData( common, aFileServer ); + CleanupStack::PushL( self ); + self->ConstructL( aRightsFile ); + + return self; + }; + +// ----------------------------------------------------------------------------- +// CDRMRightsData::OpenL +// ----------------------------------------------------------------------------- +// +CDRMRightsData* CDRMRightsData::OpenL( const TFileName& aRightsFile, + RFs& aFileServer ) + { + CDRMRightsData* self = OpenLC( aRightsFile, aFileServer ); + CleanupStack::Pop(); + + return self; + }; + +// ----------------------------------------------------------------------------- +// Destructor +// ----------------------------------------------------------------------------- +// +CDRMRightsData::~CDRMRightsData() + { + // Permanent File Store + if( iStore ) + {; + delete iStore; + iStore = NULL; + } + + // index array + iArray.Close(); + + // Common Data + if( iData ) + { + delete iData; + iData = NULL; + } + }; + + +// ----------------------------------------------------------------------------- +// CDRMRightsData::GetCommonDataL +// ----------------------------------------------------------------------------- +// +const CDRMCommonData* CDRMRightsData::GetCommonDataL() const + { + return iData; + }; + +// ----------------------------------------------------------------------------- +// CDRMRightsData::UpdateCommonDataL +// ----------------------------------------------------------------------------- +// +void CDRMRightsData::UpdateCommonDataL( CDRMCommonData* aData ) + { + RStoreWriteStream stream; + + // If not data is given, that is an error + if( !aData ) + { + User::Leave( KErrArgument ); + } + + // Open the stream + stream.ReplaceLC( *iStore, iCommonId ); + + // Delete the old data if it's around + // if the old data has been modified, write it as such + if( iData != aData ) + { + if( iData ) + { + delete iData; + iData = NULL; + } + iData = aData; + } + + // Write the data to the stream + iData->ExternalizeL( stream ); + + // commit the stream + stream.CommitL(); + + // commit the store + iStore->CommitL(); + + // pop the stream + CleanupStack::PopAndDestroy(); + }; + +// ----------------------------------------------------------------------------- +// CDRMRightsData::StoreNewPermissionL +// ----------------------------------------------------------------------------- +// +void CDRMRightsData::StoreNewPermissionL( CDRMPermission& aPermission, + TDRMUniqueID& aStream ) + { + TStreamId sid; + TStreamId rootId; + RStoreWriteStream stream; + RStoreWriteStream rootStream; + + // Create a new stream to the store: + sid = stream.CreateLC( *iStore ); + + aPermission.iUniqueID = sid.Value(); + aStream = sid.Value(); + + // Externalize the permission data + aPermission.ExternalizeL( stream ); + stream.CommitL(); + + // add the id to the array + iArray.InsertInUnsignedKeyOrder( aStream ); + + // Get the stream id of the root + rootId = iStore->Root(); + + // Open the root stream + rootStream.ReplaceLC( *iStore, rootId ); + + // Store the changed index + StoreIndexL( rootStream ); + rootStream.CommitL(); + + // Commit the store + iStore->CommitL(); + + CleanupStack::PopAndDestroy(); // root stream + CleanupStack::PopAndDestroy(); // stream + + iStore->CompactL(); + iStore->CommitL(); + }; + +// ----------------------------------------------------------------------------- +// CDRMRightsData::UpdatePermissionL +// ----------------------------------------------------------------------------- +// +void CDRMRightsData::UpdatePermissionL( const CDRMPermission& aPermission ) + { + TStreamId sid( aPermission.iUniqueID ); + RStoreWriteStream stream; + TInt index = 0; + + // get the id from the array if it doesn't exist, error + index = iArray.FindInUnsignedKeyOrder( aPermission.iUniqueID ); + + if( index == KErrNotFound ) + { + User::Leave( KErrCANoPermission ); + } + + // Replace the existing stream + stream.ReplaceLC( *iStore, sid ); + + // Externalize the permission data + aPermission.ExternalizeL( stream ); + + // Required by the ReplaceLC + stream.CommitL(); + + // Commit the store + iStore->CommitL(); + + CleanupStack::PopAndDestroy(); + }; + +// ----------------------------------------------------------------------------- +// CDRMRightsData::FetchPermissionL +// ----------------------------------------------------------------------------- +// +void CDRMRightsData::FetchPermissionL( CDRMPermission& aPermission, + const TDRMUniqueID& aStream ) const + { + TStreamId sid( aStream ); + RStoreReadStream stream; + TInt index = 0; + + // get the id from the array if it doesn't exist, error + index = iArray.FindInUnsignedKeyOrder( aStream ); + + if( index == KErrNotFound ) + { + User::Leave( KErrCANoPermission ); + } + + // Open the root stream + stream.OpenLC( *iStore, sid ); + + // Read the common id + aPermission.InternalizeL( stream ); + + // Close the stream + CleanupStack::PopAndDestroy(); + }; + +// ----------------------------------------------------------------------------- +// CDRMRightsData::DeletePermissionL +// ----------------------------------------------------------------------------- +// +void CDRMRightsData::DeletePermissionL( const TDRMUniqueID& aStream ) + { + TStreamId sid( aStream ); + TStreamId rootId; + TInt index = 0; + RStoreWriteStream rootStream; + + // get the id from the array if it doesn't exist, error + index = iArray.FindInUnsignedKeyOrder( aStream ); + + if( index == KErrNotFound ) + { + User::Leave( KErrCANoPermission ); + } + + // Delete the stream from the store + iStore->DeleteL( sid ); + + iArray.Remove( index ); + + + // Get the stream id of the root + rootId = iStore->Root(); + + // Open the root stream + rootStream.ReplaceLC( *iStore, rootId ); + + // Store the changed index + StoreIndexL( rootStream ); + rootStream.CommitL(); + + // Commit the store + iStore->CommitL(); + + CleanupStack::PopAndDestroy(); // root stream + + // Compact and commit the changes + iStore->CompactL(); + iStore->CommitL(); + }; + +// ----------------------------------------------------------------------------- +// CDRMRightsData::FetchAllPermissionsL +// ----------------------------------------------------------------------------- +// +void CDRMRightsData::FetchAllPermissionsL( RPointerArray& + aPointerArray) + { + CDRMPermission* perm = NULL; + + if ( iArray.Count() == 0) + { + User::Leave( KErrCANoPermission ); + } + + for( TInt count = 0; count < iArray.Count(); count++ ) + { + perm = CDRMPermission::NewLC(); + FetchPermissionL( *perm, iArray[ count ] ); + aPointerArray.AppendL( perm ); + CleanupStack::Pop(); + } + }; + +// ----------------------------------------------------------------------------- +// CDRMRightsData::DeleteAllPermissionsL +// ----------------------------------------------------------------------------- +// +void CDRMRightsData::DeleteAllPermissionsL() + { + TStreamId rootId; + RStoreWriteStream rootStream; + + // Delete all permissions from the store + for( TInt i = 0; i < iArray.Count(); i++ ) + { + TStreamId sid( iArray[i] ); + iStore->DeleteL( sid ); + } + + // Reset the array + iArray.Reset(); + + // Get the stream id of the root + rootId = iStore->Root(); + + // Open the root stream + rootStream.ReplaceLC( *iStore, rootId ); + + // Store the changed index + StoreIndexL( rootStream ); + rootStream.CommitL(); + + // Commit the store + iStore->CommitL(); + + CleanupStack::PopAndDestroy(); // root stream + + // Compact and Commit the store + iStore->CompactL(); + iStore->CommitL(); + }; + +// ----------------------------------------------------------------------------- +// CDRMRightsData::DeleteExpiredPermissionsL +// Deletes all rights objects which have been expired +// if the given time aTime is Time::NullTTime() then +// deletes only non time based rights +// ----------------------------------------------------------------------------- +// +TInt CDRMRightsData::DeleteExpiredPermissionsL( const TTime& aTime, TBool& aParents ) + { + CDRMPermission* permission = NULL; + RStoreReadStream stream; + TStreamId rootId; + RStoreWriteStream rootStream; + TBool remove = EFalse; + TInt k = 0; + TBool performDelete = ETrue; + + // A list for the permissions: + CDRMPointerArray* permList = CDRMPointerArray::NewLC(); + permList->SetAutoCleanup( ETrue ); + CDRMPointerArray* permDataList = CDRMPointerArray::NewLC(); + permDataList->SetAutoCleanup( ETrue ); + + // Fill the array: + for( TInt j = 0 ; j < iArray.Count(); j++ ) + { + TPermData* perm = NULL; + // Create the sid: + TStreamId psid( iArray[j] ); + + // Open the correct stream + stream.OpenLC( *iStore, psid ); + + permission = CDRMPermission::NewLC(); + + // Read the permission + permission->InternalizeL( stream ); + + permList->AppendL( permission ); + CleanupStack::Pop(); // permission + + // if the permission has a parent check if we found now or have found an + // expired one or a valid one, + // store info if required + if( permission->iParentUID ) + { + if( !aParents ) + { + aParents = ETrue; + } + + for( k = 0; k < permDataList->Count(); k++ ) + { + if( !(*permDataList)[k]->iParentId->Compare( *permission->iParentUID ) ) + { + if( !(*permDataList)[k]->iIsValid && !permission->Expired( aTime ) ) + { + (*permDataList)[k]->iParentId = permission->iParentUID; + (*permDataList)[k]->iIndex = j; + (*permDataList)[k]->iIsValid = ETrue; + } + break; + } + } + + // if it's not found, add it: + if( k == permDataList->Count() ) + { + if( !permission->Expired( aTime ) ) + { + perm = new(ELeave) TPermData( permission->iParentUID, j, ETrue); + } + else + { + perm = new(ELeave) TPermData( permission->iParentUID, j, EFalse); + } + CleanupStack::PushL( perm ); + permDataList->AppendL( perm ); + CleanupStack::Pop(); // perm + } + } + + // Close the stream + CleanupStack::PopAndDestroy(); // stream + } + + + // Delete all expired permissions from the store + for( TInt i = iArray.Count() - 1 ; i >= 0; i-- ) + { + permission = (*permList)[i]; + + // Check if the permission is expired + // if it is, check if it has a parent and if it can be deleted + if( permission->Expired( aTime ) ) + { + // if it has a parent go through the list and see if this can be deleted + // or not + if( permission->iParentUID ) + { + performDelete = EFalse; + for( k = 0; k < permDataList->Count(); k++ ) + { + TPermData* aData = (*permDataList)[k]; + + // since it's set up like this a pointer comparison is enough: + if( !(*permDataList)[k]->iParentId->Compare( *permission->iParentUID ) ) + { + if( i != (*permDataList)[k]->iIndex ) + { + performDelete = ETrue; + } + } + } + } + + if( performDelete ) + { + // Create the sid: + TStreamId sid( iArray[i] ); + + iStore->Delete( sid ); + + // remove from the array + iArray.Remove( i ); + + if( !remove ) + { + remove = ETrue; + } + } + } + performDelete = ETrue; + } + + CleanupStack::PopAndDestroy( 2 ); // permDataList, permList + + // Write the data into the the file + // if some of the rights have been removed + if( remove ) + { + // Get the stream id of the root + rootId = iStore->Root(); + + // Open the root stream + rootStream.ReplaceLC( *iStore, rootId ); + + // Store the changed index + StoreIndexL( rootStream ); + rootStream.CommitL(); + + // Commit the store + iStore->CommitL(); + + CleanupStack::PopAndDestroy(); // root stream + + // Compact and Commit the store + iStore->CompactL(); + iStore->CommitL(); + } + + return iArray.Count(); + } + + +// ----------------------------------------------------------------------------- +// CDRMRightsData::StoreKeyL +// ----------------------------------------------------------------------------- +// +void CDRMRightsData::StoreKeyL() + { + RStoreWriteStream stream; + TUint32 size = 0; + + stream.OpenLC( *iStore, iKeyId ); + + if( iKeyExists ) + { + size = KEncryptionKeySize; + } + + stream.WriteUint32L( size ); + + if( size ) + { + stream.WriteL( iKey, KEncryptionKeySize ); + } + + stream.CommitL(); + iStore->CommitL(); + + CleanupStack::PopAndDestroy(); + }; + +// ----------------------------------------------------------------------------- +// CDRMRightsData::GetKeyL +// ----------------------------------------------------------------------------- +// +HBufC8* CDRMRightsData::GetKeyL() const + { + HBufC8* key = NULL; + + if( iKeyExists ) + { + key = HBufC8::NewL( KEncryptionKeySize ); + *key = iKey; + } + + return key; + } + +// ----------------------------------------------------------------------------- +// CDRMRightsData::FetchKeyL +// ----------------------------------------------------------------------------- +// +void CDRMRightsData::FetchKeyL() + { + RStoreReadStream stream; + TUint32 size = 0; + + // Open the root stream + stream.OpenLC( *iStore, iKeyId ); + + size = stream.ReadUint32L(); + + if( !size ) + { + iKeyExists = EFalse; + } + else + { + stream.ReadL( iKey, KEncryptionKeySize ); + iKeyExists = ETrue; + } + + CleanupStack::PopAndDestroy(); + }; + +// ----------------------------------------------------------------------------- +// CDRMRightsData::CreateAndInitializeStoreL +// ----------------------------------------------------------------------------- +// +void CDRMRightsData::CreateAndInitializeStoreL( const TFileName& aRightsStore ) + { + TStreamId rootId; + RStoreWriteStream stream; + RStoreWriteStream stream2; + RStoreWriteStream rootStream; + TUint32 size = 0; + + // Create and initialize the permanent file store + iStore = CPermanentFileStore::ReplaceL( iFileServer, aRightsStore, + EFileRead|EFileWrite ); + iStore->SetTypeL( KPermanentFileStoreLayoutUid ); + iStore->CommitL(); + + // Create the root stream: + rootId = rootStream.CreateLC( *iStore ); + rootStream.CommitL(); + iStore->SetRootL( rootId ); + iStore->CommitL(); + + // Create the common data + iCommonId = stream.CreateLC( *iStore ); + iData->ExternalizeL( stream ); + stream.CommitL(); + iStore->CommitL(); + + CleanupStack::PopAndDestroy(); // stream + + // Create the key + iKeyId = stream2.CreateLC( *iStore ); + + // if the key exists set the key size accordingly + if( iKeyExists ) + { + size = KEncryptionKeySize; + } + stream2.WriteUint32L( size ); + + if( size ) + { + stream2.WriteL( iKey, KEncryptionKeySize ); + } + stream2.CommitL(); + iStore->CommitL(); + + CleanupStack::PopAndDestroy(); // stream2 + CleanupStack::PopAndDestroy(); // rootStream + + // Create the index now that we have all the data + rootId = iStore->Root(); + + rootStream.ReplaceLC(*iStore, rootId); + StoreIndexL( rootStream ); + rootStream.CommitL(); + iStore->CommitL(); + + // Commit the changes to the store as well + CleanupStack::PopAndDestroy(); // rootStream + }; + + +// ----------------------------------------------------------------------------- +// CDRMRightsData::StoreIndexL +// ----------------------------------------------------------------------------- +// +void CDRMRightsData::StoreIndexL( RWriteStream& aStream ) const + { + // Write the common id to the stream + iCommonId.ExternalizeL( aStream ); + + // Write the key id to the stream + iKeyId.ExternalizeL( aStream ); + + // Write the array size and possibly the array to the stream + aStream.WriteInt32L( iArray.Count() ); + + for( TInt count = 0; count < iArray.Count(); count++ ) + { + aStream.WriteUint32L( iArray[ count ] ); + } + }; + +// ----------------------------------------------------------------------------- +// CDRMRightsData::FetchIndexL +// ----------------------------------------------------------------------------- +// +void CDRMRightsData::FetchIndexL() + { + TStreamId rootId; + RStoreReadStream stream; + TInt count = 0; + TDRMUniqueID id; + + // Get the stream id of the root + rootId = iStore->Root(); + + // Open the root stream + stream.OpenLC( *iStore, rootId ); + + // Do the actual reading, reading also the key id and the common id + + // Read the common id + iCommonId.InternalizeL( stream ); + + // Read the key id + iKeyId.InternalizeL( stream ); + + // read the count of the array: + iArray.Reset(); + + count = stream.ReadInt32L(); + + for( ; count > 0; count-- ) + { + id = stream.ReadUint32L(); + iArray.InsertInUnsignedKeyOrder( id ); + } + + // Close the stream + CleanupStack::PopAndDestroy(); + }; + +// ----------------------------------------------------------------------------- +// CDRMRightsData::FetchCommonDataL +// ----------------------------------------------------------------------------- +// +void CDRMRightsData::FetchCommonDataL() + { + RStoreReadStream stream; + + // Open the root stream + stream.OpenLC( *iStore, iCommonId ); + + iData->InternalizeL( stream ); + + CleanupStack::PopAndDestroy(); + }; + + +// ----------------------------------------------------------------------------- +// Default Constructor - First phase. +// Can be used by itself to generate an empty object +// ----------------------------------------------------------------------------- +// +CDRMRightsData::CDRMRightsData( CDRMCommonData* aData, RFs& aFileServer ) : + iFileServer( aFileServer ), iData( aData ) + { + }; + +// ----------------------------------------------------------------------------- +// 2nd phase Constructor +// ----------------------------------------------------------------------------- +// +void CDRMRightsData::ConstructL( const TFileName& aRightsStore ) + { + // Open the file store + iStore = CPermanentFileStore::OpenL( iFileServer, aRightsStore, EFileRead|EFileWrite ); + + // Get the index + FetchIndexL(); + + // Get the common data + FetchCommonDataL(); + + // Get the key + FetchKeyL(); + }; + +// ----------------------------------------------------------------------------- +// 2nd phase Constructor +// ----------------------------------------------------------------------------- +// +void CDRMRightsData::ConstructL( const TFileName& aRightsStore, + const TDesC8& aKey ) + { + + // Check if the key is given or a null desc + if( aKey.Length() ) + { + iKey = aKey; + iKeyExists = ETrue; + } + else + { + iKeyExists = EFalse; + } + + // Creates the required stores and indexes + CreateAndInitializeStoreL( aRightsStore ); + }; + + +// End of File