diff -r 000000000000 -r d0791faffa3f mtpdataproviders/mtpimagedp/src/cmtpimagedpsendobjectinfo.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mtpdataproviders/mtpimagedp/src/cmtpimagedpsendobjectinfo.cpp Tue Feb 02 01:11:40 2010 +0200 @@ -0,0 +1,1250 @@ +// 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: +// + +/** + @file + @internalTechnology +*/ + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mtpdebug.h" +#include "cmtpimagedpobjectpropertymgr.h" +#include "cmtpimagedpsendobjectinfo.h" +#include "mtpimagedppanic.h" +#include "mtpimagedpconst.h" +#include "cmtpimagedpthumbnailcreator.h" +#include "mtpimagedputilits.h" +#include "cmtpimagedp.h" + +// Class constants. +__FLOG_STMT(_LIT8(KComponent, "ImageDPSendObjectInfo");) + +const TInt RollbackFuncCnt = 3; + +const TMTPRequestElementInfo KMTPSendObjectPropListPolicy[] = + { + {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 +*/ +MMTPRequestProcessor* CMTPImageDpSendObjectInfo::NewL(MMTPDataProviderFramework& aFramework, MMTPConnection& aConnection,CMTPImageDataProvider& aDataProvider) + { + CMTPImageDpSendObjectInfo* self = new (ELeave) CMTPImageDpSendObjectInfo(aFramework, aConnection,aDataProvider); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return self; + } + +/** +Destructor +*/ +CMTPImageDpSendObjectInfo::~CMTPImageDpSendObjectInfo() + { + __FLOG(_L8("CMTPImageDpSendObjectInfo::~CMTPImageDpSendObjectInfo - Entry")); + + Rollback(); + iRollbackList.Close(); + + delete iDateMod; + delete iDateCreated; + delete iFileReceived; + delete iParentSuid; + delete iReceivedObject; + delete iObjectInfo; + delete iObjectPropList; + + __FLOG(_L8("CMTPImageDpSendObjectInfo::~CMTPImageDpSendObjectInfo - Exit")); + __FLOG_CLOSE; + } + +/** +Standard c++ constructor +@param aFramework The data provider framework +@param aConnection The connection from which the request comes +*/ +CMTPImageDpSendObjectInfo::CMTPImageDpSendObjectInfo(MMTPDataProviderFramework& aFramework, MMTPConnection& aConnection, CMTPImageDataProvider& aDataProvider) : + CMTPRequestProcessor(aFramework, aConnection, 0, NULL), + iDataProvider(aDataProvider), + iObjectPropertyMgr(aDataProvider.PropertyMgr()) + { + + } + +#define ADD_FSM_ENTRY(currentstate, event, nextstate, failedstate, action) \ + iStateMachine[currentstate][event].iNextSuccessState = nextstate; \ + iStateMachine[currentstate][event].iNextFailedState = failedstate; \ + iStateMachine[currentstate][event].iFsmAction = action + +/** +Second-phase construction +*/ +void CMTPImageDpSendObjectInfo::ConstructL() + { + __FLOG_OPEN(KMTPSubsystem, KComponent); + __FLOG(_L8("CMTPImageDpSendObjectInfo::ConstructL - Entry")); + + iRollbackList.ReserveL(RollbackFuncCnt); + iExpectedSendObjectRequest.SetUint16(TMTPTypeRequest::ERequestOperationCode, EMTPOpCodeSendObject); + iReceivedObject = CMTPObjectMetaData::NewL(); + iReceivedObject->SetUint(CMTPObjectMetaData::EDataProviderId, iFramework.DataProviderId()); + + // build FSM matrix + // process sendobjectinfo/sendobjectproplist operation + ADD_FSM_ENTRY(EStateIdle, EObjectInfoEvent, EObjectInfoCheck, EStateIdle, FsmCheckObjectInfoParamsL); + ADD_FSM_ENTRY(EStateIdle, EObjectPropListEvent, EObjectInfoCheck, EStateIdle, FsmCheckObjectPropListParamsL); + ADD_FSM_ENTRY(EStateIdle, EObjectEvent, EStateIdle, EStateIdle, FsmCheckObjectParams); + + ADD_FSM_ENTRY(EObjectInfoCheck, EObjectInfoEvent, EObjectInfoServ, EStateIdle, FsmServiceSendObjectInfoL); + ADD_FSM_ENTRY(EObjectInfoCheck, EObjectPropListEvent, EObjectInfoServ, EStateIdle, FsmServiceSendObjectPropListL); + ADD_FSM_ENTRY(EObjectInfoCheck, EObjectEvent, EStateEnd, EStateEnd, NULL); + + ADD_FSM_ENTRY(EObjectInfoServ, EObjectInfoEvent, EObjectInfoSucceed, EStateIdle, FsmDoHandleSendObjectInfoCompleteL); + ADD_FSM_ENTRY(EObjectInfoServ, EObjectPropListEvent, EObjectInfoSucceed, EStateIdle, FsmDoHandleSendObjectPropListCompleteL); + ADD_FSM_ENTRY(EObjectInfoServ, EObjectEvent, EStateEnd, EStateEnd, NULL); + + // process sendobject operation + ADD_FSM_ENTRY(EObjectInfoSucceed, EObjectInfoEvent, EObjectInfoCheck, EStateIdle, FsmCheckObjectInfoParamsL); + ADD_FSM_ENTRY(EObjectInfoSucceed, EObjectPropListEvent, EObjectInfoCheck, EStateIdle, FsmCheckObjectPropListParamsL); + ADD_FSM_ENTRY(EObjectInfoSucceed, EObjectEvent, EObjectCheck, EObjectInfoSucceed, FsmCheckObjectParams); + + ADD_FSM_ENTRY(EObjectCheck, EObjectInfoEvent, EStateEnd, EStateEnd, NULL); + ADD_FSM_ENTRY(EObjectCheck, EObjectPropListEvent, EStateEnd, EStateEnd, NULL); + ADD_FSM_ENTRY(EObjectCheck, EObjectEvent, EObjectServ, EObjectInfoSucceed, FsmServiceSendObjectL); + + ADD_FSM_ENTRY(EObjectServ, EObjectInfoEvent, EStateEnd, EStateEnd, NULL); + ADD_FSM_ENTRY(EObjectServ, EObjectPropListEvent, EStateEnd, EStateEnd, NULL); + ADD_FSM_ENTRY(EObjectServ, EObjectEvent, EStateIdle, EObjectInfoSucceed, FsmDoHandleSendObjectCompleteL); + + __FLOG(_L8("CMTPImageEnumerator::ConstructL - Exit")); + } + +TBool CMTPImageDpSendObjectInfo::FsmCheckObjectInfoParamsL(CMTPImageDpSendObjectInfo* aObject, TAny *aPtr) + { + return aObject->CheckObjectInfoParamsL(aPtr); + } + +TBool CMTPImageDpSendObjectInfo::FsmCheckObjectPropListParamsL(CMTPImageDpSendObjectInfo* aObject, TAny *aPtr) + { + return aObject->CheckObjectPropListParamsL(aPtr); + } + +TBool CMTPImageDpSendObjectInfo::FsmCheckObjectParams(CMTPImageDpSendObjectInfo* aObject, TAny *aPtr) + { + return aObject->CheckObjectParams(aPtr); + } + +TBool CMTPImageDpSendObjectInfo::FsmServiceSendObjectInfoL(CMTPImageDpSendObjectInfo* aObject, TAny *aPtr) + { + return aObject->ServiceSendObjectInfoL(aPtr); + } + +TBool CMTPImageDpSendObjectInfo::FsmServiceSendObjectPropListL(CMTPImageDpSendObjectInfo* aObject, TAny *aPtr) + { + return aObject->ServiceSendObjectPropListL(aPtr); + } + +TBool CMTPImageDpSendObjectInfo::FsmServiceSendObjectL(CMTPImageDpSendObjectInfo* aObject, TAny *aPtr) + { + return aObject->ServiceSendObjectL(aPtr); + } + +TBool CMTPImageDpSendObjectInfo::FsmDoHandleSendObjectInfoCompleteL(CMTPImageDpSendObjectInfo* aObject, TAny *aPtr) + { + return aObject->DoHandleSendObjectInfoCompleteL(aPtr); + } + +TBool CMTPImageDpSendObjectInfo::FsmDoHandleSendObjectPropListCompleteL(CMTPImageDpSendObjectInfo* aObject, TAny *aPtr) + { + return aObject->DoHandleSendObjectPropListCompleteL(aPtr); + } + +TBool CMTPImageDpSendObjectInfo::FsmDoHandleSendObjectCompleteL(CMTPImageDpSendObjectInfo* aObject, TAny *aPtr) + { + return aObject->DoHandleSendObjectCompleteL(aPtr); + } + +/** +Verify the request +@return EMTPRespCodeOK if request is verified, otherwise one of the error response codes +*/ +TMTPResponseCode CMTPImageDpSendObjectInfo::CheckRequestL() + { + __FLOG(_L8("CMTPImageDpSendObjectInfo::CheckRequestL - Entry")); + + iOperationCode = Request().Uint16(TMTPTypeRequest::ERequestOperationCode); + + switch (iOperationCode) + { + case EMTPOpCodeSendObjectInfo: + iEvent = EObjectInfoEvent; + iElementCount = sizeof(KMTPSendObjectPropListPolicy) / sizeof(TMTPRequestElementInfo); //for the checker + iElements = KMTPSendObjectPropListPolicy; + break; + + case EMTPOpCodeSendObjectPropList: + iEvent = EObjectPropListEvent; + iElementCount = sizeof(KMTPSendObjectPropListPolicy) / sizeof(TMTPRequestElementInfo); //for the checker + iElements = KMTPSendObjectPropListPolicy; + break; + + case 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); + iEvent = EObjectEvent; + iElementCount = 0; //for the checker + iElements = NULL; + break; + + default: + // Nothing to do + break; + } + + FsmAction pCheck = iStateMachine[iCurrentState][iEvent].iFsmAction; + __ASSERT_ALWAYS((pCheck != NULL), Panic(EMTPImageDpNoMatchingProcessor)); + + //coverity[var_deref_model] + TMTPResponseCode result = CMTPRequestProcessor::CheckRequestL(); + if(EMTPRespCodeOK == result) + { + TBool ret = EFalse; + TRAPD(err, ret = (*pCheck)(this, &result)); + if (ret) + { + iCurrentState = iStateMachine[iCurrentState][iEvent].iNextSuccessState; + } + else + { + iCurrentState = iStateMachine[iCurrentState][iEvent].iNextFailedState; + } + User::LeaveIfError(err); + } + __FLOG_1(_L8("CheckRequestL - Result: 0x%04x"), result); + __FLOG(_L8("CMTPImageDpSendObjectInfo::CheckRequestL - Exit")); + + return result; + } + +TBool CMTPImageDpSendObjectInfo::HasDataphase() const + { + return ETrue; + } + +TBool CMTPImageDpSendObjectInfo::CheckObjectInfoParamsL(TAny *aPtr) + { + __FLOG(_L8("CMTPImageDpSendObjectInfo::CheckObjectInfoParamsL - Entry")); + + TMTPResponseCode* ret = static_cast(aPtr); + *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 = CMTPObjectMetaData::NewLC(); + if (iFramework.ObjectMgr().ObjectL(parentHandle, *parentObjInfo)) + { + TUint32 storageId = parentObjInfo->Uint(CMTPObjectMetaData::EStorageId); + if (storeId != storageId) + { + *ret = EMTPRespCodeInvalidObjectHandle; + } + } + else + { + *ret = EMTPRespCodeInvalidObjectHandle; + } + CleanupStack::PopAndDestroy(parentObjInfo); + } + + __FLOG(_L8("CMTPImageDpSendObjectInfo::CheckObjectInfoParamsL - Exit")); + return (*ret == EMTPRespCodeOK) ? ETrue : EFalse; + } + +TBool CMTPImageDpSendObjectInfo::CheckObjectPropListParamsL(TAny *aPtr) + { + __FLOG(_L8("CMTPImageDpSendObjectInfo::CheckObjectPropListParamsL - Entry")); + TMTPResponseCode* ret = static_cast(aPtr); + *ret = EMTPRespCodeOK; + + TMTPFormatCode formatCode = static_cast(Request().Uint32(TMTPTypeRequest::ERequestParameter3)); + if (!IsFormatValid(formatCode)) + { + *ret = EMTPRespCodeInvalidObjectFormatCode; + } + else + { + iStorageId = Request().Uint32(TMTPTypeRequest::ERequestParameter1); + TUint32 objectSizeHigh = Request().Uint32(TMTPTypeRequest::ERequestParameter4); + TUint32 objectSizeLow = Request().Uint32(TMTPTypeRequest::ERequestParameter5); + iObjectSize = MAKE_TUINT64(objectSizeHigh, objectSizeLow); + + if (iStorageId == KMTPStorageDefault) + { + iStorageId = iFramework.StorageMgr().DefaultStorageId(); + } + + //if the object size is more,then report this error. + if (!CanStoreFileL(iStorageId, iObjectSize)) + { + *ret = EMTPRespCodeStoreFull; + } + } + + __FLOG(_L8("CMTPImageDpSendObjectInfo::CheckObjectPropListParamsL - Exit")); + return (*ret == EMTPRespCodeOK) ? ETrue : EFalse; + } + +TBool CMTPImageDpSendObjectInfo::CheckObjectParams(TAny *aPtr) + { + __FLOG(_L8("CMTPImageDpSendObjectInfo::CheckObjectParamsL - Entry")); + TMTPResponseCode* ret = static_cast(aPtr); + *ret = EMTPRespCodeOK; + + /** + * If the previous request is not the SendObjectInfo/SendObjectPropList/UpdateObjectPropList operation, + * the SendObject operation should failed. + */ + if ( (iPreviousTransactionID + 1) != Request().Uint32(TMTPTypeRequest::ERequestTransactionID)) + { + *ret = EMTPRespCodeNoValidObjectInfo; + } + + __FLOG(_L8("CMTPImageDpSendObjectInfo::CheckObjectParamsL - Exit")); + return (*ret == EMTPRespCodeOK) ? ETrue : EFalse; + } + +/** +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 CMTPImageDpSendObjectInfo::ServiceL() + { + __FLOG(_L8("CMTPImageDpSendObjectInfo::ServiceL - Entry")); + + FsmAction pService = iStateMachine[iCurrentState][iEvent].iFsmAction; + __ASSERT_DEBUG(pService, Panic(EMTPImageDpNoMatchingProcessor)); + + TBool ret = EFalse; + TRAPD(err, ret = (*pService)(this, NULL)); + if (ret) + { + iCurrentState = iStateMachine[iCurrentState][iEvent].iNextSuccessState; + } + else + { + iCurrentState = iStateMachine[iCurrentState][iEvent].iNextFailedState; + } + + if (err != KErrNone) + { + Rollback(); + } + User::LeaveIfError(err); + + __FLOG(_L8("CMTPImageDpSendObjectInfo::ServiceL - 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 CMTPImageDpSendObjectInfo::Match(const TMTPTypeRequest& aRequest, MMTPConnection& aConnection) const + { + __FLOG(_L8("CMTPImageDpSendObjectInfo::Match - Entry")); + TBool result = EFalse; + TUint16 operationCode = aRequest.Uint16(TMTPTypeRequest::ERequestOperationCode); + if ((operationCode == EMTPOpCodeSendObjectInfo || + operationCode == EMTPOpCodeSendObject || + operationCode == EMTPOpCodeSendObjectPropList) && + &iConnection == &aConnection) + { + result = ETrue; + } + __FLOG(_L8("CMTPImageDpSendObjectInfo::Match - Exit")); + return result; + } + +/** +Override to handle the response phase of SendObjectInfo and SendObject requests +@return EFalse +*/ +TBool CMTPImageDpSendObjectInfo::DoHandleResponsePhaseL() + { + __FLOG(_L8("CMTPImageDpSendObjectInfo::DoHandleResponsePhaseL - Entry")); + + //to check if the sending/receiving data is successful + iSuccessful = !iCancelled; + + FsmAction pResponse = iStateMachine[iCurrentState][iEvent].iFsmAction; + __ASSERT_DEBUG(pResponse, Panic(EMTPImageDpNoMatchingProcessor)); + + TBool ret = EFalse; + TRAPD(err, ret = (*pResponse)(this, &iSuccessful)) + if (ret) + { + iCurrentState = iStateMachine[iCurrentState][iEvent].iNextSuccessState; + } + else + { + iCurrentState = iStateMachine[iCurrentState][iEvent].iNextFailedState; + } + + if (err != KErrNone) + { + Rollback(); + } + User::LeaveIfError(err); + + __FLOG(_L8("CMTPImageDpSendObjectInfo::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 CMTPImageDpSendObjectInfo::DoHandleCompletingPhaseL() + { + __FLOG(_L8("CMTPImageDpSendObjectInfo::DoHandleCompletingPhaseL - Entry")); + TBool result = ETrue; + CMTPRequestProcessor::DoHandleCompletingPhaseL(); + + if (iSuccessful) + { + if (iOperationCode == EMTPOpCodeSendObjectInfo || iOperationCode == EMTPOpCodeSendObjectPropList) + { + iPreviousTransactionID = Request().Uint32(TMTPTypeRequest::ERequestTransactionID); + result = EFalse; + } + } + else + { + if (iOperationCode == EMTPOpCodeSendObject) + { + iPreviousTransactionID++; + } + result = EFalse; + } + + __FLOG(_L8("CMTPImageDpSendObjectInfo::DoHandleCompletingPhaseL - Exit")); + return result; + } + +/** +SendObjectInfo request handler +*/ +TBool CMTPImageDpSendObjectInfo::ServiceSendObjectInfoL(TAny* /*aPtr*/) + { + __FLOG(_L8("CMTPImageDpSendObjectInfo::ServiceSendObjectInfoL - Entry")); + + delete iObjectInfo; + iObjectInfo = NULL; + iObjectInfo = CMTPTypeObjectInfo::NewL(); + ReceiveDataL(*iObjectInfo); + + __FLOG(_L8("CMTPImageDpSendObjectInfo::ServiceSendObjectInfoL - Exit")); + return ETrue; + } + +/** +SendObjectPropList request handler +*/ +TBool CMTPImageDpSendObjectInfo::ServiceSendObjectPropListL(TAny* /*aPtr*/) + { + __FLOG(_L8("CMTPImageDpSendObjectInfo::ServiceSendObjectPropListL - Entry")); + + delete iObjectPropList; + iObjectPropList = NULL; + iObjectPropList = CMTPTypeObjectPropList::NewL(); + iReceivedObject->SetUint(CMTPObjectMetaData::EFormatCode, iRequest->Uint32(TMTPTypeRequest::ERequestParameter3)); + ReceiveDataL(*iObjectPropList); + + __FLOG(_L8("CMTPImageDpSendObjectInfo::ServiceSendObjectPropListL - Exit")); + return ETrue; + } + +/** +SendObject request handler +*/ +TBool CMTPImageDpSendObjectInfo::ServiceSendObjectL(TAny* /*aPtr*/) + { + __FLOG(_L8("CMTPImageDpSendObjectInfo::ServiceSendObjectL - Entry")); + + iFramework.ObjectMgr().CommitReservedObjectHandleL(*iReceivedObject); + //prepare for rollback + iRollbackList.Append(RemoveObjectFromDb); + + delete iFileReceived; + iFileReceived = NULL; + iFileReceived = CMTPTypeFile::NewL(iFramework.Fs(), iFullPath, EFileWrite); + iFileReceived->SetSizeL(iObjectSize); + + //prepare for rollback + iRollbackList.Append(RemoveObjectFromFs); + ReceiveDataL(*iFileReceived); + + __FLOG(_L8("CMTPImageDpSendObjectInfo::ServiceSendObjectL - Exit")); + return ETrue; + } + +/** +Get a default parent object, if the request does not specify a parent object. +*/ +void CMTPImageDpSendObjectInfo::GetDefaultParentObjectL() + { + __FLOG(_L8("CMTPImageDpSendObjectInfo::GetDefaultParentObjectL - Entry")); + + if (iStorageId == KMTPStorageDefault) + { + iStorageId = iFramework.StorageMgr().DefaultStorageId(); + } + TInt drive(static_cast(iFramework.StorageMgr().DriveNumber(iStorageId))); + User::LeaveIfError(drive); + + delete iParentSuid; + iParentSuid = NULL; + iParentSuid = (iFramework.StorageMgr().StorageL(iStorageId).DesC(CMTPStorageMetaData::EStorageSuid)).AllocL(); + iReceivedObject->SetUint(CMTPObjectMetaData::EParentHandle, KMTPHandleNoParent); + + __FLOG(_L8("CMTPImageDpSendObjectInfo::GetDefaultParentObjectL - Exit")); + } + +/** +Get parent object and storage id +@return EMTPRespCodeOK if successful, otherwise, EMTPRespCodeInvalidParentObject +*/ +TMTPResponseCode CMTPImageDpSendObjectInfo::GetParentObjectAndStorageIdL() + { + __FLOG(_L8("CMTPImageDpSendObjectInfo::GetParentObjectAndStorageIdL - Entry")); + __ASSERT_DEBUG(iRequestChecker, Panic(EMTPImageDpRequestCheckNull)); + + 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("ParentSuid = %S"), iParentSuid)); + __FLOG(_L8("CMTPImageDpSendObjectInfo::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 CMTPImageDpSendObjectInfo::DoHandleSendObjectInfoCompleteL(TAny* /*aPtr*/) + { + __FLOG(_L8("CMTPImageDpSendObjectInfo::DoHandleSendObjectInfoCompleteL - Entry")); + + TBool result(ETrue); + TUint16 format(iObjectInfo->Uint16L(CMTPTypeObjectInfo::EObjectFormat)); + + result = IsFormatValid(TMTPFormatCode(format)); + + if (result) + { + delete iDateMod; + iDateMod = NULL; + iDateMod = iObjectInfo->StringCharsL(CMTPTypeObjectInfo::EDateModified).AllocL(); + delete iDateCreated; + iDateCreated = NULL; + iDateCreated = iObjectInfo->StringCharsL(CMTPTypeObjectInfo::EDateCreated).AllocL(); + + TMTPResponseCode responseCode(GetParentObjectAndStorageIdL()); + if (responseCode != EMTPRespCodeOK) + { + SendResponseL(responseCode); + result = EFalse; + } + } + else + { + SendResponseL(EMTPRespCodeInvalidObjectFormatCode); + } + + if (result) + { + iObjectSize = iObjectInfo->Uint32L(CMTPTypeObjectInfo::EObjectCompressedSize); + if(!CanStoreFileL(iStorageId, iObjectSize)) + { + SendResponseL(EMTPRespCodeStoreFull); + result = EFalse; + } + } + + if (result) + { + iProtectionStatus = iObjectInfo->Uint16L(CMTPTypeObjectInfo::EProtectionStatus); + if (iProtectionStatus != EMTPProtectionNoProtection && + iProtectionStatus != EMTPProtectionReadOnly) + { + SendResponseL(EMTPRespCodeParameterNotSupported); + result = EFalse; + } + } + + if (result) + { + result = GetFullPathName(iObjectInfo->StringCharsL(CMTPTypeObjectInfo::EFilename)); + if (!result) + { + // File and/or parent pathname invalid. + SendResponseL(EMTPRespCodeInvalidDataset); + } + } + + if (result) + { + result = !Exists(iFullPath); + if (!result) + { + SendResponseL(EMTPRespCodeAccessDenied); + } + else + { + ReserveObjectL(); + imageWidth = iObjectInfo->Uint32L(CMTPTypeObjectInfo::EImagePixWidth); + imageHeight = iObjectInfo->Uint32L(CMTPTypeObjectInfo::EImagePixHeight); + imageBitDepth = iObjectInfo->Uint32L(CMTPTypeObjectInfo::EImageBitDepth); + iReceivedObject->SetUint(CMTPObjectMetaData::EFormatCode, format); + SetPropertiesL(); + ReturnResponseL(); + } + } + + iSuccessful = result; + __FLOG(_L8("CMTPImageDpSendObjectInfo::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 CMTPImageDpSendObjectInfo::DoHandleSendObjectPropListCompleteL(TAny* /*aPtr*/) + { + __FLOG(_L8("CMTPImageDpSendObjectInfo::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)); + + 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. + SendResponseL(EMTPRespCodeAccessDenied); + } + } + + if (result) + { + //the EFormatCode property has been set in ServiceSendObjectPropListL() function + ReserveObjectL(); + SetPropertiesL(); + ReturnResponseL(); + } + + iSuccessful = result; + __FLOG(_L8("CMTPImageDpSendObjectInfo::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 CMTPImageDpSendObjectInfo::DoHandleSendObjectCompleteL(TAny* /*aPtr*/) + { + __FLOG(_L8("CMTPImageDpSendObjectInfo::DoHandleSendObjectCompleteL - Entry")); + TBool result(ETrue); + +#ifdef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API + TInt64 objectsize = 0; +#else + TInt objectsize = 0; +#endif + + iFileReceived->File().Size(objectsize); + + if (objectsize != iObjectSize) + { + __FLOG_VA((_L8("object sizes differ %lu != %lu"), objectsize, iObjectSize)); + iFramework.RouteRequestUnregisterL(iExpectedSendObjectRequest, iConnection); + Rollback(); + + TMTPResponseCode responseCode = EMTPRespCodeObjectTooLarge; + if (objectsize < iObjectSize) + { + responseCode = EMTPRespCodeInvalidDataset; + } + SendResponseL(responseCode); + result = EFalse; + } + + // SendObject is cancelled or connection is dropped. + if(result && iCancelled) + { + __FLOG(_L8("It is a cancel for sendObject.")); + iFramework.RouteRequestUnregisterL(iExpectedSendObjectRequest, iConnection); + Rollback(); + SendResponseL(EMTPRespCodeTransactionCancelled); + } + else if (result && !iCancelled) + { + if (iProtectionStatus == EMTPProtectionNoProtection || + iProtectionStatus == EMTPProtectionReadOnly) + { + TUint attValue = 0; + User::LeaveIfError(iFileReceived->File().Att(attValue)); + attValue &= ~(KEntryAttNormal | KEntryAttReadOnly); + + if (iProtectionStatus == EMTPProtectionNoProtection) + { + attValue |= KEntryAttNormal; + } + else + { + attValue |= KEntryAttReadOnly; + } + User::LeaveIfError(iFileReceived->File().SetAtt(attValue, ~attValue)); + } + + //update datemodified property. + if(iDateMod != NULL && iDateMod->Length()) + { + TTime modifiedTime; + iObjectPropertyMgr.ConvertMTPTimeStr2TTimeL(*iDateMod, modifiedTime); + User::LeaveIfError(iFileReceived->File().SetModified(modifiedTime)); + } + + 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. + + CleanUndoList(); + SendResponseL(EMTPRespCodeOK); + } + + delete iFileReceived; + iFileReceived = NULL; + + iSuccessful = result; + __FLOG(_L8("CMTPImageDpSendObjectInfo::DoHandleSendObjectCompleteL - Exit")); + return result; + } + +void CMTPImageDpSendObjectInfo::UnreserveObject(CMTPImageDpSendObjectInfo* aObject) + { + aObject->UnreserveObject(); + } + +void CMTPImageDpSendObjectInfo::RemoveObjectFromFs(CMTPImageDpSendObjectInfo* aObject) + { + aObject->RemoveObjectFromFs(); + } + +void CMTPImageDpSendObjectInfo::RemoveObjectFromDb(CMTPImageDpSendObjectInfo* aObject) + { + aObject->RemoveObjectFromDb(); + } + +void CMTPImageDpSendObjectInfo::UnreserveObject() + { + __ASSERT_DEBUG(iReceivedObject, Panic(EMTPImageDpObjectNull)); + TRAP_IGNORE(iFramework.ObjectMgr().UnreserveObjectHandleL(*iReceivedObject)); + } + +void CMTPImageDpSendObjectInfo::RemoveObjectFromFs() + { + delete iFileReceived; + iFileReceived = NULL; + TInt err = iFramework.Fs().Delete(iFullPath); + if (err != KErrNone) + { + //add Suid to deleteobjectlist + iDataProvider.AppendDeleteObjectsArrayL(iFullPath); + } + } + +void CMTPImageDpSendObjectInfo::RemoveObjectFromDb() + { + /** + * remove all cached properties if rollback occured. + */ + TRAP_IGNORE( + iFramework.ObjectMgr().RemoveObjectL(iReceivedObject->Uint(CMTPObjectMetaData::EHandle)); + iObjectPropertyMgr.ClearCacheL(); + ); + } + +void CMTPImageDpSendObjectInfo::ReturnResponseL() + { + 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); + } + +/** +*/ +TBool CMTPImageDpSendObjectInfo::IsFormatValid(TMTPFormatCode aFormat) const + { + __FLOG_1(_L8("CMTPImageDpSendObjectInfo::IsFormatValid - Format: 0x%04x"), aFormat); + TInt count(sizeof(KMTPValidCodeExtensionMappings) / sizeof(KMTPValidCodeExtensionMappings[0])); + for(TInt i=0; i < count; i++) + { + if (KMTPValidCodeExtensionMappings[i].iFormatCode == aFormat) + { + return ETrue; + } + } + __FLOG(_L8("CMTPImageDpSendObjectInfo::IsFormatValid - Exit")); + return EFalse; + } + +/** +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 CMTPImageDpSendObjectInfo::GetFullPathName(const TDesC& aFileName) + { + __FLOG_1(_L8("CMTPImageDpSendObjectInfo::GetFullPathNameL - FileName: %S"), &aFileName); + TBool result(EFalse); + if (aFileName.Length() > 0) + { + iFullPath = *iParentSuid; + if (iFullPath.Length() + aFileName.Length() < iFullPath.MaxLength()) + { + iFullPath.Append(aFileName); + result = iFramework.Fs().IsValidName(iFullPath); + } + __FLOG_1(_L16("FullPath: %S"), &iFullPath); + } + + __FLOG(_L8("CMTPImageDpSendObjectInfo::GetFullPathNameL - Exit")); + return result; + } + +/** +Check if we can store the file on the storage +@return ETrue if yes, otherwise EFalse +*/ +TBool CMTPImageDpSendObjectInfo::CanStoreFileL(TUint32 aStorageId, TInt64 aObjectSize) const + { + __FLOG(_L8("CMTPImageDpSendObjectInfo::CanStoreFileL - Entry")); + TBool result(ETrue); + if (aStorageId == KMTPStorageDefault) + { + aStorageId = iFramework.StorageMgr().DefaultStorageId(); + } + + TDriveNumber drive(static_cast(iFramework.StorageMgr().DriveNumber(aStorageId))); + User::LeaveIfError(drive); + TVolumeInfo volumeInfo; + User::LeaveIfError(iFramework.Fs().Volume(volumeInfo, drive)); + if (volumeInfo.iFree < aObjectSize) + { + result = EFalse; + } + __FLOG(_L8("CMTPImageDpSendObjectInfo::CanStoreFileL - Exit")); + return result; + } + +/** +Check if the file already exists on the storage. +@return ETrue if file is exists, otherwise EFalse +*/ +TBool CMTPImageDpSendObjectInfo::Exists(const TDesC& aName) const + { + __FLOG(_L8("CMTPImageDpSendObjectInfo::Exists - Entry")); + // This detects both files and folders + TBool ret(EFalse); + ret = BaflUtils::FileExists(iFramework.Fs(), aName); + __FLOG_VA((_L16("Exists: %S (%d)"), &aName, ret)); + __FLOG(_L8("CMTPImageDpSendObjectInfo::IsTooLarge - 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 CMTPImageDpSendObjectInfo::VerifyObjectPropListL(TInt& aInvalidParameterIndex) + { + __FLOG(_L8("CMTPImageDpSendObjectInfo::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("CMTPImageDpSendObjectInfo::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 CMTPImageDpSendObjectInfo::ExtractPropertyL(const CMTPTypeObjectPropListElement& aElement) + { + __FLOG(_L8("CMTPImageDpSendObjectInfo::ExtractPropertyL - Entry")); + TMTPResponseCode responseCode(EMTPRespCodeOK); + switch (aElement.Uint16L(CMTPTypeObjectPropListElement::EPropertyCode)) + { + case EMTPObjectPropCodeObjectFileName: + { + const TDesC& KFileName = aElement.StringL(CMTPTypeObjectPropListElement::EValue); + if (!GetFullPathName(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 EMTPObjectPropCodeDateCreated: + delete iDateCreated; + iDateCreated = NULL; + iDateCreated = aElement.StringL(CMTPTypeObjectPropListElement::EValue).AllocL(); + break; + + case EMTPObjectPropCodeName: + iName = aElement.StringL(CMTPTypeObjectPropListElement::EValue); + break; + + case EMTPObjectPropCodeObjectFormat: + iFormatCode = aElement.Uint16L(CMTPTypeObjectPropListElement::EValue); + if (iFormatCode != EMTPFormatCodeEXIFJPEG) + { + responseCode = EMTPRespCodeInvalidObjectPropFormat; + } + break; + + case EMTPObjectPropCodeWidth: + imageWidth = aElement.Uint32L(CMTPTypeObjectPropListElement::EValue); + break; + + case EMTPObjectPropCodeHeight: + imageHeight = aElement.Uint32L(CMTPTypeObjectPropListElement::EValue); + break; + + case EMTPObjectPropCodeImageBitDepth: + imageBitDepth = aElement.Uint32L(CMTPTypeObjectPropListElement::EValue); + break; + + case EMTPObjectPropCodeNonConsumable: + iNonConsumable = aElement.Uint8L(CMTPTypeObjectPropListElement::EValue); + break; + + default: + break; + } + __FLOG_VA((_L8("Result = 0x%04X"), responseCode)); + __FLOG(_L8("CMTPImageDpSendObjectInfo::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 CMTPImageDpSendObjectInfo::CheckPropCodeL(const CMTPTypeObjectPropListElement& aElement) const + { + __FLOG(_L8("CMTPImageDpSendObjectInfo::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 EMTPObjectPropCodeRepresentativeSampleFormat: + case EMTPObjectPropCodeProtectionStatus: + if (aElement.Uint16L(CMTPTypeObjectPropListElement::EDatatype) != EMTPTypeUINT16) + { + responseCode = EMTPRespCodeInvalidObjectPropFormat; + } + break; + + case EMTPObjectPropCodeDateCreated: + case EMTPObjectPropCodeDateModified: + case EMTPObjectPropCodeObjectFileName: + case EMTPObjectPropCodeName: + if (aElement.Uint16L(CMTPTypeObjectPropListElement::EDatatype) != EMTPTypeString) + { + responseCode = EMTPRespCodeInvalidObjectPropFormat; + } + break; + + case EMTPObjectPropCodeWidth: + case EMTPObjectPropCodeHeight: + case EMTPObjectPropCodeImageBitDepth: + case EMTPObjectPropCodeRepresentativeSampleSize: + case EMTPObjectPropCodeRepresentativeSampleHeight: + case EMTPObjectPropCodeRepresentativeSampleWidth: + if (aElement.Uint16L(CMTPTypeObjectPropListElement::EDatatype) != EMTPTypeUINT32) + { + responseCode = EMTPRespCodeInvalidObjectPropFormat; + } + break; + case EMTPObjectPropCodeNonConsumable: + if (aElement.Uint16L(CMTPTypeObjectPropListElement::EDatatype) != EMTPTypeUINT8) + { + responseCode = EMTPRespCodeInvalidObjectPropFormat; + } + break; + default: + responseCode = EMTPRespCodeInvalidObjectPropCode; + break; + } + __FLOG_VA((_L8("Result = 0x%04X"), responseCode)); + __FLOG(_L8("CMTPImageDpSendObjectInfo::CheckPropCode - Exit")); + return responseCode; + } + +/** +Reserves space for and assigns an object handle to the received object, then +sends a success response. +*/ +void CMTPImageDpSendObjectInfo::ReserveObjectL() + { + __FLOG(_L8("CMTPImageDpSendObjectInfo::ReserveObjectL - Entry")); + + iReceivedObject->SetUint(CMTPObjectMetaData::EStorageId, iStorageId); + iFramework.ObjectMgr().ReserveObjectHandleL(*iReceivedObject, iObjectSize); + + // prepare for rollback + iRollbackList.Append(UnreserveObject); + __FLOG(_L8("CMTPImageDpSendObjectInfo::ReserveObjectL - Exit")); + } + +/** +Sets the read only status on the current file to match the sent object. +*/ +void CMTPImageDpSendObjectInfo::SetPropertiesL() + { + __FLOG(_L8("CMTPImageDpSendObjectInfo::SetPropertiesL - Entry")); + + iObjectPropertyMgr.SetCurrentObjectL(*iReceivedObject, ETrue, ETrue); + iReceivedObject->SetDesCL(CMTPObjectMetaData::ESuid, iFullPath); + if (iName.Length() == 0) + { + TParsePtrC pathParser(iFullPath); + iName = pathParser.Name(); + } + iObjectPropertyMgr.SetPropertyL(EMTPObjectPropCodeName, iName); + iObjectPropertyMgr.SetPropertyL(EMTPObjectPropCodeProtectionStatus, iProtectionStatus); + iObjectPropertyMgr.SetPropertyL(EMTPObjectPropCodeWidth, imageWidth); + iObjectPropertyMgr.SetPropertyL(EMTPObjectPropCodeHeight, imageHeight); + iObjectPropertyMgr.SetPropertyL(EMTPObjectPropCodeImageBitDepth, imageBitDepth); + iObjectPropertyMgr.SetPropertyL(EMTPObjectPropCodeNonConsumable, iNonConsumable); + + if(iDateCreated != NULL && iDateCreated->Length()) + {//currently image dp can not support this property + iObjectPropertyMgr.SetPropertyL(EMTPObjectPropCodeDateCreated, *iDateCreated); + } + + __FLOG(_L8("CMTPImageDpSendObjectInfo::SetPropertiesL - Exit")); + } + +void CMTPImageDpSendObjectInfo::Rollback() + { + __FLOG(_L8("CMTPImageDpSendObjectInfo::Rollback - Entry")); + + TInt count = iRollbackList.Count(); + while(--count >= 0) + { + TRAP_IGNORE((*iRollbackList[count])(this)); + } + iRollbackList.Reset(); + + __FLOG(_L8("CMTPImageDpSendObjectInfo::Rollback - Exit")); + } + +void CMTPImageDpSendObjectInfo::CleanUndoList() + { + __FLOG(_L8("CMTPImageDpSendObjectInfo::CleanUndoList - Entry")); + + iRollbackList.Reset(); + + __FLOG(_L8("CMTPImageDpSendObjectInfo::CleanUndoList - Exit")); + }