mmappcomponents/mmmtpdataprovider/mmmtpdprequestprocessor/src/crequestchecker.cpp
changeset 0 a2952bb97e68
child 9 bee149131e4b
child 25 d881023c13eb
--- /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 <mtp/cmtpobjectmetadata.h>
+#include <mtp/mmtpconnection.h>
+#include <mtp/mmtpdataproviderframework.h>
+#include <mtp/mmtpobjectmgr.h>
+#include <mtp/mmtpstoragemgr.h>
+
+#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