--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/email/pop3andsmtpmtm/popservermtm/src/POPSTOPPOP.CPP Fri Jun 04 10:25:39 2010 +0100
@@ -0,0 +1,429 @@
+// Copyright (c) 2006-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 <e32std.h>
+
+#include "POPSMBX.H"
+#include "POPS.H"
+#include "POPSOP.H" //CImPop3Operations
+
+// includes for IMCV stuff
+#include <imcvrecv.h>
+#include <logwrap.h>
+#include <logwraplimits.h>
+
+#include <bautils.h>
+#include <msvutils.h>
+#include <imcvutil.h>
+
+#include <imcm.rsg>
+
+#include "PopsTopPop.h"
+#include "POPS.H"
+#include "POPSOP.H" //CImPop3Operations
+#include "POPSMBX.H"
+
+#include "POPS.PAN" // imrc's own panic codes
+
+#include "mobilitytestmtmapi.h"
+
+// IMRC Panic function
+GLREF_C void Panic(TPopsPanic aPanic);
+
+CImPop3TopPopulate* CImPop3TopPopulate::NewL(const CMsvEntrySelection& aRemoteEntry, CMsvServerEntry& aLocalEntry, TInt aLimit, CImPop3Session* aPop3Session, RFs& anFs, CImLogMessage* aLogMessage, TBool aDisconnectedMode, RArray<TUint>& aRemoteSizes)
+ {
+ CImPop3TopPopulate* self = new (ELeave) CImPop3TopPopulate( aLocalEntry, aLimit, aPop3Session, anFs, aLogMessage, aDisconnectedMode, aRemoteSizes);
+
+ CleanupStack::PushL(self);
+ self->ConstructL(aRemoteEntry);
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+CImPop3TopPopulate::~CImPop3TopPopulate()
+ {
+ iRemoteSizes.Close();
+ delete iTop;
+ delete iSource;
+ delete iRecvConverter;
+ }
+
+void CImPop3TopPopulate::StartL(TRequestStatus& aStatus)
+ {
+ iMsgCtr=0;
+ iSavedError = KErrNone;
+ // set up progress obj.
+ iProgress.iTotalMsgs=iSource->Count();
+ iProgress.iMsgsToProcess=iProgress.iTotalMsgs;
+
+ // Do a quick tally on the size of messages which are to be copied / moved.
+ iProgress.iTotalSize = 0;
+ for(TInt i = 0; i < iProgress.iTotalMsgs; ++i)
+ {
+ iDestination.SetEntry(iSource->At(i));
+ if(!iDestination.Entry().Complete())
+ {
+ iProgress.iTotalSize += iRemoteSizes[i];
+ }
+ }
+
+
+ if(iProgress.iTotalMsgs>0)
+ {
+ delete iTop;
+ iTop=NULL;
+ iTop=CImPop3Top::NewL(iPopSession,iRecvConverter,EFalse);
+ DoRetrieveL();
+ Queue(aStatus);
+ }
+ else
+ {
+ aStatus = KRequestPending;
+ TRequestStatus* pS=&aStatus;
+ User::RequestComplete(pS,KErrNone);
+ }
+ }
+
+// ******************************************************************************************
+// Resume function called by the POP Server MTM, once it has completed Migrating to new bearer
+//
+// ******************************************************************************************
+void CImPop3TopPopulate::ResumeL(CImPop3Session* aPopSession, TRequestStatus& aStatus)
+ {
+ iMigratingToNewBearer = EFalse;
+ iPopSession = aPopSession;
+
+ delete iRecvConverter;
+ iRecvConverter = NULL;
+ iRecvConverter = CImRecvConvert::NewL( iFs, &iDestination, KUidMsgTypePOP3, iServiceId);
+ iRecvConverter->SetCaf(*iPopSession->GetCafL(iFs));
+
+ delete iTop;
+ iTop=NULL;
+ iTop=CImPop3Top::NewL(iPopSession,iRecvConverter,EFalse);
+
+ // Set the MIME parser to point at the first message to be processed.
+ iRecvConverter->SetMsvId((*iSource)[iMsgCtr]);
+
+ DoRetrieveL();
+ Queue(aStatus);
+ }
+
+TPop3Progress CImPop3TopPopulate::Progress()
+ {
+ if(iPopTopPopState==EPopTopPopRetrieving)
+ {
+ // Get the Copy/Move Progress
+ iProgress.iBytesDone=iTop->Progress();
+ }
+ else if (iPopTopPopState == EPopTopPopLogging)
+ {
+ // We are doing Logging so the move/copy is complete
+ iProgress.iBytesDone = iProgress.iTotalBytes;
+ }
+ else
+ {
+ iProgress.iBytesDone=0;
+ iProgress.iTotalBytes=0;
+ }
+ return iProgress;
+ }
+
+CImPop3TopPopulate::CImPop3TopPopulate(CMsvServerEntry& aLocalEntry, TInt aLimit, CImPop3Session* aPop3Session, RFs& anFs, CImLogMessage* aLogMessage, TBool aDisconnectedMode, RArray<TUint>& aRemoteSizes)
+ : CMsgActive( KMsgPop3RefreshMailboxPriority ), iDestination(aLocalEntry), iPopSession(aPop3Session),iFs(anFs), iLogMessage(aLogMessage), iDisconnectedMode(aDisconnectedMode), iTopLimit(aLimit), iRemoteSizes(aRemoteSizes)
+ {
+ }
+
+void CImPop3TopPopulate::ConstructL( const CMsvEntrySelection& aRemoteSelection)
+ {
+ // make our copy of aRemoteEntry
+ iSource = aRemoteSelection.CopyL();
+ iServiceId = iDestination.Entry().Id();
+
+ // assume Entry passed in is set to service id (IMCV needs to set new entries to this)
+ iRecvConverter = CImRecvConvert::NewL( iFs, &iDestination, KUidMsgTypePOP3, iServiceId);
+ iRecvConverter->SetCaf(*iPopSession->GetCafL(iFs));
+ iPopTopPopState=EPopTopPopRetrieving;
+ iProcessComplete=EFalse;
+
+ // set recv conv.
+ if (iSource->Count())
+ {
+ // Set the MIME parser to point at the first message to be populated.
+ iRecvConverter->SetMsvId((*iSource)[0]);
+ }
+ CActiveScheduler::Add(this); // Add CImPop3CopyMove to scheduler's queue
+ }
+
+void CImPop3TopPopulate::DoRetrieveL()
+ {
+ iAlreadyComplete = EFalse;
+ iMessageMarkedForDelete = EFalse;
+ TRequestStatus* pS = &iStatus;
+ TMsvId msgId=(*iSource)[iMsgCtr];
+ // iDestination will later be changed back to the destination entry, if required
+ TInt err = iDestination.SetEntry(msgId);
+ TMsvEmailEntry entry = iDestination.Entry();
+ if(err != KErrNone)
+ {
+ SetActive();
+ User::RequestComplete(pS,err);
+ }
+ else if (entry.Operation() && (entry.DisconnectedOperation() == EDisconnectedDeleteOperation))
+ {
+ iMessageMarkedForDelete = ETrue;
+ SetActive();
+ User::RequestComplete(pS, KErrNone);
+ }
+ else if ((entry.Complete()))
+ {
+ iAlreadyComplete = ETrue;
+ SetActive();
+ User::RequestComplete(pS, KErrNone);
+ }
+ else
+ {
+ iProgress.iTotalBytes = iRemoteSizes[iMsgCtr];
+ // reset entry to destination context if the current entry is not meant to be populated
+ User::LeaveIfError(iDestination.SetEntry(iDestId));
+ iRetrieveMessage = ETrue;
+
+ //If the message is not found complete the request.
+ if (!iTop->SetMessageAndLines(msgId,iTopLimit))
+ {
+ iAlreadyComplete = ETrue;
+ SetActive();
+ User::RequestComplete(pS, KErrNone);
+ }
+ else
+ {
+ iCurrentMsgSize = iRemoteSizes[iMsgCtr];
+ iTop->StartL(iStatus);
+ SetActive();
+ MOBILITY_TEST_MTM_STATE(iServiceId, KMobilityTestMtmStatePopRetrieving);
+ }
+ }
+ }
+
+void CImPop3TopPopulate::RetrievalCompleteL()
+ {
+ iProcessComplete=ETrue;
+ }
+
+void CImPop3TopPopulate::DoRunL()
+ {
+ // If we have already have an error then we have just been logging the failure.
+ // The failure has been logged so we can leave now.
+ User::LeaveIfError(iSavedError);
+
+ // There was no error so handle the completion of either the logging or the retrieve operations.
+ TRAP(iSavedError, RunLProcessingL());
+
+ if (iSavedError != KErrNone)
+ // If an error has occured then we need to clean up the message and log the failure before bailing out.
+ {
+ if(iRetrieveMessage)
+ {
+ if ((!iAlreadyComplete) && (!iMessageMarkedForDelete))
+ {
+ TRAPD(err,iRecvConverter->MessageCompleteL());
+
+ if(err != KErrNone)
+ {
+ // something is wrong with the message delete and report back
+ err = iDestination.SetEntry(iDestId);
+ if (err == KErrNone)
+ {
+ err = iDestination.DeleteEntry(iTop->EntryId());
+ }
+ }
+ }
+ }
+
+ // The message is logged as 'failed' if iSavedError is not KErrNone.
+ LogFetchedMessageL();
+ }
+ }
+
+void CImPop3TopPopulate::DoComplete(TInt& /*aCompleteStatus*/)
+ {
+ }
+
+void CImPop3TopPopulate::DoCancel()
+ {
+ iPopSession->SetOpNotPending();
+
+ if(iPopTopPopState==EPopTopPopRetrieving)
+ {
+ iTop->Cancel();
+ }
+
+ CMsgActive::DoCancel();
+ }
+
+void CImPop3TopPopulate::RunLProcessingL()
+ {
+ switch (iPopTopPopState)
+ {
+ case EPopTopPopRetrieving:
+ {
+ TInt amountLeft = 0;
+ if(iRetrieveMessage)
+ {
+ TBool partial=ETrue;
+ if (iTop->Progress()>=TUint(iCurrentMsgSize))
+ {
+ partial=EFalse;
+ }
+
+ if ((!iAlreadyComplete) && (!iMessageMarkedForDelete))
+ {
+ iRecvConverter->MessageCompleteL(partial);
+ }
+ amountLeft=(iCurrentMsgSize)-iTop->Progress()+iRecvConverter->DeletedAttachmentSize();
+ if (amountLeft<0)
+ {
+ amountLeft=0;
+ }
+
+ TMsvId msgId=(*iSource)[iMsgCtr];
+ if(iDestination.SetEntry(msgId)==KErrNone)
+ {
+ TMsvEmailEntry header=iDestination.Entry();
+ TBool changed=EFalse;
+ if((header.Unread()))
+ {
+ header.SetNew(EFalse);
+ changed=ETrue;
+ }
+
+ if(partial!=EFalse)
+ {
+ // We have used TOP so the entry will be partial, unless we have got the whole thing.
+ header.SetPartialDownloaded(partial);
+ changed=ETrue;
+ }
+
+ if(changed != EFalse)
+ {
+ User::LeaveIfError(iDestination.ChangeEntry(header));
+ }
+ if(iDestination.SetEntry(iDestId)!=KErrNone)
+ {
+ User::Leave(KPop3ProblemWithRemotePopServer);
+ }
+ }
+
+ }
+
+ iRecvConverter->WritePartialFooterL(amountLeft);
+
+ iDestination.SetEntry(iDestId); // make sure not trying to delete current context
+ LogFetchedMessageL();
+ }
+ break;
+ case EPopTopPopLogging:
+ // If the message has been logged then move on and download the next one.
+ {
+ --iProgress.iMsgsToProcess;
+ if(++iMsgCtr<iSource->Count())
+ {
+ // If we are migrating halt the operation here
+ if (iMigratingToNewBearer)
+ {
+ // If we don't SetActive, the RunL will complete the request
+ return;
+ }
+ else
+ {
+ iRecvConverter->ResetL();
+ iRecvConverter->SetMsvId((*iSource)[iMsgCtr]);
+ DoRetrieveL(); //add it to the collection;
+ iPopTopPopState = EPopTopPopRetrieving;
+ }
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+//
+// Helper function to set up the iLogEntry object which is invoked after the copy/move.
+//
+void CImPop3TopPopulate::LogFetchedMessageL()
+ {
+ iPopTopPopState = EPopTopPopLogging;
+ if (iLogMessage)
+ {
+// Get the header information for the message that is to be copied or moved.
+ User::LeaveIfError(iDestination.SetEntry((*iSource)[iMsgCtr]));
+
+ // Get the 'Fetch' string from the logging string table.
+ TBuf<KLogMaxSharedStringLength> fetchString;
+ iLogMessage->GetString(fetchString, R_LOG_DIR_FETCHED);
+
+// Set up the log event.
+ iLogMessage->LogEvent().SetEventType(KLogMailEventTypeUid);
+
+ iLogMessage->LogEvent().SetDirection(fetchString);
+ iLogMessage->LogEvent().SetRemoteParty(iDestination.Entry().iDetails);
+ iLogMessage->LogEvent().SetSubject(iDestination.Entry().iDescription);
+ iLogMessage->LogEvent().SetLink(iDestId);
+
+ if (iSavedError != KErrNone)
+ {
+ TBuf<KLogMaxSharedStringLength> failedString;
+ iLogMessage->GetString(failedString, R_LOG_DEL_FAILED);
+ iLogMessage->LogEvent().SetStatus(failedString);
+ }
+
+// Run the iLogMessage operation.
+ iLogMessage->Start(iDestination.Entry().iError, iStatus);
+ SetActive();
+ }
+ else
+ {
+ TRequestStatus* status = &iStatus;
+ SetActive();
+ User::RequestComplete(status, KErrNone);
+ }
+ }
+
+
+// ******************************************************************************************
+// This is called by the POP Server MTM when it starts Migrating Bearer
+//
+// ******************************************************************************************
+void CImPop3TopPopulate::Pause()
+ {
+ // Set the Migration flag
+ iMigratingToNewBearer = ETrue;
+ }
+
+// ******************************************************************************************
+// This is called by the POP Server MTM when it starts Migrating Bearer
+//
+// ******************************************************************************************
+void CImPop3TopPopulate::CancelAllowResume()
+ {
+ iMigratingToNewBearer = ETrue;
+
+ // Cancel the copying of the current message and decrement counters
+ // so we can restart from this message onwards when we have migrated.
+ // Use the normal cancel, as we really need to cancel here.
+ Cancel();
+ }