omadrm/drmengine/ro/src/DrmRightsParser.cpp
changeset 0 95b198f216e5
child 12 8a03a285ab14
--- /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 <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