diff -r 000000000000 -r 95b198f216e5 omadrm/drmengine/ro/src/DrmRightsParser.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/omadrm/drmengine/ro/src/DrmRightsParser.cpp Thu Dec 17 08:52:27 2009 +0200 @@ -0,0 +1,1835 @@ +/* +* Copyright (c) 2002 - 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: OMA DRM rights parser +* +*/ + + + +// INCLUDE FILES +#include +#include +#include +#include +#include +#include +#include "DrmRights.h" +#include "DcfCommon.h" +#include "DrmRightsParser.h" +#include "DrmRightsClient.h" +#include "hash.h" +#include "base64.h" +#include "DRMPermission.h" +#include "DRMConstraint.h" +#include "DRMClockClient.h" + +// MODULE DATA STRUCTURES +enum TElementEnum + { + ERights = 0, + EContext, + EVersion, + EUid, + EAgreement, + EAsset, + EInherit, + EDigest, + EDigestMethod, + EDigestValue, + EKeyInfo, + EEncryptedKey, + EEncryptionMethod, + ECipherData, + ECipherValue, + ERetreivalMethod, + EPermission, + EPlay, + EDisplay, + EPrint, + EExecute, + EConstraint, + ECount, + ETimedCount, + EDateTime, + EStart, + EEnd, + EInterval, + EAccumulated, + EIndividual, + EExport, + ESystem, + EKeyValue, + EId, + EIdRef, + EProperty, + ESoftware, + EContainer, +#ifdef RD_DRM_METERING + ERequirement, + ETracked, +#endif + ELast, + }; + +struct TElements + { + const TText8* iString; + TInt iNumber; + }; + +NONSHARABLE_CLASS( CDrmRightsParser::CParsedAsset ): public CBase + { +public: + static CParsedAsset* NewL(); + ~CParsedAsset(); + void ConstructL(); + +private: + CParsedAsset(); + +public: + HBufC8* iUid; + TBuf8< KDCFKeySize > iKey; + TBuf8< KProtectedDCFKeySize > iProtectedKey; + TBuf8< KDCFKeySize > iAuthenticationSeed; + TBuf8< KProtectedDCFKeySize > iProtectedAuthSeed; + TBuf8< SHA1_HASH > iDigest; + + HBufC8* iId; + HBufC8* iIdRef; + + HBufC8* iInherit; + }; + +// Note the class CDrmRightsParser::CParsedPermission maps to +// OMA DRM2 permission container element +// CDRMConstraint reperesents indivdual permissions as constraint container +// (except Toplevel constraint really represents +// constraint container ) +NONSHARABLE_CLASS( CDrmRightsParser::CParsedPermission ): public CBase + { +public: + static CParsedPermission* NewL(); + ~CParsedPermission(); + // Removes invalidated permissions, and marks the total permission invalid, + // if all constraint containers are invalid, or toplevel container + // is invalid + void RemoveInvalidL(); + // Sets current constraint and updates available rights ( iAvailableRights ) + void SetCurrentConstraint ( TRightsType aCurrentConstraint ); + + RPointerArray< CParsedAsset > iAssets; + TUint8 iAvailableRights; + + CDRMConstraint *iTopLevel; + CDRMConstraint *iPlay; + CDRMConstraint *iDisplay; + CDRMConstraint *iPrint; + CDRMConstraint *iExecute; + CDRMConstraint *iExport; + + //2.1 addition: + // URL to send HTTP GET on expiration of permission + HBufC8* iOnExpiredUrl; + + // if constraint has unknown tags, this is ored with iCurrentConstraint + TUint8 iInvalidConstraints; + + // maintained during parsing. possible values: TRightsType enumerations + TUint8 iCurrentConstraint; + + // if top level constraint is invalid or all other constraints ate invalid + // permission will become invalid + TBool iInvalid; + // count of not_owned_assets, (updated in transform...) + TInt iNotOwned; + +private: + CParsedPermission(); + void ConstructL(); + void ResetConstraintL( CDRMConstraint*& aConstraint ); + }; + +NONSHARABLE_CLASS( CDrmRightsParser::CParsedRightsObject ): public CBase + { +public: + CParsedRightsObject(); + ~CParsedRightsObject(); + + // Removes invalidated permission containers + // (of type CParsedPermission ), and marks the whole rights object + // invalid, if all permission containers are invalid + void RemoveInvalid(); + + HBufC8* iRightsObjectId; + RPointerArray< CParsedAsset > iAssets; + RPointerArray< CParsedPermission > iPermissions; + + CParsedAsset* iCurrentAsset; + CParsedPermission* iCurrentPermission; + CDRMConstraint* iCurrentConstraint; + TBool iKeyIsCek; + TBool iInvalid; + }; + +// CONSTANTS +#define ELEMENT_COUNT( x ) static_cast< TInt >( ( sizeof( x ) / sizeof( x[ 0 ] ) ) ) + +// LOCAL CONSTANTS AND MACROS +const TInt KParserChunkSize = 512; +const TInt KMaxElementNesting = 24; + +// 15 minutes per time zone, 60 seconds per minute +const TInt KSecondsPerTimeZone = 900; +const TInt KMinuteInMicroseconds = 60000000; +const TInt KTimeZoneIncrement = 15; + +_LIT8( KXmlParserMimeType, "text/xml" ); +_LIT8( KWbxmlParserMimeType, "text/wbxml" ); +_LIT8( KSchemaAttribute, "schema" ); +_LIT8( KSchemeAttribute, "scheme" ); +_LIT8( KSchemaSymbianSid, "symbiansid" ); +_LIT8( KSchemaSymbianVid, "symbianvid" ); +_LIT8( KTimerAttribute, "timer" ); +_LIT8( KIdAttribute, "id" ); +_LIT8( KIdAttrUpperCase, "Id" ); +_LIT8( KIdRefAttribute, "idref" ); +_LIT8( KAuthSeed, "authSeed" ); +// OMA DRM 2.1 additions +_LIT8( KOnExpiredUrlAttribute, "onExpiredURL" ); //requested on premission expiry if present +#ifdef RD_DRM_METERING +_LIT8( KTimedAttribute, "timed" ); +_LIT8( KContentAccessGrantedAttribute, "contentAccessGranted" ); +_LIT8( KContentAccessGrantedValueTrue, "true" ); +#endif // RD_DRM_METERING + +static const TElements KElements[] = + { + { _S8( "rights" ), ::ERights }, + { _S8( "context" ), EContext }, + { _S8( "version" ), EVersion }, + { _S8( "uid" ), EUid }, + { _S8( "agreement" ), EAgreement }, + { _S8( "asset" ), EAsset }, + { _S8( "inherit" ), EInherit }, + { _S8( "digest" ), EDigest }, + { _S8( "DigestMethod" ), EDigestMethod }, + { _S8( "DigestValue" ), EDigestValue }, + { _S8( "KeyInfo" ), EKeyInfo }, + { _S8( "EncryptedKey" ), EEncryptedKey }, + { _S8( "EncryptionMethod" ), EEncryptionMethod }, + { _S8( "CipherData" ), ECipherData }, + { _S8( "CipherValue" ), ECipherValue }, + { _S8( "RetrievalMethod" ), ERetreivalMethod }, + { _S8( "permission" ), EPermission }, + { _S8( "play" ), ::EPlay }, + { _S8( "display" ), ::EDisplay }, + { _S8( "execute" ), ::EExecute }, + { _S8( "print" ), ::EPrint }, + { _S8( "constraint" ), EConstraint }, + { _S8( "count" ), ECount }, + { _S8( "timed-count" ), ETimedCount }, + { _S8( "datetime" ), EDateTime }, + { _S8( "start" ), EStart }, + { _S8( "end" ), EEnd }, + { _S8( "interval" ), EInterval }, + { _S8( "accumulated" ), EAccumulated }, + { _S8( "individual" ), EIndividual }, + { _S8( "export" ), EExport }, + { _S8( "system" ), ESystem }, + { _S8( "KeyValue" ), EKeyValue }, + { _S8( "software" ), ESoftware }, + { _S8( "property" ), EProperty }, + { _S8( "container" ), EContainer }, +#ifdef RD_DRM_METERING + { _S8( "requirement" ), ERequirement }, + { _S8( "tracked" ), ETracked }, +#endif //RD_DRM_METERING + }; + +enum TParserStackState + { + EUnknownState = -1, + ERoUidState = 0, + ETopLevelConstraintState, + EDisplayConstraintState, + EPlayConstraintState, + EPrintConstraintState, + EExecuteConstraintState, + EDateTimeStartState, + EDateTimeEndState, + EIntervalState, + ECountState, + ETimedCountState, + EIndividualState, + EAgreementAssetState, + EPermissionAssetState, + EAssetUidState, + EAssetDigestState, + EAssetKeyState, + EEncryptedKeyState, + EAssetInheritUidState, + EPermissionState, + ESoftwareState, + EAccumulatedState, + EKeyInfoState, + ESystemState, + EExportConstraintState, +#ifdef RD_DRM_METERING + ETrackRequirementState, +#endif // RD_DRM_METERING + }; + +struct TStackState + { + TParserStackState iState; + TElementEnum iStack[ KMaxElementNesting ]; + }; + +// Keep these sorted by the number of elements in the stack +static const TStackState KParserStackStates[] = + { + // 5 elements + { EEncryptedKeyState, { ECipherValue, ECipherData, EEncryptedKey, + EKeyInfo, EAsset, ELast } }, + // 4 elements + { EAssetInheritUidState, { EUid, EContext, EInherit, EAsset, ELast } }, + { EPermissionAssetState, { EAsset, EPermission, EAgreement, ::ERights, + ELast } }, + { ESoftwareState, { EProperty, EContext, ESoftware, EContainer, ELast } }, + // 3 elements + { EAgreementAssetState, { EAsset, EAgreement, ::ERights, ELast } }, + { EIndividualState, { EUid, EContext, EIndividual, ELast } }, + { ESystemState, { EUid, EContext, ESystem, ELast } }, + { ERoUidState, { EUid, EContext, ::ERights, ELast } }, + { EAssetUidState, { EUid, EContext, EAsset, ELast } }, + { EAssetDigestState, { EDigestValue, EDigest, EAsset, ELast } }, + { EAssetKeyState, { EKeyValue, EKeyInfo, EAsset, ELast } }, + // 2 elements + { EKeyInfoState, { EKeyInfo, EAsset, ELast } }, + { ETopLevelConstraintState, { EConstraint, EPermission, ELast } }, + { EDisplayConstraintState, { ::EDisplay, EPermission, ELast } }, + { EPlayConstraintState, { ::EPlay, EPermission, ELast } }, + { EPrintConstraintState, { ::EPrint, EPermission, ELast } }, + { EExecuteConstraintState, { ::EExecute, EPermission, ELast } }, + { EExportConstraintState, { EExport, EPermission, ELast } }, +#ifdef RD_DRM_METERING + { ETrackRequirementState, { ETracked, ERequirement, ELast } }, +#endif // RD_DRM_METERING + //1 element + { EDateTimeStartState, { EStart, ELast } }, + { EDateTimeEndState, { EEnd, ELast } }, + { EIntervalState, { EInterval, ELast } }, + { ECountState, { ECount, ELast } }, + { ETimedCountState, { ETimedCount, ELast } }, + { EAccumulatedState, { EAccumulated, ELast } }, + { EPermissionState, { EPermission, ELast } }, + }; + +// LOCAL FUNCTION PROTOTYPES + +// ============================= LOCAL FUNCTIONS =============================== + + +// ----------------------------------------------------------------------------- +// CDrmRightsParser::ValidateDay +// Returns ETrue if the day is valid +// EFalse if the day is not valid +// +// If the month is January, March, May, July, August, October, December +// - Check that the day is between 1 and 31 +// If the month is April, June, September, November +// - Check that the day is between 1 and 30 +// If the month is February +// - Check that the day is between 1 and 29, +// - if it is 29 check that the following conditions are met in that order: +// * The year is dividable by 400 it's valid +// * The year is dividable by 100 it is not valid +// * The year is dividable by 4 it is valid +// ----------------------------------------------------------------------------- +// + +TBool CDrmRightsParser::ValidateDay( TInt aYear, TMonth aMonth, TInt aDay ) + { + TBool retVal = ETrue; + + switch ( aMonth ) + { + case EJanuary: + case EMarch: + case EMay: + case EJuly: + case EAugust: + case EOctober: + case EDecember: + { + if ( aDay < 0 || aDay > 30 ) + { + retVal = EFalse; + } + } + break; + case EApril: + case EJune: + case ESeptember: + case ENovember: + { + if ( aDay < 0 || aDay > 29 ) + { + retVal = EFalse; + } + } + break; + case EFebruary: + { + if ( aDay < 0 || aDay > 28 ) + { + retVal = EFalse; + } + else + { + // If we are at day 29, it is possible that it is valid: + if ( aDay == 28 ) + { + // if the year is dividable by 400 it is valid + if ( ( aYear % 400 ) ) + { + // if the year is dividable by 100 it is not valid + if ( aYear % 100 ) + { + // if the year is dividable by 4 it is valid + if ( aYear % 4 ) + { + retVal = EFalse; + } + } + else + { + retVal = EFalse; + } + } + } + } + } + break; + default: + retVal = EFalse; + break; + } + return retVal; + } + + + +// ----------------------------------------------------------------------------- +// CDrmRightsParser::ValidTimeValues +// Returns ETrue if the time values are valid +// EFalse if any of them are valid +// Checks done as per symbian documentations +// ----------------------------------------------------------------------------- +// +TBool CDrmRightsParser::ValidTimeValues( TInt aYear, TMonth aMonth, + TInt aDay, TInt aHour, + TInt aMinute, TInt aSecond, + TInt aMicrosecond ) + { + // No check for Year + + // check Month + if ( aMonth < EJanuary || aMonth > EDecember ) + { + return EFalse; + } + + // check Day + if ( !ValidateDay( aYear, aMonth, aDay ) ) + { + return EFalse; + } + + // check Hour + if ( aHour < 0 || aHour > 23 ) + { + return EFalse; + } + + // check Minute + if ( aMinute < 0 || aMinute > 59 ) + { + return EFalse; + } + + // check Second + if ( aSecond < 0 || aSecond > 59 ) + { + return EFalse; + } + + // check Microsecond + if ( aMicrosecond < 0 || aMicrosecond > 9999999 ) + { + return EFalse; + } + + return ETrue; + }; + + +// ----------------------------------------------------------------------------- +// CDrmRightsParser::ParseRelTime +// Parses a ISO8601 relative time string +// ----------------------------------------------------------------------------- +// +TTime CDrmRightsParser::ParseRelTimeL( TDesC8& aRelTimeString ) + { + TLex8 lex; + TInt year( 0 ); + TInt month( 0 ); + TInt day( 0 ); + TInt hour( 0 ); + TInt minute( 0 ); + TInt second( 0 ); + TTime r; + TTimeIntervalSeconds offset( 0 ); + + lex = aRelTimeString; + lex.Val( year ); + lex.Inc(); + lex.Val( month ); + lex.Inc(); + lex.Val( day ); + lex.Inc(); + lex.Val( hour ); + lex.Inc(); + lex.Val( minute ); + lex.Inc(); + lex.Val( second ); + + + // The time needs to be validated before + if ( !ValidTimeValues( year, static_cast< TMonth >( month - 1 ), day - 1, + hour, minute, second, 0 ) ) + { + User::Leave( KErrArgument ); + } + + r = TTime( TDateTime( year, static_cast< TMonth >( month - 1 ), day - 1, + hour, minute, second, 0 ) ); + if ( lex.Get() != 'Z' ) + { + offset = iTimeZone * KSecondsPerTimeZone; + r -= offset; + } + return r; + } + +// ----------------------------------------------------------------------------- +// CDrmRightsParser::ParseRelInterval +// Parses a ISO8601 relative interval string +// ----------------------------------------------------------------------------- +// +TTimeIntervalSeconds CDrmRightsParser::ParseRelInterval( + TDesC8& aRelTimeString ) + { + TLex8 lex; + TInt year( 0 ); + TInt month( 0 ); + TInt day( 0 ); + TInt hour( 0 ); + TInt minute( 0 ); + TInt second( 0 ); + TInt n( 0 ); + TTimeIntervalSeconds r( 0 ); + TBool done( EFalse ); + TBool inDate( ETrue ); + + lex = aRelTimeString; + lex.Inc(); + while ( !done ) + { + if ( lex.Peek() == 'T' ) + { + lex.Inc(); + inDate = EFalse; + } + + lex.Val( n ); + switch ( lex.Get() ) + { + case 'Y': + year = n; + break; + case 'D': + day = n; + break; + case 'M': + if ( inDate ) + { + month = n; + } + else + { + minute = n; + } + break; + case 'H': + hour = n; + break; + case 'S': + second = n; + break; + default: + done = ETrue; + break; + } + } + + r = ( ( ( ( year * 365 + month * 30 + day ) * 24 + hour ) + * 60 + minute ) * 60 + second ); + return r; + } + +// ----------------------------------------------------------------------------- +// DecodeAndDeleteUndecodedL() +// Decodes base64 encoded HbufC8 buffer arcument, deletes undecoded buffer, and +// substitutes argument with Decoded buffer +// ----------------------------------------------------------------------------- +// +LOCAL_C void DecodeAndDeleteUndecodedL( HBufC8*& aDecodee ) + { + HBufC8* b( aDecodee ); + aDecodee = NULL; + CleanupStack::PushL( b ); + aDecodee = Base64DecodeL( *b ); + CleanupStack::PopAndDestroy( b ); + } + +// ----------------------------------------------------------------------------- +// CopyOrLeaveL( TDes8& aDest, const TDesC8& aSrc ) +// Copies aSrc to aDest. +// Leaves, if length of aSrc exceeds capacity of aDest +// ----------------------------------------------------------------------------- +// +LOCAL_C void CopyOrLeaveL( TDes8& aDest, const TDesC8& aSrc ) + { + if ( aSrc.Length() > aDest.MaxLength() ) + { + User::Leave( KErrArgument ); + } + aDest.Copy( aSrc ); + } + +// ============================ MEMBER FUNCTIONS =============================== + +// ----------------------------------------------------------------------------- +// CDrmRightsParser::CParsedAsset::NewL +// ----------------------------------------------------------------------------- +// +CDrmRightsParser::CParsedAsset* +CDrmRightsParser::CParsedAsset::NewL() + { + CParsedAsset* self = new ( ELeave ) CParsedAsset; + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop( self ); + return self; + } + +// ----------------------------------------------------------------------------- +// CDrmRightsParser::CParsedAsset::~CParsedAsset +// ----------------------------------------------------------------------------- +// +CDrmRightsParser::CParsedAsset::~CParsedAsset() + { + delete iUid; + delete iId; + delete iIdRef; + delete iInherit; + } + +// ----------------------------------------------------------------------------- +// CDrmRightsParser::CParsedAsset::ConstructL +// Allocate the list of attribute values +// ----------------------------------------------------------------------------- +// +void CDrmRightsParser::CParsedAsset::ConstructL() + { + } + +// ----------------------------------------------------------------------------- +// CDrmRightsParser::CParsedAsset::CParsedAsset +// ----------------------------------------------------------------------------- +// +CDrmRightsParser::CParsedAsset::CParsedAsset(): + iUid( NULL ), + iId( NULL ), + iIdRef( NULL ), + iInherit( NULL ) + { + } + +// ----------------------------------------------------------------------------- +// CDrmRightsParser::CParsedPermission::NewL +// ----------------------------------------------------------------------------- +// +CDrmRightsParser::CParsedPermission* +CDrmRightsParser::CParsedPermission::NewL() + { + CParsedPermission* self = new ( ELeave ) CParsedPermission; + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop( self ); + return self; + } + +// ----------------------------------------------------------------------------- +// CDrmRightsParser::CParsedPermission::~CParsedPermission +// ----------------------------------------------------------------------------- +// +CDrmRightsParser::CParsedPermission::~CParsedPermission() + { + for ( TInt i( 0 ); i < iNotOwned; ++i ) + { + iAssets.Remove( 0 ); + } + iAssets.ResetAndDestroy(); + iAssets.Close(); + delete iTopLevel; + delete iPlay; + delete iDisplay; + delete iPrint; + delete iExecute; + delete iExport; + delete iOnExpiredUrl; + } + +// ----------------------------------------------------------------------------- +// CDrmRightsParser::CParsedPermission::SetCurrentConstraint +// ----------------------------------------------------------------------------- +// +void CDrmRightsParser::CParsedPermission::SetCurrentConstraint( + TRightsType aCurrentConstraint ) + { + iAvailableRights |= aCurrentConstraint; + iCurrentConstraint = aCurrentConstraint; + } +// ----------------------------------------------------------------------------- +// CDrmRightsParser::CParsedPermission::RemoveInvalid +// ----------------------------------------------------------------------------- +// +void CDrmRightsParser::CParsedPermission::RemoveInvalidL() + { + TUint8 valid = ( iInvalidConstraints ^ ERightsAll ) & ERightsAll; + iAvailableRights &= valid; + if ( !valid ) + { + iInvalid = ETrue; + } + if ( iInvalid || ( iInvalidConstraints & ERightsTopLevel ) ) + { + iInvalid = ETrue; + ResetConstraintL( iTopLevel ); + } + if ( iInvalid || ( iInvalidConstraints & ERightsPlay ) ) + { + ResetConstraintL( iPlay ); + } + if ( iInvalid || ( iInvalidConstraints & ERightsDisplay ) ) + { + ResetConstraintL( iDisplay ); + } + if ( iInvalid || ( iInvalidConstraints & ERightsExecute ) ) + { + ResetConstraintL( iExecute ); + } + if ( iInvalid || ( iInvalidConstraints & ERightsPrint ) ) + { + ResetConstraintL( iPrint ); + } + if ( iInvalid || ( iInvalidConstraints & ERightsExport ) ) + { + ResetConstraintL( iExport ); + } + } + +// ----------------------------------------------------------------------------- +// CDrmRightsParser::CParsedPermission::CParsedPermission +// ----------------------------------------------------------------------------- +// +CDrmRightsParser::CParsedPermission::CParsedPermission() + { + } + +// ----------------------------------------------------------------------------- +// CDrmRightsParser::CParsedPermission::ConstructL +// ----------------------------------------------------------------------------- +// +void CDrmRightsParser::CParsedPermission::ConstructL() + { + iTopLevel = CDRMConstraint::NewL(); + iPlay = CDRMConstraint::NewL(); + iDisplay = CDRMConstraint::NewL(); + iPrint = CDRMConstraint::NewL(); + iExecute = CDRMConstraint::NewL(); + iExport = CDRMConstraint::NewL(); + } + +// ----------------------------------------------------------------------------- +// CDrmRightsParser::CParsedPermission::ResetConstraintL +// ----------------------------------------------------------------------------- +// +void CDrmRightsParser::CParsedPermission::ResetConstraintL( + CDRMConstraint*& aConstraint ) + { + delete aConstraint; + aConstraint = NULL; + aConstraint = CDRMConstraint::NewL(); + } + +// ----------------------------------------------------------------------------- +// CDrmRightsParser::CParsedRightsObject::CParsedRightsObject +// ----------------------------------------------------------------------------- +// +CDrmRightsParser::CParsedRightsObject::CParsedRightsObject(): + iRightsObjectId( NULL ), + iCurrentAsset( NULL ), + iCurrentPermission( NULL ), + iCurrentConstraint( NULL ) + { + } + +// ----------------------------------------------------------------------------- +// CDrmRightsParser::CParsedRightsObject::~CParsedRightsObject +// ----------------------------------------------------------------------------- +// +CDrmRightsParser::CParsedRightsObject::~CParsedRightsObject() + { + delete iRightsObjectId; + iAssets.ResetAndDestroy(); + iAssets.Close(); + iPermissions.ResetAndDestroy(); + iPermissions.Close(); + } + + +// ----------------------------------------------------------------------------- +// CDrmRightsParser::CParsedRightsObject::RemoveInvalid +// ----------------------------------------------------------------------------- +// +void CDrmRightsParser::CParsedRightsObject::RemoveInvalid() + { + if ( iPermissions.Count() == 0 ) + { + return; + } + for ( TInt j( 0 ); j < iPermissions.Count(); ++j ) + { + CDrmRightsParser::CParsedPermission* permission( NULL ); + permission = iPermissions[ j ]; + if ( permission->iInvalid ) + { + iPermissions.Remove( j ); + delete permission; + } + permission = NULL; + } + if ( iPermissions.Count() == 0 ) + { + iInvalid = ETrue; + } + } + +// ----------------------------------------------------------------------------- +// CDrmRightsParser::CDrmRightsParser +// ----------------------------------------------------------------------------- +// +CDrmRightsParser::CDrmRightsParser(): + iParser( NULL ), + iRights( NULL ), + iContent( NULL ), + iUnknownTag( NULL ) + { + } + +// ----------------------------------------------------------------------------- +// CDrmRightsParser::ConstructL +// ----------------------------------------------------------------------------- +// +void CDrmRightsParser::ConstructL( + TParserType aType ) + { + TTime currentUniversal; + TTime currentLocal; + TInt64 result( 0 ); + + currentUniversal.UniversalTime(); + currentLocal.HomeTime(); + + result = currentLocal.Int64() - currentUniversal.Int64(); + result /= KMinuteInMicroseconds; + result /= KTimeZoneIncrement; + + iTimeZone = I64INT( result ); + + iParserType = aType; + if ( aType == EXmlParser ) + { + iParser = CParser::NewL( KXmlParserMimeType, *this ); + } + else + { + iParser = CParser::NewL( KWbxmlParserMimeType, *this ); + } + + for ( TInt i( 0 ); i < ELEMENT_COUNT( KElements ); i++ ) + { + TPtrC8 ptr( KElements[ i ].iString, + User::StringLength( KElements[ i ].iString ) ); + iElements[ KElements[ i ].iNumber ] = + iParser->StringPool().OpenStringL( ptr ); + } + } + +// ----------------------------------------------------------------------------- +// CDrmRightsParser::NewL +// Two-phased constructor. +// ----------------------------------------------------------------------------- +// +EXPORT_C CDrmRightsParser* CDrmRightsParser::NewL( + TParserType aType ) + { + CDrmRightsParser* self( new ( ELeave ) CDrmRightsParser ); + + CleanupStack::PushL( self ); + self->ConstructL( aType ); + CleanupStack::Pop( self ); + + return self; + } + + +// Destructor +EXPORT_C CDrmRightsParser::~CDrmRightsParser() + { + for ( TInt i( 0 ); i < ELEMENT_COUNT( KElements ); i++ ) + { + iElements[ KElements[ i ].iNumber ].Close(); + } + delete iParser; + delete iRights; + delete iContent; + delete iUnknownTag; + } + + +// ----------------------------------------------------------------------------- +// CDrmRightsParser::ParseL +// ----------------------------------------------------------------------------- +// +EXPORT_C void CDrmRightsParser::ParseL( + const TDesC8& aRightsObject, + RPointerArray< CDRMRights >& aResultRights ) + { + TInt i( 0 ); + + iElementStackDepth = 0; + delete iRights; + iRights = NULL; + delete iContent; + iContent = NULL; + iRights = new ( ELeave ) CParsedRightsObject; + iParser->ParseBeginL(); + if ( iParserType == EWbxmlParser ) + { + iParser->EnableFeature( ERawContent ); + } + + while ( i < aRightsObject.Length() ) + { + TInt n( Min( aRightsObject.Length() - i, KParserChunkSize ) ); + iParser->ParseL( aRightsObject.Mid( i, n ) ); + i += n; + } + iParser->ParseEndL(); + TransformRightsObjectL( aResultRights ); + } + +// ----------------------------------------------------------------------------- +// CDrmRightsParser::ParseAndStoreL +// ----------------------------------------------------------------------------- +// +EXPORT_C void CDrmRightsParser::ParseAndStoreL( + const TDesC8& aRightsObject, + RPointerArray< CDRMRights >& aResultRights ) + { + RDRMRightsClient client; + + User::LeaveIfError( client.Connect() ); + CleanupClosePushL( client ); + ParseL( aRightsObject, aResultRights ); + for ( TInt i( 0 ); i < aResultRights.Count(); i++ ) + { + TDRMUniqueID id; + HBufC8 *cid( NULL ); + CDRMRights* rights( aResultRights[ i ] ); + rights->GetContentURI( cid ); + if ( rights->GetAsset().iKey.Length() == 0 ) + { + for ( TInt j( 0 ); j < KDCFKeySize; j++ ) + { + rights->GetAsset().iKey.Append( Math::Random() ); + } + } + client.AddRecord( rights->GetAsset().iKey, rights->GetPermission(), + *cid, id ); + rights->SetLocalID( id ); + delete cid; + } + + CleanupStack::PopAndDestroy( &client ); + } + +// ----------------------------------------------------------------------------- +// CDrmRightsParser::OnStartDocumentL +// ----------------------------------------------------------------------------- +// +void CDrmRightsParser::OnStartDocumentL( + const RDocumentParameters& /*aDocParam*/, + TInt /*aErrorCode*/ ) + { + } + +// ----------------------------------------------------------------------------- +// CDrmRightsParser::OnEndDocumentL +// ----------------------------------------------------------------------------- +// +void CDrmRightsParser::OnEndDocumentL( + TInt /*aErrorCode*/ ) + { + if ( iRights ) + { + // Remove invalid parsed permissions, + // and invalidate parsed rights object, + // if there are no valid ROs left + iRights->RemoveInvalid(); + } + } + +// ----------------------------------------------------------------------------- +// CDrmRightsParser::OnStartElementL +// ----------------------------------------------------------------------------- +// +void CDrmRightsParser::OnStartElementL( + const RTagInfo& aElement, + const RAttributeArray& aAttributes, + TInt /*aErrorCode*/ ) + { + TBool tagRecognized( EFalse ); + + if ( iUnknownTag ) + { + return; + } + if ( iContent ) + { + delete iContent; + iContent = NULL; + iContent = HBufC8::NewL( 0 ); + } + + for ( TInt i( 0 ); i < KMaxElementCount; i++ ) + { + if ( aElement.LocalName() == iElements[ i ] ) + { + tagRecognized = ETrue; + iElementStack[ iElementStackDepth ] = + static_cast< TElementEnum >( i ); + iElementStackDepth++; + if ( iElementStackDepth == KMaxElementNesting ) + { + User::Leave( EXmlUnexpectedState ); + } + break; + } + } + if ( tagRecognized ) + { + TLex8 lex; + HBufC8* b( NULL ); + TInt n( 0 ); + + switch ( MatchStackState() ) + { + case ETopLevelConstraintState: + iRights->iCurrentPermission->SetCurrentConstraint( + ERightsTopLevel ); + iRights->iCurrentConstraint = + iRights->iCurrentPermission->iTopLevel; + break; + case EDisplayConstraintState: + iRights->iCurrentPermission->SetCurrentConstraint( + ERightsDisplay ); + iRights->iCurrentConstraint = + iRights->iCurrentPermission->iDisplay; + break; + case EPlayConstraintState: + iRights->iCurrentPermission->SetCurrentConstraint( + ERightsPlay ); + iRights->iCurrentConstraint = + iRights->iCurrentPermission->iPlay; + break; + case EPrintConstraintState: + iRights->iCurrentPermission->SetCurrentConstraint( + ERightsPrint ); + iRights->iCurrentConstraint = + iRights->iCurrentPermission->iPrint; + break; + case EExecuteConstraintState: + iRights->iCurrentPermission->SetCurrentConstraint( + ERightsExecute ); + iRights->iCurrentConstraint = + iRights->iCurrentPermission->iExecute; + break; + case EExportConstraintState: + iRights->iCurrentPermission->SetCurrentConstraint( + ERightsExport ); + iRights->iCurrentConstraint = + iRights->iCurrentPermission->iExport; + break; + case EAgreementAssetState: + iRights->iCurrentAsset = CParsedAsset::NewL(); + iRights->iCurrentAsset->iId = + GetAttributeValueL( aAttributes, KIdAttribute ); + iRights->iCurrentAsset->iIdRef = + GetAttributeValueL( aAttributes, KIdRefAttribute ); + iRights->iAssets.Append( iRights->iCurrentAsset ); + break; + case EPermissionAssetState: + iRights->iCurrentAsset = CParsedAsset::NewL(); + iRights->iCurrentAsset->iId = + GetAttributeValueL( aAttributes, KIdAttribute ); + iRights->iCurrentAsset->iIdRef = + GetAttributeValueL( aAttributes, KIdRefAttribute ); + iRights->iCurrentPermission->iAssets.Append( + iRights->iCurrentAsset ); + break; + case EPermissionState: + iRights->iCurrentPermission = CParsedPermission::NewL(); + iRights->iPermissions.Append( + iRights->iCurrentPermission ); + iRights->iCurrentPermission->iOnExpiredUrl = + GetAttributeValueL( aAttributes, KOnExpiredUrlAttribute ); + break; + case ESoftwareState: + b = GetAttributeValueL( aAttributes, KSchemaAttribute ); + if ( !b ) + { + b = GetAttributeValueL( aAttributes, KSchemeAttribute ); + } + if ( !b ) + { + User::Leave( KErrArgument ); + } + CleanupStack::PushL( b ); + if ( b->CompareF( KSchemaSymbianSid ) == 0 && + iRights->iCurrentConstraint->iSecureId == + TUid::Null() ) + { + iSoftwareSchemeType = ESymbianSid; + } + else if ( b->CompareF( KSchemaSymbianVid ) == 0 && + iRights->iCurrentConstraint->iVendorId == + TUid::Null() ) + { + iSoftwareSchemeType = ESymbianVid; + } + else + { + User::Leave( KErrNotSupported ); + } + CleanupStack::PopAndDestroy( b ); + break; + case ETimedCountState: + b = GetAttributeValueL( aAttributes, KTimerAttribute ); + if ( !b ) + { + User::Leave( KErrArgument ); + } + CleanupStack::PushL( b ); + lex = *b; + lex.Val( n ); + if ( n < 0 ) + { + User::Leave( KErrArgument ); + } + iRights->iCurrentConstraint->iTimedInterval = n; + CleanupStack::PopAndDestroy( b ); + break; + case EKeyInfoState: + b = GetAttributeValueL( aAttributes, KIdAttrUpperCase ); + if ( b && b->Right( KAuthSeed().Length() ).Compare( + KAuthSeed ) == 0 ) + { + iRights->iKeyIsCek = EFalse; + delete b; + } + else + { + iRights->iKeyIsCek = ETrue; + } + break; +#ifdef RD_DRM_METERING + case ETrackRequirementState: + if ( !iRights->iCurrentConstraint || + !iRights->iCurrentPermission || + iRights->iCurrentConstraint == + iRights->iCurrentPermission->iTopLevel ) + { + User::Leave( KErrArgument ); + } + if ( !iRights->iCurrentConstraint->iDrmMeteringInfo ) + { + iRights->iCurrentConstraint->iDrmMeteringInfo = + new ( ELeave ) CDRMConstraint::TDrmMeteringInfo; + } + b = GetAttributeValueL( aAttributes, KTimedAttribute ); + if ( b ) + { + CleanupStack::PushL( b ); + lex = *b; + if ( lex.Val( n ) != KErrNone ) + { + // given input does not fit to TInt + User::Leave( KErrArgument ); + } + iRights->iCurrentConstraint->iDrmMeteringInfo->iGraceTime = n; + + CleanupStack::PopAndDestroy( b ); + b = NULL; + } + b = GetAttributeValueL( aAttributes, KContentAccessGrantedAttribute ); + // put value to content access granted without metering + if ( b && !b->CompareF( KContentAccessGrantedValueTrue ) ) + { + iRights->iCurrentConstraint->iDrmMeteringInfo->iAllowUseWithoutMetering = ETrue; + } + else + { + iRights->iCurrentConstraint->iDrmMeteringInfo->iAllowUseWithoutMetering = EFalse; + } + delete b; + break; +#endif // RD_DRM_METERING + } + } + if ( !tagRecognized && iElementStackDepth > 0 && + iElementStack[ 0 ] == ::ERights ) + { + //Found unrecognised tag in <(o-ex:)rights>. Let's ignore its content. + iUnknownTag = aElement.LocalName().DesC().AllocL(); + if ( iRights && iRights->iCurrentPermission ) + { + iRights->iCurrentPermission->iInvalidConstraints |= + iRights->iCurrentPermission->iCurrentConstraint; + if ( iRights->iCurrentPermission->iCurrentConstraint + == ERightsTopLevel ) + { + iRights->iCurrentPermission->iInvalid = ETrue; + } + } + } + } + +// ----------------------------------------------------------------------------- +// CDrmRightsParser::OnEndElementL +// ----------------------------------------------------------------------------- +// +void CDrmRightsParser::OnEndElementL( + const RTagInfo& aElement, + TInt /*aErrorCode*/ ) + { + if ( iUnknownTag ) + { + if ( !iUnknownTag->Compare( aElement.LocalName().DesC() ) ) + { + delete iUnknownTag; + iUnknownTag = NULL; + } + return; + } + + for ( TInt i ( 0 ); i < KMaxElementCount; i++ ) + { + if ( aElement.LocalName() == iElements[ i ] ) + { + switch ( MatchStackState() ) + { + case ERoUidState: + iContent->Des().Trim(); // remove ignorable white spaces + iRights->iRightsObjectId = iContent->AllocL(); + break; + case EDateTimeStartState: + if ( iRights->iCurrentConstraint ) + { + iRights->iCurrentConstraint->iActiveConstraints |= + EConstraintStartTime; + iRights->iCurrentConstraint->iStartTime = + ParseRelTimeL( *iContent ); + } + break; + case EDateTimeEndState: + if ( iRights->iCurrentConstraint ) + { + iRights->iCurrentConstraint->iActiveConstraints |= + EConstraintEndTime; + iRights->iCurrentConstraint->iEndTime = + ParseRelTimeL( *iContent ); + } + break; + case EIntervalState: + if ( iRights->iCurrentConstraint ) + { + iRights->iCurrentConstraint->iActiveConstraints |= + EConstraintInterval; + iRights->iCurrentConstraint->iInterval = + ParseRelInterval( *iContent ); + iRights->iCurrentConstraint->iIntervalStart = + Time::NullTTime(); + if ( iRights->iCurrentConstraint->iInterval.Int() + <= 0 ) + { + User::Leave( KErrArgument ); + } + } + break; + case EAccumulatedState: +#ifndef __DRM_OMA2 + User::Leave( KErrArgument ); +#endif + if ( iRights->iCurrentConstraint ) + { + iRights->iCurrentConstraint->iActiveConstraints |= + EConstraintAccumulated; + iRights->iCurrentConstraint->iAccumulatedTime = + ParseRelInterval( *iContent ).Int(); + if ( iRights->iCurrentConstraint-> + iAccumulatedTime.Int() <= 0 ) + { + User::Leave( KErrArgument ); + } + } + break; + case ECountState: + if ( iRights->iCurrentConstraint ) + { + TLex8 lex( *iContent ); + iRights->iCurrentConstraint->iActiveConstraints |= + EConstraintCounter; + lex.Val( iRights->iCurrentConstraint-> + iOriginalCounter ); + iRights->iCurrentConstraint->iCounter = + iRights->iCurrentConstraint->iOriginalCounter; + if ( iRights->iCurrentConstraint->iCounter <= 0 || + iRights->iCurrentConstraint->iCounter > + KDRMCounterMax ) + { + User::Leave( KErrArgument ); + } + } + break; + case ETimedCountState: +#ifndef __DRM_OMA2 + User::Leave( KErrArgument ); +#endif + if ( iRights->iCurrentConstraint ) + { + CDRMConstraint* c( iRights->iCurrentConstraint ); + TLex8 lex( *iContent ); + lex.Val( c->iOriginalTimedCounter ); + if ( c->iOriginalTimedCounter <= 0 || + c->iOriginalTimedCounter > KDRMCounterMax ) + { + User::Leave( KErrArgument ); + } + if ( c->iTimedInterval.Int() > 0 ) + { + c->iActiveConstraints |= EConstraintTimedCounter; + c->iTimedCounter = c->iOriginalTimedCounter; + } + else + { + c->iActiveConstraints |= EConstraintCounter; + c->iOriginalCounter = c->iOriginalTimedCounter; + c->iCounter = c->iOriginalCounter; + c->iOriginalTimedCounter = 0; + } + } + break; + case ESystemState: +#ifndef __DRM_OMA2 + User::Leave( KErrArgument ); +#endif + if ( iRights->iCurrentConstraint ) + { + HBufC8* b( iContent->AllocLC() ); + iRights->iCurrentConstraint->iSystem.AppendL( b ); + CleanupStack::Pop( b ); + iRights->iCurrentConstraint->iActiveConstraints |= + EConstraintSystem; + } + break; + case EAssetUidState: + iContent->Des().Trim(); // remove ignorable white spaces + if ( !iRights->iCurrentAsset ) + { + User::Leave( KErrArgument ); + } + iRights->iCurrentAsset->iUid = iContent->AllocL(); + break; + case EAssetDigestState: + if ( iParserType == EXmlParser ) + { + DecodeAndDeleteUndecodedL( iContent ); + } + CopyOrLeaveL( iRights->iCurrentAsset->iDigest, *iContent ); + break; + case EAssetKeyState: + if ( iParserType == EXmlParser ) + { + DecodeAndDeleteUndecodedL( iContent ); + } + CopyOrLeaveL( iRights->iCurrentAsset->iKey, *iContent ); + break; + case EEncryptedKeyState: + if ( iParserType == EXmlParser ) + { + DecodeAndDeleteUndecodedL( iContent ); + } + if ( iRights->iKeyIsCek ) + { + CopyOrLeaveL( + iRights->iCurrentAsset->iProtectedKey, *iContent ); + } + else + { + CopyOrLeaveL( + iRights->iCurrentAsset->iProtectedAuthSeed, + *iContent ); + } + break; + case EAssetInheritUidState: + iContent->Des().Trim(); // remove ignorable white spaces + iRights->iCurrentAsset->iInherit = iContent->AllocL(); + break; + case EIndividualState: +#ifndef __DRM_OMA2 + User::Leave( KErrArgument ); +#endif + if ( iRights->iCurrentConstraint ) + { + HBufC8* b( NULL ); + iRights->iCurrentConstraint->iActiveConstraints |= + EConstraintIndividual; + iContent->Des().Trim(); // remove ignorable white spaces + b = iContent->AllocLC(); + iRights->iCurrentConstraint->iIndividual.AppendL( b ); + CleanupStack::Pop( b ); + } + break; + case ESoftwareState: +#ifndef __DRM_OMA2 + User::Leave( KErrArgument ); +#endif + if ( iRights->iCurrentConstraint ) + { + TUint32 n( 0 ); + TLex8 lex( *iContent ); + User::LeaveIfError( lex.Val( n, EHex ) ); + if ( iSoftwareSchemeType == ESymbianSid ) + { + iRights->iCurrentConstraint->iActiveConstraints |= + EConstraintSoftware; + iRights->iCurrentConstraint->iSecureId = + TUid::Uid( n ); + } + else + { + iRights->iCurrentConstraint->iActiveConstraints |= + EConstraintVendor; + iRights->iCurrentConstraint->iVendorId = + TUid::Uid( n ); + } + } + break; + case EExportConstraintState: + case ETopLevelConstraintState: +#ifndef __DRM_OMA2 + User::Leave( KErrArgument ); +#endif + case EDisplayConstraintState: + case EPlayConstraintState: + case EPrintConstraintState: + case EExecuteConstraintState: + iRights->iCurrentConstraint = NULL; + iRights->iCurrentPermission->iCurrentConstraint = 0; + break; + case EPermissionState: + iRights->iCurrentPermission->RemoveInvalidL(); + iRights->iCurrentPermission = NULL; + break; + + } + iElementStackDepth--; + if ( iElementStackDepth < 0 ) + { + User::Leave( EXmlUnexpectedState ); + } + break; // no need to iterate after element name matched + } + } + } + +// ----------------------------------------------------------------------------- +// CDrmRightsParser::OnContentL +// ----------------------------------------------------------------------------- +// +void CDrmRightsParser::OnContentL( + const TDesC8& aBytes, + TInt /*aErrorCode*/ ) + { + if ( iUnknownTag ) + { + return; + } + if ( !iContent ) + { + iContent = HBufC8::NewL( aBytes.Size() ); + *iContent = aBytes; + } + else + { + iContent = iContent->ReAllocL( iContent->Size() + aBytes.Size() ); + TPtr8 c( iContent->Des() ); + c.Append( aBytes ); + } + } + +// ----------------------------------------------------------------------------- +// CDrmRightsParser::OnStartPrefixMappingL +// ----------------------------------------------------------------------------- +// +void CDrmRightsParser::OnStartPrefixMappingL( + const RString& /*aPrefix*/, + const RString& /*aUri*/, + TInt /*aErrorCode*/ ) + { + } + +// ----------------------------------------------------------------------------- +// CDrmRightsParser::OnEndPrefixMappingL +// ----------------------------------------------------------------------------- +// +void CDrmRightsParser::OnEndPrefixMappingL( + const RString& /*aPrefix*/, + TInt /*aErrorCode*/ ) + { + } + +// ----------------------------------------------------------------------------- +// CDrmRightsParser::OnIgnorableWhiteSpaceL +// ----------------------------------------------------------------------------- +// +void CDrmRightsParser::OnIgnorableWhiteSpaceL( + const TDesC8& /*aBytes*/, + TInt /*aErrorCode*/ ) + { + } + +// ----------------------------------------------------------------------------- +// CDrmRightsParser::OnSkippedEntityL +// ----------------------------------------------------------------------------- +// +void CDrmRightsParser::OnSkippedEntityL( + const RString& /*aName*/, + TInt /*aErrorCode*/ ) + { + } + +// ----------------------------------------------------------------------------- +// CDrmRightsParser::OnProcessingInstructionL +// ----------------------------------------------------------------------------- +// +void CDrmRightsParser::OnProcessingInstructionL( + const TDesC8& /*aTarget*/, + const TDesC8& /*aData*/, + TInt /*aErrorCode*/ ) + { + } + +// ----------------------------------------------------------------------------- +// CDrmRightsParser::OnOutOfData +// ----------------------------------------------------------------------------- +// +void CDrmRightsParser::OnOutOfData() + { + } + +// ----------------------------------------------------------------------------- +// CDrmRightsParser::OnError +// ----------------------------------------------------------------------------- +// +void CDrmRightsParser::OnError( + TInt /*aErrorCode*/ ) + { + } + +// ----------------------------------------------------------------------------- +// CDrmRightsParser::GetExtendedInterface +// ----------------------------------------------------------------------------- +// +TAny* CDrmRightsParser::GetExtendedInterface( + const TInt32 /*aUid*/ ) + { + return NULL; + } + +// ----------------------------------------------------------------------------- +// CDrmRightsParser::MatchStackState +// ----------------------------------------------------------------------------- +// +TInt CDrmRightsParser::MatchStackState( void ) + { + TParserStackState r( EUnknownState ); + + for ( TInt i( 0 ); + r == EUnknownState && + i < ELEMENT_COUNT( KParserStackStates ); i++ ) + { + TInt j( 0 ); + TInt k( 0 ); + for ( j = iElementStackDepth - 1, k = 0; + j > 0 && KParserStackStates[ i ].iStack[ k ] != ELast; + j--, k++ ) + { + if ( iElementStack[ j ] != KParserStackStates[ i ].iStack[ k ] ) + { + break; + } + } + if ( ( j == 0 && + iElementStack[ j ] == KParserStackStates[ i ].iStack[ k ] && + KParserStackStates[ i ].iStack[ k + 1 ] == ELast ) || + KParserStackStates[ i ].iStack[ k ] == ELast ) + { + r = KParserStackStates[ i ].iState; + } + } + return r; + } + +// ----------------------------------------------------------------------------- +// CDrmRightsParser::TransformRightsObjectL +// ----------------------------------------------------------------------------- +// +void CDrmRightsParser::TransformRightsObjectL( + RPointerArray< CDRMRights >& aResult ) + { + CParsedAsset* asset( NULL ); + CDRMRights* rights( NULL ); + CParsedPermission* permission( NULL ); + CDRMPermission *ro( CDRMPermission::NewLC() ); + CDRMAsset* a( NULL ); + HBufC8* id( NULL ); + HBufC8* idRef( NULL ); + + // If no permissions are given, create an empty RO. + // The procedure is quite different + // than processing the permissions + if ( iRights->iInvalid ) + { + //The RO is invalid. Let's leave + User::Leave( KErrArgument ); + } + if ( iRights->iPermissions.Count() == 0 ) + { + for ( TInt i( 0 ); i < iRights->iAssets.Count(); i++ ) + { + asset = iRights->iAssets[ i ]; + // No uid for the asset, it's an invalid asset + if( !asset->iUid ) + { + continue; + } + + rights = CDRMRights::NewL(); + CleanupStack::PushL( rights ); + + a = CDRMAsset::NewLC(); + a->iDigest.Copy( asset->iDigest ); + a->iKey.Copy( asset->iKey ); + a->iProtectedKey.Copy( asset->iProtectedKey ); + a->iAuthenticationSeed.Copy( asset->iAuthenticationSeed ); + a->iProtectedAuthSeed.Copy( asset->iProtectedAuthSeed ); + + // guaranteed not to be NULL UID in this phase + a->iUid = asset->iUid->AllocL(); + + if ( ro->iParentUID ) + { + delete ro->iParentUID; + ro->iParentUID = NULL; + } + if ( asset->iInherit ) + { + a->iParentRights = asset->iInherit->AllocL(); + ro->iParentUID = asset->iInherit->AllocL(); + } + rights->SetAssetL( *a ); + CleanupStack::PopAndDestroy( a ); + + // by default, set the RO version as OMA 1.0 + ro->iRightsObjectVersion.iVersionMain = EOma1Rights; + rights->SetPermissionL( *ro ); + + // Warning: assuming RPointerArray + // does not put its argument to clenaupstack + aResult.AppendL( rights ); + CleanupStack::Pop( rights ); + } + } + else for ( TInt i( 0 ); i < iRights->iPermissions.Count(); i++ ) + { + permission = iRights->iPermissions[ i ]; + if ( permission->iInvalid ) + { + // The permission under test is invalid, so let's move forward + continue; + } + if ( permission->iAssets.Count() > 0 ) + { + // The permission refers to asset elements in the RO, + // add all referenced assets to the permission + for ( TInt j( 0 ); j < permission->iAssets.Count(); j++ ) + { + TInt k( 0 ); + for ( ; k < iRights->iAssets.Count(); k++ ) + { + id = iRights->iAssets[ k ]->iId; + idRef = permission->iAssets[ j ]->iIdRef; + if ( id && idRef && *id == *idRef ) + { + break; + } + } + if ( k < iRights->iAssets.Count() ) + { + asset = permission->iAssets[ j ]; + permission->iAssets[ j ] = iRights->iAssets[ k ]; + delete asset; + permission->iNotOwned++; + } + } + } + else + { + // The permission does not refer to an asset explictly, + // link all assets in the RO to this permission + for ( TInt j( 0 ); j < iRights->iAssets.Count(); j++ ) + { + permission->iAssets.Append( iRights->iAssets[ j ] ); + permission->iNotOwned++; + } + } + + for ( TInt j( 0 ); j < permission->iAssets.Count(); j++ ) + { + asset = permission->iAssets[ j ]; + // No uid for the asset, it's an invalid asset + if( !asset->iUid ) + { + continue; + } + + rights = CDRMRights::NewL(); + CleanupStack::PushL( rights ); + + a = CDRMAsset::NewLC(); + a->iDigest.Copy( asset->iDigest ); + a->iKey.Copy( asset->iKey ); + a->iProtectedKey.Copy( asset->iProtectedKey ); + a->iAuthenticationSeed.Copy( asset->iAuthenticationSeed ); + a->iProtectedAuthSeed.Copy( asset->iProtectedAuthSeed ); + + // guaranteed not to be NULL UID in this phase + a->iUid = asset->iUid->AllocL(); + + if ( ro->iParentUID ) + { + delete ro->iParentUID; + ro->iParentUID = NULL; + } + if ( asset->iInherit ) + { + a->iParentRights = asset->iInherit->AllocL(); + ro->iParentUID = asset->iInherit->AllocL(); + } + rights->SetAssetL( *a ); + CleanupStack::PopAndDestroy( a ); + + + // ( == iOnExpiredUrl must not be referred elsewhere) + ro->iOnExpiredUrl = permission->iOnExpiredUrl; + permission->iOnExpiredUrl = NULL; + + ro->iAvailableRights = permission->iAvailableRights; + ro->iDisplay->DuplicateL( *permission->iDisplay ); + ro->iPlay->DuplicateL( *permission->iPlay ); + ro->iPrint->DuplicateL( *permission->iPrint ); + ro->iExecute->DuplicateL( *permission->iExecute ); + ro->iExport->DuplicateL( *permission->iExport ); + ro->iTopLevel->DuplicateL( *permission->iTopLevel ); + // by default, set the RO version as OMA 1.0 + ro->iRightsObjectVersion.iVersionMain = EOma1Rights; + rights->SetPermissionL( *ro ); + + aResult.AppendL( rights ); + CleanupStack::Pop( rights ); + } + } + CleanupStack::PopAndDestroy( ro ); + } + +// ----------------------------------------------------------------------------- +// CDrmRightsParser::GetAttributeValueL +// ----------------------------------------------------------------------------- +// +HBufC8* CDrmRightsParser::GetAttributeValueL( + const RAttributeArray& aAttrList, + const TDesC8& aAttrName ) + { + HBufC8* r( NULL ); + RAttribute a; + + for ( TInt i( 0 ); !r && i < aAttrList.Count(); i++ ) + { + a = aAttrList[ i ]; + if ( a.Attribute().LocalName().DesC().Compare( aAttrName ) == 0 ) + { + r = a.Value().DesC().AllocL(); + } + } + return r; + } + +// End of File