email/imap4mtm/imapprotocolcontroller/src/cimapcompoundsyncservice.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 "cimapcompoundsyncservice.h"
       
    17 
       
    18 #include <imapset.h>
       
    19 
       
    20 #include "cimapfolder.h"
       
    21 #include "cimapsession.h"
       
    22 #include "cimapmailstore.h" 
       
    23 #include "cimapofflinecontrol.h"
       
    24 #include "cimapsyncmanager.h"
       
    25 #include "cimapfolder.h"
       
    26 #include "cimaplogger.h"
       
    27 
       
    28 #include "cimapcompoundcopyfromlocal.h"
       
    29 #include "cimapcompoundcopytolocal.h"
       
    30 #include "cimapcompoundcopywithinservice.h"
       
    31 #include "cimapcompoundcreate.h"
       
    32 #include "cimapcompounddelete.h"
       
    33 #include "cimapcompounddeletefolder.h"
       
    34 #include "cimapcompounddisconnect.h"
       
    35 #include "cimapcompoundrename.h"
       
    36 #include "cimapcompoundselect.h"
       
    37 #include "cimapsessionconsts.h"
       
    38 #include "imappaniccodes.h"
       
    39 #include "cimapofflinecontrol.h"
       
    40 #include "imappaniccodes.h"
       
    41 #include "cimapsyncdownloadrules.h"
       
    42 
       
    43 #include "mobilitytestmtmapi.h"
       
    44 
       
    45 CImapCompoundSyncService::CImapCompoundSyncService(CImapSyncManager& aSyncManager, CMsvServerEntry& aServerEntry, CImapSettings& aImapSettings, CImapMailStore& aImapMailStore, CImapOfflineControl& aImapOfflineControl ,TBool aDoLateDeletes)
       
    46  : CImapCompoundBase(aSyncManager, aServerEntry, aImapSettings), iImapOfflineControl(aImapOfflineControl), iImapMailStore(aImapMailStore), iDoLateDeletes(aDoLateDeletes)
       
    47 	{
       
    48 	// Set default progress values here so that any progress request before
       
    49 	// the operation is started returns valid information.
       
    50 	if(aDoLateDeletes)
       
    51 		{
       
    52 		iProgressState = TImap4GenericProgress::EBusy;
       
    53 		iSyncProgressState=TImap4SyncProgress::EDeleting;
       
    54 		}
       
    55 	else
       
    56 		{
       
    57 		iProgressState = TImap4GenericProgress::ESyncing;
       
    58 		iSyncProgressState=TImap4SyncProgress::ESyncInbox;
       
    59 		}
       
    60 	}
       
    61 
       
    62 CImapCompoundSyncService::~CImapCompoundSyncService()
       
    63 	{
       
    64 	delete iOutstandingOps;
       
    65 	delete iOutstandingMoveTypeDeletes;
       
    66 	delete iOutstandingLocalDeletes;
       
    67 	delete iImapCompound;
       
    68 	delete iDoNotFetchSel;
       
    69 	}
       
    70 	
       
    71 CImapCompoundSyncService* CImapCompoundSyncService::NewL(CImapSyncManager& aSyncManager, CMsvServerEntry& aServerEntry, CImapSettings& aImapSettings, CImapMailStore& aImapMailStore, CImapOfflineControl& aImapOfflineControl ,TBool aDoLateDeletes)
       
    72 	{
       
    73 	CImapCompoundSyncService* self = new (ELeave) CImapCompoundSyncService(aSyncManager, aServerEntry, aImapSettings, aImapMailStore, aImapOfflineControl,aDoLateDeletes);
       
    74 	CleanupStack::PushL(self);
       
    75 	self->ConstructL();
       
    76 	CleanupStack::Pop(self);
       
    77 	return self;
       
    78 	}
       
    79 	
       
    80 void CImapCompoundSyncService::ConstructL()
       
    81 	{
       
    82 	iOutstandingMoveTypeDeletes = new (ELeave) CArrayFixFlat<TMsvId>(4);
       
    83 	iOutstandingLocalDeletes = new (ELeave) CArrayFixFlat<TMsvId>(4);
       
    84 	iPerformDeletes = !(iImapSettings.DeleteEmailsWhenDisconnecting());
       
    85 	
       
    86 	CActiveScheduler::Add(this);
       
    87 	}
       
    88 
       
    89 void CImapCompoundSyncService::StartOperation(TRequestStatus& aStatus, CImapSession& aSession)
       
    90 	{
       
    91 	iSession = &aSession;
       
    92 	__LOG_TEXT(iSession->LogId(), "CImapCompoundSyncService::StartOperation()");
       
    93 	if(iDoLateDeletes)
       
    94 		{
       
    95 		iNextStep = EInboxLateDeletes;
       
    96 		}
       
    97 	else
       
    98 		{
       
    99 		iNextStep = ESyncService;
       
   100 		}
       
   101 	Queue(aStatus);
       
   102 	CompleteSelf();
       
   103 	}
       
   104 	
       
   105 /**
       
   106 Handles the compound operation state machine
       
   107 
       
   108 @return ETrue if compound operation is completed, 
       
   109 		EFalse otherwise (will be called again, unless active)
       
   110 */
       
   111 TBool CImapCompoundSyncService::DoRunLoopL()
       
   112 	{
       
   113 	SetCurrentStep();
       
   114 	switch (iCurrentStep)
       
   115 		{
       
   116 		case ESyncService:  // synchronous
       
   117 			{
       
   118 			// Starts the full sync process by synching the inbox
       
   119 			iNextFolderSync = 0;
       
   120 					
       
   121 			__LOG_TEXT(iSession->LogId(), "CImapCompoundSyncService::DoRunLoopL : Starting the full Sync steps.");
       
   122 			CImapFolder* inbox = iSyncManager.Inbox();
       
   123 			
       
   124 			if(inbox != NULL)
       
   125 				{
       
   126 				iNextStep = EInboxSync;
       
   127 				__LOG_TEXT(iSession->LogId(), "CImapCompoundSyncService::DoRunLoopL : Processing offline for the inbox.");
       
   128 					// Deal with operations in the array
       
   129 				if (RefreshOutstandingOpsL(inbox->MailboxId()))
       
   130 					{
       
   131 					iNextStep = EInboxCheckPendingOps;
       
   132 					}
       
   133 				}
       
   134 			else
       
   135 				{
       
   136 				iNextStep = ESyncTree;
       
   137 				}
       
   138 			
       
   139 			CompleteSelf();
       
   140 			}
       
   141 			break;
       
   142 		case EInboxDoneOps: // synchronous
       
   143 			{
       
   144 			__LOG_TEXT(iSession->LogId(), "CImapCompoundSyncService::DoRunLoopL : Performing the current offline op for the inbox.");
       
   145 
       
   146 			iNextStep = EInboxCheckPendingOps;
       
   147 			DonePendingOpL();
       
   148 			CompleteSelf();
       
   149 			}
       
   150 			break;
       
   151 		case EInboxCheckPendingOps: // synchronous
       
   152 			{
       
   153 			iSyncProgressState=TImap4SyncProgress::EProcessingPendingOps;
       
   154 			__LOG_TEXT(iSession->LogId(), "CImapCompoundSyncService::DoRunLoopL : Find the next offline op for the inbox.");
       
   155 			if (NextPendingOpL())
       
   156 				{
       
   157 				iNextStep = EInboxSync;
       
   158 				DonePendingOpL();
       
   159 				CompleteSelf();
       
   160 				}
       
   161 			else
       
   162 				{
       
   163 				iNextStep = EInboxDoneOps;
       
   164 
       
   165 				// As there is a next pending op, we should be active so that the
       
   166 				// operation can go ahead. However under some circumstances (such
       
   167 				// as a missing shadow ID), the operation will not happen so we need
       
   168 				// to ensure the state machine does not lock up.
       
   169 				if (!IsActive())
       
   170 					{
       
   171 					CompleteSelf();
       
   172 					}
       
   173 				}
       
   174 			}
       
   175 			break;
       
   176 		case EInboxEarlyDeletes: // async, SELECTing the inbox prior to EXPUNGE. 
       
   177 			{
       
   178 			__LOG_TEXT(iSession->LogId(), "CImapCompoundSyncService::DoRunLoopL : Performing early deletes for the inbox.");
       
   179 
       
   180 			iSyncProgressState=TImap4SyncProgress::EDeleting;
       
   181 			// get rid of the FromLocal message sources
       
   182 			CImapFolder* inbox = iSyncManager.Inbox();
       
   183 			
       
   184 			if(inbox)
       
   185 				{
       
   186 				for (TInt i = 0; i < iOutstandingLocalDeletes->Count(); ++i)
       
   187 					{
       
   188 					TMsvId id = (*iOutstandingLocalDeletes)[i];
       
   189 					__LOG_FORMAT((iSession->LogId(), "CImapCompoundSyncService::DoRunLoopL : Removing message %d.", id));
       
   190 					inbox->DeleteMessageL(id);
       
   191 					}
       
   192 
       
   193 				iOutstandingLocalDeletes->Reset();
       
   194 
       
   195 				// then do the inbox deletes
       
   196 				if (ProcessPendingDeleteOpsL(inbox->MailboxId(), !iPerformDeletes))
       
   197 					{
       
   198 					MOBILITY_TEST_MTM_STATE(iImapSettings.ServiceId(), KMobilityTestMtmImapSyncEInboxEarlyDeletes);
       
   199 					iNextStep = EInboxEarlyExpunge;
       
   200 					inbox->SelectL(iStatus, *iSession);
       
   201 					SetActive();
       
   202 					return EFalse;
       
   203 					}
       
   204 				}
       
   205 			else
       
   206 				{
       
   207 				iOutstandingLocalDeletes->Reset();
       
   208 				}
       
   209 
       
   210 			iNextStep = ESyncTree;
       
   211 			CompleteSelf();
       
   212 			}
       
   213 	  		break;
       
   214 		case EInboxEarlyExpunge: // async - sync deletes performed by the folder object, STORE /deleted and EXPUNGE
       
   215 			{
       
   216 			iSyncProgressState=TImap4SyncProgress::EDeleting;
       
   217 
       
   218 			iNextStep = ESyncTree;
       
   219 
       
   220 			if (iStatus.Int() == KErrImapNo)
       
   221 				{
       
   222 				iFoldersNotFound++;
       
   223 				}
       
   224 			else
       
   225 				{
       
   226 				// expunge the folder
       
   227 				iFolder = iSyncManager.Inbox();
       
   228 				
       
   229 				if(iFolder)
       
   230 					{
       
   231 					MOBILITY_TEST_MTM_STATE(iImapSettings.ServiceId(), KMobilityTestMtmImapSyncEInboxEarlyExpunge);
       
   232 					__LOG_FORMAT((iSession->LogId(), "CImapCompoundSyncService::DoRunLoopL : Expunge the folder %S.", &(iFolder->FullFolderPathL())));
       
   233 					iFolder->SyncDeletesL(iStatus, *iSession);
       
   234 					SetActive();
       
   235 					return EFalse;
       
   236 					}
       
   237 				}
       
   238 
       
   239 			CompleteSelf();
       
   240 			}
       
   241 			break;
       
   242 		case EInboxSync: // async
       
   243 			{
       
   244 			__LOG_TEXT(iSession->LogId(), "CImapCompoundSyncService::DoRunLoopL : Calling the Syncmanger step for synching the inbox.");
       
   245 
       
   246 			// suspend operation if stop for migrate has been requested
       
   247 			if (iStopForMigrate)
       
   248 				{
       
   249 				__LOG_TEXT(iSession->LogId(), "CImapCompoundSyncService::Stopped for migrate");
       
   250 				iCurrentStep = ESuspendedForMigrate;
       
   251 				iNextStep = EInboxSync;
       
   252 				Complete(KErrNone);
       
   253 				return ETrue;
       
   254 				}
       
   255 
       
   256 			// Call the SyncManager inbox sync
       
   257 			MOBILITY_TEST_MTM_STATE(iImapSettings.ServiceId(), KMobilityTestMtmImapSyncEInboxSync);			
       
   258 			iSyncProgressState=TImap4SyncProgress::ESyncInbox;
       
   259 			iSyncManager.SynchroniseInboxL(iStatus, *iSession);
       
   260 			iNextStep = EInboxEarlyDeletes;
       
   261 			}
       
   262 			break;
       
   263 		case ESyncTree:  // async
       
   264 			{
       
   265 			// suspend operation if stop for migrate has been requested
       
   266 			if (iStopForMigrate)
       
   267 				{
       
   268 				__LOG_TEXT(iSession->LogId(), "CImapCompoundSyncService::Stopped for migrate");
       
   269 				iCurrentStep = ESuspendedForMigrate;
       
   270 				iNextStep = ESyncTree;
       
   271 				Complete(KErrNone);
       
   272 				return ETrue;
       
   273 				}
       
   274 
       
   275 			iNextStep = ESyncSubscriptions;
       
   276 
       
   277 			// skip folder tree sync if disabled.
       
   278 			if (iImapSettings.FolderSyncDisabled())
       
   279 				{
       
   280 				__LOG_TEXT(iSession->LogId(), "CImapCompoundSyncService::DoRunLoopL : Folder Tree Sync Disabled....");
       
   281 				return EFalse;
       
   282 				}
       
   283 
       
   284 			__LOG_TEXT(iSession->LogId(), "CImapCompoundSyncService::DoRunLoopL : Calling the Syncmanger step to sync the folder tree.");
       
   285 
       
   286 			// Synching the remote folders tree to local
       
   287 			MOBILITY_TEST_MTM_STATE(iImapSettings.ServiceId(), KMobilityTestMtmImapSyncESyncTree);			
       
   288 			iSyncProgressState=TImap4SyncProgress::ESyncFolderTree;
       
   289 			iSyncManager.SynchroniseFolderTreeL(iStatus, *iSession);
       
   290 			}
       
   291 			break;
       
   292 		case ESyncSubscriptions:  // async
       
   293 			{
       
   294 			__LOG_TEXT(iSession->LogId(), "CImapCompoundSyncService::DoRunLoopL : Calling the Syncmanger step to sync the folders subscriptions.");
       
   295 			// Synching the remote folders tree to local
       
   296 			MOBILITY_TEST_MTM_STATE(iImapSettings.ServiceId(), KMobilityTestMtmImapSyncESyncSubscriptions);
       
   297 			iSyncProgressState=TImap4SyncProgress::ECheckRemoteSubscription;
       
   298 			iSyncManager.SynchroniseFolderSubscriptionsL(iStatus, *iSession);
       
   299 			iNextStep = ESelectSyncFolder;
       
   300 			}
       
   301 			break;	
       
   302 		case EFolderDoneOps:  // synchronous
       
   303 			{
       
   304 			if(iNextFolderSync > 0)
       
   305 				{
       
   306 				__LOG_TEXT(iSession->LogId(), "CImapCompoundSyncService::DoRunLoopL : Calling DonePendingOp.");
       
   307 				iNextStep = EFolderCheckPendingOPs;
       
   308 				DonePendingOpL();
       
   309 				}
       
   310 			else
       
   311 				{
       
   312 				// All folders are done.
       
   313 				iNextStep = ESyncInboxAutoFetch;
       
   314 				}
       
   315 			
       
   316 			CompleteSelf();
       
   317 			}
       
   318 			break;
       
   319 		case EFolderCheckPendingOPs: // synchronous
       
   320 			{
       
   321 			iSyncProgressState=TImap4SyncProgress::EProcessingPendingOps;
       
   322 
       
   323 			if(NextPendingOpL())
       
   324 				{
       
   325 				__LOG_TEXT(iSession->LogId(), "CImapCompoundSyncService::DoRunLoopL : All offline ops are done, calling folder sync.");
       
   326 				iNextStep = ESyncFolder;
       
   327 				DonePendingOpL();
       
   328 				CompleteSelf();
       
   329 				}
       
   330 			else
       
   331 				{
       
   332 				__LOG_TEXT(iSession->LogId(), "CImapCompoundSyncService::DoRunLoopL : Got a pending offline op, now do it.");
       
   333 				iNextStep = EFolderDoneOps;
       
   334 
       
   335 				// As there is a next pending op, we should be active so that the
       
   336 				// operation can go ahead. However under some circumstances (such
       
   337 				// as a missing shadow ID), the operation will not happen so we need
       
   338 				// to ensure the state machine does not lock up.
       
   339 				if (!IsActive())
       
   340 					{
       
   341 					CompleteSelf();
       
   342 					}
       
   343 				}
       
   344 			}
       
   345 			break;
       
   346 		case EFolderEarlyDeletes: // asynchronous
       
   347 			{
       
   348 			iSyncProgressState=TImap4SyncProgress::EDeleting;
       
   349 
       
   350 			CImapFolder* currentFolder = iSyncManager.GetFolderL(iNextFolderSync);
       
   351 
       
   352 			if (currentFolder)
       
   353 				{
       
   354 				for (TInt i = 0; i < iOutstandingLocalDeletes->Count(); ++i)
       
   355 					{
       
   356 					TMsvId id = (*iOutstandingLocalDeletes)[i];
       
   357 					__LOG_FORMAT((iSession->LogId(), "CImapCompoundSyncService::DoRunLoopL : Removing message %d.", id));
       
   358 					currentFolder->DeleteMessageL(id);
       
   359 					}
       
   360 
       
   361 				iOutstandingLocalDeletes->Reset();
       
   362 
       
   363 				// if we are doing deletes on connection then all deletes will
       
   364 				// be marked Delete
       
   365 				if (ProcessPendingDeleteOpsListL(!iPerformDeletes))
       
   366 					{
       
   367 					__LOG_FORMAT((iSession->LogId(), "CImapCompoundSyncService::DoRunLoopL : Selecting the folder %S for expunge.", &(currentFolder->FullFolderPathL())));
       
   368 					MOBILITY_TEST_MTM_STATE(iImapSettings.ServiceId(), KMobilityTestMtmImapSyncEFolderEarlyDeletes);
       
   369 					currentFolder->SelectL(iStatus, *iSession);
       
   370 					iNextStep = EFolderEarlyExpunge;
       
   371 					SetActive();
       
   372 					return EFalse;
       
   373 					}
       
   374 				}
       
   375 			else
       
   376 				{
       
   377 				iOutstandingLocalDeletes->Reset();
       
   378 				}
       
   379 
       
   380 			iNextStep = ESelectSyncFolder;
       
   381 			CompleteSelf();
       
   382 			}
       
   383 			break;
       
   384 		case EFolderEarlyExpunge: // asynchronous
       
   385 			{
       
   386 			iSyncProgressState=TImap4SyncProgress::EDeleting;
       
   387 
       
   388 			iNextStep = ESelectSyncFolder;
       
   389 
       
   390 			if (iStatus.Int() == KErrImapNo)
       
   391 				{
       
   392 				++iFoldersNotFound;
       
   393 				}
       
   394 			else
       
   395 				{
       
   396 				iFolder = iSyncManager.GetFolderL(iNextFolderSync);
       
   397 				if(iFolder)
       
   398 					{
       
   399 					// expunge the folder
       
   400 					__LOG_FORMAT((iSession->LogId(), "CImapCompoundSyncService::DoRunLoopL : Expunge the folder %S.", &(iFolder->FullFolderPathL())));
       
   401 					MOBILITY_TEST_MTM_STATE(iImapSettings.ServiceId(), KMobilityTestMtmImapSyncEFolderEarlyExpunge);
       
   402 					iFolder->SyncDeletesL(iStatus, *iSession);
       
   403 					SetActive();
       
   404 					return EFalse;
       
   405 					}
       
   406 				}
       
   407 
       
   408 			CompleteSelf();
       
   409 			}
       
   410 			break;
       
   411 		case ESelectSyncFolder: // synchronous
       
   412 			{
       
   413 			__LOG_TEXT(iSession->LogId(), "CImapCompoundSyncService::ESelectSyncFolder()");
       
   414 			// suspend operation if stop for migrate has been requested
       
   415 			if (iStopForMigrate)
       
   416 				{
       
   417 				__LOG_TEXT(iSession->LogId(), "CImapCompoundSyncService::Stopped for migrate");
       
   418 				iCurrentStep = ESuspendedForMigrate;
       
   419 				iNextStep = ESelectSyncFolder;
       
   420 				Complete(KErrNone);
       
   421 				return ETrue;
       
   422 				}
       
   423 				
       
   424 			// Call for the first time will not be active
       
   425 			iSyncManager.NextSubscribedFoldersL(iNextFolderSync);
       
   426 			iSyncProgressState=TImap4SyncProgress::ESyncOther;
       
   427 
       
   428 			if(iNextFolderSync > 0)
       
   429 				{
       
   430 				// Perform the pending offline operations first
       
   431 				iNextStep = ESyncFolder;
       
   432 				if(RefreshOutstandingOpsL(iNextFolderSync))
       
   433 					{
       
   434 					iNextStep = EFolderCheckPendingOPs;	
       
   435 					}
       
   436 				}
       
   437 			else
       
   438 				{
       
   439 				// All folders are done.
       
   440 				iNextStep = ESyncInboxAutoFetch;
       
   441 				}
       
   442 			CompleteSelf();
       
   443 			}
       
   444 			break;
       
   445 		case ESyncFolder: // async
       
   446 			{
       
   447 			if(iNextFolderSync > 0)
       
   448 				{
       
   449 				// Now sync the folder
       
   450 				MOBILITY_TEST_MTM_STATE(iImapSettings.ServiceId(), KMobilityTestMtmImapSyncESyncFolder);
       
   451 				iSyncManager.SynchroniseSubscribedFoldersL(iStatus, *iSession, iNextFolderSync);
       
   452 				iNextStep = EFolderEarlyDeletes;
       
   453 				}
       
   454 			else
       
   455 				{
       
   456 				// All folders are done.
       
   457 				iNextStep = ESyncInboxAutoFetch;
       
   458 				CompleteSelf();
       
   459 				}
       
   460 			}
       
   461 			break;	
       
   462 		case EInboxLateDeletes: // async
       
   463 			{
       
   464 			iNextFolderSync = 0;
       
   465 			iSyncProgressState=TImap4SyncProgress::EDeleting;
       
   466 			CImapFolder* inbox = iSyncManager.Inbox();
       
   467 
       
   468 			if (inbox)
       
   469 				{
       
   470 				if (ProcessPendingDeleteOpsL( inbox->MailboxId(), EFalse ))
       
   471 					{
       
   472 					MOBILITY_TEST_MTM_STATE(iImapSettings.ServiceId(), KMobilityTestMtmImapEInboxLateDeletes);
       
   473 					inbox->SelectL(iStatus, *iSession);
       
   474 					iNextStep = EInboxLateExpunge;
       
   475 					SetActive();
       
   476 					return EFalse;
       
   477 					}
       
   478 				}
       
   479 
       
   480 			iNextStep = EFolderLateDeletes;
       
   481 			CompleteSelf();
       
   482 			}
       
   483 			break;	
       
   484 		case EInboxLateExpunge: // async
       
   485 			{
       
   486 			iNextStep = EFolderLateDeletes;
       
   487 
       
   488 			if (iStatus.Int() == KErrImapNo)
       
   489 				{
       
   490 				iFoldersNotFound++;
       
   491 				}
       
   492 			else
       
   493 				{
       
   494 				// expunge the folder
       
   495 				iFolder = iSyncManager.Inbox();
       
   496 				
       
   497 				if(iFolder)
       
   498 					{
       
   499 					MOBILITY_TEST_MTM_STATE(iImapSettings.ServiceId(), KMobilityTestMtmImapSyncESyncFolder);
       
   500 					__LOG_FORMAT((iSession->LogId(), "CImapCompoundSyncService::DoRunLoopL : Late Expunge the folder %S.", &(iFolder->FullFolderPathL())));
       
   501 					iFolder->SyncDeletesL(iStatus, *iSession);
       
   502 					SetActive();
       
   503 					return EFalse;
       
   504 					}
       
   505 				}
       
   506 
       
   507 			CompleteSelf();
       
   508 			}
       
   509 			break;
       
   510 		case EFolderLateDeletes: // async
       
   511 			{
       
   512 			iSyncProgressState=TImap4SyncProgress::EDeleting;
       
   513 
       
   514 			// Call for the first time will not be active
       
   515 			iSyncManager.NextSubscribedFoldersL(iNextFolderSync);
       
   516 
       
   517 			if(iNextFolderSync > 0)
       
   518 				{
       
   519 				if (ProcessPendingDeleteOpsListL( EFalse ) )
       
   520 					{
       
   521 					iNextStep = EFolderLateExpunge;
       
   522 					}		
       
   523 				else
       
   524 					{
       
   525 					CImapFolder* currentFolder = iSyncManager.GetFolderL(iNextFolderSync);
       
   526 					if(currentFolder)
       
   527 						{
       
   528 						__LOG_FORMAT((iSession->LogId(), "CImapCompoundSyncService::DoRunLoopL : Selecting the folder %S for expunge.", &(currentFolder->FullFolderPathL())));
       
   529 						MOBILITY_TEST_MTM_STATE(iImapSettings.ServiceId(), KMobilityTestMtmImapSyncEFolderLateDeletes);
       
   530 						iNextStep = EFolderLateExpunge;
       
   531 						currentFolder->SelectL(iStatus, *iSession);
       
   532 						SetActive();
       
   533 						return EFalse;
       
   534 						}
       
   535 
       
   536 					// back to select next folder
       
   537 					iNextStep = EFolderLateDeletes;
       
   538 					}
       
   539 				}
       
   540 			else
       
   541 				{
       
   542 				// No more subscribed folder was found
       
   543 				iNextStep = EFinished;
       
   544 				}
       
   545 
       
   546 			CompleteSelf();
       
   547 			}
       
   548 			break;
       
   549 		case EFolderLateExpunge: // async
       
   550 			{
       
   551 			iNextStep = EFolderLateDeletes;
       
   552 
       
   553 			if (iStatus.Int() == KErrImapNo)
       
   554 				{
       
   555 				iFoldersNotFound++;
       
   556 				}
       
   557 			else
       
   558 				{
       
   559 				iFolder = iSyncManager.GetFolderL(iNextFolderSync);
       
   560 				if(iFolder)
       
   561 					{
       
   562 					__LOG_FORMAT((iSession->LogId(), "CImapCompoundSyncService::DoRunLoopL : Late Expunge the folder %S.", &(iFolder->FullFolderPathL())));
       
   563 					// expunge the folder
       
   564 					MOBILITY_TEST_MTM_STATE(iImapSettings.ServiceId(), KMobilityTestMtmImapSyncEFolderLateExpunge);
       
   565 					iFolder->SyncDeletesL(iStatus, *iSession);
       
   566 					SetActive();
       
   567 					return EFalse;
       
   568 					}
       
   569 				}
       
   570 
       
   571 			CompleteSelf();
       
   572 			}
       
   573 			break;
       
   574 		case ESyncInboxAutoFetch:
       
   575 			{
       
   576 			// suspend operation if stop for migrate has been requested
       
   577 			if (iStopForMigrate)
       
   578 				{
       
   579 				__LOG_TEXT(iSession->LogId(), "CImapCompoundSyncService::Stopped for migrate");
       
   580 				iCurrentStep = ESuspendedForMigrate;
       
   581 				iNextStep = ESyncInboxAutoFetch;
       
   582 				Complete(KErrNone);
       
   583 				return ETrue;
       
   584 				}
       
   585 				
       
   586 			iSyncProgressState=TImap4SyncProgress::ESyncOther;
       
   587 			if (!iImapSettings.UseSyncDownloadRules())
       
   588 				{
       
   589 				// not using sync rules, loop to EFinished.
       
   590 				iNextStep = EFinished;
       
   591 				return EFalse;
       
   592 				}
       
   593 
       
   594 			__LOG_TEXT(iSession->LogId(), "CImapCompoundSyncService::Starting Second Phase Synchronisation");
       
   595 
       
   596 			// set the next step to perform
       
   597 			iNextStep = ESyncFolderAutoFetchCheck;
       
   598 			
       
   599 			if (KErrNotFound == iImapSettings.GetSyncDownloadRuleL(CImapSyncDownloadRules::EInboxRulesType, iMailInfo))
       
   600 				{
       
   601 				// No download rules for the inbox, check other folders
       
   602 				__LOG_TEXT(iSession->LogId(), "CImapCompoundSyncService::No download rules for inbox on this bearer");
       
   603 				return EFalse;
       
   604 				}
       
   605 			
       
   606 			CMsvEntrySelection* selection = new (ELeave) CMsvEntrySelection;
       
   607 			CleanupStack::PushL(selection);
       
   608 			
       
   609 			TInt msgsToFetch = iSyncManager.Inbox()->GetFetchMessageChildrenL(*selection);
       
   610 			__LOG_FORMAT((iSession->LogId(), "CImapCompoundSyncService::Fetching %d INBOX messages.", msgsToFetch));
       
   611 			if (msgsToFetch>0)
       
   612 				{
       
   613 				delete iImapCompound;
       
   614 				iImapCompound = NULL;
       
   615 				// Create the compound operation object
       
   616 				iImapCompound = CImapCompoundCopyToLocal::NewL(iSyncManager, 
       
   617 				                    			               iServerEntry, 
       
   618 				                                			   iImapSettings,
       
   619 				                                			   iImapMailStore, 
       
   620 				                                               EFalse,
       
   621 				                                               *selection,
       
   622 				                                               KMsvNullIndexEntryId,
       
   623 				                                               iMailInfo);
       
   624 				iImapCompound->StartOperation(iStatus, *iSession);
       
   625 				if (iDoNotFetchSel)
       
   626 					{
       
   627 					((CImapCompoundCopyToLocal*)iImapCompound)->RemoveFromSelection(*iDoNotFetchSel);
       
   628 					}
       
   629 				SetActive();
       
   630 				}
       
   631 			CleanupStack::PopAndDestroy(selection);
       
   632 			return EFalse; // if not active, will re-enter this function and perform next step...
       
   633 			}
       
   634 			
       
   635 		case ESyncFolderAutoFetchCheck:
       
   636 			{
       
   637 			// suspend operation if stop for migrate has been requested
       
   638 			if (iStopForMigrate)
       
   639 				{
       
   640 				__LOG_TEXT(iSession->LogId(), "CImapCompoundSyncService::Stopped for migrate");
       
   641 				iCurrentStep = ESuspendedForMigrate;
       
   642 				// fetching of inbox contents may have been stopped prematurely,
       
   643 				// on resume, go back to check if any inbox messages still to fetch.
       
   644 				iNextStep = ESyncInboxAutoFetch;
       
   645 				Complete(KErrNone);
       
   646 				return ETrue;
       
   647 				}
       
   648 
       
   649 			// reset folder sync counter
       
   650 			iFolderSyncCount = 0;
       
   651 			// can only get here if download rules being used, so no need to check that.
       
   652 			// No point in continuing if no download rules defined for non-inbox folders:
       
   653 			if (KErrNotFound == iImapSettings.GetSyncDownloadRuleL(CImapSyncDownloadRules::EFolderRulesType, iMailInfo))
       
   654 				{
       
   655 				// No download rules for non-inbox folders.
       
   656 				iNextStep = EFinished;
       
   657 				return EFalse;
       
   658 				}
       
   659 			// else continue to next step...
       
   660 			}
       
   661 		case ESyncFolderAutoFetch:
       
   662 			{
       
   663 			// suspend operation if stop for migrate has been requested
       
   664 			if (iStopForMigrate)
       
   665 				{
       
   666 				__LOG_TEXT(iSession->LogId(), "CImapCompoundSyncService::Stopped for migrate");
       
   667 				iCurrentStep = ESuspendedForMigrate;
       
   668 				iNextStep = ESyncFolderAutoFetchCheck;
       
   669 				// delete the compound fetch operation - we will create a new one on resume,
       
   670 				// using the download rules for the new bearer.
       
   671 				delete iImapCompound;
       
   672 				iImapCompound = NULL;
       
   673 				Complete(KErrNone);
       
   674 				return ETrue;
       
   675 				}
       
   676 
       
   677 			TInt32 numSubscribedFolders;
       
   678 			CImapFolder* folder = iSyncManager.GetSubscribedFolder(iFolderSyncCount, numSubscribedFolders);
       
   679 			if (folder)
       
   680 				{
       
   681 				CMsvEntrySelection* selection = new (ELeave) CMsvEntrySelection;
       
   682 				CleanupStack::PushL(selection);
       
   683 				TInt msgsToFetch = folder->GetFetchMessageChildrenL(*selection);
       
   684 				__LOG_FORMAT((iSession->LogId(), "CImapCompoundSyncService::Fetching %d messages in folder %d.", msgsToFetch, folder->MailboxId()));
       
   685 				if (msgsToFetch>0)
       
   686 					{
       
   687 					delete iImapCompound;
       
   688 					iImapCompound = NULL;
       
   689 					// Create the compound operation object
       
   690 					iImapCompound = CImapCompoundCopyToLocal::NewL(iSyncManager, 
       
   691 					                    			               iServerEntry, 
       
   692 					                                			   iImapSettings,
       
   693 					                                			   iImapMailStore, 
       
   694 					                                               EFalse,
       
   695 					                                               *selection,
       
   696 					                                               KMsvNullIndexEntryId,
       
   697 					                                               iMailInfo);
       
   698 					iImapCompound->StartOperation(iStatus, *iSession);
       
   699 					if (iDoNotFetchSel)
       
   700 						{
       
   701 						((CImapCompoundCopyToLocal*)iImapCompound)->RemoveFromSelection(*iDoNotFetchSel);
       
   702 						}
       
   703 					SetActive();
       
   704 					}
       
   705 				CleanupStack::PopAndDestroy(selection);
       
   706 				// when complete, check the next folder...
       
   707 				++iFolderSyncCount;
       
   708 				iNextStep = ESyncFolderAutoFetch;
       
   709 				}
       
   710 			else
       
   711 				{
       
   712 				__LOG_TEXT(iSession->LogId(), "CImapCompoundSyncService::Download Rules Auto Fetch Completed.");
       
   713 				iNextStep = EFinished;
       
   714 				}
       
   715 			return EFalse; // not finished yet...
       
   716 			}
       
   717 			
       
   718 		case EFinished:
       
   719 			{
       
   720 			__LOG_TEXT(iSession->LogId(), "CImapCompoundSyncService::Completing OK");
       
   721 			iSyncProgressState=TImap4SyncProgress::EIdle;
       
   722 			iProgressState = TImap4GenericProgress::EIdle;
       
   723 			Complete(KErrNone);
       
   724 			return ETrue;
       
   725 			}
       
   726 		default:
       
   727 			{
       
   728 			__ASSERT_DEBUG(EFalse, TImapServerPanic::ImapPanic(TImapServerPanic::ESyncServiceCompoundUnexpectedState));
       
   729 			// unexpected state - complete the request
       
   730 			iSyncProgressState=TImap4SyncProgress::EIdle;
       
   731 			iProgressState = TImap4GenericProgress::EIdle;
       
   732 			return ETrue;
       
   733 			}
       
   734 		} // end of switch (iCurrentStep)
       
   735 
       
   736 	if (!IsActive())
       
   737 		{
       
   738 		SetActive();
       
   739 		}
       
   740 	return EFalse;
       
   741 	}
       
   742 	
       
   743 /**
       
   744 May be called in case of a genuine cancel or a cancel for migrate.
       
   745 Following a genuine cancel, the compound operation will be deleted.
       
   746 Following a cancel for migrate, the compound operation will be resumed,
       
   747 so the iNextState is updated here to ensure the operation is
       
   748 correctly restarted.
       
   749 
       
   750 In either case, CMsgActive::DoCancel() is called to complete the
       
   751 user request with KErrCancel.
       
   752 
       
   753 In most cases, it is possible to resume at the current step following a
       
   754 cancel-for-migration (sometimes following a SELECT on the current folder).
       
   755 
       
   756 Note that if the default CMsgActive::DoComplete() is overridden,
       
   757 then that must also be modified to handle either case described above.
       
   758 
       
   759 Note on cancelling folder select operations: the folder actually passes 
       
   760 the iStatus to the session, hence the cancel is on the session.
       
   761 */
       
   762 void CImapCompoundSyncService::DoCancel()
       
   763 	{
       
   764 	switch (iCurrentStep)
       
   765 		{
       
   766 		case ESelectSourceMailboxRW:
       
   767 			{
       
   768 			// only set by ResumeOperation. No update to iNextStep required
       
   769 			iSession->Cancel();
       
   770 			break;
       
   771 			}
       
   772 		case EInboxEarlyDeletes:  // re-select inbox before resuming
       
   773 		case EFolderEarlyDeletes: // re-select current folder before resuming
       
   774 		case EInboxLateDeletes:   // wont be resumed, as part of disconnect
       
   775 		case EFolderLateDeletes:  // wont be resumed, as part of disconnect
       
   776 			{
       
   777 			// outstanding request on session.
       
   778 			iSession->Cancel();
       
   779 			break;
       
   780 			}
       
   781 		case EInboxEarlyExpunge:  // re-select inbox before resuming
       
   782 		case EFolderEarlyExpunge: // re-select current folder before resuming
       
   783 		case EInboxLateExpunge:   // should not be resumed, as part of disconnect
       
   784 		case EFolderLateExpunge:  // should not resumed, as part of disconnect
       
   785 			{
       
   786 			// outstanding request on folder
       
   787 			if (iFolder)
       
   788 				{
       
   789 				iFolder->Cancel();
       
   790 				}
       
   791 			iNextStep = iCurrentStep; 
       
   792 			break;
       
   793 			}
       
   794 		case EInboxSync:
       
   795 		case ESyncSubscriptions:
       
   796 		case ESyncTree:
       
   797 		case ESyncFolder:
       
   798 			{
       
   799 			// outstanding request on syncmanager
       
   800 			if (iCancelForMigrate)
       
   801 				{
       
   802 				iSyncManager.CancelForMigrate();
       
   803 				}
       
   804 			else
       
   805 				{
       
   806 				iSyncManager.Cancel();
       
   807 				}
       
   808 			// resume from the tree synchronisation
       
   809 			iNextStep = iCurrentStep;			
       
   810 			break;
       
   811 			}		
       
   812 		case EFolderCheckPendingOPs:
       
   813 		case EInboxCheckPendingOps:
       
   814 			{
       
   815 			// outstanding request on compound object
       
   816 			if (iImapCompound)
       
   817 				{
       
   818 				if (iCancelForMigrate)
       
   819 					{
       
   820 					iImapCompound->CancelForMigrate();
       
   821 					// do not update iNextStep ( == EInboxDoneOps || EFolderDoneOps )
       
   822 					// This operation will be resumed...
       
   823 					}
       
   824 				else
       
   825 					{
       
   826 					iImapCompound->Cancel();
       
   827 					}
       
   828 				}
       
   829 			break;
       
   830 			}
       
   831 		case ESyncInboxAutoFetch:
       
   832 			{
       
   833 			// outstanding request on compound object
       
   834 			if (iImapCompound)
       
   835 				{
       
   836 				// don't cancel-for-migrate - will re-create new object on restart
       
   837 				// as the download rules may well be different on the new carrier.
       
   838 				iImapCompound->Cancel();
       
   839 				}
       
   840 			iNextStep = ESyncInboxAutoFetch;
       
   841 			break;
       
   842 			}
       
   843 		case ESyncFolderAutoFetchCheck:
       
   844 		case ESyncFolderAutoFetch:
       
   845 			{
       
   846 			// outstanding request on compound object
       
   847 			if (iImapCompound)
       
   848 				{
       
   849 				// don't cancel-for-migrate - will re-create new object on restart
       
   850 				// as the download rules may well be different on the new carrier.
       
   851 				iImapCompound->Cancel();
       
   852 				}
       
   853 			// restart in the check state to update the download rules being used.
       
   854 			iNextStep = ESyncFolderAutoFetchCheck;
       
   855 			break;
       
   856 			}
       
   857 		case EInboxDoneOps:
       
   858 		case ESyncService:
       
   859 		case EFolderDoneOps:
       
   860 		case ESelectSyncFolder:
       
   861 		case EFinished:
       
   862 		case ESuspendedForMigrate:
       
   863 		default:
       
   864 			{
       
   865 			__ASSERT_DEBUG(EFalse, TImapServerPanic::ImapPanic(TImapServerPanic::ESyncServiceCompoundCancelUnexpectedState));
       
   866 			iNextStep = EFinished;
       
   867 			break;
       
   868 			}
       
   869 		} // end of switch (iCurrentStep)
       
   870 
       
   871 	if (!iCancelForMigrate)
       
   872 		{
       
   873 		// genuine cancel - update progress
       
   874 		iProgressErrorCode = KErrCancel;
       
   875 		}
       
   876 	CMsgActive::DoCancel();	
       
   877 	}
       
   878 
       
   879 
       
   880 void CImapCompoundSyncService::Progress(TImap4CompoundProgress& aCompoundProgress)
       
   881 	{
       
   882 	aCompoundProgress.iGenericProgress.iOperation = TImap4GenericProgress::ESync;
       
   883 	aCompoundProgress.iGenericProgress.iState = iProgressState;
       
   884 
       
   885 	iSyncManager.Progress(aCompoundProgress.iSyncProgress);
       
   886 	aCompoundProgress.iSyncProgress.iState = iSyncProgressState;
       
   887 
       
   888 	// Put error into progress buffer
       
   889 	if( aCompoundProgress.iGenericProgress.iErrorCode == KErrNone )
       
   890 		{
       
   891 		aCompoundProgress.iGenericProgress.iErrorCode = iProgressErrorCode;
       
   892 		}
       
   893 	}
       
   894 
       
   895 /**
       
   896 Handles NO/BAD responses according to current step.
       
   897 Negative server responses are not fatal - the error is saved in
       
   898 the message currently being operated on and the state machine pushed
       
   899 on to process the next message in the requested selection.
       
   900 
       
   901 @return KErrNone if the error has been handled
       
   902 		Completion error code otherwise.
       
   903 */
       
   904 TInt CImapCompoundSyncService::ProcessNegativeServerResponse()
       
   905 	{
       
   906 	TInt err = iStatus.Int();
       
   907 	switch (iCurrentStep)
       
   908 		{
       
   909 	case ESyncTree:
       
   910 	case ESyncSubscriptions:
       
   911 	case EInboxDoneOps:
       
   912 	case EFolderDoneOps:
       
   913 	case EFolderCheckPendingOPs:
       
   914 	case EInboxCheckPendingOps:
       
   915 	case EInboxSync:
       
   916 	case EInboxEarlyDeletes:
       
   917 	case EFolderEarlyDeletes:
       
   918 	case EInboxEarlyExpunge:
       
   919 	case EFolderEarlyExpunge:
       
   920 	case EInboxLateDeletes:
       
   921 	case EFolderLateDeletes:
       
   922 	case EInboxLateExpunge:
       
   923 	case EFolderLateExpunge:
       
   924 	case ESyncFolder:
       
   925 	case ESyncService:
       
   926 	case ESyncInboxAutoFetch:
       
   927 	case ESyncFolderAutoFetchCheck:
       
   928 	case ESyncFolderAutoFetch:
       
   929 		{
       
   930 		// Just store the error code in the progress response.
       
   931 		break;
       
   932 		}
       
   933 	case ESuspendedForMigrate:
       
   934 	case EFinished:
       
   935 	default:
       
   936 		{
       
   937 		// positive error code not expected,
       
   938 		// self-completed states or no outstanding request.
       
   939 		TImapServerPanic::ImapPanic(TImapServerPanic::ESyncServiceCompoundUnexpectedState);
       
   940 		break;
       
   941 		}
       
   942 		} // end of switch (iCurrentStep)
       
   943 	iProgressErrorCode = err;
       
   944 	return KErrNone;
       
   945 	}
       
   946 
       
   947 
       
   948 /**
       
   949 Given an id of a folder or the service, restores the offline
       
   950 operation array. Returns the number of operations in the array.
       
   951 Any non-zero return value indicates an action that needs to be addressed.
       
   952 */
       
   953 TBool CImapCompoundSyncService::RefreshOutstandingOpsL(TMsvId aId)
       
   954 	{
       
   955 	if (iOutstandingOps)
       
   956 		{
       
   957 		delete iOutstandingOps;
       
   958 		iOutstandingOps = NULL;
       
   959 		}
       
   960 	
       
   961 	iOutstandingOps = iImapOfflineControl.OffLineOpArrayL(aId);
       
   962 	iOutstandingOpsFolder = aId;
       
   963 
       
   964 	// reset the count
       
   965 	iMsgsToDo = iOutstandingOps->CountOperations();
       
   966 	
       
   967 	iMsgsDone = 0;
       
   968 	
       
   969 	iMovedId = KMsvNullIndexEntryId;
       
   970 	iShadowId = KMsvNullIndexEntryId;
       
   971 
       
   972 	return iMsgsToDo;
       
   973 	}
       
   974 
       
   975 /**
       
   976  This routine sets up iShadowId which will be deleted when the
       
   977 operation completes successfully
       
   978 
       
   979 */
       
   980 void CImapCompoundSyncService::DoOpL(const CImOffLineOperation& aOp)
       
   981 	{
       
   982 	// clean the disconnected op flags and ensure its visible and get
       
   983 	// an entry copy
       
   984 	SetEntryL(aOp.MessageId());
       
   985 	TMsvEmailEntry entry = iServerEntry.Entry();
       
   986 	entry.SetVisible(ETrue);
       
   987 	entry.SetDisconnectedOperation(ENoDisconnectedOperations);
       
   988 	ChangeEntryL(entry);
       
   989 
       
   990 	// check and see if there is a shadow and whether it has been
       
   991 	// removed or marked for deletion
       
   992 	TBool shadowOK = ETrue;
       
   993 	if ( aOp.OpType() != CImOffLineOperation::EOffLineOpMtmSpecific &&
       
   994 		 aOp.OpType() != CImOffLineOperation::EOffLineOpDelete )
       
   995 		{
       
   996 		iShadowId = iImapOfflineControl.FindShadowIdL(aOp);
       
   997 
       
   998 		shadowOK = iShadowId != KMsvNullIndexEntryId &&
       
   999 			iServerEntry.SetEntry(iShadowId) == KErrNone &&
       
  1000 			((TMsvEmailEntry)iServerEntry.Entry()).DisconnectedOperation() != EDisconnectedDeleteOperation;
       
  1001 		}
       
  1002 
       
  1003 	delete iImapCompound;
       
  1004 	iImapCompound = NULL;
       
  1005 
       
  1006 	CMsvEntrySelection* selection = new (ELeave) CMsvEntrySelection;
       
  1007 	CleanupStack::PushL(selection);
       
  1008 	
       
  1009 	// Deal with operation
       
  1010 	switch(aOp.OpType())
       
  1011 		{
       
  1012 	case CImOffLineOperation::EOffLineOpCopyToLocal:
       
  1013 		// do the copy, if not a message
       
  1014 		if (entry.iType != KUidMsvMessageEntry ||
       
  1015 			// or the shadow exists
       
  1016 			shadowOK )
       
  1017 			{
       
  1018 			__LOG_FORMAT((iSession->LogId(), "CImOffLineOperation::EOffLineOpCopyToLocal : %d %d", aOp.MessageId(), aOp.TargetMessageId()));
       
  1019 
       
  1020 			//Create Copy to Local Compound object
       
  1021 		
       
  1022 			selection->AppendL(aOp.MessageId());
       
  1023 			
       
  1024 			iImapCompound = CImapCompoundCopyToLocal::NewL(iSyncManager, 
       
  1025 														   iServerEntry, 
       
  1026 														   iImapSettings,
       
  1027 														   iImapMailStore,
       
  1028 														   EFalse,
       
  1029 		                                               	   *selection,
       
  1030 		                                               	   aOp.TargetMessageId());
       
  1031 			
       
  1032 			iImapCompound->StartOperation(iStatus, *iSession);
       
  1033 			SetActive();
       
  1034 			}
       
  1035 		break;
       
  1036 		
       
  1037 	case CImOffLineOperation::EOffLineOpCopyFromLocal:
       
  1038 		if (shadowOK)
       
  1039 			{
       
  1040 			__LOG_FORMAT((iSession->LogId(), "CImOffLineOperation::EOffLineOpCopyFromLocal : %d %d", aOp.MessageId(), aOp.TargetMessageId()));
       
  1041 
       
  1042 			//Create Copy from Local Compound object
       
  1043 
       
  1044 			selection->AppendL(aOp.MessageId());
       
  1045 			
       
  1046 			iImapCompound = CImapCompoundCopyFromLocal::NewL(iSyncManager, 
       
  1047 														     iServerEntry, 
       
  1048 														     iImapSettings,
       
  1049 														     EFalse,
       
  1050 		                                               	     *selection,
       
  1051 		                                               	     aOp.TargetMessageId());
       
  1052 			
       
  1053 			iImapCompound->StartOperation(iStatus, *iSession);
       
  1054 			SetActive();
       
  1055 			}
       
  1056 		break;
       
  1057 
       
  1058 	case CImOffLineOperation::EOffLineOpCopyWithinService:
       
  1059 		if (shadowOK)
       
  1060 			{
       
  1061 			__LOG_FORMAT((iSession->LogId(), "CImOffLineOperation::EOffLineOpCopyWithinService : %d %d", aOp.MessageId(), aOp.TargetMessageId()));
       
  1062 
       
  1063 			//Create Copy within service Compound object
       
  1064 
       
  1065 			selection->AppendL(aOp.MessageId());
       
  1066 			
       
  1067 			iImapCompound = CImapCompoundCopyWithinService::NewL(iSyncManager, 
       
  1068 														   		 iServerEntry, 
       
  1069 														   		 iImapSettings,
       
  1070 														   		 EFalse,
       
  1071 														   		 *selection,
       
  1072 														   		 aOp.TargetMessageId());
       
  1073 			
       
  1074 			iImapCompound->StartOperation(iStatus, *iSession);
       
  1075 			SetActive();
       
  1076 			}
       
  1077 		break;
       
  1078 		
       
  1079 	case CImOffLineOperation::EOffLineOpMoveToLocal:
       
  1080 		if (shadowOK)
       
  1081 			{
       
  1082 			__LOG_FORMAT((iSession->LogId(), "CImOffLineOperation::EOffLineOpMoveToLocal : %d %d", aOp.MessageId(), aOp.TargetMessageId()));
       
  1083 
       
  1084 			selection->AppendL(aOp.MessageId());
       
  1085 			
       
  1086 			iImapCompound = CImapCompoundCopyToLocal::NewL(iSyncManager, 
       
  1087 														   iServerEntry, 
       
  1088 														   iImapSettings,
       
  1089 														   iImapMailStore,
       
  1090 														   EFalse,
       
  1091 		                                               	   *selection,
       
  1092 		                                               	   aOp.TargetMessageId());
       
  1093 			
       
  1094 			iImapCompound->StartOperation(iStatus, *iSession);
       
  1095 			SetActive();
       
  1096 			}
       
  1097 		// even if the shadow has been removed we still want to delete
       
  1098 		// the original
       
  1099 		iMovedId = aOp.MessageId();
       
  1100 		break;
       
  1101 
       
  1102 	case CImOffLineOperation::EOffLineOpMoveFromLocal:
       
  1103 		if (shadowOK)
       
  1104 			{
       
  1105 			__LOG_FORMAT((iSession->LogId(), "CImOffLineOperation::EOffLineOpMoveFromLocal : %d %d", aOp.MessageId(), aOp.TargetMessageId()));
       
  1106 
       
  1107 			//Create Copy from Local Compound object
       
  1108 
       
  1109 			selection->AppendL(aOp.MessageId());
       
  1110 			
       
  1111 			iImapCompound = CImapCompoundCopyFromLocal::NewL(iSyncManager, 
       
  1112 														     iServerEntry, 
       
  1113 														     iImapSettings,
       
  1114 														     EFalse,
       
  1115 		                                               	     *selection,
       
  1116 		                                               	     aOp.TargetMessageId());
       
  1117 			
       
  1118 			iImapCompound->StartOperation(iStatus, *iSession);
       
  1119 			SetActive();
       
  1120 			}
       
  1121 		// even if the shadow has been removed we still want to delete
       
  1122 		// the original
       
  1123 		iMovedId = aOp.MessageId();
       
  1124 		break;
       
  1125 
       
  1126 	case CImOffLineOperation::EOffLineOpMoveWithinService:
       
  1127 		if (shadowOK)
       
  1128 			{
       
  1129 			__LOG_FORMAT((iSession->LogId(), "CImOffLineOperation::EOffLineOpMoveWithinService : %d %d", aOp.MessageId(), aOp.TargetMessageId()));
       
  1130 
       
  1131 			//Create Copy within service Compound object
       
  1132 
       
  1133 			selection->AppendL(aOp.MessageId());
       
  1134 			
       
  1135 			iImapCompound = CImapCompoundCopyWithinService::NewL(iSyncManager, 
       
  1136 														   		 iServerEntry, 
       
  1137 														   		 iImapSettings,
       
  1138 														   		 EFalse,
       
  1139 														   		 *selection,
       
  1140 														   		 aOp.TargetMessageId());
       
  1141 			
       
  1142 			iImapCompound->StartOperation(iStatus, *iSession);
       
  1143 			SetActive();
       
  1144 			}
       
  1145 		// even if the shadow has been removed we still want to delete
       
  1146 		// the original, unless the folder itself has been removed
       
  1147 		if (iServerEntry.SetEntry(aOp.TargetMessageId()) == KErrNone)
       
  1148 			{
       
  1149 			iMovedId = aOp.MessageId();
       
  1150 			}
       
  1151 		break;
       
  1152 
       
  1153 	case CImOffLineOperation::EOffLineOpMtmSpecific:
       
  1154 		switch (aOp.MtmFunctionId())
       
  1155 			{
       
  1156 		case EFnOffLineOpPopulate:
       
  1157 			{
       
  1158 			__LOG_FORMAT((iSession->LogId(), "CImOffLineOperation::EFnOffLineOpPopulate : %d", aOp.MessageId()));
       
  1159 
       
  1160 			//Create Copy to Local Compound object
       
  1161 		
       
  1162 			selection->AppendL(aOp.MessageId());
       
  1163 			
       
  1164 			// aOp.MtmParameters() for EFnOffLineOpPopulate is a package that contains the partial mail info.
       
  1165 			//
       
  1166 			// 1) Create an unitialised dummy partial mail object.  This will NOT receive the partial mail data, but is needed for the build.
       
  1167 			TImImap4GetPartialMailInfo dummyPartialMailInfo;
       
  1168 			// 2) Create a package object that WILL point at the package data.
       
  1169 			//    but for now we need to point it at our unitialised partial mail object, in order for it to compile.
       
  1170 			TPckgC<TImImap4GetPartialMailInfo> partialMailInfoPackage(dummyPartialMailInfo);
       
  1171 			// 3) Immediately point our package object at the actual package data.
       
  1172 			partialMailInfoPackage.Set(aOp.MtmParameters());
       
  1173 					
       
  1174 			iImapCompound = CImapCompoundCopyToLocal::NewL(iSyncManager, 
       
  1175 														   iServerEntry, 
       
  1176 														   iImapSettings,
       
  1177 														   iImapMailStore,
       
  1178 														   EFalse,
       
  1179 		                                               	   *selection,
       
  1180 		                                               	   KMsvNullIndexEntryId,
       
  1181 		                                               	   partialMailInfoPackage()); // pass the actual package data as an object
       
  1182 			
       
  1183 			iImapCompound->StartOperation(iStatus, *iSession);
       
  1184 			SetActive();
       
  1185 			break;
       
  1186 			}
       
  1187 		default:
       
  1188 			break;
       
  1189 			}
       
  1190 		break;
       
  1191 
       
  1192 	case CImOffLineOperation::EOffLineOpDelete:
       
  1193 	default:
       
  1194 		break;
       
  1195 		}
       
  1196 
       
  1197 	CleanupStack::PopAndDestroy(selection);
       
  1198 	}
       
  1199 
       
  1200 /**
       
  1201 Tidies up after performing an offline operation. 
       
  1202 In the case of move operations, this means storing an array of messages that are to
       
  1203 be deleted on the server later in the sync phase (early deletes) or as the service 
       
  1204 is disconnected (late deletes).
       
  1205 
       
  1206 */
       
  1207 void CImapCompoundSyncService::DonePendingOpL()
       
  1208 	{
       
  1209 	// if we've done one then...
       
  1210 	if (iMsgsDone != 0)
       
  1211 		{
       
  1212 		// if this was a move then append a delete
       
  1213 		if (iMovedId != KMsvNullIndexEntryId)
       
  1214 			{
       
  1215 			SetEntryL(iMovedId);
       
  1216 			if (iServerEntry.Entry().Parent() == iOutstandingOpsFolder)
       
  1217 				{
       
  1218 				__LOG_FORMAT((iSession->LogId(), "Append MoveDelete for %x", iMovedId));
       
  1219 				iOutstandingMoveTypeDeletes->AppendL(iMovedId);
       
  1220 				}
       
  1221 			else
       
  1222 				{
       
  1223 				// if this id was from a MoveFrom (ie its parent is not
       
  1224 				// this folder) then put it in a different pending array
       
  1225 				__LOG_FORMAT((iSession->LogId(), "Append LocalDelete for %x", iMovedId));
       
  1226 				iOutstandingLocalDeletes->AppendL(iMovedId);
       
  1227 				}
       
  1228 			}
       
  1229 		
       
  1230 		// delete the shadowid if there is one, ignore errors
       
  1231 		if (iShadowId != KMsvNullIndexEntryId &&
       
  1232 			iServerEntry.SetEntry(iShadowId) == KErrNone &&
       
  1233 			iServerEntry.SetEntry(iServerEntry.Entry().Parent()) == KErrNone)
       
  1234 			{
       
  1235 			iServerEntry.DeleteEntry(iShadowId);
       
  1236 			}
       
  1237 		}
       
  1238 	}
       
  1239 
       
  1240 /**
       
  1241 Checks current folder's pending offline operation list. If no more pending operations
       
  1242 exist, returns ETrue, otherwise calls DoOpL() and returns EFalse.
       
  1243 
       
  1244 DoOpL() creates a compound operation object to perform the requested operation, 
       
  1245 and launches it, setting this class active.
       
  1246 
       
  1247 Note in some circumstances it is possible that the operation cannot be performed, for
       
  1248 example if the folder in question has subsequently become unsubscribed. If this occurs,
       
  1249 this function shall return EFalse (as though an operation had been started) however,
       
  1250 the class will not have been set active.
       
  1251 
       
  1252 @return ETrue if no more pending operations to be performed at this time.
       
  1253 */
       
  1254 TBool CImapCompoundSyncService::NextPendingOpL()
       
  1255 	{
       
  1256 	TBool finished = EFalse;
       
  1257 
       
  1258 	iMovedId = KMsvNullIndexEntryId;
       
  1259 	iShadowId = KMsvNullIndexEntryId;
       
  1260 
       
  1261 	// Any operations in outstanding list?
       
  1262 	if (iOutstandingOps->CountOperations())
       
  1263 		{
       
  1264 		__LOG_FORMAT((iSession->LogId(), "Outstanding operations on this folder %d", iOutstandingOps->CountOperations()));
       
  1265 
       
  1266 		// Fetch operation
       
  1267 		CImOffLineOperation* thisop = new(ELeave)CImOffLineOperation();
       
  1268 		CleanupStack::PushL(thisop);
       
  1269 		
       
  1270 		thisop->CopyL(iOutstandingOps->Operation(0));
       
  1271 
       
  1272 		// when we get to one of the Delete operations then it is time
       
  1273 		// to stop
       
  1274 		if (thisop->OpType() == CImOffLineOperation::EOffLineOpDelete ||
       
  1275 			(thisop->OpType() == CImOffLineOperation::EOffLineOpMtmSpecific &&
       
  1276 			 thisop->MtmFunctionId() == EFnOffLineOpMoveDelete))
       
  1277 			{
       
  1278 			__LOG_TEXT(iSession->LogId(),"Reached delete op. Finished");
       
  1279 			++iMsgsDone;
       
  1280 			finished = ETrue;
       
  1281 			}
       
  1282 		else
       
  1283 			{
       
  1284 			// remove from list and save back
       
  1285 			iOutstandingOps->Delete(0);
       
  1286 			iImapOfflineControl.SetOffLineOpArrayL(iOutstandingOpsFolder, *iOutstandingOps);
       
  1287 
       
  1288 			// and execute
       
  1289 			DoOpL(*thisop);
       
  1290 			++iMsgsDone;
       
  1291 			}
       
  1292 		
       
  1293 		CleanupStack::PopAndDestroy(thisop);
       
  1294 		}
       
  1295 	else
       
  1296 		{
       
  1297 		// No more operations to do, return to what we should be doing next
       
  1298 		finished = ETrue;
       
  1299 		}
       
  1300 
       
  1301 	// when we are about to finish this folder then tidy up
       
  1302 	if (finished)
       
  1303 		{
       
  1304 		// add the list of pending deletes to the front of the
       
  1305 		// offline op array
       
  1306 		for (TInt i = 0; i < iOutstandingMoveTypeDeletes->Count(); i++)
       
  1307 			{
       
  1308 			TMsvId id = (*iOutstandingMoveTypeDeletes)[i];
       
  1309 			CImOffLineOperation* thisop = new(ELeave)CImOffLineOperation();
       
  1310 			CleanupStack::PushL(thisop);
       
  1311 
       
  1312 			// if we are doing deletes on connection then store this
       
  1313 			// as a delete and we will do all deletes at the end of
       
  1314 			// the sync.
       
  1315 
       
  1316 			// if we are doing deletes on disconnection then store
       
  1317 			// this as a special code - it will still get done at end
       
  1318 			// of sync, but real deletes will be done on
       
  1319 			// disconnection.
       
  1320 			if (!iImapSettings.DeleteEmailsWhenDisconnecting()) // iPerformDeletes
       
  1321 				{
       
  1322 				thisop->SetDelete(id);
       
  1323 				}				
       
  1324 			else
       
  1325 				{
       
  1326 				thisop->SetMtmSpecificCommandL(id, EFnOffLineOpMoveDelete, 0, KNullDesC8());
       
  1327 				}
       
  1328 
       
  1329 			iOutstandingOps->InsertOperationL(*thisop, 0);
       
  1330 			CleanupStack::PopAndDestroy(thisop);
       
  1331 			}
       
  1332 
       
  1333 		// if there were outstanding move type deletes then clear
       
  1334 		// their array and save back the main outstanding ops list
       
  1335 		if (iOutstandingMoveTypeDeletes->Count())
       
  1336 			{
       
  1337 			iOutstandingMoveTypeDeletes->Reset();
       
  1338 
       
  1339 			iImapOfflineControl.SetOffLineOpArrayL(iOutstandingOpsFolder, *iOutstandingOps);
       
  1340 			}
       
  1341 		}
       
  1342 
       
  1343 	return finished;
       
  1344 	}
       
  1345 
       
  1346 TBool CImapCompoundSyncService::MatchDeleteOp(const CImOffLineOperation& aOp , TBool aMoveDeletesOnly )
       
  1347 	{
       
  1348 	return (aOp.OpType() == CImOffLineOperation::EOffLineOpMtmSpecific && aOp.MtmFunctionId() == EFnOffLineOpMoveDelete) ||
       
  1349 		(!aMoveDeletesOnly && aOp.OpType() == CImOffLineOperation::EOffLineOpDelete);
       
  1350 	}
       
  1351 
       
  1352 TBool CImapCompoundSyncService::ProcessPendingDeleteOpsL( TMsvId aFolder, TBool aMoveDeletesOnly )
       
  1353 	{
       
  1354 	TBool hadDeletes = EFalse;
       
  1355 
       
  1356 	__LOG_FORMAT((iSession->LogId(), "CImapCompoundSyncService::ProcessPendingDeleteOpsL: Folder %x aMoveDeletesOnly=%d", aFolder, aMoveDeletesOnly));
       
  1357 		
       
  1358 	// get the current offline operations of this folder
       
  1359 	if (RefreshOutstandingOpsL(aFolder))
       
  1360 		{
       
  1361 		// Fetch operation
       
  1362 		CImOffLineOperation* thisop = new(ELeave)CImOffLineOperation();
       
  1363 		CleanupStack::PushL(thisop);
       
  1364 		
       
  1365 		thisop->CopyL(iOutstandingOps->Operation(0));
       
  1366 
       
  1367 		// check delete type
       
  1368 		if (MatchDeleteOp(*thisop, aMoveDeletesOnly))
       
  1369 			{
       
  1370 			do
       
  1371 				{
       
  1372 				// if can't find the entry then just skip it so it is
       
  1373 				// removed from array
       
  1374 				if (iServerEntry.SetEntry(thisop->MessageId()) == KErrNone)
       
  1375 					{
       
  1376 					// set its server deleted flag
       
  1377 					TMsvEmailEntry entry=iServerEntry.Entry();
       
  1378 					entry.SetDeletedIMAP4Flag(ETrue);
       
  1379 					ChangeEntryL(entry);
       
  1380 					}
       
  1381 
       
  1382 				// remove from the array and write back immediately
       
  1383 				iOutstandingOps->Delete(0);
       
  1384 				iImapOfflineControl.SetOffLineOpArrayL(iOutstandingOpsFolder, *iOutstandingOps);
       
  1385 
       
  1386 				// check for finish
       
  1387 				if (iOutstandingOps->CountOperations() == 0)
       
  1388 					break;
       
  1389 			
       
  1390 				// get next op
       
  1391 				thisop->CopyL(iOutstandingOps->Operation(0));
       
  1392 				}
       
  1393 			while (MatchDeleteOp(*thisop, aMoveDeletesOnly));
       
  1394 					
       
  1395 			hadDeletes = ETrue;
       
  1396 			}
       
  1397 			
       
  1398 		CleanupStack::PopAndDestroy(thisop);
       
  1399 		}
       
  1400 
       
  1401 	return hadDeletes;
       
  1402 	}
       
  1403 
       
  1404 TBool CImapCompoundSyncService::ProcessPendingDeleteOpsListL( TBool aMoveDeletesOnly )
       
  1405 	{
       
  1406 	if(iNextFolderSync > 0)
       
  1407 		{
       
  1408 		if (ProcessPendingDeleteOpsL( iNextFolderSync, aMoveDeletesOnly ))
       
  1409 			{
       
  1410 			return ETrue;
       
  1411 			}				
       
  1412 		}
       
  1413 
       
  1414 	return EFalse;
       
  1415 	}
       
  1416 
       
  1417 /**
       
  1418 Sets the context's index entry to the specified values on the Message server
       
  1419 
       
  1420 @param  aEntry
       
  1421 The new details for the entry.
       
  1422 @leave KErrAccessDenied - the entry is read only (deleted entry, standard folder, or locked); 
       
  1423 KErrNotSupported - aEntry is invalid or the ID specified in aEntry is not the same as the context ID
       
  1424 or no context has been set for the object; 
       
  1425 KErrNoMemory - a memory allocation failed. 
       
  1426 */
       
  1427 void CImapCompoundSyncService::ChangeEntryL(const TMsvEntry& aEntry)
       
  1428 	{
       
  1429 	User::LeaveIfError(iServerEntry.ChangeEntry(aEntry));
       
  1430 	}
       
  1431 
       
  1432 /**
       
  1433 Called when operation has completed and we are about to complete the caller.
       
  1434 
       
  1435 @param aErr Error code that we will complete with.
       
  1436 */
       
  1437 void CImapCompoundSyncService::DoComplete(TInt& aErr)
       
  1438 	{
       
  1439 	CImapCompoundBase::DoComplete(aErr);
       
  1440 
       
  1441 	if (!iCancelForMigrate)
       
  1442 		{
       
  1443 		// Reset the flags which show if the new flags should be cleared on the
       
  1444 		// next sync.
       
  1445 		iSyncManager.ResetInboxClearNewFlags();
       
  1446 		iSyncManager.ResetNonInboxClearNewFlags();
       
  1447 		}
       
  1448 	}
       
  1449 
       
  1450 
       
  1451 /**
       
  1452 Resumes the operation following a migration.
       
  1453 */
       
  1454 void CImapCompoundSyncService::ResumeOperationL(TRequestStatus& aStatus, CImapSession& aSession)
       
  1455 	{
       
  1456 	iSession = &aSession;
       
  1457 	__LOG_TEXT(iSession->LogId(), "CImapCompoundSyncService::Resuming");
       
  1458 	__ASSERT_DEBUG(iCurrentStep==ESuspendedForMigrate, TImapServerPanic::ImapPanic(TImapServerPanic::ESyncServiceCompoundUnexpectedState));
       
  1459 	iStopForMigrate = EFalse;
       
  1460 	
       
  1461 	switch (iNextStep)
       
  1462 		{
       
  1463 		case EInboxEarlyExpunge:
       
  1464 		case EInboxEarlyDeletes:
       
  1465 			{
       
  1466 			// re-select the inbox, and then re-enter state machine
       
  1467 			iSyncManager.Inbox()->SelectL(iStatus, *iSession);
       
  1468 			SetActive();
       
  1469 			iCurrentStep = ESelectSourceMailboxRW;
       
  1470 			break;
       
  1471 			}
       
  1472 		case EFolderEarlyDeletes:
       
  1473 		case EFolderEarlyExpunge:
       
  1474 			{
       
  1475 			// re-select the inbox, and then re-enter state machine
       
  1476 			iSyncManager.GetFolderL(iNextFolderSync)->SelectL(iStatus, *iSession);
       
  1477 			iCurrentStep = ESelectSourceMailboxRW;
       
  1478 			break;
       
  1479 			}
       
  1480 		case EInboxLateDeletes:
       
  1481 		case EFolderLateDeletes:
       
  1482 		case EInboxLateExpunge:
       
  1483 		case EFolderLateExpunge:
       
  1484 			{
       
  1485 			// resume not expected since these states are only entered during
       
  1486 			// a disconnection operation. Migrations are not accepted during
       
  1487 			// diconnection - a downgrade results in the operation being
       
  1488 			// cancelled and any sessions deleted.
       
  1489 			iNextStep=EFinished;
       
  1490 			CompleteSelf();
       
  1491 			break;
       
  1492 			}
       
  1493 		case EInboxSync:  			// select is called by the sync manager in this state
       
  1494 		case ESyncSubscriptions:	// select not required
       
  1495 		case ESyncTree:				// select not required
       
  1496 		case ESyncFolder:			// select is called by the sync manager in this state
       
  1497 		case ESelectSyncFolder:		// self-completed state, however can suspend in this state
       
  1498 		case ESyncInboxAutoFetch:   // select not required prior to resuming 2nd phase
       
  1499 		case ESyncFolderAutoFetchCheck:// select not required prior to resuming 2nd phase
       
  1500 			{
       
  1501 			// resume the state machine in this state.
       
  1502 			CompleteSelf();
       
  1503 			break;
       
  1504 			}		
       
  1505 		case EInboxDoneOps:
       
  1506 			{
       
  1507 			if (iImapCompound)
       
  1508 				{
       
  1509 				// restart the compound object performing the offline-requested operation.
       
  1510 				iCurrentStep = EInboxCheckPendingOps;
       
  1511 				iImapCompound->ResumeOperationL(iStatus, *iSession);
       
  1512 				SetActive();
       
  1513 				}
       
  1514 			else
       
  1515 				{
       
  1516 				// Resume with check for further pending inbox operations
       
  1517 				iNextStep = EInboxCheckPendingOps;
       
  1518 				CompleteSelf();
       
  1519 				}
       
  1520 			break;
       
  1521 			}
       
  1522 		case EFolderDoneOps:
       
  1523 			{
       
  1524 			if (iImapCompound)
       
  1525 				{
       
  1526 				// resume the compound object performing the offline-requested operation.
       
  1527 				iCurrentStep = EFolderCheckPendingOPs;
       
  1528 				iImapCompound->ResumeOperationL(iStatus, *iSession);
       
  1529 				SetActive();
       
  1530 				}
       
  1531 			else
       
  1532 				{
       
  1533 				// Resume with check for further pending folder operations
       
  1534 				iNextStep = EFolderCheckPendingOPs;
       
  1535 				CompleteSelf();
       
  1536 				}
       
  1537 			break;
       
  1538 			}
       
  1539 		case ESyncFolderAutoFetch:
       
  1540 		case EFolderCheckPendingOPs: // not expected...
       
  1541 		case EInboxCheckPendingOps:  // not expected...
       
  1542 		case ESyncService:           // self-completed state
       
  1543 		case EFinished:
       
  1544 		default:
       
  1545 			{
       
  1546 			__ASSERT_DEBUG(EFalse, TImapServerPanic::ImapPanic(TImapServerPanic::ESyncServiceCompoundCancelUnexpectedState));
       
  1547 			// something unexpected has happened. Complete the operation.
       
  1548 			iNextStep = EFinished;
       
  1549 			break;
       
  1550 			}
       
  1551 		} // end of switch (iNextStep)
       
  1552 	Queue(aStatus);
       
  1553 	}
       
  1554 
       
  1555 /**
       
  1556 Provides the sync class with an array of messages that are not to be fetched according
       
  1557 to the download rules. This function is called by the background sync controller if a
       
  1558 fetch command is received by the server MTM is performing a background synchronise, and
       
  1559 allows the sync operation to prevent attempts to simultaneously fetch the same message
       
  1560 via multiple imap sessions.
       
  1561 
       
  1562 If message content fetch is already underway, then the array is passed to the 
       
  1563 CImapCompoundCopyToLocal object for immediate checking. The array is then stored
       
  1564 within this class and each subsequent copy to local operation is checked for matching
       
  1565 message id's.
       
  1566 
       
  1567 Note that it is possible for a message ID to be remove from the passed entry selection
       
  1568 in the case that that message is currently being fetched at the time of calling this
       
  1569 function.
       
  1570 
       
  1571 @param aSelection - the selection of messages that should not be autofetched
       
  1572 */
       
  1573 void CImapCompoundSyncService::RemoveFromSelectionL(CMsvEntrySelection& aDeleteSel)
       
  1574 	{
       
  1575 	if (iCurrentStep == ESyncFolderAutoFetch ||
       
  1576 	    iCurrentStep == ESyncInboxAutoFetch  ||
       
  1577 	    iCurrentStep == ESyncFolderAutoFetchCheck)
       
  1578 		{
       
  1579 		((CImapCompoundCopyToLocal*)iImapCompound)->RemoveFromSelection(aDeleteSel);
       
  1580 		}
       
  1581 
       
  1582 	// keep a copy of this selection to prevent future fetch clashes.
       
  1583 	delete iDoNotFetchSel;
       
  1584 	iDoNotFetchSel = aDeleteSel.CopyL();
       
  1585 	}
       
  1586 
       
  1587 /**
       
  1588 Indicates that the compound operation should complete as soon as it is possible
       
  1589 for the operation to be re-started without requiring a significant amount of
       
  1590 repeated communication.
       
  1591 The operation will be restarted by a call to ResumeOperationL()
       
  1592 Overrides the base-class implementation.
       
  1593 */
       
  1594 void CImapCompoundSyncService::StopForMigrate()
       
  1595 	{
       
  1596 	__LOG_TEXT(iSession->LogId(), "CImapCompoundSyncService::StopForMigrate()");
       
  1597 	
       
  1598 	if (iCurrentStep==ESyncFolderAutoFetch || iCurrentStep==ESyncInboxAutoFetch)
       
  1599 		{
       
  1600 		// if doing a download-rules based fetch, instruct it to stop.
       
  1601 		if(iImapCompound)
       
  1602 			{
       
  1603 			iImapCompound->StopForMigrate();
       
  1604 			}
       
  1605 		}
       
  1606 	iStopForMigrate = ETrue;
       
  1607 	}
       
  1608