--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/messagingfw/msgsrvnstore/server/src/CMsvAttachmentManager.cpp Wed Nov 03 22:41:46 2010 +0530
@@ -0,0 +1,682 @@
+// Copyright (c) 2004-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 <msvstore.h>
+#include <f32file.h>
+
+#include "CMsvAttachmentManager.h"
+#include <mmsvstoremanager.h>
+#include "CCopyOneFile.h"
+#include "CMsvAttachmentRename.h"
+#include "TMsvServerStoreManager.h"
+
+const TUid KMsvEntryAttachmentInfo={0x10202D55};
+_LIT(KTxtRenameLockFile, "_Rename_._");
+
+CMsvAttachmentManager* CMsvAttachmentManager::NewL(CMsvStore& aStore, MMsvStoreManager& aStoreManager, const TMsvId aEntryId, RFs& aFs, TBool aReadOnly)
+ {
+ CMsvAttachmentManager* me = new(ELeave) CMsvAttachmentManager(aStore, aStoreManager, aEntryId, aFs, aReadOnly);
+ CleanupStack::PushL(me);
+ me->ConstructL();
+ CleanupStack::Pop(me);
+ return me;
+ }
+
+CMsvAttachmentManager::CMsvAttachmentManager(CMsvStore& aStore, MMsvStoreManager& aStoreManager, const TMsvId aEntryId, RFs& aFs, TBool aReadOnly)
+ :CActive(EPriorityStandard), iStore(aStore), iStoreManager(aStoreManager), iEntryId(aEntryId), iFs(aFs), iReadOnly(aReadOnly)
+ {
+ CActiveScheduler::Add(this);
+ }
+
+void CMsvAttachmentManager::ConstructL()
+ {
+ // Only need the CCopyOneFile if attachment is not readonly
+ if( !iReadOnly )
+ iCopyOneFile = CCopyOneFile::NewL(iFs);
+
+ // Populate the array of attachments from store file that contains all of the data
+ RestoreL();
+ }
+
+CMsvAttachmentManager::~CMsvAttachmentManager()
+ {
+ Cancel();
+
+ // if we have any added attachments, these must be deleted as they have not been committed
+ TInt addedAttachmentCount = iAddedAttachments.Count();
+ for( TInt ii=0; ii<addedAttachmentCount; ++ii )
+ {
+ iStoreManager.DeleteAttachment(iEntryId, *iAddedAttachments[ii]); // ignore return code
+ }
+
+ iAddedAttachments.ResetAndDestroy();
+ iDeletedAttachments.ResetAndDestroy();
+ iAttachments.ResetAndDestroy();
+ iRenamed.ResetAndDestroy();
+ delete iCopyOneFile;
+ }
+
+void CMsvAttachmentManager::RunL()
+ {
+ User::LeaveIfError(iStatus.Int());
+
+ User::RequestComplete(iReportStatus, KErrNone);
+ }
+
+void CMsvAttachmentManager::DoCancel()
+ {
+ __ASSERT_DEBUG(iCopyOneFile!=NULL, User::Invariant());
+
+ if( iCopyOneFile->IsActive() )
+ iCopyOneFile->Cancel();
+ }
+
+TInt CMsvAttachmentManager::RunError(TInt aError)
+ {
+ // Asynchronous request only occur when an attachment is added
+ // so delete the last added attachment
+ TInt count = iAttachments.Count();
+ --count;
+ if (count > 0)
+ {
+ delete iAttachments[count];
+ iAttachments.Remove(count);
+ }
+
+ count = iAddedAttachments.Count();
+ --count;
+ if (count > 0)
+ {
+ delete iAddedAttachments[count];
+ iAddedAttachments.Remove(count);
+ }
+ User::RequestComplete(iReportStatus, aError);
+ return KErrNone;
+ }
+
+void CMsvAttachmentManager::CompleteSelf()
+ {
+ iStatus=KRequestPending;
+ SetActive();
+ TRequestStatus* status = &iStatus;
+ User::RequestComplete(status, KErrNone);
+ }
+
+void CMsvAttachmentManager::RestoreL()
+ {
+ // Before loading, ensure that array is flushed out, all changes since last
+ // store commit will be lost
+ iAttachments.ResetAndDestroy();
+ iDeletedAttachments.ResetAndDestroy();
+
+ // if any added attachment file were added since the last commit, these must be removed
+ TInt addedAttachmentCount = iAddedAttachments.Count();
+ for( TInt ii=0; ii<addedAttachmentCount; ++ii )
+ {
+ iStoreManager.DeleteAttachment(iEntryId, *iAddedAttachments[ii]); // ignore return error
+ }
+ // All the added attachments have been cleaned up, reset the list
+ iAddedAttachments.ResetAndDestroy();
+
+ // Only load the attachment info stream if one exists
+ if(iStore.IsPresentL(KMsvEntryAttachmentInfo))
+ {
+ RMsvReadStream readStream;
+ readStream.OpenLC(iStore, KMsvEntryAttachmentInfo);
+
+ // Read the data...
+ // 1. the number of attachments
+ TInt attachmentCount = readStream.ReadInt32L();
+
+ TFileName attachmentFilePath;
+
+ // 2. populate the attachment array contents
+ // for every object create and populate it from the stream
+ for(TInt ii=0; ii<attachmentCount; ++ii)
+ {
+ // create empty attachment object, doesn't matter what type as the
+ // correct attachment type is set when it is internalised
+ CMsvAttachment* attachment = CMsvAttachment::NewL(CMsvAttachment::EMsvFile);
+ CleanupStack::PushL(attachment);
+ readStream >> *attachment;
+ if( attachment->IsPathRequired() )
+ {
+ // The attachment path needs to be dynamically set, only get the file path if needed
+ if( attachmentFilePath.Length()==0 )
+ {
+ iStoreManager.AttachmentFilePathL(iEntryId, attachmentFilePath);
+ }
+
+ TParse fullPath;
+ User::LeaveIfError(fullPath.Set(attachmentFilePath, &attachment->FilePath(), NULL));
+ attachment->SetFilePathL(fullPath.FullName());
+ }
+
+ User::LeaveIfError(iAttachments.Append(attachment));
+ CleanupStack::Pop(attachment);
+ }
+
+ // 3. attachment id generator
+ iIdGenerator = readStream.ReadUint32L();
+
+ CleanupStack::PopAndDestroy(&readStream);
+ }
+
+ // Restore any rename info from the rename lock file
+ TInt err = InternaliseRenameLockL();
+ if( err==KErrNone )
+ {
+ // lock file exists
+ TInt currentIndex = iRenamed.Count();
+ while( currentIndex>0 )
+ {
+ // We have some files that have been renamed and need to
+ // be renamed back to the old name, these are renamed in
+ // reverse order in case any one single attachment was
+ // renamed twice before committing.
+ --currentIndex;
+ CMsvAttachmentRename* renameInfo = iRenamed[currentIndex];
+ iStoreManager.RenameAttachment(iEntryId, renameInfo->NewName(), renameInfo->OldName()); // ignore errors
+ }
+
+ iRenamed.ResetAndDestroy();
+
+ // delete the lock file as it no longer needed
+ iStoreManager.DeleteAttachment(iEntryId, KTxtRenameLockFile); // ignore return error
+ }
+ }
+
+void CMsvAttachmentManager::HandleCommitComplete()
+ {
+ // The attachments have been commited, the cache of added files can be removed
+ iAddedAttachments.ResetAndDestroy();
+
+ // Any attachment files that are marked for delete, must be deleted from the message store
+ TInt deleteAttachmentCount = iDeletedAttachments.Count();
+ for( TInt ii=0; ii<deleteAttachmentCount; ++ii )
+ {
+ iStoreManager.DeleteAttachment(iEntryId, *iDeletedAttachments[ii]); // ignore errors
+ }
+ iDeletedAttachments.ResetAndDestroy();
+
+ // Remove the rename info as changes have been committed
+ iStoreManager.DeleteAttachment(iEntryId, KTxtRenameLockFile); // ignore return error
+ iRenamed.ResetAndDestroy();
+ }
+
+void CMsvAttachmentManager::StoreL()
+ {
+ __ASSERT_DEBUG(iReadOnly==EFalse, User::Invariant());
+
+ TInt attachmentCount = iAttachments.Count();
+
+ // If there are no attachments, remove the stream
+ if(attachmentCount==0)
+ {
+ iStore.Remove(KMsvEntryAttachmentInfo);
+ }
+ else
+ {
+ RMsvWriteStream writeStream;
+ writeStream.AssignLC(iStore, KMsvEntryAttachmentInfo);
+
+ // Write the data...
+ // 1. the number of attachments
+ writeStream.WriteInt32L(attachmentCount);
+
+ // 2. save the attachment array contents
+ // for every object create and populate it from the stream
+ for(TInt ii=0; ii<attachmentCount; ++ii)
+ {
+ CMsvAttachment* attachment = iAttachments[ii];
+ writeStream << *attachment;
+ }
+
+ // 3. attachment id generator
+ writeStream.WriteUint32L(iIdGenerator);
+
+ writeStream.CommitL();
+ CleanupStack::PopAndDestroy(&writeStream);
+ }
+ }
+
+TMsvAttachmentId CMsvAttachmentManager::GenerateAttachmentId()
+ {
+ return ++iIdGenerator;
+ }
+
+void CMsvAttachmentManager::CreateAttachmentInStoreLC(TDes& aFileName, RFile& aFile, CMsvAttachment* aAttachmentInfo, TBool aIsShareProtected)
+ {
+ if( aFileName.CompareF(KTxtRenameLockFile)==0 )
+ {
+ // Cant add attachments using the same name as the rename lock file
+ User::Leave(KErrBadName);
+ }
+
+ if(aIsShareProtected)
+ {
+ iStoreManager.CreateShareProtectedAttachmentForWriteL(iEntryId, aFileName, aFile);
+ }
+ else
+ {
+ iStoreManager.CreateAttachmentForWriteL(iEntryId, aFileName, aFile);
+ }
+
+ CleanupClosePushL(aFile);
+
+ HBufC* addedFilePath = aFileName.AllocLC();
+ User::LeaveIfError(iAddedAttachments.Append(addedFilePath));
+ CleanupStack::Pop(addedFilePath);
+
+ // initailise attachment info and take ownership
+ aAttachmentInfo->SetFilePathL(aFileName);
+ User::LeaveIfError(iAttachments.Append(aAttachmentInfo));
+ aAttachmentInfo->SetId(GenerateAttachmentId());
+ }
+
+void CMsvAttachmentManager::AddAttachmentL(const TDesC& aFilePath, CMsvAttachment* aAttachmentInfo, TRequestStatus& aStatus)
+ {
+ if(iReadOnly)
+ User::Leave(KErrAccessDenied);
+
+ __ASSERT_ALWAYS(aAttachmentInfo->Type() == CMsvAttachment::EMsvFile, User::Invariant());
+
+ RFile fileToCopy;
+ User::LeaveIfError(fileToCopy.Open(iFs, aFilePath, EFileRead|EFileShareReadersOnly));
+ CleanupClosePushL(fileToCopy);
+
+ TFileName fileName;
+ User::LeaveIfError(fileToCopy.Name(fileName));
+
+ RFile newFileHandle;
+ CreateAttachmentInStoreLC(fileName, newFileHandle, aAttachmentInfo, EFalse);
+
+ aStatus=KRequestPending;
+ iReportStatus=&aStatus;
+
+ iCopyOneFile->Copy(fileToCopy, newFileHandle, iStatus);
+ CleanupStack::Pop(2, &fileToCopy); // newFileHandle, fileToCopy
+ SetActive();
+ }
+
+void CMsvAttachmentManager::AddAttachmentL(RFile& aFileHandle, CMsvAttachment* aAttachmentInfo, TRequestStatus& aStatus)
+ {
+ if(iReadOnly)
+ User::Leave(KErrAccessDenied);
+
+ __ASSERT_ALWAYS(aAttachmentInfo->Type() == CMsvAttachment::EMsvFile, User::Invariant());
+
+ TFileName fileName;
+ User::LeaveIfError(aFileHandle.Name(fileName));
+
+ RFile newFileHandle;
+ CreateAttachmentInStoreLC(fileName, newFileHandle, aAttachmentInfo, EFalse);
+
+ aStatus=KRequestPending;
+ iReportStatus=&aStatus;
+
+ iCopyOneFile->Copy(aFileHandle, newFileHandle, iStatus);
+ CleanupStack::Pop(&newFileHandle);
+ SetActive();
+ }
+
+void CMsvAttachmentManager::AddLinkedAttachmentL(const TDesC& aFilePath, CMsvAttachment* aAttachmentInfo, TRequestStatus& aStatus)
+ {
+ if(iReadOnly)
+ User::Leave(KErrAccessDenied);
+
+ __ASSERT_ALWAYS(aAttachmentInfo->Type() == CMsvAttachment::EMsvLinkedFile, User::Invariant());
+
+ // initailise attachment info and take ownership
+ aAttachmentInfo->SetFilePathL(aFilePath);
+ User::LeaveIfError(iAttachments.Append(aAttachmentInfo));
+ aAttachmentInfo->SetId(GenerateAttachmentId());
+
+ aStatus=KRequestPending;
+ iReportStatus=&aStatus;
+ CompleteSelf();
+ }
+
+void CMsvAttachmentManager::AddEntryAsAttachmentL(TMsvId aEntryId, CMsvAttachment* aAttachmentInfo, TRequestStatus& aStatus)
+ {
+ if(iReadOnly)
+ User::Leave(KErrAccessDenied);
+
+ __ASSERT_ALWAYS(aAttachmentInfo->Type() == CMsvAttachment::EMsvMessageEntry, User::Invariant());
+
+ // initailise attachment info and take ownership
+ User::LeaveIfError(iAttachments.Append(aAttachmentInfo));
+ aAttachmentInfo->SetId(GenerateAttachmentId());
+ aAttachmentInfo->SetEntryAttachmentId(aEntryId);
+
+ aStatus=KRequestPending;
+ iReportStatus=&aStatus;
+ User::RequestComplete(iReportStatus, KErrNone);
+ }
+
+void CMsvAttachmentManager::CreateAttachmentL(const TDesC& aFileName, RFile& aAttachmentFile, CMsvAttachment* aAttachmentInfo, TRequestStatus& aStatus)
+ {
+ CreateAttachmentL(aFileName, aAttachmentFile, aAttachmentInfo);
+
+ aStatus=KRequestPending;
+ iReportStatus=&aStatus;
+ CompleteSelf();
+ }
+
+
+TInt CMsvAttachmentManager::AttachmentCount() const
+ {
+ return iAttachments.Count();
+ }
+
+CMsvAttachment* CMsvAttachmentManager::GetAttachmentInfoL(TInt aIndex)
+ {
+ // Create a deep copy the CMsvAttachment object to pass back to the client
+ CMsvAttachment* currentAttachment = iAttachments[aIndex];
+
+ return CMsvAttachment::NewL(*currentAttachment);
+ }
+
+CMsvAttachment* CMsvAttachmentManager::GetAttachmentInfoL(TMsvAttachmentId aId)
+ {
+ return GetAttachmentInfoL(IndexPositionOfAttachmentL(aId));
+ }
+
+void CMsvAttachmentManager::ModifyAttachmentInfoL(CMsvAttachment* aAttachmentInfo)
+ {
+ if(iReadOnly)
+ User::Leave(KErrAccessDenied);
+
+ // Get the index position of the attachment info with the same Id
+ TInt attachmentIndex = IndexPositionOfAttachmentL(aAttachmentInfo->Id());
+ __ASSERT_ALWAYS(aAttachmentInfo->Type()==iAttachments[attachmentIndex]->Type(), User::Invariant());
+
+ // Insert the replaced attachment info object into the same position and then
+ // remove the old one
+ User::LeaveIfError(iAttachments.Insert(aAttachmentInfo, attachmentIndex));
+ ++attachmentIndex;
+ delete iAttachments[attachmentIndex];
+ iAttachments.Remove(attachmentIndex);
+ }
+
+void CMsvAttachmentManager::ModifyAttachmentInfoL(CMsvAttachment* aAttachmentInfo, TRequestStatus& aStatus)
+ {
+ ModifyAttachmentInfoL(aAttachmentInfo);
+ aStatus=KRequestPending;
+ iReportStatus=&aStatus;
+ CompleteSelf();
+ }
+
+RFile CMsvAttachmentManager::GetAttachmentFileL(TInt aIndex)
+ {
+ CMsvAttachment* attachment = iAttachments[aIndex];
+
+ // Make sure that the attachment is a file attachment
+ if( attachment->Type() == CMsvAttachment::EMsvMessageEntry )
+ User::Leave(KErrNotSupported);
+
+ RFile attachmentFile;
+
+ if( attachment->Type() == CMsvAttachment::EMsvFile )
+ {
+ iStoreManager.OpenAttachmentL(iEntryId, attachment->FilePath(), attachmentFile);
+ }
+ else // attachment->iType == ELinkedFile
+ {
+ RFs fs;
+ fs.Connect();
+ fs.ShareProtected();
+ User::LeaveIfError(attachmentFile.Open(fs, attachment->FilePath(), EFileRead | EFileShareReadersOnly));
+ }
+
+ // handle to attachment file allocated, return to caller
+ return attachmentFile;
+ }
+
+RFile CMsvAttachmentManager::GetAttachmentFileL(TMsvAttachmentId aId)
+ {
+ return GetAttachmentFileL(IndexPositionOfAttachmentL(aId));
+ }
+
+RFile CMsvAttachmentManager::GetAttachmentFileForWriteL(TInt aIndex)
+ {
+ if(iReadOnly)
+ User::Leave(KErrAccessDenied);
+
+ CMsvAttachment* attachment = iAttachments[aIndex];
+
+ // Make sure that the attachment is a file attachment
+ if( attachment->Type() == CMsvAttachment::EMsvMessageEntry )
+ User::Leave(KErrNotSupported);
+
+ RFile attachmentFile;
+
+ if( attachment->Type() == CMsvAttachment::EMsvFile )
+ {
+ iStoreManager.OpenAttachmentForWriteL(iEntryId, attachment->FilePath(), attachmentFile);
+ }
+ else // attachment->iType == ELinkedFile
+ {
+ RFs fs;
+ fs.Connect();
+ fs.ShareProtected();
+ User::LeaveIfError(attachmentFile.Open(fs, attachment->FilePath(), EFileWrite));
+ }
+
+ // handle to attachment file allocated, return to caller
+ return attachmentFile;
+ }
+
+RFile CMsvAttachmentManager::GetAttachmentFileForWriteL(TMsvAttachmentId aId)
+ {
+ return GetAttachmentFileForWriteL(IndexPositionOfAttachmentL(aId));
+ }
+
+void CMsvAttachmentManager::RemoveAttachmentL(TInt aIndex, TRequestStatus& aStatus)
+ {
+ RemoveAttachmentL(aIndex);
+
+ aStatus=KRequestPending;
+ iReportStatus=&aStatus;
+ CompleteSelf();
+ }
+
+void CMsvAttachmentManager::RemoveAttachmentL(TMsvAttachmentId aId, TRequestStatus& aStatus)
+ {
+ RemoveAttachmentL(IndexPositionOfAttachmentL(aId), aStatus);
+ }
+
+TInt CMsvAttachmentManager::IndexPositionOfAttachmentL(TMsvAttachmentId aId) const
+ {
+ TInt foundPosition = KErrNotFound;
+ TInt attachmentCount = iAttachments.Count();
+ // Go through the attachment list to find the attachment by its id
+ for( TInt ii=0; ii<attachmentCount; ++ii )
+ {
+ if( iAttachments[ii]->Id() == aId )
+ {
+ foundPosition = ii;
+ break;
+ }
+ }
+
+ // Leave with KErrNotFound if the attachment id is not found
+ User::LeaveIfError(foundPosition);
+
+ // return the index position of attachment
+ return foundPosition;
+ }
+
+void CMsvAttachmentManager::CancelRequest()
+ {
+ Cancel();
+ User::RequestComplete(iReportStatus, KErrCancel);
+ }
+
+void CMsvAttachmentManager::CreateAttachmentL(const TDesC& aFileName, RFile& aAttachmentFile, CMsvAttachment* aAttachmentInfo)
+ {
+ if(iReadOnly)
+ User::Leave(KErrAccessDenied);
+
+ __ASSERT_ALWAYS(aAttachmentInfo->Type() == CMsvAttachment::EMsvFile, User::Invariant());
+
+ // File name must be provided
+ if( aFileName.Length() == 0 || aAttachmentFile.SubSessionHandle() != KNullHandle)
+ User::Leave(KErrArgument);
+
+ TFileName fileName = aFileName;
+
+ CreateAttachmentInStoreLC(fileName, aAttachmentFile, aAttachmentInfo, EFalse);
+ CleanupStack::Pop(&aAttachmentFile);
+ }
+
+void CMsvAttachmentManager::CreateShareProtectedAttachmentL(const TDesC& aFileName, RFile& aAttachmentFile, CMsvAttachment* aAttachmentInfo)
+ {
+ if(iReadOnly)
+ User::Leave(KErrAccessDenied);
+
+ __ASSERT_ALWAYS(aAttachmentInfo->Type() == CMsvAttachment::EMsvFile, User::Invariant());
+
+ // File name must be provided
+ if( aFileName.Length() == 0 || aAttachmentFile.SubSessionHandle() != KNullHandle)
+ User::Leave(KErrArgument);
+
+ TFileName fileName = aFileName;
+
+ CreateAttachmentInStoreLC(fileName, aAttachmentFile, aAttachmentInfo, ETrue);
+ CleanupStack::Pop(&aAttachmentFile);
+ }
+
+TInt CMsvAttachmentManager::InternaliseRenameLockL()
+ {
+ iRenamed.ResetAndDestroy();
+
+ // if the rename lock file exists internalise it
+ RFile renameLockFile;
+ TRAPD(err, iStoreManager.OpenAttachmentL(iEntryId, KTxtRenameLockFile, renameLockFile));
+ if( err==KErrNone )
+ {
+ // got the rename lock file
+ RFileReadStream renameReadStream(renameLockFile);
+ renameReadStream.PushL();
+ TInt renamedCount = renameReadStream.ReadInt32L();
+ for( TInt ii=0; ii<renamedCount; ++ii )
+ {
+ CMsvAttachmentRename* renameInfo = CMsvAttachmentRename::NewLC();
+ renameReadStream >> *renameInfo;
+ iRenamed.AppendL(renameInfo);
+ CleanupStack::Pop(renameInfo);
+ }
+ CleanupStack::PopAndDestroy(); // renameReadStream
+ }
+ else if( err==KErrNotFound || err==KErrPathNotFound )
+ {
+ err = KErrNotFound; // rename lock file not found
+ }
+ else
+ {
+ User::Leave(err);
+ }
+
+ return err;
+ }
+
+void CMsvAttachmentManager::ExternaliseRenameLockL()
+ {
+ __ASSERT_DEBUG(iRenamed.Count()>0, User::Invariant());
+
+ // Get the rename lock file to store the rename information
+ RFile renameLockFile;
+ TFileName lockFileName(KTxtRenameLockFile());
+ iStoreManager.ReplaceAttachmentForWriteL(iEntryId, lockFileName, renameLockFile);
+ RFileWriteStream renameWriteStream(renameLockFile);
+ renameWriteStream.PushL();
+
+ // Externalise the count and each rename file info object
+ TInt renamedCount = iRenamed.Count();
+ renameWriteStream.WriteInt32L(renamedCount);
+ for( TInt ii=0; ii<renamedCount; ++ii )
+ {
+ renameWriteStream << *(iRenamed[ii]);
+ }
+
+ renameWriteStream.CommitL();
+ CleanupStack::PopAndDestroy(); // renameWriteStream
+ }
+
+void CMsvAttachmentManager::DoAttachmentRenameL(TInt aIndex, const TDesC& aNewName)
+ {
+ if(iReadOnly)
+ {
+ User::Leave(KErrAccessDenied);
+ }
+
+ CMsvAttachment* renameAttachment = iAttachments[aIndex];
+ __ASSERT_ALWAYS(renameAttachment->Type() == CMsvAttachment::EMsvFile, User::Invariant());
+
+ // Build the attachment rename infomation and store in array
+ TPtrC oldFilePath(renameAttachment->FilePath());
+ CMsvAttachmentRename* renameInfo = CMsvAttachmentRename::NewLC(oldFilePath, aNewName);
+ iRenamed.AppendL(renameInfo);
+ CleanupStack::Pop(renameInfo);
+
+ // Save the rename infomation
+ ExternaliseRenameLockL();
+
+ // Rename and update the attachment info
+ TParse newFilePath;
+ User::LeaveIfError(newFilePath.Set(aNewName, &oldFilePath, NULL));
+ User::LeaveIfError(iStoreManager.RenameAttachment(iEntryId, oldFilePath, aNewName));
+ renameAttachment->SetFilePathL(newFilePath.FullName());
+ }
+
+void CMsvAttachmentManager::RenameAttachmentL(TInt aIndex, const TDesC& aNewName)
+ {
+ DoAttachmentRenameL(aIndex, aNewName);
+ }
+
+void CMsvAttachmentManager::RenameAttachmentL(TInt aIndex, const TDesC& aNewName, TRequestStatus& aStatus)
+ {
+ DoAttachmentRenameL(aIndex, aNewName);
+
+ aStatus=KRequestPending;
+ iReportStatus=&aStatus;
+ User::RequestComplete(iReportStatus, KErrNone);
+ }
+
+void CMsvAttachmentManager::RemoveAttachmentL(TInt aIndex)
+ {
+ if(iReadOnly)
+ User::Leave(KErrAccessDenied);
+
+ // If the attachment is a file attachment, we need remove the attachment object
+ // and mark the file for deletion so that it is deleted only when SaveL is called.
+ // This ensures that if the store is reverted, the attachment files are still in
+ // the message store
+ CMsvAttachment* deleteAttachment = iAttachments[aIndex];
+
+ // only need to mark the file for deletion if it is an attachment stored in the
+ // message server, ie. dont delete linked attachments
+ if( deleteAttachment->Type() == CMsvAttachment::EMsvFile )
+ {
+ HBufC* deleteFilePath = deleteAttachment->FilePath().AllocLC();
+ User::LeaveIfError(iDeletedAttachments.Append(deleteFilePath));
+ CleanupStack::Pop(deleteFilePath);
+ }
+
+ iAttachments.Remove(aIndex);
+ delete deleteAttachment;
+ }
+