messagingfw/msgsrvnstore/server/src/CMsvAttachmentManager.cpp
changeset 0 8e480a14352b
child 41 0abbef78e78b
equal deleted inserted replaced
-1:000000000000 0:8e480a14352b
       
     1 // Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 #include <msvstore.h>
       
    17 #include <f32file.h>
       
    18 
       
    19 #include "CMsvAttachmentManager.h"
       
    20 #include <mmsvstoremanager.h>
       
    21 #include "CCopyOneFile.h"
       
    22 #include "CMsvAttachmentRename.h"
       
    23 #include "TMsvServerStoreManager.h"
       
    24 
       
    25 const TUid KMsvEntryAttachmentInfo={0x10202D55};
       
    26 _LIT(KTxtRenameLockFile, "_Rename_._");
       
    27 
       
    28 CMsvAttachmentManager* CMsvAttachmentManager::NewL(CMsvStore& aStore, MMsvStoreManager& aStoreManager, const TMsvId aEntryId, RFs& aFs, TBool aReadOnly)
       
    29 	{
       
    30 	CMsvAttachmentManager* me = new(ELeave) CMsvAttachmentManager(aStore, aStoreManager, aEntryId, aFs, aReadOnly);
       
    31 	CleanupStack::PushL(me);
       
    32 	me->ConstructL();
       
    33 	CleanupStack::Pop(me);
       
    34 	return me;
       
    35 	}
       
    36 	
       
    37 CMsvAttachmentManager::CMsvAttachmentManager(CMsvStore& aStore, MMsvStoreManager& aStoreManager, const TMsvId aEntryId, RFs& aFs, TBool aReadOnly)
       
    38 	:CActive(EPriorityStandard), iStore(aStore), iStoreManager(aStoreManager), iEntryId(aEntryId), iFs(aFs), iReadOnly(aReadOnly)
       
    39 	{
       
    40 	CActiveScheduler::Add(this);
       
    41 	}
       
    42 	
       
    43 void CMsvAttachmentManager::ConstructL()
       
    44 	{
       
    45 	// Only need the CCopyOneFile if attachment is not readonly
       
    46 	if( !iReadOnly )
       
    47 		iCopyOneFile = CCopyOneFile::NewL(iFs);
       
    48 	
       
    49 	// Populate the array of attachments from store file that contains all of the data
       
    50 	RestoreL();
       
    51 	}
       
    52 	
       
    53 CMsvAttachmentManager::~CMsvAttachmentManager()
       
    54 	{
       
    55 	Cancel();
       
    56 	
       
    57 	// if we have any added attachments, these must be deleted as they have not been committed
       
    58 	TInt addedAttachmentCount = iAddedAttachments.Count();
       
    59 	for( TInt ii=0; ii<addedAttachmentCount; ++ii )
       
    60 		{
       
    61 		iStoreManager.DeleteAttachment(iEntryId, *iAddedAttachments[ii]); // ignore return code
       
    62 		}
       
    63 		
       
    64 	iAddedAttachments.ResetAndDestroy();
       
    65 	iDeletedAttachments.ResetAndDestroy();	
       
    66 	iAttachments.ResetAndDestroy();
       
    67 	iRenamed.ResetAndDestroy();
       
    68 	delete iCopyOneFile;
       
    69 	}
       
    70 
       
    71 void CMsvAttachmentManager::RunL()
       
    72 	{
       
    73 	User::LeaveIfError(iStatus.Int());
       
    74 	
       
    75 	User::RequestComplete(iReportStatus, KErrNone);
       
    76 	}
       
    77 	
       
    78 void CMsvAttachmentManager::DoCancel()
       
    79 	{
       
    80 	__ASSERT_DEBUG(iCopyOneFile!=NULL, User::Invariant());
       
    81 	
       
    82 	if( iCopyOneFile->IsActive() )
       
    83 		iCopyOneFile->Cancel();
       
    84 	}
       
    85 
       
    86 TInt CMsvAttachmentManager::RunError(TInt aError)
       
    87 	{
       
    88 	// Asynchronous request only occur when an attachment is added
       
    89 	// so delete the last added attachment
       
    90 	TInt count = iAttachments.Count();
       
    91 	--count;
       
    92 	if (count > 0)
       
    93 		{
       
    94 		delete iAttachments[count];
       
    95 		iAttachments.Remove(count);
       
    96 		}
       
    97 
       
    98 	count = iAddedAttachments.Count();
       
    99 	--count;
       
   100 	if (count > 0)
       
   101 		{
       
   102 		delete iAddedAttachments[count];
       
   103 		iAddedAttachments.Remove(count);
       
   104 		}
       
   105 	User::RequestComplete(iReportStatus, aError);
       
   106 	return KErrNone;
       
   107 	}
       
   108 
       
   109 void CMsvAttachmentManager::CompleteSelf()
       
   110 	{
       
   111 	iStatus=KRequestPending;
       
   112 	SetActive();
       
   113 	TRequestStatus* status = &iStatus;
       
   114 	User::RequestComplete(status, KErrNone);
       
   115 	}
       
   116 	
       
   117 void CMsvAttachmentManager::RestoreL()
       
   118 	{
       
   119 	// Before loading, ensure that array is flushed out, all changes since last
       
   120 	// store commit will be lost
       
   121 	iAttachments.ResetAndDestroy();
       
   122 	iDeletedAttachments.ResetAndDestroy();
       
   123 	
       
   124 	// if any added attachment file were added since the last commit, these must be removed
       
   125 	TInt addedAttachmentCount = iAddedAttachments.Count();
       
   126 	for( TInt ii=0; ii<addedAttachmentCount; ++ii )
       
   127 		{
       
   128 		iStoreManager.DeleteAttachment(iEntryId, *iAddedAttachments[ii]); // ignore return error
       
   129 		}
       
   130 	// All the added attachments have been cleaned up, reset the list
       
   131 	iAddedAttachments.ResetAndDestroy();
       
   132 	
       
   133 	// Only load the attachment info stream if one exists
       
   134 	if(iStore.IsPresentL(KMsvEntryAttachmentInfo))
       
   135 		{	
       
   136 		RMsvReadStream readStream;
       
   137 		readStream.OpenLC(iStore, KMsvEntryAttachmentInfo);
       
   138 		
       
   139 		// Read the data...
       
   140 		// 1. the number of attachments
       
   141 		TInt attachmentCount = readStream.ReadInt32L();
       
   142 		
       
   143 		TFileName attachmentFilePath;
       
   144 		
       
   145 		// 2. populate the attachment array contents
       
   146 		// for every object create and populate it from the stream
       
   147 		for(TInt ii=0; ii<attachmentCount; ++ii)
       
   148 			{
       
   149 			// create empty attachment object, doesn't matter what type as the
       
   150 			// correct attachment type is set when it is internalised
       
   151 			CMsvAttachment* attachment = CMsvAttachment::NewL(CMsvAttachment::EMsvFile);
       
   152 			CleanupStack::PushL(attachment);
       
   153 			readStream >> *attachment;
       
   154 			if( attachment->IsPathRequired() )
       
   155 				{
       
   156 				// The attachment path needs to be dynamically set, only get the file path if needed
       
   157 				if( attachmentFilePath.Length()==0 )
       
   158 					{
       
   159 					iStoreManager.AttachmentFilePathL(iEntryId, attachmentFilePath);
       
   160 					}
       
   161 				
       
   162 				TParse fullPath;
       
   163 				User::LeaveIfError(fullPath.Set(attachmentFilePath, &attachment->FilePath(), NULL));
       
   164 				attachment->SetFilePathL(fullPath.FullName());
       
   165 				}
       
   166 				
       
   167 			User::LeaveIfError(iAttachments.Append(attachment));
       
   168 			CleanupStack::Pop(attachment);
       
   169 			}
       
   170 			
       
   171 		// 3. attachment id generator
       
   172 		iIdGenerator = readStream.ReadUint32L();
       
   173 		
       
   174 		CleanupStack::PopAndDestroy(&readStream);
       
   175 		}
       
   176 		
       
   177 	// Restore any rename info from the rename lock file
       
   178 	TInt err = InternaliseRenameLockL();
       
   179 	if( err==KErrNone )
       
   180 		{
       
   181 		// lock file exists
       
   182 		TInt currentIndex = iRenamed.Count();
       
   183 		while( currentIndex>0 )
       
   184 			{
       
   185 			// We have some files that have been renamed and need to
       
   186 			// be renamed back to the old name, these are renamed in
       
   187 			// reverse order in case any one single attachment was
       
   188 			// renamed twice before committing.
       
   189 			--currentIndex;
       
   190 			CMsvAttachmentRename* renameInfo = iRenamed[currentIndex];
       
   191 			iStoreManager.RenameAttachment(iEntryId, renameInfo->NewName(), renameInfo->OldName()); // ignore errors
       
   192 			}
       
   193 			
       
   194 		iRenamed.ResetAndDestroy();
       
   195 		
       
   196 		// delete the lock file as it no longer needed
       
   197 		iStoreManager.DeleteAttachment(iEntryId, KTxtRenameLockFile); // ignore return error
       
   198 		}
       
   199 	}
       
   200 	
       
   201 void CMsvAttachmentManager::HandleCommitComplete()
       
   202 	{
       
   203 	// The attachments have been commited, the cache of added files can be removed
       
   204 	iAddedAttachments.ResetAndDestroy();
       
   205 	
       
   206 	// Any attachment files that are marked for delete, must be deleted from the message store
       
   207 	TInt deleteAttachmentCount = iDeletedAttachments.Count();
       
   208 	for( TInt ii=0; ii<deleteAttachmentCount; ++ii )
       
   209 		{
       
   210 		iStoreManager.DeleteAttachment(iEntryId, *iDeletedAttachments[ii]); // ignore errors
       
   211 		}
       
   212 	iDeletedAttachments.ResetAndDestroy();
       
   213 	
       
   214 	// Remove the rename info as changes have been committed
       
   215 	iStoreManager.DeleteAttachment(iEntryId, KTxtRenameLockFile); // ignore return error
       
   216 	iRenamed.ResetAndDestroy();
       
   217 	}
       
   218 	
       
   219 void CMsvAttachmentManager::StoreL()
       
   220 	{
       
   221 	__ASSERT_DEBUG(iReadOnly==EFalse, User::Invariant());
       
   222 	
       
   223 	TInt attachmentCount = iAttachments.Count();
       
   224 	
       
   225 	// If there are no attachments, remove the stream
       
   226 	if(attachmentCount==0)
       
   227 		{
       
   228 		iStore.Remove(KMsvEntryAttachmentInfo);
       
   229 		}
       
   230 	else
       
   231 		{
       
   232 		RMsvWriteStream writeStream;
       
   233 		writeStream.AssignLC(iStore, KMsvEntryAttachmentInfo);
       
   234 		
       
   235 		// Write the data...
       
   236 		// 1. the number of attachments
       
   237 		writeStream.WriteInt32L(attachmentCount);
       
   238 		
       
   239 		// 2. save the attachment array contents
       
   240 		// for every object create and populate it from the stream
       
   241 		for(TInt ii=0; ii<attachmentCount; ++ii)
       
   242 			{
       
   243 			CMsvAttachment* attachment = iAttachments[ii];
       
   244 			writeStream << *attachment;
       
   245 			}
       
   246 		
       
   247 		// 3. attachment id generator
       
   248 		writeStream.WriteUint32L(iIdGenerator);
       
   249 		
       
   250 		writeStream.CommitL();
       
   251 		CleanupStack::PopAndDestroy(&writeStream);
       
   252 		}
       
   253 	}
       
   254 
       
   255 TMsvAttachmentId CMsvAttachmentManager::GenerateAttachmentId()
       
   256 	{
       
   257 	return ++iIdGenerator;
       
   258 	}
       
   259 	
       
   260 void CMsvAttachmentManager::CreateAttachmentInStoreLC(TDes& aFileName, RFile& aFile, CMsvAttachment* aAttachmentInfo, TBool aIsShareProtected)
       
   261 	{
       
   262 	if( aFileName.CompareF(KTxtRenameLockFile)==0 )
       
   263 		{
       
   264 		// Cant add attachments using the same name as the rename lock file
       
   265 		User::Leave(KErrBadName);
       
   266 		}
       
   267 	
       
   268 	if(aIsShareProtected)
       
   269 		{
       
   270 		iStoreManager.CreateShareProtectedAttachmentForWriteL(iEntryId, aFileName, aFile);
       
   271 		}
       
   272 	else
       
   273 		{				
       
   274 		iStoreManager.CreateAttachmentForWriteL(iEntryId, aFileName, aFile);
       
   275 		}
       
   276 	
       
   277 	CleanupClosePushL(aFile);
       
   278 	
       
   279 	HBufC* addedFilePath = aFileName.AllocLC();
       
   280 	User::LeaveIfError(iAddedAttachments.Append(addedFilePath));
       
   281 	CleanupStack::Pop(addedFilePath);
       
   282 	
       
   283 	// initailise attachment info and take ownership
       
   284 	aAttachmentInfo->SetFilePathL(aFileName);
       
   285 	User::LeaveIfError(iAttachments.Append(aAttachmentInfo));
       
   286 	aAttachmentInfo->SetId(GenerateAttachmentId());
       
   287 	}
       
   288 
       
   289 void CMsvAttachmentManager::AddAttachmentL(const TDesC& aFilePath, CMsvAttachment* aAttachmentInfo, TRequestStatus& aStatus)
       
   290 	{
       
   291 	if(iReadOnly)
       
   292 		User::Leave(KErrAccessDenied);
       
   293 	
       
   294 	__ASSERT_ALWAYS(aAttachmentInfo->Type() == CMsvAttachment::EMsvFile, User::Invariant());
       
   295 
       
   296 	RFile fileToCopy;
       
   297 	User::LeaveIfError(fileToCopy.Open(iFs, aFilePath, EFileRead|EFileShareReadersOnly));
       
   298 	CleanupClosePushL(fileToCopy);
       
   299 	
       
   300 	TFileName fileName;
       
   301 	User::LeaveIfError(fileToCopy.Name(fileName));
       
   302 	
       
   303 	RFile newFileHandle;
       
   304 	CreateAttachmentInStoreLC(fileName, newFileHandle, aAttachmentInfo, EFalse);
       
   305 
       
   306 	aStatus=KRequestPending;
       
   307 	iReportStatus=&aStatus;
       
   308 	
       
   309 	iCopyOneFile->Copy(fileToCopy, newFileHandle, iStatus);
       
   310 	CleanupStack::Pop(2, &fileToCopy); // newFileHandle, fileToCopy
       
   311 	SetActive();
       
   312 	}
       
   313 		
       
   314 void CMsvAttachmentManager::AddAttachmentL(RFile& aFileHandle, CMsvAttachment* aAttachmentInfo, TRequestStatus& aStatus)
       
   315 	{
       
   316 	if(iReadOnly)
       
   317 		User::Leave(KErrAccessDenied);
       
   318 	
       
   319 	__ASSERT_ALWAYS(aAttachmentInfo->Type() == CMsvAttachment::EMsvFile, User::Invariant());
       
   320 	
       
   321 	TFileName fileName;
       
   322 	User::LeaveIfError(aFileHandle.Name(fileName));
       
   323 	
       
   324 	RFile newFileHandle;
       
   325 	CreateAttachmentInStoreLC(fileName, newFileHandle, aAttachmentInfo, EFalse);
       
   326 	
       
   327 	aStatus=KRequestPending;
       
   328 	iReportStatus=&aStatus;
       
   329 	
       
   330 	iCopyOneFile->Copy(aFileHandle, newFileHandle, iStatus);
       
   331 	CleanupStack::Pop(&newFileHandle);
       
   332 	SetActive();
       
   333 	}
       
   334 
       
   335 void CMsvAttachmentManager::AddLinkedAttachmentL(const TDesC& aFilePath, CMsvAttachment* aAttachmentInfo, TRequestStatus& aStatus)
       
   336 	{
       
   337 	if(iReadOnly)
       
   338 		User::Leave(KErrAccessDenied);
       
   339 	
       
   340 	__ASSERT_ALWAYS(aAttachmentInfo->Type() == CMsvAttachment::EMsvLinkedFile, User::Invariant());
       
   341 	
       
   342 	// initailise attachment info and take ownership
       
   343 	aAttachmentInfo->SetFilePathL(aFilePath);
       
   344 	User::LeaveIfError(iAttachments.Append(aAttachmentInfo));
       
   345 	aAttachmentInfo->SetId(GenerateAttachmentId());
       
   346 	
       
   347 	aStatus=KRequestPending;
       
   348 	iReportStatus=&aStatus;
       
   349 	CompleteSelf();
       
   350 	}
       
   351 	
       
   352 void CMsvAttachmentManager::AddEntryAsAttachmentL(TMsvId aEntryId, CMsvAttachment* aAttachmentInfo, TRequestStatus& aStatus)
       
   353 	{
       
   354 	if(iReadOnly)
       
   355 		User::Leave(KErrAccessDenied);
       
   356 	
       
   357 	__ASSERT_ALWAYS(aAttachmentInfo->Type() == CMsvAttachment::EMsvMessageEntry, User::Invariant());
       
   358 	
       
   359 	// initailise attachment info and take ownership
       
   360 	User::LeaveIfError(iAttachments.Append(aAttachmentInfo));
       
   361 	aAttachmentInfo->SetId(GenerateAttachmentId());
       
   362 	aAttachmentInfo->SetEntryAttachmentId(aEntryId);
       
   363 	
       
   364 	aStatus=KRequestPending;
       
   365 	iReportStatus=&aStatus;
       
   366 	User::RequestComplete(iReportStatus, KErrNone);
       
   367 	}
       
   368 	
       
   369 void CMsvAttachmentManager::CreateAttachmentL(const TDesC& aFileName, RFile& aAttachmentFile, CMsvAttachment* aAttachmentInfo, TRequestStatus& aStatus)
       
   370 	{
       
   371 	CreateAttachmentL(aFileName, aAttachmentFile, aAttachmentInfo);
       
   372 	
       
   373 	aStatus=KRequestPending;
       
   374 	iReportStatus=&aStatus;
       
   375 	CompleteSelf();
       
   376 	}
       
   377 	
       
   378 	
       
   379 TInt CMsvAttachmentManager::AttachmentCount() const
       
   380 	{
       
   381 	return iAttachments.Count();
       
   382 	}
       
   383 	
       
   384 CMsvAttachment* CMsvAttachmentManager::GetAttachmentInfoL(TInt aIndex)
       
   385 	{
       
   386 	// Create a deep copy the CMsvAttachment object to pass back to the client
       
   387 	CMsvAttachment* currentAttachment = iAttachments[aIndex];
       
   388 	
       
   389 	return CMsvAttachment::NewL(*currentAttachment);
       
   390 	}
       
   391 
       
   392 CMsvAttachment* CMsvAttachmentManager::GetAttachmentInfoL(TMsvAttachmentId aId)
       
   393 	{
       
   394 	return GetAttachmentInfoL(IndexPositionOfAttachmentL(aId));
       
   395 	}
       
   396 
       
   397 void CMsvAttachmentManager::ModifyAttachmentInfoL(CMsvAttachment* aAttachmentInfo)
       
   398 	{
       
   399 	if(iReadOnly)
       
   400 		User::Leave(KErrAccessDenied);
       
   401 	
       
   402 	// Get the index position of the attachment info with the same Id
       
   403 	TInt attachmentIndex = IndexPositionOfAttachmentL(aAttachmentInfo->Id());
       
   404 	__ASSERT_ALWAYS(aAttachmentInfo->Type()==iAttachments[attachmentIndex]->Type(), User::Invariant());
       
   405 	
       
   406 	// Insert the replaced attachment info object into the same position and then
       
   407 	// remove the old one
       
   408 	User::LeaveIfError(iAttachments.Insert(aAttachmentInfo, attachmentIndex));
       
   409 	++attachmentIndex;
       
   410 	delete iAttachments[attachmentIndex];
       
   411 	iAttachments.Remove(attachmentIndex);
       
   412 	}
       
   413 	
       
   414 void CMsvAttachmentManager::ModifyAttachmentInfoL(CMsvAttachment* aAttachmentInfo, TRequestStatus& aStatus)
       
   415 	{
       
   416 	ModifyAttachmentInfoL(aAttachmentInfo);	
       
   417 	aStatus=KRequestPending;
       
   418 	iReportStatus=&aStatus;
       
   419 	CompleteSelf();
       
   420 	}
       
   421 
       
   422 RFile CMsvAttachmentManager::GetAttachmentFileL(TInt aIndex)
       
   423 	{
       
   424 	CMsvAttachment* attachment = iAttachments[aIndex];
       
   425 	
       
   426 	// Make sure that the attachment is a file attachment
       
   427 	if( attachment->Type() == CMsvAttachment::EMsvMessageEntry )
       
   428 		User::Leave(KErrNotSupported);
       
   429 	
       
   430 	RFile attachmentFile;
       
   431 	
       
   432 	if( attachment->Type() == CMsvAttachment::EMsvFile )
       
   433 		{		
       
   434 		iStoreManager.OpenAttachmentL(iEntryId, attachment->FilePath(), attachmentFile);
       
   435 		}
       
   436 	else // attachment->iType == ELinkedFile
       
   437 		{
       
   438 		RFs fs;
       
   439 		fs.Connect();
       
   440 		fs.ShareProtected();
       
   441 		User::LeaveIfError(attachmentFile.Open(fs, attachment->FilePath(), EFileRead | EFileShareReadersOnly));
       
   442 		}
       
   443 	
       
   444 	// handle to attachment file allocated, return to caller
       
   445 	return attachmentFile;
       
   446 	}
       
   447 
       
   448 RFile CMsvAttachmentManager::GetAttachmentFileL(TMsvAttachmentId aId)
       
   449 	{
       
   450 	return GetAttachmentFileL(IndexPositionOfAttachmentL(aId));
       
   451 	}
       
   452 
       
   453 RFile CMsvAttachmentManager::GetAttachmentFileForWriteL(TInt aIndex)
       
   454 	{
       
   455 	if(iReadOnly)
       
   456 		User::Leave(KErrAccessDenied);
       
   457 	
       
   458 	CMsvAttachment* attachment = iAttachments[aIndex];
       
   459 	
       
   460 	// Make sure that the attachment is a file attachment
       
   461 	if( attachment->Type() == CMsvAttachment::EMsvMessageEntry )
       
   462 		User::Leave(KErrNotSupported);
       
   463 	
       
   464 	RFile attachmentFile;
       
   465 	
       
   466 	if( attachment->Type() == CMsvAttachment::EMsvFile )
       
   467 		{		
       
   468 		iStoreManager.OpenAttachmentForWriteL(iEntryId, attachment->FilePath(), attachmentFile);
       
   469 		}
       
   470 	else // attachment->iType == ELinkedFile
       
   471 		{
       
   472 		RFs fs;
       
   473 		fs.Connect();
       
   474 		fs.ShareProtected();
       
   475 		User::LeaveIfError(attachmentFile.Open(fs, attachment->FilePath(), EFileWrite));
       
   476 		}
       
   477 	
       
   478 	// handle to attachment file allocated, return to caller
       
   479 	return attachmentFile;
       
   480 	}
       
   481 
       
   482 RFile CMsvAttachmentManager::GetAttachmentFileForWriteL(TMsvAttachmentId aId)
       
   483 	{
       
   484 	return GetAttachmentFileForWriteL(IndexPositionOfAttachmentL(aId));
       
   485 	}
       
   486 	
       
   487 void CMsvAttachmentManager::RemoveAttachmentL(TInt aIndex, TRequestStatus& aStatus)
       
   488 	{
       
   489 	RemoveAttachmentL(aIndex);
       
   490 	
       
   491 	aStatus=KRequestPending;
       
   492 	iReportStatus=&aStatus;
       
   493 	CompleteSelf();
       
   494 	}
       
   495 	
       
   496 void CMsvAttachmentManager::RemoveAttachmentL(TMsvAttachmentId aId, TRequestStatus& aStatus)
       
   497 	{
       
   498 	RemoveAttachmentL(IndexPositionOfAttachmentL(aId), aStatus);
       
   499 	}
       
   500 
       
   501 TInt CMsvAttachmentManager::IndexPositionOfAttachmentL(TMsvAttachmentId aId) const
       
   502 	{
       
   503 	TInt foundPosition = KErrNotFound;
       
   504 	TInt attachmentCount = iAttachments.Count();
       
   505 	// Go through the attachment list to find the attachment by its id
       
   506 	for( TInt ii=0; ii<attachmentCount; ++ii )
       
   507 		{
       
   508 		if( iAttachments[ii]->Id() == aId )
       
   509 			{
       
   510 			foundPosition = ii;
       
   511 			break;
       
   512 			}
       
   513 		}
       
   514 		
       
   515 	// Leave with KErrNotFound if the attachment id is not found
       
   516 	User::LeaveIfError(foundPosition);
       
   517 	
       
   518 	// return the index position of attachment
       
   519 	return foundPosition;
       
   520 	}
       
   521 
       
   522 void CMsvAttachmentManager::CancelRequest()
       
   523 	{
       
   524 	Cancel();
       
   525 	User::RequestComplete(iReportStatus, KErrCancel);
       
   526 	}
       
   527 	
       
   528 void CMsvAttachmentManager::CreateAttachmentL(const TDesC& aFileName, RFile& aAttachmentFile, CMsvAttachment* aAttachmentInfo)
       
   529 	{
       
   530 	if(iReadOnly)
       
   531 		User::Leave(KErrAccessDenied);
       
   532 	
       
   533 	__ASSERT_ALWAYS(aAttachmentInfo->Type() == CMsvAttachment::EMsvFile, User::Invariant());
       
   534 	
       
   535 	// File name must be provided
       
   536 	if( aFileName.Length() == 0 || aAttachmentFile.SubSessionHandle() != KNullHandle)
       
   537 		User::Leave(KErrArgument);
       
   538 	
       
   539 	TFileName fileName = aFileName;
       
   540 	
       
   541 	CreateAttachmentInStoreLC(fileName, aAttachmentFile, aAttachmentInfo, EFalse);
       
   542 	CleanupStack::Pop(&aAttachmentFile);
       
   543 	}
       
   544 
       
   545 void CMsvAttachmentManager::CreateShareProtectedAttachmentL(const TDesC& aFileName, RFile& aAttachmentFile, CMsvAttachment* aAttachmentInfo)
       
   546 	{
       
   547 	if(iReadOnly)
       
   548 		User::Leave(KErrAccessDenied);
       
   549 	
       
   550 	__ASSERT_ALWAYS(aAttachmentInfo->Type() == CMsvAttachment::EMsvFile, User::Invariant());
       
   551 	
       
   552 	// File name must be provided
       
   553 	if( aFileName.Length() == 0 || aAttachmentFile.SubSessionHandle() != KNullHandle)
       
   554 		User::Leave(KErrArgument);
       
   555 	
       
   556 	TFileName fileName = aFileName;
       
   557 	
       
   558 	CreateAttachmentInStoreLC(fileName, aAttachmentFile, aAttachmentInfo, ETrue);
       
   559 	CleanupStack::Pop(&aAttachmentFile);
       
   560 	}
       
   561 	
       
   562 TInt CMsvAttachmentManager::InternaliseRenameLockL()
       
   563 	{
       
   564 	iRenamed.ResetAndDestroy();
       
   565 	
       
   566 	// if the rename lock file exists internalise it
       
   567 	RFile renameLockFile;
       
   568 	TRAPD(err, iStoreManager.OpenAttachmentL(iEntryId, KTxtRenameLockFile, renameLockFile));
       
   569 	if( err==KErrNone )
       
   570 		{
       
   571 		// got the rename lock file
       
   572 		RFileReadStream renameReadStream(renameLockFile);
       
   573 		renameReadStream.PushL();
       
   574 		TInt renamedCount = renameReadStream.ReadInt32L();
       
   575 		for( TInt ii=0; ii<renamedCount; ++ii )
       
   576 			{
       
   577 			CMsvAttachmentRename* renameInfo = CMsvAttachmentRename::NewLC();
       
   578 			renameReadStream >> *renameInfo;
       
   579 			iRenamed.AppendL(renameInfo);
       
   580 			CleanupStack::Pop(renameInfo);
       
   581 			}
       
   582 		CleanupStack::PopAndDestroy(); // renameReadStream
       
   583 		}
       
   584 	else if( err==KErrNotFound || err==KErrPathNotFound )
       
   585 		{
       
   586 		err = KErrNotFound; // rename lock file not found
       
   587 		}
       
   588 	else
       
   589 		{
       
   590 		User::Leave(err);
       
   591 		}
       
   592 		
       
   593 	return err; 
       
   594 	}
       
   595 	
       
   596 void CMsvAttachmentManager::ExternaliseRenameLockL()
       
   597 	{
       
   598 	__ASSERT_DEBUG(iRenamed.Count()>0, User::Invariant());
       
   599 	
       
   600 	// Get the rename lock file to store the rename information
       
   601 	RFile renameLockFile;
       
   602 	TFileName lockFileName(KTxtRenameLockFile());
       
   603 	iStoreManager.ReplaceAttachmentForWriteL(iEntryId, lockFileName, renameLockFile);
       
   604 	RFileWriteStream renameWriteStream(renameLockFile);
       
   605 	renameWriteStream.PushL();
       
   606 	
       
   607 	// Externalise the count and each rename file info object
       
   608 	TInt renamedCount = iRenamed.Count();
       
   609 	renameWriteStream.WriteInt32L(renamedCount);
       
   610 	for( TInt ii=0; ii<renamedCount; ++ii )
       
   611 		{
       
   612 		renameWriteStream << *(iRenamed[ii]);
       
   613 		}
       
   614 	
       
   615 	renameWriteStream.CommitL();	
       
   616 	CleanupStack::PopAndDestroy(); // renameWriteStream
       
   617 	}
       
   618 	
       
   619 void CMsvAttachmentManager::DoAttachmentRenameL(TInt aIndex, const TDesC& aNewName)
       
   620 	{
       
   621 	if(iReadOnly)
       
   622 		{
       
   623 		User::Leave(KErrAccessDenied);
       
   624 		}
       
   625 	
       
   626 	CMsvAttachment* renameAttachment = iAttachments[aIndex];	
       
   627 	__ASSERT_ALWAYS(renameAttachment->Type() == CMsvAttachment::EMsvFile, User::Invariant());	
       
   628 	
       
   629 	// Build the attachment rename infomation and store in array
       
   630 	TPtrC oldFilePath(renameAttachment->FilePath());
       
   631 	CMsvAttachmentRename* renameInfo = CMsvAttachmentRename::NewLC(oldFilePath, aNewName);
       
   632 	iRenamed.AppendL(renameInfo);
       
   633 	CleanupStack::Pop(renameInfo);
       
   634 	
       
   635 	// Save the rename infomation
       
   636 	ExternaliseRenameLockL();
       
   637 	
       
   638 	// Rename and update the attachment info
       
   639 	TParse newFilePath;
       
   640 	User::LeaveIfError(newFilePath.Set(aNewName, &oldFilePath, NULL));
       
   641 	User::LeaveIfError(iStoreManager.RenameAttachment(iEntryId, oldFilePath, aNewName));
       
   642 	renameAttachment->SetFilePathL(newFilePath.FullName());
       
   643 	}
       
   644 	
       
   645 void CMsvAttachmentManager::RenameAttachmentL(TInt aIndex, const TDesC& aNewName)
       
   646 	{
       
   647     DoAttachmentRenameL(aIndex, aNewName);
       
   648 	}
       
   649 
       
   650 void CMsvAttachmentManager::RenameAttachmentL(TInt aIndex, const TDesC& aNewName, TRequestStatus& aStatus)
       
   651 	{
       
   652 	DoAttachmentRenameL(aIndex, aNewName);
       
   653 	
       
   654 	aStatus=KRequestPending;
       
   655 	iReportStatus=&aStatus;
       
   656 	User::RequestComplete(iReportStatus, KErrNone);			
       
   657 	}
       
   658 
       
   659 void CMsvAttachmentManager::RemoveAttachmentL(TInt aIndex)
       
   660 	{
       
   661 	if(iReadOnly)
       
   662 		User::Leave(KErrAccessDenied);
       
   663 	
       
   664 	// If the attachment is a file attachment, we need remove the attachment object
       
   665 	// and mark the file for deletion so that it is deleted only when SaveL is called.
       
   666 	// This ensures that if the store is reverted, the attachment files are still in
       
   667 	// the message store
       
   668 	CMsvAttachment* deleteAttachment = iAttachments[aIndex];
       
   669 	
       
   670 	// only need to mark the file for deletion if it is an attachment stored in the
       
   671 	// message server, ie. dont delete linked attachments
       
   672 	if( deleteAttachment->Type() == CMsvAttachment::EMsvFile )
       
   673 		{
       
   674 		HBufC* deleteFilePath = deleteAttachment->FilePath().AllocLC();
       
   675 		User::LeaveIfError(iDeletedAttachments.Append(deleteFilePath));
       
   676 		CleanupStack::Pop(deleteFilePath);
       
   677 		} 
       
   678 	
       
   679 	iAttachments.Remove(aIndex);
       
   680 	delete deleteAttachment;
       
   681 	}
       
   682