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

/*
* Copyright (c) 2006-2009 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:  DRM Utility
*
*/


// INCLUDE FILES
#include <Oma2Dcf.h>
#include <drmagents.h>
#include <drmutility.h>
#include <centralrepository.h>
#include <UTF.h>

#include "Oma1Dcf.h"

#include "DrmUtilityInternalcrkeys.h"      // Cenrep extension for OmaBased

// CONSTANTS
_LIT8( KASFHeaderObject, "75B22630668E11CFA6D900AA0062CE6C" );
_LIT8( KWrmHeader, "W\0R\0M\0H\0E\0A\0D\0E\0R\0" );

const TInt KMinContentLength( 16 );
const TInt KOma2EncryptionFieldOffset( 8 );
const TInt KOmaHeaderLength( 512 );
// This constant is for OMA1 case in which a buffer of 35-40
// bytes is needed to recognize the mime type.
const TInt KMinContentLengthOma1Based( 40 );
const TInt KWMHeaderObjectLength( 8 );
const TInt KWMTopLevelHeaderObjectLength( 30 );
const TInt KMaxWMHeaderLength( ( KMaxTInt32 / 2 ) - 1 );

const TInt KCenRepDataLength( 50 );

// ============================ LOCAL FUNCTIONS ================================

// -----------------------------------------------------------------------------
// FormatGUID
// -----------------------------------------------------------------------------
//
LOCAL_C void FormatGUID( TDes8 &aGUID )
    {
    TBuf8<16> copyGUID( aGUID );
    TInt i( 0 );
    for ( i = 0; i < 4; i++ )
        {
        copyGUID[i] = aGUID[3-i];
        }
    for ( i = 4; i < 6; i++ )
        {
        copyGUID[i] = aGUID[9 - i];
        }
    for ( i = 6; i < 8; i++ )
        {
        copyGUID[i] = aGUID[13 - i];
        }
    for ( i = 8; i < 16 ; i++) 
        {
        copyGUID[i] = aGUID[i];
        }
    aGUID.Delete( 0, 32 );
    for ( i = 0; i < 16; i++ )
        {
        aGUID.AppendNumFixedWidthUC( copyGUID[i], EHex, 2 );
        }
    }

// -----------------------------------------------------------------------------
// ConvertToInt64
// -----------------------------------------------------------------------------
//
LOCAL_C TInt64 ConvertToInt64( TDesC8& aDes )
    {
    TInt64 num( 0 );
    TInt i( 0 );
    for ( i = 7 ; i >= 0; i-- )
        {
        num <<= 8;
        num |= aDes[i];
        }
    return num;
    }

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

// -----------------------------------------------------------------------------
// Default constructor
// -----------------------------------------------------------------------------
//  
DRM::CDrmUtility::CDrmUtility()
    {
    }
    
// -----------------------------------------------------------------------------
// Destructor
// -----------------------------------------------------------------------------
//  
DRM::CDrmUtility::~CDrmUtility()
    {
    delete iOmaBasedAgentName;
    delete iOmaBasedMimeType;
    }
    
// -----------------------------------------------------------------------------
// CDrmUtility::NewLC
// First phase constructor
// -----------------------------------------------------------------------------
//  
EXPORT_C DRM::CDrmUtility* DRM::CDrmUtility::NewLC()
    {
    DRM::CDrmUtility* self( new( ELeave ) CDrmUtility );
    CleanupStack::PushL( self );
    self->ConstructL();
    return self;
    }

// -----------------------------------------------------------------------------
// CDrmUtility::NewL
// First phase constructor
// -----------------------------------------------------------------------------
//  
EXPORT_C DRM::CDrmUtility* DRM::CDrmUtility::NewL()
    {
    DRM::CDrmUtility* self( NewLC() );
    CleanupStack::Pop();
    return self;
    }

void DRM::CDrmUtility::ConstructL()
    {
    TInt err( KErrNone );
             
     TRAP(err, FetchOmaBasedInfoL() );
     if( err)
         {
         if( iOmaBasedAgentName )
             {
             delete iOmaBasedAgentName;
             }
         iOmaBasedAgentName = NULL;
         if( iOmaBasedMimeType )
             {
             delete iOmaBasedMimeType;
             }
         iOmaBasedMimeType = NULL;
         }   
    }

