/*
* 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 <e32base.h>
#include <e32math.h>
#include <apmstd.h>
#include <utf.h>
#include <stringpool.h>
#include <xml/parserfeature.h>
#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 <permission>
// CDRMConstraint reperesents indivdual permissions as constraint container
// (except Toplevel constraint really represents
// constraint container <constraint>)
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