email/imap4mtm/imapservermtm/src/cimap4servermtm.cpp
changeset 0 72b543305e3a
child 54 fa1df4b99609
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 "cimap4servermtm.h"
       
    17 #include "cimapofflinecontrol.h"
       
    18 #include "cimapprotocolcontroller.h"
       
    19 #include "cimaplogger.h"
       
    20 
       
    21 #include <e32std.h>
       
    22 #include <imapset.h>
       
    23 #include <imapcmds.h>
       
    24 #include <mentact.h>
       
    25 #include <msventry.h>	// CMsvServerEntry
       
    26 #include <tmsvsystemprogress.h>
       
    27 
       
    28 #if (defined SYMBIAN_USER_PROMPT_SERVICE)
       
    29 #include "cimapupsresponsewaiter.h"
       
    30 #endif 
       
    31 
       
    32 #ifdef __IMAP_LOGGING
       
    33 _LIT(KDefaultLogFileName, "imaplog");
       
    34 #endif //__IMAP_LOGGING
       
    35 
       
    36 /**
       
    37 Static constructor for the server MTM. The server MTMs default constructor is 
       
    38 private hence this method must be called to instantiate the class.
       
    39 
       
    40 @param aRegisteredMtmDll
       
    41 @param aEntry
       
    42 @return A pointer to the newly created CImap4ServerMtm object. The caller is 
       
    43 responsible for cleanup
       
    44 */
       
    45 EXPORT_C CImap4ServerMtm* CImap4ServerMtm::NewL( CRegisteredMtmDll& aRegisteredMtmDll,
       
    46 										   		 CMsvServerEntry* aEntry )
       
    47 	{
       
    48 	CImap4ServerMtm* self = new ( ELeave ) CImap4ServerMtm( aRegisteredMtmDll, 
       
    49 															aEntry );		
       
    50 	CleanupStack::PushL( self );
       
    51 	self->ConstructL();
       
    52 	CleanupStack::Pop( self );
       
    53 	return self;
       
    54 	
       
    55 	}
       
    56 
       
    57 /**
       
    58 CImap4ServerMtm constructor
       
    59 
       
    60 @param aRegisteredMtmDll
       
    61 @param aEntry
       
    62 */
       
    63 CImap4ServerMtm::CImap4ServerMtm( CRegisteredMtmDll& aRegisteredMtmDll, 
       
    64 								  CMsvServerEntry* aServerEntry) :
       
    65  CBaseServerMtm( aRegisteredMtmDll, aServerEntry ), iServerEntry (aServerEntry)
       
    66 	{
       
    67 	
       
    68 	}
       
    69 
       
    70 /**
       
    71 CImap4SeverMtm destructor
       
    72 
       
    73 */	
       
    74 CImap4ServerMtm::~CImap4ServerMtm()
       
    75 	{
       
    76 	__LOG_TEXT(KDefaultLog, "CImap4ServerMtm::~CImap4ServerMtm()");
       
    77 	Cancel();
       
    78 
       
    79 	delete iImapProtocolController;
       
    80 	delete iImapOfflineControl;
       
    81 	__LOG_CLOSE(KDefaultLog);
       
    82 	CImapUtils::Delete();
       
    83 #if (defined SYMBIAN_USER_PROMPT_SERVICE)
       
    84 	delete iWaiter;
       
    85 #endif		
       
    86 	}
       
    87 
       
    88 /**
       
    89 CImap4ServerMtm second phase constructor
       
    90 */	
       
    91 void CImap4ServerMtm::ConstructL()
       
    92 	{
       
    93 	CImapUtils::CreateL();
       
    94 	__LOG_CREATE_DEFAULT(KDefaultLogFileName);
       
    95 
       
    96 	iImapOfflineControl = CImapOfflineControl::NewL( *iServerEntry );
       
    97 	iImapProtocolController = CImapProtocolController::NewL( *iServerEntry , *iImapOfflineControl);
       
    98 	
       
    99 #if (defined SYMBIAN_USER_PROMPT_SERVICE)
       
   100 	iWaiter = CImapUpsResponseWaiter::NewL(*iServerEntry, *iImapProtocolController);
       
   101 	iHasCapability = ETrue;
       
   102 #endif	
       
   103 	// We need to see invisible entries
       
   104 	TMsvSelectionOrdering invisible;
       
   105 	invisible=iServerEntry->Sort();
       
   106 	invisible.SetShowInvisibleEntries(ETrue);
       
   107 	iServerEntry->SetSort(invisible);
       
   108 	// Add us to the scheduler
       
   109 	CActiveScheduler::Add( this );
       
   110 	}
       
   111 
       
   112 /**
       
   113 This command is used to copy a message to a local folder. This may be 
       
   114 the local mirror of the IMAP folder, i.e. the local representation of 
       
   115 the online IMAP folder as it exists on the remote server, or a local 
       
   116 service folder (eg the global inbox) in which case the message is fetched 
       
   117 completely to the mirror folder then copied to the destination folder. 
       
   118 This command results in an entire message being fetched, as it fetches 
       
   119 according to the default parameters, which are:
       
   120 
       
   121 iTotalSizeLimit = KMaxTInt
       
   122 iBodyTextSizeLimit = KMaxTInt
       
   123 iAttachmentSizeLimit = KMaxTInt
       
   124 iGetMailBodyParts = EGetImap4EmailBodyTextAndAttachments	 
       
   125 iPartialMailOptions = ENoSizeLimits
       
   126 iDestinationFolder = <target destination>
       
   127 
       
   128 This command can result in additional IMAP sessions being instantiated. 
       
   129 As it is a "read only" operation (ie, the contents of the remote server 
       
   130 are not updated as a result of performing this operation) it is safe to 
       
   131 perform such fetches while a background sync is in progress.
       
   132 
       
   133 @param aSelection The selection of message TMsvIds that are copied.
       
   134 @param aDestination The TMsvId of the destination folder.
       
   135 @param aStatus The request status to be completed when the operation has finished.
       
   136 */
       
   137 void CImap4ServerMtm::CopyToLocalL( const CMsvEntrySelection& aSelection, 
       
   138 				  					TMsvId aDestination, 
       
   139 				  					TRequestStatus& aStatus )
       
   140 	{
       
   141 	__LOG_TEXT(KDefaultLog, "CImap4ServerMtm::CopyToLocalL()");
       
   142 
       
   143 	if (!iImapProtocolController->Connected())
       
   144 		{
       
   145 		iState = EMtmStateOffLineCopyToLocal;
       
   146 		CImapOfflineControl::TImap4OpType opType=CImapOfflineControl::EImap4OpCopyToLocal;
       
   147 		iImapOfflineControl->StoreOfflineCommandL(opType, aSelection, aDestination, iStatus);
       
   148 		}
       
   149 	else
       
   150 		{
       
   151 		iState = EMtmStateCopyToLocal;
       
   152 		iImapProtocolController->CopyToLocalL(iStatus, aSelection, aDestination);
       
   153 		}	
       
   154 	Queue(aStatus);
       
   155 	SetActive();										   
       
   156 	}
       
   157 
       
   158 /**
       
   159 CopyFromLocalL appends entire messages in the mirror to the server.
       
   160 
       
   161 @param aSelection The selection of message TMsvIds that are copied.
       
   162 @param aDestination The TMsvId of the destination folder.
       
   163 @param aStatus The request status to be completed when the operation has finished.
       
   164 */
       
   165 void CImap4ServerMtm::CopyFromLocalL( const CMsvEntrySelection& aSelection,
       
   166 								      TMsvId aDestination, 
       
   167 				   					  TRequestStatus& aStatus )
       
   168 	{
       
   169 	__LOG_TEXT(KDefaultLog, "CImap4ServerMtm::CopyFromLocalL()");
       
   170 	
       
   171 	// Check the destination folder is a mailbox
       
   172 	User::LeaveIfError(iServerEntry->SetEntry(aDestination));
       
   173 	TMsvEmailEntry destination = iServerEntry->Entry();
       
   174 	if (!destination.Mailbox())
       
   175 		{
       
   176 		Queue(aStatus);
       
   177 		User::RequestComplete(iRequest, KErrNotSupported);
       
   178 		return;
       
   179 		}
       
   180 
       
   181 	if (!iImapProtocolController->Connected())
       
   182 		{
       
   183 		iState = EMtmStateOffLineCopyFromLocal;
       
   184 		CImapOfflineControl::TImap4OpType opType=CImapOfflineControl::EImap4OpCopyFromLocal;
       
   185 		iImapOfflineControl->StoreOfflineCommandL(opType, aSelection, aDestination, iStatus);
       
   186 		}
       
   187 	else
       
   188 		{
       
   189 		iState = EMtmStateCopyFromLocal;
       
   190 		iImapProtocolController->CopyFromLocalL(iStatus, aSelection, aDestination);
       
   191 		}	
       
   192 	Queue(aStatus);
       
   193 	SetActive();
       
   194 	}
       
   195 
       
   196 /**
       
   197 CopyWithinService copies entire messages to other folders on the server, 
       
   198 using the IMAP COPY command.
       
   199 
       
   200 @param aSelection The selection of message TMsvIds that are copied.
       
   201 @param aDestination The TMsvId of the destination folder.
       
   202 @param aStatus The request status to be completed when the operation has finished.
       
   203 */
       
   204 void CImap4ServerMtm::CopyWithinServiceL( const CMsvEntrySelection& aSelection, 
       
   205 							 			  TMsvId aDestination, 
       
   206 							 			  TRequestStatus& aStatus )
       
   207 	{
       
   208 	__LOG_TEXT(KDefaultLog, "CImap4ServerMtm::CopyWithinServiceL()");
       
   209 	
       
   210 	// Check the destination folder is a mailbox
       
   211 	User::LeaveIfError(iServerEntry->SetEntry(aDestination));
       
   212 	TMsvEmailEntry destination = iServerEntry->Entry();
       
   213 	if (!destination.Mailbox())
       
   214 		{
       
   215 		Queue(aStatus);
       
   216 		User::RequestComplete(iRequest, KErrNotSupported);
       
   217 		return;
       
   218 		}
       
   219 
       
   220 	if (!iImapProtocolController->Connected())
       
   221 		{
       
   222 		iState = EMtmStateOffLineCopyWithinService;
       
   223 		CImapOfflineControl::TImap4OpType opType=CImapOfflineControl::EImap4OpCopyWithinService;
       
   224 		iImapOfflineControl->StoreOfflineCommandL(opType, aSelection, aDestination, iStatus);
       
   225 		}
       
   226 	else
       
   227 		{
       
   228 		iState = EMtmStateCopyWithinService;
       
   229 		iImapProtocolController->CopyWithinServiceL(iStatus, aSelection, aDestination);
       
   230 		}	
       
   231 	Queue(aStatus);
       
   232 	SetActive();
       
   233 	}
       
   234 
       
   235 /**
       
   236 MoveToLocalL moves a message from the remote server to a local folder: this 
       
   237 is performed as a fetch, then a delete on the remote server.
       
   238 
       
   239 @param aSelection The selection of message TMsvIds that are moved.
       
   240 @param aDestination The TMsvId of the destination folder.
       
   241 @param aStatus The request status to be completed when the operation has finished.
       
   242 */
       
   243 void CImap4ServerMtm::MoveToLocalL( const CMsvEntrySelection& aSelection, 
       
   244 				  	   			    TMsvId aDestination, 
       
   245 				  	   				TRequestStatus& aStatus )
       
   246 	{
       
   247 	__LOG_TEXT(KDefaultLog, "CImap4ServerMtm::MoveToLocalL()");
       
   248 
       
   249 	if (!iImapProtocolController->Connected())
       
   250 		{
       
   251 		iState = EMtmStateOffLineMoveToLocal;
       
   252 		CImapOfflineControl::TImap4OpType opType=CImapOfflineControl::EImap4OpMoveToLocal;
       
   253 		iImapOfflineControl->StoreOfflineCommandL(opType, aSelection, aDestination, iStatus);
       
   254 		}
       
   255 	else
       
   256 		{
       
   257 		iState = EMtmStateMoveToLocal;
       
   258 		iImapProtocolController->MoveToLocalL(iStatus, aSelection, aDestination);
       
   259 		}	
       
   260 	Queue(aStatus);
       
   261 	SetActive();
       
   262 	}
       
   263 
       
   264 /**
       
   265 MoveFromLocalL does a CopyFromLocal (ie, IMAP APPEND of the message), then 
       
   266 deletes the local message if it was sucessful.
       
   267 
       
   268 @param aSelection The selection of message TMsvIds that are moved.
       
   269 @param aDestination The TMsvId of the destination folder.
       
   270 @param aStatus The request status to be completed when the operation has finished.
       
   271 */
       
   272 void CImap4ServerMtm::MoveFromLocalL( const CMsvEntrySelection& aSelection,
       
   273 						 			  TMsvId aDestination, 
       
   274 						 			  TRequestStatus& aStatus )
       
   275 	{
       
   276 	__LOG_TEXT(KDefaultLog, "CImap4ServerMtm::MoveFromLocalL()");
       
   277 	
       
   278 	// Check the destination folder is a mailbox
       
   279 	User::LeaveIfError(iServerEntry->SetEntry(aDestination));
       
   280 	TMsvEmailEntry destination = iServerEntry->Entry();
       
   281 	if (!destination.Mailbox())
       
   282 		{
       
   283 		Queue(aStatus);
       
   284 		User::RequestComplete(iRequest, KErrNotSupported);
       
   285 		return;
       
   286 		}
       
   287 
       
   288 	if (!iImapProtocolController->Connected())
       
   289 		{
       
   290 		iState = EMtmStateOffLineMoveFromLocal;
       
   291 		CImapOfflineControl::TImap4OpType opType=CImapOfflineControl::EImap4OpMoveFromLocal;
       
   292 		iImapOfflineControl->StoreOfflineCommandL(opType, aSelection, aDestination, iStatus);
       
   293 		}
       
   294 	else
       
   295 		{
       
   296 		iState = EMtmStateMoveFromLocal;
       
   297 		iImapProtocolController->MoveFromLocalL(iStatus, aSelection, aDestination);
       
   298 		}	
       
   299 	Queue(aStatus);
       
   300 	SetActive();
       
   301 	}
       
   302 
       
   303 /**
       
   304 MoveWithinServiceL copies entire messages to other folders on the server, 
       
   305 using the IMAP COPY command. If the copy was successful, the original is deleted, 
       
   306 resulting in a move operation having been performed.
       
   307 
       
   308 @param aSelection The selection of message TMsvIds that are moved.
       
   309 @param aDestination The TMsvId of the destination folder.
       
   310 @param aStatus The request status to be completed when the operation has finished.
       
   311 */
       
   312 void CImap4ServerMtm::MoveWithinServiceL( const CMsvEntrySelection& aSelection, 
       
   313 										  TMsvId aDestination, 
       
   314 										  TRequestStatus& aStatus )
       
   315 	{
       
   316 	__LOG_TEXT(KDefaultLog, "CImap4ServerMtm::MoveWithinServiceL()");
       
   317 	
       
   318 	// Check the destination folder is a mailbox
       
   319 	User::LeaveIfError(iServerEntry->SetEntry(aDestination));
       
   320 	TMsvEmailEntry destination = iServerEntry->Entry();
       
   321 	if (!destination.Mailbox())
       
   322 		{
       
   323 		Queue(aStatus);
       
   324 		User::RequestComplete(iRequest, KErrNotSupported);
       
   325 		return;
       
   326 		}
       
   327 
       
   328 	if (!iImapProtocolController->Connected())
       
   329 		{
       
   330 		iState = EMtmStateOffLineMoveWithinService;
       
   331 		CImapOfflineControl::TImap4OpType opType=CImapOfflineControl::EImap4OpMoveWithinService;
       
   332 		iImapOfflineControl->StoreOfflineCommandL(opType, aSelection, aDestination, iStatus);
       
   333 		}
       
   334 	else
       
   335 		{
       
   336 		iState = EMtmStateMoveWithinService;
       
   337 		iImapProtocolController->MoveWithinServiceL(iStatus, aSelection, aDestination);
       
   338 		}	
       
   339 	Queue(aStatus);
       
   340 	SetActive();
       
   341 	}
       
   342 
       
   343 /**
       
   344 Can be used to delete a selection of messages, a selection of folders, or 
       
   345 local parts of a message. The intention of the user is inferred from the
       
   346 entry type at location 0 of the passed CMsvEntrySelection.
       
   347 
       
   348 @param aSelection
       
   349 @param aStatus
       
   350 */
       
   351 void CImap4ServerMtm::DeleteAllL( const CMsvEntrySelection& aSelection, 
       
   352 								  TRequestStatus& aStatus )
       
   353 	{
       
   354 	__LOG_TEXT(KDefaultLog, "CImap4ServerMtm::DeleteAllL()");
       
   355 	
       
   356 	if (PruneMessages(aSelection, aStatus))
       
   357 		{
       
   358 		// Was this call to DeleteAllL an instruction to delete local parts of a message ?
       
   359 		// If so then we don't need to continue. PruneMessages will complete the outstanding request.
       
   360 		return;
       
   361 		}
       
   362 	
       
   363 	// Not a prune of local messages. 
       
   364 	// Is the first entry a message or a folder?			
       
   365 	User::LeaveIfError(iServerEntry->SetEntry(aSelection[0]));
       
   366 
       
   367 	if (iServerEntry->Entry().iType==KUidMsvMessageEntry)
       
   368 		{
       
   369 		if (!iImapProtocolController->Connected())
       
   370 			{
       
   371 			iState = EMtmStateOffLineDelete;
       
   372 			CImapOfflineControl::TImap4OpType opType=CImapOfflineControl::EImap4OpDelete;
       
   373 			iImapOfflineControl->StoreOfflineCommandL(opType, aSelection,  KMsvNullIndexEntryId, iStatus);
       
   374 			}
       
   375 		else
       
   376 			{
       
   377 			iState = EMtmStateDelete;
       
   378 			iImapProtocolController->DeleteL(iStatus, aSelection);
       
   379 			}
       
   380 		}
       
   381 	else if (iServerEntry->Entry().iType==KUidMsvFolderEntry)
       
   382 		{
       
   383 		// no offline support for delete folder
       
   384 		if (!iImapProtocolController->Connected())
       
   385 			{
       
   386 			Queue(aStatus);
       
   387 			User::RequestComplete(iRequest, KErrDisconnected);
       
   388 			return;
       
   389 			}
       
   390 		else
       
   391 			{
       
   392 			iState = EMtmStateDeleteFolder;
       
   393 			iImapProtocolController->DeleteFolderL(iStatus, aSelection);
       
   394 			}
       
   395 		}
       
   396 	else
       
   397 		{
       
   398 		TImapServerPanic::ImapPanic(TImapServerPanic::EDeleteOfUnknownType);
       
   399 		}
       
   400 	Queue(aStatus);
       
   401 	SetActive();
       
   402 	}
       
   403 
       
   404 /**
       
   405 Create: make a folder or mailbox.
       
   406 Only supported when online.
       
   407 
       
   408 @param aNewEntry The Details of the folder or mailbox to be created.
       
   409 @param aStatus The request status to be completed when the operation has finished.
       
   410 */
       
   411 void CImap4ServerMtm::CreateL( TMsvEntry aNewEntry,
       
   412 							   TRequestStatus& aStatus )
       
   413 	{
       
   414 	__LOG_TEXT(KDefaultLog, "CImap4ServerMtm::CreateL()");
       
   415 	
       
   416 	// Creating a folder?
       
   417 	if (aNewEntry.iType!=KUidMsvFolderEntry)
       
   418 		{
       
   419 		// No - illegal op
       
   420 		Queue(aStatus);
       
   421 		User::RequestComplete(iRequest, KErrNotSupported);
       
   422 		return;
       
   423 		}
       
   424 
       
   425 	// Not supported as an offline operation
       
   426 	if (!iImapProtocolController->Connected())
       
   427 		{
       
   428 		Queue(aStatus);
       
   429 		User::RequestComplete(iRequest, KErrDisconnected);
       
   430 		return;
       
   431 		}
       
   432 
       
   433 	TBool isfolder = ETrue;
       
   434 	if ( ((TMsvEmailEntry)aNewEntry).Mailbox() )
       
   435 		{
       
   436 		isfolder = EFalse;
       
   437 		}
       
   438 		
       
   439 	iImapProtocolController->CreateL(iStatus, aNewEntry.Parent(), aNewEntry.iDetails, isfolder);
       
   440 	iState = EMtmStateCreateFolder;
       
   441 	Queue(aStatus);
       
   442 	SetActive();
       
   443 	}
       
   444 	
       
   445 /**
       
   446 This command has been recinded, and is replaced by IMAP Client MTM command 
       
   447 KIMAP4MTMRenameFolder
       
   448 
       
   449 This command has been recinded,
       
   450 and is replaced by IMAP Client MTM command KIMAP4MTMRenameFolder
       
   451 		 
       
   452 @param aNewEntry The Details of the folder or mailbox to be renamed.
       
   453 @param aStatus The request status to be completed when the operation has finished.
       
   454 */
       
   455 void CImap4ServerMtm::ChangeL( TMsvEntry aNewEntry, TRequestStatus& aStatus ) 
       
   456 	{
       
   457 	__LOG_TEXT(KDefaultLog, "CImap4ServerMtm::ChangeL()");
       
   458 	
       
   459 	TMsvEmailEntry origEntry = iServerEntry->Entry();
       
   460 	TMsvEntry *newEntry1 = new (ELeave) TMsvEntry;
       
   461 	CleanupStack::PushL(newEntry1);
       
   462 	TMsvEmailEntry newEntry = (TMsvEmailEntry) aNewEntry;
       
   463 	TMsvEmailEntry *newEntry2= new (ELeave) TMsvEmailEntry();
       
   464 	CleanupStack::PushL(newEntry2);
       
   465 	
       
   466 	if(origEntry.Id() != aNewEntry.Id())
       
   467 		{
       
   468 		iServerEntry->GetEntryFromId(aNewEntry.Id(), newEntry1);
       
   469 		newEntry2 = (TMsvEmailEntry*) newEntry1;
       
   470 		origEntry = newEntry;
       
   471 		}
       
   472 	else
       
   473 		{
       
   474 		newEntry2 = &newEntry;
       
   475 		}
       
   476 	TBool flagChanged = EFalse;
       
   477 	if((origEntry.SeenIMAP4Flag()!= newEntry2->SeenIMAP4Flag())
       
   478 	 || (origEntry.UnreadIMAP4Flag()!=newEntry2->UnreadIMAP4Flag())
       
   479 	 || (origEntry.Unread()!=newEntry2->Unread())
       
   480 	 || (origEntry.New()!=newEntry2->New()))
       
   481 		{	
       
   482 		flagChanged = ETrue;
       
   483 		}
       
   484 		
       
   485 	User::LeaveIfError(iServerEntry->SetEntry(aNewEntry.Id()));
       
   486 	User::LeaveIfError(iServerEntry->ChangeEntry(aNewEntry));
       
   487 
       
   488 	//if not offline
       
   489 	if (iImapProtocolController->Connected() && flagChanged)
       
   490 		{
       
   491 		//to update read/unread flags at remote server
       
   492 		iImapProtocolController->UpdateFlagL(iStatus);	
       
   493   	 	iState= EMtmStateUpdateFlag;
       
   494   	 	Queue(aStatus);
       
   495 		SetActive();	
       
   496 		}
       
   497 	else
       
   498 		{
       
   499 		Queue(aStatus);
       
   500 		User::RequestComplete(iRequest, KErrNone);
       
   501 		}
       
   502 	CleanupStack::PopAndDestroy(2);
       
   503 	}
       
   504 
       
   505 
       
   506 /**
       
   507 Performs the IMAP specific MTM commands.
       
   508 
       
   509 @param aSelection A selection of messages. The use is dependant upon 
       
   510 	   the command specified by aFunctionID. 
       
   511 @param aCommand Specifies which operation to perform e.g. connect, copy new mail 
       
   512 				etc. The specific operations are defined by the TImap4Cmds enumeration. 
       
   513 @param aParameter Use is dependant upon the command specified by aFunctionID 
       
   514 @param aStatus The request status to be completed when the operation has finished.
       
   515 */
       
   516 void CImap4ServerMtm::StartCommandL( CMsvEntrySelection& aSelection, 
       
   517 					    			 TInt aCommand, 
       
   518 									 const TDesC8& aParameter, 
       
   519 									 TRequestStatus& aStatus )
       
   520 	{
       
   521     const TBool connected = iImapProtocolController->Connected();
       
   522     __LOG_FORMAT((KDefaultLog, "CImap4ServerMtm::StartCommandL() - iStatus: %d, iState: %d, aCommand: %d, connected: %d", iStatus.Int(), iState, aCommand, connected));
       
   523 	
       
   524 	// Complete now if offline and no offline support for requested command
       
   525 	if (!connected)
       
   526 		{
       
   527 		if ( aCommand == KIMAP4MTMSynchronise  || aCommand == KIMAP4MTMFullSync ||
       
   528 		 	 aCommand == KIMAP4MTMInboxNewSync || aCommand == KIMAP4MTMFolderFullSync ||
       
   529 		 	 aCommand == KIMAP4MTMRenameFolder || aCommand == KIMAP4MTMDisconnect ||
       
   530 			 aCommand == KIMAP4MTMSyncTree     || aCommand == KIMAP4MTMSelect ||
       
   531 			 aCommand == KIMAP4MTMIsConnected )
       
   532 			{
       
   533 			__LOG_TEXT(KDefaultLog, "     - Online only command requested.");
       
   534 			Queue(aStatus);
       
   535 			User::RequestComplete(iRequest, KErrDisconnected);
       
   536 			return;
       
   537 			}
       
   538 		}
       
   539 		
       
   540 	// change to false if an asynchronous request is issued.
       
   541     TBool complete = ETrue;
       
   542     iState = EMtmStateMiscCommand;
       
   543     
       
   544     switch (aCommand)
       
   545 		{
       
   546 	case KIMAP4MTMIsConnected:
       
   547 		{
       
   548 		__LOG_TEXT(KDefaultLog, "     -  KIMAP4MTMIsConnected");
       
   549 		// Completes the requesting client immediately with KErrNone (when a
       
   550 		// session is connected) or KErrDisconnected otherwise.
       
   551 		if (iImapProtocolController->Connected())
       
   552 			{
       
   553 			Queue(aStatus);
       
   554 			User::RequestComplete(iRequest, KErrNone);
       
   555 			}
       
   556 		else
       
   557 			{
       
   558 			Queue(aStatus);
       
   559 			User::RequestComplete(iRequest, KErrDisconnected);
       
   560 			}
       
   561 		
       
   562 		break;
       
   563 		}
       
   564 		
       
   565 	case KIMAP4MTMBusy:
       
   566 		{
       
   567 		__LOG_TEXT(KDefaultLog, "     -  KIMAP4MTMBusy");
       
   568 		// Completes immediately with KErrServerBusy if a background sync is
       
   569 		// in progress or second session is busy (this implies that all connected
       
   570 		// sessions are busy).
       
   571 		if (iImapProtocolController->Busy())
       
   572 			{
       
   573 			Queue(aStatus);
       
   574 			User::RequestComplete(iRequest, KErrServerBusy);
       
   575 			}
       
   576 		else
       
   577 			{
       
   578 			Queue(aStatus);
       
   579 			User::RequestComplete(iRequest, KErrNone);
       
   580 			}
       
   581 		break;	
       
   582 		}
       
   583 
       
   584 	case KIMAP4MTMConnect:
       
   585 		{
       
   586 		__LOG_TEXT(KDefaultLog, "     -  KIMAP4MTMConnect");
       
   587 		// Completes with KErrServerBusy if already connected, otherwise 
       
   588 		// establishes a connected IMAP session.
       
   589 		if (iImapProtocolController->Connected())
       
   590 			{
       
   591 			Queue(aStatus);
       
   592 			User::RequestComplete(iRequest, KErrServerBusy);
       
   593 			}
       
   594 		else
       
   595 			{
       
   596 #if (defined SYMBIAN_USER_PROMPT_SERVICE)			
       
   597 			iState = EMtmStateAuthoriseConnection;
       
   598 			iWaiter->AuthoriseAndConnectL(aSelection, aCommand, iClientThreadId, iHasCapability, iStatus);
       
   599 #else			
       
   600 			iImapProtocolController->ConnectL(iStatus, aSelection);
       
   601 			iState = EMtmStatePrimaryConnect;
       
   602 #endif			
       
   603 			complete = EFalse;
       
   604 			}
       
   605 		break;
       
   606 		}
       
   607 		
       
   608 	case KIMAP4MTMConnectAndSynchronise:
       
   609 		{
       
   610 		__LOG_TEXT(KDefaultLog, "     -  KIMAP4MTMConnectAndSynchronise");
       
   611 		// Completes with KErrServerBusy if already connected, otherwise
       
   612 		// establishes a connected IMAP session.
       
   613 
       
   614 		// The Protocol Controller will start the synchronise operation as
       
   615 		// a background operation on completion of the connect operation.
       
   616 		
       
   617 		if (iImapProtocolController->Connected())
       
   618 			{
       
   619 			Queue(aStatus);
       
   620 			User::RequestComplete(iRequest, KErrServerBusy);
       
   621 			}
       
   622 		else
       
   623 			{
       
   624 #if (defined SYMBIAN_USER_PROMPT_SERVICE)			
       
   625 			iState = EMtmStateAuthoriseConnection;
       
   626 			iWaiter->AuthoriseAndConnectL(aSelection, aCommand, iClientThreadId, iHasCapability, iStatus);
       
   627 #else			
       
   628 			iImapProtocolController->ConnectAndSynchroniseL(iStatus, aSelection);
       
   629 #endif			
       
   630 			complete = EFalse;
       
   631 			}
       
   632 		break;
       
   633 		}
       
   634 
       
   635 	case KIMAP4MTMStartBatch:
       
   636 		{
       
   637 		__LOG_TEXT(KDefaultLog, "     -  KIMAP4MTMStartBatch");
       
   638 		// Batch mode enables the client to declare that it is about to send a
       
   639 		// sequence of commands. While in batch mode the IMAP Server MTM ensures
       
   640 		// that it remains loaded by returning ETrue when the CommandExpected()
       
   641 		// function is called by the messaging server.
       
   642 		iBatchInProgress = ETrue;
       
   643 		Queue(aStatus);
       
   644 		User::RequestComplete(iRequest, KErrNone);
       
   645 		break;
       
   646 		}
       
   647 		
       
   648 	case KIMAP4MTMEndBatch:
       
   649 		{
       
   650 		__LOG_TEXT(KDefaultLog, "     -  KIMAP4MTMEndBatch");
       
   651 		iBatchInProgress = EFalse;
       
   652 		Queue(aStatus);
       
   653 		User::RequestComplete(iRequest, KErrNone);
       
   654 		break;
       
   655 		}
       
   656 		
       
   657 	case KIMAP4MTMCancelBackgroundSynchronise :
       
   658 		{
       
   659 		__LOG_TEXT(KDefaultLog, "     -  KIMAP4MTMCancelBackgroundSynchronise");
       
   660 		// Enables the client to cancel an ongoing background synchronisation
       
   661 		// process.
       
   662 		iImapProtocolController->CancelBackgroundSync(iStatus);
       
   663 		complete = EFalse;
       
   664 		break;
       
   665 		}
       
   666 		
       
   667 	case KIMAP4MTMSelect:
       
   668 		{
       
   669 		__LOG_TEXT(KDefaultLog, "     -  KIMAP4MTMSelect");
       
   670 		// This command allows the client to issue a SELECT command for the
       
   671 		// specified mailbox.
       
   672 		iImapProtocolController->SelectL(iStatus, aSelection[0]);
       
   673 		complete = EFalse;
       
   674 		break;
       
   675 		}
       
   676 		
       
   677 	case KIMAP4MTMSynchronise:
       
   678 		{
       
   679 		__LOG_TEXT(KDefaultLog, "     -  KIMAP4MTMSynchronise");
       
   680 		// Synchronises the currently selected folder. 
       
   681 		iImapProtocolController->FullSyncSelectedFolderL(iStatus);
       
   682 		complete = EFalse;
       
   683 		break;
       
   684 		}
       
   685 		
       
   686 	case KIMAP4MTMSyncTree:
       
   687 		{
       
   688 		__LOG_TEXT(KDefaultLog, "     -  KIMAP4MTMSyncTree");
       
   689 		// Synchronises the remote and mirror folder tree. This operation is
       
   690 		// handled by the Sync Manager, via method
       
   691 		// CImapProtocolController::SynchroniseTreeL()
       
   692 		iImapProtocolController->SynchroniseTreeL(iStatus);
       
   693 		complete = EFalse;
       
   694 		break;
       
   695 		}
       
   696 		
       
   697 	case KIMAP4MTMLocalSubscribe:
       
   698 		{
       
   699 		__LOG_TEXT(KDefaultLog, "     -  KIMAP4MTMLocalSubscribe");
       
   700 		// Completes synchronously, having set the subscribed flag on the TMsvEntry 
       
   701 		// identified.
       
   702 		TInt err = iImapProtocolController->SetLocalSubscription(aSelection[0], ETrue);
       
   703 		Queue(aStatus);
       
   704 		User::RequestComplete(iRequest, err);
       
   705 		break;
       
   706 		}
       
   707 		
       
   708 	case KIMAP4MTMLocalUnsubscribe:
       
   709 		{
       
   710 		__LOG_TEXT(KDefaultLog, "     -  KIMAP4MTMLocalUnsubscribe");
       
   711 		// Completes synchronously, having cleared the subscribed flag for the
       
   712 		// specified folder. Also sets the invisible flag for the folder if it
       
   713 		// contains no subscribed subfolders, and the parent folder with the
       
   714 		// same test.
       
   715 		TInt err = iImapProtocolController->SetLocalSubscription(aSelection[0], EFalse);
       
   716 		Queue(aStatus);
       
   717 		User::RequestComplete(iRequest, err);
       
   718 		break;
       
   719 		}
       
   720 		
       
   721 	case KIMAP4MTMFullSync:
       
   722 		{
       
   723 		__LOG_TEXT(KDefaultLog, "     -  KIMAP4MTMFullSync");
       
   724 		// This command initiates a full foreground sync. Cannot be performed if a 
       
   725 		// background sync is already in progress. The steps performed to perform
       
   726 		// the complete synchronisation process is managed by the IMAP Sync Manager, 
       
   727 		// CImapSyncManager::SynchroniseL(), via a call to 
       
   728 		// CProtocolController::SynchroniseAllL()
       
   729 		iState = EMtmStateForegroundSync;
       
   730 		iImapProtocolController->SynchroniseAllL( iStatus );
       
   731 		complete = EFalse;
       
   732 		break;
       
   733 		}
       
   734 		
       
   735 	case KIMAP4MTMPopulate:
       
   736 		{
       
   737 		__LOG_TEXT(KDefaultLog, "     -  KIMAP4MTMPopulate");
       
   738 		// This command is used to fetch specified parts of the identified
       
   739 		// message to the local mirror folder. The parts to fetch and body size
       
   740 		// limits are specified by a passed TImImap4GetPartialMailInfo object
       
   741 		TImImap4GetPartialMailInfo imap4GetPartialMailInfo;	
       
   742  		if (aParameter.Length() > 0)
       
   743 			{
       
   744 			TPckgC<TImImap4GetPartialMailInfo> paramPartialPack(imap4GetPartialMailInfo);
       
   745 			paramPartialPack.Set(aParameter);
       
   746 			imap4GetPartialMailInfo = paramPartialPack();
       
   747 			}
       
   748 			
       
   749 		if (!iImapProtocolController->Connected())
       
   750 			{
       
   751 			iState = EMtmStateOffLinePopulate;
       
   752 			CImapOfflineControl::TImap4OpType opType=CImapOfflineControl::EImap4OpPopulate;
       
   753 			TPckgBuf<TImImap4GetPartialMailInfo> package(imap4GetPartialMailInfo);
       
   754             iImapOfflineControl->StoreOfflineCommandL(opType, aSelection, KMsvNullIndexEntryId, package, iStatus);
       
   755             complete = EFalse;
       
   756 			}
       
   757 		else
       
   758 			{
       
   759 			iState = EMtmStatePopulate;
       
   760 	        __LOG_FORMAT((KDefaultLog, "     -   pre-iStatus: %d", iStatus.Int()));
       
   761 			iImapProtocolController->PopulateL(iStatus, aSelection, imap4GetPartialMailInfo);
       
   762 	        __LOG_FORMAT((KDefaultLog, "     -  post-iStatus: %d", iStatus.Int()));
       
   763 			complete = EFalse;
       
   764 			}	
       
   765 		break;
       
   766 		}
       
   767 		
       
   768 	case KIMAP4MTMInboxNewSync:
       
   769 		{
       
   770 		__LOG_TEXT(KDefaultLog, "     -  KIMAP4MTMInboxNewSync");
       
   771 		// Performs synchronisation of messages received by the remote server
       
   772 		// Inbox since the last synchronisation operation.
       
   773 		iState = EMtmStateForegroundSync;
       
   774 		iImapProtocolController->NewOnlySyncFolderL( iStatus );
       
   775 		complete = EFalse;			
       
   776 		break;
       
   777 		}
       
   778 		
       
   779 	case KIMAP4MTMFolderFullSync:
       
   780 		{
       
   781 		__LOG_TEXT(KDefaultLog, "     -  KIMAP4MTMFolderFullSync");
       
   782 		// Performs a full synchronisation of the folder identified in aSelection[0].
       
   783 		iState = EMtmStateForegroundSync;
       
   784 		iImapProtocolController->FullSyncFolderL(iStatus, aSelection[0]);
       
   785 		complete = EFalse;
       
   786 		break;
       
   787 		}
       
   788 		
       
   789 	case KIMAP4MTMWaitForBackground:
       
   790 		{
       
   791 		__LOG_TEXT(KDefaultLog, "     -  KIMAP4MTMWaitForBackground");
       
   792 		// This effectively makes a background sync a foreground operation, by 
       
   793 		// requesting completion when an outstanding background synchronisation 
       
   794 		// operation completes. 
       
   795 		// If no background sync is in progress, this completes immediately with 
       
   796 		// KErrNone.
       
   797 		iState = EMtmStateWaitingForBackgroundToFinish;
       
   798 		iImapProtocolController->WaitForBackground(iStatus);
       
   799 		complete = EFalse;
       
   800 		break;
       
   801 		}
       
   802 		
       
   803 	case KIMAP4MTMDisconnect:
       
   804 		{
       
   805 		__LOG_TEXT(KDefaultLog, "     -  KIMAP4MTMDisconnect");
       
   806 		// Issues a disconnect to all connected IMAP sessions.
       
   807 		// If service settings specify synchronise deletes on disconnect, 
       
   808 		// CImapSyncManager::SynchroniseDeletes() is called to perform outstanding 
       
   809 		// offline delete operations.
       
   810 		iImapProtocolController->DisconnectL(iStatus);
       
   811 		complete = EFalse;
       
   812 		break;
       
   813 		}
       
   814 		
       
   815 	case KIMAP4MTMRenameFolder:
       
   816 		{
       
   817 		__LOG_TEXT(KDefaultLog, "     -  KIMAP4MTMRenameFolder");
       
   818 		// Renames the remote IMAP folder.
       
   819 
       
   820 		// extract the new folder name
       
   821 		TImap4RenameFolder cmd;
       
   822 		TPckgC<TImap4RenameFolder> package(cmd);
       
   823 		package.Set(aParameter);
       
   824 		TImap4RenameFolder rename = package();
       
   825 
       
   826 		// call the rename command
       
   827 		iImapProtocolController->RenameL(iStatus, aSelection[0], rename.iNewName);
       
   828 		iState = EMtmStateRenameFolder;
       
   829 		complete = EFalse;
       
   830 		break;
       
   831 		}
       
   832 		
       
   833 	case KIMAP4MTMUndeleteAll:
       
   834 		{
       
   835 		__LOG_TEXT(KDefaultLog, "     -  KIMAP4MTMUndeleteAll");
       
   836 		// This command allows the client to undo offline delete operations, and
       
   837 		// is handled by the offline command manager
       
   838 		// CImap4OffLineControl::StoreOfflineCommandL(). This command removes 
       
   839 		// the cause of the delete, ie it removes offline delete operations and 
       
   840 		// changes move to copy operations.
       
   841 		iState = EMtmStateOffLineUndelete;
       
   842 		CImapOfflineControl::TImap4OpType opType=CImapOfflineControl::EImap4OpUndelete;
       
   843 		iImapOfflineControl->StoreOfflineCommandL(opType, aSelection,  KMsvNullIndexEntryId, iStatus);
       
   844 		complete = EFalse;
       
   845 		break;
       
   846 		}
       
   847 		
       
   848 	case KIMAP4MTMCancelOffLineOperations:
       
   849 		{
       
   850 		__LOG_TEXT(KDefaultLog, "     -  KIMAP4MTMCancelOffLineOperations");
       
   851 		// This command allows the client to cancel queued offline operations in
       
   852 		// folders specified in aSelection. Note that offline operations that were
       
   853 		// performed while offline cannot be undone by this method. The operation
       
   854 		// array associated with the folder is emptied, and the offline command
       
   855 		// flags in the associated TMsvEmailEntries are cleared.
       
   856 		// CImap4OffLineControl::CancelOffLineOperationsL()
       
   857 		iImapOfflineControl->CancelOffLineOperationsL(aSelection);
       
   858 		Queue(aStatus);
       
   859 		User::RequestComplete(iRequest,KErrNone);
       
   860 		break;
       
   861 		}
       
   862 	default :
       
   863 		{
       
   864 		__LOG_TEXT(KDefaultLog, "     -  Unknown command");
       
   865 		Queue(aStatus);
       
   866 		User::RequestComplete(iRequest, KErrNotSupported);
       
   867 		break;
       
   868 		}
       
   869 		
       
   870 		} // end switch (aCommand)
       
   871 
       
   872 	if (!complete)
       
   873 		{
       
   874 		Queue(aStatus);
       
   875 		SetActive();
       
   876 		}
       
   877 	}
       
   878 
       
   879 /**
       
   880 This is used by the Messaging Server to determine if the MTM can be unloaded.
       
   881 
       
   882 @return true if further client commands are expected.
       
   883 */
       
   884 TBool CImap4ServerMtm::CommandExpected()
       
   885 	{
       
   886 	// ...basically, when we're disconnected we can be deleted
       
   887 	TBool connected = iImapProtocolController->Connected();
       
   888 
       
   889 	__LOG_FORMAT((KDefaultLog, "CommandExpected - Conn %d, Batch %d", connected, iBatchInProgress));
       
   890 
       
   891 	return (connected || iBatchInProgress);
       
   892 	}
       
   893 
       
   894 /**
       
   895 Report progress information back to client. Note that if we do a populate whilst 
       
   896 background syncing (for example) then this will give details of the populate. 
       
   897 If we are only syncing then this will give details about the sync operation.
       
   898 
       
   899 @return
       
   900 */
       
   901 const TDesC8& CImap4ServerMtm::Progress()
       
   902 	{
       
   903 	TImap4CompoundProgress progress;
       
   904 	GetProgress(progress);
       
   905 	iProgressBuffer = TImap4ProgressBuf(progress);
       
   906 
       
   907 	return iProgressBuffer;
       
   908 	}
       
   909 
       
   910 /** 
       
   911 Obtain the progress information
       
   912 @return TImap4CompoundProgress progress structure.
       
   913 */
       
   914 void CImap4ServerMtm::GetProgress(TImap4CompoundProgress& imap4Progress)
       
   915 	{
       
   916 		// Work out which object to get the progress from.
       
   917 	TBool useOffline = EFalse;
       
   918 	switch (iState)
       
   919 		{
       
   920 		case EMtmStateOffLineDelete:
       
   921 		case EMtmStateOffLineUndelete:
       
   922 		case EMtmStateOffLineCopyToLocal:
       
   923 		case EMtmStateOffLineMoveToLocal:
       
   924 		case EMtmStateOffLineCopyFromLocal:
       
   925 		case EMtmStateOffLineMoveFromLocal:
       
   926 		case EMtmStateOffLineCopyWithinService:
       
   927 		case EMtmStateOffLineMoveWithinService:
       
   928 		case EMtmStateOffLinePopulate:
       
   929 			{
       
   930 			useOffline = ETrue;
       
   931 			break;
       
   932 			}
       
   933 		case EMtmStateIdle:
       
   934 			{
       
   935 			useOffline = iLastOpWasOffline;
       
   936 			break;
       
   937 			}	
       
   938 		case EMtmStateCopyToLocal:
       
   939 		case EMtmStateCopyFromLocal:
       
   940 		case EMtmStateCopyWithinService:
       
   941 		case EMtmStateMoveToLocal:
       
   942 		case EMtmStateMoveFromLocal:
       
   943 		case EMtmStateMoveWithinService:
       
   944 		case EMtmStateDelete:
       
   945 		case EMtmStateDeleteFolder:
       
   946 		case EMtmStateCreateFolder:
       
   947 		case EMtmStateRenameFolder:
       
   948 		case EMtmStatePrimaryConnect:
       
   949 		case EMtmStateForegroundSync:
       
   950 		case EMtmStateMiscCommand:
       
   951 		case EMtmStateWaitingForBackgroundToFinish:
       
   952 		case EMtmStatePopulate:
       
   953 		case EMtmStateAuthoriseConnection:
       
   954 		case EMtmStateUpdateFlag:
       
   955 		default:
       
   956 			{
       
   957 			// useOffline remains EFalse
       
   958 			break;
       
   959 			}
       
   960 		} // end of switch (iState)
       
   961 	 
       
   962 	// Get the progress from the appropriate object
       
   963 	imap4Progress = useOffline ? iImapOfflineControl->Progress() 
       
   964 												 : iImapProtocolController->Progress();
       
   965 
       
   966 	__LOG_FORMAT((KDefaultLog, "Progress: GT %d GO %d GS %d GE %d SS %d SE %d",
       
   967 	              imap4Progress.iGenericProgress.iType,
       
   968 	              imap4Progress.iGenericProgress.iOperation,
       
   969 	              imap4Progress.iGenericProgress.iState,
       
   970 	              imap4Progress.iGenericProgress.iErrorCode,
       
   971 	              imap4Progress.iSyncProgress.iState,
       
   972 	              imap4Progress.iSyncProgress.iErrorCode));
       
   973 	}
       
   974 
       
   975 /** 
       
   976 This call leads to calling GetProgress() to populate the
       
   977 TImap4CompoundProgress structure.
       
   978 @param aOutSysProg The TMsvSystemProgress structure to be populated
       
   979 */
       
   980 void CImap4ServerMtm::GetSystemProgress(TMsvSystemProgress& aOutSysProg)
       
   981 	{
       
   982 	TImap4CompoundProgress imap4Progress;
       
   983 	GetProgress(imap4Progress);
       
   984 	aOutSysProg.iErrorCode = imap4Progress.iGenericProgress.iErrorCode;
       
   985 	}
       
   986 
       
   987 /** 
       
   988 The extension method provides a polymorphic behaviour to call the correct
       
   989 MTM.
       
   990 @param aExtensionId The Uid passed in as KUIDMsgMsvSystemProgress to obtain the
       
   991 					System Progress.
       
   992 @return KErrNone if GetSystemProgress is called successfully.
       
   993 */
       
   994 EXPORT_C TInt CImap4ServerMtm::Extension_(TUint aExtensionId, TAny *&a0, TAny *a1)	
       
   995 	{
       
   996 	switch(aExtensionId)
       
   997 		{
       
   998 		case KUIDMsgMsvSystemProgress:
       
   999 			{
       
  1000 			TMsvSystemProgress* systemProgress = reinterpret_cast<TMsvSystemProgress*>(a1);
       
  1001 			GetSystemProgress(*systemProgress);
       
  1002 			return KErrNone;
       
  1003 			}
       
  1004 #if (defined SYMBIAN_USER_PROMPT_SERVICE)			
       
  1005 		case KUIDMsgClientThreadInfo:
       
  1006 			{
       
  1007 			iClientThreadId = *(TThreadId*) (a1);
       
  1008 	    	iHasCapability = (TBool)*(TInt*)(a0);
       
  1009 	    	return KErrNone;
       
  1010 			}
       
  1011 #endif
       
  1012 
       
  1013 		case KUidMsgNonOperationMtmData:
       
  1014 			{
       
  1015 			TNonOperationMtmDataType* mtmDataType = reinterpret_cast<TNonOperationMtmDataType*>(a0);
       
  1016 			TPtrC8* mtmDataBuffer = reinterpret_cast<TPtrC8*>(a1);
       
  1017 			return GetNonOperationMtmData(*mtmDataType, *mtmDataBuffer);
       
  1018 			}
       
  1019 
       
  1020 		default:
       
  1021 			{
       
  1022 			break;
       
  1023 			}
       
  1024 		}
       
  1025 
       
  1026 	//Chain to base class
       
  1027 	return CBaseServerMtm::Extension_(aExtensionId, a0, a1);
       
  1028 	}
       
  1029 
       
  1030 void CImap4ServerMtm::DoCancel()
       
  1031 	{
       
  1032     __LOG_FORMAT( ( KDefaultLog, "CImap4ServerMtm::DoCancel() - START - iState: %d, iRequest: 0x%08x, iStatus: %d, RThread().RequestCount: %d", iState, iRequest, iStatus.Int(), RThread().RequestCount() ) );
       
  1033 
       
  1034 	switch (iState)
       
  1035 		{
       
  1036 	case EMtmStateCopyToLocal:
       
  1037 	case EMtmStateCopyFromLocal:
       
  1038 	case EMtmStateCopyWithinService:
       
  1039 	case EMtmStateMoveToLocal:
       
  1040 	case EMtmStateMoveFromLocal:
       
  1041 	case EMtmStateMoveWithinService:
       
  1042 	case EMtmStateDelete:
       
  1043 	case EMtmStateDeleteFolder:
       
  1044 	case EMtmStateCreateFolder:
       
  1045 	case EMtmStateRenameFolder:
       
  1046 	case EMtmStatePrimaryConnect:
       
  1047 	case EMtmStateForegroundSync:
       
  1048 	case EMtmStateMiscCommand:
       
  1049 	case EMtmStateWaitingForBackgroundToFinish:
       
  1050 	case EMtmStatePopulate:
       
  1051 	case EMtmStateUpdateFlag:
       
  1052 		{
       
  1053 		// online requests done by the protocol controller
       
  1054         __LOG_FORMAT( ( KDefaultLog, "CImap4ServerMtm::DoCancel() - about to CancelAndCleanup() - iStatus: %d, RThread().RequestCount: %d", iStatus.Int(), RThread().RequestCount() ) );
       
  1055 		iImapProtocolController->CancelAndCleanup();
       
  1056         __LOG_FORMAT( ( KDefaultLog, "CImap4ServerMtm::DoCancel() - done CancelAndCleanup() - iStatus: %d, RThread().RequestCount: %d", iStatus.Int(), RThread().RequestCount() ) );
       
  1057 		break;
       
  1058 		}
       
  1059 #if (defined SYMBIAN_USER_PROMPT_SERVICE)		
       
  1060 	case EMtmStateAuthoriseConnection:
       
  1061 		{
       
  1062 		iWaiter->Cancel();
       
  1063 		break;
       
  1064 		}
       
  1065 #endif		
       
  1066 	case EMtmStateOffLineDelete:
       
  1067 	case EMtmStateOffLineUndelete:
       
  1068 	case EMtmStateOffLineCopyToLocal:
       
  1069 	case EMtmStateOffLineMoveToLocal:
       
  1070 	case EMtmStateOffLineCopyFromLocal:
       
  1071 	case EMtmStateOffLineMoveFromLocal:
       
  1072 	case EMtmStateOffLineCopyWithinService:
       
  1073 	case EMtmStateOffLineMoveWithinService:
       
  1074 	case EMtmStateOffLinePopulate:
       
  1075 		{
       
  1076 		// ofline requests done by the offline controller
       
  1077 		iImapOfflineControl->Cancel();
       
  1078 		break;
       
  1079 		}
       
  1080 	case EMtmStateIdle:
       
  1081 	default:
       
  1082 		{
       
  1083 		// no outstanding requests to cancel.
       
  1084 		break;
       
  1085 		}
       
  1086 		} // end of switch (iState)
       
  1087 	
       
  1088 	if (iRequest)
       
  1089 		{
       
  1090 	    __LOG_FORMAT( ( KDefaultLog, "CImap4ServerMtm::DoCancel() - about to complete iRequest: 0x%08x with KErrCancel", iRequest ) );
       
  1091 		User::RequestComplete(iRequest, KErrCancel);
       
  1092 		}
       
  1093     else
       
  1094         {
       
  1095     	__LOG_TEXT(KDefaultLog, "CImap4ServerMtm::DoCancel() - ** NO REQUEST TO COMPLETE **");
       
  1096         }
       
  1097 
       
  1098     __LOG_FORMAT( ( KDefaultLog, "CImap4ServerMtm::DoCancel() - END - iState: %d, iStatus: %d, RThread().RequestCount: %d", iState, iStatus.Int(), RThread().RequestCount() ) );
       
  1099 	}
       
  1100 
       
  1101 /** 
       
  1102 Called on completion of an asynchronous service request
       
  1103 */
       
  1104 void CImap4ServerMtm::DoRunL()
       
  1105 	{
       
  1106 	__LOG_TEXT(KDefaultLog, "CImap4ServerMtm::DoRunL()");
       
  1107 	
       
  1108 	// Was the last operation offline?
       
  1109 	switch (iState)
       
  1110 		{
       
  1111 		case EMtmStateOffLineDelete:
       
  1112 		case EMtmStateOffLineUndelete:
       
  1113 		case EMtmStateOffLineCopyToLocal:
       
  1114 		case EMtmStateOffLineMoveToLocal:
       
  1115 		case EMtmStateOffLineCopyFromLocal:
       
  1116 		case EMtmStateOffLineMoveFromLocal:
       
  1117 		case EMtmStateOffLineCopyWithinService:
       
  1118 		case EMtmStateOffLineMoveWithinService:
       
  1119 		case EMtmStateOffLinePopulate:
       
  1120 			{
       
  1121 			iLastOpWasOffline = ETrue;
       
  1122 			break;
       
  1123 			}
       
  1124 		case EMtmStateIdle:
       
  1125 		case EMtmStateCopyToLocal:
       
  1126 		case EMtmStateCopyFromLocal:
       
  1127 		case EMtmStateCopyWithinService:
       
  1128 		case EMtmStateMoveToLocal:
       
  1129 		case EMtmStateMoveFromLocal:
       
  1130 		case EMtmStateMoveWithinService:
       
  1131 		case EMtmStateDelete:
       
  1132 		case EMtmStateDeleteFolder:
       
  1133 		case EMtmStateCreateFolder:
       
  1134 		case EMtmStateRenameFolder:
       
  1135 		case EMtmStatePrimaryConnect:
       
  1136 		case EMtmStateForegroundSync:
       
  1137 		case EMtmStateMiscCommand:
       
  1138 		case EMtmStateWaitingForBackgroundToFinish:
       
  1139 		case EMtmStatePopulate:
       
  1140 		case EMtmStateAuthoriseConnection:
       
  1141 		case EMtmStateUpdateFlag:
       
  1142 		default:
       
  1143 			{
       
  1144 			iLastOpWasOffline = EFalse;
       
  1145 			break;
       
  1146 			}
       
  1147 		} // end of switch (iState)
       
  1148 	
       
  1149 	iState = EMtmStateIdle;
       
  1150 	User::RequestComplete(iRequest, iStatus.Int());
       
  1151 	}
       
  1152 
       
  1153 /** 
       
  1154 Called if a leave occurs in DoRunL
       
  1155 */
       
  1156 void CImap4ServerMtm::DoComplete(TInt aError)
       
  1157 	{
       
  1158 	__LOG_TEXT(KDefaultLog, "CImap4ServerMtm::DoComplete()");
       
  1159 
       
  1160 	// Park entry
       
  1161 	iServerEntry->SetEntry(KMsvNullIndexEntryId);
       
  1162 	if (iRequest)
       
  1163 		{
       
  1164 		User::RequestComplete(iRequest, aError);
       
  1165 		}
       
  1166 	}
       
  1167 
       
  1168 /**
       
  1169 Call this last when an asynch operation has been requested
       
  1170 @param aStatus The request status to be completed when the operation has finished.
       
  1171 */
       
  1172 void CImap4ServerMtm::Queue(TRequestStatus& aStatus)
       
  1173     {
       
  1174 	 __ASSERT_DEBUG(iRequest==NULL, User::Invariant());
       
  1175 
       
  1176 	aStatus=KRequestPending;
       
  1177 	iRequest=&aStatus;
       
  1178 	}
       
  1179 
       
  1180 /**
       
  1181 Removes all message body parts that are in the selection from the message store 
       
  1182 without removing the headers.
       
  1183 @param aSelection The selection that is pruned
       
  1184 */
       
  1185 TBool CImap4ServerMtm::PruneMessages(const CMsvEntrySelection& aSelection, TRequestStatus& aStatus)
       
  1186 	{
       
  1187 	TInt index = aSelection.Count();
       
  1188 	
       
  1189 	// See if the parent of the first entry is a message.
       
  1190 	// If it is then we need to prune the entries, ie. delete them locally.
       
  1191 	if (index == 0)
       
  1192 		{
       
  1193 		return EFalse;
       
  1194 		}
       
  1195 
       
  1196 	TInt err = iServerEntry->SetEntry(aSelection[0]);
       
  1197 
       
  1198 	if (err == KErrNone)
       
  1199 		{
       
  1200 		err = iServerEntry->SetEntry(iServerEntry->Entry().Parent());
       
  1201 		if (KUidMsvMessageEntry != iServerEntry->Entry().iType)
       
  1202 			{
       
  1203 			// The parent of the given entry was not a message, so we don't prune it.
       
  1204 			return EFalse;
       
  1205 			}
       
  1206 		}
       
  1207 
       
  1208 	while ((index--) && (err==KErrNone))
       
  1209 		{
       
  1210 		// Go to the required entry
       
  1211 		err = iServerEntry->SetEntry(aSelection[index]);
       
  1212 
       
  1213 		if (KErrNone == err)
       
  1214 			{
       
  1215 			// Go to the parent entry to see if it is a message entry
       
  1216 			iServerEntry->SetEntry(iServerEntry->Entry().Parent());
       
  1217 			TMsvEmailEntry entry = iServerEntry->Entry();
       
  1218 
       
  1219 			// Clear the complete flag because we are about to delete the child parts.
       
  1220 			entry.SetComplete(EFalse);
       
  1221 			entry.SetBodyTextComplete(EFalse);
       
  1222 			err = iServerEntry->ChangeEntry(entry);
       
  1223 
       
  1224 			if (KErrNone == err)
       
  1225 				{
       
  1226 				// Delete the body of the message.
       
  1227 				iServerEntry->DeleteEntry(aSelection[index]);
       
  1228 				}
       
  1229 			}
       
  1230 		}
       
  1231 
       
  1232 	Queue(aStatus);
       
  1233 	User::RequestComplete(iRequest, err);
       
  1234 
       
  1235 	return ETrue;
       
  1236 	}
       
  1237 
       
  1238 /**
       
  1239 Gets MTM information that is not related to the current operation
       
  1240 
       
  1241 @param aMtmDataType Type of data to fetch
       
  1242 @param aMtmDataBuffer On return this points to a descriptor holding the data
       
  1243 
       
  1244 @return KErrNone if successful, or a system wide error code
       
  1245 */
       
  1246 TInt CImap4ServerMtm::GetNonOperationMtmData(TNonOperationMtmDataType aMtmDataType, TPtrC8& aMtmDataBuffer)
       
  1247 	{
       
  1248 	if (aMtmDataType == EMtmDataAccessPointId)
       
  1249 		{
       
  1250 		TNonOperationMtmDataAccessPointId mtmDataAccessPointId;
       
  1251 		
       
  1252 		TInt err = iImapProtocolController->GetAccessPointIdForConnection(mtmDataAccessPointId.iAccessPointId);
       
  1253 
       
  1254 		if (err == KErrNone)
       
  1255 			{
       
  1256 			iMtmDataAccessPointIdBuffer = TNonOperationMtmDataAccessPointIdBuffer(mtmDataAccessPointId);
       
  1257 			aMtmDataBuffer.Set(iMtmDataAccessPointIdBuffer);
       
  1258 			return KErrNone;
       
  1259 			}
       
  1260 		
       
  1261 		return KErrNotFound;
       
  1262 		}
       
  1263 	
       
  1264 	return KErrNotSupported;
       
  1265 	}