// -----------------------------------------------------------------------------
// CDrmUtility::FetchOmaBasedInfoL
// -----------------------------------------------------------------------------
//
void DRM::CDrmUtility::FetchOmaBasedInfoL()
    {
    TInt err = KErrNone;
    CRepository* repository( NULL );
    RBuf bOmaBasedAgentName;
    RBuf bOmaBasedMimeType;
    
    CleanupClosePushL(bOmaBasedAgentName);
    CleanupClosePushL(bOmaBasedMimeType);
    bOmaBasedAgentName.CreateL( KCenRepDataLength );
    bOmaBasedMimeType.CreateL( KCenRepDataLength );
 
    TRAP( err, repository = CRepository::NewL( KCRUidOmaBased ) );
    if ( !err )
        {
        CleanupStack::PushL( repository );
        
        err = repository->Get( KDrmOmaBasedName, bOmaBasedAgentName );
        if( !err )
            {
            iOmaBasedAgentName = bOmaBasedAgentName.AllocL(); 
            }
        
        err = repository->Get( KOmaBasedMimeType, bOmaBasedMimeType );
        if( !err )
            {
            iOmaBasedMimeType = CnvUtfConverter::ConvertFromUnicodeToUtf8L( bOmaBasedMimeType );
            }
        CleanupStack::PopAndDestroy( repository );
        }
    
    CleanupStack::PopAndDestroy(2);
    
    User::LeaveIfError( err );
    }


// -----------------------------------------------------------------------------
// CDrmUtility::GetDrmInfoL
// -----------------------------------------------------------------------------
//  
EXPORT_C TBool DRM::CDrmUtility::GetDrmInfoL( 
    RFile& aFileHandle,
    TPtrC& aAgent,
    DRM::TDrmProtectionStatus& aProtected ) const
    {
    TInt r( KErrNone );
    HBufC8* buffer( NULL );
    TInt pos( 0 );
    RFile file;
    TBuf8< 32 > header;
    TInt64 headerSize( 0 );
    TBool isDrmFile( EFalse );
    TPtr8 headerPtr( NULL, 0 );
        
    aProtected = DRM::EUUnprotected;
    aAgent.Set( KNullDesC );
    
    CheckFileHandleL( aFileHandle );
    User::LeaveIfError( file.Duplicate( aFileHandle ) );
    CleanupClosePushL( file );

    User::LeaveIfError( file.Seek( ESeekStart, pos ) );
    
    // Check if the file is an ASF file
    // To be Checked on runtime wether WM DRM is supporeted or not
    User::LeaveIfError( file.Read( 0, header, KMinContentLength ) );
    if ( header.Length() < KMinContentLength )
        {
        User::Leave( KErrArgument ); 
        }    
        
    FormatGUID( header );
    
    if ( header == KASFHeaderObject )
        {
        // It's ASF, check still whether it's WM DRM protected or not
        file.Read( header, KWMHeaderObjectLength );
        headerSize = ConvertToInt64( header );
        if( headerSize <= KWMTopLevelHeaderObjectLength || 
            headerSize > KMaxWMHeaderLength )
            {
            User::Leave( KErrArgument );
            }
        buffer = HBufC8::NewLC( headerSize );

        headerPtr.Set( buffer->Des() ); 
        User::LeaveIfError( file.Read( headerPtr, 
                headerSize - ( KMinContentLength + KWMHeaderObjectLength ) ) );
    
        r = headerPtr.Find( KWrmHeader );
        if ( r == KErrNotFound ) 
            {
            aProtected = DRM::EUUnprotected;
            }
        else
            {
            isDrmFile = ETrue;
            aProtected = DRM::EUProtected;
            aAgent.Set( DRM::KDrmWMAgentName );                            
            }
        CleanupStack::PopAndDestroy( buffer ); // buffer    
        }
    else
        {
        // Check whether it's OMA DRM protected or not
        buffer = HBufC8::NewLC( KOmaHeaderLength );
        
        headerPtr.Set( buffer->Des() );
        User::LeaveIfError( file.Read( 0, headerPtr ));
        
        if ( COma1Dcf::IsValidDcf( headerPtr ) )
            {
            isDrmFile = ETrue;
            aProtected = DRM::EUProtected;                             
            aAgent.Set( DRM::KDrmOmaAgentName );                
            }
        else if ( COma2Dcf::IsValidDcf( headerPtr ) )
            {
            isDrmFile = ETrue;
            _LIT8( KCommonHeadersBox, "ohdr" );
            pos = headerPtr.Find( KCommonHeadersBox );
            
            // If no box can be found or if there isn't enough data
            // set protection as unknown
            if( pos == KErrNotFound || 
                headerPtr.Length() < pos + KOma2EncryptionFieldOffset )
                {
                aProtected = DRM::EUUnknown;
                }
            // If encryption field is 0, then content isn't protected
            else if ( !headerPtr[pos + KOma2EncryptionFieldOffset] )
                {
                aProtected = DRM::EUUnprotected;
                }
            else
                {
                aProtected = DRM::EUProtected;
                }                  
            aAgent.Set( DRM::KDrmOmaAgentName );                
            }   
        else if ( (buffer->Des())[0] == 1)
            {
            // set the mimetype from the buffer which is in the beginning
            // starting from byte 3 with the length specified at position 2		
            TPtrC8 mimeType( buffer->Des().Mid(3, (buffer->Des())[1]) );
            if( !mimeType.CompareF( *iOmaBasedMimeType ) ) 
                {	
                aAgent.Set( *DRM::CDrmUtility::iOmaBasedAgentName );
                isDrmFile = ETrue;
                }
            }
        CleanupStack::PopAndDestroy( buffer );
        }  
    CleanupStack::PopAndDestroy( &file ); // file
    return isDrmFile;
    }  
  
