email/pop3andsmtpmtm/popservermtm/src/POPSRFSH.CPP
changeset 31 ebfee66fde93
child 47 5b14749788d7
equal deleted inserted replaced
30:6a20128ce557 31:ebfee66fde93
       
     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 <e32std.h>
       
    17 #include "POPSMBX.H"
       
    18 #include "POPS.H"
       
    19 #include "POPSOP.H" //CImPop3Operations
       
    20 // includes for IMCV stuff
       
    21 #include <txtetext.h>
       
    22 #include <txtrich.h>
       
    23 #include <miuthdr.h>
       
    24 #include <imcvrecv.h>
       
    25 #include <msvapi.h>
       
    26 
       
    27 #include <s32mem.h>
       
    28 #include <s32file.h>
       
    29 
       
    30 #include "POPS.PAN" // imrc's own panic codes
       
    31 // Oyster includes
       
    32 #include <msvstd.h>
       
    33 #include <msventry.h>	// CMsvServerEntry
       
    34 #include <msvstore.h>
       
    35 #include <mmsvattachmentmanager.h>
       
    36 #include <mmsvattachmentmanagersync.h>
       
    37 
       
    38 #include <miutset.h>
       
    39 #include <imcvutil.h>
       
    40 
       
    41 #include <popsmtm.h>
       
    42 #include "POPSRFSH.h"
       
    43 #include "POPS.H"
       
    44 #include "POPSOP.H" //CImPop3Operations
       
    45 #include "POPSMBX.H"
       
    46 
       
    47 _LIT(KUidlFile,"UIDLS");
       
    48 
       
    49 const TInt KMaxStringLength = 1024;	
       
    50 
       
    51 
       
    52 
       
    53 //
       
    54 // My own panic command 
       
    55 //
       
    56 GLREF_C void Panic(TPopsPanic aPanic);
       
    57 
       
    58 CImPop3RefreshMailBox::CImPop3RefreshMailBox(CImPop3Session& aPopSession): CMsgActive( KMsgPop3RefreshMailboxPriority ), iPopSession( aPopSession)
       
    59 	{
       
    60 	__DECLARE_NAME(_S("CImPop3RefreshMailBox"));
       
    61 	}
       
    62 
       
    63 CImPop3RefreshMailBox* CImPop3RefreshMailBox::NewL(CMsvServerEntry& aRemoteServerEntry, CImPop3Session& aPopSession, RFs& anFs)
       
    64 	{
       
    65 	CImPop3RefreshMailBox* self = new (ELeave) CImPop3RefreshMailBox( aPopSession);
       
    66 	CleanupStack::PushL(self);	
       
    67 	self->ConstructL(aRemoteServerEntry, anFs);
       
    68 	CleanupStack::Pop();
       
    69 	return self;
       
    70 	}
       
    71 
       
    72 void CImPop3RefreshMailBox::ConstructL(CMsvServerEntry& aRemoteServerEntry, RFs& anFs)
       
    73 	{
       
    74 	iRefreshOperation = CImPop3RefreshOperation::NewL(aRemoteServerEntry, &iPopSession, anFs);	
       
    75 	_LIT8(KCrLfStr,".\r\n");
       
    76 	iFullStopTerminator = KCrLfStr();
       
    77 	iTextServer=iPopSession.TextServerSession();
       
    78 	CActiveScheduler::Add(this);	  // Add PopSession to scheduler's queue
       
    79 	}
       
    80 
       
    81 
       
    82 CImPop3RefreshMailBox::~CImPop3RefreshMailBox()
       
    83 	{
       
    84 	Cancel();
       
    85 	delete iRefreshOperation;
       
    86 	}
       
    87 
       
    88 void CImPop3RefreshMailBox::DoCancel()
       
    89 	{
       
    90 	switch(iState)
       
    91 		{
       
    92 		case EPop3RefreshBoxDefault:
       
    93 		case EPop3RefreshBoxTop:
       
    94 			{
       
    95 			if (iMigratingToNewBearer)
       
    96 			{
       
    97 			iRefreshOperation->CancelAllowResume();
       
    98 			}
       
    99 			else
       
   100 			{
       
   101 			iRefreshOperation->Cancel();
       
   102 			}
       
   103 			break;
       
   104 			}
       
   105 		case EPop3RefreshBoxPurgeInput:
       
   106 			{
       
   107 			iTextServer->Cancel();
       
   108 			break;
       
   109 			}
       
   110 		default:
       
   111 			{
       
   112 			__ASSERT_DEBUG(EFalse, Panic(EImppUnknownRefreshState));
       
   113 			}
       
   114 			break;
       
   115 		}
       
   116 	CMsgActive::DoCancel();
       
   117 	}
       
   118 
       
   119 
       
   120 void CImPop3RefreshMailBox::Start(TRequestStatus& aStatus, CArrayFixFlat<TMsvId>* aMsvIdArray)
       
   121 	{	
       
   122 	Queue(aStatus);
       
   123 	iMsvIdArray = aMsvIdArray;// Provided for transparency
       
   124 	
       
   125 	TRAPD(stateErr,ChangeStateL(EPop3RefreshBoxDefault));
       
   126 	if(stateErr!=KErrNone)
       
   127 		{
       
   128 		Complete(stateErr);
       
   129 		}
       
   130 	}
       
   131 
       
   132 void CImPop3RefreshMailBox::DoRunL()
       
   133 	{
       
   134 	if (iMigratingToNewBearer)
       
   135 		{
       
   136 		// The Pops MTM is currently migrating so no processing is required here
       
   137 		// This call to doRunl is probably as a result of CImPop3RefreshOperation::Pause()
       
   138 		// completing us.
       
   139 		return;
       
   140 		}
       
   141 	switch (iState)
       
   142 		{
       
   143 	case EPop3RefreshBoxDefault:
       
   144 		if (iStatus.Int() == KPop3RefreshUidlEquate) 
       
   145 			{
       
   146 			ChangeStateL(EPop3RefreshBoxPurgeInput);
       
   147 			}
       
   148 		break;
       
   149 	case  EPop3RefreshBoxPurgeInput:
       
   150 		iTextServer->GetCurrentTextLine(iTextServerResponse);
       
   151 		if(iTextServerResponse.Compare(iFullStopTerminator)!=0)	
       
   152 			{
       
   153 			iTextServer->QueueReceiveNextTextLine(iStatus);
       
   154 			SetActive();
       
   155 			} 
       
   156 		else 
       
   157 			{
       
   158 			ChangeStateL(EPop3RefreshBoxTop);
       
   159 			}
       
   160 		break;
       
   161 	case EPop3RefreshBoxTop:
       
   162 			break;
       
   163 	default:
       
   164 			break;
       
   165 		};		
       
   166 	}
       
   167 
       
   168 void CImPop3RefreshMailBox::ChangeStateL(TState aState)
       
   169     {
       
   170 	switch (aState)
       
   171         {
       
   172 	case EPop3RefreshBoxDefault:
       
   173 			// Start refresh with UIDL
       
   174 			iRefreshOperation->Start(iStatus,iMsvIdArray);
       
   175 			break;
       
   176 	case EPop3RefreshBoxPurgeInput:
       
   177 			iPopSession.SetOpNotPending();
       
   178 			iTextServer->GetCurrentTextLine(iTextServerResponse);
       
   179 			if(iTextServerResponse.Compare(iFullStopTerminator)!=0) 
       
   180 			{
       
   181 				iTextServer->QueueReceiveNextTextLine(iStatus);
       
   182 				// Break here to make sure Async function is called before SetActive() is called, 
       
   183 				// else we'll get a Stray Signal
       
   184 				break;
       
   185 			}
       
   186 	case EPop3RefreshBoxTop:
       
   187 			iRefreshOperation->Cancel();
       
   188 			iRefreshOperation->Start(iStatus); // Restart refresh with Top
       
   189 			break;
       
   190 	default:
       
   191 			break;
       
   192 	}
       
   193 	iState = aState;
       
   194 	SetActive();
       
   195 	}
       
   196 
       
   197 TPop3Progress CImPop3RefreshMailBox::Progress()
       
   198 	{
       
   199 	 return iRefreshOperation->Progress();
       
   200 	}
       
   201 
       
   202 
       
   203 void CImPop3RefreshMailBox::SetMessagesToKeepL(const CMsvEntrySelection* aMessagesToKeep)
       
   204 	{
       
   205 	iRefreshOperation->SetMessagesToKeepL(aMessagesToKeep);
       
   206 	}
       
   207 
       
   208 
       
   209 TUint CImPop3RefreshMailBox::RemoteMessageSizeL(TMsvId aId)
       
   210 	{
       
   211 	return iRefreshOperation->RemoteMessageSizeL(aId);
       
   212 	}
       
   213 
       
   214 // ****************************************************************************************** 
       
   215 // This is called by the POP Client MTM when it starts Migrating Bearer
       
   216 // 
       
   217 // ******************************************************************************************	
       
   218 void CImPop3RefreshMailBox::Pause()
       
   219 	{
       
   220 	iMigratingToNewBearer = ETrue;
       
   221 	// Ask the Refresh Operation to prepare itself for Migration
       
   222 	switch(iState)
       
   223 		{
       
   224 		case EPop3RefreshBoxDefault:
       
   225 		case EPop3RefreshBoxTop:
       
   226 			{
       
   227 			iRefreshOperation->Pause();
       
   228 			break;
       
   229 			}
       
   230 		case EPop3RefreshBoxPurgeInput:
       
   231 			{
       
   232 			// Cancel the Text Server request, so we can complete to migrate.
       
   233 			iTextServer->Cancel();
       
   234 			break;
       
   235 			}
       
   236 		default:
       
   237 			{
       
   238 			__ASSERT_DEBUG(EFalse, Panic(EImppUnknownRefreshState));
       
   239 			}
       
   240 			break;
       
   241 			
       
   242 		}
       
   243 	
       
   244 	}
       
   245 
       
   246 // ****************************************************************************************** 
       
   247 // This is called by the POP Client MTM when it starts Migrating Bearer
       
   248 // 
       
   249 // ******************************************************************************************	
       
   250 void CImPop3RefreshMailBox::CancelAllowResume()
       
   251 	{
       
   252 	iMigratingToNewBearer = ETrue;
       
   253 	Cancel();
       
   254 	}
       
   255 
       
   256 // Called by the POP Client MTM, once it has completed Migrating to new bearer 
       
   257 void CImPop3RefreshMailBox::ResumeL(CImPop3Session* aPopSession, TRequestStatus& aStatus)
       
   258 	{
       
   259 	Queue(aStatus);
       
   260 	iMigratingToNewBearer = EFalse;
       
   261 
       
   262 	if (iState == EPop3RefreshBoxPurgeInput)
       
   263 		{
       
   264 		ChangeStateL(EPop3RefreshBoxTop);
       
   265 		}
       
   266 	else
       
   267 		{
       
   268 		// Inform the Refresh Operation of Migration Completion
       
   269 		iRefreshOperation->ResumeL(aPopSession, iStatus);
       
   270 		SetActive();
       
   271 		}
       
   272 	}
       
   273 
       
   274 //================================================================================
       
   275 
       
   276 CImPop3RefreshOperation::CImPop3RefreshOperation(CMsvServerEntry& aRemoteServerEntry, CImPop3Session* aPopSession, RFs& anFs)
       
   277 	: CMsgActive( KMsgPop3RefreshMailboxPriority ),	iUidlKey(_FOFF(TMsgUidlStore,iMsvId),ECmpTUint),
       
   278 		iRemoteServerEntry(aRemoteServerEntry),iPopSession(aPopSession),iFs(anFs)
       
   279 	{
       
   280 	__DECLARE_NAME(_S("CImPop3RefreshOperation"));
       
   281 	}
       
   282 
       
   283 
       
   284 CImPop3RefreshOperation* CImPop3RefreshOperation::NewL(CMsvServerEntry& aRemoteServerEntry, CImPop3Session* aPopSession, RFs& anFs)
       
   285 	{
       
   286 	CImPop3RefreshOperation* self = new (ELeave) CImPop3RefreshOperation( aRemoteServerEntry, aPopSession, anFs);
       
   287 	CleanupStack::PushL(self);
       
   288 	self->ConstructL();
       
   289 	CleanupStack::Pop();
       
   290 	return self;
       
   291 	}
       
   292 
       
   293 
       
   294 void CImPop3RefreshOperation::ConstructL()
       
   295 	{
       
   296 	// store id of remote collection
       
   297 	iRemoteId=iRemoteServerEntry.Entry().Id();
       
   298 	iRecvConverter=CImRecvConvert::NewL( iFs, &iRemoteServerEntry, KUidMsgTypePOP3, iRemoteId);
       
   299 	iRecvConverter->SetCaf(*iPopSession->GetCafL(iFs));
       
   300 	iPopTop=CImPop3Top::NewL(iPopSession,iRecvConverter);
       
   301 	iPopRetr=CImPop3Retr::NewL(iPopSession,iRecvConverter, iFs);
       
   302 	
       
   303 	iUidlArray = new(ELeave) CArrayFixSeg<TMsgUidlStore>(8);
       
   304 
       
   305 	iMsvSelection = new (ELeave) CMsvEntrySelection;
       
   306 	iUnwantedEntries = new (ELeave) CMsvEntrySelection;
       
   307 	// store id of remote collection
       
   308 	// set recv conv. 
       
   309 	iRecvConverter->SetMsvId(iRemoteId);
       
   310 
       
   311 	CActiveScheduler::Add(this);	  // Add CImPop3RefreshOperation to scheduler's queue
       
   312 
       
   313 	iCurrentDrive = MessageServer::CurrentDriveL(iFs);
       
   314 	}
       
   315 
       
   316 
       
   317 CImPop3RefreshOperation::~CImPop3RefreshOperation()
       
   318 	{
       
   319 	Cancel();
       
   320 	delete  iMsvSelection;
       
   321 	
       
   322 	// delete everything here
       
   323 	delete iPopStat;
       
   324 	delete iPopList;
       
   325 	delete iPopUidl;
       
   326   	delete iPopTop;
       
   327 	delete iPopRetr;
       
   328 	iUniqueUidlPosArray.Close();
       
   329 	iTemporaryUidlPosArray.Close();
       
   330 	if (iUidlArray)
       
   331 		{
       
   332 		for (TInt ii=iUidlArray->Count();--ii>=0;)
       
   333 			DeleteUidl(ii);
       
   334 		delete iUidlArray;
       
   335 		}
       
   336 	delete iPop3Uidls;
       
   337 	delete [] iSize;
       
   338 
       
   339 	delete iRecvConverter;
       
   340 	delete iUnwantedEntries;
       
   341 	delete iMessagesToKeep;
       
   342 	}
       
   343 
       
   344 //
       
   345 // Cancel any current operation
       
   346 //
       
   347 void CImPop3RefreshOperation::DoCancel()
       
   348 	{
       
   349 	iPopSession->SetOpNotPending();
       
   350 
       
   351 	switch(iState)
       
   352 		{
       
   353 		case EPopRefreshStat:
       
   354 			if(iPopStat)
       
   355 				{
       
   356 				iPopStat->Cancel();
       
   357 				}
       
   358 			break;
       
   359 		case EPopRefreshList:
       
   360 			if(iPopList)
       
   361 				{
       
   362 				iPopList->Cancel();
       
   363 				}
       
   364 			break;
       
   365 		case EPopRefreshUidl:
       
   366 			if(iPopUidl)
       
   367 				{
       
   368 				iPopUidl->Cancel();
       
   369 				}
       
   370 			break;
       
   371 		case EPopRefreshGetHeader:
       
   372 			if(iPopTop)
       
   373 				{
       
   374 				iPopTop->Cancel();
       
   375 				}
       
   376 			if(iPopRetr)
       
   377 				{
       
   378 				iPopRetr->Cancel();
       
   379 				}
       
   380 			break;
       
   381 		default:	// do nothing for all other states
       
   382 				break;
       
   383 		}
       
   384 	CMsgActive::DoCancel();
       
   385 	}
       
   386 
       
   387 //
       
   388 // what to do on completion
       
   389 //
       
   390 void CImPop3RefreshOperation::DoComplete(TInt& aCompleteStatus)
       
   391 	{
       
   392 	// if we had empty headers report back to user with error code
       
   393 	switch (iState)
       
   394 		{
       
   395 	case EPopRefreshComplete:
       
   396 		break;
       
   397 	case EPopRefreshGetHeader:
       
   398 		if (aCompleteStatus!=KErrNone)
       
   399 			{// If there is no memory to download further, complete
       
   400 			 // the operation without calling MessageCompleteL.
       
   401 			 if(aCompleteStatus == KErrNoMemory)
       
   402 				{
       
   403 				break;
       
   404 				}
       
   405 			// try and remember what we've done, at least
       
   406 			TRAPD(ignore,iRecvConverter->MessageCompleteL());
       
   407 			TRAP(ignore,RefreshFinishedL());
       
   408 			}
       
   409 		break;
       
   410 	default:
       
   411 		break;
       
   412 		}
       
   413 	}
       
   414 
       
   415 //
       
   416 // Start me up
       
   417 //
       
   418 void CImPop3RefreshOperation::Start(TRequestStatus& aStatus, CArrayFixFlat<TMsvId>* aMsgIdArray)
       
   419 	{	
       
   420 	Queue(aStatus);
       
   421 	iCheckDiskSpaceCounter = 0;
       
   422 	iNewMsg=aMsgIdArray; // take ownership of the message id array
       
   423 	TRAPD(stateErr,ChangeStateL(EPopRefreshSyncCollection));
       
   424 	if(stateErr!=KErrNone)
       
   425 		{
       
   426 		Complete(stateErr);
       
   427 		}
       
   428 	}
       
   429 
       
   430 //
       
   431 // Start me up and skip UIDL downloading
       
   432 // (BFSW1-2016)
       
   433 void CImPop3RefreshOperation::Start(TRequestStatus& aStatus)
       
   434 	{
       
   435 	Queue(aStatus);
       
   436 
       
   437 	__ASSERT_ALWAYS(iNewMsg,Panic(ETopStartBeforeUidlStart));
       
   438 
       
   439 	iCheckDiskSpaceCounter = 0;
       
   440 	if (iUidlArray) 
       
   441 		{ // Delete unreliable UIDL list (BFSW1-2016)
       
   442 		for (TInt ii=iUidlArray->Count();--ii>=0;)
       
   443 			DeleteUidl(ii);
       
   444 		}
       
   445 	
       
   446 
       
   447 	TRAPD(stateErr,ChangeStateL(EPopRefreshGetHeader));
       
   448 	if(stateErr!=KErrNone)
       
   449 		{
       
   450 		Complete(stateErr);	
       
   451 		}
       
   452 	}
       
   453 
       
   454 // ****************************************************************************************** 
       
   455 // Resume function called by the POP Client MTM, once it has completed Migrating to new bearer
       
   456 // 
       
   457 // ******************************************************************************************	
       
   458 void CImPop3RefreshOperation::ResumeL(CImPop3Session* aPopSession, TRequestStatus& aStatus)
       
   459 	{
       
   460 	iMigratingToNewBearer = EFalse;
       
   461 	iPopSession = aPopSession;
       
   462 
       
   463 	delete iRecvConverter;
       
   464 	iRecvConverter = NULL;
       
   465 	iRecvConverter=CImRecvConvert::NewL( iFs, &iRemoteServerEntry, KUidMsgTypePOP3, iRemoteId);
       
   466 	iRecvConverter->SetCaf(*iPopSession->GetCafL(iFs));
       
   467 
       
   468 	delete iPopTop;
       
   469 	iPopTop = NULL;
       
   470 	iPopTop=CImPop3Top::NewL(iPopSession,iRecvConverter);
       
   471 	delete iPopRetr;
       
   472 	iPopRetr = NULL;
       
   473 	iPopRetr=CImPop3Retr::NewL(iPopSession,iRecvConverter, iFs);
       
   474 
       
   475 	iRecvConverter->SetMsvId(iRemoteId);
       
   476 	
       
   477 	Queue(aStatus);
       
   478 	iCheckDiskSpaceCounter = 0;
       
   479 	TRAPD(stateErr,ChangeStateL(iState));
       
   480 	if(stateErr!=KErrNone)
       
   481 		{
       
   482 		Complete(stateErr);
       
   483 		}
       
   484 	}	
       
   485 
       
   486 //
       
   487 // Result of last active call
       
   488 //
       
   489 void CImPop3RefreshOperation::DoRunL()
       
   490     {
       
   491         
       
   492 	switch(iState)
       
   493 	{
       
   494 	case EPopRefreshSyncCollection:
       
   495 		if(iRemoteArrayCtr>0)
       
   496 			{
       
   497 			SyncCollectionL();
       
   498 			QueueRemoteUpdate();
       
   499 			}
       
   500 		else
       
   501 			{
       
   502 			CompleteSyncCollection();
       
   503 			if (iMigratingToNewBearer)
       
   504 				{
       
   505 				ChangeStateForMigrate(EPopRefreshStat);
       
   506 				return;
       
   507 				}
       
   508 			else
       
   509 				{
       
   510 				ChangeStateL(EPopRefreshStat);
       
   511 				}
       
   512 			}
       
   513 		break;
       
   514 
       
   515 	case EPopRefreshStat:
       
   516 		// initialise progress object
       
   517 
       
   518 		iProgress.iMsgsToProcess=iNoMessages;
       
   519 	
       
   520 		iProgress.iTotalMsgs=iNoMessages;
       
   521 
       
   522 		User::LeaveIfError(iRemoteServerEntry.SetEntry(iRemoteId));
       
   523 		iEntry = iRemoteServerEntry.Entry();
       
   524 		iEntry.SetMtmData3(iNoMessages);
       
   525 		User::LeaveIfError(iRemoteServerEntry.ChangeEntry(iEntry));
       
   526 
       
   527 		delete iPopStat;
       
   528 		iPopStat=NULL;
       
   529 		if(iNoMessages)
       
   530 			{
       
   531 			if (iMigratingToNewBearer)
       
   532 				{
       
   533 				ChangeStateForMigrate(EPopRefreshList);
       
   534 				return;
       
   535 				}
       
   536 			ChangeStateL(EPopRefreshList);
       
   537 			}
       
   538 		else
       
   539 			{
       
   540 			if (iMigratingToNewBearer)
       
   541 				{
       
   542 				ChangeStateForMigrate(EPopRefreshDeleteDeadMessages);
       
   543 				return;
       
   544 				}
       
   545 			ChangeStateL(EPopRefreshDeleteDeadMessages);
       
   546 			}
       
   547 		break;
       
   548 
       
   549 	case EPopRefreshList:
       
   550 		delete iPopList;
       
   551 		iPopList=NULL;
       
   552 		if (iMigratingToNewBearer)
       
   553 			{
       
   554 			ChangeStateForMigrate(EPopRefreshUidl);
       
   555 			return;
       
   556 			}
       
   557 		ChangeStateL(EPopRefreshUidl);
       
   558 		break;
       
   559 
       
   560 	case EPopRefreshUidl:
       
   561 		__ASSERT_ALWAYS(iPopUidl, Panic(EPopNullPointer));
       
   562 			
       
   563 		iUidlExists=iPopUidl->PopCommandAccepted();
       
   564 		delete iPopUidl;
       
   565 		iPopUidl=NULL;
       
   566 		if (iUidlExists)
       
   567 			{
       
   568 			if (iMigratingToNewBearer)
       
   569 				{
       
   570 				ChangeStateForMigrate(EPopRefreshSyncUidl);
       
   571 				return;
       
   572 				}
       
   573 			ChangeStateL(EPopRefreshSyncUidl);
       
   574 			}
       
   575 		else
       
   576 			{
       
   577 			// delete any entries with a zero length inet msg id
       
   578 			//scan UIDL file for msgs with no POP id. If found, delete from UIDL file and Messaging Server
       
   579 			//??? why would they have a zero length POP id ?
       
   580 			User::LeaveIfError(iRemoteServerEntry.SetEntry(iRemoteId));
       
   581 			CArrayFix<TMsgUidlStore>& uidlarray=*iUidlArray;
       
   582 			TInt row = uidlarray.Count();
       
   583 			while(--row>=0)
       
   584 				{
       
   585 				if(uidlarray[row].iPopId->Length()==0)
       
   586 					{
       
   587 #ifdef _DEBUG
       
   588 					TInt error = 
       
   589 #endif						
       
   590 					iRemoteServerEntry.DeleteEntry( uidlarray[row].iMsvId);
       
   591 					__ASSERT_DEBUG( error == KErrNone, Panic(EPopFailedDebugAssert));
       
   592 					DeleteUidl(row);
       
   593 					}
       
   594 				}
       
   595 			if (iMigratingToNewBearer)
       
   596 				{
       
   597 				ChangeStateForMigrate(EPopRefreshGetHeader);
       
   598 				return;
       
   599 				}	
       
   600 			ChangeStateL(EPopRefreshGetHeader);
       
   601 			}
       
   602 		break;
       
   603 
       
   604 	case EPopRefreshSyncUidl:		
       
   605 		if(iRemoteArrayCtr>0)
       
   606 			{
       
   607 			SyncUidlL();
       
   608 			QueueRemoteUpdate();
       
   609 			}
       
   610 		else
       
   611 			{	
       
   612 			if (iMigratingToNewBearer)
       
   613 				{
       
   614 				ChangeStateForMigrate(EPopRefreshGetHeader);
       
   615 				return;
       
   616 				}
       
   617 			ChangeStateL(EPopRefreshGetHeader);
       
   618 			}
       
   619 		break;
       
   620 	
       
   621 	case EPopRefreshGetHeader:
       
   622 		//At this point iMsgCtr contains the index of the hdr to download
       
   623 	
       
   624 		if(iFirstCallToTop)
       
   625 			{
       
   626 			__ASSERT_ALWAYS(iPopTop, Panic(EPopNullPointer));
       
   627 			iTopExists=iPopTop->PopCommandAccepted();
       
   628 			}
       
   629 
       
   630 		if ( !iFirstCallToTop || iTopExists )
       
   631 			{
       
   632 			//This is not the 1st call to TOP, or the TOP command exists
       
   633 
       
   634 			// Don't create a message if the header has none of the following RFC 822 fields:
       
   635 			//  To:, Cc:, Bcc:, From:, ReturnPath 
       
   636 			// I assume that if it is missing ALL of these fields then the Email message MUST be broken!
       
   637 						
       
   638 			if(iUidlExists || CompareIdAndSizeL())
       
   639 				{
       
   640 				// create new TMsvEntry here in folder CMsvEntry
       
   641 				TMsvEntry msvEntry = iRecvConverter->MessageEntryDetailsL();
       
   642 				TRAP_IGNORE(CreateNewHeaderEntryL( msvEntry ));
       
   643 	
       
   644 				iIdTab[iMsgCtr]=msvEntry.Id();
       
   645 				__ASSERT_ALWAYS(iNewMsg, Panic(EPopNullPointer));
       
   646 				iNewMsg->AppendL(msvEntry.Id());	// cannot fail, as we have SetReserveL()'d
       
   647 				
       
   648 				if (iTopExists)
       
   649 					{
       
   650 					iRecvConverter->MessageCompleteL(msvEntry);
       
   651 					}
       
   652 				}
       
   653 			else
       
   654 				{
       
   655 				TMsvEntry msvEntry = iRecvConverter->MessageEntryDetailsL();
       
   656 				iRecvConverter->MessageCompleteL(msvEntry);
       
   657 				}
       
   658 			iProgress.iMsgsToProcess--;
       
   659 
       
   660 			iMsgCtr--;
       
   661 			}
       
   662 
       
   663 		iFirstCallToTop=EFalse;
       
   664 
       
   665 		if (GetMessagesIfAny())
       
   666 			{
       
   667 			RetrieveHeadersL();
       
   668 			}
       
   669 		else
       
   670 			{
       
   671 			if (iMigratingToNewBearer)
       
   672 				{
       
   673 				ChangeStateForMigrate(EPopRefreshDeleteExcessMessages);
       
   674 				return;
       
   675 				}
       
   676 			ChangeStateL(EPopRefreshDeleteExcessMessages);
       
   677 			if(iUidlExists==EFalse)
       
   678 				{
       
   679 				//We need to remove TOPed or RETRed msgs that were already downloaded
       
   680 				User::LeaveIfError(iRemoteServerEntry.SetEntry(iRemoteId));
       
   681 				for( TInt loop = iUnwantedEntries->Count(); --loop>=0;)
       
   682 					{
       
   683 #if defined(_DEBUG)
       
   684 					TInt err = iRemoteServerEntry.DeleteEntry((*iUnwantedEntries)[loop]); 
       
   685 					__ASSERT_DEBUG(err == KErrNone, Panic(EPopFailedDebugAssert));
       
   686 #else
       
   687 					iRemoteServerEntry.DeleteEntry((*iUnwantedEntries)[loop]); 
       
   688 #endif
       
   689 					}
       
   690 				}
       
   691 			}
       
   692 		break;
       
   693 
       
   694 	case EPopRefreshDeleteExcessMessages:
       
   695 	
       
   696 		if (!iUidlExists)
       
   697 			{
       
   698 			// Fix to stop the deletion of existing headers when POP MTM should connect but not synch 
       
   699 
       
   700 			if (iPopSession->MaxHeaders()==0)
       
   701 				{
       
   702 				if (iMigratingToNewBearer)
       
   703 					{
       
   704 					ChangeStateForMigrate(EPopRefreshDeleteDeadMessages);
       
   705 					return;
       
   706 					}
       
   707 				ChangeStateL(EPopRefreshDeleteDeadMessages);
       
   708 				break;
       
   709 				}  
       
   710 			else
       
   711 				{
       
   712 				while (--iRemoteArrayCtr>=0)
       
   713 					{
       
   714 					if (iRemoteArrayCtr<TInt(iNoMessages-iPopSession->MaxHeaders()))
       
   715 						{
       
   716 						iRemoteServerEntry.SetEntry(iIdTab[iRemoteArrayCtr]);
       
   717 						const TMsvEmailEntry& entry=iRemoteServerEntry.Entry();
       
   718 						// Check if the message entry is marked for offline delete operation.
       
   719 						TBool notMarkedForOfflineDelete = EFalse;
       
   720 						TImDisconnectedOperationType  opType;
       
   721 						if((opType = entry.DisconnectedOperation())!= EDisconnectedDeleteOperation)
       
   722 							{
       
   723 							notMarkedForOfflineDelete = ETrue;
       
   724 							}
       
   725 						if (CanDeleteEntry(entry))
       
   726 							{
       
   727 							//  Don't handle the error
       
   728 							User::LeaveIfError(iRemoteServerEntry.SetEntry(iRemoteId));
       
   729 							// The message entry is not marked for offline delete, so delete the entry from
       
   730 							// message INDEX(mail2) file.
       
   731 							if(notMarkedForOfflineDelete)
       
   732 								{
       
   733 								User::LeaveIfError(iRemoteServerEntry.DeleteEntry(iIdTab[iRemoteArrayCtr]));								
       
   734 								}
       
   735 							DeleteUidl(iRemoteArrayCtr);
       
   736 							QueueRemoteUpdate();
       
   737 							break;
       
   738 							}
       
   739 						}
       
   740 					}
       
   741 				}
       
   742 
       
   743 			}
       
   744 		else
       
   745 			// Fix to stop the deletion of existing headers when POP MTM should connect but not synch 
       
   746 
       
   747 			if (iPopSession->MaxHeaders()==0)
       
   748 				{
       
   749 				if (iMigratingToNewBearer)
       
   750 					{
       
   751 					ChangeStateForMigrate(EPopRefreshDeleteDeadMessages);
       
   752 					return;
       
   753 					}
       
   754 				ChangeStateL(EPopRefreshDeleteDeadMessages);
       
   755 				break;
       
   756 				}  
       
   757 			else 
       
   758 				while (--iRemoteArrayCtr>=0)
       
   759 					{
       
   760 					const TMsgUidlStore& uidl=iUidlArray->At(iRemoteArrayCtr);
       
   761 					if (iPop3Uidls->MsgNo(*uidl.iPopId) < TInt(iNoMessages-iPopSession->MaxHeaders()))
       
   762 						{
       
   763 						iRemoteServerEntry.SetEntry(uidl.iMsvId);
       
   764 						const TMsvEmailEntry& entry=iRemoteServerEntry.Entry();
       
   765 						// Check if the message entry is marked for offline delete operation.
       
   766 						TBool notMarkedForOfflineDelete = EFalse;
       
   767 						TImDisconnectedOperationType  opType;
       
   768 						if((opType = entry.DisconnectedOperation())!= EDisconnectedDeleteOperation)
       
   769 							{
       
   770 							notMarkedForOfflineDelete = ETrue;
       
   771 							}
       
   772 						if (CanDeleteEntry(entry))
       
   773 							{
       
   774 							//  Don't handle the error
       
   775 							User::LeaveIfError(iRemoteServerEntry.SetEntry(iRemoteId));
       
   776 							// The message entry is not marked for offline delete, so delete the entry from
       
   777 							// message INDEX(mail2) file.
       
   778 							if(notMarkedForOfflineDelete)
       
   779 								{
       
   780 								User::LeaveIfError(iRemoteServerEntry.DeleteEntry(uidl.iMsvId));	
       
   781 								}
       
   782 							DeleteUidl(iRemoteArrayCtr);
       
   783 							QueueRemoteUpdate();
       
   784 							break;
       
   785 							}
       
   786 						}
       
   787 					}
       
   788 			
       
   789 			if (iRemoteArrayCtr<0)
       
   790 				{
       
   791 				if (iMigratingToNewBearer)
       
   792 					{
       
   793 					ChangeStateForMigrate(EPopRefreshDeleteDeadMessages);
       
   794 					return;
       
   795 					}
       
   796 				ChangeStateL(EPopRefreshDeleteDeadMessages);
       
   797 				}
       
   798 			break;
       
   799 				
       
   800 	
       
   801 	case EPopRefreshDeleteDeadMessages:	// dispose of un-present messages
       
   802 		if (!iUidlExists)
       
   803 			{
       
   804 			//delete all messages from the Messaging Server whose MsvID does NOT appear in
       
   805 			//the iIdTab[] array.
       
   806 			User::LeaveIfError(iRemoteServerEntry.SetEntry(iRemoteId));
       
   807 			CMsvEntrySelection* pop3Entries = new (ELeave) CMsvEntrySelection;
       
   808 			CleanupStack::PushL(pop3Entries);
       
   809 			User::LeaveIfError(iRemoteServerEntry.GetChildren(*pop3Entries ));
       
   810 			
       
   811 			if (iNoMessages == 0)
       
   812 				{
       
   813 				// Clear the entries from the local POP3 Mailbox, and delete the UIDs
       
   814 				if (pop3Entries ->Count()!=0)
       
   815 					{
       
   816 					iRemoteServerEntry.DeleteEntries(*pop3Entries);
       
   817 					}
       
   818 				if (iUidlArray) 
       
   819 					{ // Delete UIDL list 
       
   820 					for (TInt ii=iUidlArray->Count();--ii>=0;)
       
   821 						DeleteUidl(ii);
       
   822 					}
       
   823 				}		
       
   824 			else
       
   825 				{
       
   826 				// Downloaded each header in turn to get the uid list.
       
   827 				// Delete any messages in remote folder that aren't in the iUidlArray.
       
   828 				// 
       
   829 				CMsvEntrySelection* deadEntries = new (ELeave) CMsvEntrySelection;
       
   830 				CleanupStack::PushL(deadEntries);
       
   831 				TInt msgCtr = pop3Entries->Count();
       
   832 				//nested loops! - not an ideal search method 
       
   833 				while (--msgCtr>=0)
       
   834 					{
       
   835 					TBool found = EFalse;
       
   836 					for (TUint index = 0; index < iNoMessages && !found; index++)
       
   837 						{
       
   838 						if ((*pop3Entries)[msgCtr] == iIdTab[index])
       
   839 							{
       
   840 							found = ETrue;
       
   841 							}
       
   842 						}
       
   843 					if (!found)
       
   844 						{
       
   845 						deadEntries->AppendL((*pop3Entries)[msgCtr]);
       
   846 						}
       
   847 					}
       
   848 				if (deadEntries->Count())
       
   849 					{
       
   850 					User::LeaveIfError(iRemoteServerEntry.DeleteEntries(*deadEntries));
       
   851 					}
       
   852 				CleanupStack::PopAndDestroy(deadEntries);
       
   853 				}
       
   854 			CleanupStack::PopAndDestroy(pop3Entries);
       
   855 			ChangeStateL(EPopRefreshComplete);
       
   856 			break;
       
   857 			}
       
   858 		else
       
   859 			{
       
   860 			while (--iRemoteArrayCtr>=0)
       
   861 				{
       
   862 				const TMsgUidlStore& uidl=iUidlArray->At(iRemoteArrayCtr);
       
   863 
       
   864 				if (uidl.iSelectionPos!=TMsgUidlStore::EPresent)
       
   865 					{
       
   866 					//  Don't handle the error
       
   867 					iRemoteServerEntry.DeleteEntry(uidl.iMsvId);
       
   868 					User::LeaveIfError(iRemoteServerEntry.DeleteEntry(uidl.iMsvId));
       
   869 					DeleteUidl(iRemoteArrayCtr);
       
   870 					QueueRemoteUpdate();
       
   871 					break;
       
   872 					}
       
   873 				}
       
   874 			}
       
   875 
       
   876 		if (iRemoteArrayCtr<0)
       
   877 			{
       
   878 			ChangeStateL(EPopRefreshComplete);
       
   879 			}
       
   880 		break;
       
   881 
       
   882 	default:     // Unknown state
       
   883 	Panic(EImppUnknownRefreshState);
       
   884 	break;
       
   885 	}
       
   886     }
       
   887 
       
   888 	//
       
   889 	// Finished refresh so tidy up
       
   890 	//
       
   891 	//
       
   892 	void CImPop3RefreshOperation::RefreshFinishedL()
       
   893 	{
       
   894 	iRemoteServerEntry.CompleteBulk();
       
   895 	CreateUidlFileL();
       
   896 	delete iPopTop;
       
   897 	iPopTop=NULL;
       
   898 	delete iPopRetr;
       
   899 	iPopRetr=NULL;
       
   900 	__ASSERT_ALWAYS(iNewMsg, Panic(EPopNullPointer));
       
   901 	iNewMsg->Reset();	// all new messages are sound
       
   902 	}
       
   903 
       
   904 	// retrieve headers(or whole messages) else complete
       
   905 	//
       
   906 	TBool CImPop3RefreshOperation::GetMessagesIfAny()
       
   907 	{
       
   908 	while (iMsgCtr>=iLastHeaderToGet && iIdTab[iMsgCtr]!=0)
       
   909 	iMsgCtr--;
       
   910 	if (iMsgCtr < 0 )
       
   911 	{
       
   912 	return EFalse;
       
   913 	}
       
   914 	return (iMsgCtr>=iLastHeaderToGet);
       
   915 	}
       
   916 
       
   917 void CImPop3RefreshOperation::ChangeStateForMigrate(TState aState)
       
   918 	{
       
   919 	iState = aState;
       
   920 	
       
   921 	delete iPopTop;
       
   922 	iPopTop=NULL;
       
   923 	delete iPopRetr;
       
   924 	iPopRetr=NULL;
       
   925 	}
       
   926 	
       
   927 void CImPop3RefreshOperation::ChangeStateL(TState aState)
       
   928 	{
       
   929 	//
       
   930 	// State machine of the whole POP mail session.
       
   931 	//
       
   932 	// Identify state on entry, change to next state and then
       
   933 	// start new operation associated with that new state.
       
   934 	//
       
   935 	switch (aState)
       
   936 	{
       
   937 	case EPopRefreshSyncCollection:
       
   938 		GetRemoteMessagesL();
       
   939 		QueueRemoteUpdate();	
       
   940 	break;
       
   941 
       
   942 	case EPopRefreshStat:
       
   943 		GetNoMessagesL();
       
   944 	break;
       
   945 
       
   946 	case EPopRefreshList:
       
   947 		AllocateArraysL();
       
   948 		GetMsgSizesL();
       
   949 	break;
       
   950 
       
   951 	case EPopRefreshUidl:
       
   952 		GetMsgUidlsL();
       
   953 	break;
       
   954 
       
   955 	case EPopRefreshSyncUidl:
       
   956 		iUniqueUidlPosArray.Reset();
       
   957 		iTemporaryUidlPosArray.Reset();
       
   958 		iPreviousIndex = KErrGeneral;		
       
   959 		iRemoteArrayCtr=iUidlArray->Count();
       
   960 		QueueRemoteUpdate();	
       
   961 	break;
       
   962 
       
   963 	case EPopRefreshGetHeader:
       
   964 		// start retrieving headers
       
   965 
       
   966 		iFirstCallToTop=ETrue;
       
   967 		iTopExists=ETrue;
       
   968 
       
   969 		iMsgCtr=iNoMessages-1;
       
   970 		if (!iUidlExists)
       
   971 			{
       
   972 			iLastHeaderToGet =0;
       
   973 			}
       
   974 		else
       
   975 			{
       
   976 			iLastHeaderToGet=iPopSession->MaxHeaders();
       
   977 			if (iLastHeaderToGet >= 0)
       
   978 				iLastHeaderToGet=iNoMessages-iLastHeaderToGet;
       
   979 			if (iLastHeaderToGet<0)
       
   980 				iLastHeaderToGet=0;
       
   981 			}
       
   982 
       
   983 		if(GetMessagesIfAny())
       
   984 			{
       
   985 			if(iPopSession->PipeliningSupport())
       
   986 				{
       
   987 				__ASSERT_ALWAYS(iPopTop, Panic(EPopNullPointer));
       
   988 				iPopTop->SetStartAndEndMessageIndex(iLastHeaderToGet, iMsgCtr);
       
   989 				}
       
   990 			RetrieveHeadersL();
       
   991 			break;
       
   992 			}
       
   993 		aState=EPopRefreshDeleteExcessMessages;
       
   994 		// nothing to do: drop through
       
   995 
       
   996 	case EPopRefreshDeleteExcessMessages:
       
   997 		//Need to commit downloaded headers to file before doing any deletions
       
   998 		iRemoteServerEntry.CompleteBulk();
       
   999 		if (iLastHeaderToGet==0)	//no excess messages !
       
  1000 			{
       
  1001 			aState=EPopRefreshDeleteDeadMessages;
       
  1002 			}
       
  1003 		// nothing to do: drop through
       
  1004 
       
  1005 	case EPopRefreshDeleteDeadMessages:
       
  1006 		//Need to commit downloaded headers to file before doing any deletions
       
  1007 		iRemoteServerEntry.CompleteBulk();
       
  1008 		// make sure we're pointing to correct context
       
  1009 		User::LeaveIfError(iRemoteServerEntry.SetEntry(iRemoteId));
       
  1010 		iRemoteArrayCtr=iUidlArray->Count();
       
  1011 		QueueRemoteUpdate();	
       
  1012 	break;
       
  1013 
       
  1014 	case EPopRefreshComplete:
       
  1015 		RefreshFinishedL();
       
  1016 	break;
       
  1017 
       
  1018 	default:     // Unknown state
       
  1019 		Panic(EImppUnknownRefreshState);
       
  1020 	break;
       
  1021 	}
       
  1022 	iState=aState;
       
  1023 	}
       
  1024 
       
  1025 	//
       
  1026 	// Use Pop STAT command to obtain of messages in remote mailbox
       
  1027 	//
       
  1028 	void CImPop3RefreshOperation::GetNoMessagesL()
       
  1029 	{
       
  1030 	CImPop3Stat* popStat = CImPop3Stat::NewL(iPopSession);
       
  1031 	if ( iPopStat  )
       
  1032 	{
       
  1033 	delete iPopStat;
       
  1034 	iPopStat = NULL;
       
  1035 	}
       
  1036 	iPopStat = popStat;
       
  1037 	iPopStat->Start(iStatus,iNoMessages,iMboxSize);
       
  1038 	SetActive();
       
  1039 	}
       
  1040 
       
  1041 	//
       
  1042 
       
  1043 	// Use LIST command to get message sizes
       
  1044 	//
       
  1045 	void CImPop3RefreshOperation::GetMsgSizesL()
       
  1046 	{
       
  1047 	CImPop3List* popList = CImPop3List::NewL(iPopSession);
       
  1048 	if ( iPopList  )
       
  1049 		{
       
  1050 		delete iPopList;
       
  1051 		iPopList = NULL;
       
  1052 		}
       
  1053 	iPopList = popList;
       
  1054 	iPopList->Start(iStatus,iSize);
       
  1055 	SetActive();
       
  1056 	}
       
  1057 
       
  1058 //
       
  1059 // Use UIDL to obtain POP3 unique message Ids
       
  1060 //
       
  1061 void CImPop3RefreshOperation::GetMsgUidlsL()
       
  1062 	{
       
  1063 	CImPop3Uidl* popUidl = CImPop3Uidl::NewL(iPopSession);
       
  1064 	if ( iPopUidl  )
       
  1065 		{
       
  1066 		delete iPopUidl;
       
  1067 		iPopUidl = NULL;
       
  1068 		}
       
  1069 	iPopUidl = popUidl;
       
  1070 	iPopUidl->Start(iStatus,*iPop3Uidls);
       
  1071 	SetActive();
       
  1072 	}
       
  1073 	
       
  1074 //
       
  1075 // Post Stat allocate the various arrays
       
  1076 // we know how many messages there are
       
  1077 void CImPop3RefreshOperation::AllocateArraysL()
       
  1078 	{
       
  1079  	// Allocate the message id array and give it to the POP session
       
  1080  	// so that any operation can access it.For example, Top requires
       
  1081  	// access to this for pipelining
       
  1082 	iIdTab = new(ELeave) TInt32[iNoMessages];
       
  1083 	Mem::FillZ(iIdTab,iNoMessages*sizeof(TInt32));
       
  1084 	iPopSession->SetMessageArray(iIdTab, iNoMessages);
       
  1085 	iSize = new(ELeave) TUint[iNoMessages];
       
  1086 	__ASSERT_ALWAYS(iNewMsg, Panic(EPopNullPointer));
       
  1087 	iNewMsg->SetReserveL(iNoMessages);		// no failure during AppendL()
       
  1088 
       
  1089 	iPop3Uidls = CImPop3UidlMap::NewL(iNoMessages);
       
  1090 	}
       
  1091 
       
  1092 void CImPop3RefreshOperation::DeleteUidl(TInt anIndex)
       
  1093 	{
       
  1094 	TMsgUidlStore& uidl=(*iUidlArray)[anIndex];
       
  1095 	delete uidl.iPopId;
       
  1096 	iUidlArray->Delete(anIndex);
       
  1097 	}
       
  1098 
       
  1099 //
       
  1100 // Open uidl file
       
  1101 //
       
  1102 void CImPop3RefreshOperation::GetRemoteMessagesL()
       
  1103 	{
       
  1104 	TMsvSelectionOrdering order;
       
  1105 	order.SetShowInvisibleEntries( ETrue );
       
  1106 	iRemoteServerEntry.SetSort( order );
       
  1107 	TInt selErr=iRemoteServerEntry.GetChildren(*iMsvSelection);
       
  1108 	if(selErr!=KErrNone)
       
  1109 		{
       
  1110 		User::Leave(selErr);
       
  1111 		}
       
  1112 	iRemoteArrayCtr=iMsvSelection->Count();
       
  1113 	TRAP_IGNORE(OpenUidlFileL());
       
  1114 	}
       
  1115 
       
  1116 //
       
  1117 //  Kick off async operation
       
  1118 //
       
  1119 void CImPop3RefreshOperation::QueueRemoteUpdate()
       
  1120 	{
       
  1121 	TRequestStatus *pS = &iStatus;
       
  1122 	SetActive();
       
  1123 	User::RequestComplete(pS,KErrNone);
       
  1124 	}
       
  1125 
       
  1126 //
       
  1127 // Sets the element with the INDEX in the message server
       
  1128 //
       
  1129 void CImPop3RefreshOperation::SyncCollectionL()
       
  1130 	{
       
  1131 	//iUidlArray has been read from the UIDL file
       
  1132 	//Look for the Messaging Server ID in iUidlArray
       
  1133 	//If found, set the member in the array element that points to the message INDEX (not id) in the Messaging Server
       
  1134 	--iRemoteArrayCtr;	// one at a time
       
  1135 	TMsgUidlStore aUidlStore;;
       
  1136 	aUidlStore.iMsvId=(*iMsvSelection)[iRemoteArrayCtr];
       
  1137 	TInt selectRow;
       
  1138 	if(iUidlArray->FindIsq(aUidlStore,iUidlKey,selectRow))
       
  1139 		{
       
  1140         //  Don't handle error in release mode.
       
  1141 #ifdef _DEBUG        
       
  1142 		TInt err = 
       
  1143 #endif				
       
  1144 		iRemoteServerEntry.DeleteEntry(aUidlStore.iMsvId);
       
  1145       	__ASSERT_DEBUG(err == KErrNone, Panic(EPopFailedDebugAssert));
       
  1146 		}
       
  1147 	else
       
  1148 		iUidlArray->At(selectRow).iSelectionPos=iRemoteArrayCtr;
       
  1149 	}
       
  1150 
       
  1151 void CImPop3RefreshOperation::CompleteSyncCollection()
       
  1152 //
       
  1153 // Complete the synchronization of the collection and local UIDL store
       
  1154 //
       
  1155 	{
       
  1156 	for(TInt ii=iUidlArray->Count();--ii>=0;)
       
  1157 		{
       
  1158 		if(iUidlArray->At(ii).iSelectionPos==TMsgUidlStore::EInvalid)
       
  1159 			{
       
  1160 			DeleteUidl(ii);
       
  1161 			}
       
  1162 		}
       
  1163 	}
       
  1164 //
       
  1165 // Sync the UIDL file for the Message Server to the POP server.
       
  1166 //
       
  1167 void CImPop3RefreshOperation::SyncUidlL()
       
  1168 	{
       
  1169 	//iPop3Uidls now contains the message ids of the messages on the POP3 server
       
  1170 	--iRemoteArrayCtr;
       
  1171 	TMsgUidlStore& uidl=(*iUidlArray)[iRemoteArrayCtr];
       
  1172 	__ASSERT_DEBUG(uidl.iSelectionPos>=0,User::Invariant());
       
  1173 
       
  1174 	TInt popUidlPos = 0;
       
  1175 	TInt popUidlRow = iPop3Uidls->MsgUidlNo(*uidl.iPopId,popUidlPos);
       
  1176 	// For duplicated case get the actual positions of the UIDLs.
       
  1177 	if(popUidlRow == KErrAlreadyExists)
       
  1178 		{
       
  1179 		 while ( popUidlPos > 0 )
       
  1180 			{
       
  1181 			if (iPop3Uidls->MsgUidl(popUidlPos-1) == *uidl.iPopId)
       
  1182 		 		{
       
  1183 		 		--popUidlPos;
       
  1184 				}
       
  1185 				else
       
  1186 				{
       
  1187 				break;
       
  1188 				}
       
  1189 			}
       
  1190 		TInt uidlExists = iUniqueUidlPosArray.FindInOrder(popUidlPos);
       
  1191 		if(uidlExists != KErrNotFound)
       
  1192 			{
       
  1193 			//If aUidl already exists find position of next duplicated uidl.
       
  1194 			popUidlPos = iTemporaryUidlPosArray[uidlExists] + 1;
       
  1195 	    
       
  1196 	    	// Remove the last duplicated Uidl position value.
       
  1197 			iTemporaryUidlPosArray.Remove(uidlExists);
       
  1198 	
       
  1199 			//Insert the position of the present duplicate uidl to the array.
       
  1200 			iTemporaryUidlPosArray.Insert(popUidlPos,uidlExists);
       
  1201 			}
       
  1202 		else
       
  1203 			{
       
  1204 			//iUniqueUidlPosArray will contain the first occurrences(pos)of all duplicated UIDLs
       
  1205 			iUniqueUidlPosArray.InsertInOrder(popUidlPos);
       
  1206 			
       
  1207 			// For getting next position of duplicate Uidl.
       
  1208 			iTemporaryUidlPosArray.InsertInOrder(popUidlPos);
       
  1209 			}
       
  1210 	
       
  1211 		//Maximum value of popUidlPos should not exceed count(No. of uidls in the popserver - 1).
       
  1212 		TInt count = iPop3Uidls->MsgCount() - 1;
       
  1213 		popUidlRow = -1;
       
  1214 		if(count >= popUidlPos)		
       
  1215 			{
       
  1216 			// Check Whether the UIDL at popUidlRow of POP server matches the UIDL in Uidl file..
       
  1217 			if(iPop3Uidls->MsgUidl(popUidlPos) == *uidl.iPopId)
       
  1218 				{
       
  1219 				popUidlRow = iPop3Uidls->MsgIndex(popUidlPos);	
       
  1220 				}
       
  1221 			}
       
  1222 		}
       
  1223 	
       
  1224 	//Check whether the UIDL index has already been passed.
       
  1225 	//This is to Handle the deletion of all duplicated mails from server using other email client.
       
  1226 	if(iPreviousIndex == popUidlRow)
       
  1227 		{
       
  1228 		popUidlRow = -1;
       
  1229 		}
       
  1230 	else
       
  1231 		{
       
  1232 		iPreviousIndex = popUidlRow;	
       
  1233 		}
       
  1234 
       
  1235 
       
  1236 	if(popUidlRow<0)
       
  1237 		{
       
  1238 		//A Message is in the Messaging Server but not on the POP3 server, so delete it from the
       
  1239 		//the Messaging Server
       
  1240 #ifdef _DEBUG		
       
  1241      	TInt err = 
       
  1242 #endif     	     	
       
  1243      	iRemoteServerEntry.DeleteEntry(uidl.iMsvId);//  Don't handle the error in release mode
       
  1244          __ASSERT_DEBUG(err == KErrNone, Panic(EPopFailedDebugAssert));
       
  1245 		// & delete it from the UIDL file
       
  1246 		DeleteUidl(iRemoteArrayCtr);
       
  1247 		}
       
  1248 	else
       
  1249 		{
       
  1250 		//A message is in the Messaging Server *and* is on the POP3 server,
       
  1251 		//so mark it as present in the UIDL file, and decrement the number of headers to download
       
  1252 		iIdTab[popUidlRow]=uidl.iMsvId; //GetMessagesIfAny() checks this to see if the header is already present
       
  1253 		iProgress.iMsgsToProcess--;
       
  1254 		uidl.iSelectionPos=TMsgUidlStore::EPresent;
       
  1255 		}
       
  1256 	}
       
  1257 //
       
  1258 // Report the refreshing news back to the UI
       
  1259 //
       
  1260 TPop3Progress CImPop3RefreshOperation::Progress()
       
  1261 	{
       
  1262 	return iProgress;
       
  1263 	}
       
  1264 //
       
  1265 // Gets Headers or Messages
       
  1266 //
       
  1267 void CImPop3RefreshOperation::RetrieveHeadersL()
       
  1268 	{
       
  1269 	// Check to see we have at least the minimum free disk space available
       
  1270 	if (--iCheckDiskSpaceCounter <= 0)
       
  1271   		{
       
  1272 		// If we are running low on disk space then leave
       
  1273 
       
  1274 		ImCheckDiskSpace::LeaveIfLowDiskL(iFs, iCurrentDrive);
       
  1275 		iCheckDiskSpaceCounter = KCheckDiskSpaceEveryNMessages;
       
  1276 		}
       
  1277   	
       
  1278 	// get header or msg
       
  1279 	iTopExists ? GetHeaderByIndexL(iMsgCtr) : GetMessageByIndexL(iMsgCtr);
       
  1280 
       
  1281 	SetActive();
       
  1282 	}
       
  1283 
       
  1284 //
       
  1285 // Use Top to Retrieve the message header
       
  1286 //
       
  1287 void CImPop3RefreshOperation::GetHeaderByIndexL(TInt anIndex)
       
  1288 	{
       
  1289 	__ASSERT_ALWAYS(iPopTop, Panic(EPopNullPointer));
       
  1290 	iPopTop->SetMessageIndexAndLines(anIndex+1,1);
       
  1291 	iPopTop->StartL(iStatus);
       
  1292 	}
       
  1293 
       
  1294 //
       
  1295 // If no Top need to retrieve whole message
       
  1296 //
       
  1297 void CImPop3RefreshOperation::GetMessageByIndexL(TInt anIndex)
       
  1298 	{
       
  1299 	__ASSERT_ALWAYS(iPopRetr, Panic(EPopNullPointer));
       
  1300 	iPopRetr->SetMessageIndex(anIndex+1);
       
  1301 	iPopRetr->StartL(iStatus);
       
  1302 	}
       
  1303 
       
  1304 //
       
  1305 //
       
  1306 // Get TMsvEntry from CImHeader via CMsgIMail add to msg collection?
       
  1307 //
       
  1308 void CImPop3RefreshOperation::CreateNewHeaderEntryL(TMsvEntry& aNewEntry)
       
  1309 	{
       
  1310 	TPtrC8 id;
       
  1311 	if(iTopExists)
       
  1312 		{
       
  1313 		__ASSERT_ALWAYS(iPopTop, Panic(EPopNullPointer));
       
  1314 		iPopTop->EntryId();
       
  1315 		id.Set(iPopTop->ImMsgId());
       
  1316 		}
       
  1317 	else
       
  1318 		{
       
  1319 		__ASSERT_ALWAYS(iPopRetr, Panic(EPopNullPointer));
       
  1320 		iPopRetr->EntryId();
       
  1321 		id.Set(iPopRetr->ImMsgId());
       
  1322 		}
       
  1323 
       
  1324 	aNewEntry.SetComplete(EFalse);
       
  1325 	aNewEntry.SetAttachment(EFalse);
       
  1326 	aNewEntry.iSize = iSize[iMsgCtr];
       
  1327 	aNewEntry.iServiceId = iRemoteId;
       
  1328 	aNewEntry.SetVisible(ETrue);
       
  1329 	aNewEntry.SetInPreparation(EFalse);
       
  1330 
       
  1331 	// add message to list uidl list
       
  1332 	TMsgUidlStore	msgUidlStore;	
       
  1333 	if(iUidlExists)
       
  1334 		{
       
  1335 		msgUidlStore.iPopId=(*iPop3Uidls)[iMsgCtr].AllocLC();
       
  1336 		}
       
  1337 	else
       
  1338 #if defined _UNICODE
       
  1339 		{
       
  1340 		msgUidlStore.iPopId = HBufC8::NewLC(id.Length());
       
  1341 		msgUidlStore.iPopId->Des().Copy(id);
       
  1342 		}
       
  1343 #else
       
  1344 		msgUidlStore.iPopId=id.AllocLC();
       
  1345 #endif
       
  1346 
       
  1347 	msgUidlStore.iMsvId=(aNewEntry.Id());
       
  1348 	msgUidlStore.iRemoteSize=iSize[iMsgCtr];
       
  1349 	msgUidlStore.iSelectionPos=TMsgUidlStore::EPresent;
       
  1350 	iUidlArray->InsertIsqL(msgUidlStore,iUidlKey);
       
  1351 	CleanupStack::Pop();	//iPopId
       
  1352 	}
       
  1353 
       
  1354 
       
  1355 //
       
  1356 // Compare internet msg id of retrieved header to what we have stored and compare sizes
       
  1357 //
       
  1358 TBool CImPop3RefreshOperation::CompareIdAndSizeL()
       
  1359 	{
       
  1360 	TPtrC8 id;
       
  1361 
       
  1362 	__ASSERT_ALWAYS(iPopTop && iPopRetr, Panic(EPopNullPointer));
       
  1363 	iTopExists ? id.Set(iPopTop->ImMsgId()) : id.Set(iPopRetr->ImMsgId());
       
  1364 
       
  1365 	CArrayFix<TMsgUidlStore>& uidlarray=*iUidlArray;
       
  1366 	TInt row=uidlarray.Count();
       
  1367 	while (--row>=0 && *uidlarray[row].iPopId!=id)
       
  1368 		;
       
  1369 
       
  1370 	if (row>=0)	
       
  1371 		{
       
  1372 //we've found an entry in the UIDL file which matches our msg id
       
  1373 //so we don't need to create a new message
       
  1374 		TMsgUidlStore& uidlstore=uidlarray[row];
       
  1375 		if (uidlstore.iRemoteSize==iSize[iMsgCtr])			
       
  1376 			{
       
  1377 			iIdTab[iMsgCtr]=uidlstore.iMsvId;
       
  1378 			__ASSERT_DEBUG(uidlstore.iSelectionPos>=0,User::Invariant());
       
  1379 			uidlstore.iSelectionPos=TMsgUidlStore::EPresent;
       
  1380 //as the UIDL command is not supported, we have downloaded the header or the message body
       
  1381 //we're throwing this away now because the message already exists.
       
  1382 			__ASSERT_ALWAYS(iPopTop && iPopRetr, Panic(EPopNullPointer));
       
  1383 			TMsvId newId;
       
  1384 			iTopExists ? newId = iPopTop->EntryId() : newId = iPopRetr->EntryId();
       
  1385 			iUnwantedEntries->AppendL(newId);
       
  1386 			return EFalse;
       
  1387 			}
       
  1388 		// Set the current context to the POP3 service entry else DeleteEntry panics
       
  1389 		User::LeaveIfError(iRemoteServerEntry.SetEntry(iRemoteId));
       
  1390         //  Don't handle the error in release mode.
       
  1391 #ifdef _DEBUG        
       
  1392 		TInt err = 
       
  1393 #endif				
       
  1394 		iRemoteServerEntry.DeleteEntry(uidlstore.iMsvId); // should this happen?
       
  1395         __ASSERT_DEBUG(err == KErrNone, Panic(EPopFailedDebugAssert));
       
  1396 		DeleteUidl(row);
       
  1397 		}
       
  1398 	return ETrue;
       
  1399 	}
       
  1400 
       
  1401 //
       
  1402 // Open a file of existing POP Uidls with corresponding Babel MsgIds
       
  1403 //
       
  1404 void CImPop3RefreshOperation::OpenUidlFileL()
       
  1405 	{
       
  1406 	// get path of uidls file from id of remote server entry
       
  1407     TInt error = KErrNone;
       
  1408 	TParse p;
       
  1409 	TFileName path;
       
  1410 
       
  1411 	CMsvStore* store = iRemoteServerEntry.ReadStoreL(); 
       
  1412 	CleanupStack::PushL(store);
       
  1413 	MMsvAttachmentManager& attachmentMgr = store->AttachmentManagerL();
       
  1414 	// if there is no attachment then a UIDL file has not been
       
  1415 	// created, so not found.
       
  1416 	if(attachmentMgr.AttachmentCount() < 1)
       
  1417 		{
       
  1418 		User::Leave(KErrNotFound);
       
  1419 		}
       
  1420 	CMsvAttachment* attachment = attachmentMgr.GetAttachmentInfoL(0);
       
  1421 	CleanupStack::PushL(attachment);
       
  1422 	path = attachment->FilePath();
       
  1423 	p.Set(path,NULL,NULL);
       
  1424 	CleanupStack::PopAndDestroy(2,store);
       
  1425 
       
  1426 	RFile f;
       
  1427 	error = f.Open(iFs,p.FullName(),EFileShareReadersOnly);
       
  1428 	User::LeaveIfError(error);
       
  1429 
       
  1430 	CDirectFileStore* index=CDirectFileStore::FromLC(f);
       
  1431 	const TUidType type(KDirectFileStoreLayoutUid,KNullUid,KMsgFileRemoteIdIndex);
       
  1432 	if (type != index->Type())
       
  1433 		{
       
  1434 		User::Leave(KErrCorrupt);
       
  1435 		}
       
  1436 	RStoreReadStream in;
       
  1437 	in.OpenLC(*index,index->Root());
       
  1438 	TInt entries = in.ReadInt32L();
       
  1439 	TMsgUidlStore entry;
       
  1440 	while (--entries>=0)
       
  1441 		{
       
  1442 		HBufC8* popid=HBufC8::NewLC( in, KMaxStringLength );
       
  1443 		// internalization code... inline to handle cleanup issues
       
  1444 		entry.iPopId=popid;
       
  1445 		entry.iMsvId=in.ReadUint32L();
       
  1446 		entry.iRemoteSize=in.ReadUint32L();
       
  1447 		entry.iSelectionPos=TMsgUidlStore::EInvalid;	// not present in selection (yet)
       
  1448 		//
       
  1449 		iUidlArray->AppendL(entry);
       
  1450 		CleanupStack::Pop(popid);	// HBufC8's
       
  1451 		}
       
  1452 	CleanupStack::PopAndDestroy(2); // in, index
       
  1453 	}
       
  1454 
       
  1455 //
       
  1456 // Create new POP Uidl file
       
  1457 //
       
  1458 void CImPop3RefreshOperation::CreateUidlFileL()
       
  1459 	{
       
  1460 	// create the new index of uidl stuff
       
  1461 	// put it in folder for current server entry (correct remote mailbox folder)
       
  1462 	TParse p;
       
  1463 	TFileName path;
       
  1464 
       
  1465 	TInt fileErr = iRemoteServerEntry.SetEntry( iRemoteId );
       
  1466 	if(fileErr!=KErrNone)
       
  1467 		{
       
  1468 		return;
       
  1469 		}
       
  1470 	
       
  1471 	CMsvStore* store = iRemoteServerEntry.EditStoreL(); 
       
  1472 	CleanupStack::PushL(store);
       
  1473 	// UIDL file is stored as the first attachment to the server entry
       
  1474 	// if it is already present then overwrite, else create it,
       
  1475 	MMsvAttachmentManager& attachmentMgr = store->AttachmentManagerL();
       
  1476 	RFile file;
       
  1477 	if(attachmentMgr.AttachmentCount() < 1)
       
  1478 		{
       
  1479 		MMsvAttachmentManagerSync& attachmentMgrSync = store->AttachmentManagerExtensionsL();
       
  1480 		CMsvAttachment *attachment = CMsvAttachment::NewL(CMsvAttachment::EMsvFile);
       
  1481 		attachmentMgrSync.CreateAttachmentL(KUidlFile,file,attachment); // Takes ownership of attachment
       
  1482 		CleanupClosePushL(file);
       
  1483 		store->CommitL();
       
  1484 		CleanupStack::Pop(&file);
       
  1485 		}
       
  1486 	else
       
  1487 		{
       
  1488 		file=attachmentMgr.GetAttachmentFileForWriteL(0);
       
  1489 		}
       
  1490 	CleanupStack::PopAndDestroy(store);
       
  1491 
       
  1492 	CDirectFileStore* index = CDirectFileStore::NewLC(file);
       
  1493 	const TUidType type(KDirectFileStoreLayoutUid,KNullUid,KMsgFileRemoteIdIndex);
       
  1494 	index->SetTypeL(type);
       
  1495 	RStoreWriteStream out;
       
  1496 	TStreamId id = out.CreateLC(*index);
       
  1497 	TInt entries = iUidlArray->Count();
       
  1498 	out.WriteInt32L(entries);
       
  1499 	for(TInt number = 0; number<entries; number++)	// must keep order, go forwards
       
  1500 		{
       
  1501 		out << (*iUidlArray)[number];
       
  1502 		}
       
  1503 	out.CommitL();                      // Commit stream : Is this needed?
       
  1504 	CleanupStack::PopAndDestroy();      // Destroy stream
       
  1505 	index->SetRootL(id);
       
  1506 	index->CommitL();                   // Commit store : I guess this is needed!
       
  1507 	CleanupStack::PopAndDestroy();      // Destroy store
       
  1508 	}
       
  1509 
       
  1510 //
       
  1511 // Externalise/Internalise Uidl structure
       
  1512 //
       
  1513 
       
  1514 void CImPop3RefreshOperation::TMsgUidlStore::ExternalizeL(RWriteStream& aStream) const
       
  1515 	{
       
  1516 	aStream << *iPopId;
       
  1517 	aStream.WriteUint32L(iMsvId);
       
  1518 	aStream.WriteUint32L(iRemoteSize);
       
  1519 	}
       
  1520 //
       
  1521 // Sets the selection of entries to keep
       
  1522 //
       
  1523 void CImPop3RefreshOperation::SetMessagesToKeepL(const CMsvEntrySelection* aMessagesToKeep)
       
  1524 	{
       
  1525 	delete iMessagesToKeep;
       
  1526 	iMessagesToKeep = NULL;
       
  1527 	if (aMessagesToKeep)
       
  1528 		{
       
  1529 		iMessagesToKeep = aMessagesToKeep->CopyL();
       
  1530 		}
       
  1531 	}
       
  1532 //
       
  1533 // Check if ok to delete message
       
  1534 //
       
  1535 TBool CImPop3RefreshOperation::CanDeleteEntry(const TMsvEmailEntry& aEntry) const
       
  1536 	// Don't delete email if body exists or if it is an email that is being opened immediately after
       
  1537 	// the inbox refreshing (See defect PEN-5ESAWM)
       
  1538 	{
       
  1539 	// iMessagesToKeep may be Null
       
  1540 	if (iMessagesToKeep && iMessagesToKeep->Find(aEntry.Id()) != KErrNotFound)
       
  1541 		{
       
  1542 		return EFalse;
       
  1543 		}
       
  1544 	return ETrue;
       
  1545 	}
       
  1546 //
       
  1547 // Gets the size of the remote message
       
  1548 //
       
  1549 TUint CImPop3RefreshOperation::RemoteMessageSizeL(TMsvId aId)
       
  1550 	{
       
  1551 	TInt 	count	= iUidlArray->Count();
       
  1552 	TUint 	retVal 	= NULL;
       
  1553 
       
  1554 	while( count-- )
       
  1555 		{
       
  1556 		const TMsgUidlStore &store=iUidlArray->At(count);
       
  1557 		if(store.iMsvId == aId)
       
  1558 			{
       
  1559 			// We have found a match, so return the size for this item
       
  1560 			retVal = store.iRemoteSize;
       
  1561 			break;
       
  1562 			}
       
  1563 		}
       
  1564 
       
  1565 	if (!retVal)
       
  1566 		{
       
  1567 		// Leave if none of the MsvIds match
       
  1568 		User::Leave(KErrNotFound);
       
  1569 		}
       
  1570 	return retVal;
       
  1571 	}
       
  1572 
       
  1573 // ****************************************************************************************** 
       
  1574 // This is called by the POP Client MTM when it starts Migrating Bearer
       
  1575 // 
       
  1576 // ******************************************************************************************
       
  1577 void CImPop3RefreshOperation::Pause()
       
  1578 	{
       
  1579 	// Set the Migration flag
       
  1580 	iMigratingToNewBearer = ETrue;
       
  1581 	}
       
  1582 
       
  1583 // ****************************************************************************************** 
       
  1584 // This is called by the POP Client MTM when it starts Migrating Bearer
       
  1585 // 
       
  1586 // ******************************************************************************************	
       
  1587 void CImPop3RefreshOperation::CancelAllowResume()
       
  1588 	{
       
  1589 	// Cancel the copying of the current message  and decrement counters 
       
  1590 	// so we can restart from this message onwards when we have migrated.
       
  1591 	// Use the normal cancel, as we really need to cancel here.
       
  1592 	Cancel();		
       
  1593 	}