mtpfws/mtpfw/dataproviders/dputility/src/cmtpsendobjectinfo.cpp
changeset 0 d0791faffa3f
child 2 4843bb5893b6
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mtpfws/mtpfw/dataproviders/dputility/src/cmtpsendobjectinfo.cpp	Tue Feb 02 01:11:40 2010 +0200
@@ -0,0 +1,1232 @@
+// 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:
+//
+
+#include <f32file.h>
+#include <bautils.h>
+#include <mtp/cmtpdataproviderplugin.h>
+#include <mtp/mmtpdataproviderframework.h>
+
+#include <mtp/cmtpobjectmetadata.h>
+#include <mtp/cmtptypefile.h>
+#include <mtp/cmtptypeobjectinfo.h>
+#include <mtp/cmtptypeobjectproplist.h>
+#include <mtp/cmtptypestring.h>
+#include <mtp/mmtpobjectmgr.h>
+#include <mtp/mmtpstoragemgr.h>
+#include <mtp/mtpprotocolconstants.h>
+
+
+#include <mtp/tmtptyperequest.h>
+#include "cmtpconnection.h"
+#include "cmtpconnectionmgr.h"
+#include "cmtpsendobjectinfo.h"
+#include "mtpdppanic.h"
+#include "cmtpfsexclusionmgr.h"
+#include "cmtpdataprovidercontroller.h"
+#include "cmtpdataprovider.h"
+
+
+// Class constants.
+__FLOG_STMT(_LIT8(KComponent,"SendObjectInfo");)
+
+/**
+Verification data for the SendObjectInfo request
+*/
+const TMTPRequestElementInfo KMTPSendObjectInfoPolicy[] = 
+    {
+        {TMTPTypeRequest::ERequestParameter1, EMTPElementTypeStorageId, EMTPElementAttrWrite, 1, 0, 0},                
+        {TMTPTypeRequest::ERequestParameter2, EMTPElementTypeObjectHandle, EMTPElementAttrDir, 2, KMTPHandleAll, KMTPHandleNone}
+    };
+
+
+/**
+Two-phase construction method
+@param aFramework  The data provider framework
+@param aConnection The connection from which the request comes
+@return a pointer to the created request processor object
+*/ 
+EXPORT_C MMTPRequestProcessor* CMTPSendObjectInfo::NewL(MMTPDataProviderFramework& aFramework, MMTPConnection& aConnection)
+    {
+    CMTPSendObjectInfo* self = new (ELeave) CMTPSendObjectInfo(aFramework, aConnection);
+    CleanupStack::PushL(self);
+    self->ConstructL();
+    CleanupStack::Pop(self);
+    return self;
+    }
+
+/**
+Destructor
+*/    
+EXPORT_C CMTPSendObjectInfo::~CMTPSendObjectInfo()
+    {
+    __FLOG(_L8("~CMTPSendObjectInfo - Entry"));
+    
+    if ((iProgress == EObjectInfoSucceed ||
+        iProgress == EObjectInfoFail || 
+        iProgress == EObjectInfoInProgress) && !iNoRollback)
+        {
+        // Not finished SendObjectInfo/PropList SendObject pair detected.
+        Rollback();
+        }
+    
+    iDpSingletons.Close();
+    delete iDateMod;
+    delete iFileReceived;
+    delete iParentSuid;    
+    delete iReceivedObject;
+    delete iObjectInfo;
+    delete iObjectPropList;
+    iSingletons.Close();
+    __FLOG(_L8("~CMTPSendObjectInfo - Exit"));
+    __FLOG_CLOSE; 
+    }
+
+/**
+Standard c++ constructor
+@param aFramework    The data provider framework
+@param aConnection    The connection from which the request comes
+*/    
+CMTPSendObjectInfo::CMTPSendObjectInfo(MMTPDataProviderFramework& aFramework, MMTPConnection& aConnection) :
+    CMTPRequestProcessor(aFramework, aConnection, 0, NULL)
+    {
+    }
+
+/**
+Verify the request
+@return EMTPRespCodeOK if request is verified, otherwise one of the error response codes
+*/    
+TMTPResponseCode CMTPSendObjectInfo::CheckRequestL()
+    {
+    __FLOG(_L8("CheckRequestL - Entry"));
+    TMTPResponseCode result = CheckSendingStateL();
+    
+    if (result != EMTPRespCodeOK) 
+        {
+        return result;
+        }
+    
+    if (iProgress == EObjectNone)    //this is the SendObjectInfo phase
+        {
+        iElementCount = sizeof(KMTPSendObjectInfoPolicy) / sizeof(TMTPRequestElementInfo);
+        iElements = KMTPSendObjectInfoPolicy;            
+        }
+    else if (iProgress == EObjectInfoSucceed)
+        {
+        iElementCount = 0;
+        iElements = NULL;
+        }
+    //coverity[var_deref_model]
+	result = CMTPRequestProcessor::CheckRequestL();     	
+ 
+    if (EMTPRespCodeOK == result)
+        {
+        result = MatchStoreAndParentL();
+        }
+        
+    if (result == EMTPRespCodeOK && iOperationCode == EMTPOpCodeSendObjectPropList)
+        {
+        TMTPFormatCode formatCode = static_cast<TMTPFormatCode>(Request().Uint32(TMTPTypeRequest::ERequestParameter3));
+        if (!iDpSingletons.ExclusionMgrL().IsFormatValid(formatCode))
+            {
+            result = EMTPRespCodeInvalidObjectFormatCode;
+            }
+        else
+            {
+            iStorageId = Request().Uint32(TMTPTypeRequest::ERequestParameter1);
+            TUint32 objectSizeHigh = Request().Uint32(TMTPTypeRequest::ERequestParameter4);
+            TUint32 objectSizeLow = Request().Uint32(TMTPTypeRequest::ERequestParameter5);
+            if (iStorageId == KMTPStorageDefault)
+                {
+                iStorageId = iFramework.StorageMgr().DefaultStorageId();
+                }
+            iObjectSize = MAKE_TUINT64(objectSizeHigh, objectSizeLow);
+            if (IsTooLarge(iObjectSize))
+                {
+                result = EMTPRespCodeObjectTooLarge;            
+                }
+         	   
+            //File size is limited to KMaxTInt64 that is 8ExaBytes
+            //if the object size is more,then report this error.
+            if (!CanStoreFileL(iStorageId, iObjectSize)||(iObjectSize > (KMaxTInt64)))
+                {
+                result = EMTPRespCodeStoreFull;
+                }
+            }
+        }
+        
+    // If the previous request is not SendObjectInfo or SendObjectPropList, SendObject fails
+    if (result == EMTPRespCodeOK && iOperationCode == EMTPOpCodeSendObject)
+        {
+        if (iPreviousTransactionID + 1 != Request().Uint32(TMTPTypeRequest::ERequestTransactionID))
+            {
+            result = EMTPRespCodeNoValidObjectInfo;
+            }
+        }
+        
+    __FLOG_VA((_L8("Result = 0x%04X"), result));
+    __FLOG(_L8("CheckRequestL - Exit"));
+    return result;    
+    }
+    
+TBool CMTPSendObjectInfo::HasDataphase() const
+    {
+    return ETrue;
+    }
+
+/**
+SendObjectInfo/SendObject request handler
+NOTE: SendObjectInfo has to be comes before SendObject requests.  To maintain the state information
+between the two requests, the two requests are combined together in one request processor.
+*/    
+void CMTPSendObjectInfo::ServiceL()
+    {
+    __FLOG(_L8("ServiceL - Entry"));
+    if (iProgress == EObjectNone)
+        {
+        iIsFolder = EFalse;
+        if (iOperationCode == EMTPOpCodeSendObjectInfo)
+            {
+            ServiceSendObjectInfoL();
+            }
+        else
+            {
+            ServiceSendObjectPropListL();
+            }
+        }
+    else
+        {
+        ServiceSendObjectL();
+        }    
+    __FLOG(_L8("ServiceL - Exit"));
+    }
+
+/**
+Second-phase construction
+*/        
+void CMTPSendObjectInfo::ConstructL()
+    {
+    __FLOG_OPEN(KMTPSubsystem, KComponent);
+    __FLOG(_L8("ConstructL - Entry")); 
+    iExpectedSendObjectRequest.SetUint16(TMTPTypeRequest::ERequestOperationCode, EMTPOpCodeSendObject);
+    iReceivedObject = CMTPObjectMetaData::NewL();
+    iReceivedObject->SetUint(CMTPObjectMetaData::EDataProviderId, iFramework.DataProviderId());
+    iDpSingletons.OpenL(iFramework);
+    iNoRollback = EFalse;
+    iSingletons.OpenL();
+    __FLOG(_L8("ConstructL - Exit"));
+    }
+
+/**
+Override to match both the SendObjectInfo and SendObject requests
+@param aRequest    The request to match
+@param aConnection The connection from which the request comes
+@return ETrue if the processor can handle the request, otherwise EFalse
+*/        
+TBool CMTPSendObjectInfo::Match(const TMTPTypeRequest& aRequest, MMTPConnection& aConnection) const
+    {
+    __FLOG(_L8("Match - Entry"));
+    TBool result = EFalse;
+    TUint16 operationCode = aRequest.Uint16(TMTPTypeRequest::ERequestOperationCode);
+    if ((operationCode == EMTPOpCodeSendObjectInfo || 
+        operationCode == EMTPOpCodeSendObject ||
+        operationCode == EMTPOpCodeSendObjectPropList) &&
+        &iConnection == &aConnection)
+        {
+        result = ETrue;
+        }
+    __FLOG(_L8("Match - Exit"));
+    return result;    
+    }
+
+/**
+Override to handle the response phase of SendObjectInfo and SendObject requests
+@return EFalse
+*/
+TBool CMTPSendObjectInfo::DoHandleResponsePhaseL()
+    {
+    __FLOG(_L8("DoHandleResponsePhaseL - Entry"));
+    //to check if the sending/receiving data is successful
+    TBool successful = !iCancelled;
+    if (iProgress == EObjectInfoInProgress)
+        {
+        if (iOperationCode == EMTPOpCodeSendObjectInfo)
+            {            
+            successful = DoHandleSendObjectInfoCompleteL();
+            }
+        else
+            {
+            successful = DoHandleSendObjectPropListCompleteL();
+            }
+        iProgress = (successful ? EObjectInfoSucceed : EObjectInfoFail);
+        if(iIsFolder && iProgress == EObjectInfoSucceed)
+			{
+			iProgress = EObjectNone;
+			}
+        }
+    else if (iProgress == ESendObjectInProgress)
+        {
+        successful = DoHandleSendObjectCompleteL();
+        iProgress = (successful ? ESendObjectSucceed : ESendObjectFail);
+        }
+        
+    __FLOG(_L8("DoHandleResponsePhaseL - Exit"));
+    return EFalse;
+    }
+
+/**
+Override to handle the completing phase of SendObjectInfo and SendObject requests
+@return ETrue if succesfully received the file, otherwise EFalse
+*/    
+TBool CMTPSendObjectInfo::DoHandleCompletingPhaseL()
+    {
+    __FLOG(_L8("DoHandleCompletingPhaseL - Entry"));
+    TBool result = ETrue;
+    CMTPRequestProcessor::DoHandleCompletingPhaseL();
+    if (iProgress == EObjectInfoSucceed)
+        {
+        if (iOperationCode == EMTPOpCodeSendObjectInfo || iOperationCode == EMTPOpCodeSendObjectPropList)
+            {
+            iPreviousTransactionID = Request().Uint32(TMTPTypeRequest::ERequestTransactionID);
+            }
+        result = EFalse;
+        }
+    else if (iProgress == ESendObjectFail)
+        {
+        if (iOperationCode == EMTPOpCodeSendObject)
+            {
+            iPreviousTransactionID++;
+            }
+        iProgress = EObjectInfoSucceed;
+        result = EFalse;
+        }
+    
+    __FLOG(_L8("DoHandleCompletingPhaseL - Exit"));
+    return result;    
+    }
+
+
+/**
+Verify if the SendObject request comes after SendObjectInfo request
+@return EMTPRespCodeOK if SendObject request comes after a valid SendObjectInfo request, otherwise
+EMTPRespCodeNoValidObjectInfo
+*/
+TMTPResponseCode CMTPSendObjectInfo::CheckSendingStateL()
+    {
+    __FLOG(_L8("CheckSendingState - Entry"));
+    TMTPResponseCode result = EMTPRespCodeOK;
+    iOperationCode = Request().Uint16(TMTPTypeRequest::ERequestOperationCode);
+
+    if (iOperationCode == EMTPOpCodeSendObject)
+    	{
+    	//In ParseRouter everytime SendObject gets resolved then will be removed from Registry
+    	//Right away therefore we need reRegister it here again in case possible cancelRequest
+    	//Against this SendObject being raised.
+    	iExpectedSendObjectRequest.SetUint32(TMTPTypeRequest::ERequestSessionID, iSessionId);
+    	iFramework.RouteRequestRegisterL(iExpectedSendObjectRequest, iConnection);
+       	}        
+    
+    if (iProgress == EObjectNone)
+        {
+        if (iOperationCode == EMTPOpCodeSendObject)
+            {
+            result = EMTPRespCodeNoValidObjectInfo;
+            }        
+        }
+    else if (iProgress == EObjectInfoSucceed) 
+        {
+        if (iOperationCode == EMTPOpCodeSendObjectInfo || iOperationCode == EMTPOpCodeSendObjectPropList)
+            {
+            //SendObjectInfo/SendObjectPropList sending the folder over which not necessarily
+            //being followed by SendObject as per MTP Specification in which case we need unregister RouteRequest of 
+            //SendObject made by previous SendObjectInfo/SendObjectPropList transaction without SendObject being followed.
+            if( iIsFolder )
+            	{
+            	iFramework.RouteRequestUnregisterL(iExpectedSendObjectRequest, iConnection);
+        		}
+        
+            delete iObjectInfo;
+            iObjectInfo = NULL;
+            delete iObjectPropList;
+            iObjectPropList = NULL;
+            iProgress = EObjectNone;
+            }
+        }
+    else 
+        {
+        Panic(EMTPDpSendObjectStateInvalid);
+        }
+    __FLOG(_L8("CheckSendingState - Exit"));
+    return result;    
+    }
+
+/**
+SendObjectInfo request handler
+*/
+void CMTPSendObjectInfo::ServiceSendObjectInfoL()
+    {
+    __FLOG(_L8("ServiceSendObjectInfoL - Entry"));
+    delete iObjectInfo;
+    iObjectInfo = NULL;
+    iObjectInfo = CMTPTypeObjectInfo::NewL();
+    iCancelled = EFalse;
+    ReceiveDataL(*iObjectInfo);
+    iProgress = EObjectInfoInProgress;
+    __FLOG(_L8("ServiceSendObjectInfoL - Exit"));
+    }
+
+/**
+SendObjectPropList request handler
+*/
+void CMTPSendObjectInfo::ServiceSendObjectPropListL()
+    {
+    __FLOG(_L8("ServiceSendObjectPropListL - Entry"));
+    delete iObjectPropList;
+    iObjectPropList = NULL;
+    iObjectPropList = CMTPTypeObjectPropList::NewL();
+    iCancelled = EFalse;
+    iReceivedObject->SetUint(CMTPObjectMetaData::EFormatCode, iRequest->Uint32(TMTPTypeRequest::ERequestParameter3));
+    ReceiveDataL(*iObjectPropList);
+    iProgress = EObjectInfoInProgress;
+    __FLOG(_L8("ServiceSendObjectPropListL - Exit"));
+    }
+    
+/**
+SendObject request handler
+*/    
+void CMTPSendObjectInfo::ServiceSendObjectL()
+    {
+    __FLOG(_L8("ServiceSendObjectL - Entry"));
+    if (iIsFolder)
+        {
+        // A generic folder doesn't have anything interesting during its data phase
+        ReceiveDataL(iNullObject);
+        }
+    else    
+        {        
+        ReceiveDataL(*iFileReceived);
+        }
+    
+    iProgress = ESendObjectInProgress;
+    __FLOG(_L8("ServiceSendObjectL - Exit"));
+    }
+
+/**
+Get a default parent object, if the request does not specify a parent object.
+*/
+void CMTPSendObjectInfo::GetDefaultParentObjectL()
+    {    
+    __FLOG(_L8("GetDefaultParentObjectL - Entry"));
+    if (iStorageId == KMTPStorageDefault)
+        {
+        iStorageId = iFramework.StorageMgr().DefaultStorageId();
+        }
+    TInt drive(iFramework.StorageMgr().DriveNumber(iStorageId));
+    User::LeaveIfError(drive);
+
+    // Obtain the root of the drive.  Logical storages can sometimes have a filesystem root
+    // other than <drive>:\ .  For example an MP3 DP might have a root of c:\media\music\
+    // The DevDP needs to be aware of this when handling associations (folders) so they are
+    // created in the correct location on the filesystem.
+    delete iParentSuid;
+    iParentSuid = NULL;
+    iParentSuid=(iFramework.StorageMgr().StorageL(iStorageId).DesC(CMTPStorageMetaData::EStorageSuid)).AllocL();
+    iReceivedObject->SetUint(CMTPObjectMetaData::EParentHandle, KMTPHandleNoParent);
+    __FLOG(_L8("GetDefaultParentObjectL - Exit"));        
+    }
+
+/**
+Get parent object and storage id
+@return EMTPRespCodeOK if successful, otherwise, EMTPRespCodeInvalidParentObject
+*/
+TMTPResponseCode CMTPSendObjectInfo::GetParentObjectAndStorageIdL()
+    {
+    __FLOG(_L8("GetParentObjectAndStorageIdL - Entry"));    
+    __ASSERT_DEBUG(iRequestChecker, Panic(EMTPDpRequestCheckNull));
+
+    iStorageId = Request().Uint32(TMTPTypeRequest::ERequestParameter1);
+    iParentHandle = Request().Uint32(TMTPTypeRequest::ERequestParameter2);
+    //does not take ownership
+    CMTPObjectMetaData* parentObjectInfo = iRequestChecker->GetObjectInfo(iParentHandle);
+
+    if (!parentObjectInfo)
+        {
+        GetDefaultParentObjectL();    
+        }
+    else
+        {        
+        delete iParentSuid;
+        iParentSuid = NULL;
+        iParentSuid = parentObjectInfo->DesC(CMTPObjectMetaData::ESuid).AllocL();
+        iReceivedObject->SetUint(CMTPObjectMetaData::EParentHandle, iParentHandle);
+        }
+
+    __FLOG_VA((_L8("iParentSuid = %S"), iParentSuid));
+    __FLOG(_L8("GetParentObjectAndStorageIdL - Exit"));    
+    return EMTPRespCodeOK;
+    }
+
+/**
+Handling the completing phase of SendObjectInfo request
+@return ETrue if the specified object can be saved on the specified location, otherwise, EFalse
+*/    
+TBool CMTPSendObjectInfo::DoHandleSendObjectInfoCompleteL()
+    {
+    __FLOG(_L8("DoHandleSendObjectInfoCompleteL - Entry"));    
+    TBool result(ETrue);
+    TUint16 format(iObjectInfo->Uint16L(CMTPTypeObjectInfo::EObjectFormat));
+    
+    result = iDpSingletons.ExclusionMgrL().IsFormatValid(TMTPFormatCode(format));
+    
+    if (result)
+        {
+        __FLOG_VA((_L8("ASSOCIATION TYPE IS: %X"), iObjectInfo->Uint16L(CMTPTypeObjectInfo::EAssociationType)));        
+		if(format == EMTPFormatCodeAssociation)
+			{
+			if((iObjectInfo->Uint16L(CMTPTypeObjectInfo::EAssociationType) == EMTPAssociationTypeGenericFolder) ||
+        		      (iObjectInfo->Uint16L(CMTPTypeObjectInfo::EAssociationType) == EMTPAssociationTypeUndefined))
+				iIsFolder = ETrue;
+			else{
+				SendResponseL(EMTPRespCodeInvalidDataset);
+	            result = EFalse;	
+				}
+			}
+        delete iDateMod;
+        iDateMod = NULL;
+    
+        iDateMod = iObjectInfo->StringCharsL(CMTPTypeObjectInfo::EDateModified).AllocL();
+    
+        TMTPResponseCode responseCode(GetParentObjectAndStorageIdL());
+        if (responseCode != EMTPRespCodeOK)
+            {
+            SendResponseL(responseCode);
+            result = EFalse;
+            }
+        }
+    else
+        {
+        SendResponseL(EMTPRespCodeInvalidObjectFormatCode);
+        }
+        
+    if (result)
+        {
+        iObjectSize = iObjectInfo->Uint32L(CMTPTypeObjectInfo::EObjectCompressedSize);
+        
+        if (IsTooLarge(iObjectSize))
+            {
+            SendResponseL(EMTPRespCodeObjectTooLarge);
+            result = EFalse;            
+            }
+        if(result && !CanStoreFileL(iStorageId, iObjectSize))
+            {
+            SendResponseL(EMTPRespCodeStoreFull);
+            result = EFalse;            
+            }
+        }
+
+    if (result)
+        {
+        iProtectionStatus = iObjectInfo->Uint16L(CMTPTypeObjectInfo::EProtectionStatus);
+        result = GetFullPathNameL(iObjectInfo->StringCharsL(CMTPTypeObjectInfo::EFilename));
+        if (!result)
+            {        
+            // File and/or parent pathname invalid.
+            SendResponseL(EMTPRespCodeInvalidDataset);
+            }
+        }
+
+    if (result)
+        {    
+        result &= !Exists(iFullPath);
+        if (!result)
+            {        
+            // Object with the same name already exists.
+            iNoRollback = ETrue;
+            SendResponseL(EMTPRespCodeAccessDenied);
+            }
+        }
+    
+    if (result)
+        {
+        iReceivedObject->SetUint(CMTPObjectMetaData::EFormatCode, format);
+        
+        if (iIsFolder)
+        	{
+        	iReceivedObject->SetUint(CMTPObjectMetaData::EFormatSubCode, EMTPAssociationTypeGenericFolder);
+        	}
+        	
+        TRAPD(err, CreateFsObjectL());
+        
+        if (err != KErrNone)
+            {
+            SendResponseL(ErrorToMTPError(err));
+            }
+        else
+            {
+            ReserveObjectL();
+            }
+        }
+    __FLOG(_L8("DoHandleSendObjectInfoCompleteL - Exit"));
+    return result;    
+    }
+
+/**
+Handling the completing phase of SendObjectPropList request
+@return ETrue if the specified object can be saved on the specified location, otherwise, EFalse
+*/    
+TBool CMTPSendObjectInfo::DoHandleSendObjectPropListCompleteL()
+    {
+    __FLOG(_L8("DoHandleSendObjectPropListCompleteL - Entry"));
+    TBool result(ETrue);
+    
+    TMTPResponseCode responseCode(GetParentObjectAndStorageIdL());
+    if (responseCode != EMTPRespCodeOK)
+        {
+        SendResponseL(responseCode);
+        result = EFalse;
+        }    
+
+    if (result)
+        {
+        // Any kind of association is treated as a folder
+        const TUint32 formatCode(Request().Uint32(TMTPTypeRequest::ERequestParameter3));
+        iIsFolder = (formatCode == EMTPFormatCodeAssociation);
+
+        TInt invalidParameterIndex = KErrNotFound;
+        responseCode = VerifyObjectPropListL(invalidParameterIndex);
+        result = (responseCode == EMTPRespCodeOK);    
+        if (!result)
+            {
+            TUint32 parameters[4];
+            parameters[0] = 0;
+            parameters[1] = 0;
+            parameters[2] = 0;
+            parameters[3] = invalidParameterIndex;
+            SendResponseL(responseCode, 4, parameters);
+            }
+        }
+        
+    if (result) 
+        {
+        result = !Exists(iFullPath);
+        if (!result)
+            {
+            // Object with the same name already exists.
+            iNoRollback = ETrue;
+            SendResponseL(EMTPRespCodeAccessDenied);
+            }
+        }    
+    
+    if (result)
+        {
+        if (iIsFolder)
+        	{
+        	iReceivedObject->SetUint(CMTPObjectMetaData::EFormatSubCode, EMTPAssociationTypeGenericFolder);
+        	}
+        
+        TRAPD(err, CreateFsObjectL());
+        
+        if (err != KErrNone)
+            {
+            SendResponseL(ErrorToMTPError(err));
+            }
+        else
+            {
+            ReserveObjectL();
+            }
+        }
+        
+    __FLOG(_L8("DoHandleSendObjectPropListCompleteL - Exit"));
+    return result;    
+    }
+    
+/**
+Handling the completing phase of SendObject request
+@return ETrue if the object has been successfully saved on the device, otherwise, EFalse
+*/    
+TBool CMTPSendObjectInfo::DoHandleSendObjectCompleteL()
+    {
+    __FLOG(_L8("DoHandleSendObjectCompleteL - Entry"));
+    TBool result(ETrue);
+        
+    if (!iIsFolder)
+        {        
+        delete iFileReceived;
+        iFileReceived = NULL;
+        
+        TEntry fileEntry;
+        User::LeaveIfError(iFramework.Fs().Entry(iFullPath, fileEntry));
+
+        if (fileEntry.FileSize() != iObjectSize)
+            {
+            iFramework.RouteRequestUnregisterL(iExpectedSendObjectRequest, iConnection);
+            
+            iFramework.Fs().Delete(iFullPath);
+            iFramework.ObjectMgr().UnreserveObjectHandleL(*iReceivedObject);
+            TMTPResponseCode responseCode = EMTPRespCodeObjectTooLarge;
+            if (fileEntry.FileSize() < iObjectSize)
+                {
+                responseCode = EMTPRespCodeInvalidDataset;
+                }
+            SendResponseL(responseCode);
+            result = EFalse;
+            }
+        }
+    
+    
+    // Get the result of the SendObject operation. 
+    RMTPFramework frameworkSingletons;   
+    frameworkSingletons.OpenL();
+    TUint connectionId = iConnection.ConnectionId();
+    CMTPConnectionMgr& connectionMgr = frameworkSingletons.ConnectionMgr();
+    CMTPConnection& connection = connectionMgr.ConnectionL(connectionId);
+    TInt ret = connection.GetDataReceiveResult(); 
+    frameworkSingletons.Close();
+     // SendObject is cancelled or connection is dropped.
+    if(result && (iCancelled || (ret == KErrAbort)))
+        {
+        __FLOG(_L8("It is a cancel for sendObject."));
+        iFramework.RouteRequestUnregisterL(iExpectedSendObjectRequest, iConnection);
+        Rollback();
+        SendResponseL(EMTPRespCodeTransactionCancelled);        
+        }
+    else if (result && !iCancelled)
+	    {
+	     iFramework.RouteRequestUnregisterL(iExpectedSendObjectRequest, iConnection);
+        
+        //The MTP spec states that it is not mandatory for SendObjectInfo/SendObjectPropList
+        //to be followed by a SendObject.  An object is reserved in the ObjectStore on 
+        //receiving a SendObjectInfo/SendObjectPropList request, but we only commit it 
+        //on receiving the corresponding SendObject request.  With Associations however 
+        //we commit the object straight away as the SendObject phase is often absent 
+        //with folder creation.
+
+        if(!iIsFolder)
+        	{
+			SetPropertiesL();    
+        	iFramework.ObjectMgr().CommitReservedObjectHandleL(*iReceivedObject);
+        	
+        	TParsePtrC file( iFullPath );
+        	_LIT( KTxtExtensionODF, ".odf" );
+        	if ( file.ExtPresent() && file.Ext().CompareF(KTxtExtensionODF)==0 )
+        	    {;
+        	    TUint32 DpId = iFramework.DataProviderId();
+        	    DpId = iDpSingletons.MTPUtility().GetDpId(file.Ext().Mid(1),KNullDesC);
+        	    //The data provider which owns all mimetypes of a file extension is not found 
+        	    if ( 255 == DpId )
+        	        {
+        	        HBufC* mime = NULL;
+        	        mime = iDpSingletons.MTPUtility().ContainerMimeType(iFullPath);
+        	        if ( mime != NULL )
+        	            {
+        	            DpId = iDpSingletons.MTPUtility().GetDpId(file.Ext().Mid(1),*mime);
+        	            delete mime;
+        	            mime = NULL;
+        	            }
+        	        }
+        	    if ( DpId!=iFramework.DataProviderId() && DpId!=255)
+        	        {
+        	        iReceivedObject->SetUint(CMTPObjectMetaData::EDataProviderId,DpId);
+        	        //iReceivedObject->SetUint(CMTPObjectMetaData::EFormatCode,format);
+        	        iFramework.ObjectMgr().ModifyObjectL(*iReceivedObject);
+        	        TUint32 handle = iReceivedObject->Uint(CMTPObjectMetaData::EHandle);
+        	        iSingletons.DpController().NotifyDataProvidersL(DpId,EMTPObjectAdded,(TAny*)&handle);
+        	        }
+        	    }
+        	}
+        
+        SendResponseL(EMTPRespCodeOK);
+	    }
+    __FLOG(_L8("DoHandleSendObjectCompleteL - Exit"));
+    return result;
+    }
+
+
+/**
+Get the full path name of the object to be saved
+@param aFileName, on entry, contains the file name of the object,
+on return, contains the full path name of the object to be saved
+@return ETrue if the name is valid, EFalse otherwise
+*/
+TBool CMTPSendObjectInfo::GetFullPathNameL(const TDesC& aFileName)
+    {
+    __FLOG(_L8("GetFullPathNameL - Entry"));
+    TBool result(EFalse);
+    if (aFileName.Length() > 0)
+        {
+        iFullPath = *iParentSuid;
+        if (iFullPath.Length() + aFileName.Length() < iFullPath.MaxLength())
+            {
+            iFullPath.Append(aFileName);
+            if (iIsFolder)
+                {
+                iFullPath.Append(KPathDelimiter);
+                
+                   TBool valid(EFalse);
+                if (BaflUtils::CheckWhetherFullNameRefersToFolder(iFullPath, valid) == KErrNone)
+                    {
+                    result = valid;
+                    }
+                }
+            else
+                {
+                result = iFramework.Fs().IsValidName(iFullPath);
+                }
+            }
+        }
+
+#ifdef __FLOG_ACTIVE
+    TFileName tempName;
+    tempName.Copy(iFullPath);
+    tempName.Collapse();
+    __FLOG_VA((_L8("iFullPath = %S, Result = %d"), &tempName, result));
+    __FLOG(_L8("GetFullPathNameL - Exit"));
+#endif
+    return result;
+    }
+
+/**
+Check if we can store the file on the storage
+@return ETrue if yes, otherwise EFalse
+*/
+TBool CMTPSendObjectInfo::CanStoreFileL(TUint32 aStorageId, TInt64 aObjectSize) const
+    {
+    __FLOG(_L8("CanStoreFileL - Entry"));
+    TBool result(ETrue);
+    if (aStorageId == KMTPStorageDefault)
+        {
+        aStorageId = iFramework.StorageMgr().DefaultStorageId();
+        }
+    TInt drive( iFramework.StorageMgr().DriveNumber(aStorageId) );
+    User::LeaveIfError(drive);
+    TVolumeInfo volumeInfo;
+    User::LeaveIfError(iFramework.Fs().Volume(volumeInfo, drive));
+    if (volumeInfo.iFree < aObjectSize)
+        {        
+        result = EFalse;
+        }
+    __FLOG_VA((_L8("Result = %d"), result));
+    __FLOG(_L8("CanStoreFileL - Exit"));
+    return result;        
+    }
+
+/**
+Check if the object is too large
+@return ETrue if yes, otherwise EFalse
+*/
+TBool CMTPSendObjectInfo::IsTooLarge(TUint64 aObjectSize) const
+    {
+    __FLOG(_L8("IsTooLarge - Entry"));
+    TBool ret(aObjectSize > KMaxTInt64);
+    
+    if(!ret)
+        {
+        TBuf<255> fsname;
+        TUint32 storageId = iStorageId;
+        if (storageId == KMTPStorageDefault)
+            {
+            storageId = iFramework.StorageMgr().DefaultStorageId();
+            }
+        TInt drive( iFramework.StorageMgr().DriveNumber(storageId) );
+        User::LeaveIfError(drive);
+        iFramework.Fs().FileSystemSubType(drive, fsname);        
+        
+        const TUint64 KMaxFatFileSize = 0xFFFFFFFF; //Maximal file size supported by all FAT filesystems (4GB-1)
+        _LIT(KFsFAT16, "FAT16");
+        _LIT(KFsFAT32, "FAT32");
+        
+        if((fsname.CompareF(KFsFAT16) == 0 || fsname.CompareF(KFsFAT32) == 0) && aObjectSize > KMaxFatFileSize)
+            {
+            ret = ETrue;
+            }
+        }
+    __FLOG_VA((_L8("Result = %d"), ret));
+    __FLOG(_L8("IsTooLarge - Exit"));
+    return ret;
+    }
+    
+/**
+Check if the file already exists on the storage.
+@return ETrue if file is exists, otherwise EFalse
+*/
+TBool CMTPSendObjectInfo::Exists(const TDesC& aName) const
+    {
+    __FLOG(_L8("Exists - Entry"));
+    // This detects both files and folders
+    TBool ret(EFalse); 
+    ret = BaflUtils::FileExists(iFramework.Fs(), aName);
+    __FLOG_VA((_L8("Result = %d"), ret));
+    __FLOG(_L8("Exists - Exit"));
+    return ret;
+    }
+
+/**
+Check if the property list is valid and extract properties (file name)
+@param aInvalidParameterIndex if invalid, contains the index of the property.  Undefined, if it is valid.
+@return if error, one of the error response code; otherwise EMTPRespCodeOK
+*/
+TMTPResponseCode CMTPSendObjectInfo::VerifyObjectPropListL(TInt& aInvalidParameterIndex)
+    {
+    __FLOG(_L8("VerifyObjectPropListL - Entry"));
+    TMTPResponseCode responseCode(EMTPRespCodeOK);
+    const TUint KCount(iObjectPropList->NumberOfElements());
+	iObjectPropList->ResetCursor();
+    for (TUint i(0); (i < KCount); i++)
+        {
+		CMTPTypeObjectPropListElement& KElement=iObjectPropList->GetNextElementL();
+        const TUint32 KHandle(KElement.Uint32L(CMTPTypeObjectPropListElement::EObjectHandle));
+        aInvalidParameterIndex = i;
+        if (KHandle != KMTPHandleNone)
+            {
+            responseCode = EMTPRespCodeInvalidObjectHandle;            
+            break;
+            }
+            
+        responseCode = CheckPropCodeL(KElement);
+        if (responseCode != EMTPRespCodeOK)
+            {
+            break;
+            }
+        responseCode = ExtractPropertyL(KElement);
+        if (responseCode != EMTPRespCodeOK)
+            {
+            break;
+            }        
+        }
+    __FLOG_VA((_L8("Result = 0x%04X"), responseCode));
+    __FLOG(_L8("VerifyObjectPropListL - Exit"));
+    return responseCode;        
+    }
+
+/**
+Extracts the file information from the object property list element
+@param aElement an object property list element
+@param aPropertyCode MTP property code for the element
+@return MTP response code
+*/
+TMTPResponseCode CMTPSendObjectInfo::ExtractPropertyL(const CMTPTypeObjectPropListElement& aElement)
+    {
+    __FLOG(_L8("ExtractPropertyL - Entry"));
+    TMTPResponseCode responseCode(EMTPRespCodeOK);
+    switch (aElement.Uint16L(CMTPTypeObjectPropListElement::EPropertyCode))
+        {
+    case EMTPObjectPropCodeAssociationDesc:
+        // Actually, any association is treated as a folder, and iIsFolder should already be set
+        iIsFolder = ((aElement.Uint32L(CMTPTypeObjectPropListElement::EValue) == EMTPAssociationTypeGenericFolder)||
+					(aElement.Uint32L(CMTPTypeObjectPropListElement::EValue) == EMTPAssociationTypeUndefined));
+        break;
+        
+    case EMTPObjectPropCodeObjectFileName:
+        {
+        const TDesC& KFileName = aElement.StringL(CMTPTypeObjectPropListElement::EValue);
+        if (!GetFullPathNameL(KFileName))
+            {
+            responseCode = EMTPRespCodeInvalidDataset;
+            }
+        }
+        break;
+
+    case EMTPObjectPropCodeProtectionStatus:
+        {
+        iProtectionStatus = aElement.Uint16L(CMTPTypeObjectPropListElement::EValue);
+        if (iProtectionStatus !=  EMTPProtectionNoProtection &&
+            iProtectionStatus != EMTPProtectionReadOnly)
+            {
+            responseCode = EMTPRespCodeParameterNotSupported;
+            }
+        }
+        break;
+
+    case EMTPObjectPropCodeDateModified:
+        delete iDateMod;
+        iDateMod = NULL;
+        iDateMod = aElement.StringL(CMTPTypeObjectPropListElement::EValue).AllocL();
+        break;
+    case EMTPObjectPropCodeName:
+    	iName = aElement.StringL(CMTPTypeObjectPropListElement::EValue);
+    	break;
+    default:
+        break;
+        }
+    __FLOG_VA((_L8("Result = 0x%04X"), responseCode));
+    __FLOG(_L8("ExtractPropertyL - Exit"));
+    return responseCode;    
+    }
+
+/**
+Validates the data type for a given property code.
+@param aElement an object property list element
+@param aPropertyCode MTP property code for the element
+@return EMTPRespCodeOK if the combination is valid, or another MTP response code if not
+*/
+TMTPResponseCode CMTPSendObjectInfo::CheckPropCodeL(const CMTPTypeObjectPropListElement& aElement) const
+    {
+    __FLOG(_L8("CheckPropCode - Entry"));
+    TMTPResponseCode responseCode(EMTPRespCodeOK);
+    switch(aElement.Uint16L(CMTPTypeObjectPropListElement::EPropertyCode))
+        {
+    case EMTPObjectPropCodeStorageID:
+        if (aElement.Uint16L(CMTPTypeObjectPropListElement::EDatatype) != EMTPTypeUINT32)
+            {
+            responseCode = EMTPRespCodeInvalidObjectPropFormat;
+            }
+        else if (iStorageId != aElement.Uint32L(CMTPTypeObjectPropListElement::EValue))
+            {
+            responseCode = EMTPRespCodeInvalidDataset;
+            }
+        break;
+    
+    case EMTPObjectPropCodeObjectFormat:
+        if (aElement.Uint16L(CMTPTypeObjectPropListElement::EDatatype) != EMTPTypeUINT16)
+            {
+            responseCode = EMTPRespCodeInvalidObjectPropFormat;
+            }
+        else if (Request().Uint32(TMTPTypeRequest::ERequestParameter3) != aElement.Uint16L(CMTPTypeObjectPropListElement::EValue))
+            {
+            responseCode = EMTPRespCodeInvalidDataset;
+            }
+        break;
+       
+    case EMTPObjectPropCodeObjectSize:
+        if (aElement.Uint16L(CMTPTypeObjectPropListElement::EDatatype) != EMTPTypeUINT64)
+            {
+            responseCode = EMTPRespCodeInvalidObjectPropFormat;
+            }
+        else if (iObjectSize != aElement.Uint64L(CMTPTypeObjectPropListElement::EValue))
+            {
+            responseCode = EMTPRespCodeInvalidDataset;
+            }
+        break;
+         
+    case EMTPObjectPropCodeParentObject:
+        if (aElement.Uint16L(CMTPTypeObjectPropListElement::EDatatype) != EMTPTypeUINT32)
+            {
+            responseCode = EMTPRespCodeInvalidObjectPropFormat;
+            }
+        else if (Request().Uint32(TMTPTypeRequest::ERequestParameter2) != aElement.Uint32L(CMTPTypeObjectPropListElement::EValue))
+            {
+            responseCode = EMTPRespCodeInvalidDataset;
+            }
+        break;
+
+    case EMTPObjectPropCodePersistentUniqueObjectIdentifier:
+        responseCode =     EMTPRespCodeAccessDenied;
+        break;
+
+    case EMTPObjectPropCodeProtectionStatus:
+        if (aElement.Uint16L(CMTPTypeObjectPropListElement::EDatatype) != EMTPTypeUINT16)
+            {
+            responseCode = EMTPRespCodeInvalidObjectPropFormat;
+            }                        
+        break;
+        
+    case EMTPObjectPropCodeDateModified:                    
+    case EMTPObjectPropCodeObjectFileName:    
+    case EMTPObjectPropCodeName:
+        if (aElement.Uint16L(CMTPTypeObjectPropListElement::EDatatype) != EMTPTypeString)
+            {
+            responseCode = EMTPRespCodeInvalidObjectPropFormat;
+            }
+        break;
+        
+    case EMTPObjectPropCodeNonConsumable:
+        if (aElement.Uint16L(CMTPTypeObjectPropListElement::EDatatype) != EMTPTypeUINT8)
+            {
+            responseCode = EMTPRespCodeInvalidObjectPropFormat;
+            }
+        break;
+        
+    case EMTPObjectPropCodeAssociationType:
+        if (aElement.Uint16L(CMTPTypeObjectPropListElement::EDatatype) != EMTPTypeUINT16)
+             {
+             responseCode = EMTPRespCodeInvalidObjectPropFormat;
+             }
+    	break;
+    	
+    case EMTPObjectPropCodeAssociationDesc:
+        if (aElement.Uint16L(CMTPTypeObjectPropListElement::EDatatype) != EMTPTypeUINT32)
+             {
+             responseCode = EMTPRespCodeInvalidObjectPropFormat;
+             }
+    	break;
+                
+    default:
+        responseCode = EMTPRespCodeInvalidObjectPropCode;
+        break;
+        }
+    __FLOG_VA((_L8("Result = 0x%04X"), responseCode));
+    __FLOG(_L8("CheckPropCode - Exit"));
+    return responseCode;    
+    }
+
+/**
+Validates the data type for a given property code.
+@return EMTPRespCodeOK if the parent handle matches the store id, or another MTP response code if not
+*/
+TMTPResponseCode CMTPSendObjectInfo::MatchStoreAndParentL() const
+    {
+    TMTPResponseCode ret = EMTPRespCodeOK;
+    const TUint32 storeId(Request().Uint32(TMTPTypeRequest::ERequestParameter1));
+    const TUint32 parentHandle(Request().Uint32(TMTPTypeRequest::ERequestParameter2));
+    
+    // this checking is only valid when the second parameter is not a special value.
+    if (parentHandle != KMTPHandleAll && parentHandle != KMTPHandleNone)
+        {
+        //does not take owernship
+        CMTPObjectMetaData* parentObjInfo = iRequestChecker->GetObjectInfo(parentHandle);
+        __ASSERT_DEBUG(parentObjInfo, Panic(EMTPDpObjectNull));
+        
+        if (parentObjInfo->Uint(CMTPObjectMetaData::EStorageId) != storeId)      
+            {
+            ret = EMTPRespCodeInvalidObjectHandle;
+            }
+        }
+        
+    return ret;
+    }
+
+/**
+Reserves space for and assigns an object handle to the received object, then
+sends a success response.
+*/
+void CMTPSendObjectInfo::ReserveObjectL()
+    {
+    __FLOG(_L8("ReserveObjectL - Entry"));    
+    iReceivedObject->SetUint(CMTPObjectMetaData::EStorageId, iStorageId);
+    iReceivedObject->SetDesCL(CMTPObjectMetaData::ESuid, iFullPath);
+    
+    iFramework.ObjectMgr().ReserveObjectHandleL(*iReceivedObject, iObjectSize);    
+    
+    if(iIsFolder)
+        {
+        SetPropertiesL(); 
+        iFramework.ObjectMgr().CommitReservedObjectHandleL(*iReceivedObject);       
+        }
+    else
+    	{
+    	iExpectedSendObjectRequest.SetUint32(TMTPTypeRequest::ERequestSessionID, iSessionId);
+    	iFramework.RouteRequestRegisterL(iExpectedSendObjectRequest, iConnection);
+    	}
+    TUint32 parameters[3];
+    parameters[0] = iStorageId;
+    parameters[1] = iParentHandle;
+    parameters[2] = iReceivedObject->Uint(CMTPObjectMetaData::EHandle);
+    SendResponseL(EMTPRespCodeOK, (sizeof(parameters) / sizeof(parameters[0])), parameters);
+    __FLOG(_L8("ReserveObjectL - Exit"));    
+    }
+    
+void CMTPSendObjectInfo::CreateFsObjectL()
+    {
+    if (iIsFolder)
+        {
+        User::LeaveIfError(iFramework.Fs().MkDirAll(iFullPath));
+        }
+    else
+        {
+        delete iFileReceived;
+        iFileReceived = NULL;
+        iFileReceived = CMTPTypeFile::NewL(iFramework.Fs(), iFullPath, EFileWrite);
+        iFileReceived->SetSizeL(iObjectSize);
+        }
+    }
+    
+void CMTPSendObjectInfo::Rollback()
+    {
+    if(iIsFolder)
+        {
+        __FLOG(_L8("It is a folder cancel process."));
+        iFramework.Fs().RmDir(iFullPath);
+        // If it is folder, delete it from MTP database, i.e ObjectStore.
+        TRAP_IGNORE(iFramework.ObjectMgr().RemoveObjectL(iFullPath));
+        }
+    else
+        {
+        __FLOG(_L8("It is a file cancel process."));
+        // Delete this object from file system.
+        iFramework.Fs().Delete(iFullPath);
+        TRAP_IGNORE(iFramework.ObjectMgr().UnreserveObjectHandleL(*iReceivedObject));
+        }
+    }
+    
+TMTPResponseCode CMTPSendObjectInfo::ErrorToMTPError(TInt aError) const
+    {
+    TMTPResponseCode resp = EMTPRespCodeGeneralError;
+    
+    switch (aError)
+        {
+    case KErrNone:
+        resp = EMTPRespCodeOK;
+        break;
+        
+    case KErrAccessDenied:
+        resp = EMTPRespCodeAccessDenied;
+        break;
+        
+    case KErrDiskFull:
+        resp = EMTPRespCodeStoreFull;
+        break;
+        }
+        
+    return resp;
+    }
+
+/**
+Sets the read only status on the current file to match the sent object.
+*/
+void CMTPSendObjectInfo::SetPropertiesL()
+    {
+    __FLOG(_L8("SetPropertiesL - Entry"));
+    TEntry entry;
+    User::LeaveIfError(iFramework.Fs().Entry(iFullPath, entry));  
+    
+    TUint16 assoc(EMTPAssociationTypeUndefined);
+	if (entry.IsDir())
+		{
+		assoc = EMTPAssociationTypeGenericFolder;
+		}
+	iReceivedObject->SetUint(CMTPObjectMetaData::EFormatSubCode, assoc);    
+        
+    if (iName.Length() == 0)
+    {
+    	if (entry.IsDir())
+    	{
+    		TParsePtrC pathParser(iFullPath.Left(iFullPath.Length() - 1)); // Ignore the trailing "\".
+    		iName = pathParser.Name();
+    	}
+    	else
+    	{
+        	TParsePtrC pathParser(iFullPath);
+        	iName = pathParser.Name();
+    	}
+    }    
+    
+    if (iProtectionStatus ==  EMTPProtectionNoProtection ||
+        iProtectionStatus == EMTPProtectionReadOnly)
+        {
+        entry.iAtt &= ~(KEntryAttNormal | KEntryAttReadOnly);
+        if (iProtectionStatus == EMTPProtectionNoProtection)
+            {                        
+            entry.iAtt |= KEntryAttNormal;
+            }
+        else
+            {
+            entry.iAtt |= KEntryAttReadOnly;
+            }
+        User::LeaveIfError(iFramework.Fs().SetAtt(iFullPath, entry.iAtt, ~entry.iAtt));
+        }
+    iReceivedObject->SetDesCL(CMTPObjectMetaData::EName, iName);
+    
+    __FLOG(_L8("SetPropertiesL - Exit"));
+    }
+