// -----------------------------------------------------------------------------
// CDrmUtility::GetDrmInfoL
// -----------------------------------------------------------------------------
//  
EXPORT_C TBool DRM::CDrmUtility::GetDrmInfoL( 
    const TDesC8& aContent,
    TPtrC& aAgent,
    DRM::TDrmProtectionStatus& aProtected ) const
    {
    TInt r( KErrNone );
    RFile file;
    TPtr8 asfPtr( NULL, 0 );
    TBuf8< 32 > asfGuidHex;
    TBool isDrmFile( EFalse );
    
    aProtected = DRM::EUUnprotected;
    aAgent.Set( KNullDesC );

    if ( aContent.Length() < KMinContentLength )
        {
        User::Leave( KErrArgument );   
        }
        
    // Check if the file is an ASF file
    asfPtr.Set( 
        const_cast<TUint8*>( asfGuidHex.Ptr() ), 0, KMinContentLength * 2 );
    asfPtr.Copy( aContent.Left( KMinContentLength ) );    
    FormatGUID( asfPtr );
    
    if ( asfPtr == KASFHeaderObject )
        {
        // It's ASF, check still whether it's WM DRM protected or not
        r = aContent.Find( KWrmHeader );
        if ( r == KErrNotFound ) 
            {
            aProtected = DRM::EUUnprotected;   
            }
        else
            {
            isDrmFile = ETrue;
            aProtected = DRM::EUProtected;                               
            aAgent.Set( DRM::KDrmWMAgentName ); 
            }   
        }
    else
        {
        // Check whether it's OMA DRM protected or not.
        if ( ( aContent.Length() >= KMinContentLengthOma1Based ) && 
            ( COma1Dcf::IsValidDcf( aContent ) ) )
            {
            isDrmFile = ETrue;
            aProtected = DRM::EUProtected;                          
            aAgent.Set( DRM::KDrmOmaAgentName );
            }
        else if ( COma2Dcf::IsValidDcf( aContent ) )
            {
            isDrmFile = ETrue;
            _LIT8( KCommonHeadersBox, "ohdr" );
            TInt pos( aContent.Find( KCommonHeadersBox ) );
            
            // If no box can be found or if there isn't enough data
            // set protection as unknown
            if ( pos == KErrNotFound || 
                 aContent.Length() < pos + KOma2EncryptionFieldOffset )
                {
                aProtected = DRM::EUUnknown;
                }
            // If encryption field is 0, then content isn't protected    
            else if ( !aContent[pos + KOma2EncryptionFieldOffset] )
                {
                aProtected = DRM::EUUnprotected;    
                }
            else
                {
                aProtected = DRM::EUProtected;    
                }                               
            aAgent.Set( DRM::KDrmOmaAgentName );            
            }
        else if ( (aContent)[0] == 1)
            {
            // set the mimetype from the buffer which is in the beginning
            // starting from byte 3 with the length specified at position 2     
            TPtrC8 mimeType( aContent.Mid(3, (aContent)[1]) );
            if( !mimeType.CompareF( *iOmaBasedMimeType ) )
                {   
                aAgent.Set( *DRM::CDrmUtility::iOmaBasedAgentName );
                isDrmFile = ETrue;
                aProtected = DRM::EUProtected;
                }
            }
        }
    return isDrmFile;
    }      

