email/imap4mtm/imapservermtm/src/cimap4servermtm.cpp
changeset 80 8b14b30db193
equal deleted inserted replaced
79:2981cb3aa489 80:8b14b30db193
       
     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 ChangeEntriesL update the message read/Unread status in  Local and remote, 
       
   508 using the IMAP COPY command.
       
   509 
       
   510 @param aSelection The selection of message TMsvIds that are changed.
       
   511 @param aMark The selection marked as read  or unread.If 1 is Unread 0 for read.
       
   512 @param aStatus The request status to be completed when the operation has finished.
       
   513 */
       
   514 
       
   515 TInt CImap4ServerMtm::ChangeEntriesL( const CMsvEntrySelection& aSelection, TInt aMark, TRequestStatus& aStatus ) 
       
   516     {
       
   517     __LOG_TEXT(KDefaultLog, "CImap4ServerMtm::ChangeEntriesL()");
       
   518    
       
   519     TMsvEntry* aNewEntry1 = new (ELeave) TMsvEntry;
       
   520     CleanupStack::PushL(aNewEntry1);
       
   521     
       
   522     TBool flagChanged;
       
   523     
       
   524     if(aMark ==  0) 
       
   525         flagChanged = EFalse; //Selection to update as Read.
       
   526     else
       
   527         flagChanged = ETrue; ////Selection to update as UnRead.
       
   528     
       
   529     TInt count  = aSelection.Count();
       
   530     while(count--)
       
   531         { 
       
   532         iServerEntry->GetEntryFromId(aSelection[count],aNewEntry1);
       
   533         TMsvEmailEntry entry(*aNewEntry1);
       
   534         if(flagChanged)
       
   535              {
       
   536             entry.SetSeenIMAP4Flag(EFalse);
       
   537              }
       
   538          else
       
   539              {
       
   540              entry.SetSeenIMAP4Flag(ETrue);  
       
   541              }
       
   542         //Local Updation.
       
   543         User::LeaveIfError(iServerEntry->SetEntry(entry.Id()));
       
   544         User::LeaveIfError(iServerEntry->ChangeEntry(entry));
       
   545         }
       
   546      //if not offline
       
   547      if (iImapProtocolController->Connected())
       
   548         {
       
   549         //to update read/unread flags at remote server
       
   550         iImapProtocolController->UpdateEntriesFlagL(iStatus,aSelection,flagChanged);    
       
   551         iState= EMtmStateUpdateFlag;
       
   552         Queue(aStatus);
       
   553         SetActive(); 
       
   554         }
       
   555     else
       
   556         {
       
   557         Queue(aStatus);
       
   558         User::RequestComplete(iRequest, KErrNone);
       
   559         }
       
   560     CleanupStack::PopAndDestroy(1); //aNewEntry1
       
   561 	return KErrNone;
       
   562     }
       
   563 
       
   564 
       
   565 /**
       
   566 Performs the IMAP specific MTM commands.
       
   567 
       
   568 @param aSelection A selection of messages. The use is dependant upon 
       
   569 	   the command specified by aFunctionID. 
       
   570 @param aCommand Specifies which operation to perform e.g. connect, copy new mail 
       
   571 				etc. The specific operations are defined by the TImap4Cmds enumeration. 
       
   572 @param aParameter Use is dependant upon the command specified by aFunctionID 
       
   573 @param aStatus The request status to be completed when the operation has finished.
       
   574 */
       
   575 void CImap4ServerMtm::StartCommandL( CMsvEntrySelection& aSelection, 
       
   576 					    			 TInt aCommand, 
       
   577 									 const TDesC8& aParameter, 
       
   578 									 TRequestStatus& aStatus )
       
   579 	{
       
   580     const TBool connected = iImapProtocolController->Connected();
       
   581     __LOG_FORMAT((KDefaultLog, "CImap4ServerMtm::StartCommandL() - iStatus: %d, iState: %d, aCommand: %d, connected: %d", iStatus.Int(), iState, aCommand, connected));
       
   582 	
       
   583 	// Complete now if offline and no offline support for requested command
       
   584 	if (!connected)
       
   585 		{
       
   586 		if ( aCommand == KIMAP4MTMSynchronise  || aCommand == KIMAP4MTMFullSync ||
       
   587 		 	 aCommand == KIMAP4MTMInboxNewSync || aCommand == KIMAP4MTMFolderFullSync ||
       
   588 		 	 aCommand == KIMAP4MTMRenameFolder || aCommand == KIMAP4MTMDisconnect ||
       
   589 			 aCommand == KIMAP4MTMSyncTree     || aCommand == KIMAP4MTMSelect ||
       
   590 			 aCommand == KIMAP4MTMIsConnected )
       
   591 			{
       
   592 			__LOG_TEXT(KDefaultLog, "     - Online only command requested.");
       
   593 			Queue(aStatus);
       
   594 			User::RequestComplete(iRequest, KErrDisconnected);
       
   595 			return;
       
   596 			}
       
   597 		}
       
   598 		
       
   599 	// change to false if an asynchronous request is issued.
       
   600     TBool complete = ETrue;
       
   601     iState = EMtmStateMiscCommand;
       
   602     
       
   603     switch (aCommand)
       
   604 		{
       
   605 	case KIMAP4MTMIsConnected:
       
   606 		{
       
   607 		__LOG_TEXT(KDefaultLog, "     -  KIMAP4MTMIsConnected");
       
   608 		// Completes the requesting client immediately with KErrNone (when a
       
   609 		// session is connected) or KErrDisconnected otherwise.
       
   610 		if (iImapProtocolController->Connected())
       
   611 			{
       
   612 			Queue(aStatus);
       
   613 			User::RequestComplete(iRequest, KErrNone);
       
   614 			}
       
   615 		else
       
   616 			{
       
   617 			Queue(aStatus);
       
   618 			User::RequestComplete(iRequest, KErrDisconnected);
       
   619 			}
       
   620 		
       
   621 		break;
       
   622 		}
       
   623 		
       
   624 	case KIMAP4MTMBusy:
       
   625 		{
       
   626 		__LOG_TEXT(KDefaultLog, "     -  KIMAP4MTMBusy");
       
   627 		// Completes immediately with KErrServerBusy if a background sync is
       
   628 		// in progress or second session is busy (this implies that all connected
       
   629 		// sessions are busy).
       
   630 		if (iImapProtocolController->Busy())
       
   631 			{
       
   632 			Queue(aStatus);
       
   633 			User::RequestComplete(iRequest, KErrServerBusy);
       
   634 			}
       
   635 		else
       
   636 			{
       
   637 			Queue(aStatus);
       
   638 			User::RequestComplete(iRequest, KErrNone);
       
   639 			}
       
   640 		break;	
       
   641 		}
       
   642 
       
   643 	case KIMAP4MTMConnect:
       
   644 		{
       
   645 		__LOG_TEXT(KDefaultLog, "     -  KIMAP4MTMConnect");
       
   646 		// Completes with KErrServerBusy if already connected, otherwise 
       
   647 		// establishes a connected IMAP session.
       
   648 		if (iImapProtocolController->Connected())
       
   649 			{
       
   650 			Queue(aStatus);
       
   651 			User::RequestComplete(iRequest, KErrServerBusy);
       
   652 			}
       
   653 		else
       
   654 			{
       
   655 #if (defined SYMBIAN_USER_PROMPT_SERVICE)			
       
   656 			iState = EMtmStateAuthoriseConnection;
       
   657 			iWaiter->AuthoriseAndConnectL(aSelection, aCommand, iClientThreadId, iHasCapability, iStatus);
       
   658 #else			
       
   659 			iImapProtocolController->ConnectL(iStatus, aSelection);
       
   660 			iState = EMtmStatePrimaryConnect;
       
   661 #endif			
       
   662 			complete = EFalse;
       
   663 			}
       
   664 		break;
       
   665 		}
       
   666 		
       
   667 	case KIMAP4MTMConnectAndSynchronise:
       
   668 		{
       
   669 		__LOG_TEXT(KDefaultLog, "     -  KIMAP4MTMConnectAndSynchronise");
       
   670 		// Completes with KErrServerBusy if already connected, otherwise
       
   671 		// establishes a connected IMAP session.
       
   672 
       
   673 		// The Protocol Controller will start the synchronise operation as
       
   674 		// a background operation on completion of the connect operation.
       
   675 		
       
   676 		if (iImapProtocolController->Connected())
       
   677 			{
       
   678 			Queue(aStatus);
       
   679 			User::RequestComplete(iRequest, KErrServerBusy);
       
   680 			}
       
   681 		else
       
   682 			{
       
   683 #if (defined SYMBIAN_USER_PROMPT_SERVICE)			
       
   684 			iState = EMtmStateAuthoriseConnection;
       
   685 			iWaiter->AuthoriseAndConnectL(aSelection, aCommand, iClientThreadId, iHasCapability, iStatus);
       
   686 #else			
       
   687 			iImapProtocolController->ConnectAndSynchroniseL(iStatus, aSelection);
       
   688 #endif			
       
   689 			complete = EFalse;
       
   690 			}
       
   691 		break;
       
   692 		}
       
   693 
       
   694 	case KIMAP4MTMStartBatch:
       
   695 		{
       
   696 		__LOG_TEXT(KDefaultLog, "     -  KIMAP4MTMStartBatch");
       
   697 		// Batch mode enables the client to declare that it is about to send a
       
   698 		// sequence of commands. While in batch mode the IMAP Server MTM ensures
       
   699 		// that it remains loaded by returning ETrue when the CommandExpected()
       
   700 		// function is called by the messaging server.
       
   701 		iBatchInProgress = ETrue;
       
   702 		Queue(aStatus);
       
   703 		User::RequestComplete(iRequest, KErrNone);
       
   704 		break;
       
   705 		}
       
   706 		
       
   707 	case KIMAP4MTMEndBatch:
       
   708 		{
       
   709 		__LOG_TEXT(KDefaultLog, "     -  KIMAP4MTMEndBatch");
       
   710 		iBatchInProgress = EFalse;
       
   711 		Queue(aStatus);
       
   712 		User::RequestComplete(iRequest, KErrNone);
       
   713 		break;
       
   714 		}
       
   715 		
       
   716 	case KIMAP4MTMCancelBackgroundSynchronise :
       
   717 		{
       
   718 		__LOG_TEXT(KDefaultLog, "     -  KIMAP4MTMCancelBackgroundSynchronise");
       
   719 		// Enables the client to cancel an ongoing background synchronisation
       
   720 		// process.
       
   721 		iImapProtocolController->CancelBackgroundSync(iStatus);
       
   722 		complete = EFalse;
       
   723 		break;
       
   724 		}
       
   725 		
       
   726 	case KIMAP4MTMSelect:
       
   727 		{
       
   728 		__LOG_TEXT(KDefaultLog, "     -  KIMAP4MTMSelect");
       
   729 		// This command allows the client to issue a SELECT command for the
       
   730 		// specified mailbox.
       
   731 		iImapProtocolController->SelectL(iStatus, aSelection[0]);
       
   732 		complete = EFalse;
       
   733 		break;
       
   734 		}
       
   735 		
       
   736 	case KIMAP4MTMSynchronise:
       
   737 		{
       
   738 		__LOG_TEXT(KDefaultLog, "     -  KIMAP4MTMSynchronise");
       
   739 		// Synchronises the currently selected folder. 
       
   740 		iImapProtocolController->FullSyncSelectedFolderL(iStatus);
       
   741 		complete = EFalse;
       
   742 		break;
       
   743 		}
       
   744 		
       
   745 	case KIMAP4MTMSyncTree:
       
   746 		{
       
   747 		__LOG_TEXT(KDefaultLog, "     -  KIMAP4MTMSyncTree");
       
   748 		// Synchronises the remote and mirror folder tree. This operation is
       
   749 		// handled by the Sync Manager, via method
       
   750 		// CImapProtocolController::SynchroniseTreeL()
       
   751 		iImapProtocolController->SynchroniseTreeL(iStatus);
       
   752 		complete = EFalse;
       
   753 		break;
       
   754 		}
       
   755 		
       
   756 	case KIMAP4MTMLocalSubscribe:
       
   757 		{
       
   758 		__LOG_TEXT(KDefaultLog, "     -  KIMAP4MTMLocalSubscribe");
       
   759 		// Completes synchronously, having set the subscribed flag on the TMsvEntry 
       
   760 		// identified.
       
   761 		TInt err = iImapProtocolController->SetLocalSubscription(aSelection[0], ETrue);
       
   762 		Queue(aStatus);
       
   763 		User::RequestComplete(iRequest, err);
       
   764 		break;
       
   765 		}
       
   766 		
       
   767 	case KIMAP4MTMLocalUnsubscribe:
       
   768 		{
       
   769 		__LOG_TEXT(KDefaultLog, "     -  KIMAP4MTMLocalUnsubscribe");
       
   770 		// Completes synchronously, having cleared the subscribed flag for the
       
   771 		// specified folder. Also sets the invisible flag for the folder if it
       
   772 		// contains no subscribed subfolders, and the parent folder with the
       
   773 		// same test.
       
   774 		TInt err = iImapProtocolController->SetLocalSubscription(aSelection[0], EFalse);
       
   775 		Queue(aStatus);
       
   776 		User::RequestComplete(iRequest, err);
       
   777 		break;
       
   778 		}
       
   779 		
       
   780 	case KIMAP4MTMFullSync:
       
   781 		{
       
   782 		__LOG_TEXT(KDefaultLog, "     -  KIMAP4MTMFullSync");
       
   783 		// This command initiates a full foreground sync. Cannot be performed if a 
       
   784 		// background sync is already in progress. The steps performed to perform
       
   785 		// the complete synchronisation process is managed by the IMAP Sync Manager, 
       
   786 		// CImapSyncManager::SynchroniseL(), via a call to 
       
   787 		// CProtocolController::SynchroniseAllL()
       
   788 		iState = EMtmStateForegroundSync;
       
   789 		iImapProtocolController->SynchroniseAllL( iStatus );
       
   790 		complete = EFalse;
       
   791 		break;
       
   792 		}
       
   793 		
       
   794 	case KIMAP4MTMPopulate:
       
   795 		{
       
   796 		__LOG_TEXT(KDefaultLog, "     -  KIMAP4MTMPopulate");
       
   797 		// This command is used to fetch specified parts of the identified
       
   798 		// message to the local mirror folder. The parts to fetch and body size
       
   799 		// limits are specified by a passed TImImap4GetPartialMailInfo object
       
   800 		TImImap4GetPartialMailInfo imap4GetPartialMailInfo;	
       
   801  		if (aParameter.Length() > 0)
       
   802 			{
       
   803 			TPckgC<TImImap4GetPartialMailInfo> paramPartialPack(imap4GetPartialMailInfo);
       
   804 			paramPartialPack.Set(aParameter);
       
   805 			imap4GetPartialMailInfo = paramPartialPack();
       
   806 			}
       
   807 			
       
   808 		if (!iImapProtocolController->Connected())
       
   809 			{
       
   810 			iState = EMtmStateOffLinePopulate;
       
   811 			CImapOfflineControl::TImap4OpType opType=CImapOfflineControl::EImap4OpPopulate;
       
   812 			TPckgBuf<TImImap4GetPartialMailInfo> package(imap4GetPartialMailInfo);
       
   813             iImapOfflineControl->StoreOfflineCommandL(opType, aSelection, KMsvNullIndexEntryId, package, iStatus);
       
   814             complete = EFalse;
       
   815 			}
       
   816 		else
       
   817 			{
       
   818 			iState = EMtmStatePopulate;
       
   819 	        __LOG_FORMAT((KDefaultLog, "     -   pre-iStatus: %d", iStatus.Int()));
       
   820 			iImapProtocolController->PopulateL(iStatus, aSelection, imap4GetPartialMailInfo);
       
   821 	        __LOG_FORMAT((KDefaultLog, "     -  post-iStatus: %d", iStatus.Int()));
       
   822 			complete = EFalse;
       
   823 			}	
       
   824 		break;
       
   825 		}
       
   826 		
       
   827 	case KIMAP4MTMInboxNewSync:
       
   828 		{
       
   829 		__LOG_TEXT(KDefaultLog, "     -  KIMAP4MTMInboxNewSync");
       
   830 		// Performs synchronisation of messages received by the remote server
       
   831 		// Inbox since the last synchronisation operation.
       
   832 		iState = EMtmStateForegroundSync;
       
   833 		iImapProtocolController->NewOnlySyncFolderL( iStatus );
       
   834 		complete = EFalse;			
       
   835 		break;
       
   836 		}
       
   837 		
       
   838 	case KIMAP4MTMFolderFullSync:
       
   839 		{
       
   840 		__LOG_TEXT(KDefaultLog, "     -  KIMAP4MTMFolderFullSync");
       
   841 		// Performs a full synchronisation of the folder identified in aSelection[0].
       
   842 		iState = EMtmStateForegroundSync;
       
   843 		iImapProtocolController->FullSyncFolderL(iStatus, aSelection[0]);
       
   844 		complete = EFalse;
       
   845 		break;
       
   846 		}
       
   847 		
       
   848 	case KIMAP4MTMWaitForBackground:
       
   849 		{
       
   850 		__LOG_TEXT(KDefaultLog, "     -  KIMAP4MTMWaitForBackground");
       
   851 		// This effectively makes a background sync a foreground operation, by 
       
   852 		// requesting completion when an outstanding background synchronisation 
       
   853 		// operation completes. 
       
   854 		// If no background sync is in progress, this completes immediately with 
       
   855 		// KErrNone.
       
   856 		iState = EMtmStateWaitingForBackgroundToFinish;
       
   857 		iImapProtocolController->WaitForBackground(iStatus);
       
   858 		complete = EFalse;
       
   859 		break;
       
   860 		}
       
   861 		
       
   862 	case KIMAP4MTMDisconnect:
       
   863 		{
       
   864 		__LOG_TEXT(KDefaultLog, "     -  KIMAP4MTMDisconnect");
       
   865 		// Issues a disconnect to all connected IMAP sessions.
       
   866 		// If service settings specify synchronise deletes on disconnect, 
       
   867 		// CImapSyncManager::SynchroniseDeletes() is called to perform outstanding 
       
   868 		// offline delete operations.
       
   869 		iImapProtocolController->DisconnectL(iStatus);
       
   870 		complete = EFalse;
       
   871 		break;
       
   872 		}
       
   873 		
       
   874 	case KIMAP4MTMRenameFolder:
       
   875 		{
       
   876 		__LOG_TEXT(KDefaultLog, "     -  KIMAP4MTMRenameFolder");
       
   877 		// Renames the remote IMAP folder.
       
   878 
       
   879 		// extract the new folder name
       
   880 		TImap4RenameFolder cmd;
       
   881 		TPckgC<TImap4RenameFolder> package(cmd);
       
   882 		package.Set(aParameter);
       
   883 		TImap4RenameFolder rename = package();
       
   884 
       
   885 		// call the rename command
       
   886 		iImapProtocolController->RenameL(iStatus, aSelection[0], rename.iNewName);
       
   887 		iState = EMtmStateRenameFolder;
       
   888 		complete = EFalse;
       
   889 		break;
       
   890 		}
       
   891 		
       
   892 	case KIMAP4MTMUndeleteAll:
       
   893 		{
       
   894 		__LOG_TEXT(KDefaultLog, "     -  KIMAP4MTMUndeleteAll");
       
   895 		// This command allows the client to undo offline delete operations, and
       
   896 		// is handled by the offline command manager
       
   897 		// CImap4OffLineControl::StoreOfflineCommandL(). This command removes 
       
   898 		// the cause of the delete, ie it removes offline delete operations and 
       
   899 		// changes move to copy operations.
       
   900 		iState = EMtmStateOffLineUndelete;
       
   901 		CImapOfflineControl::TImap4OpType opType=CImapOfflineControl::EImap4OpUndelete;
       
   902 		iImapOfflineControl->StoreOfflineCommandL(opType, aSelection,  KMsvNullIndexEntryId, iStatus);
       
   903 		complete = EFalse;
       
   904 		break;
       
   905 		}
       
   906 		
       
   907 	case KIMAP4MTMCancelOffLineOperations:
       
   908 		{
       
   909 		__LOG_TEXT(KDefaultLog, "     -  KIMAP4MTMCancelOffLineOperations");
       
   910 		// This command allows the client to cancel queued offline operations in
       
   911 		// folders specified in aSelection. Note that offline operations that were
       
   912 		// performed while offline cannot be undone by this method. The operation
       
   913 		// array associated with the folder is emptied, and the offline command
       
   914 		// flags in the associated TMsvEmailEntries are cleared.
       
   915 		// CImap4OffLineControl::CancelOffLineOperationsL()
       
   916 		iImapOfflineControl->CancelOffLineOperationsL(aSelection);
       
   917 		Queue(aStatus);
       
   918 		User::RequestComplete(iRequest,KErrNone);
       
   919 		break;
       
   920 		}
       
   921 	default :
       
   922 		{
       
   923 		__LOG_TEXT(KDefaultLog, "     -  Unknown command");
       
   924 		Queue(aStatus);
       
   925 		User::RequestComplete(iRequest, KErrNotSupported);
       
   926 		break;
       
   927 		}
       
   928 		
       
   929 		} // end switch (aCommand)
       
   930 
       
   931 	if (!complete)
       
   932 		{
       
   933 		Queue(aStatus);
       
   934 		SetActive();
       
   935 		}
       
   936 	}
       
   937 
       
   938 /**
       
   939 This is used by the Messaging Server to determine if the MTM can be unloaded.
       
   940 
       
   941 @return true if further client commands are expected.
       
   942 */
       
   943 TBool CImap4ServerMtm::CommandExpected()
       
   944 	{
       
   945 	// ...basically, when we're disconnected we can be deleted
       
   946 	TBool connected = iImapProtocolController->Connected();
       
   947 
       
   948 	__LOG_FORMAT((KDefaultLog, "CommandExpected - Conn %d, Batch %d", connected, iBatchInProgress));
       
   949 
       
   950 	return (connected || iBatchInProgress);
       
   951 	}
       
   952 
       
   953 /**
       
   954 Report progress information back to client. Note that if we do a populate whilst 
       
   955 background syncing (for example) then this will give details of the populate. 
       
   956 If we are only syncing then this will give details about the sync operation.
       
   957 
       
   958 @return
       
   959 */
       
   960 const TDesC8& CImap4ServerMtm::Progress()
       
   961 	{
       
   962 	TImap4CompoundProgress progress;
       
   963 	GetProgress(progress);
       
   964 	iProgressBuffer = TImap4ProgressBuf(progress);
       
   965 
       
   966 	return iProgressBuffer;
       
   967 	}
       
   968 
       
   969 /** 
       
   970 Obtain the progress information
       
   971 @return TImap4CompoundProgress progress structure.
       
   972 */
       
   973 void CImap4ServerMtm::GetProgress(TImap4CompoundProgress& imap4Progress)
       
   974 	{
       
   975 		// Work out which object to get the progress from.
       
   976 	TBool useOffline = EFalse;
       
   977 	switch (iState)
       
   978 		{
       
   979 		case EMtmStateOffLineDelete:
       
   980 		case EMtmStateOffLineUndelete:
       
   981 		case EMtmStateOffLineCopyToLocal:
       
   982 		case EMtmStateOffLineMoveToLocal:
       
   983 		case EMtmStateOffLineCopyFromLocal:
       
   984 		case EMtmStateOffLineMoveFromLocal:
       
   985 		case EMtmStateOffLineCopyWithinService:
       
   986 		case EMtmStateOffLineMoveWithinService:
       
   987 		case EMtmStateOffLinePopulate:
       
   988 			{
       
   989 			useOffline = ETrue;
       
   990 			break;
       
   991 			}
       
   992 		case EMtmStateIdle:
       
   993 			{
       
   994 			useOffline = iLastOpWasOffline;
       
   995 			break;
       
   996 			}	
       
   997 		case EMtmStateCopyToLocal:
       
   998 		case EMtmStateCopyFromLocal:
       
   999 		case EMtmStateCopyWithinService:
       
  1000 		case EMtmStateMoveToLocal:
       
  1001 		case EMtmStateMoveFromLocal:
       
  1002 		case EMtmStateMoveWithinService:
       
  1003 		case EMtmStateDelete:
       
  1004 		case EMtmStateDeleteFolder:
       
  1005 		case EMtmStateCreateFolder:
       
  1006 		case EMtmStateRenameFolder:
       
  1007 		case EMtmStatePrimaryConnect:
       
  1008 		case EMtmStateForegroundSync:
       
  1009 		case EMtmStateMiscCommand:
       
  1010 		case EMtmStateWaitingForBackgroundToFinish:
       
  1011 		case EMtmStatePopulate:
       
  1012 		case EMtmStateAuthoriseConnection:
       
  1013 		case EMtmStateUpdateFlag:
       
  1014 		default:
       
  1015 			{
       
  1016 			// useOffline remains EFalse
       
  1017 			break;
       
  1018 			}
       
  1019 		} // end of switch (iState)
       
  1020 	 
       
  1021 	// Get the progress from the appropriate object
       
  1022 	imap4Progress = useOffline ? iImapOfflineControl->Progress() 
       
  1023 												 : iImapProtocolController->Progress();
       
  1024 
       
  1025 	__LOG_FORMAT((KDefaultLog, "Progress: GT %d GO %d GS %d GE %d SS %d SE %d",
       
  1026 	              imap4Progress.iGenericProgress.iType,
       
  1027 	              imap4Progress.iGenericProgress.iOperation,
       
  1028 	              imap4Progress.iGenericProgress.iState,
       
  1029 	              imap4Progress.iGenericProgress.iErrorCode,
       
  1030 	              imap4Progress.iSyncProgress.iState,
       
  1031 	              imap4Progress.iSyncProgress.iErrorCode));
       
  1032 	}
       
  1033 
       
  1034 /** 
       
  1035 This call leads to calling GetProgress() to populate the
       
  1036 TImap4CompoundProgress structure.
       
  1037 @param aOutSysProg The TMsvSystemProgress structure to be populated
       
  1038 */
       
  1039 void CImap4ServerMtm::GetSystemProgress(TMsvSystemProgress& aOutSysProg)
       
  1040 	{
       
  1041 	TImap4CompoundProgress imap4Progress;
       
  1042 	GetProgress(imap4Progress);
       
  1043 	aOutSysProg.iErrorCode = imap4Progress.iGenericProgress.iErrorCode;
       
  1044 	}
       
  1045 
       
  1046 /** 
       
  1047 The extension method provides a polymorphic behaviour to call the correct
       
  1048 MTM.
       
  1049 @param aExtensionId The Uid passed in as KUIDMsgMsvSystemProgress to obtain the
       
  1050 					System Progress.
       
  1051 @return KErrNone if GetSystemProgress is called successfully.
       
  1052 */
       
  1053 EXPORT_C TInt CImap4ServerMtm::Extension_(TUint aExtensionId, TAny *&a0, TAny *a1)	
       
  1054 	{
       
  1055 	switch(aExtensionId)
       
  1056 		{
       
  1057 		case KUIDMsgMsvSystemProgress:
       
  1058 			{
       
  1059 			TMsvSystemProgress* systemProgress = reinterpret_cast<TMsvSystemProgress*>(a1);
       
  1060 			GetSystemProgress(*systemProgress);
       
  1061 			return KErrNone;
       
  1062 			}
       
  1063 #if (defined SYMBIAN_USER_PROMPT_SERVICE)			
       
  1064 		case KUIDMsgClientThreadInfo:
       
  1065 			{
       
  1066 			iClientThreadId = *(TThreadId*) (a1);
       
  1067 	    	iHasCapability = (TBool)*(TInt*)(a0);
       
  1068 	    	return KErrNone;
       
  1069 			}
       
  1070 #endif
       
  1071 
       
  1072 		case KUidMsgNonOperationMtmData:
       
  1073 			{
       
  1074 			TNonOperationMtmDataType* mtmDataType = reinterpret_cast<TNonOperationMtmDataType*>(a0);
       
  1075 			TPtrC8* mtmDataBuffer = reinterpret_cast<TPtrC8*>(a1);
       
  1076 			return GetNonOperationMtmData(*mtmDataType, *mtmDataBuffer);
       
  1077 			}
       
  1078 
       
  1079 		default:
       
  1080 			{
       
  1081 			break;
       
  1082 			}
       
  1083 		}
       
  1084 
       
  1085 	//Chain to base class
       
  1086 	return CBaseServerMtm::Extension_(aExtensionId, a0, a1);
       
  1087 	}
       
  1088 
       
  1089 void CImap4ServerMtm::DoCancel()
       
  1090 	{
       
  1091     __LOG_FORMAT( ( KDefaultLog, "CImap4ServerMtm::DoCancel() - START - iState: %d, iRequest: 0x%08x, iStatus: %d, RThread().RequestCount: %d", iState, iRequest, iStatus.Int(), RThread().RequestCount() ) );
       
  1092 
       
  1093 	switch (iState)
       
  1094 		{
       
  1095 	case EMtmStateCopyToLocal:
       
  1096 	case EMtmStateCopyFromLocal:
       
  1097 	case EMtmStateCopyWithinService:
       
  1098 	case EMtmStateMoveToLocal:
       
  1099 	case EMtmStateMoveFromLocal:
       
  1100 	case EMtmStateMoveWithinService:
       
  1101 	case EMtmStateDelete:
       
  1102 	case EMtmStateDeleteFolder:
       
  1103 	case EMtmStateCreateFolder:
       
  1104 	case EMtmStateRenameFolder:
       
  1105 	case EMtmStatePrimaryConnect:
       
  1106 	case EMtmStateForegroundSync:
       
  1107 	case EMtmStateMiscCommand:
       
  1108 	case EMtmStateWaitingForBackgroundToFinish:
       
  1109 	case EMtmStatePopulate:
       
  1110 	case EMtmStateUpdateFlag:
       
  1111 		{
       
  1112 		// online requests done by the protocol controller
       
  1113         __LOG_FORMAT( ( KDefaultLog, "CImap4ServerMtm::DoCancel() - about to CancelAndCleanup() - iStatus: %d, RThread().RequestCount: %d", iStatus.Int(), RThread().RequestCount() ) );
       
  1114 		iImapProtocolController->CancelAndCleanup();
       
  1115         __LOG_FORMAT( ( KDefaultLog, "CImap4ServerMtm::DoCancel() - done CancelAndCleanup() - iStatus: %d, RThread().RequestCount: %d", iStatus.Int(), RThread().RequestCount() ) );
       
  1116 		break;
       
  1117 		}
       
  1118 #if (defined SYMBIAN_USER_PROMPT_SERVICE)		
       
  1119 	case EMtmStateAuthoriseConnection:
       
  1120 		{
       
  1121 		iWaiter->Cancel();
       
  1122 		break;
       
  1123 		}
       
  1124 #endif		
       
  1125 	case EMtmStateOffLineDelete:
       
  1126 	case EMtmStateOffLineUndelete:
       
  1127 	case EMtmStateOffLineCopyToLocal:
       
  1128 	case EMtmStateOffLineMoveToLocal:
       
  1129 	case EMtmStateOffLineCopyFromLocal:
       
  1130 	case EMtmStateOffLineMoveFromLocal:
       
  1131 	case EMtmStateOffLineCopyWithinService:
       
  1132 	case EMtmStateOffLineMoveWithinService:
       
  1133 	case EMtmStateOffLinePopulate:
       
  1134 		{
       
  1135 		// ofline requests done by the offline controller
       
  1136 		iImapOfflineControl->Cancel();
       
  1137 		break;
       
  1138 		}
       
  1139 	case EMtmStateIdle:
       
  1140 	default:
       
  1141 		{
       
  1142 		// no outstanding requests to cancel.
       
  1143 		break;
       
  1144 		}
       
  1145 		} // end of switch (iState)
       
  1146 	
       
  1147 	if (iRequest)
       
  1148 		{
       
  1149 	    __LOG_FORMAT( ( KDefaultLog, "CImap4ServerMtm::DoCancel() - about to complete iRequest: 0x%08x with KErrCancel", iRequest ) );
       
  1150 		User::RequestComplete(iRequest, KErrCancel);
       
  1151 		}
       
  1152     else
       
  1153         {
       
  1154     	__LOG_TEXT(KDefaultLog, "CImap4ServerMtm::DoCancel() - ** NO REQUEST TO COMPLETE **");
       
  1155         }
       
  1156 
       
  1157     __LOG_FORMAT( ( KDefaultLog, "CImap4ServerMtm::DoCancel() - END - iState: %d, iStatus: %d, RThread().RequestCount: %d", iState, iStatus.Int(), RThread().RequestCount() ) );
       
  1158 	}
       
  1159 
       
  1160 /** 
       
  1161 Called on completion of an asynchronous service request
       
  1162 */
       
  1163 void CImap4ServerMtm::DoRunL()
       
  1164 	{
       
  1165 	__LOG_TEXT(KDefaultLog, "CImap4ServerMtm::DoRunL()");
       
  1166 	
       
  1167 	// Was the last operation offline?
       
  1168 	switch (iState)
       
  1169 		{
       
  1170 		case EMtmStateOffLineDelete:
       
  1171 		case EMtmStateOffLineUndelete:
       
  1172 		case EMtmStateOffLineCopyToLocal:
       
  1173 		case EMtmStateOffLineMoveToLocal:
       
  1174 		case EMtmStateOffLineCopyFromLocal:
       
  1175 		case EMtmStateOffLineMoveFromLocal:
       
  1176 		case EMtmStateOffLineCopyWithinService:
       
  1177 		case EMtmStateOffLineMoveWithinService:
       
  1178 		case EMtmStateOffLinePopulate:
       
  1179 			{
       
  1180 			iLastOpWasOffline = ETrue;
       
  1181 			break;
       
  1182 			}
       
  1183 		case EMtmStateIdle:
       
  1184 		case EMtmStateCopyToLocal:
       
  1185 		case EMtmStateCopyFromLocal:
       
  1186 		case EMtmStateCopyWithinService:
       
  1187 		case EMtmStateMoveToLocal:
       
  1188 		case EMtmStateMoveFromLocal:
       
  1189 		case EMtmStateMoveWithinService:
       
  1190 		case EMtmStateDelete:
       
  1191 		case EMtmStateDeleteFolder:
       
  1192 		case EMtmStateCreateFolder:
       
  1193 		case EMtmStateRenameFolder:
       
  1194 		case EMtmStatePrimaryConnect:
       
  1195 		case EMtmStateForegroundSync:
       
  1196 		case EMtmStateMiscCommand:
       
  1197 		case EMtmStateWaitingForBackgroundToFinish:
       
  1198 		case EMtmStatePopulate:
       
  1199 		case EMtmStateAuthoriseConnection:
       
  1200 		case EMtmStateUpdateFlag:
       
  1201 		default:
       
  1202 			{
       
  1203 			iLastOpWasOffline = EFalse;
       
  1204 			break;
       
  1205 			}
       
  1206 		} // end of switch (iState)
       
  1207 	
       
  1208 	iState = EMtmStateIdle;
       
  1209 	User::RequestComplete(iRequest, iStatus.Int());
       
  1210 	}
       
  1211 
       
  1212 /** 
       
  1213 Called if a leave occurs in DoRunL
       
  1214 */
       
  1215 void CImap4ServerMtm::DoComplete(TInt aError)
       
  1216 	{
       
  1217 	__LOG_TEXT(KDefaultLog, "CImap4ServerMtm::DoComplete()");
       
  1218 
       
  1219 	// Park entry
       
  1220 	iServerEntry->SetEntry(KMsvNullIndexEntryId);
       
  1221 	if (iRequest)
       
  1222 		{
       
  1223 		User::RequestComplete(iRequest, aError);
       
  1224 		}
       
  1225 	}
       
  1226 
       
  1227 /**
       
  1228 Call this last when an asynch operation has been requested
       
  1229 @param aStatus The request status to be completed when the operation has finished.
       
  1230 */
       
  1231 void CImap4ServerMtm::Queue(TRequestStatus& aStatus)
       
  1232     {
       
  1233 	 __ASSERT_DEBUG(iRequest==NULL, User::Invariant());
       
  1234 
       
  1235 	aStatus=KRequestPending;
       
  1236 	iRequest=&aStatus;
       
  1237 	}
       
  1238 
       
  1239 /**
       
  1240 Removes all message body parts that are in the selection from the message store 
       
  1241 without removing the headers.
       
  1242 @param aSelection The selection that is pruned
       
  1243 */
       
  1244 TBool CImap4ServerMtm::PruneMessages(const CMsvEntrySelection& aSelection, TRequestStatus& aStatus)
       
  1245 	{
       
  1246 	TInt index = aSelection.Count();
       
  1247 	
       
  1248 	// See if the parent of the first entry is a message.
       
  1249 	// If it is then we need to prune the entries, ie. delete them locally.
       
  1250 	if (index == 0)
       
  1251 		{
       
  1252 		return EFalse;
       
  1253 		}
       
  1254 
       
  1255 	TInt err = iServerEntry->SetEntry(aSelection[0]);
       
  1256 
       
  1257 	if (err == KErrNone)
       
  1258 		{
       
  1259 		err = iServerEntry->SetEntry(iServerEntry->Entry().Parent());
       
  1260 		if (KUidMsvMessageEntry != iServerEntry->Entry().iType)
       
  1261 			{
       
  1262 			// The parent of the given entry was not a message, so we don't prune it.
       
  1263 			return EFalse;
       
  1264 			}
       
  1265 		}
       
  1266 
       
  1267 	while ((index--) && (err==KErrNone))
       
  1268 		{
       
  1269 		// Go to the required entry
       
  1270 		err = iServerEntry->SetEntry(aSelection[index]);
       
  1271 
       
  1272 		if (KErrNone == err)
       
  1273 			{
       
  1274 			// Go to the parent entry to see if it is a message entry
       
  1275 			iServerEntry->SetEntry(iServerEntry->Entry().Parent());
       
  1276 			TMsvEmailEntry entry = iServerEntry->Entry();
       
  1277 
       
  1278 			// Clear the complete flag because we are about to delete the child parts.
       
  1279 			entry.SetComplete(EFalse);
       
  1280 			entry.SetBodyTextComplete(EFalse);
       
  1281 			err = iServerEntry->ChangeEntry(entry);
       
  1282 
       
  1283 			if (KErrNone == err)
       
  1284 				{
       
  1285 				// Delete the body of the message.
       
  1286 				iServerEntry->DeleteEntry(aSelection[index]);
       
  1287 				}
       
  1288 			}
       
  1289 		}
       
  1290 
       
  1291 	Queue(aStatus);
       
  1292 	User::RequestComplete(iRequest, err);
       
  1293 
       
  1294 	return ETrue;
       
  1295 	}
       
  1296 
       
  1297 /**
       
  1298 Gets MTM information that is not related to the current operation
       
  1299 
       
  1300 @param aMtmDataType Type of data to fetch
       
  1301 @param aMtmDataBuffer On return this points to a descriptor holding the data
       
  1302 
       
  1303 @return KErrNone if successful, or a system wide error code
       
  1304 */
       
  1305 TInt CImap4ServerMtm::GetNonOperationMtmData(TNonOperationMtmDataType aMtmDataType, TPtrC8& aMtmDataBuffer)
       
  1306 	{
       
  1307 	if (aMtmDataType == EMtmDataAccessPointId)
       
  1308 		{
       
  1309 		TNonOperationMtmDataAccessPointId mtmDataAccessPointId;
       
  1310 		
       
  1311 		TInt err = iImapProtocolController->GetAccessPointIdForConnection(mtmDataAccessPointId.iAccessPointId);
       
  1312 
       
  1313 		if (err == KErrNone)
       
  1314 			{
       
  1315 			iMtmDataAccessPointIdBuffer = TNonOperationMtmDataAccessPointIdBuffer(mtmDataAccessPointId);
       
  1316 			aMtmDataBuffer.Set(iMtmDataAccessPointIdBuffer);
       
  1317 			return KErrNone;
       
  1318 			}
       
  1319 		
       
  1320 		return KErrNotFound;
       
  1321 		}
       
  1322 	
       
  1323 	return KErrNotSupported;
       
  1324 	}