--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/email/pop3andsmtpmtm/popservermtm/src/POPSRFSH.CPP Thu Dec 17 08:44:11 2009 +0200
@@ -0,0 +1,1597 @@
+// 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 <txtetext.h>
+#include <txtrich.h>
+#include <miuthdr.h>
+#include <imcvrecv.h>
+#include <msvapi.h>
+
+#include <s32mem.h>
+#include <s32file.h>
+
+#include "POPS.PAN" // imrc's own panic codes
+// Oyster includes
+#include <msvstd.h>
+#include <msventry.h> // CMsvServerEntry
+#include <msvstore.h>
+#include <mmsvattachmentmanager.h>
+#include <mmsvattachmentmanagersync.h>
+
+#include <miutset.h>
+#include <imcvutil.h>
+
+#include <popsmtm.h>
+#include "POPSRFSH.h"
+#include "POPS.H"
+#include "POPSOP.H" //CImPop3Operations
+#include "POPSMBX.H"
+
+_LIT(KUidlFile,"UIDLS");
+
+const TInt KMaxStringLength = 1024;
+
+
+
+//
+// My own panic command
+//
+GLREF_C void Panic(TPopsPanic aPanic);
+
+CImPop3RefreshMailBox::CImPop3RefreshMailBox(CImPop3Session& aPopSession): CMsgActive( KMsgPop3RefreshMailboxPriority ), iPopSession( aPopSession)
+ {
+ __DECLARE_NAME(_S("CImPop3RefreshMailBox"));
+ }
+
+CImPop3RefreshMailBox* CImPop3RefreshMailBox::NewL(CMsvServerEntry& aRemoteServerEntry, CImPop3Session& aPopSession, RFs& anFs)
+ {
+ CImPop3RefreshMailBox* self = new (ELeave) CImPop3RefreshMailBox( aPopSession);
+ CleanupStack::PushL(self);
+ self->ConstructL(aRemoteServerEntry, anFs);
+ CleanupStack::Pop();
+ return self;
+ }
+
+void CImPop3RefreshMailBox::ConstructL(CMsvServerEntry& aRemoteServerEntry, RFs& anFs)
+ {
+ iRefreshOperation = CImPop3RefreshOperation::NewL(aRemoteServerEntry, &iPopSession, anFs);
+ _LIT8(KCrLfStr,".\r\n");
+ iFullStopTerminator = KCrLfStr();
+ iTextServer=iPopSession.TextServerSession();
+ CActiveScheduler::Add(this); // Add PopSession to scheduler's queue
+ }
+
+
+CImPop3RefreshMailBox::~CImPop3RefreshMailBox()
+ {
+ Cancel();
+ delete iRefreshOperation;
+ }
+
+void CImPop3RefreshMailBox::DoCancel()
+ {
+ switch(iState)
+ {
+ case EPop3RefreshBoxDefault:
+ case EPop3RefreshBoxTop:
+ {
+ if (iMigratingToNewBearer)
+ {
+ iRefreshOperation->CancelAllowResume();
+ }
+ else
+ {
+ iRefreshOperation->Cancel();
+ }
+ break;
+ }
+ case EPop3RefreshBoxPurgeInput:
+ {
+ iTextServer->Cancel();
+ break;
+ }
+ default:
+ {
+ __ASSERT_DEBUG(EFalse, Panic(EImppUnknownRefreshState));
+ }
+ break;
+ }
+ CMsgActive::DoCancel();
+ }
+
+
+void CImPop3RefreshMailBox::Start(TRequestStatus& aStatus, CArrayFixFlat<TMsvId>* aMsvIdArray)
+ {
+ Queue(aStatus);
+ iMsvIdArray = aMsvIdArray;// Provided for transparency
+
+ TRAPD(stateErr,ChangeStateL(EPop3RefreshBoxDefault));
+ if(stateErr!=KErrNone)
+ {
+ Complete(stateErr);
+ }
+ }
+
+void CImPop3RefreshMailBox::DoRunL()
+ {
+ if (iMigratingToNewBearer)
+ {
+ // The Pops MTM is currently migrating so no processing is required here
+ // This call to doRunl is probably as a result of CImPop3RefreshOperation::Pause()
+ // completing us.
+ return;
+ }
+ switch (iState)
+ {
+ case EPop3RefreshBoxDefault:
+ if (iStatus.Int() == KPop3RefreshUidlEquate)
+ {
+ ChangeStateL(EPop3RefreshBoxPurgeInput);
+ }
+ break;
+ case EPop3RefreshBoxPurgeInput:
+ iTextServer->GetCurrentTextLine(iTextServerResponse);
+ if(iTextServerResponse.Compare(iFullStopTerminator)!=0)
+ {
+ iTextServer->QueueReceiveNextTextLine(iStatus);
+ SetActive();
+ }
+ else
+ {
+ ChangeStateL(EPop3RefreshBoxTop);
+ }
+ break;
+ case EPop3RefreshBoxTop:
+ break;
+ default:
+ break;
+ };
+ }
+
+void CImPop3RefreshMailBox::ChangeStateL(TState aState)
+ {
+ switch (aState)
+ {
+ case EPop3RefreshBoxDefault:
+ // Start refresh with UIDL
+ iRefreshOperation->Start(iStatus,iMsvIdArray);
+ break;
+ case EPop3RefreshBoxPurgeInput:
+ iPopSession.SetOpNotPending();
+ iTextServer->GetCurrentTextLine(iTextServerResponse);
+ if(iTextServerResponse.Compare(iFullStopTerminator)!=0)
+ {
+ iTextServer->QueueReceiveNextTextLine(iStatus);
+ // Break here to make sure Async function is called before SetActive() is called,
+ // else we'll get a Stray Signal
+ break;
+ }
+ case EPop3RefreshBoxTop:
+ iRefreshOperation->Cancel();
+ iRefreshOperation->Start(iStatus); // Restart refresh with Top
+ break;
+ default:
+ break;
+ }
+ iState = aState;
+ SetActive();
+ }
+
+TPop3Progress CImPop3RefreshMailBox::Progress()
+ {
+ return iRefreshOperation->Progress();
+ }
+
+
+void CImPop3RefreshMailBox::SetMessagesToKeepL(const CMsvEntrySelection* aMessagesToKeep)
+ {
+ iRefreshOperation->SetMessagesToKeepL(aMessagesToKeep);
+ }
+
+
+TUint CImPop3RefreshMailBox::RemoteMessageSizeL(TMsvId aId)
+ {
+ return iRefreshOperation->RemoteMessageSizeL(aId);
+ }
+
+// ******************************************************************************************
+// This is called by the POP Client MTM when it starts Migrating Bearer
+//
+// ******************************************************************************************
+void CImPop3RefreshMailBox::Pause()
+ {
+ iMigratingToNewBearer = ETrue;
+ // Ask the Refresh Operation to prepare itself for Migration
+ switch(iState)
+ {
+ case EPop3RefreshBoxDefault:
+ case EPop3RefreshBoxTop:
+ {
+ iRefreshOperation->Pause();
+ break;
+ }
+ case EPop3RefreshBoxPurgeInput:
+ {
+ // Cancel the Text Server request, so we can complete to migrate.
+ iTextServer->Cancel();
+ break;
+ }
+ default:
+ {
+ __ASSERT_DEBUG(EFalse, Panic(EImppUnknownRefreshState));
+ }
+ break;
+
+ }
+
+ }
+
+// ******************************************************************************************
+// This is called by the POP Client MTM when it starts Migrating Bearer
+//
+// ******************************************************************************************
+void CImPop3RefreshMailBox::CancelAllowResume()
+ {
+ iMigratingToNewBearer = ETrue;
+ Cancel();
+ }
+
+// Called by the POP Client MTM, once it has completed Migrating to new bearer
+void CImPop3RefreshMailBox::ResumeL(CImPop3Session* aPopSession, TRequestStatus& aStatus)
+ {
+ Queue(aStatus);
+ iMigratingToNewBearer = EFalse;
+
+ if (iState == EPop3RefreshBoxPurgeInput)
+ {
+ ChangeStateL(EPop3RefreshBoxTop);
+ }
+ else
+ {
+ // Inform the Refresh Operation of Migration Completion
+ iRefreshOperation->ResumeL(aPopSession, iStatus);
+ SetActive();
+ }
+ }
+
+//================================================================================
+
+CImPop3RefreshOperation::CImPop3RefreshOperation(CMsvServerEntry& aRemoteServerEntry, CImPop3Session* aPopSession, RFs& anFs)
+ : CMsgActive( KMsgPop3RefreshMailboxPriority ), iUidlKey(_FOFF(TMsgUidlStore,iMsvId),ECmpTUint),
+ iRemoteServerEntry(aRemoteServerEntry),iPopSession(aPopSession),iFs(anFs)
+ {
+ __DECLARE_NAME(_S("CImPop3RefreshOperation"));
+ }
+
+
+CImPop3RefreshOperation* CImPop3RefreshOperation::NewL(CMsvServerEntry& aRemoteServerEntry, CImPop3Session* aPopSession, RFs& anFs)
+ {
+ CImPop3RefreshOperation* self = new (ELeave) CImPop3RefreshOperation( aRemoteServerEntry, aPopSession, anFs);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop();
+ return self;
+ }
+
+
+void CImPop3RefreshOperation::ConstructL()
+ {
+ // store id of remote collection
+ iRemoteId=iRemoteServerEntry.Entry().Id();
+ iRecvConverter=CImRecvConvert::NewL( iFs, &iRemoteServerEntry, KUidMsgTypePOP3, iRemoteId);
+ iRecvConverter->SetCaf(*iPopSession->GetCafL(iFs));
+ iPopTop=CImPop3Top::NewL(iPopSession,iRecvConverter);
+ iPopRetr=CImPop3Retr::NewL(iPopSession,iRecvConverter, iFs);
+
+ iUidlArray = new(ELeave) CArrayFixSeg<TMsgUidlStore>(8);
+
+ iMsvSelection = new (ELeave) CMsvEntrySelection;
+ iUnwantedEntries = new (ELeave) CMsvEntrySelection;
+ // store id of remote collection
+ // set recv conv.
+ iRecvConverter->SetMsvId(iRemoteId);
+
+ CActiveScheduler::Add(this); // Add CImPop3RefreshOperation to scheduler's queue
+
+ iCurrentDrive = MessageServer::CurrentDriveL(iFs);
+ }
+
+
+CImPop3RefreshOperation::~CImPop3RefreshOperation()
+ {
+ Cancel();
+ delete iMsvSelection;
+
+ // delete everything here
+ delete iPopStat;
+ delete iPopList;
+ delete iPopUidl;
+ delete iPopTop;
+ delete iPopRetr;
+ iUniqueUidlPosArray.Close();
+ iTemporaryUidlPosArray.Close();
+ if (iUidlArray)
+ {
+ for (TInt ii=iUidlArray->Count();--ii>=0;)
+ DeleteUidl(ii);
+ delete iUidlArray;
+ }
+ delete iPop3Uidls;
+ delete [] iSize;
+
+ delete iRecvConverter;
+ delete iUnwantedEntries;
+ delete iMessagesToKeep;
+ }
+
+//
+// Cancel any current operation
+//
+void CImPop3RefreshOperation::DoCancel()
+ {
+ iPopSession->SetOpNotPending();
+
+ switch(iState)
+ {
+ case EPopRefreshStat:
+ if(iPopStat)
+ {
+ iPopStat->Cancel();
+ }
+ break;
+ case EPopRefreshList:
+ if(iPopList)
+ {
+ iPopList->Cancel();
+ }
+ break;
+ case EPopRefreshUidl:
+ if(iPopUidl)
+ {
+ iPopUidl->Cancel();
+ }
+ break;
+ case EPopRefreshGetHeader:
+ if(iPopTop)
+ {
+ iPopTop->Cancel();
+ }
+ if(iPopRetr)
+ {
+ iPopRetr->Cancel();
+ }
+ break;
+ default: // do nothing for all other states
+ break;
+ }
+ CMsgActive::DoCancel();
+ }
+
+//
+// what to do on completion
+//
+void CImPop3RefreshOperation::DoComplete(TInt& aCompleteStatus)
+ {
+ // if we had empty headers report back to user with error code
+ switch (iState)
+ {
+ case EPopRefreshComplete:
+ break;
+ case EPopRefreshGetHeader:
+ if (aCompleteStatus!=KErrNone)
+ {// If there is no memory to download further, complete
+ // the operation without calling MessageCompleteL.
+ if(aCompleteStatus == KErrNoMemory)
+ {
+ break;
+ }
+ // try and remember what we've done, at least
+ TRAPD(ignore,iRecvConverter->MessageCompleteL());
+ TRAP(ignore,RefreshFinishedL());
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+//
+// Start me up
+//
+void CImPop3RefreshOperation::Start(TRequestStatus& aStatus, CArrayFixFlat<TMsvId>* aMsgIdArray)
+ {
+ Queue(aStatus);
+ iCheckDiskSpaceCounter = 0;
+ iNewMsg=aMsgIdArray; // take ownership of the message id array
+ TRAPD(stateErr,ChangeStateL(EPopRefreshSyncCollection));
+ if(stateErr!=KErrNone)
+ {
+ Complete(stateErr);
+ }
+ }
+
+//
+// Start me up and skip UIDL downloading
+// (BFSW1-2016)
+void CImPop3RefreshOperation::Start(TRequestStatus& aStatus)
+ {
+ Queue(aStatus);
+
+ __ASSERT_ALWAYS(iNewMsg,Panic(ETopStartBeforeUidlStart));
+
+ iCheckDiskSpaceCounter = 0;
+ if (iUidlArray)
+ { // Delete unreliable UIDL list (BFSW1-2016)
+ for (TInt ii=iUidlArray->Count();--ii>=0;)
+ DeleteUidl(ii);
+ }
+
+
+ TRAPD(stateErr,ChangeStateL(EPopRefreshGetHeader));
+ if(stateErr!=KErrNone)
+ {
+ Complete(stateErr);
+ }
+ }
+
+// ******************************************************************************************
+// Resume function called by the POP Client MTM, once it has completed Migrating to new bearer
+//
+// ******************************************************************************************
+void CImPop3RefreshOperation::ResumeL(CImPop3Session* aPopSession, TRequestStatus& aStatus)
+ {
+ iMigratingToNewBearer = EFalse;
+ iPopSession = aPopSession;
+
+ delete iRecvConverter;
+ iRecvConverter = NULL;
+ iRecvConverter=CImRecvConvert::NewL( iFs, &iRemoteServerEntry, KUidMsgTypePOP3, iRemoteId);
+ iRecvConverter->SetCaf(*iPopSession->GetCafL(iFs));
+
+ delete iPopTop;
+ iPopTop = NULL;
+ iPopTop=CImPop3Top::NewL(iPopSession,iRecvConverter);
+ delete iPopRetr;
+ iPopRetr = NULL;
+ iPopRetr=CImPop3Retr::NewL(iPopSession,iRecvConverter, iFs);
+
+ iRecvConverter->SetMsvId(iRemoteId);
+
+ Queue(aStatus);
+ iCheckDiskSpaceCounter = 0;
+ TRAPD(stateErr,ChangeStateL(iState));
+ if(stateErr!=KErrNone)
+ {
+ Complete(stateErr);
+ }
+ }
+
+//
+// Result of last active call
+//
+void CImPop3RefreshOperation::DoRunL()
+ {
+
+ switch(iState)
+ {
+ case EPopRefreshSyncCollection:
+ if(iRemoteArrayCtr>0)
+ {
+ SyncCollectionL();
+ QueueRemoteUpdate();
+ }
+ else
+ {
+ CompleteSyncCollection();
+ if (iMigratingToNewBearer)
+ {
+ ChangeStateForMigrate(EPopRefreshStat);
+ return;
+ }
+ else
+ {
+ ChangeStateL(EPopRefreshStat);
+ }
+ }
+ break;
+
+ case EPopRefreshStat:
+ // initialise progress object
+
+ iProgress.iMsgsToProcess=iNoMessages;
+
+ iProgress.iTotalMsgs=iNoMessages;
+
+ User::LeaveIfError(iRemoteServerEntry.SetEntry(iRemoteId));
+ iEntry = iRemoteServerEntry.Entry();
+ iEntry.SetMtmData3(iNoMessages);
+ User::LeaveIfError(iRemoteServerEntry.ChangeEntry(iEntry));
+
+ delete iPopStat;
+ iPopStat=NULL;
+ if(iNoMessages)
+ {
+ if (iMigratingToNewBearer)
+ {
+ ChangeStateForMigrate(EPopRefreshList);
+ return;
+ }
+ ChangeStateL(EPopRefreshList);
+ }
+ else
+ {
+ if (iMigratingToNewBearer)
+ {
+ ChangeStateForMigrate(EPopRefreshDeleteDeadMessages);
+ return;
+ }
+ ChangeStateL(EPopRefreshDeleteDeadMessages);
+ }
+ break;
+
+ case EPopRefreshList:
+ delete iPopList;
+ iPopList=NULL;
+ if (iMigratingToNewBearer)
+ {
+ ChangeStateForMigrate(EPopRefreshUidl);
+ return;
+ }
+ ChangeStateL(EPopRefreshUidl);
+ break;
+
+ case EPopRefreshUidl:
+ __ASSERT_ALWAYS(iPopUidl, Panic(EPopNullPointer));
+
+ iUidlExists=iPopUidl->PopCommandAccepted();
+ delete iPopUidl;
+ iPopUidl=NULL;
+ if (iUidlExists)
+ {
+ if (iMigratingToNewBearer)
+ {
+ ChangeStateForMigrate(EPopRefreshSyncUidl);
+ return;
+ }
+ ChangeStateL(EPopRefreshSyncUidl);
+ }
+ else
+ {
+ // delete any entries with a zero length inet msg id
+ //scan UIDL file for msgs with no POP id. If found, delete from UIDL file and Messaging Server
+ //??? why would they have a zero length POP id ?
+ User::LeaveIfError(iRemoteServerEntry.SetEntry(iRemoteId));
+ CArrayFix<TMsgUidlStore>& uidlarray=*iUidlArray;
+ TInt row = uidlarray.Count();
+ while(--row>=0)
+ {
+ if(uidlarray[row].iPopId->Length()==0)
+ {
+#ifdef _DEBUG
+ TInt error =
+#endif
+ iRemoteServerEntry.DeleteEntry( uidlarray[row].iMsvId);
+ __ASSERT_DEBUG( error == KErrNone, Panic(EPopFailedDebugAssert));
+ DeleteUidl(row);
+ }
+ }
+ if (iMigratingToNewBearer)
+ {
+ ChangeStateForMigrate(EPopRefreshGetHeader);
+ return;
+ }
+ ChangeStateL(EPopRefreshGetHeader);
+ }
+ break;
+
+ case EPopRefreshSyncUidl:
+ if(iRemoteArrayCtr>0)
+ {
+ SyncUidlL();
+ QueueRemoteUpdate();
+ }
+ else
+ {
+ if (iMigratingToNewBearer)
+ {
+ ChangeStateForMigrate(EPopRefreshGetHeader);
+ return;
+ }
+ ChangeStateL(EPopRefreshGetHeader);
+ }
+ break;
+
+ case EPopRefreshGetHeader:
+ //At this point iMsgCtr contains the index of the hdr to download
+
+ if(iFirstCallToTop)
+ {
+ __ASSERT_ALWAYS(iPopTop, Panic(EPopNullPointer));
+ iTopExists=iPopTop->PopCommandAccepted();
+ }
+
+ if ( !iFirstCallToTop || iTopExists )
+ {
+ //This is not the 1st call to TOP, or the TOP command exists
+
+ // Don't create a message if the header has none of the following RFC 822 fields:
+ // To:, Cc:, Bcc:, From:, ReturnPath
+ // I assume that if it is missing ALL of these fields then the Email message MUST be broken!
+
+ if(iUidlExists || CompareIdAndSizeL())
+ {
+ // create new TMsvEntry here in folder CMsvEntry
+ TMsvEntry msvEntry = iRecvConverter->MessageEntryDetailsL();
+ TRAP_IGNORE(CreateNewHeaderEntryL( msvEntry ));
+
+ iIdTab[iMsgCtr]=msvEntry.Id();
+ __ASSERT_ALWAYS(iNewMsg, Panic(EPopNullPointer));
+ iNewMsg->AppendL(msvEntry.Id()); // cannot fail, as we have SetReserveL()'d
+
+ if (iTopExists)
+ {
+ iRecvConverter->MessageCompleteL(msvEntry);
+ }
+ }
+ else
+ {
+ TMsvEntry msvEntry = iRecvConverter->MessageEntryDetailsL();
+ iRecvConverter->MessageCompleteL(msvEntry);
+ }
+ iProgress.iMsgsToProcess--;
+
+ iMsgCtr--;
+ }
+
+ iFirstCallToTop=EFalse;
+
+ if (GetMessagesIfAny())
+ {
+ RetrieveHeadersL();
+ }
+ else
+ {
+ if (iMigratingToNewBearer)
+ {
+ ChangeStateForMigrate(EPopRefreshDeleteExcessMessages);
+ return;
+ }
+ ChangeStateL(EPopRefreshDeleteExcessMessages);
+ if(iUidlExists==EFalse)
+ {
+ //We need to remove TOPed or RETRed msgs that were already downloaded
+ User::LeaveIfError(iRemoteServerEntry.SetEntry(iRemoteId));
+ for( TInt loop = iUnwantedEntries->Count(); --loop>=0;)
+ {
+#if defined(_DEBUG)
+ TInt err = iRemoteServerEntry.DeleteEntry((*iUnwantedEntries)[loop]);
+ __ASSERT_DEBUG(err == KErrNone, Panic(EPopFailedDebugAssert));
+#else
+ iRemoteServerEntry.DeleteEntry((*iUnwantedEntries)[loop]);
+#endif
+ }
+ }
+ }
+ break;
+
+ case EPopRefreshDeleteExcessMessages:
+
+ if (!iUidlExists)
+ {
+ // Fix to stop the deletion of existing headers when POP MTM should connect but not synch
+
+ if (iPopSession->MaxHeaders()==0)
+ {
+ if (iMigratingToNewBearer)
+ {
+ ChangeStateForMigrate(EPopRefreshDeleteDeadMessages);
+ return;
+ }
+ ChangeStateL(EPopRefreshDeleteDeadMessages);
+ break;
+ }
+ else
+ {
+ while (--iRemoteArrayCtr>=0)
+ {
+ if (iRemoteArrayCtr<TInt(iNoMessages-iPopSession->MaxHeaders()))
+ {
+ iRemoteServerEntry.SetEntry(iIdTab[iRemoteArrayCtr]);
+ const TMsvEmailEntry& entry=iRemoteServerEntry.Entry();
+ // Check if the message entry is marked for offline delete operation.
+ TBool notMarkedForOfflineDelete = EFalse;
+ TImDisconnectedOperationType opType;
+ if((opType = entry.DisconnectedOperation())!= EDisconnectedDeleteOperation)
+ {
+ notMarkedForOfflineDelete = ETrue;
+ }
+ if (CanDeleteEntry(entry))
+ {
+ // Don't handle the error
+ User::LeaveIfError(iRemoteServerEntry.SetEntry(iRemoteId));
+ // The message entry is not marked for offline delete, so delete the entry from
+ // message INDEX(mail2) file.
+ if(notMarkedForOfflineDelete)
+ {
+ User::LeaveIfError(iRemoteServerEntry.DeleteEntry(iIdTab[iRemoteArrayCtr]));
+ }
+ DeleteUidl(iRemoteArrayCtr);
+ QueueRemoteUpdate();
+ break;
+ }
+ }
+ }
+ }
+
+ }
+ else
+ // Fix to stop the deletion of existing headers when POP MTM should connect but not synch
+
+ if (iPopSession->MaxHeaders()==0)
+ {
+ if (iMigratingToNewBearer)
+ {
+ ChangeStateForMigrate(EPopRefreshDeleteDeadMessages);
+ return;
+ }
+ ChangeStateL(EPopRefreshDeleteDeadMessages);
+ break;
+ }
+ else
+ while (--iRemoteArrayCtr>=0)
+ {
+ const TMsgUidlStore& uidl=iUidlArray->At(iRemoteArrayCtr);
+ if (iPop3Uidls->MsgNo(*uidl.iPopId) < TInt(iNoMessages-iPopSession->MaxHeaders()))
+ {
+ iRemoteServerEntry.SetEntry(uidl.iMsvId);
+ const TMsvEmailEntry& entry=iRemoteServerEntry.Entry();
+ // Check if the message entry is marked for offline delete operation.
+ TBool notMarkedForOfflineDelete = EFalse;
+ TImDisconnectedOperationType opType;
+ if((opType = entry.DisconnectedOperation())!= EDisconnectedDeleteOperation)
+ {
+ notMarkedForOfflineDelete = ETrue;
+ }
+ if (CanDeleteEntry(entry))
+ {
+ // Don't handle the error
+ User::LeaveIfError(iRemoteServerEntry.SetEntry(iRemoteId));
+ // The message entry is not marked for offline delete, so delete the entry from
+ // message INDEX(mail2) file.
+ if(notMarkedForOfflineDelete)
+ {
+ User::LeaveIfError(iRemoteServerEntry.DeleteEntry(uidl.iMsvId));
+ }
+ DeleteUidl(iRemoteArrayCtr);
+ QueueRemoteUpdate();
+ break;
+ }
+ }
+ }
+
+ if (iRemoteArrayCtr<0)
+ {
+ if (iMigratingToNewBearer)
+ {
+ ChangeStateForMigrate(EPopRefreshDeleteDeadMessages);
+ return;
+ }
+ ChangeStateL(EPopRefreshDeleteDeadMessages);
+ }
+ break;
+
+
+ case EPopRefreshDeleteDeadMessages: // dispose of un-present messages
+ if (!iUidlExists)
+ {
+ //delete all messages from the Messaging Server whose MsvID does NOT appear in
+ //the iIdTab[] array.
+ User::LeaveIfError(iRemoteServerEntry.SetEntry(iRemoteId));
+ CMsvEntrySelection* pop3Entries = new (ELeave) CMsvEntrySelection;
+ CleanupStack::PushL(pop3Entries);
+ User::LeaveIfError(iRemoteServerEntry.GetChildren(*pop3Entries ));
+
+ if (iNoMessages == 0)
+ {
+ // Clear the entries from the local POP3 Mailbox, and delete the UIDs
+ if (pop3Entries ->Count()!=0)
+ {
+ iRemoteServerEntry.DeleteEntries(*pop3Entries);
+ }
+ if (iUidlArray)
+ { // Delete UIDL list
+ for (TInt ii=iUidlArray->Count();--ii>=0;)
+ DeleteUidl(ii);
+ }
+ }
+ else
+ {
+ // Downloaded each header in turn to get the uid list.
+ // Delete any messages in remote folder that aren't in the iUidlArray.
+ //
+ CMsvEntrySelection* deadEntries = new (ELeave) CMsvEntrySelection;
+ CleanupStack::PushL(deadEntries);
+ TInt msgCtr = pop3Entries->Count();
+ //nested loops! - not an ideal search method
+ while (--msgCtr>=0)
+ {
+ TBool found = EFalse;
+ for (TUint index = 0; index < iNoMessages && !found; index++)
+ {
+ if ((*pop3Entries)[msgCtr] == iIdTab[index])
+ {
+ found = ETrue;
+ }
+ }
+ if (!found)
+ {
+ deadEntries->AppendL((*pop3Entries)[msgCtr]);
+ }
+ }
+ if (deadEntries->Count())
+ {
+ User::LeaveIfError(iRemoteServerEntry.DeleteEntries(*deadEntries));
+ }
+ CleanupStack::PopAndDestroy(deadEntries);
+ }
+ CleanupStack::PopAndDestroy(pop3Entries);
+ ChangeStateL(EPopRefreshComplete);
+ break;
+ }
+ else
+ {
+ while (--iRemoteArrayCtr>=0)
+ {
+ const TMsgUidlStore& uidl=iUidlArray->At(iRemoteArrayCtr);
+
+ if (uidl.iSelectionPos!=TMsgUidlStore::EPresent)
+ {
+ // Don't handle the error
+ iRemoteServerEntry.DeleteEntry(uidl.iMsvId);
+ User::LeaveIfError(iRemoteServerEntry.DeleteEntry(uidl.iMsvId));
+ DeleteUidl(iRemoteArrayCtr);
+ QueueRemoteUpdate();
+ break;
+ }
+ }
+ }
+
+ if (iRemoteArrayCtr<0)
+ {
+ ChangeStateL(EPopRefreshComplete);
+ }
+ break;
+
+ default: // Unknown state
+ Panic(EImppUnknownRefreshState);
+ break;
+ }
+ }
+
+ //
+ // Finished refresh so tidy up
+ //
+ //
+ void CImPop3RefreshOperation::RefreshFinishedL()
+ {
+ iRemoteServerEntry.CompleteBulk();
+ CreateUidlFileL();
+ delete iPopTop;
+ iPopTop=NULL;
+ delete iPopRetr;
+ iPopRetr=NULL;
+ __ASSERT_ALWAYS(iNewMsg, Panic(EPopNullPointer));
+ iNewMsg->Reset(); // all new messages are sound
+ }
+
+ // retrieve headers(or whole messages) else complete
+ //
+ TBool CImPop3RefreshOperation::GetMessagesIfAny()
+ {
+ while (iMsgCtr>=iLastHeaderToGet && iIdTab[iMsgCtr]!=0)
+ iMsgCtr--;
+ if (iMsgCtr < 0 )
+ {
+ return EFalse;
+ }
+ return (iMsgCtr>=iLastHeaderToGet);
+ }
+
+void CImPop3RefreshOperation::ChangeStateForMigrate(TState aState)
+ {
+ iState = aState;
+
+ delete iPopTop;
+ iPopTop=NULL;
+ delete iPopRetr;
+ iPopRetr=NULL;
+ }
+
+void CImPop3RefreshOperation::ChangeStateL(TState aState)
+ {
+ //
+ // State machine of the whole POP mail session.
+ //
+ // Identify state on entry, change to next state and then
+ // start new operation associated with that new state.
+ //
+ switch (aState)
+ {
+ case EPopRefreshSyncCollection:
+ GetRemoteMessagesL();
+ QueueRemoteUpdate();
+ break;
+
+ case EPopRefreshStat:
+ GetNoMessagesL();
+ break;
+
+ case EPopRefreshList:
+ AllocateArraysL();
+ GetMsgSizesL();
+ break;
+
+ case EPopRefreshUidl:
+ GetMsgUidlsL();
+ break;
+
+ case EPopRefreshSyncUidl:
+ iUniqueUidlPosArray.Reset();
+ iTemporaryUidlPosArray.Reset();
+ iPreviousIndex = KErrGeneral;
+ iRemoteArrayCtr=iUidlArray->Count();
+ QueueRemoteUpdate();
+ break;
+
+ case EPopRefreshGetHeader:
+ // start retrieving headers
+
+ iFirstCallToTop=ETrue;
+ iTopExists=ETrue;
+
+ iMsgCtr=iNoMessages-1;
+ if (!iUidlExists)
+ {
+ iLastHeaderToGet =0;
+ }
+ else
+ {
+ iLastHeaderToGet=iPopSession->MaxHeaders();
+ if (iLastHeaderToGet >= 0)
+ iLastHeaderToGet=iNoMessages-iLastHeaderToGet;
+ if (iLastHeaderToGet<0)
+ iLastHeaderToGet=0;
+ }
+
+ if(GetMessagesIfAny())
+ {
+ if(iPopSession->PipeliningSupport())
+ {
+ __ASSERT_ALWAYS(iPopTop, Panic(EPopNullPointer));
+ iPopTop->SetStartAndEndMessageIndex(iLastHeaderToGet, iMsgCtr);
+ }
+ RetrieveHeadersL();
+ break;
+ }
+ aState=EPopRefreshDeleteExcessMessages;
+ // nothing to do: drop through
+
+ case EPopRefreshDeleteExcessMessages:
+ //Need to commit downloaded headers to file before doing any deletions
+ iRemoteServerEntry.CompleteBulk();
+ if (iLastHeaderToGet==0) //no excess messages !
+ {
+ aState=EPopRefreshDeleteDeadMessages;
+ }
+ // nothing to do: drop through
+
+ case EPopRefreshDeleteDeadMessages:
+ //Need to commit downloaded headers to file before doing any deletions
+ iRemoteServerEntry.CompleteBulk();
+ // make sure we're pointing to correct context
+ User::LeaveIfError(iRemoteServerEntry.SetEntry(iRemoteId));
+ iRemoteArrayCtr=iUidlArray->Count();
+ QueueRemoteUpdate();
+ break;
+
+ case EPopRefreshComplete:
+ RefreshFinishedL();
+ break;
+
+ default: // Unknown state
+ Panic(EImppUnknownRefreshState);
+ break;
+ }
+ iState=aState;
+ }
+
+ //
+ // Use Pop STAT command to obtain of messages in remote mailbox
+ //
+ void CImPop3RefreshOperation::GetNoMessagesL()
+ {
+ CImPop3Stat* popStat = CImPop3Stat::NewL(iPopSession);
+ if ( iPopStat )
+ {
+ delete iPopStat;
+ iPopStat = NULL;
+ }
+ iPopStat = popStat;
+ iPopStat->Start(iStatus,iNoMessages,iMboxSize);
+ SetActive();
+ }
+
+ //
+
+ // Use LIST command to get message sizes
+ //
+ void CImPop3RefreshOperation::GetMsgSizesL()
+ {
+ CImPop3List* popList = CImPop3List::NewL(iPopSession);
+ if ( iPopList )
+ {
+ delete iPopList;
+ iPopList = NULL;
+ }
+ iPopList = popList;
+ iPopList->Start(iStatus,iSize);
+ SetActive();
+ }
+
+//
+// Use UIDL to obtain POP3 unique message Ids
+//
+void CImPop3RefreshOperation::GetMsgUidlsL()
+ {
+ CImPop3Uidl* popUidl = CImPop3Uidl::NewL(iPopSession);
+ if ( iPopUidl )
+ {
+ delete iPopUidl;
+ iPopUidl = NULL;
+ }
+ iPopUidl = popUidl;
+ iPopUidl->Start(iStatus,*iPop3Uidls);
+ SetActive();
+ }
+
+//
+// Post Stat allocate the various arrays
+// we know how many messages there are
+void CImPop3RefreshOperation::AllocateArraysL()
+ {
+ // Allocate the message id array and give it to the POP session
+ // so that any operation can access it.For example, Top requires
+ // access to this for pipelining
+ iIdTab = new(ELeave) TInt32[iNoMessages];
+ Mem::FillZ(iIdTab,iNoMessages*sizeof(TInt32));
+ iPopSession->SetMessageArray(iIdTab, iNoMessages);
+ iSize = new(ELeave) TUint[iNoMessages];
+ __ASSERT_ALWAYS(iNewMsg, Panic(EPopNullPointer));
+ iNewMsg->SetReserveL(iNoMessages); // no failure during AppendL()
+
+ iPop3Uidls = CImPop3UidlMap::NewL(iNoMessages);
+ }
+
+void CImPop3RefreshOperation::DeleteUidl(TInt anIndex)
+ {
+ TMsgUidlStore& uidl=(*iUidlArray)[anIndex];
+ delete uidl.iPopId;
+ iUidlArray->Delete(anIndex);
+ }
+
+//
+// Open uidl file
+//
+void CImPop3RefreshOperation::GetRemoteMessagesL()
+ {
+ TMsvSelectionOrdering order;
+ order.SetShowInvisibleEntries( ETrue );
+ iRemoteServerEntry.SetSort( order );
+ TInt selErr=iRemoteServerEntry.GetChildren(*iMsvSelection);
+ if(selErr!=KErrNone)
+ {
+ User::Leave(selErr);
+ }
+ iRemoteArrayCtr=iMsvSelection->Count();
+ TRAP_IGNORE(OpenUidlFileL());
+ }
+
+//
+// Kick off async operation
+//
+void CImPop3RefreshOperation::QueueRemoteUpdate()
+ {
+ TRequestStatus *pS = &iStatus;
+ SetActive();
+ User::RequestComplete(pS,KErrNone);
+ }
+
+//
+// Sets the element with the INDEX in the message server
+//
+void CImPop3RefreshOperation::SyncCollectionL()
+ {
+ //iUidlArray has been read from the UIDL file
+ //Look for the Messaging Server ID in iUidlArray
+ //If found, set the member in the array element that points to the message INDEX (not id) in the Messaging Server
+ --iRemoteArrayCtr; // one at a time
+ TMsgUidlStore aUidlStore;;
+ aUidlStore.iMsvId=(*iMsvSelection)[iRemoteArrayCtr];
+ TInt selectRow;
+ if(iUidlArray->FindIsq(aUidlStore,iUidlKey,selectRow))
+ {
+ // Don't handle error in release mode.
+#ifdef _DEBUG
+ TInt err =
+#endif
+ iRemoteServerEntry.DeleteEntry(aUidlStore.iMsvId);
+ __ASSERT_DEBUG(err == KErrNone, Panic(EPopFailedDebugAssert));
+ }
+ else
+ iUidlArray->At(selectRow).iSelectionPos=iRemoteArrayCtr;
+ }
+
+void CImPop3RefreshOperation::CompleteSyncCollection()
+//
+// Complete the synchronization of the collection and local UIDL store
+//
+ {
+ for(TInt ii=iUidlArray->Count();--ii>=0;)
+ {
+ if(iUidlArray->At(ii).iSelectionPos==TMsgUidlStore::EInvalid)
+ {
+ DeleteUidl(ii);
+ }
+ }
+ }
+//
+// Sync the UIDL file for the Message Server to the POP server.
+//
+void CImPop3RefreshOperation::SyncUidlL()
+ {
+ //iPop3Uidls now contains the message ids of the messages on the POP3 server
+ --iRemoteArrayCtr;
+ TMsgUidlStore& uidl=(*iUidlArray)[iRemoteArrayCtr];
+ __ASSERT_DEBUG(uidl.iSelectionPos>=0,User::Invariant());
+
+ TInt popUidlPos = 0;
+ TInt popUidlRow = iPop3Uidls->MsgUidlNo(*uidl.iPopId,popUidlPos);
+ // For duplicated case get the actual positions of the UIDLs.
+ if(popUidlRow == KErrAlreadyExists)
+ {
+ while ( popUidlPos > 0 )
+ {
+ if (iPop3Uidls->MsgUidl(popUidlPos-1) == *uidl.iPopId)
+ {
+ --popUidlPos;
+ }
+ else
+ {
+ break;
+ }
+ }
+ TInt uidlExists = iUniqueUidlPosArray.FindInOrder(popUidlPos);
+ if(uidlExists != KErrNotFound)
+ {
+ //If aUidl already exists find position of next duplicated uidl.
+ popUidlPos = iTemporaryUidlPosArray[uidlExists] + 1;
+
+ // Remove the last duplicated Uidl position value.
+ iTemporaryUidlPosArray.Remove(uidlExists);
+
+ //Insert the position of the present duplicate uidl to the array.
+ iTemporaryUidlPosArray.Insert(popUidlPos,uidlExists);
+ }
+ else
+ {
+ //iUniqueUidlPosArray will contain the first occurrences(pos)of all duplicated UIDLs
+ iUniqueUidlPosArray.InsertInOrder(popUidlPos);
+
+ // For getting next position of duplicate Uidl.
+ iTemporaryUidlPosArray.InsertInOrder(popUidlPos);
+ }
+
+ //Maximum value of popUidlPos should not exceed count(No. of uidls in the popserver - 1).
+ TInt count = iPop3Uidls->MsgCount() - 1;
+ popUidlRow = -1;
+ if(count >= popUidlPos)
+ {
+ // Check Whether the UIDL at popUidlRow of POP server matches the UIDL in Uidl file..
+ if(iPop3Uidls->MsgUidl(popUidlPos) == *uidl.iPopId)
+ {
+ popUidlRow = iPop3Uidls->MsgIndex(popUidlPos);
+ }
+ }
+ }
+
+ //Check whether the UIDL index has already been passed.
+ //This is to Handle the deletion of all duplicated mails from server using other email client.
+ if(iPreviousIndex == popUidlRow)
+ {
+ popUidlRow = -1;
+ }
+ else
+ {
+ iPreviousIndex = popUidlRow;
+ }
+
+
+ if(popUidlRow<0)
+ {
+ //A Message is in the Messaging Server but not on the POP3 server, so delete it from the
+ //the Messaging Server
+#ifdef _DEBUG
+ TInt err =
+#endif
+ iRemoteServerEntry.DeleteEntry(uidl.iMsvId);// Don't handle the error in release mode
+ __ASSERT_DEBUG(err == KErrNone, Panic(EPopFailedDebugAssert));
+ // & delete it from the UIDL file
+ DeleteUidl(iRemoteArrayCtr);
+ }
+ else
+ {
+ //A message is in the Messaging Server *and* is on the POP3 server,
+ //so mark it as present in the UIDL file, and decrement the number of headers to download
+ iIdTab[popUidlRow]=uidl.iMsvId; //GetMessagesIfAny() checks this to see if the header is already present
+ iProgress.iMsgsToProcess--;
+ uidl.iSelectionPos=TMsgUidlStore::EPresent;
+ }
+ }
+//
+// Report the refreshing news back to the UI
+//
+TPop3Progress CImPop3RefreshOperation::Progress()
+ {
+ return iProgress;
+ }
+//
+// Gets Headers or Messages
+//
+void CImPop3RefreshOperation::RetrieveHeadersL()
+ {
+ // Check to see we have at least the minimum free disk space available
+ if (--iCheckDiskSpaceCounter <= 0)
+ {
+ // If we are running low on disk space then leave
+
+ ImCheckDiskSpace::LeaveIfLowDiskL(iFs, iCurrentDrive);
+ iCheckDiskSpaceCounter = KCheckDiskSpaceEveryNMessages;
+ }
+
+ // get header or msg
+ iTopExists ? GetHeaderByIndexL(iMsgCtr) : GetMessageByIndexL(iMsgCtr);
+
+ SetActive();
+ }
+
+//
+// Use Top to Retrieve the message header
+//
+void CImPop3RefreshOperation::GetHeaderByIndexL(TInt anIndex)
+ {
+ __ASSERT_ALWAYS(iPopTop, Panic(EPopNullPointer));
+ iPopTop->SetMessageIndexAndLines(anIndex+1,1);
+ iPopTop->StartL(iStatus);
+ }
+
+//
+// If no Top need to retrieve whole message
+//
+void CImPop3RefreshOperation::GetMessageByIndexL(TInt anIndex)
+ {
+ __ASSERT_ALWAYS(iPopRetr, Panic(EPopNullPointer));
+ iPopRetr->SetMessageIndex(anIndex+1);
+ iPopRetr->StartL(iStatus);
+ }
+
+//
+//
+// Get TMsvEntry from CImHeader via CMsgIMail add to msg collection?
+//
+void CImPop3RefreshOperation::CreateNewHeaderEntryL(TMsvEntry& aNewEntry)
+ {
+ TPtrC8 id;
+ if(iTopExists)
+ {
+ __ASSERT_ALWAYS(iPopTop, Panic(EPopNullPointer));
+ iPopTop->EntryId();
+ id.Set(iPopTop->ImMsgId());
+ }
+ else
+ {
+ __ASSERT_ALWAYS(iPopRetr, Panic(EPopNullPointer));
+ iPopRetr->EntryId();
+ id.Set(iPopRetr->ImMsgId());
+ }
+
+ aNewEntry.SetComplete(EFalse);
+ aNewEntry.SetAttachment(EFalse);
+ aNewEntry.iSize = iSize[iMsgCtr];
+ aNewEntry.iServiceId = iRemoteId;
+ aNewEntry.SetVisible(ETrue);
+ aNewEntry.SetInPreparation(EFalse);
+
+ // add message to list uidl list
+ TMsgUidlStore msgUidlStore;
+ if(iUidlExists)
+ {
+ msgUidlStore.iPopId=(*iPop3Uidls)[iMsgCtr].AllocLC();
+ }
+ else
+#if defined _UNICODE
+ {
+ msgUidlStore.iPopId = HBufC8::NewLC(id.Length());
+ msgUidlStore.iPopId->Des().Copy(id);
+ }
+#else
+ msgUidlStore.iPopId=id.AllocLC();
+#endif
+
+ msgUidlStore.iMsvId=(aNewEntry.Id());
+ msgUidlStore.iRemoteSize=iSize[iMsgCtr];
+ msgUidlStore.iSelectionPos=TMsgUidlStore::EPresent;
+ iUidlArray->InsertIsqL(msgUidlStore,iUidlKey);
+ CleanupStack::Pop(); //iPopId
+ }
+
+
+//
+// Compare internet msg id of retrieved header to what we have stored and compare sizes
+//
+TBool CImPop3RefreshOperation::CompareIdAndSizeL()
+ {
+ TPtrC8 id;
+
+ __ASSERT_ALWAYS(iPopTop && iPopRetr, Panic(EPopNullPointer));
+ iTopExists ? id.Set(iPopTop->ImMsgId()) : id.Set(iPopRetr->ImMsgId());
+
+ CArrayFix<TMsgUidlStore>& uidlarray=*iUidlArray;
+ TInt row=uidlarray.Count();
+ while (--row>=0 && *uidlarray[row].iPopId!=id)
+ ;
+
+ if (row>=0)
+ {
+//we've found an entry in the UIDL file which matches our msg id
+//so we don't need to create a new message
+ TMsgUidlStore& uidlstore=uidlarray[row];
+ if (uidlstore.iRemoteSize==iSize[iMsgCtr])
+ {
+ iIdTab[iMsgCtr]=uidlstore.iMsvId;
+ __ASSERT_DEBUG(uidlstore.iSelectionPos>=0,User::Invariant());
+ uidlstore.iSelectionPos=TMsgUidlStore::EPresent;
+//as the UIDL command is not supported, we have downloaded the header or the message body
+//we're throwing this away now because the message already exists.
+ __ASSERT_ALWAYS(iPopTop && iPopRetr, Panic(EPopNullPointer));
+ TMsvId newId;
+ iTopExists ? newId = iPopTop->EntryId() : newId = iPopRetr->EntryId();
+ iUnwantedEntries->AppendL(newId);
+ return EFalse;
+ }
+ // Set the current context to the POP3 service entry else DeleteEntry panics
+ User::LeaveIfError(iRemoteServerEntry.SetEntry(iRemoteId));
+ // Don't handle the error in release mode.
+#ifdef _DEBUG
+ TInt err =
+#endif
+ iRemoteServerEntry.DeleteEntry(uidlstore.iMsvId); // should this happen?
+ __ASSERT_DEBUG(err == KErrNone, Panic(EPopFailedDebugAssert));
+ DeleteUidl(row);
+ }
+ return ETrue;
+ }
+
+//
+// Open a file of existing POP Uidls with corresponding Babel MsgIds
+//
+void CImPop3RefreshOperation::OpenUidlFileL()
+ {
+ // get path of uidls file from id of remote server entry
+ TInt error = KErrNone;
+ TParse p;
+ TFileName path;
+
+ CMsvStore* store = iRemoteServerEntry.ReadStoreL();
+ CleanupStack::PushL(store);
+ MMsvAttachmentManager& attachmentMgr = store->AttachmentManagerL();
+ // if there is no attachment then a UIDL file has not been
+ // created, so not found.
+ if(attachmentMgr.AttachmentCount() < 1)
+ {
+ User::Leave(KErrNotFound);
+ }
+ CMsvAttachment* attachment = attachmentMgr.GetAttachmentInfoL(0);
+ CleanupStack::PushL(attachment);
+ path = attachment->FilePath();
+ p.Set(path,NULL,NULL);
+ CleanupStack::PopAndDestroy(2,store);
+
+ RFile f;
+ error = f.Open(iFs,p.FullName(),EFileShareReadersOnly);
+ User::LeaveIfError(error);
+
+ CDirectFileStore* index=CDirectFileStore::FromLC(f);
+ const TUidType type(KDirectFileStoreLayoutUid,KNullUid,KMsgFileRemoteIdIndex);
+ if (type != index->Type())
+ {
+ User::Leave(KErrCorrupt);
+ }
+ RStoreReadStream in;
+ in.OpenLC(*index,index->Root());
+ TInt entries = in.ReadInt32L();
+ TMsgUidlStore entry;
+ while (--entries>=0)
+ {
+ HBufC8* popid=HBufC8::NewLC( in, KMaxStringLength );
+ // internalization code... inline to handle cleanup issues
+ entry.iPopId=popid;
+ entry.iMsvId=in.ReadUint32L();
+ entry.iRemoteSize=in.ReadUint32L();
+ entry.iSelectionPos=TMsgUidlStore::EInvalid; // not present in selection (yet)
+ //
+ iUidlArray->AppendL(entry);
+ CleanupStack::Pop(popid); // HBufC8's
+ }
+ CleanupStack::PopAndDestroy(2); // in, index
+ }
+
+//
+// Create new POP Uidl file
+//
+void CImPop3RefreshOperation::CreateUidlFileL()
+ {
+ // create the new index of uidl stuff
+ // put it in folder for current server entry (correct remote mailbox folder)
+ TParse p;
+ TFileName path;
+
+ TInt fileErr = iRemoteServerEntry.SetEntry( iRemoteId );
+ if(fileErr!=KErrNone)
+ {
+ return;
+ }
+
+ CMsvStore* store = iRemoteServerEntry.EditStoreL();
+ CleanupStack::PushL(store);
+ // UIDL file is stored as the first attachment to the server entry
+ // if it is already present then overwrite, else create it,
+ MMsvAttachmentManager& attachmentMgr = store->AttachmentManagerL();
+ RFile file;
+ if(attachmentMgr.AttachmentCount() < 1)
+ {
+ MMsvAttachmentManagerSync& attachmentMgrSync = store->AttachmentManagerExtensionsL();
+ CMsvAttachment *attachment = CMsvAttachment::NewL(CMsvAttachment::EMsvFile);
+ attachmentMgrSync.CreateAttachmentL(KUidlFile,file,attachment); // Takes ownership of attachment
+ CleanupClosePushL(file);
+ store->CommitL();
+ CleanupStack::Pop(&file);
+ }
+ else
+ {
+ file=attachmentMgr.GetAttachmentFileForWriteL(0);
+ }
+ CleanupStack::PopAndDestroy(store);
+
+ CDirectFileStore* index = CDirectFileStore::NewLC(file);
+ const TUidType type(KDirectFileStoreLayoutUid,KNullUid,KMsgFileRemoteIdIndex);
+ index->SetTypeL(type);
+ RStoreWriteStream out;
+ TStreamId id = out.CreateLC(*index);
+ TInt entries = iUidlArray->Count();
+ out.WriteInt32L(entries);
+ for(TInt number = 0; number<entries; number++) // must keep order, go forwards
+ {
+ out << (*iUidlArray)[number];
+ }
+ out.CommitL(); // Commit stream : Is this needed?
+ CleanupStack::PopAndDestroy(); // Destroy stream
+ index->SetRootL(id);
+ index->CommitL(); // Commit store : I guess this is needed!
+ CleanupStack::PopAndDestroy(); // Destroy store
+ }
+
+//
+// Externalise/Internalise Uidl structure
+//
+
+void CImPop3RefreshOperation::TMsgUidlStore::ExternalizeL(RWriteStream& aStream) const
+ {
+ aStream << *iPopId;
+ aStream.WriteUint32L(iMsvId);
+ aStream.WriteUint32L(iRemoteSize);
+ }
+//
+// Sets the selection of entries to keep
+//
+void CImPop3RefreshOperation::SetMessagesToKeepL(const CMsvEntrySelection* aMessagesToKeep)
+ {
+ delete iMessagesToKeep;
+ iMessagesToKeep = NULL;
+ if (aMessagesToKeep)
+ {
+ iMessagesToKeep = aMessagesToKeep->CopyL();
+ }
+ }
+//
+// Check if ok to delete message
+//
+TBool CImPop3RefreshOperation::CanDeleteEntry(const TMsvEmailEntry& aEntry) const
+ // Don't delete email if body exists or if it is an email that is being opened immediately after
+ // the inbox refreshing (See defect PEN-5ESAWM)
+ {
+ if (aEntry.BodyTextComplete())
+ {
+ return EFalse;
+ }
+ // iMessagesToKeep may be Null
+ if (iMessagesToKeep && iMessagesToKeep->Find(aEntry.Id()) != KErrNotFound)
+ {
+ return EFalse;
+ }
+ return ETrue;
+ }
+//
+// Gets the size of the remote message
+//
+TUint CImPop3RefreshOperation::RemoteMessageSizeL(TMsvId aId)
+ {
+ TInt count = iUidlArray->Count();
+ TUint retVal = NULL;
+
+ while( count-- )
+ {
+ const TMsgUidlStore &store=iUidlArray->At(count);
+ if(store.iMsvId == aId)
+ {
+ // We have found a match, so return the size for this item
+ retVal = store.iRemoteSize;
+ break;
+ }
+ }
+
+ if (!retVal)
+ {
+ // Leave if none of the MsvIds match
+ User::Leave(KErrNotFound);
+ }
+ return retVal;
+ }
+
+// ******************************************************************************************
+// This is called by the POP Client MTM when it starts Migrating Bearer
+//
+// ******************************************************************************************
+void CImPop3RefreshOperation::Pause()
+ {
+ // Set the Migration flag
+ iMigratingToNewBearer = ETrue;
+ }
+
+// ******************************************************************************************
+// This is called by the POP Client MTM when it starts Migrating Bearer
+//
+// ******************************************************************************************
+void CImPop3RefreshOperation::CancelAllowResume()
+ {
+ // 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();
+ }