diff -r 000000000000 -r e686773b3f54 phonebookui/Phonebook2/CommonUI/src/CPbk2DrmManager.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/phonebookui/Phonebook2/CommonUI/src/CPbk2DrmManager.cpp Tue Feb 02 10:12:17 2010 +0200 @@ -0,0 +1,607 @@ +/* +* 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: +* Phonebook 2 DRM manager. +* +*/ + + +// INCLUDE FILES +#include "CPbk2DrmManager.h" + +// Phonebook 2 +#include + +// System includes +#include +#include +#include +#include +#include // RApaLsSession +#include // KCRUidMusicPlayerFeatures +#include +#include +#include + +#ifdef RD_DRM_COMMON_INTERFACE_FOR_OMA_AND_WMDRM +#include +#include +#endif + +/// Unnamed namespace for local definitions +namespace { + +_LIT(KSpaceTxt, " "); + +} /// namespace + +// -------------------------------------------------------------------------- +// CPbk2DrmManager::CPbk2DrmManager +// -------------------------------------------------------------------------- +// +CPbk2DrmManager::CPbk2DrmManager() : + iDrmEnabled( EFalse ) + { + } + +// -------------------------------------------------------------------------- +// CPbk2DrmManager::~CPbk2DrmManager +// -------------------------------------------------------------------------- +// +EXPORT_C CPbk2DrmManager::~CPbk2DrmManager() + { + if ( iDrmClient ) + { + iDrmClient->Disconnect(); + } + delete iDrmClient; + delete iDrmHelper; + delete iMusicPlayerFeatures; + + FeatureManager::UnInitializeLib(); + } + +// -------------------------------------------------------------------------- +// CPbk2DrmManager::NewL +// -------------------------------------------------------------------------- +// +EXPORT_C CPbk2DrmManager* CPbk2DrmManager::NewL() + { + CPbk2DrmManager* self = new ( ELeave ) CPbk2DrmManager; + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop( self ); + return self; + } + +// -------------------------------------------------------------------------- +// CPbk2DrmManager::ConstructL +// -------------------------------------------------------------------------- +// +void CPbk2DrmManager::ConstructL() + { + // Sets up TLS, must be done before FeatureManager is used + FeatureManager::InitializeLibL(); + + iDrmHelper = CDRMHelper::NewL(); + iDrmClient = DRMCommon::NewL(); + if ( iDrmClient->Connect() == DRMCommon::EOk ) + { + // If unable to connect, DRM protection is always on + iDrmEnabled = ETrue; + } + + iMusicPlayerFeatures = CRepository::NewLC( KCRUidMusicPlayerFeatures ); + CleanupStack::Pop(); // iMusicPlayerFeatures + } + +#ifndef RD_DRM_COMMON_INTERFACE_FOR_OMA_AND_WMDRM + +// Some magic constants +static const TInt KMinContentLength( 16 ); +_LIT8( KContentProtectionType, "DRM" ); +_LIT8( KASFHeaderObject, "75B22630668E11CFA6D900AA0062CE6C" ); + + +// ----------------------------------------------------------------------------- +// FormatGUID +// ----------------------------------------------------------------------------- +// +LOCAL_C void FormatGUID( TDes8& aGUID ) + { + TBuf8<16> copyGUID( aGUID ); + TInt i; + 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; + for( i = 7 ; i >= 0; i-- ) + { + num <<= 8; + num |= aDes[i]; + } + return num; + } + + +// ----------------------------------------------------------------------------- +// IsProtectedWmDrmL +// returns ETrue, if file is protected WMDRM file +// EFalse if file is not protected WMDRM file +// Leaves with KErrUnderflow if file has too little data to decide +// whether WmDrm or not +// may also leave with other system wide error code +// ----------------------------------------------------------------------------- +// +LOCAL_C TBool IsProtectedWmDrmL( RFile& aFileHandle ) + { + TInt r( KErrNone ); + HBufC8* buffer( NULL ); + TInt pos( 0 ); + RFile file; + TBuf8< 32 > header; + + TInt64 headerSize( 0 ); + TBool isProtectedWmDrm( EFalse ); + TPtr8 headerPtr( NULL, 0 ); + + // Leave if given handle is invalid + if( !aFileHandle.SubSessionHandle() ) + { + User::Leave( KErrBadHandle ); + } + + file.Duplicate( aFileHandle ); + CleanupClosePushL( file ); + + User::LeaveIfError( file.Seek( ESeekStart, pos ) ); + + // Check if the file is an ASF file + // TODO: Check on runtime wether WM DRM is supporeted or not + // Take Implementation from DRM::CDrmUtility::GetDrmInfoL, + // which is not yet available + + User::LeaveIfError( file.Read( 0, header, KMinContentLength ) ); + if( header.Length() < KMinContentLength ) + { + User::Leave( KErrUnderflow ); + } + + FormatGUID( header ); + + if( header == KASFHeaderObject ) + { + // It's ASF, check still whether it's WM DRM protected or not + file.Read( header,8 ); + headerSize = ConvertToInt64( header ); + if( headerSize <= 30 ) + { + User::Leave( KErrUnderflow ); + } + if ( headerSize > KMaxTInt16 ) + { + User::Leave( KErrOverflow ); + } + buffer = HBufC8::NewLC( headerSize ); + + headerPtr.Set( buffer->Des() ); + User::LeaveIfError( file.Read( headerPtr, headerSize - 24 ) ); + + r = headerPtr.Find( KContentProtectionType ); + if ( KErrNotFound != r ) + { + isProtectedWmDrm = ETrue; + } + CleanupStack::PopAndDestroy( buffer ); // buffer + } + CleanupStack::PopAndDestroy(); // file + + return isProtectedWmDrm; + } + +#endif // RD_DRM_COMMON_INTERFACE_FOR_OMA_AND_WMDRM + +// ----------------------------------------------------------------------------- +// CPbk2DrmManager::IsFileWMDRMProtectedL +// ----------------------------------------------------------------------------- +// +TBool CPbk2DrmManager::IsFileWMDRMProtectedL( const TDesC& aFileName, + TBool& aIsProtected ) const + { + TBool res = EFalse; + RFs& fsSession( CCoeEnv::Static()->FsSession() ); + RFile hFile; + + TInt err = hFile.Open( fsSession, aFileName, + EFileRead | EFileStream | EFileShareReadersOnly ); + if( err == KErrInUse ) + { + err = hFile.Open( fsSession, aFileName, + EFileRead | EFileStream | EFileShareAny ); + } + if( err != KErrNone ) + { + User::Leave( err ); + } + CleanupClosePushL( hFile ); + +#ifdef RD_DRM_COMMON_INTERFACE_FOR_OMA_AND_WMDRM + TPtrC agent( KNullDesC ); + DRM::CDrmUtility* drmUtil( DRM::CDrmUtility::NewLC() ); + drmUtil->GetAgentL( hFile, agent ); + if( agent.Compare( DRM::KDrmWMAgentName ) == 0 ) + { + res = ETrue; + } + else + { + res = iDrmClient->IsProtectedFile( aFileName, aIsProtected ); + } + CleanupStack::PopAndDestroy( drmUtil ); +#else + res = IsProtectedWmDrmL( hFile ); + aIsProtected = EFalse; +#endif + + CleanupStack::PopAndDestroy( &hFile ); + return res; + } + +// -------------------------------------------------------------------------- +// CPbk2DrmManager::IsProtectedFile +// -------------------------------------------------------------------------- +// + +EXPORT_C TInt CPbk2DrmManager::IsProtectedFile( + const TDesC& aFileName, + TBool& aIsProtected ) + { + aIsProtected = ETrue; + + const TBool drmSupported = + ( FeatureManager::FeatureSupported( KFeatureIdDrm )|| + FeatureManager::FeatureSupported( KFeatureIdDrmFull ) ); + + TInt drmErrorCode( KErrNone ); + if ( !drmSupported ) + { + // No DRM support, file retrieval always ok + aIsProtected = EFalse; + } + else if ( iDrmEnabled ) + { + // Check is the file protected + drmErrorCode = IsFileWMDRMProtectedL( aFileName,aIsProtected ); + } + return drmErrorCode; + } + +// -------------------------------------------------------------------------- +// CPbk2DrmManager::IsRingingToneForbidden +// -------------------------------------------------------------------------- +// +EXPORT_C TInt CPbk2DrmManager::IsRingingToneForbidden( + const TDesC& aFileName, + TBool& aIsProtected ) + { + aIsProtected = ETrue; + TInt error( KErrNone ); + const TBool drmSupported = + ( FeatureManager::FeatureSupported( KFeatureIdDrm ) || + FeatureManager::FeatureSupported( KFeatureIdDrmFull ) ); + + if ( !drmSupported ) + { + // No DRM support, file retrieval always ok + aIsProtected = EFalse; + } + else + { + // DRM is enabled. File must be checked + error = IsProtectedFile( aFileName, aIsProtected ); + if ( error == KErrNone ) + { + if ( aIsProtected ) + { + TRAP( error, CheckProtectedFileL( aFileName, aIsProtected ) ); + } + else + { + TRAP( error, CheckUnprotectedFileL( aFileName, aIsProtected ) ); + } + } + else + { + error = 0; + TRAP_IGNORE( ShowErrorNoteL( R_QTN_PHOB_PROTECTED_TONE ) ); + } + } + return error; + } + +// -------------------------------------------------------------------------- +// CPbk2DrmManager::IsThumbnailForbidden +// -------------------------------------------------------------------------- +// +EXPORT_C TInt CPbk2DrmManager::IsThumbnailForbidden( + const TDesC& aFileName, + TBool& aIsProtected ) + { + aIsProtected = ETrue; + TInt error = IsProtectedFile( aFileName, aIsProtected ); + + // Thumbnails with any DRM protection are not allowed + if ( error == KErrNone && aIsProtected ) + { + TRAP_IGNORE( ShowErrorNoteL( R_PBK2_QTN_DRM_NOT_ALLOWED ) ); + } + + return error; + } + +// -------------------------------------------------------------------------- +// CPbk2DrmManager::ShowErrorNoteL +// -------------------------------------------------------------------------- +// +void CPbk2DrmManager::ShowErrorNoteL( TInt aResource ) + { + CEikonEnv* env = CEikonEnv::Static(); + HBufC* noteText = StringLoader::LoadLC( aResource, env ); + + // DRM notifications are shown as waiting information notes + CAknInformationNote* note = new ( ELeave ) CAknInformationNote( ETrue ); + note->ExecuteLD( *noteText ); + + CleanupStack::PopAndDestroy( noteText ); //noteText + } + +// -------------------------------------------------------------------------- +// CPbk2DrmManager::IsDrmRequiredForPlaybackL +// -------------------------------------------------------------------------- +// +TBool CPbk2DrmManager::IsDrmRequiredForPlaybackL() + { + // It is possible to disable support for non-DRM protected rich audio + // formats + TInt value( 0 ); + User::LeaveIfError( + iMusicPlayerFeatures->Get( KRequireDRMInPlayback, value ) ); + return static_cast( value ); + } + +// -------------------------------------------------------------------------- +// CPbk2DrmManager::IsBlockedMimeTypeL +// -------------------------------------------------------------------------- +// +TBool CPbk2DrmManager::IsBlockedMimeTypeL( const TDesC& aMimeType ) + { + TBool ret = EFalse; + TBuf<1> tmp; // Magic: 1 char to get length of actual value + TInt realLen = 0; + TInt err = iMusicPlayerFeatures->Get( + KPlaybackRestrictedMimeTypes, tmp, realLen ); + if ( err == KErrOverflow ) + { + // Prepare list of blocked MIME types + HBufC* listBuf = HBufC::NewLC( realLen + KSpaceTxt().Length() ); + TPtr list = listBuf->Des(); + User::LeaveIfError( + iMusicPlayerFeatures->Get + ( KPlaybackRestrictedMimeTypes, list ) ); + list.Append( KSpaceTxt ); + + // Prepare buffer for aMimeType + HBufC* mimeBuf = HBufC::NewLC( aMimeType.Length() + + KSpaceTxt().Length() ); + TPtr mime = mimeBuf->Des(); + mime = aMimeType; + // FindF() would find "audio/3gpp" in "audio/3gpp2" without + // the added space + mime.Append( KSpaceTxt ); + + // If result is not KErrNotFound, this MIME-type is indeed blocked + ret = ( list.FindF( mime ) >= 0 ); + + CleanupStack::PopAndDestroy(2); // listBuf, mimeBuf + } + else + { + User::LeaveIfError( err ); + } + return ret; + } + +// -------------------------------------------------------------------------- +// CPbk2DrmManager::CheckProtectedFileL +// -------------------------------------------------------------------------- +// +void CPbk2DrmManager::CheckProtectedFileL( + const TDesC& aFileName, + TBool& aProtected ) + { + aProtected = ETrue; + TBool automatedOk(EFalse); + + // Check that file can be set as automated content. + TInt err = iDrmHelper->CanSetAutomated( aFileName, automatedOk ); + if ( err==KErrNone ) + { + if ( !automatedOk ) + { + ShowErrorNoteL(R_QTN_PHOB_DRM_PREV_RIGHTS_SET); + } + else + { + DRMCommon::TContentProtection protection; + HBufC8* mimeType = NULL; // ignored + HBufC8* contentUri = NULL; + TUint dataLength; // ignored + err = iDrmClient->GetFileInfo( + aFileName, protection, mimeType, contentUri, dataLength ); + delete mimeType; + mimeType = NULL; + if( err ) + { + delete contentUri; + User::Leave( err ); + } + + CDRMRights* rights = NULL; + err = iDrmClient->GetActiveRights( + *contentUri, DRMCommon::EPlay, rights ); + + switch ( err ) + { + case CDRMRights::EFullRights: // Fall through + case CDRMRights::ERestrictedRights: + { + CDRMRights::TRestriction restriction; // ignore + CDRMRights::TExpiration expiration; + TUint32 constType; + + // Ignore return value + rights->GetRightsInfo( + DRMCommon::EPlay, restriction, expiration, constType ); + + // This is CFM protected file, ringingtone is set to "no" + if ( ( rights->GetPermission().iInfoBits & ENoRingingTone ) + // This is normal DRM protected tone + || ( constType & ( CDRMRights::ECountBased | + CDRMRights::ETimeIsAccumulatedTime ) ) ) + { + ShowErrorNoteL( R_QTN_PHOB_DRM_PREV_RIGHTS_SET ); + } + else + { + switch ( expiration ) + { + case CDRMRights::EValidRights: + { + aProtected = EFalse; + break; + } + case CDRMRights::EFutureRights: + { + iDrmHelper->HandleErrorL( + DRMCommon::ENoRights, aFileName ); + break; + } + case CDRMRights::EExpiredRights: + { + iDrmHelper->HandleErrorL( + DRMCommon::ERightsExpired, aFileName ); + break; + } + default: + { + // Do nothing + break; + } + } + } + break; + } + case CDRMRights::EPreviewRights: + { + ShowErrorNoteL( R_QTN_PHOB_DRM_PREV_RIGHTS_SET ); + break; + } + case DRMCommon::ENoRights: + { + iDrmHelper->HandleErrorL( DRMCommon::ENoRights, aFileName ); + break; + } + default: + { + // Do nothing + break; + } + } + + delete rights; + delete contentUri; + } + } + else + { + // Locked file case is handled separately. + if ( err==KErrInUse ) + { + CCoeEnv::Static()->HandleError( KErrInUse ); + } + else + { + // Leave if DrmHelper not handle the error + User::LeaveIfError( iDrmHelper->HandleErrorL(err,aFileName) ); + } + } + } + +// -------------------------------------------------------------------------- +// CPbk2DrmManager::CheckUnprotectedFileL +// -------------------------------------------------------------------------- +// +void CPbk2DrmManager::CheckUnprotectedFileL( + const TDesC& aFileName, + TBool& aProtected ) + { + aProtected = ETrue; + RApaLsSession apaLs; + User::LeaveIfError( apaLs.Connect() ); + TUid appUidNotUsed = KNullUid; + TDataType dataType; + TInt err = apaLs.AppForDocument( aFileName, appUidNotUsed, dataType ); + apaLs.Close(); + User::LeaveIfError( err ); + + // Check if this unprotected MIME type should be blocked + if ( IsDrmRequiredForPlaybackL() && + IsBlockedMimeTypeL( dataType.Des() ) ) + { + ShowErrorNoteL( R_QTN_PHOB_UNPROTECTED_TONE ); + } + else + { + aProtected = EFalse; + } + } + +// End of File