commondrm/drmutility/src/drmutilitywmdrmutilities.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Thu, 17 Dec 2009 08:52:27 +0200
changeset 0 95b198f216e5
child 18 8a03a285ab14
permissions -rw-r--r--
Revision: 200949 Kit: 200951

/*
* Copyright (c) 2008 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:  WM DRM specific methods for DRM Rights Manager
*
*/


#include <e32std.h>
#include <DRMRights.h>

#include "drmclockclient.h"
#include "drmutilitywmdrmutilities.h"
#include "drmrights.h"

// CONSTANTS
_LIT( KLicenseType, "licensetype=" );
_LIT( KTime, "time" );
_LIT( KCount, "count" );
_LIT( KDuration, "duration" );
_LIT( KTimeCount, "time-count" );
_LIT( KUnlimited, "unlimited" );

_LIT( KDurationLeft, "duration=" );
_LIT( KCountLeft, "countleft=" );
_LIT( KStartTime, "starttime=" );
_LIT( KEndTime, "endtime=" );

const TUint8 KFoundStartTime = 0x01;
const TUint8 KFoundEndTime = 0x02;

// masks for constraint existence
const TInt KWmDrmConstraintCount( 1 );
const TInt KWmDrmConstraintStartTime ( 2 );
const TInt KWmDrmConstraintEndTime( 4 );
const TInt KWmDrmConstraintDuration( 8 );

#ifdef _DEBUG
// debug panic
_LIT( KWmDrmUtilitiesDebugPanicMessage, "WmDrmUtilitiesDebugPanic" );
const TInt KWmDrmUtilitiesDebugPanicCode( 2 );
#endif

// LOCAL FUNCTION PROTOTYPES
// Parses the given lexicographic representation. Return value indicates
// whether the given end character of the searched substring was found or not.
// Special handling is applied for certain separators (e.g. ';', '-')
LOCAL_C TBool ParseString( TChar aChar, TLex& aLex, TPtrC16& aPtr );

// ================= MEMBER FUNCTIONS =======================

LOCAL_C TBool ParseString( TChar aChar, TLex& aLex, TPtrC16& aPtr )
    {
    TBool found( EFalse );
    aLex.Mark();
    
    while ( !aLex.Eos() && found == EFalse )
        {
        TChar ch;
        ch = aLex.Get();
        if ( ch == aChar )
            {
            if ( ch == ';' || ch == '-' || ch == ':' || ch == 'T' || ch == 'Z' )
                {
                // Remove char from the token string and read it from the lex.
                aLex.UnGet();
                aPtr.Set( aLex.MarkedToken() );
                aLex.Get();
                }
            else 
                {
                aPtr.Set( aLex.MarkedToken() );
                }
            found = ETrue;
            }
        }
    return found;
    }

