email/imap4mtm/imapmailstore/src/cattachmentqueueentry.cpp
changeset 0 72b543305e3a
equal deleted inserted replaced
-1:000000000000 0:72b543305e3a
       
     1 // Copyright (c) 2006-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 <mmsvattachmentmanager.h>
       
    17 #include <mmsvattachmentmanagersync.h>
       
    18 #include <imcvtext.h>
       
    19 #include <miuthdr.h>
       
    20 #include "cattachmentqueueentry.h"
       
    21 #include "cimaputils.h"
       
    22 #include "cimaplogger.h"
       
    23 
       
    24 /**
       
    25 Used to sort chunks of data by chunk number.
       
    26 @param aChunkAttachmentInfo1 	the first chunk in the comparision
       
    27 @param aChunkAttachmentInfo2 	the second chunk in the comparision
       
    28 @return TInt					the difference between the first chunks number and the second chunks number.
       
    29 */	
       
    30 TInt CAttachmentQueueEntry::CompareChunks(const CChunkAttachmentInfo& aChunkAttachmentInfo1, const CChunkAttachmentInfo& aChunkAttachmentInfo2)
       
    31 	{
       
    32 	return aChunkAttachmentInfo1.iChunkNumber-aChunkAttachmentInfo2.iChunkNumber;	
       
    33 	}
       
    34 
       
    35 /**
       
    36 Constructor.
       
    37 */
       
    38 CChunkAttachmentInfo::CChunkAttachmentInfo(TInt aChunkNumber,HBufC8* aData)
       
    39 :iChunkNumber(aChunkNumber),iData(aData)
       
    40 	{
       
    41 	}
       
    42 
       
    43 /**
       
    44 Destructor.
       
    45 */	
       
    46 CChunkAttachmentInfo::~CChunkAttachmentInfo()
       
    47 	{
       
    48 	delete iData;
       
    49 	}
       
    50 		
       
    51 /**
       
    52 Constructor.
       
    53 */
       
    54 CAttachmentQueueEntry::CAttachmentQueueEntry(TInt aTotalChunks,CImapMailStore& aParent,CMsvServerEntry& aServerEntry,CImapSettings& aImapSettings,CFetchBodyInfo& aFetchBodyInfo,TInt aLogId,MMailStoreObserver& aObserver)
       
    55 	: CQueueEntryBase(aFetchBodyInfo.PartId(),EAttachment,aParent,aServerEntry,aObserver),
       
    56 	iTotalChunks(aTotalChunks),
       
    57 	iEncoding(aFetchBodyInfo.ContentTransferEncoding()),
       
    58 	iImapSettings(aImapSettings),
       
    59 	iCaf(aFetchBodyInfo.Caf()),
       
    60 	iLogId(aLogId)
       
    61 	{
       
    62 	}
       
    63 	
       
    64 /**
       
    65 Destructor.
       
    66 */
       
    67 CAttachmentQueueEntry::~CAttachmentQueueEntry()
       
    68 	{
       
    69 	iFile.Close();
       
    70 	iDataArray.ResetAndDestroy();
       
    71 	delete iStoreUtilities;
       
    72 	delete iDecodedData;
       
    73 	iDataArray.Close();
       
    74 	}
       
    75 
       
    76 /**
       
    77 Factory constructors.
       
    78 */
       
    79 CAttachmentQueueEntry* CAttachmentQueueEntry::NewL(TInt aTotalChunks,CImapMailStore& aParent,CMsvServerEntry& aServerEntry,CImapSettings& aImapSettings,CFetchBodyInfo& aFetchBodyInfo,TInt aLogId,MMailStoreObserver& aObserver)
       
    80 	{
       
    81 	CAttachmentQueueEntry* self=new(ELeave)CAttachmentQueueEntry(aTotalChunks,aParent,aServerEntry,aImapSettings,aFetchBodyInfo,aLogId,aObserver);
       
    82 	CleanupStack::PushL(self);
       
    83 	self->ConstructL();	
       
    84 	CleanupStack::Pop();
       
    85 	return self;
       
    86 	}
       
    87 	
       
    88 void CAttachmentQueueEntry::ConstructL()
       
    89 	{
       
    90 	BaseConstructL();
       
    91 	iServerEntry.SetEntry(iId);	
       
    92 	//create an attachment ready for downloading	
       
    93 	CreateAttachmentL(iServerEntry);
       
    94 	//charsetId is not used by attachments
       
    95 	TUint charsetId=0;
       
    96 	iStoreUtilities=CStoreUtilities::NewL(iEncoding,charsetId, CImapUtils::GetRef().Fs());
       
    97 	}
       
    98 
       
    99 /**
       
   100 Adds a chunk of attachment data to the data array and sorts the array
       
   101 @param aData 			the attachment data, ownership  is taken.
       
   102 @param aChunkNumber 	the order number in which the chunk makes up the whole data.
       
   103 @return 
       
   104 */	
       
   105 void CAttachmentQueueEntry::AddChunkL(HBufC8* aData,TInt aChunkNumber)
       
   106 	{
       
   107 	__LOG_FORMAT((iLogId, "CAttachmentQueueEntry::AddChunkL chunk number = %d",aChunkNumber));
       
   108 	CleanupStack::PushL(aData);
       
   109 	__ASSERT_DEBUG(aChunkNumber<iTotalChunks,TImapServerPanic::ImapPanic(TImapServerPanic::EMailStoreDataChunkOutOfRange));
       
   110 	
       
   111  	CChunkAttachmentInfo* chunkInfo = new(ELeave) CChunkAttachmentInfo(aChunkNumber,aData); 	
       
   112  	CleanupStack::PushL(chunkInfo);
       
   113 	TLinearOrder<CChunkAttachmentInfo>compareChunks(CompareChunks);
       
   114    	iDataArray.InsertInOrderL(chunkInfo,compareChunks);
       
   115     CleanupStack::Pop(2,aData);
       
   116     
       
   117     if(!IsActive())
       
   118 		{
       
   119   	  	CompleteSelf();	
       
   120 		}
       
   121 	}
       
   122 	
       
   123 /**
       
   124 Creates and stores an CMsvAttachment object and an empty file as a place holder for an attachment
       
   125 	    that is not currently being downloaded.
       
   126 @param 	aServerEntry entry used to access the store.
       
   127 		aFile used to create the attachment file.
       
   128 @return
       
   129 */
       
   130 void CAttachmentQueueEntry::CreateAttachmentInfoL(CMsvServerEntry& aServerEntry,RFile& aFile)
       
   131 	{
       
   132 	CMsvStore* store = aServerEntry.EditStoreL();
       
   133 	CleanupStack::PushL(store);
       
   134 
       
   135 	MMsvAttachmentManager& attachmentMgr = store->AttachmentManagerL();
       
   136 
       
   137 	TInt attachmentCount=attachmentMgr.AttachmentCount();
       
   138 	// if we are just regestering that the attachment exists we dont need to do any more. 
       
   139 	// need to do anything	
       
   140 	if(attachmentCount!=0)
       
   141 		{
       
   142 		CleanupStack::PopAndDestroy(store);
       
   143 		return;
       
   144 		}
       
   145 	
       
   146 	MMsvAttachmentManagerSync& attachmentMgrSync = store->AttachmentManagerExtensionsL();
       
   147 	// Now create the attachment entry
       
   148 	CMsvAttachment* attachment = CMsvAttachment::NewL(CMsvAttachment::EMsvFile);
       
   149 	CleanupStack::PushL(attachment);
       
   150 	
       
   151 	// Need to create the MIME-type information - first get the MIME headers
       
   152 	//check if their present if not leave the mime type blank
       
   153 	if(store->IsPresentL(KUidMsgFileMimeHeader))
       
   154 		{
       
   155 		CImMimeHeader* mimeHeaders = CImMimeHeader::NewLC();
       
   156 		mimeHeaders->RestoreL(*store);
       
   157 
       
   158 		HBufC8* buf = HBufC8::NewLC(mimeHeaders->ContentSubType().Length() + mimeHeaders->ContentType().Length() + 1);
       
   159 		TPtr8 ptr(buf->Des());
       
   160 		ptr.Copy(mimeHeaders->ContentType());
       
   161 		ptr.Append(KImcvForwardSlash);
       
   162 		ptr.Append(mimeHeaders->ContentSubType());
       
   163 		//set the mime time
       
   164 		attachment->SetMimeTypeL(ptr);
       
   165 		CleanupStack::PopAndDestroy(2, mimeHeaders);	
       
   166 		}
       
   167 
       
   168 	//set flags	
       
   169 	attachment->SetAttachmentNameL(aServerEntry.Entry().iDetails);	
       
   170 	attachment->SetComplete(EFalse);
       
   171 	//if not downloading then set the size here
       
   172 	attachment->SetSize(aServerEntry.Entry().iSize);
       
   173 	//Creates an empty file representing the attachment, used by MMsvAttachmentManagerSync
       
   174 	attachmentMgrSync.CreateAttachmentL(aServerEntry.Entry().iDetails,aFile,attachment);
       
   175  	// ownership passed to attachment manager
       
   176 	CleanupStack::Pop(attachment);	
       
   177 	//commit changes
       
   178 	store->CommitL();
       
   179 	CleanupStack::PopAndDestroy(store);
       
   180 	}
       
   181 	
       
   182 /**
       
   183 Creates and stores a CMsvAttachment object and file representing the attachment being downloaded.
       
   184 @param 	aServerEntry entry used to access the store.			
       
   185 @return
       
   186 */
       
   187 void CAttachmentQueueEntry::CreateAttachmentL(CMsvServerEntry& aServerEntry)
       
   188 	{
       
   189 	__LOG_FORMAT((iLogId, "CAttachmentQueueEntry::CreateAttachmentL"));
       
   190 	
       
   191 	CMsvStore* store = aServerEntry.EditStoreL();
       
   192 	CleanupStack::PushL(store);
       
   193 
       
   194 	MMsvAttachmentManager& attachmentMgr = store->AttachmentManagerL();
       
   195 
       
   196 	TInt attachmentCount=attachmentMgr.AttachmentCount();
       
   197 
       
   198 	//delete existing attachments
       
   199 	for(TInt i=0;i<attachmentCount;++i)
       
   200 		{
       
   201 		// Remove [0] as array is shuffled. Once index [n] is removed n+1 becomes n
       
   202 		store->AttachmentManagerExtensionsL().RemoveAttachmentL(0);
       
   203 		}
       
   204 	if(attachmentCount)
       
   205 		{
       
   206 		store->CommitL();	
       
   207 		}	
       
   208 
       
   209 	MMsvAttachmentManagerSync& attachmentMgrSync = store->AttachmentManagerExtensionsL();
       
   210 	// Now create the attachment entry
       
   211 	CMsvAttachment* attachment = CMsvAttachment::NewL(CMsvAttachment::EMsvFile);
       
   212 	CleanupStack::PushL(attachment);
       
   213 	
       
   214 	// Need to create the MIME-type information - first get the MIME headers
       
   215 	//check if their present if not leave the mime type blank
       
   216 	if(store->IsPresentL(KUidMsgFileMimeHeader))
       
   217 		{
       
   218 		CImMimeHeader* mimeHeaders = CImMimeHeader::NewLC();
       
   219 		mimeHeaders->RestoreL(*store);
       
   220 
       
   221 		HBufC8* buf = HBufC8::NewLC(mimeHeaders->ContentSubType().Length() + mimeHeaders->ContentType().Length() + 1);
       
   222 		TPtr8 ptr(buf->Des());
       
   223 		ptr.Copy(mimeHeaders->ContentType());
       
   224 		ptr.Append(KImcvForwardSlash);
       
   225 		ptr.Append(mimeHeaders->ContentSubType());
       
   226 		//set the mime time
       
   227 		attachment->SetMimeTypeL(ptr);
       
   228 		CleanupStack::PopAndDestroy(2, mimeHeaders);	
       
   229 		}
       
   230 
       
   231 	//set flags	
       
   232 	attachment->SetAttachmentNameL(aServerEntry.Entry().iDetails);	
       
   233 	attachment->SetComplete(EFalse);
       
   234 	
       
   235 	//is caf interested in this attachment?
       
   236 	
       
   237 	if(iCaf!=NULL && iCaf->Registered())
       
   238 		{
       
   239 		iCaf->PrepareProcessingL(); // Init the CAF import file session
       
   240 		RFile startFile;
       
   241 		TFileName suggestedFileName;
       
   242 		if(iCaf->GetSuggestedAttachmentFileName(suggestedFileName) == KErrNone) // CAF agent may provide a filename
       
   243 			{
       
   244 			attachmentMgrSync.CreateAttachmentL(suggestedFileName,startFile,attachment);
       
   245 			}
       
   246 		else
       
   247 			{
       
   248 			attachmentMgrSync.CreateAttachmentL(aServerEntry.Entry().iDetails,startFile,attachment);
       
   249 			}
       
   250 			
       
   251 		iCaf->StartProcessing(iImapSettings.DefaultAttachmentName(),attachment->FilePath(),aServerEntry,startFile); // Init the CAF session
       
   252 		startFile.Close();
       
   253 		}
       
   254 	else
       
   255 		{
       
   256 		// Normal behaviour
       
   257 		attachmentMgrSync.CreateAttachmentL(aServerEntry.Entry().iDetails,iFile,attachment);
       
   258 		}
       
   259 
       
   260 	CleanupStack::Pop(attachment);	
       
   261 	//commit changes
       
   262 	store->CommitL();
       
   263 	CleanupStack::PopAndDestroy(store);
       
   264 		
       
   265 	}
       
   266 	
       
   267 void CAttachmentQueueEntry::DoCancel()
       
   268 	{
       
   269 	//there is no way to cancel the RFile::Write() request.	
       
   270 	delete iDecodedData;
       
   271 	iDecodedData=NULL;
       
   272 	}
       
   273 	
       
   274 	
       
   275 void CAttachmentQueueEntry::CancelRequest()
       
   276 	{
       
   277 	//any error is ingnored
       
   278 	TRAP_IGNORE(CancelRequestL());	
       
   279 	}
       
   280 	
       
   281 void CAttachmentQueueEntry::CancelRequestL()
       
   282 	{
       
   283 	if (iCaf && iCaf->Processing())
       
   284 		{
       
   285 		iCaf->EndProcessingL();
       
   286 		}
       
   287 	else
       
   288 		{
       
   289 		iFile.Flush();
       
   290 		iFile.Close();
       
   291 		}
       
   292 
       
   293 	CMsvStore* store = iServerEntry.EditStoreL(); 
       
   294 	CleanupStack::PushL(store);
       
   295 	// Could be multiple attachments in the folder.
       
   296 	TInt attachmentCount = store->AttachmentManagerL().AttachmentCount();
       
   297 	for(TInt i=0;i<attachmentCount;i++)
       
   298 		{
       
   299 		// Remove [0] as array is shuffled. Once index [n] is removed n+1 becomes n
       
   300 		store->AttachmentManagerExtensionsL().RemoveAttachmentL(0);
       
   301 		}
       
   302 	if(attachmentCount)
       
   303 		{
       
   304 		store->CommitL();	
       
   305 		}
       
   306 	CleanupStack::PopAndDestroy(store);
       
   307 	//create attachment info
       
   308 	CreateAttachmentInfoL(iServerEntry,iFile);	
       
   309 	}
       
   310 	
       
   311 TInt CAttachmentQueueEntry::RunError(TInt aError)
       
   312 	{
       
   313 	delete iDecodedData;
       
   314 	iDecodedData=NULL;
       
   315 	iDataArray.Close();
       
   316 	return CQueueEntryBase::RunError(aError);
       
   317 	}
       
   318 	
       
   319 /**
       
   320 Uses an RFile object to asynchronously write the attachment data to the file system.
       
   321 @param 	 
       
   322 @return
       
   323 */
       
   324 void CAttachmentQueueEntry::RunL()
       
   325 	{	
       
   326 	
       
   327 	//if we have just saved a chunk of data to the file store then we can delete the chunk.
       
   328 	if(iReadyToRemoveChunk)
       
   329 		{
       
   330 		delete iDecodedData;
       
   331 		iDecodedData=NULL;
       
   332 		iReadyToRemoveChunk=EFalse;	
       
   333 		}
       
   334 		
       
   335 	//if we have finished then we close the file and call back to the observer
       
   336 	if(iNextExpectedChunk==iTotalChunks)
       
   337 		{
       
   338 		
       
   339 		if(iCaf!=NULL && iCaf->Processing())
       
   340 			{
       
   341 			__LOG_FORMAT((iLogId, "CAttachmentQueueEntry::RunL finished caf processing..."));
       
   342 			iCaf->EndProcessingL();		
       
   343 			}
       
   344 		else
       
   345 			{
       
   346 			__LOG_FORMAT((iLogId, "CAttachmentQueueEntry::RunL storing attachment..."));
       
   347 			iFile.Close();	
       
   348 			}
       
   349 		
       
   350 		StoreComplete(KErrNone);
       
   351 		//request can be removed from the queue
       
   352 		iParent.RemoveFromQueueAndDelete(this);	
       
   353 		}
       
   354 	//if we have an item of contiguous data in the data array then write it to the file asynchronously
       
   355 	else if(iDataArray.Count()>0 && iDataArray[0]->iChunkNumber==iNextExpectedChunk )
       
   356 		{
       
   357 		++iNextExpectedChunk;
       
   358 		//is this the last chunk?
       
   359 		TBool lastChunk=(iNextExpectedChunk==iTotalChunks);
       
   360 		//decode the data
       
   361 		iDecodedData=iStoreUtilities->DecodeL(*(iDataArray[0]->iData),lastChunk);
       
   362 		
       
   363 		if(iCaf!=NULL && iCaf->Processing())
       
   364 			{
       
   365 			iCaf->WriteData(*iDecodedData);
       
   366 			CompleteSelf();
       
   367 			}
       
   368 		else
       
   369 			{
       
   370 			iFile.Write(*iDecodedData,iStatus);		
       
   371 			SetActive();
       
   372 			}
       
   373 		//delete the origninal encoded chunk
       
   374 		CChunkAttachmentInfo* chunkInfo=iDataArray[0];
       
   375 		iDataArray.Remove(0);
       
   376 		delete chunkInfo;	
       
   377 			
       
   378 		iReadyToRemoveChunk=ETrue;
       
   379 		}
       
   380 	}