omadrm/drmengine/ro/src/DRMConstraint.cpp
changeset 0 95b198f216e5
child 12 8a03a285ab14
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/omadrm/drmengine/ro/src/DRMConstraint.cpp	Thu Dec 17 08:52:27 2009 +0200
@@ -0,0 +1,1174 @@
+/*
+* Copyright (c) 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:  Datatype implementation for Rights Constraint
+*
+*/
+
+
+// INCLUDE FILES
+#include <s32strm.h>
+#include <s32mem.h>
+#include "DRMConstraint.h"
+
+// CONSTANTS
+
+// Synchronizing marker in the beginning of the stream in order to synchronize
+// to an externalized Constraint object having the new structure.  
+const TInt32 KSyncMark = 0xAFCE;
+
+// Old and new version number of the Constraint object
+const TInt8 KVersion3_2_0 = 0;
+const TInt8 KVersion3_2_1 = 1; 
+   
+const TInt KSanityDataLengthLow = 0;
+const TInt KSanityDataLengthHigh = 32768;
+
+
+// ============================ LOCAL FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// SanitizeL
+// Performs a sanity check on length parameters
+// -----------------------------------------------------------------------------
+//
+LOCAL_C void SanitizeL( TInt aParam )
+    {
+    if( aParam < KSanityDataLengthLow || aParam > KSanityDataLengthHigh )
+        {
+        User::Leave(KErrArgument);
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// AppendToArrayL
+// Appends the strings of array aFrom to array aTo
+// -----------------------------------------------------------------------------
+//
+LOCAL_C void AppendToArrayL( RPointerArray<HBufC8>& aTo, 
+                             const RPointerArray<HBufC8>& aFrom )
+    {
+    HBufC8* addData = NULL;
+    
+    for( TInt i = 0; i < aFrom.Count(); i++ )
+        {
+        addData = aFrom[i]->AllocLC();
+        aTo.AppendL( addData );
+        CleanupStack::Pop( addData ); 
+        }    
+    }
+
+// -----------------------------------------------------------------------------
+// CountArrayStoreSize
+// Returns the size in bytes how much the array needs for storing
+// -----------------------------------------------------------------------------
+//
+LOCAL_C TInt CountArrayStoreSize( const RPointerArray<HBufC8>& aArray )
+    {
+    TInt size = 0;
+    
+    for(TInt i = 0; i < aArray.Count(); i++ )
+        {
+        size += sizeof(TInt);
+        size += aArray[i]->Size();
+        }
+    return size;    
+    }
+// -----------------------------------------------------------------------------
+// WriteArrayToStreamL
+// Write the array to the stream
+// -----------------------------------------------------------------------------
+//
+LOCAL_C void WriteArrayToStreamL( RWriteStream& aStream,
+                                  const RPointerArray<HBufC8>& aArray )
+    {
+    for(TInt i = 0; i < aArray.Count(); i++ )
+        {
+        aStream.WriteInt32L( aArray[i]->Size() );
+        aStream.WriteL( aArray[i]->Des() );
+        }
+    }
+    
+// -----------------------------------------------------------------------------
+// ReadArrayFromStringL
+// Reads the array from the string
+// -----------------------------------------------------------------------------
+//    
+LOCAL_C void ReadArrayFromStringL( const TDesC8& aString,
+                                   RPointerArray<HBufC8>& aArray )
+    {
+    RMemReadStream inRead( static_cast<const TAny*>( aString.Ptr() ), aString.Size() );
+    TInt size = 0;
+    HBufC8* addData = NULL;
+    TPtr8 dataBuffer(NULL,0,0);
+    CleanupClosePushL( inRead );
+    
+    
+    aArray.ResetAndDestroy();
+    
+    
+    for( TInt i = 0; i < aString.Size();)
+        {
+        // If there is not enough data to read the integer 
+        // it means that it's an old version and the whole thing is the
+        // string since in previous versions only one string is stored        
+        if(( aString.Size() - i) < sizeof(TInt) )
+            {
+            aArray.ResetAndDestroy();
+            addData = aString.AllocLC();
+            aArray.AppendL( addData );
+            CleanupStack::Pop();
+            CleanupStack::PopAndDestroy(); // inRead              
+            return;            
+            }
+        
+        size = inRead.ReadInt32L();
+        i += sizeof(TInt);
+        
+        // If the size is negative or the size left is not large enough
+        // it means that it's an old version and the whole thing is the
+        // string since in previous versions only one string is stored.
+        if( size < 0 || size > ( aString.Size() - i ) )
+            {
+            aArray.ResetAndDestroy();
+            addData = aString.AllocLC();
+            aArray.AppendL( addData );
+            CleanupStack::Pop();
+            CleanupStack::PopAndDestroy(); // inRead            
+            return;
+            }
+        addData = HBufC8::NewMaxLC( size );    
+
+        // Set the read buffer:
+        dataBuffer.Set(const_cast<TUint8*>(addData->Ptr()), 0, size);
+        
+        // Read the data:
+        inRead.ReadL( dataBuffer );
+        
+        aArray.AppendL( addData );
+        CleanupStack::Pop( addData );
+
+        i += size;
+        }
+    CleanupStack::PopAndDestroy();    
+    return;
+    }
+    
+// -----------------------------------------------------------------------------
+// IsIndividualConstraintValid
+// -----------------------------------------------------------------------------
+//
+LOCAL_C TBool IsIndividualConstraintValid( const RPointerArray<HBufC8>& aConstraint, 
+                                           const RPointerArray<HBufC8>& aValidConstraints)
+    {
+    TInt retVal = 0;
+    
+    for( TInt i = 0; i < aConstraint.Count(); i++ )
+        {
+        for( TInt j = 0; j < aValidConstraints.Count(); j++ )
+            {
+            retVal = aConstraint[i]->Des().Compare( aValidConstraints[j]->Des() );
+            if( !retVal )
+                {
+                return ETrue;
+                }
+            }
+        }
+    return EFalse;    
+    };
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+
+// -----------------------------------------------------------------------------
+// CDRMConstraint::NewLC
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C CDRMConstraint* CDRMConstraint::NewLC()
+    {
+    CDRMConstraint* self = new( ELeave ) CDRMConstraint();
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    
+    return self;    
+    };
+
+// -----------------------------------------------------------------------------
+// CDRMConstraint::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C CDRMConstraint* CDRMConstraint::NewL()
+    {
+    CDRMConstraint* self = NewLC();
+    CleanupStack::Pop();
+    
+    return self;
+    }; 
+
+// -----------------------------------------------------------------------------
+// Default Constructor - First phase.
+// Can be used by itself to generate an empty object
+// -----------------------------------------------------------------------------
+//
+EXPORT_C CDRMConstraint::CDRMConstraint() :
+    iSyncMark( KSyncMark ),
+    iVersion( KVersion3_2_1 ), // Version number for differentiation 
+                               // in InternalizeL. 
+    iStartTime( Time::NullTTime() ),
+    iEndTime( Time::NullTTime() ),
+    iIntervalStart( Time::NullTTime() ),
+    iInterval( 0 ),
+    iCounter( 0 ),
+    iOriginalCounter( 0 ),
+    iTimedCounter( 0 ),
+	iTimedInterval( 0 ),
+	iAccumulatedTime( 0 ),
+	iVendorId( TUid::Null() ),
+	iSecureId( TUid::Null() ),
+    iActiveConstraints( 0 ),
+    iDrmMeteringInfo( NULL ),
+    iOriginalTimedCounter( 0 ) 
+    {
+    }
+    
+// -----------------------------------------------------------------------------
+// Destructor
+// -----------------------------------------------------------------------------
+// 
+EXPORT_C CDRMConstraint::~CDRMConstraint()
+    {
+
+    iIndividual.ResetAndDestroy();
+    iIndividual.Close();
+    
+    iSystem.ResetAndDestroy();
+    iSystem.Close(); 
+            
+#ifdef RD_DRM_METERING       
+    if( iDrmMeteringInfo )
+        {
+        delete iDrmMeteringInfo;
+        iDrmMeteringInfo = NULL;
+        }
+#endif
+        
+    }; 
+
+// -----------------------------------------------------------------------------
+// CDRMConstraint::ExternalizeL
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CDRMConstraint::ExternalizeL( RWriteStream& aStream ) const
+    {
+    
+    // used for the buffers
+    TInt32 dataLength = 0;
+    
+    // write the synchronizing marker
+    aStream.WriteInt32L( iSyncMark );
+    
+    // Write the version number
+    aStream.WriteInt32L( iVersion );
+    
+    // Write the start time
+    WriteInt64L( iStartTime.Int64(), aStream );
+    
+    // Write the end time
+    WriteInt64L( iEndTime.Int64(), aStream );
+    
+    // Write the interval start time
+    WriteInt64L( iIntervalStart.Int64(), aStream ); 
+    
+    // Write the interval   
+    aStream.WriteInt32L( iInterval.Int() );
+    
+    // Write the counter
+    aStream.WriteInt32L( iCounter );
+    
+    // Write the original counter
+    aStream.WriteInt32L( iOriginalCounter );
+    
+    // Write the timed counter
+    aStream.WriteInt32L( iTimedCounter );
+
+    // Write the timed interval
+    aStream.WriteInt32L( iTimedInterval.Int() );
+    
+    // Write the accumulated time
+    aStream.WriteInt32L( iAccumulatedTime.Int() );
+    
+    // Write the individual
+    dataLength = 0;
+    if ( iIndividual.Count() )
+        {
+        dataLength = CountArrayStoreSize( iIndividual );
+        }
+    aStream.WriteInt32L( dataLength );
+
+    if ( dataLength )
+        {
+        WriteArrayToStreamL( aStream, iIndividual );       
+        }         
+    
+    // Software Vendor Id
+    aStream.WriteInt32L( iVendorId.iUid );
+    
+    // Secure Id of the allowed application
+    aStream.WriteInt32L( iSecureId.iUid );
+    
+    // Active constraints
+    aStream.WriteUint32L( iActiveConstraints );
+    
+    // Metering info
+#ifdef RD_DRM_METERING    
+    dataLength = 0;
+    if ( iDrmMeteringInfo )
+        {
+        dataLength = sizeof( TTimeIntervalSeconds ) + sizeof( TUint8 );
+        }
+    
+    aStream.WriteInt32L( dataLength );
+    
+    if ( dataLength )
+        {
+        aStream.WriteInt32L( iDrmMeteringInfo->iGraceTime.Int() );
+        aStream.WriteInt8L( iDrmMeteringInfo->iAllowUseWithoutMetering );
+        }
+   
+#endif
+    
+    // Write the system
+    dataLength = 0;
+    if ( iSystem.Count() )
+        {
+        dataLength = CountArrayStoreSize( iSystem );
+        }
+    
+    aStream.WriteInt32L( dataLength );
+        
+    if ( dataLength )
+        {
+        WriteArrayToStreamL( aStream, iSystem );
+        }
+            
+    // write the original timed counter
+    aStream.WriteInt32L( iOriginalTimedCounter );
+        
+    // For future use
+    aStream.WriteInt32L( 0 );
+    
+    };
+    
+// -----------------------------------------------------------------------------
+// CDRMConstraint::InternalizeL
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CDRMConstraint::InternalizeL( RReadStream& aStream )
+    {
+
+    TInt64 timeData = 0;
+    TInt32 temp = 0;
+    
+    // used for the buffers
+    TInt dataLength = 0;
+    HBufC8* dataPart = NULL;
+    TPtr8 dataBuffer(NULL,0,0);
+    
+    // Read the (possible) synchronizing marker.
+    iSyncMark = aStream.ReadInt32L();
+    
+    if ( iSyncMark != KSyncMark )
+        {
+         
+        // The structure of the externalized Permission object is the old one.
+        // The first four bytes constitute half of the eight bytes of Start time.
+        // Read another four bytes from the stream (and apply bit modifications) 
+        // in order to reconstruct the Start time (iStartTime).
+        temp = aStream.ReadInt32L();
+        
+        timeData = temp;
+        timeData <<= 32;
+        
+        Mem::Copy( &timeData, &iSyncMark, sizeof(TInt32) );
+        
+        iStartTime = timeData;
+        timeData = 0;
+         
+        // The version is marked as old version for differentiation in 
+        // InternalizeL.
+        iVersion = KVersion3_2_0;
+                             
+        }
+    else 
+        {
+        // The structure of the externalized Permission object is the new one.
+        // Read the version and Start time.    
+        iVersion = aStream.ReadInt32L();
+        
+        // Read the start time
+        ReadInt64L( timeData, aStream );
+        iStartTime = timeData;
+        
+        }
+     
+    // Read the end time
+    ReadInt64L( timeData, aStream );
+    iEndTime = timeData;
+    
+    // Read the interval start time
+    ReadInt64L( timeData, aStream ); 
+    iIntervalStart = timeData;
+    
+    // Read the interval   
+    iInterval = aStream.ReadInt32L();
+    
+    // Read the counter
+    iCounter = aStream.ReadInt32L();
+    
+    // Read the original counter
+    iOriginalCounter = aStream.ReadInt32L();
+    
+    // Read the timed counter
+    iTimedCounter = aStream.ReadInt32L();
+
+    // Read the timed interval
+    iTimedInterval = aStream.ReadInt32L();
+    
+    // Read the accumulated time
+    iAccumulatedTime = aStream.ReadInt32L();
+    
+    // Read the individual
+    dataLength = aStream.ReadInt32L();
+    
+    SanitizeL( dataLength );
+    
+    if( dataLength > 0 )
+        {
+        // Reserve a new buffer:
+        dataPart = HBufC8::NewMaxLC( dataLength );
+        
+        // Set the read buffer:
+        dataBuffer.Set(const_cast<TUint8*>(dataPart->Ptr()), 0, dataLength);
+        
+        // Read the data:
+        aStream.ReadL( dataBuffer );
+        
+        
+        // Fill the array from the string
+        ReadArrayFromStringL( dataBuffer, iIndividual);
+        
+        // Pop the buffer 
+        CleanupStack::PopAndDestroy(); // dataPart
+                    
+        }
+    else
+        {
+        iIndividual.ResetAndDestroy();       
+        }           
+    
+    
+    // Read the system 
+    if ( iVersion == KVersion3_2_0 ) // Constraint has the old structure.
+        {
+        
+        dataLength = aStream.ReadInt32L();
+        
+        SanitizeL( dataLength );
+        
+        if( dataLength > 0 )
+            {
+            // Reserve a new buffer:
+            dataPart = HBufC8::NewMaxLC( dataLength );
+        
+            // Set the read buffer:
+            dataBuffer.Set( const_cast<TUint8*>(dataPart->Ptr()), 0, 
+                            dataLength );
+        
+            // Read the data:
+            aStream.ReadL( dataBuffer );
+        
+            // Pop the buffer 
+            CleanupStack::Pop(); // dataPart
+                
+            // If an old content identifier exists delete it        
+            if ( iSystem.Count() )
+                {
+                iSystem.ResetAndDestroy();
+                }
+        
+            // assign the new content id
+            iSystem.AppendL( dataPart );    
+            }
+        else
+            {
+            // If an old system exists delete it 
+            if ( iSystem.Count() )
+                {
+                iSystem.ResetAndDestroy();
+                }        
+            }  
+        }
+    
+    // Software Vendor Id
+    iVendorId.iUid = aStream.ReadInt32L();
+    
+    // Secure Id of the allowed application
+    iSecureId.iUid = aStream.ReadInt32L(); 
+    
+    // Active constraints
+    iActiveConstraints = aStream.ReadUint32L();    
+
+#ifdef RD_DRM_METERING    
+    
+    // Do not read metering information if the version
+    // is the old one because Metering is not activated in it.
+    if ( iVersion == KVersion3_2_1 )
+        {
+        
+        // Metering info
+        dataLength = aStream.ReadInt32L();
+    
+        SanitizeL( dataLength );
+        
+        if( dataLength > 0 )
+            {
+        
+            if( !iDrmMeteringInfo )
+                {
+                // Reserve a new metering information instance
+                iDrmMeteringInfo = new (ELeave)TDrmMeteringInfo;
+                }
+            else 
+                {
+                iDrmMeteringInfo->iGraceTime = 0;
+                iDrmMeteringInfo->iAllowUseWithoutMetering = EFalse;
+                }
+        
+            // Read grace time 
+            iDrmMeteringInfo->iGraceTime = aStream.ReadInt32L();
+        
+            // Read whether content can be consumed without 
+            // metering being used
+            iDrmMeteringInfo->iAllowUseWithoutMetering = 
+                aStream.ReadInt8L();
+           
+            }
+        else
+            {
+        
+            // If old metering information exists delete it 
+            if( iDrmMeteringInfo )
+                {
+                delete iDrmMeteringInfo;
+                iDrmMeteringInfo = NULL;
+                }        
+            }
+        }
+    
+#endif //RD_DRM_METERING
+
+    // Read the system and original timed counter
+    // according to the new structure.
+    if ( iVersion == KVersion3_2_1 )
+        {
+        
+        dataLength = aStream.ReadInt32L();
+        
+        SanitizeL( dataLength );
+            
+        if( dataLength > 0 )
+            {
+            // Reserve a new buffer:
+            dataPart = HBufC8::NewMaxLC( dataLength );
+        
+            // Set the read buffer:
+            dataBuffer.Set(const_cast<TUint8*>(dataPart->Ptr()), 0, dataLength);
+        
+            // Read the data:
+            aStream.ReadL( dataBuffer );
+        
+            // Fill the array from the string
+            ReadArrayFromStringL( dataBuffer, iSystem);
+        
+            // Pop the buffer 
+            CleanupStack::PopAndDestroy(); // dataPart
+                    
+            }
+        else
+            {
+            iSystem.ResetAndDestroy();       
+            }         
+    
+        // Read the original timed counter
+        iOriginalTimedCounter = aStream.ReadInt32L();
+    
+        // For future use or development, reads the data at the end of the stream
+        dataLength = aStream.ReadInt32L();
+        
+        SanitizeL( dataLength );
+        
+        if ( dataLength > 0 )
+            {
+      
+            // Reserve a new buffer:
+            dataPart = HBufC8::NewMaxLC( dataLength );
+        
+            // Set the read buffer:
+            dataBuffer.Set(const_cast<TUint8*>(dataPart->Ptr()), 0, dataLength);
+        
+            // Read the data:
+            aStream.ReadL( dataBuffer );
+        
+            // Pop the buffer 
+            CleanupStack::PopAndDestroy( dataPart );
+            }
+        }
+    
+    // Constraint can be considered to have the new structure from now on. 
+    if ( iVersion == KVersion3_2_0 ) 
+        {
+        iSyncMark = KSyncMark;
+        iVersion = KVersion3_2_1; 
+        }
+    
+    };
+    
+// -----------------------------------------------------------------------------
+// CDRMConstraint::Stateful
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TBool CDRMConstraint::Stateful() const
+    {
+    // counters, timed counters and accumulated are stateful
+    if ( iActiveConstraints &  (EConstraintCounter |
+                               EConstraintTimedCounter |
+                               EConstraintAccumulated ) ) 
+        {
+        return ETrue;
+        }
+        
+     // Non-Activated interval is stateful
+    if ( ( iActiveConstraints & EConstraintInterval ) &&
+        iIntervalStart == Time::NullTTime() ) 
+        {
+        return ETrue;
+        }
+        
+    return EFalse;
+    };
+
+// -----------------------------------------------------------------------------
+// CDRMConstraint::Size
+// -----------------------------------------------------------------------------
+//   
+EXPORT_C TInt CDRMConstraint::Size() const
+    {
+    TInt size = 0;
+    
+    // synchronizing marker
+    size += sizeof(TInt32);
+    
+    // version number
+    size += sizeof(TInt32);
+    
+    // usage start time
+    size += sizeof(TTime);
+
+    // usage end time
+    size += sizeof(TTime);
+
+    // interval start time
+    size += sizeof(TTime);
+
+    // interval duration
+    size += sizeof(TTimeIntervalSeconds);
+
+    // counter
+    size += sizeof(TDRMCounter);
+
+    // original counter value
+    size += sizeof(TDRMCounter);
+
+    // timed counter
+	size += sizeof(TDRMCounter);
+
+    // Interval of the timed counter constraint
+	size += sizeof(TTimeIntervalSeconds);
+
+    // accumulated time
+	size += sizeof(TTimeIntervalSeconds);
+
+    // individual allowed usage
+    size += sizeof(TInt32);
+    size += CountArrayStoreSize( iIndividual );
+
+    // Software Vendor Id
+    size += sizeof(TUid);
+    
+    // Secure Id of the allowed application
+    size += sizeof(TUid);
+	
+	// Bitmask of active constraints
+    size += sizeof(TUint32);
+    
+#ifdef RD_DRM_METERING    
+    // Metering information
+    size += sizeof(TInt32);
+    
+    if (iDrmMeteringInfo)
+        {
+        size += sizeof(TTimeIntervalSeconds); 
+        size += sizeof(TUint8);
+        }
+    
+#endif //RD_DRM_METERING
+    
+    // system allowed usage
+    size += sizeof(TInt32);
+    size += CountArrayStoreSize(iSystem);
+    
+    // original timed counter value
+    size += sizeof(TDRMCounter);
+    
+    // For future use
+    size += sizeof(TInt32);
+    
+    return size;
+       
+    };    
+
+// -----------------------------------------------------------------------------
+// CDRMConstraint::Expired
+// -----------------------------------------------------------------------------
+//      
+EXPORT_C TBool CDRMConstraint::Expired( const TTime& aTime ) const
+    {
+	// Full Rights do not expire
+	if ( iActiveConstraints == EConstraintNone )
+		{
+		return EFalse;
+		}
+
+	// First check counters, accumulated time and timed counters
+	// if any of these is expired the whole thing is expired regardless of the
+	// actual time based constrants or future rights
+	
+    // Counters
+    if ( ( iActiveConstraints & EConstraintCounter ) && iCounter < 1 ) 
+    	{
+    	return ETrue;	
+    	}
+    		
+    // Accumulated time	
+    if ( ( iActiveConstraints & EConstraintAccumulated ) && iAccumulatedTime.Int() == 0 )
+    	{
+    	return ETrue;
+    	}
+    		
+     // Timed Counters
+    if ( ( iActiveConstraints & EConstraintTimedCounter ) && iTimedCounter < 1 ) 
+    	{
+    	return ETrue;	
+    	} 
+    		
+
+    // Dont check time based rights
+    if ( aTime != Time::NullTTime() )
+    	{	
+    	
+    	// Check for activated intervals
+    	if ( ( iActiveConstraints & EConstraintInterval) && iIntervalStart != Time::NullTTime() )
+    		{
+        	TTimeIntervalSeconds current;
+        
+        	aTime.SecondsFrom( iIntervalStart, current );
+        
+        	if ( current >= iInterval )
+            	{
+            	return ETrue;
+            	}    			
+    		}
+    	
+    	// Check for end time
+    	if ( ( iActiveConstraints & EConstraintEndTime ) && aTime >= iEndTime )
+    		{
+    		return ETrue;	
+    		}	
+    		
+    	// Check for start time, future rights	
+    	if ( ( iActiveConstraints & EConstraintStartTime ) && aTime < iStartTime )
+    		{
+    		return EFalse;	
+    		}
+    	}
+
+    return EFalse;
+    }
+// -----------------------------------------------------------------------------
+// CDRMConstraint::Merge
+// -----------------------------------------------------------------------------
+//      
+EXPORT_C void CDRMConstraint::Merge( const CDRMConstraint& aConstraint )
+    {
+    TInt error = KErrNone;
+    
+    if ( this != &aConstraint )
+        {
+        if ( aConstraint.iActiveConstraints & EConstraintStartTime )
+            {
+            if ( iActiveConstraints & EConstraintStartTime )
+                {
+                iStartTime = Max( iStartTime, aConstraint.iStartTime );
+                }
+            else
+                {
+                iStartTime = aConstraint.iStartTime;
+                iActiveConstraints |= EConstraintStartTime;
+                }
+            }
+            
+        if ( aConstraint.iActiveConstraints & EConstraintEndTime )
+            {
+            if ( iActiveConstraints & EConstraintEndTime )
+                {
+                iEndTime = Min( aConstraint.iEndTime, iEndTime );
+                }
+            else
+                {
+                iEndTime = aConstraint.iEndTime;
+                iActiveConstraints |= EConstraintEndTime;
+                }
+            }
+            
+        if ( aConstraint.iActiveConstraints & EConstraintCounter )
+            {
+            if ( iActiveConstraints & EConstraintCounter )
+                {
+                iCounter = Min( iCounter, aConstraint.iCounter );
+                iOriginalCounter = Min( iOriginalCounter, aConstraint.iOriginalCounter );
+                }
+            else
+                {
+                iCounter = aConstraint.iCounter;
+                iOriginalCounter = aConstraint.iOriginalCounter;
+                iActiveConstraints |= EConstraintCounter;
+                }
+            }
+        
+        if ( aConstraint.iActiveConstraints & EConstraintInterval )
+            {
+            if ( iActiveConstraints & EConstraintInterval )
+                {
+                iIntervalStart = Max( iIntervalStart, aConstraint.iIntervalStart );
+                iInterval = Min( iInterval, aConstraint.iInterval );
+                }
+            else
+                {
+                iIntervalStart = aConstraint.iIntervalStart;
+                iInterval = aConstraint.iInterval;
+                iActiveConstraints |= EConstraintInterval;
+                }
+            }
+            
+        if ( aConstraint.iActiveConstraints & EConstraintTimedCounter )
+            {
+            if ( iActiveConstraints & EConstraintTimedCounter )
+                {
+                if ( aConstraint.iTimedCounter < iTimedCounter )
+                    {
+                    iTimedCounter = aConstraint.iTimedCounter;
+                    iTimedInterval = aConstraint.iTimedInterval;
+                    }
+                }
+            else
+                {
+                iTimedCounter = aConstraint.iTimedCounter;
+                iTimedInterval = aConstraint.iTimedInterval;
+                iActiveConstraints |= EConstraintTimedCounter;
+                }
+            }
+        
+        if ( aConstraint.iActiveConstraints & EConstraintAccumulated )
+            {
+            if ( iActiveConstraints & EConstraintAccumulated )
+                {
+                iAccumulatedTime = Min( iAccumulatedTime, aConstraint.iAccumulatedTime );
+                }
+            else
+                {
+                iAccumulatedTime = aConstraint.iAccumulatedTime;
+                iActiveConstraints |= EConstraintAccumulated;
+                }
+            }
+             
+        if( aConstraint.iActiveConstraints & EConstraintIndividual )
+            {
+            // Ignore the error since we don't return an error code or leave
+            TRAP( error, AppendToArrayL( iIndividual, aConstraint.iIndividual ) );
+            }
+            
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CDRMConstraint::Consume  
+// -----------------------------------------------------------------------------
+//  
+EXPORT_C void CDRMConstraint::Consume( const TTime& aCurrentTime )
+    {
+    if ( ( iActiveConstraints & EConstraintInterval ) &&
+        iIntervalStart == Time::NullTTime() )
+        {
+        iIntervalStart = aCurrentTime;
+        }
+        
+    if ( iActiveConstraints & EConstraintCounter )
+        {
+        --iCounter;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CDRMConstraint::DuplicateL
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CDRMConstraint::DuplicateL( const CDRMConstraint& aConstraint )
+    {
+    
+    // synchronizing marker
+    iSyncMark = aConstraint.iSyncMark;
+    
+    // version number
+    iVersion = aConstraint.iVersion;
+    
+    // usage start time
+    iStartTime = aConstraint.iStartTime;
+
+    // usage end time
+    iEndTime = aConstraint.iEndTime;
+
+    // interval start time
+    iIntervalStart = aConstraint.iIntervalStart;
+
+    // interval duration
+    iInterval = aConstraint.iInterval;
+
+    // counter
+    iCounter = aConstraint.iCounter;
+
+    // original counter value
+    iOriginalCounter = aConstraint.iOriginalCounter;
+
+    // timed counter
+	iTimedCounter = aConstraint.iTimedCounter;
+
+    // Interval of the timed counter constraint
+	iTimedInterval = aConstraint.iTimedInterval;
+
+    // accumulated time
+	iAccumulatedTime = aConstraint.iAccumulatedTime;
+
+    // individual allowed usage
+    iIndividual.ResetAndDestroy();
+    
+    AppendToArrayL( iIndividual, aConstraint.iIndividual );
+	
+    // Software Vendor Id
+    iVendorId = aConstraint.iVendorId;
+	
+    // Secure Id of the allowed application
+    iSecureId = aConstraint.iSecureId;
+	
+	// Bitmask of active constraints
+    iActiveConstraints = aConstraint.iActiveConstraints;	// Bitmask
+
+#ifdef RD_DRM_METERING    
+    // Metering information
+    if ( aConstraint.iDrmMeteringInfo )
+        {
+        
+        if( !iDrmMeteringInfo )
+            {
+            iDrmMeteringInfo = new (ELeave) TDrmMeteringInfo;
+            }
+    
+        iDrmMeteringInfo->iGraceTime = aConstraint.iDrmMeteringInfo->iGraceTime;
+        iDrmMeteringInfo->iAllowUseWithoutMetering = aConstraint.iDrmMeteringInfo->iAllowUseWithoutMetering; 
+        }
+#endif
+    
+    // system allowed usage
+    iSystem.ResetAndDestroy();
+    AppendToArrayL( iSystem, aConstraint.iSystem );
+    
+    // original timed counter value
+    iOriginalTimedCounter = aConstraint.iOriginalTimedCounter;
+    
+    };
+
+
+// -----------------------------------------------------------------------------
+// CDRMConstraint::Valid
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TBool CDRMConstraint::Valid( const TTime& aTime,
+                                      const RPointerArray<HBufC8>& aIndividual,
+                                      TUint32& aRejection ) const
+	{
+	TBool drmTime = EFalse;
+	// Null the rejection requirement:
+	aRejection = EConstraintNone;
+	
+	// Full Rights are always valid
+	if ( iActiveConstraints == EConstraintNone )
+		{
+		return ETrue;
+		}
+
+	// First check counters, accumulated time and timed counters
+	// if any of these are invalid the whole thing is invalid regardless of the
+	// actual time based constraints
+	
+    // Counters
+    if ( ( iActiveConstraints & EConstraintCounter ) && iCounter < 1 ) 
+    	{
+    	aRejection |= EConstraintCounter;
+    	}
+    		
+    // Accumulated time	
+    if ( ( iActiveConstraints & EConstraintAccumulated ) && iAccumulatedTime.Int() == 0 )
+    	{
+    	aRejection |= EConstraintAccumulated;
+    	}
+    		
+     // Timed Counters
+    if ( ( iActiveConstraints & EConstraintTimedCounter ) && iTimedCounter < 1 ) 
+    	{
+    	aRejection |= EConstraintTimedCounter;	
+    	} 
+    		
+    // Dont check time based rights
+    if ( aTime != Time::NullTTime() )
+    	{	
+    	drmTime = ETrue;
+    	// Check for activated intervals
+    	if ( (iActiveConstraints & EConstraintInterval) && iIntervalStart != Time::NullTTime() )
+    		{
+        	TTimeIntervalSeconds current;
+        
+        	aTime.SecondsFrom( iIntervalStart, current );
+        
+        	if ( ( current >= iInterval ) || ( aTime < iIntervalStart ) )
+            	{
+            	aRejection |= EConstraintInterval;
+            	}    			
+    		}
+    	
+    	// Check for end time
+    	if ( ( iActiveConstraints & EConstraintEndTime ) && aTime >= iEndTime ) 
+    	    {
+    	    aRejection |= EConstraintEndTime;
+    	    }
+    	    
+    	if ( ( iActiveConstraints & EConstraintStartTime ) && aTime < iStartTime )     
+    		{
+    		aRejection |= EConstraintStartTime;	
+    		}	
+    	}
+    else
+        {
+        drmTime = EFalse;
+        
+    	// Check for activated intervals
+    	if ( (iActiveConstraints & EConstraintInterval) )
+    		{
+            aRejection |= EConstraintInterval; 			
+    		}
+    	
+    	// Check for end time
+    	if ( ( iActiveConstraints & EConstraintEndTime ) ) 
+    	    {
+    	    aRejection |= EConstraintEndTime;
+    	    }
+    	    
+    	if( ( iActiveConstraints & EConstraintStartTime ) )     
+    		{
+    		aRejection |= EConstraintStartTime;	
+    		}
+        }	
+
+    // IMSI Checking:
+    if( iActiveConstraints & EConstraintIndividual )
+        {
+        if ( !aIndividual.Count() && !iIndividual.Count() )
+            {
+            aRejection |= EConstraintIndividual;
+            }
+        else if( !IsIndividualConstraintValid( iIndividual, aIndividual ) )
+            {
+            aRejection |= EConstraintIndividual;
+            }
+        }        
+
+    if( aRejection )
+        {
+        // drmTime is null, so some constraints may have been discarded because of that
+        if( !drmTime )
+            {
+            aRejection |= EConstraintNullDrmTime;
+            }       
+        return EFalse;        
+        }
+
+    return ETrue;		
+	};
+
+
+// -----------------------------------------------------------------------------
+// CDRMConstraint::ConstructL
+// 2nd phase constructor
+// -----------------------------------------------------------------------------
+//
+void CDRMConstraint::ConstructL()
+    {
+    };
+    
+// -----------------------------------------------------------------------------
+// CDRMConstraint::WriteInt64L
+// -----------------------------------------------------------------------------
+//
+void CDRMConstraint::WriteInt64L( const TInt64& aWrite, RWriteStream& aStream ) const
+    {
+    TPtr8 output(NULL,0,0);
+    
+    output.Set( reinterpret_cast<TUint8*>(const_cast<TInt64*>(&aWrite)), 
+                sizeof(TInt64), sizeof(TInt64) );
+    
+    aStream.WriteL( output, sizeof(TInt64) );
+    };
+
+// -----------------------------------------------------------------------------
+// CDRMConstraint::ReadInt64L
+// -----------------------------------------------------------------------------
+//
+void CDRMConstraint::ReadInt64L( TInt64& aRead, RReadStream& aStream )
+    {
+    TPtr8 input(NULL,0,0);
+    
+    input.Set( reinterpret_cast<TUint8*>(&aRead), 0, sizeof(TInt64) );
+    
+    aStream.ReadL( input, sizeof(TInt64) );    
+    };        
+// End of File