// ----------------------------------------------------------------------------
// DrmUtilityWmDrmUtilities::ParseWmDrmTimeRightsL
// ----------------------------------------------------------------------------
EXPORT_C void DrmUtilityWmDrmUtilities::ParseWmDrmTimeRightsL( TLex& aLex,
    TTime& aStartTime, TTime& aEndTime )
    {
    TPtrC16 token( NULL, 0 );
    TUint8 times( 0 );
    TTime localTime( Time::NullTTime() );
    TTime universalTime( Time::NullTTime() );
    TTimeIntervalSeconds timeDifference( 0 ); // local time - secure time
    TInt years, months, days, hours, minutes, secs; 
    TChar ch;
    TLex lex;
    TTime drmTime;
    TInt timeZone;
    
    DRMClock::ESecurityLevel secLevel = DRMClock::KInsecure;
    
    // The format of the start and end time strings is the following:
    // "starttime=yy-mm-ddThh:mins:ssZ
    // "endtime=yy-mm-ddThh:mins:ssZ
    // where yy = years, mm = months, dd = days, hh = hours, 
    // mins = minutes and ss = seconds, "-", "T", ":" and "Z" 
    // are separators.     
    while ( !aLex.Eos() && ( aLex.Peek() != 0 ) )
        {
        // The next string should be start time, end time or then
        // it does not exist.
        ParseString( '=', aLex, token );
        
        if ( token.CompareF( KStartTime ) == 0 )
            {
            times |= KFoundStartTime;
            } 
        else if ( token.CompareF( KEndTime ) == 0 )
            {
            times |= KFoundEndTime;
            }
        else 
            {
            // No start time ("starttime=") or end time ("endtime=")  
            // string was found -> return   
            return;
            }
               
        if ( ( times & KFoundStartTime ) || ( times & KFoundEndTime ) )
            {     
            // Search for years, months, days, hours, minutes, secs     
            if ( ParseString( '-', aLex, token ) )
                {
                TLex lexYear( token );
                User::LeaveIfError( lexYear.Val( years ) );
                }
            else 
                {
                User::Leave( KErrNotFound );    
                }
            
            if ( ParseString( '-', aLex, token ) )
                {
                TLex lexMonths( token );
                User::LeaveIfError( lexMonths.Val( months ) );
                }
            else 
                {
                User::Leave( KErrNotFound );    
                }
            
            if ( ParseString( 'T', aLex, token ) )
                {
                TLex lexDays( token );
                User::LeaveIfError( lexDays.Val( days ) );
                }
            else 
                {
                User::Leave( KErrNotFound );    
                }
            
            if( ParseString( ':', aLex, token ) )
                {
                TLex lexHours( token );
                User::LeaveIfError( lexHours.Val( hours ) );
                }
            else 
                {
                User::Leave( KErrNotFound );
                }
            
            if ( ParseString( ':', aLex, token ) )
                {
                TLex lexMinutes( token );
                User::LeaveIfError( lexMinutes.Val( minutes ) );
                }
            else 
                {
                User::Leave( KErrNotFound );
                }
            
            if( ParseString( 'Z', aLex, token ) )
                {
                TLex lexSeconds( token );
                User::LeaveIfError( lexSeconds.Val( secs ) );
                }
            else 
                {
                User::Leave( KErrNotFound );
                }    
            
            ParseString( ';', aLex, token );
            token.Set( NULL, 0 );
            
            TDateTime date( years, (TMonth)( months - 1 ), days - 1, hours, 
                minutes, secs, 0 );
            TTime dateTime( date );
            
            // Get secure time from DRM clock 
            RDRMClockClient client;
            
            User::LeaveIfError( client.Connect() );
            client.GetSecureTime( drmTime, timeZone, secLevel );
            client.Close();
            
			localTime.HomeTime();
			        	
          	if ( secLevel == DRMClock::KSecure ) 
          		{
				// Calculate the difference between local time and secure time
            	localTime.SecondsFrom( drmTime, timeDifference );
            	}
			else 
				{
				// Calculate the difference between local and universal time	
				universalTime.UniversalTime();	
				localTime.SecondsFrom( universalTime, timeDifference ); 	
				}
          	
			dateTime += timeDifference;
			               
            if ( times & KFoundStartTime )
                {
                aStartTime = dateTime;
                times &= ~KFoundStartTime;
                }
            else if ( times & KFoundEndTime )
                {
                aEndTime = dateTime;
                times &= ~KFoundEndTime;
                }
            }
        }
    }

// ----------------------------------------------------------------------------
// DrmUtilityWmDrmUtilities::ParseWmDrmCountRightsL
// ----------------------------------------------------------------------------
//
EXPORT_C TBool DrmUtilityWmDrmUtilities::ParseWmDrmCountRightsL( TLex& aLex,
    TUint32& aCounts )
    {
    TPtrC16 token( NULL, 0 );
    TInt counts( 0 ); 
    TChar ch;
    TLex lex;
        
    ParseString( '=', aLex, token );
        
    if ( token.CompareF( KCountLeft ) == 0 )
        {
        ParseString( ';', aLex, token );
        TLex lexCount( token );
        User::LeaveIfError( lexCount.Val( counts ) );
        aCounts = counts;
        return ETrue;
        }    
    else 
        {
        // No counts left ("countleft=") string was found.
        // -> No count information was found, return EFalse
        return EFalse;
        }
    }

// ----------------------------------------------------------------------------
// DrmUtilityWmDrmUtilities::ParseWmDrmDurationRightsL
// ----------------------------------------------------------------------------
//
EXPORT_C TBool DrmUtilityWmDrmUtilities::ParseWmDrmDurationRightsL( TLex& aLex, 
    TTimeIntervalSeconds& aDuration )
    {
    TPtrC16 token( NULL, 0 );
    TChar ch;
    TInt duration( 0 );
        
    ParseString( '=', aLex, token );
        
    if ( token.CompareF( KDurationLeft ) == 0 )
        {
        ParseString( ';', aLex, token );
        TLex lexDuration( token );
        User::LeaveIfError( lexDuration.Val( duration ) );
        aDuration = duration;
        return ETrue;
        }
    else 
        {
        // No duration left ("durationleft=") string was found.
        // -> No duration information was found, return EFalse
        return EFalse;
        }         
    }

