--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/email/imap4mtm/imapmailstore/src/cmsvplainbodytextqueueentry.cpp Thu Dec 17 08:44:11 2009 +0200
@@ -0,0 +1,285 @@
+// Copyright (c) 2007-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:
+// CMSVPLAINBODYTEXTQUEENTRY.CPP
+//
+//
+
+#include "cmsvplainbodytextqueueentry.h"
+#include "cimaputils.h"
+#include "cimaplogger.h"
+
+#include <cmsvplainbodytext.h>
+
+const TInt KOutOfOrderChunks = 3;
+
+
+
+CPlainBodyChunkInfo* CPlainBodyChunkInfo::NewL(TInt aChunkNumber, HBufC8* aData)
+ {
+ CPlainBodyChunkInfo* self = new(ELeave) CPlainBodyChunkInfo(aChunkNumber,aData);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop();
+ return self;
+ }
+
+/**
+Constructor for CPlainBodyChunkInfo.
+*/
+CPlainBodyChunkInfo::CPlainBodyChunkInfo(TInt aChunkNumber, HBufC8* aData)
+:iChunkNumber(aChunkNumber), iData(aData)
+ {
+ }
+
+void CPlainBodyChunkInfo::ConstructL()
+ {
+
+ }
+
+/**
+Destructor for CPlainBodyChunkInfo.
+*/
+CPlainBodyChunkInfo::~CPlainBodyChunkInfo()
+ {
+ delete iData;
+ }
+
+/**
+Constructor.
+*/
+CMsvPlainBodyTextQueueEntry::CMsvPlainBodyTextQueueEntry(TInt aTotalChunks, CImapMailStore& aParent, CMsvServerEntry& aServerEntry, CImapSettings& aImapSettings, CFetchBodyInfo& aFetchBodyInfo, TInt aLogId, MMailStoreObserver& aObserver, MChunkOutOfOrderObserver& aChunkObserver, TBool aBinaryCap)
+ :CQueueEntryBase(aFetchBodyInfo.PartId(), EPlainTextBody, aParent, aServerEntry, aObserver),
+ iTotalChunks(aTotalChunks),
+ iEncoding(aFetchBodyInfo.ContentTransferEncoding()),
+ iCharsetId(aFetchBodyInfo.CharsetId()),
+ iBodyPartRemainingSize(aFetchBodyInfo.BodyPartRemainingSize()),
+ iImapSettings(aImapSettings),
+ iLogId(aLogId),
+ iChunkObserver(aChunkObserver)
+#if (defined SYMBIAN_EMAIL_CAPABILITY_SUPPORT)
+ , iBinaryCap(aBinaryCap)
+#endif
+ {
+ //to ignore compilation warnings
+ aBinaryCap = aBinaryCap;
+ }
+
+
+/**
+Destructor.
+*/
+CMsvPlainBodyTextQueueEntry::~CMsvPlainBodyTextQueueEntry()
+ {
+ delete iStoreUtilities;
+ iDataArray.ResetAndDestroy();
+ iDataArray.Close();
+ delete iPlainBodyText;
+ delete iStore;
+ delete iDecodedData;
+ }
+
+/**
+NewL Factory functions.
+*/
+CMsvPlainBodyTextQueueEntry* CMsvPlainBodyTextQueueEntry::NewL(TInt aTotalChunks, CImapMailStore& aParent, CMsvServerEntry& aServerEntry, CImapSettings& aImapSettings, CFetchBodyInfo& aFetchBodyInfo, TInt aLogId, MMailStoreObserver& aObserver, MChunkOutOfOrderObserver& aChunkObserver, TBool aBinaryCap)
+ {
+ CMsvPlainBodyTextQueueEntry* self=new(ELeave)CMsvPlainBodyTextQueueEntry(aTotalChunks, aParent, aServerEntry, aImapSettings, aFetchBodyInfo, aLogId, aObserver, aChunkObserver, aBinaryCap);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop();
+ return self;
+ }
+
+/**
+The Two Phase constructor
+*/
+void CMsvPlainBodyTextQueueEntry::ConstructL()
+ {
+ BaseConstructL();
+
+ // Get the default charset
+ CCnvCharacterSetConverter* characterConverter = CCnvCharacterSetConverter::NewL();
+ CleanupStack::PushL(characterConverter);
+ CImConvertCharconv* charConv = CImConvertCharconv::NewL(*characterConverter, CImapUtils::GetRef().Fs());
+ CleanupStack::PushL(charConv);
+
+ TUint defaultCharset = charConv->SystemDefaultCharset();
+ CleanupStack::PopAndDestroy(2, characterConverter);
+ if(iCharsetId == KUidMsvCharsetNone)
+ {
+ iCharsetId = defaultCharset;
+ }
+
+ iStoreUtilities=CStoreUtilities::NewL(iEncoding,iCharsetId,CImapUtils::GetRef().Fs());
+ iServerEntry.SetEntry(iId);
+ iStore = iServerEntry.EditStoreL();
+ TInt is8Bit = iImapSettings.Store8BitData();
+ iPlainBodyText = iStore->InitialisePlainBodyTextForWriteL(is8Bit,iCharsetId,defaultCharset);
+ }
+
+
+
+/**
+Adds a chunk of body data to the data array and sorts the array
+@param aData the body data, ownership is taken.
+@param aChunkNumber the order number in which the chunk makes up the whole data.
+@return TBool indicates whether the FETCH command need to be sent to server
+ ETrue : Send the FETCH command.
+ EFalse: Do not send the FETCH command.
+*/
+
+TBool CMsvPlainBodyTextQueueEntry::AddChunkL(HBufC8* aData, TInt aChunkNumber, TInt aExtraFetchRequestCount)
+ {
+#if (defined SYMBIAN_EMAIL_CAPABILITY_SUPPORT)
+ if(iBinaryCap)
+ {
+ iExtraFetchRequestCount=aExtraFetchRequestCount;
+ }
+#else
+ //to ignore compilation warnings
+ aExtraFetchRequestCount = aExtraFetchRequestCount;
+#endif
+ TBool sendCommand = ETrue;
+ __LOG_FORMAT((iLogId, "CMsvPlainBodyTextQueueEntry::AddChunkL chunk number = %d",aChunkNumber));
+ CleanupStack::PushL(aData);
+ //make sure the chunk is within range.
+ __ASSERT_DEBUG(aChunkNumber<iTotalChunks,TImapServerPanic::ImapPanic(TImapServerPanic::EMailStoreDataChunkOutOfRange));
+ //append the chunk
+ CPlainBodyChunkInfo* chunkInfo = CPlainBodyChunkInfo::NewL(aChunkNumber, aData);
+ CleanupStack::Pop(aData);
+ CleanupStack::PushL(chunkInfo);
+
+ TLinearOrder<CPlainBodyChunkInfo>compareChunks(CompareChunks);
+ iDataArray.InsertInOrderL(chunkInfo,compareChunks);
+
+ if(iDataArray.Count() >= KOutOfOrderChunks)
+ {
+ sendCommand = EFalse;
+ }
+
+ CleanupStack::Pop(chunkInfo);
+
+ if(!IsActive())
+ {
+ CompleteSelf();
+ }
+ return sendCommand;
+ }
+
+
+/**
+Used to sort chunks of data by chunk number.
+@param aChunkBodyInfo1 the first chunk in the comparision
+@param aChunkBodyInfo2 the second chunk in the comparision
+@return TInt the difference between the first chunks number and the second chunks number.
+*/
+TInt CMsvPlainBodyTextQueueEntry::CompareChunks(const CPlainBodyChunkInfo& aChunkBodyInfo1, const CPlainBodyChunkInfo& aChunkBodyInfo2)
+ {
+ return aChunkBodyInfo1.iChunkNumber-aChunkBodyInfo2.iChunkNumber;
+ }
+
+TInt CMsvPlainBodyTextQueueEntry::RunError(TInt aError)
+ {
+ return CQueueEntryBase::RunError(aError);
+ }
+
+
+
+/**
+Uses CMsvPlainBodyText to asynchronousy store the requests data object.
+@param
+@return
+*/
+void CMsvPlainBodyTextQueueEntry::RunL()
+ {
+ User::LeaveIfError(iStatus.Int());
+ if(iReadyToRemoveChunk)
+ {
+ delete iDecodedData;
+ iDecodedData=NULL;
+ iChunkObserver.EnableSendFetch();
+ iReadyToRemoveChunk=EFalse;
+ }
+
+#if (defined SYMBIAN_EMAIL_CAPABILITY_SUPPORT)
+ if(iBinaryCap && iExtraFetchRequestCount > 0)
+ {
+ iTotalChunks-=iExtraFetchRequestCount;
+ //reset iExtraFetchRequestCount to zero
+ iExtraFetchRequestCount=0;
+ }
+#endif
+
+ //if we have appended all the chunks then store the data.
+ if(iNextExpectedChunk==iTotalChunks)
+ {
+ __LOG_FORMAT((iLogId, "CMsvPlainBodyTextQueueEntry::RunL Commiting body data..."));
+ iPlainBodyText->CommitL();
+ //call back to the observer as the operation is complete
+ StoreComplete(KErrNone);
+ //request can be removed from the queue
+ iParent.RemoveFromQueueAndDelete(this);
+ }
+ else if(iDataArray.Count()>0 && iDataArray[0]->iChunkNumber==iNextExpectedChunk )
+ {
+ ++iNextExpectedChunk;
+ //is this the last chunk?
+ TBool lastChunk=(iNextExpectedChunk==iTotalChunks);
+ HBufC8* decodedData = NULL;
+#if (defined SYMBIAN_EMAIL_CAPABILITY_SUPPORT)
+ if(iBinaryCap)
+ {
+ const TPtrC8& bodyData = *(iDataArray[0]->iData);
+ decodedData = HBufC8::NewL(bodyData.Length());
+ // Message body is downloaded using Fetch Binary and the data is decoded by the IMAP mail server
+ // Nothing to do, just copy data
+ decodedData->Des().Append(bodyData);
+ }
+ else
+#endif
+ {
+ // create a new buffer, decodedData and push it to CleannupStack because AttachFooterInfoL will
+ // pop decodedData first and pushes it when it returns.
+ __LOG_FORMAT((iLogId, "CMsvPlainBodyTextQueueEntry::RunL Decoding..."));
+ decodedData = iStoreUtilities->DecodeL(*(iDataArray[0]->iData), lastChunk);
+ }
+
+ __ASSERT_DEBUG(decodedData!=NULL, TImapServerPanic::ImapPanic(TImapServerPanic::EMailStoreDecodeDataNull));
+ CleanupStack::PushL(decodedData);
+
+ //if this is the last chunk and if was a partial download then add footer
+ if(iBodyPartRemainingSize && iNextExpectedChunk==iTotalChunks)
+ {
+ __LOG_FORMAT((iLogId, "CMsvPlainBodyTextQueueEntry::RunL AttachFooterInfoL..."));
+ iStoreUtilities->AttachFooterInfoL(iBodyPartRemainingSize, iImapSettings, decodedData);
+ }
+
+ // pop decodedData since the ownership will be transferred to iDecodedData.
+ CleanupStack::Pop(decodedData);
+ __ASSERT_DEBUG(iDecodedData == NULL, TImapServerPanic::ImapPanic(TImapServerPanic::EMailStoreDecodeDataNotNull));
+
+ // transferring ownership to iDecodedData.
+ iDecodedData = decodedData;
+
+ __LOG_FORMAT((iLogId, "CMsvPlainBodyTextQueueEntry::RunL StoreChunk..."));
+ iPlainBodyText->StoreChunkL(*iDecodedData, iStatus);
+ SetActive();
+
+ //delete the origninal encoded chunk
+ CPlainBodyChunkInfo* chunkInfo=iDataArray[0];
+ iDataArray.Remove(0);
+ delete chunkInfo;
+ iReadyToRemoveChunk=ETrue;
+ }
+ }