mmappcomponents/mmmtpdataprovider/mmmtpdprequestprocessor/src/crequestchecker.cpp
changeset 0 a2952bb97e68
child 9 bee149131e4b
child 25 d881023c13eb
equal deleted inserted replaced
-1:000000000000 0:a2952bb97e68
       
     1 /*
       
     2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: 
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include <mtp/cmtpobjectmetadata.h>
       
    20 #include <mtp/mmtpconnection.h>
       
    21 #include <mtp/mmtpdataproviderframework.h>
       
    22 #include <mtp/mmtpobjectmgr.h>
       
    23 #include <mtp/mmtpstoragemgr.h>
       
    24 
       
    25 #include "crequestchecker.h"
       
    26 #include "mmmtpdplogger.h"
       
    27 
       
    28 static const TInt KMTPRequestCheckerHandleGranularity = 2;
       
    29 
       
    30 // -----------------------------------------------------------------------------
       
    31 // CRequestChecker::NewL
       
    32 // Two-phase construction method
       
    33 // -----------------------------------------------------------------------------
       
    34 //
       
    35 CRequestChecker* CRequestChecker::NewL( MMTPDataProviderFramework& aFramework,
       
    36     MMTPConnection& aConnection )
       
    37     {
       
    38     CRequestChecker* self = new (ELeave) CRequestChecker( aFramework, aConnection );
       
    39     CleanupStack::PushL( self );
       
    40     self->ConstructL();
       
    41     CleanupStack::Pop( self );
       
    42     return self;
       
    43     }
       
    44 
       
    45 // -----------------------------------------------------------------------------
       
    46 // CRequestChecker::CRequestChecker
       
    47 // Standard c++ constructor
       
    48 // -----------------------------------------------------------------------------
       
    49 //
       
    50 CRequestChecker::CRequestChecker( MMTPDataProviderFramework& aFramework,
       
    51     MMTPConnection& aConnection ) :
       
    52     iFramework( aFramework ),
       
    53     iConnection( aConnection ),
       
    54     iHandles( KMTPRequestCheckerHandleGranularity ),
       
    55     iObjectArray( KMTPRequestCheckerHandleGranularity )
       
    56     {
       
    57     
       
    58     }
       
    59 
       
    60 // -----------------------------------------------------------------------------
       
    61 // CRequestChecker::ConstructL
       
    62 // Two-phase construction method
       
    63 // -----------------------------------------------------------------------------
       
    64 //
       
    65 void CRequestChecker::ConstructL()
       
    66     {
       
    67     
       
    68     }
       
    69 
       
    70 // -----------------------------------------------------------------------------
       
    71 // CRequestChecker::~CRequestChecker
       
    72 // Destructor
       
    73 // -----------------------------------------------------------------------------
       
    74 //
       
    75 CRequestChecker::~CRequestChecker()
       
    76     {
       
    77     iHandles.Close();
       
    78     iObjectArray.ResetAndDestroy();
       
    79     }
       
    80 
       
    81 // -----------------------------------------------------------------------------
       
    82 // CRequestChecker::VerifyRequestL
       
    83 // Verfiy the request
       
    84 // -----------------------------------------------------------------------------
       
    85 //
       
    86 TMTPResponseCode CRequestChecker::VerifyRequestL( const TMTPTypeRequest& aRequest,
       
    87         TInt aCount,
       
    88         const TMTPRequestElementInfo* aElementInfo )
       
    89     {
       
    90     TMTPResponseCode result = EMTPRespCodeOK;
       
    91     iHandles.Close();
       
    92     iObjectArray.ResetAndDestroy();
       
    93 
       
    94     result = CheckRequestHeader( aRequest );
       
    95 
       
    96     for ( TInt i = 0; i < aCount && EMTPRespCodeOK == result; i++ )
       
    97         {
       
    98         TUint32 parameter = aRequest.Uint32( aElementInfo[i].iElementIndex );
       
    99         PRINT3( _L( "MM MTP <> CRequestChecker parameter %d/%d = %d" ), 
       
   100                 i + 1, aCount, parameter );
       
   101         
       
   102         if ( !IsSpecialValue( parameter, aElementInfo[i] ) )
       
   103             {
       
   104             switch ( aElementInfo[i].iElementType )
       
   105                 {
       
   106                 case EMTPElementTypeSessionID:
       
   107                     result = VerifySessionId( parameter, aElementInfo[i] );
       
   108                     break;
       
   109 
       
   110                 case EMTPElementTypeObjectHandle:
       
   111                     result = VerifyObjectHandleL( parameter, aElementInfo[i] );
       
   112                     break;
       
   113 
       
   114                 case EMTPElementTypeStorageId:
       
   115                     result = VerifyStorageIdL( parameter, aElementInfo[i] );
       
   116                     break;
       
   117 
       
   118                 case EMTPElementTypeFormatCode:
       
   119                     result = VerifyFormatCode( parameter, aElementInfo[i] );
       
   120                     break;
       
   121 
       
   122                 default:
       
   123                     User::Invariant(); // Should never run
       
   124                     break;
       
   125                 }
       
   126             }
       
   127         }
       
   128 
       
   129     return result;
       
   130     }
       
   131 
       
   132 // -----------------------------------------------------------------------------
       
   133 // CRequestChecker::GetObjectInfo
       
   134 // Return the object info for the handle
       
   135 // -----------------------------------------------------------------------------
       
   136 //
       
   137 CMTPObjectMetaData* CRequestChecker::GetObjectInfo( TUint32 aHandle ) const
       
   138     {
       
   139     CMTPObjectMetaData* result = NULL;
       
   140     TInt count = iHandles.Count();
       
   141     for( TInt i = 0; i < count; i++ )
       
   142         {
       
   143         if ( iHandles[i] == aHandle )
       
   144             {
       
   145             result = iObjectArray[i];
       
   146             break;
       
   147             }
       
   148         }
       
   149     return result;
       
   150     }
       
   151 
       
   152 // -----------------------------------------------------------------------------
       
   153 // CRequestChecker::CheckRequestHeader
       
   154 // Check the request header portion (session Id and transaction code)
       
   155 // -----------------------------------------------------------------------------
       
   156 //
       
   157 TMTPResponseCode CRequestChecker::CheckRequestHeader( const TMTPTypeRequest& aRequest ) const
       
   158     {
       
   159     TMTPResponseCode ret = EMTPRespCodeOK;
       
   160     TUint16 operationCode = aRequest.Uint16( TMTPTypeRequest::ERequestOperationCode );
       
   161     TUint32 sessionId = aRequest.Uint32( TMTPTypeRequest::ERequestSessionID );
       
   162     TUint32 transactionCode = aRequest.Uint32( TMTPTypeRequest::ERequestTransactionID );
       
   163 
       
   164     if ( operationCode == EMTPOpCodeCloseSession || operationCode == EMTPOpCodeResetDevice )
       
   165         {
       
   166         if ( sessionId != 0 )
       
   167             {
       
   168             ret = EMTPRespCodeInvalidParameter;
       
   169             }
       
   170         }
       
   171     else
       
   172         {
       
   173         // requests that are valid when there's no opened session.
       
   174         if ( sessionId == 0 )
       
   175             {
       
   176             switch ( operationCode )
       
   177                 {
       
   178                 case EMTPOpCodeGetDeviceInfo:
       
   179                 case EMTPOpCodeOpenSession:
       
   180                     {
       
   181                     // Transaction id must be 0 when called out side an active session.
       
   182                     if ( transactionCode != 0 )
       
   183                         {
       
   184                         ret = EMTPRespCodeInvalidTransactionID;
       
   185                         }
       
   186                     }
       
   187                     break;
       
   188 
       
   189                 default:
       
   190                     {
       
   191                     ret = EMTPRespCodeSessionNotOpen;
       
   192                     }
       
   193                     break;
       
   194                 }
       
   195             }
       
   196         else if ( !iConnection.SessionWithMTPIdExists( sessionId ) )
       
   197             {
       
   198             ret = EMTPRespCodeSessionNotOpen;
       
   199             }
       
   200         }
       
   201     
       
   202     return ret;
       
   203     }
       
   204 
       
   205 // -----------------------------------------------------------------------------
       
   206 // CRequestChecker::VerifySessionId
       
   207 // Check the session id in the request parameter (NOTE the session id is different from the one in the request header),
       
   208 // this usually only applies to the OpenSession request
       
   209 // -----------------------------------------------------------------------------
       
   210 //
       
   211 TMTPResponseCode CRequestChecker::VerifySessionId( TUint32 aSessionId,
       
   212         const TMTPRequestElementInfo& /*aElementInfo*/ ) const
       
   213     {
       
   214     TMTPResponseCode ret = EMTPRespCodeOK;
       
   215 
       
   216     if ( aSessionId != 0 )
       
   217         {
       
   218         if ( iConnection.SessionWithMTPIdExists( aSessionId ) )
       
   219             {
       
   220             ret = EMTPRespCodeSessionAlreadyOpen;
       
   221             }
       
   222         }
       
   223     else
       
   224         {
       
   225         ret = EMTPRespCodeInvalidParameter;
       
   226         }
       
   227     
       
   228     return ret;
       
   229     }
       
   230 
       
   231 // -----------------------------------------------------------------------------
       
   232 // CRequestChecker::VerifyObjectHandleL
       
   233 // Check the object handle in the request parameter, whether the handle is in the object store,
       
   234 // read/write, file/dir
       
   235 // -----------------------------------------------------------------------------
       
   236 //
       
   237 TMTPResponseCode CRequestChecker::VerifyObjectHandleL( TUint32 aHandle,
       
   238         const TMTPRequestElementInfo& aElementInfo )
       
   239     {
       
   240     PRINT1( _L("MM MTP => CRequestChecker::VerifyObjectHandleL aHandle = 0x%x"), aHandle );
       
   241     TMTPResponseCode ret = EMTPRespCodeOK;
       
   242 
       
   243     CMTPObjectMetaData* object( CMTPObjectMetaData::NewLC() );
       
   244     TBool result( iFramework.ObjectMgr().ObjectL( aHandle, *object ) );
       
   245     iObjectArray.AppendL( object );
       
   246     CleanupStack::Pop( object );
       
   247     iHandles.AppendL( aHandle );
       
   248 
       
   249     // Obj handle exists
       
   250     if ( result )
       
   251         {
       
   252         const TDesC& suid( object->DesC( CMTPObjectMetaData::ESuid ) );
       
   253         TEntry entry;
       
   254         TInt err = iFramework.Fs().Entry( suid, entry );
       
   255         
       
   256         if ( object->Uint( CMTPObjectMetaData::EFormatCode ) == EMTPFormatCodeAssociation )
       
   257 //            && ( object->Uint( CMTPObjectMetaData::EFormatSubCode ) == EMTPAssociationTypeGenericFolder ) )
       
   258             {
       
   259             // Special association type .. not always present on the filesystem.
       
   260             return ret;
       
   261             }
       
   262         else
       
   263             {
       
   264             User::LeaveIfError( err );
       
   265             
       
   266             if ( iFramework.ObjectMgr().ObjectOwnerId( aHandle ) != iFramework.DataProviderId() )
       
   267                 {
       
   268                 PRINT( _L(" ewrwe ret = EMTPRespCodeInvalidObjectHandle;"));
       
   269                 ret = EMTPRespCodeInvalidObjectHandle;
       
   270                 }
       
   271             }
       
   272 
       
   273         if ( aElementInfo.iElementAttr & EMTPElementAttrWrite )
       
   274             {
       
   275             if ( entry.IsReadOnly() )
       
   276                 {
       
   277                 ret = EMTPRespCodeObjectWriteProtected;
       
   278                 }
       
   279             }
       
   280 
       
   281         //((EMTPRespCodeOK == ret) && (aElementInfo.iElementAttr & EMTPElementAttrFileOrDir)) is
       
   282         // covered implicitly here, EMTPRespCodeOK will be returned. It is a valid case for an object to be either a folder or file
       
   283         // for certain operation's request parameter, for instance the first parameter of copyObject or
       
   284         // moveObject can be either a file or a directory.
       
   285 
       
   286         // Other cases.
       
   287         if ( ( EMTPRespCodeOK == ret ) && ( aElementInfo.iElementAttr & EMTPElementAttrFile) )
       
   288             {
       
   289             if ( entry.IsDir() )
       
   290                 {
       
   291                 ret = EMTPRespCodeInvalidObjectHandle;
       
   292                 }
       
   293             }
       
   294 
       
   295         if ( ( EMTPRespCodeOK == ret ) && ( aElementInfo.iElementAttr & EMTPElementAttrDir ) )
       
   296             {
       
   297             if (!entry.IsDir())
       
   298                 {
       
   299                 ret = EMTPRespCodeInvalidParentObject;
       
   300                 }
       
   301             }
       
   302         }
       
   303     else
       
   304         {
       
   305         PRINT( _L( "MM MTP <> CRequestChecker::VerifyObjectHandleL, Object does not exist." ) );
       
   306         ret = EMTPRespCodeInvalidObjectHandle;
       
   307         }
       
   308     PRINT1( _L( "MM MTP <= CRequestChecker::VerifyObjectHandleL ret = 0x%x" ), ret );
       
   309     
       
   310     return ret;
       
   311     }
       
   312 
       
   313 // -----------------------------------------------------------------------------
       
   314 // CRequestChecker::VerifyStorageIdL
       
   315 // Check the storage id parameter in the request, read/write attributes
       
   316 // -----------------------------------------------------------------------------
       
   317 //
       
   318 TMTPResponseCode CRequestChecker::VerifyStorageIdL( TUint32 aStorageId,
       
   319         const TMTPRequestElementInfo& aElementInfo ) const
       
   320     {
       
   321     MMTPStorageMgr& mgr( iFramework.StorageMgr() );
       
   322     TMTPResponseCode ret( EMTPRespCodeOK );
       
   323     if ( !mgr.ValidStorageId( aStorageId ) )
       
   324         {
       
   325         ret = EMTPRespCodeInvalidStorageID;
       
   326         }
       
   327     else
       
   328         {
       
   329         if ( !mgr.LogicalStorageId( aStorageId ) )
       
   330             {
       
   331             ret = EMTPRespCodeStoreNotAvailable;
       
   332             }
       
   333         else
       
   334             {
       
   335             TInt drive( mgr.DriveNumber( aStorageId ) );
       
   336             // StorageIDs which are not system owned do not correspond to drives.
       
   337             if ( drive != KErrNotFound )
       
   338                 {
       
   339                 TDriveInfo info;
       
   340                 User::LeaveIfError( iFramework.Fs().Drive( info, drive ) );
       
   341                 if ( info.iType == EMediaNotPresent )
       
   342                     {
       
   343                     /**
       
   344                     * Race conditions between media ejection and request processing
       
   345                     * may result in a previously valid storage ID no longer being
       
   346                     * available.
       
   347                     */
       
   348                     ret = EMTPRespCodeStoreNotAvailable;
       
   349                     }
       
   350                 else
       
   351                     if ( ( aElementInfo.iElementAttr & EMTPElementAttrWrite )
       
   352                         && ( ( info.iMediaAtt & KMediaAttWriteProtected )
       
   353                         || ( info.iDriveAtt & KDriveAttRom ) ) )
       
   354                         {
       
   355                         ret = EMTPRespCodeStoreReadOnly;
       
   356                         }
       
   357                 }
       
   358             }
       
   359        }
       
   360     
       
   361     return ret;
       
   362     }
       
   363 
       
   364 // -----------------------------------------------------------------------------
       
   365 // CRequestChecker::VerifyFormatCode
       
   366 // Check the format code parameter in the request
       
   367 // -----------------------------------------------------------------------------
       
   368 //
       
   369 TMTPResponseCode CRequestChecker::VerifyFormatCode( TUint32 aFormatCode,
       
   370         const TMTPRequestElementInfo& aElementInfo ) const
       
   371     {
       
   372     PRINT1( _L( "MM MTP => CRequestChecker::VerifyFormatCode aFormatCode = 0x%x" ), aFormatCode );
       
   373     TMTPResponseCode ret = EMTPRespCodeInvalidObjectFormatCode;
       
   374 
       
   375     if ( aElementInfo.iElementAttr == EMTPElementAttrFormatEnums )
       
   376         {
       
   377         TUint32* formatArray = (TUint32*)( aElementInfo.iValue1 );
       
   378         TUint32 i = 0;
       
   379         for ( i = 0; i < aElementInfo.iValue2; i++ )
       
   380             {
       
   381             if ( aFormatCode == formatArray[i] )
       
   382                 {
       
   383                 ret = EMTPRespCodeOK;
       
   384                 break;
       
   385                 }
       
   386             }
       
   387         }
       
   388     else
       
   389         {
       
   390         if ( ( aFormatCode >= EMTPFormatCodePTPStart )
       
   391             && ( aFormatCode <= EMTPFormatCodeMTPEnd ) )
       
   392             {
       
   393             ret = EMTPRespCodeOK;
       
   394             }
       
   395         }
       
   396 
       
   397     PRINT1( _L( "MM MTP => CRequestChecker::VerifyFormatCode ret = 0x%x" ), ret );
       
   398     
       
   399     return ret;
       
   400     }
       
   401 
       
   402 // -----------------------------------------------------------------------------
       
   403 // CRequestChecker::IsSpecialValue
       
   404 // Check if the parameter is one of the special values
       
   405 // -----------------------------------------------------------------------------
       
   406 //
       
   407 TBool CRequestChecker::IsSpecialValue( TUint32 aParameter,
       
   408         const TMTPRequestElementInfo& aElementInfo ) const
       
   409     {
       
   410     TBool result = EFalse;
       
   411     switch ( aElementInfo.iCount )
       
   412         {
       
   413         case 1:
       
   414             result = ( aParameter == aElementInfo.iValue1 );
       
   415             break;
       
   416             
       
   417         case 2:
       
   418             result = ( aParameter == aElementInfo.iValue1
       
   419                 || aParameter == aElementInfo.iValue2 );
       
   420             break;
       
   421             
       
   422         default:
       
   423             break;
       
   424         }
       
   425     
       
   426     return result;
       
   427     }
       
   428 
       
   429 // end of file