diff -r 000000000000 -r a2952bb97e68 mmappcomponents/mmmtpdataprovider/mmmtpdprequestprocessor/src/crequestchecker.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mmappcomponents/mmmtpdataprovider/mmmtpdprequestprocessor/src/crequestchecker.cpp Thu Dec 17 08:55:47 2009 +0200 @@ -0,0 +1,429 @@ +/* +* Copyright (c) 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: +* +*/ + + +#include +#include +#include +#include +#include + +#include "crequestchecker.h" +#include "mmmtpdplogger.h" + +static const TInt KMTPRequestCheckerHandleGranularity = 2; + +// ----------------------------------------------------------------------------- +// CRequestChecker::NewL +// Two-phase construction method +// ----------------------------------------------------------------------------- +// +CRequestChecker* CRequestChecker::NewL( MMTPDataProviderFramework& aFramework, + MMTPConnection& aConnection ) + { + CRequestChecker* self = new (ELeave) CRequestChecker( aFramework, aConnection ); + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop( self ); + return self; + } + +// ----------------------------------------------------------------------------- +// CRequestChecker::CRequestChecker +// Standard c++ constructor +// ----------------------------------------------------------------------------- +// +CRequestChecker::CRequestChecker( MMTPDataProviderFramework& aFramework, + MMTPConnection& aConnection ) : + iFramework( aFramework ), + iConnection( aConnection ), + iHandles( KMTPRequestCheckerHandleGranularity ), + iObjectArray( KMTPRequestCheckerHandleGranularity ) + { + + } + +// ----------------------------------------------------------------------------- +// CRequestChecker::ConstructL +// Two-phase construction method +// ----------------------------------------------------------------------------- +// +void CRequestChecker::ConstructL() + { + + } + +// ----------------------------------------------------------------------------- +// CRequestChecker::~CRequestChecker +// Destructor +// ----------------------------------------------------------------------------- +// +CRequestChecker::~CRequestChecker() + { + iHandles.Close(); + iObjectArray.ResetAndDestroy(); + } + +// ----------------------------------------------------------------------------- +// CRequestChecker::VerifyRequestL +// Verfiy the request +// ----------------------------------------------------------------------------- +// +TMTPResponseCode CRequestChecker::VerifyRequestL( const TMTPTypeRequest& aRequest, + TInt aCount, + const TMTPRequestElementInfo* aElementInfo ) + { + TMTPResponseCode result = EMTPRespCodeOK; + iHandles.Close(); + iObjectArray.ResetAndDestroy(); + + result = CheckRequestHeader( aRequest ); + + for ( TInt i = 0; i < aCount && EMTPRespCodeOK == result; i++ ) + { + TUint32 parameter = aRequest.Uint32( aElementInfo[i].iElementIndex ); + PRINT3( _L( "MM MTP <> CRequestChecker parameter %d/%d = %d" ), + i + 1, aCount, parameter ); + + if ( !IsSpecialValue( parameter, aElementInfo[i] ) ) + { + switch ( aElementInfo[i].iElementType ) + { + case EMTPElementTypeSessionID: + result = VerifySessionId( parameter, aElementInfo[i] ); + break; + + case EMTPElementTypeObjectHandle: + result = VerifyObjectHandleL( parameter, aElementInfo[i] ); + break; + + case EMTPElementTypeStorageId: + result = VerifyStorageIdL( parameter, aElementInfo[i] ); + break; + + case EMTPElementTypeFormatCode: + result = VerifyFormatCode( parameter, aElementInfo[i] ); + break; + + default: + User::Invariant(); // Should never run + break; + } + } + } + + return result; + } + +// ----------------------------------------------------------------------------- +// CRequestChecker::GetObjectInfo +// Return the object info for the handle +// ----------------------------------------------------------------------------- +// +CMTPObjectMetaData* CRequestChecker::GetObjectInfo( TUint32 aHandle ) const + { + CMTPObjectMetaData* result = NULL; + TInt count = iHandles.Count(); + for( TInt i = 0; i < count; i++ ) + { + if ( iHandles[i] == aHandle ) + { + result = iObjectArray[i]; + break; + } + } + return result; + } + +// ----------------------------------------------------------------------------- +// CRequestChecker::CheckRequestHeader +// Check the request header portion (session Id and transaction code) +// ----------------------------------------------------------------------------- +// +TMTPResponseCode CRequestChecker::CheckRequestHeader( const TMTPTypeRequest& aRequest ) const + { + TMTPResponseCode ret = EMTPRespCodeOK; + TUint16 operationCode = aRequest.Uint16( TMTPTypeRequest::ERequestOperationCode ); + TUint32 sessionId = aRequest.Uint32( TMTPTypeRequest::ERequestSessionID ); + TUint32 transactionCode = aRequest.Uint32( TMTPTypeRequest::ERequestTransactionID ); + + if ( operationCode == EMTPOpCodeCloseSession || operationCode == EMTPOpCodeResetDevice ) + { + if ( sessionId != 0 ) + { + ret = EMTPRespCodeInvalidParameter; + } + } + else + { + // requests that are valid when there's no opened session. + if ( sessionId == 0 ) + { + switch ( operationCode ) + { + case EMTPOpCodeGetDeviceInfo: + case EMTPOpCodeOpenSession: + { + // Transaction id must be 0 when called out side an active session. + if ( transactionCode != 0 ) + { + ret = EMTPRespCodeInvalidTransactionID; + } + } + break; + + default: + { + ret = EMTPRespCodeSessionNotOpen; + } + break; + } + } + else if ( !iConnection.SessionWithMTPIdExists( sessionId ) ) + { + ret = EMTPRespCodeSessionNotOpen; + } + } + + return ret; + } + +// ----------------------------------------------------------------------------- +// CRequestChecker::VerifySessionId +// Check the session id in the request parameter (NOTE the session id is different from the one in the request header), +// this usually only applies to the OpenSession request +// ----------------------------------------------------------------------------- +// +TMTPResponseCode CRequestChecker::VerifySessionId( TUint32 aSessionId, + const TMTPRequestElementInfo& /*aElementInfo*/ ) const + { + TMTPResponseCode ret = EMTPRespCodeOK; + + if ( aSessionId != 0 ) + { + if ( iConnection.SessionWithMTPIdExists( aSessionId ) ) + { + ret = EMTPRespCodeSessionAlreadyOpen; + } + } + else + { + ret = EMTPRespCodeInvalidParameter; + } + + return ret; + } + +// ----------------------------------------------------------------------------- +// CRequestChecker::VerifyObjectHandleL +// Check the object handle in the request parameter, whether the handle is in the object store, +// read/write, file/dir +// ----------------------------------------------------------------------------- +// +TMTPResponseCode CRequestChecker::VerifyObjectHandleL( TUint32 aHandle, + const TMTPRequestElementInfo& aElementInfo ) + { + PRINT1( _L("MM MTP => CRequestChecker::VerifyObjectHandleL aHandle = 0x%x"), aHandle ); + TMTPResponseCode ret = EMTPRespCodeOK; + + CMTPObjectMetaData* object( CMTPObjectMetaData::NewLC() ); + TBool result( iFramework.ObjectMgr().ObjectL( aHandle, *object ) ); + iObjectArray.AppendL( object ); + CleanupStack::Pop( object ); + iHandles.AppendL( aHandle ); + + // Obj handle exists + if ( result ) + { + const TDesC& suid( object->DesC( CMTPObjectMetaData::ESuid ) ); + TEntry entry; + TInt err = iFramework.Fs().Entry( suid, entry ); + + if ( object->Uint( CMTPObjectMetaData::EFormatCode ) == EMTPFormatCodeAssociation ) +// && ( object->Uint( CMTPObjectMetaData::EFormatSubCode ) == EMTPAssociationTypeGenericFolder ) ) + { + // Special association type .. not always present on the filesystem. + return ret; + } + else + { + User::LeaveIfError( err ); + + if ( iFramework.ObjectMgr().ObjectOwnerId( aHandle ) != iFramework.DataProviderId() ) + { + PRINT( _L(" ewrwe ret = EMTPRespCodeInvalidObjectHandle;")); + ret = EMTPRespCodeInvalidObjectHandle; + } + } + + if ( aElementInfo.iElementAttr & EMTPElementAttrWrite ) + { + if ( entry.IsReadOnly() ) + { + ret = EMTPRespCodeObjectWriteProtected; + } + } + + //((EMTPRespCodeOK == ret) && (aElementInfo.iElementAttr & EMTPElementAttrFileOrDir)) is + // covered implicitly here, EMTPRespCodeOK will be returned. It is a valid case for an object to be either a folder or file + // for certain operation's request parameter, for instance the first parameter of copyObject or + // moveObject can be either a file or a directory. + + // Other cases. + if ( ( EMTPRespCodeOK == ret ) && ( aElementInfo.iElementAttr & EMTPElementAttrFile) ) + { + if ( entry.IsDir() ) + { + ret = EMTPRespCodeInvalidObjectHandle; + } + } + + if ( ( EMTPRespCodeOK == ret ) && ( aElementInfo.iElementAttr & EMTPElementAttrDir ) ) + { + if (!entry.IsDir()) + { + ret = EMTPRespCodeInvalidParentObject; + } + } + } + else + { + PRINT( _L( "MM MTP <> CRequestChecker::VerifyObjectHandleL, Object does not exist." ) ); + ret = EMTPRespCodeInvalidObjectHandle; + } + PRINT1( _L( "MM MTP <= CRequestChecker::VerifyObjectHandleL ret = 0x%x" ), ret ); + + return ret; + } + +// ----------------------------------------------------------------------------- +// CRequestChecker::VerifyStorageIdL +// Check the storage id parameter in the request, read/write attributes +// ----------------------------------------------------------------------------- +// +TMTPResponseCode CRequestChecker::VerifyStorageIdL( TUint32 aStorageId, + const TMTPRequestElementInfo& aElementInfo ) const + { + MMTPStorageMgr& mgr( iFramework.StorageMgr() ); + TMTPResponseCode ret( EMTPRespCodeOK ); + if ( !mgr.ValidStorageId( aStorageId ) ) + { + ret = EMTPRespCodeInvalidStorageID; + } + else + { + if ( !mgr.LogicalStorageId( aStorageId ) ) + { + ret = EMTPRespCodeStoreNotAvailable; + } + else + { + TInt drive( mgr.DriveNumber( aStorageId ) ); + // StorageIDs which are not system owned do not correspond to drives. + if ( drive != KErrNotFound ) + { + TDriveInfo info; + User::LeaveIfError( iFramework.Fs().Drive( info, drive ) ); + if ( info.iType == EMediaNotPresent ) + { + /** + * Race conditions between media ejection and request processing + * may result in a previously valid storage ID no longer being + * available. + */ + ret = EMTPRespCodeStoreNotAvailable; + } + else + if ( ( aElementInfo.iElementAttr & EMTPElementAttrWrite ) + && ( ( info.iMediaAtt & KMediaAttWriteProtected ) + || ( info.iDriveAtt & KDriveAttRom ) ) ) + { + ret = EMTPRespCodeStoreReadOnly; + } + } + } + } + + return ret; + } + +// ----------------------------------------------------------------------------- +// CRequestChecker::VerifyFormatCode +// Check the format code parameter in the request +// ----------------------------------------------------------------------------- +// +TMTPResponseCode CRequestChecker::VerifyFormatCode( TUint32 aFormatCode, + const TMTPRequestElementInfo& aElementInfo ) const + { + PRINT1( _L( "MM MTP => CRequestChecker::VerifyFormatCode aFormatCode = 0x%x" ), aFormatCode ); + TMTPResponseCode ret = EMTPRespCodeInvalidObjectFormatCode; + + if ( aElementInfo.iElementAttr == EMTPElementAttrFormatEnums ) + { + TUint32* formatArray = (TUint32*)( aElementInfo.iValue1 ); + TUint32 i = 0; + for ( i = 0; i < aElementInfo.iValue2; i++ ) + { + if ( aFormatCode == formatArray[i] ) + { + ret = EMTPRespCodeOK; + break; + } + } + } + else + { + if ( ( aFormatCode >= EMTPFormatCodePTPStart ) + && ( aFormatCode <= EMTPFormatCodeMTPEnd ) ) + { + ret = EMTPRespCodeOK; + } + } + + PRINT1( _L( "MM MTP => CRequestChecker::VerifyFormatCode ret = 0x%x" ), ret ); + + return ret; + } + +// ----------------------------------------------------------------------------- +// CRequestChecker::IsSpecialValue +// Check if the parameter is one of the special values +// ----------------------------------------------------------------------------- +// +TBool CRequestChecker::IsSpecialValue( TUint32 aParameter, + const TMTPRequestElementInfo& aElementInfo ) const + { + TBool result = EFalse; + switch ( aElementInfo.iCount ) + { + case 1: + result = ( aParameter == aElementInfo.iValue1 ); + break; + + case 2: + result = ( aParameter == aElementInfo.iValue1 + || aParameter == aElementInfo.iValue2 ); + break; + + default: + break; + } + + return result; + } + +// end of file