diff -r 000000000000 -r 95b198f216e5 commondrm/drmutility/src/DrmUtility.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/commondrm/drmutility/src/DrmUtility.cpp Thu Dec 17 08:52:27 2009 +0200 @@ -0,0 +1,505 @@ +/* +* 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 +#include +#include +#include +#include + +#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( 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