// ----------------------------------------------------------------------------
// DrmUtilityWmDrmUtilities::ParseWmDrmStringL
// ----------------------------------------------------------------------------
//
EXPORT_C void DrmUtilityWmDrmUtilities::ParseWmDrmStringL(
    ContentAccess::CRightsInfo& aRights,
    CDRMRightsConstraints*& aRightsConstraint )
    {
    
    __ASSERT_DEBUG( !aRightsConstraint, 
                    User::Panic( KWmDrmUtilitiesDebugPanicMessage,
                                 KWmDrmUtilitiesDebugPanicCode ) );
       
    TChar ch;
    TTime startTime( Time::NullTTime() );
    TTime endTime( Time::NullTTime() );
    TTimeIntervalSeconds duration( 0 );
    TUint32 counter( 0 );
    
    TPtrC16 token( NULL, 0 );
    
    // Parse the WM DRM rights string
    TLex lex( aRights.Description() );
    
    // First, find the license type format string ("licensetype=") 
    ParseString( '=', lex, token );
    
    if ( token.CompareF( KLicenseType ) != 0 )
        {
        // License type format string was not found  
        User::Leave( KErrArgument );
        }
 
    // Peek for the end of string (eos) in case of (licensetype="") 
    ch = lex.Peek();
    if ( ch == 0 ) 
        {
        return;
        }
    
    // Check the license type
    ParseString( ';', lex, token );
    
    aRightsConstraint = CDRMRightsConstraints::NewL();
    CleanupStack::PushL( aRightsConstraint );
    
    // Check what kind of rights are in question by parsing the string
    // onward. The possible rights are date time (start time and/or end time),
    // count, duration, time count (count and/or date time) and unlimited
    // rights. The substrings for certain rights are further parsed in
    // specific methods. 
    if ( token.CompareF( KTime ) == 0 )
        {
        ParseWmDrmTimeRightsL( lex, startTime, endTime );
        if ( Time::NullTTime() != startTime )
            {
            aRightsConstraint->SetStartTime( startTime );
            }
        if ( Time::NullTTime() != endTime )
            {
            aRightsConstraint->SetEndTime( endTime );
            }
        }
    else if ( token.CompareF( KCount ) == 0 )
        {
        if ( ParseWmDrmCountRightsL( lex, counter ) )
            {
            aRightsConstraint->SetCounters( counter, counter );
            }
        }
    else if ( token.CompareF( KDuration ) == 0 )
        {
        if ( ParseWmDrmDurationRightsL( lex, duration ) )
            {
            aRightsConstraint->SetInterval( duration );
            }
        }
    else if ( token.CompareF( KTimeCount ) == 0 )
        {
        counter = 0;
        if ( ParseWmDrmCountRightsL( lex, counter ) )
            {
            aRightsConstraint->SetCounters( counter, counter );
            }
        ParseWmDrmTimeRightsL( lex, startTime, endTime );
        if ( Time::NullTTime() != startTime )
            {
            aRightsConstraint->SetStartTime( startTime );
            }
        if ( Time::NullTTime() != endTime )
            {
            aRightsConstraint->SetEndTime( endTime );
            }
        }
    else if ( token.CompareF( KUnlimited ) != 0 )
        {
        // Unknown license type  
        User::Leave( KErrArgument );
        }
          
    CleanupStack::Pop( aRightsConstraint );
        
    }