// -----------------------------------------------------------------------------
// CDrmUtility::IsProtectedL
// -----------------------------------------------------------------------------
//  
EXPORT_C TBool DRM::CDrmUtility::IsProtectedL( RFile& aFileHandle ) const
    {
    DRM::TDrmProtectionStatus protection( DRM::EUUnknown );
    TPtrC agent( KNullDesC );
    TBool isDrmFile( EFalse );
    TBool isProtected( EFalse );
    
    isDrmFile = GetDrmInfoL( aFileHandle, agent, protection );
    
    if ( isDrmFile && protection == DRM::EUProtected )
        {
        isProtected = ETrue;
        }
    return isProtected;
    }

    
// -----------------------------------------------------------------------------
// CDrmUtility::IsProtectedL
// -----------------------------------------------------------------------------
//  
EXPORT_C TBool DRM::CDrmUtility::IsProtectedL( const TDesC8& aContent ) const
    {
    DRM::TDrmProtectionStatus protection( DRM::EUUnknown );
    TPtrC agent( KNullDesC );
    TBool isDrmFile( EFalse );
    TBool isProtected( EFalse );
    
    isDrmFile = GetDrmInfoL( aContent, agent, protection );
    
    if( isDrmFile && protection == DRM::EUProtected )
        {
        isProtected = ETrue;
        }
    return isProtected;
    }


// -----------------------------------------------------------------------------
// CDrmUtility::GetAgentL
// -----------------------------------------------------------------------------
//  
EXPORT_C TBool DRM::CDrmUtility::GetAgentL( 
    RFile& aFileHandle,
    TPtrC& aAgent ) const
    {
    DRM::TDrmProtectionStatus protection( DRM::EUUnknown );
    TBool isDrmFile( EFalse );

    isDrmFile = GetDrmInfoL( aFileHandle, aAgent, protection );

    return isDrmFile;
    }
    
// -----------------------------------------------------------------------------
// CDrmUtility::GetAgentL
// -----------------------------------------------------------------------------
//  
EXPORT_C TBool DRM::CDrmUtility::GetAgentL( 
    const TDesC8& aContent,
    TPtrC& aAgent ) const
    {
    DRM::TDrmProtectionStatus protection( DRM::EUUnknown );
    TBool isDrmFile( EFalse );

    isDrmFile = GetDrmInfoL( aContent, aAgent, protection );

    return isDrmFile;
    }
 	

// -----------------------------------------------------------------------------
// CDrmUtility::CheckFileHandlerL
// Checks whether given filehandle is valid if not leaves with KErrArgument
// (other items were commented in a header).
// -----------------------------------------------------------------------------
// 
EXPORT_C void DRM::CDrmUtility::CheckFileHandleL( RFile& aFileHandle ) const
    {
    if ( !aFileHandle.SubSessionHandle() )
        {
        User::Leave( KErrBadHandle );
        }
    }
       
//  End of File