--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mtpdataproviders/mtppictbridgedp/src/cmtppictbridgedpsendobjectinfo.cpp Tue Feb 02 01:11:40 2010 +0200
@@ -0,0 +1,984 @@
+// Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+
+#include <f32file.h>
+#include <bautils.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/mmtpconnection.h>
+#include <mtp/tmtptyperequest.h>
+#include "ptpdef.h"
+#include "cmtppictbridgedpsendobjectinfo.h"
+#include "mtppictbridgedppanic.h"
+#include "mtppictbridgedpconst.h"
+#include "cmtppictbridgeprinter.h"
+#include "cptpserver.h"
+#include "cmtpconnection.h"
+#include "cmtpconnectionmgr.h"
+
+/**
+Verification data for the SendObjectInfo request
+*/
+const TMTPRequestElementInfo KMTPSendObjectInfoPolicy[] =
+ {
+ {TMTPTypeRequest::ERequestParameter1, EMTPElementTypeStorageId, EMTPElementAttrWrite, 1, 0, 0},
+ {TMTPTypeRequest::ERequestParameter2, EMTPElementTypeObjectHandle, EMTPElementAttrWrite, 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* CMTPPictBridgeDpSendObjectInfo::NewL(
+ MMTPDataProviderFramework& aFramework,
+ MMTPConnection& aConnection,
+ CMTPPictBridgeDataProvider& aDataProvider)
+ {
+ CMTPPictBridgeDpSendObjectInfo* self = new (ELeave) CMTPPictBridgeDpSendObjectInfo(aFramework, aConnection, aDataProvider);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+/**
+Destructor
+*/
+CMTPPictBridgeDpSendObjectInfo::~CMTPPictBridgeDpSendObjectInfo()
+ {
+ __FLOG_VA((_L8(">> CMTPPictBridgeDpSendObjectInfo::~CMTPPictBridgeDpSendObjectInfo iProgress=%d iNoRollback=%d "), iProgress, iNoRollback));
+
+ if ((iProgress == EObjectInfoSucceed ||
+ iProgress == EObjectInfoFail ||
+ iProgress == EObjectInfoInProgress) && !iNoRollback)
+ {
+ // Not finished SendObjectInfo/PropList SendObject pair detected.
+ Rollback();
+ }
+
+ iDpSingletons.Close();
+ delete iDateModP;
+ delete iFileReceivedP;
+ delete iParentSuidP;
+ delete iReceivedObjectP;
+ delete iObjectInfoP;
+ delete iObjectPropList;
+
+ __FLOG(_L8("<< CMTPPictBridgeDpSendObjectInfo::~CMTPPictBridgeDpSendObjectInfo"));
+ __FLOG_CLOSE;
+ }
+
+/**
+Standard c++ constructor
+@param aFramework The data provider framework
+@param aConnection The connection from which the request comes
+*/
+CMTPPictBridgeDpSendObjectInfo::CMTPPictBridgeDpSendObjectInfo(MMTPDataProviderFramework& aFramework, MMTPConnection& aConnection, CMTPPictBridgeDataProvider& aDataProvider):
+ CMTPRequestProcessor(aFramework, aConnection, 0, NULL),
+ iPictBridgeDP(aDataProvider)
+ {
+ }
+
+/**
+Verify the request
+@return EMTPRespCodeOK if request is verified, otherwise one of the error response codes
+*/
+TMTPResponseCode CMTPPictBridgeDpSendObjectInfo::CheckRequestL()
+ {
+ __FLOG(_L8(">> CMTPPictBridgeDpSendObjectInfo::CheckRequestL"));
+ 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;
+ }
+
+ if (iElements)
+ {
+ result = CMTPRequestProcessor::CheckRequestL();
+ }
+
+ if ( EMTPRespCodeOK == result )
+ {
+ result = MatchStoreAndParentL();
+ }
+
+ if (( EMTPRespCodeOK == result ) && ( EMTPOpCodeSendObjectPropList == iOperationCode ))
+ {
+ iStorageId = Request().Uint32(TMTPTypeRequest::ERequestParameter1);
+ TUint32 objectSizeHigh = Request().Uint32(TMTPTypeRequest::ERequestParameter4);
+ TUint32 objectSizeLow = Request().Uint32(TMTPTypeRequest::ERequestParameter5);
+ iObjectSize = MAKE_TUINT64(objectSizeHigh, objectSizeLow);
+ if (IsTooLarge(iObjectSize))
+ {
+ result = EMTPRespCodeObjectTooLarge;
+ }
+ if(result && !CanStoreFileL(iStorageId, iObjectSize))
+ {
+ result = EMTPRespCodeStoreFull;
+ }
+ }
+ // If the previous request is not SendObjectInfo, SendObject fails
+ if (result == EMTPRespCodeOK && iOperationCode == EMTPOpCodeSendObject)
+ {
+ if (iPreviousTransactionID + 1 != Request().Uint32(TMTPTypeRequest::ERequestTransactionID))
+ {
+ result = EMTPRespCodeNoValidObjectInfo;
+ }
+ }
+
+ __FLOG_VA((_L8("<< CMTPPictBridgeDpSendObjectInfo::CheckRequestL 0x%04x"), result));
+
+ return result;
+ }
+
+TBool CMTPPictBridgeDpSendObjectInfo::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 CMTPPictBridgeDpSendObjectInfo::ServiceL()
+ {
+ __FLOG(_L8(">> CMTPPictBridgeDpSendObjectInfo::ServiceL"));
+ if (iProgress == EObjectNone)
+ {
+ if ( EMTPOpCodeSendObjectInfo == iOperationCode )
+ {
+ ServiceSendObjectInfoL();
+ }
+ else
+ {
+ ServiceSendObjectPropListL();
+ }
+ }
+ else
+ {
+ ServiceSendObjectL();
+ }
+ __FLOG(_L8("<< CMTPPictBridgeDpSendObjectInfo::ServiceL"));
+ }
+
+/**
+Second-phase construction
+*/
+void CMTPPictBridgeDpSendObjectInfo::ConstructL()
+ {
+ __FLOG_OPEN(KMTPSubsystem, KComponent);
+ __FLOG(_L8(">> CMTPPictBridgeDpSendObjectInfo::ConstructL"));
+ iExpectedSendObjectRequest.SetUint16(TMTPTypeRequest::ERequestOperationCode, EMTPOpCodeSendObject);
+ iReceivedObjectP = CMTPObjectMetaData::NewL();
+ iReceivedObjectP->SetUint(CMTPObjectMetaData::EDataProviderId, iFramework.DataProviderId());
+ iDpSingletons.OpenL(iFramework);
+ iNoRollback = EFalse;
+ __FLOG(_L8("<< CMTPPictBridgeDpSendObjectInfo::ConstructL"));
+ }
+
+/**
+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 CMTPPictBridgeDpSendObjectInfo::Match(const TMTPTypeRequest& aRequest, MMTPConnection& aConnection) const
+ {
+ __FLOG(_L8(">> CMTPPictBridgeDpSendObjectInfo::Match"));
+ TBool result = EFalse;
+ TUint16 operationCode = aRequest.Uint16(TMTPTypeRequest::ERequestOperationCode);
+ if ((operationCode == EMTPOpCodeSendObjectInfo ||
+ operationCode == EMTPOpCodeSendObject ||
+ operationCode == EMTPOpCodeSendObjectPropList) &&
+ &iConnection == &aConnection)
+ {
+ result = ETrue;
+ }
+ __FLOG(_L8("<< CMTPPictBridgeDpSendObjectInfo::Match"));
+ return result;
+ }
+
+/**
+Override to handle the response phase of SendObjectInfo and SendObject requests
+@return EFalse
+*/
+TBool CMTPPictBridgeDpSendObjectInfo::DoHandleResponsePhaseL()
+ {
+ __FLOG_VA((_L8(">> CMTPPictBridgeDpSendObjectInfo::DoHandleResponsePhaseL iProgress==%d opCode==0x%x"),iProgress, iOperationCode));
+ //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);
+ }
+ else if (iProgress == ESendObjectInProgress)
+ {
+ successful = DoHandleSendObjectCompleteL();
+ iProgress = (successful ? ESendObjectSucceed : ESendObjectFail);
+ }
+ __FLOG(_L8("<< CMTPPictBridgeDpSendObjectInfo::DoHandleResponsePhaseL"));
+ return EFalse;
+ }
+
+/**
+Override to handle the completing phase of SendObjectInfo and SendObject requests
+@return ETrue if succesfully received the file, otherwise EFalse
+*/
+TBool CMTPPictBridgeDpSendObjectInfo::DoHandleCompletingPhaseL()
+ {
+ __FLOG_VA((_L8(">> CMTPPictBridgeDpSendObjectInfo::DoHandleCompletingPhaseL iProgress==%d opCode==0x%x"),iProgress, iOperationCode));
+ TBool result = ETrue;
+ CMTPRequestProcessor::DoHandleCompletingPhaseL();
+ if (iProgress == EObjectInfoSucceed)
+ {
+ if (( iOperationCode == EMTPOpCodeSendObjectInfo ) || ( iOperationCode == EMTPOpCodeSendObjectPropList ))
+ {
+ iPreviousTransactionID = Request().Uint32(TMTPTypeRequest::ERequestTransactionID);
+ }
+ result = EFalse;
+ }
+ else if (iProgress == ESendObjectSucceed)
+ {
+ iPictBridgeDP.PtpServer()->Printer()->DpsObjectReceived(iReceivedObjectP->Uint(CMTPObjectMetaData::EHandle));
+ }
+ else if (iProgress == ESendObjectFail)
+ {
+ if (iOperationCode == EMTPOpCodeSendObject)
+ {
+ iPreviousTransactionID++;
+ }
+ iProgress = EObjectInfoSucceed;
+ result = EFalse;
+ }
+
+ __FLOG(_L8("<< CMTPPictBridgeDpSendObjectInfo::DoHandleCompletingPhaseL"));
+ 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 CMTPPictBridgeDpSendObjectInfo::CheckSendingStateL()
+ {
+ __FLOG(_L8(">> CMTPPictBridgeDpSendObjectInfo::CheckSendingStateL"));
+ 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)
+ {
+ // Not finished SendObjectInfo/SendObject pair detected, need to remove the object reservation that was created, unless the object already existed
+ if (!iNoRollback )
+ {
+ __FLOG(_L8(" CMTPPictBridgeDpSendObjectInfo::CheckSendingStateL ... Rolling back!"));
+ Rollback();
+ }
+
+ delete iObjectInfoP;
+ iObjectInfoP = NULL;
+ delete iObjectPropList;
+ iObjectPropList = NULL;
+ iProgress = EObjectNone;
+ }
+ }
+ else
+ {
+ Panic(EMTPPictBridgeDpSendObjectStateInvalid);
+ }
+ __FLOG(_L8("<< CMTPPictBridgeDpSendObjectInfo::CheckSendingStateL"));
+ return result;
+ }
+
+/**
+SendObjectInfo request handler
+*/
+void CMTPPictBridgeDpSendObjectInfo::ServiceSendObjectInfoL()
+ {
+ delete iObjectInfoP;
+ iObjectInfoP = NULL;
+ iObjectInfoP = CMTPTypeObjectInfo::NewL();
+ ReceiveDataL(*iObjectInfoP);
+ iProgress = EObjectInfoInProgress;
+ }
+
+/**
+ServiceSendObjectPropListL request handler
+*/
+void CMTPPictBridgeDpSendObjectInfo::ServiceSendObjectPropListL()
+ {
+ delete iObjectPropList;
+ iObjectPropList = NULL;
+ iObjectPropList = CMTPTypeObjectPropList::NewL();
+ ReceiveDataL( *iObjectPropList );
+ iProgress = EObjectInfoInProgress;
+ }
+
+/**
+SendObject request handler
+*/
+void CMTPPictBridgeDpSendObjectInfo::ServiceSendObjectL()
+ {
+ ReceiveDataL(*iFileReceivedP);
+ iProgress = ESendObjectInProgress;
+ }
+
+/**
+Get a default parent object, if the request does not specify a parent object.
+*/
+void CMTPPictBridgeDpSendObjectInfo::GetDefaultParentObjectL()
+ {
+ __FLOG(_L8(">> CMTPPictBridgeDpSendObjectInfo::GetDefaultParentObjectL"));
+
+ if (iStorageId == KMTPStorageDefault)
+ {
+ iStorageId = iFramework.StorageMgr().DefaultStorageId();
+ }
+ TInt drive(static_cast<TDriveNumber>(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\
+
+ delete iParentSuidP;
+ iParentSuidP = NULL;
+ iParentSuidP=(iFramework.StorageMgr().StorageL(iStorageId).DesC(CMTPStorageMetaData::EStorageSuid)).AllocL();
+ iReceivedObjectP->SetUint(CMTPObjectMetaData::EParentHandle, KMTPHandleNoParent);
+ __FLOG(_L8("<< CMTPPictBridgeDpSendObjectInfo::GetDefaultParentObjectL"));
+ }
+
+/**
+Get parent object and storage id
+@return EMTPRespCodeOK if successful, otherwise, EMTPRespCodeInvalidParentObject
+*/
+TMTPResponseCode CMTPPictBridgeDpSendObjectInfo::GetParentObjectAndStorageIdL()
+ {
+ __FLOG(_L8(">> CMTPPictBridgeDpSendObjectInfo::GetParentObjectAndStorageIdL"));
+ __ASSERT_DEBUG(iRequestChecker, Panic(EMTPPictBridgeDpRequestCheckNull));
+
+ iStorageId = Request().Uint32(TMTPTypeRequest::ERequestParameter1);
+ iParentHandle = Request().Uint32(TMTPTypeRequest::ERequestParameter2);
+ //does not take ownership
+ CMTPObjectMetaData* parentObjectInfo = iRequestChecker->GetObjectInfo(iParentHandle);
+
+ if (!parentObjectInfo)
+ {
+ GetDefaultParentObjectL();
+ }
+ else
+ {
+ delete iParentSuidP;
+ iParentSuidP = NULL;
+ iParentSuidP = parentObjectInfo->DesC(CMTPObjectMetaData::ESuid).AllocL();
+ iReceivedObjectP->SetUint(CMTPObjectMetaData::EParentHandle, iParentHandle);
+ }
+
+ __FLOG_VA((_L16("<< CMTPPictBridgeDpSendObjectInfo::GetParentObjectAndStorageIdL %S"), iParentSuidP));
+ 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 CMTPPictBridgeDpSendObjectInfo::DoHandleSendObjectInfoCompleteL()
+ {
+ __FLOG(_L8(">> CMTPPictBridgeDpSendObjectInfo::DoHandleSendObjectInfoCompleteL"));
+ TBool result(ETrue);
+ TUint16 format(iObjectInfoP->Uint16L(CMTPTypeObjectInfo::EObjectFormat));
+
+ result = IsFormatValid(TMTPFormatCode(format));
+
+ if (result)
+ {
+ delete iDateModP;
+ iDateModP = NULL;
+ iDateModP = iObjectInfoP->StringCharsL(CMTPTypeObjectInfo::EDateModified).AllocL();
+
+ TMTPResponseCode responseCode(GetParentObjectAndStorageIdL());
+ if (responseCode != EMTPRespCodeOK)
+ {
+ SendResponseL(responseCode);
+ result = EFalse;
+ }
+ }
+ else
+ {
+ SendResponseL(EMTPRespCodeInvalidObjectFormatCode);
+ }
+
+ if (result)
+ {
+ iObjectSize = iObjectInfoP->Uint32L(CMTPTypeObjectInfo::EObjectCompressedSize);
+ if (IsTooLarge(iObjectSize))
+ {
+ SendResponseL(EMTPRespCodeObjectTooLarge);
+ result = EFalse;
+ }
+ if(result && !CanStoreFileL(iStorageId, iObjectSize))
+ {
+ SendResponseL(EMTPRespCodeStoreFull);
+ result = EFalse;
+ }
+ }
+
+ if (result)
+ {
+ iProtectionStatus = iObjectInfoP->Uint16L(CMTPTypeObjectInfo::EProtectionStatus);
+ if (iProtectionStatus != EMTPProtectionNoProtection &&
+ iProtectionStatus != EMTPProtectionReadOnly)
+ {
+ SendResponseL(EMTPRespCodeParameterNotSupported);
+ result = EFalse;
+ }
+ }
+
+ if (result)
+ {
+ result = GetFullPathNameL(iObjectInfoP->StringCharsL(CMTPTypeObjectInfo::EFilename));
+ if (!result)
+ {
+ // File and/or parent pathname invalid.
+ SendResponseL(EMTPRespCodeInvalidDataset);
+ }
+ }
+
+ // pictbridge objects should be overwritten
+/*
+ if (result)
+ {
+ result &= !Exists(iFullPath);
+ if (!result)
+ {
+ // Object with the same name already exists.
+ __FLOG(_L8(" no rollback"));
+ iNoRollback = ETrue;
+ SendResponseL(EMTPRespCodeAccessDenied);
+ }
+ }
+ */
+
+ if (result)
+ {
+ iReceivedObjectP->SetUint(CMTPObjectMetaData::EFormatCode, format);
+ iPictBridgeDP.PtpServer()->Printer()->DpsDiscovery(iFullPath, &iConnection);
+ TRAPD(err, CreateFsObjectL());
+
+ if (err != KErrNone)
+ {
+ SendResponseL(ErrorToMTPError(err));
+ }
+ else
+ {
+ ReserveObjectL();
+ }
+ }
+ __FLOG(_L8("<< CMTPPictBridgeDpSendObjectInfo::DoHandleSendObjectInfoCompleteL"));
+ return result;
+ }
+
+
+TBool CMTPPictBridgeDpSendObjectInfo::DoHandleSendObjectPropListCompleteL()
+ {
+ __FLOG(_L8(">> CMTPPictBridgeDpSendObjectInfo::DoHandleSendObjectPropListCompleteL"));
+ TBool result(ETrue);
+ TMTPResponseCode responseCode( GetParentObjectAndStorageIdL() );
+ if ( responseCode != EMTPRespCodeOK )
+ {
+ SendResponseL( responseCode );
+ result = EFalse;
+ }
+
+ if ( result )
+ {
+ 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 )
+ {
+ iReceivedObjectP->SetUint(CMTPObjectMetaData::EFormatCode, iRequest->Uint32( TMTPTypeRequest::ERequestParameter3 ));
+ iPictBridgeDP.PtpServer()->Printer()->DpsDiscovery(iFullPath, &iConnection);
+ TRAPD(err, CreateFsObjectL());
+ if ( err != KErrNone )
+ {
+ SendResponseL(ErrorToMTPError(err));
+ }
+ else
+ {
+ ReserveObjectL();
+ }
+ }
+
+ __FLOG(_L8("<< CMTPPictBridgeDpSendObjectInfo::DoHandleSendObjectPropListCompleteL"));
+ return result;
+ }
+
+/**
+*/
+TBool CMTPPictBridgeDpSendObjectInfo::IsFormatValid(TMTPFormatCode aFormat) const
+ {
+ __FLOG_VA((_L8(">> CMTPPictGetObjectPropDesc::IsFormatValid %d"),aFormat));
+ TInt count(sizeof(KMTPValidCodeExtensionMappings) / sizeof(KMTPValidCodeExtensionMappings[0]));
+ for(TInt i = 0; i < count; i++)
+ {
+ if (KMTPValidCodeExtensionMappings[i].iFormatCode == aFormat)
+ {
+ __FLOG(_L8("<< CMTPPictGetObjectPropDesc::IsFormatValid ETrue"));
+ return ETrue;
+ }
+ }
+ __FLOG(_L8("<< CMTPPictGetObjectPropDesc::IsFormatValid EFalse"));
+ return EFalse;
+ }
+
+/**
+Handling the completing phase of SendObject request
+@return ETrue if the object has been successfully saved on the device, otherwise, EFalse
+*/
+TBool CMTPPictBridgeDpSendObjectInfo::DoHandleSendObjectCompleteL()
+ {
+ __FLOG_VA((_L8(">> CMTPPictGetObjectPropDesc::DoHandleSendObjectCompleteL size=%d cancelled=%d"), iObjectSize, iCancelled));
+ TBool result(ETrue);
+
+ delete iFileReceivedP;
+ iFileReceivedP = NULL;
+
+ TEntry fileEntry;
+ User::LeaveIfError(iFramework.Fs().Entry(iFullPath, fileEntry));
+
+ if (fileEntry.FileSize() != iObjectSize)
+ {
+ __FLOG_VA((_L8(" sizes differ %d!=%d"),fileEntry.iSize, iObjectSize));
+ iFramework.RouteRequestUnregisterL(iExpectedSendObjectRequest, iConnection);
+
+ iFramework.Fs().Delete(iFullPath);
+ iFramework.ObjectMgr().UnreserveObjectHandleL(*iReceivedObjectP);
+ 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)))
+ {
+ 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
+ //to be followed by a SendObject. An object is reserved in the ObjectStore on
+ //receiving a SendObjectInfo 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.
+
+
+ iFramework.ObjectMgr().CommitReservedObjectHandleL(*iReceivedObjectP);
+ SendResponseL(EMTPRespCodeOK);
+ }
+ __FLOG(_L8("<< CMTPPictGetObjectPropDesc::DoHandleSendObjectCompleteL"));
+ 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 CMTPPictBridgeDpSendObjectInfo::GetFullPathNameL(const TDesC& aFileName)
+ {
+ __FLOG_VA((_L16(">> CMTPPictBridgeDpSendObjectInfo::GetFullPathNameL file %S"), &aFileName));
+ TBool result(EFalse);
+ if (aFileName.Length() > 0)
+ {
+ iFullPath = *iParentSuidP;
+ if (iFullPath.Length() + aFileName.Length() < iFullPath.MaxLength())
+ {
+ iFullPath.Append(aFileName);
+ result = iFramework.Fs().IsValidName(iFullPath);
+ }
+ }
+
+ __FLOG_VA((_L16("<< CMTPPictBridgeDpSendObjectInfo::GetFullPathNameL full path %S"), &iFullPath));
+ return result;
+ }
+
+/**
+Check if we can store the file on the storage
+@return ETrue if yes, otherwise EFalse
+*/
+TBool CMTPPictBridgeDpSendObjectInfo::CanStoreFileL(TUint32 aStorageId, TInt64 aObjectSize) const
+ {
+ 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;
+ }
+ return result;
+ }
+
+/**
+Check if the object is too large
+@return ETrue if yes, otherwise EFalse
+*/
+TBool CMTPPictBridgeDpSendObjectInfo::IsTooLarge(TUint64 aObjectSize) const
+ {
+ TBool ret(aObjectSize > KMaxTInt64);
+ return ret;
+ }
+
+TMTPResponseCode CMTPPictBridgeDpSendObjectInfo::VerifyObjectPropListL( TInt& aInvalidParameterIndex )
+ {
+ __FLOG(_L8(">> CMTPPictBridgeDpSendObjectInfo::VerifyObjectPropListL"));
+ 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(_L8("<< CMTPPictBridgeDpSendObjectInfo::VerifyObjectPropListL"));
+ return responseCode;
+ }
+
+TMTPResponseCode CMTPPictBridgeDpSendObjectInfo::ExtractPropertyL( const CMTPTypeObjectPropListElement& aElement )
+ {
+ __FLOG(_L8(">> CMTPPictBridgeDpSendObjectInfo::ExtractPropertyL"));
+ TMTPResponseCode responseCode(EMTPRespCodeOK);
+ switch ( aElement.Uint16L(CMTPTypeObjectPropListElement::EPropertyCode) )
+ {
+ 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 iDateModP;
+ iDateModP = NULL;
+ iDateModP = aElement.StringL(CMTPTypeObjectPropListElement::EValue).AllocL();
+ break;
+ case EMTPObjectPropCodeName:
+ iName = aElement.StringL(CMTPTypeObjectPropListElement::EValue);
+ break;
+ default:
+ break;
+ }
+
+ __FLOG(_L8("<< CMTPPictBridgeDpSendObjectInfo::ExtractPropertyL"));
+ return responseCode;
+ }
+
+TMTPResponseCode CMTPPictBridgeDpSendObjectInfo::CheckPropCodeL( const CMTPTypeObjectPropListElement& aElement ) const
+ {
+ __FLOG(_L8(">> CMTPPictBridgeDpSendObjectInfo::CheckPropCodeL"));
+ 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;
+ default:
+ {
+ responseCode = EMTPRespCodeInvalidObjectPropCode;
+ }
+ break;
+ }
+ __FLOG(_L8("<< CMTPPictBridgeDpSendObjectInfo::CheckPropCodeL"));
+ return responseCode;
+ }
+
+TMTPResponseCode CMTPPictBridgeDpSendObjectInfo::MatchStoreAndParentL() const
+ {
+ __FLOG(_L8(">> CMTPPictBridgeDpSendObjectInfo::MatchStoreAndParentL"));
+ TMTPResponseCode ret = EMTPRespCodeOK;
+ const TUint32 storeId(Request().Uint32(TMTPTypeRequest::ERequestParameter1));
+ const TUint32 parentHandle(Request().Uint32(TMTPTypeRequest::ERequestParameter2));
+ if (parentHandle != KMTPHandleAll && parentHandle != KMTPHandleNone)
+ {
+ CMTPObjectMetaData* parentObjInfo = iRequestChecker->GetObjectInfo(parentHandle);
+ __ASSERT_DEBUG(parentObjInfo, Panic(EMTPPictBridgeDpObjectNull));
+
+ if (parentObjInfo->Uint(CMTPObjectMetaData::EStorageId) != storeId)
+ {
+ ret = EMTPRespCodeInvalidObjectHandle;
+ }
+ }
+ __FLOG(_L8("<< CMTPPictBridgeDpSendObjectInfo::MatchStoreAndParentL"));
+ return ret;
+ }
+
+/**
+Reserves space for and assigns an object handle to the received object, then
+sends a success response.
+*/
+void CMTPPictBridgeDpSendObjectInfo::ReserveObjectL()
+ {
+ __FLOG(_L8(">> CMTPPictBridgeDpSendObjectInfo::ReserveObjectL"));
+ iReceivedObjectP->SetUint(CMTPObjectMetaData::EStorageId, iStorageId);
+ iReceivedObjectP->SetDesCL(CMTPObjectMetaData::ESuid, iFullPath);
+
+ iFramework.ObjectMgr().ReserveObjectHandleL(*iReceivedObjectP, iObjectSize);
+
+ iExpectedSendObjectRequest.SetUint32(TMTPTypeRequest::ERequestSessionID, iSessionId);
+ iFramework.RouteRequestRegisterL(iExpectedSendObjectRequest, iConnection);
+ TUint32 parameters[3];
+ parameters[0] = iStorageId;
+ parameters[1] = iParentHandle;
+ parameters[2] = iReceivedObjectP->Uint(CMTPObjectMetaData::EHandle);
+ SendResponseL(EMTPRespCodeOK, (sizeof(parameters) / sizeof(parameters[0])), parameters);
+ __FLOG(_L8("<< CMTPPictBridgeDpSendObjectInfo::ReserveObjectL"));
+ }
+
+void CMTPPictBridgeDpSendObjectInfo::CreateFsObjectL()
+ {
+ __FLOG(_L8(">> CMTPPictBridgeDpSendObjectInfo::CreateFsObjectL"));
+ delete iFileReceivedP;
+ iFileReceivedP = NULL;
+ iFileReceivedP = CMTPTypeFile::NewL(iFramework.Fs(), iFullPath, EFileWrite);
+ iFileReceivedP->SetSizeL(iObjectSize);
+ __FLOG(_L8("<< CMTPPictBridgeDpSendObjectInfo::CreateFsObjectL"));
+ }
+
+void CMTPPictBridgeDpSendObjectInfo::Rollback()
+ {
+ __FLOG(_L8(">> CMTPPictBridgeDpSendObjectInfo::Rollback"));
+ // Delete this object from file system.
+ delete iFileReceivedP;
+ iFileReceivedP=NULL;
+ TInt err=iFramework.Fs().Delete(iFullPath);
+ __FLOG_VA((_L16(">> CMTPPictBridgeDpSendObjectInfo::Rollback deleted %S with return code %d"), &iFullPath, err));
+ TRAP_IGNORE(iFramework.ObjectMgr().UnreserveObjectHandleL(*iReceivedObjectP));
+ __FLOG(_L8("<< CMTPPictBridgeDpSendObjectInfo::Rollback"));
+ }
+
+TMTPResponseCode CMTPPictBridgeDpSendObjectInfo::ErrorToMTPError(TInt aError) const
+ {
+ TMTPResponseCode resp = EMTPRespCodeGeneralError;
+
+ switch (aError)
+ {
+ case KErrAccessDenied:
+ resp = EMTPRespCodeAccessDenied;
+ break;
+
+ case KErrDiskFull:
+ resp = EMTPRespCodeStoreFull;
+ break;
+
+ default:
+ resp = EMTPRespCodeGeneralError;
+ break;
+ }
+
+ return resp;
+ }
+