// -----------------------------------------------------------------------------
// DrmUtilityWmDrmUtilities::CheckWmDrmRightsL
// -----------------------------------------------------------------------------
//
EXPORT_C void DrmUtilityWmDrmUtilities::CheckWmDrmRightsL( TBool& aUnconstrained, 
    TTimeIntervalSeconds& aTime,
    TInt& aCounts,  
    ContentAccess::CRightsInfo& aRights )
    {
    
    TChar ch;
    TPtrC16 token( NULL, 0 );
    TInt constraints( 0 );
    TInt error( KErrNone );
    TTime startTime( Time::NullTTime() );
    TTime endTime( Time::NullTTime() );
    TUint32 counter( 0 );
    TTime now( Time::NullTTime() ); // current time
    // End time of rights when duration is taken into account.
    TTime durationEndTime( Time::NullTTime() );
    TTimeIntervalSeconds secondsLeft( 0 ); // seconds to end of time based rights
    
    // Parse WM DRM rights string  
    TLex lex( aRights.Description() );
    
    // First, find the license type format string ("licensetype=") 
    ParseString( '=', lex, token );
    
    if ( token.CompareF( KLicenseType ) != 0 )
        {
        // License type format string was not found  
        User::Leave( KErrArgument );
        }
    
    // Peek for the end of string (Eos) in case of (licensetype="") 
    ch = lex.Peek();
    if ( ch == 0 ) 
        {
        return;
        }
    
    // Check the license type
    ParseString( ';', lex, token );
    
    // Check what kind of rights are in question by parsing the string
    // onward. The possible rights are date time (start time and/or end time),
    // count, duration, time count (count and/or date time) and unlimited
    // rights. The substrings for certain rights are further parsed in
    // specific methods. 
    if ( token.CompareF( KTime ) == 0 )
        {
        ParseWmDrmTimeRightsL( lex, startTime, endTime );
        if ( Time::NullTTime() != startTime )
            {
            constraints |= KWmDrmConstraintStartTime;
            }
        if ( Time::NullTTime() != endTime )
            {
            constraints |= KWmDrmConstraintEndTime;
            }
        }
    else if ( token.CompareF( KCount ) == 0 )
        {
        if ( ParseWmDrmCountRightsL( lex, counter ) )
            {
            aCounts = counter;
            constraints |= KWmDrmConstraintCount;
            }    
        }
    else if ( token.CompareF( KDuration ) == 0 )
        {
        if ( ParseWmDrmDurationRightsL( lex, aTime ) )
            {
            if ( aTime < (TTimeIntervalSeconds)0 )
                {
                aTime = 0;
                }
            constraints |= KWmDrmConstraintDuration;
            }
        }
    else if ( token.CompareF( KTimeCount ) == 0 )
        {
        if ( ParseWmDrmCountRightsL( lex, counter ) )
            {
            aCounts = counter;
            constraints |= KWmDrmConstraintCount;
            }
        ParseWmDrmTimeRightsL( lex, startTime, endTime );
        if ( Time::NullTTime() != startTime )
            {
            constraints |= KWmDrmConstraintStartTime;
            }
        if ( Time::NullTTime() != endTime )
            {
            constraints |= KWmDrmConstraintEndTime;
            }
        }        
    else if ( token.CompareF( KUnlimited ) == 0 ) 
        {
        aUnconstrained = ETrue;
        return;
        }
    else 
        {
        // Unknown license type
        User::Leave( KErrArgument );
        }
    
    // Get current time
    now.HomeTime();
        
    // The rights are not constrained
    if ( !constraints )
        {
        aUnconstrained = ETrue;
        }
    
    if ( constraints & KWmDrmConstraintStartTime )
        {
        // The start time is in the past or the current time
        if ( ( now >= startTime ) && 
            !( constraints & KWmDrmConstraintEndTime ) &&
            !( constraints & KWmDrmConstraintCount ) )
            {
            aUnconstrained = ETrue;
            }
        
        // This use case is unclear and should be specified later.
        // There are counts for the content, but the start time has
        // not been reached.    
        if ( ( constraints & KWmDrmConstraintCount ) &&
            ( now < startTime ) ) 
            {
            aCounts = 0;
            }               
        }
    
    // Find out the amount of time that the rights have left in
    // case the rights have end time constraint.
    if ( constraints & KWmDrmConstraintEndTime )
        {
        error = endTime.SecondsFrom( now, secondsLeft );
        
        // The difference between current time and the end time does not
        // fit to 32-bit number, the start time has been reached and there
        // are no count constraints defined.
        if ( ( error == KErrOverflow ) && 
            ( !( constraints & KWmDrmConstraintStartTime ) || 
            ( now >= startTime ) ) && !( constraints & KWmDrmConstraintCount ) )
            {
            aUnconstrained = ETrue;
            }
        
        // End time has not been reached and start time has been reached
        if ( ( secondsLeft > (TTimeIntervalSeconds)0 ) && ( now >= startTime ) )
            {
            aTime = secondsLeft;
            }
       
        // This use case is unclear and should be specified later.
        // There are counts for the content, but the end time has
        // been reached.
        if ( ( constraints & KWmDrmConstraintCount ) &&
            ( now > endTime ) )
            {
            aCounts = 0;
            }
        }
        
    return;
    
    }
    
// End of File