|
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 "cimapcompoundcopywithinservice.h" |
|
17 #include "cimapsessionconsts.h" |
|
18 #include "cimapsyncmanager.h" |
|
19 #include "cimapfolder.h" |
|
20 #include "cimaplogger.h" |
|
21 #include "imappaniccodes.h" |
|
22 |
|
23 #include "mobilitytestmtmapi.h" |
|
24 |
|
25 _LIT8( KMessageDataItem, "+FLAGS" ); |
|
26 _LIT8( KDeleteValue, "\\Deleted" ); |
|
27 |
|
28 CImapCompoundCopyWithinService::CImapCompoundCopyWithinService( CImapSyncManager& aSyncManager, |
|
29 CMsvServerEntry& aServerEntry, |
|
30 CImapSettings& aImapSettings, |
|
31 TBool aIsMove, |
|
32 const TMsvId aDestination ) |
|
33 : CImapCompoundBase(aSyncManager, aServerEntry, aImapSettings), |
|
34 iIsMove(aIsMove), iDestinationId(aDestination) |
|
35 { |
|
36 |
|
37 } |
|
38 |
|
39 CImapCompoundCopyWithinService::~CImapCompoundCopyWithinService() |
|
40 { |
|
41 iOutMessageFlagInfo.Close(); |
|
42 iMessageUids.Reset(); |
|
43 delete iUidSeq; |
|
44 delete iSourceSel; |
|
45 } |
|
46 |
|
47 CImapCompoundCopyWithinService* CImapCompoundCopyWithinService::NewL( CImapSyncManager& aSyncManager, |
|
48 CMsvServerEntry& aServerEntry, |
|
49 CImapSettings& aImapSettings, |
|
50 TBool aIsMove, |
|
51 const CMsvEntrySelection& aSourceSel, |
|
52 const TMsvId aDestination ) |
|
53 { |
|
54 CImapCompoundCopyWithinService* self = new (ELeave) CImapCompoundCopyWithinService( aSyncManager, |
|
55 aServerEntry, |
|
56 aImapSettings, |
|
57 aIsMove, |
|
58 aDestination ); |
|
59 CleanupStack::PushL(self); |
|
60 self->ConstructL(aSourceSel); |
|
61 CleanupStack::Pop(self); |
|
62 return self; |
|
63 |
|
64 } |
|
65 |
|
66 void CImapCompoundCopyWithinService::ConstructL(const CMsvEntrySelection& aSourceSel) |
|
67 { |
|
68 // Local copy of the selection of messages to copy |
|
69 iSourceSel = new (ELeave) CMsvEntrySelection(); |
|
70 |
|
71 // Check the source selection for acceptable message types/parts |
|
72 // Messages True |
|
73 // Handle Parts True |
|
74 // Handle Folders False |
|
75 // Check source True |
|
76 // Makes a local copy of the source selection in iSourceSel |
|
77 TInt err = CheckSelectionL(aSourceSel, iSourceSel, ETrue, ETrue, EFalse, ETrue); |
|
78 if (err==KErrNone) |
|
79 { |
|
80 // reset the stats |
|
81 iMsgsCopied = 0; |
|
82 iMsgsDone = 0; |
|
83 iMsgsToDo = aSourceSel.Count(); |
|
84 iTotalSize = CalculateDownloadSizeL(*iSourceSel); |
|
85 } |
|
86 |
|
87 // Add to the active scheduler |
|
88 CActiveScheduler::Add(this); |
|
89 } |
|
90 |
|
91 void CImapCompoundCopyWithinService::StartOperation(TRequestStatus& aStatus, CImapSession& aSession) |
|
92 { |
|
93 iSession = &aSession; |
|
94 __LOG_TEXT(iSession->LogId(), "CImapCompoundCopyWithinService::StartOperation()"); |
|
95 iNextStep = ECheckDestinationMailbox; |
|
96 Queue(aStatus); |
|
97 CompleteSelf(); |
|
98 } |
|
99 |
|
100 /** |
|
101 Handles the compound operation state machine |
|
102 |
|
103 @return ETrue if compound operation is completed, |
|
104 EFalse otherwise. |
|
105 */ |
|
106 TBool CImapCompoundCopyWithinService::DoRunLoopL( ) |
|
107 { |
|
108 SetCurrentStep(); |
|
109 switch (iCurrentStep) |
|
110 { |
|
111 case ECheckDestinationMailbox: // synchronous |
|
112 { |
|
113 // Obtain pointer to CImapFolder object for the destination folder. |
|
114 iDestinationFolder = iSyncManager.GetFolderL(iDestinationId); |
|
115 if (iDestinationFolder==NULL) |
|
116 { |
|
117 // note the error code for the progress report and complete |
|
118 iProgressErrorCode = KErrNotFound; |
|
119 iNextStep = EFinished; |
|
120 } |
|
121 else |
|
122 { |
|
123 iNextStep = ESetSourceMailbox; |
|
124 } |
|
125 // go to the next step |
|
126 return EFalse; |
|
127 } |
|
128 |
|
129 case ESetSourceMailbox: // synchronous |
|
130 { |
|
131 // State machine returns to this state after performing a copy/move |
|
132 // on messages in the selection in a single mailbox. The progress is |
|
133 // incremented here for messages that have been copied. If all messages |
|
134 // have been moved/copied the state machine progresses to the |
|
135 // synchronisation of the destination folder. |
|
136 IncrementProgress(iMsgsCopied); |
|
137 |
|
138 // starting a new copy operation... |
|
139 iMsgsCopied = 0; |
|
140 |
|
141 if (iSourceSel->Count() > 0) |
|
142 { |
|
143 if (iStopForMigrate) |
|
144 { |
|
145 __LOG_TEXT(iSession->LogId(), "CImapCompoundCopyWithinService::Stopped for migrate"); |
|
146 iCurrentStep = ESuspendedForMigrate; |
|
147 iNextStep = ESetSourceMailbox; |
|
148 Complete(KErrNone); |
|
149 return ETrue; |
|
150 } |
|
151 |
|
152 iCurrentMsgId = (*iSourceSel)[0]; |
|
153 SetSourceFolderL(iCurrentMsgId); |
|
154 if (iSourceFolderId != NULL && iSourceFolder != NULL) |
|
155 { |
|
156 iNextStep = (iIsMove) ? ESelectSourceMailboxRW : ESelectSourceMailboxRO; |
|
157 } |
|
158 else |
|
159 { |
|
160 // no change in state if folder not acceptable, |
|
161 // try again with the next message in the selection. |
|
162 iNextStep = ESetSourceMailbox; |
|
163 IncrementProgress(1); |
|
164 } |
|
165 } |
|
166 else |
|
167 { |
|
168 // All messages copied or moved... |
|
169 // Sync the destination folder |
|
170 iNextStep = ESelectDestinationMailboxRO; |
|
171 } |
|
172 // go to the next step |
|
173 return EFalse; |
|
174 } |
|
175 |
|
176 case ESelectSourceMailboxRW: // asynchronous |
|
177 { |
|
178 MOBILITY_TEST_MTM_STATE(iImapSettings.ServiceId(), KMobilityTestMtmStateImapCopyWithinService1); // SELECT source mailbox |
|
179 iSourceFolder->SelectL(iStatus, *iSession); |
|
180 iNextStep = ECopyMessage; |
|
181 SetActive(); |
|
182 break; |
|
183 } |
|
184 |
|
185 case ESelectSourceMailboxRO: |
|
186 { |
|
187 MOBILITY_TEST_MTM_STATE(iImapSettings.ServiceId(), KMobilityTestMtmStateImapCopyWithinService1); // EXAMINE source mailbox |
|
188 iSourceFolder->ExamineL(iStatus, *iSession); |
|
189 iNextStep = ECopyMessage; |
|
190 SetActive(); |
|
191 break; |
|
192 } |
|
193 |
|
194 case ECopyMessage: // asynchronous |
|
195 { |
|
196 MOBILITY_TEST_MTM_STATE(iImapSettings.ServiceId(), KMobilityTestMtmStateImapCopyWithinService2); // COPY message(s) |
|
197 // issue the COPY command - copies all messages in the selection |
|
198 // that have the same parent folder as the first in the selection. |
|
199 CopyMessagesL(); |
|
200 if (iIsMove) |
|
201 { |
|
202 iProgressState = TImap4GenericProgress::EMoving; |
|
203 iNextStep = EDeleteMessage; |
|
204 } |
|
205 else |
|
206 { |
|
207 // on completion, return to SetSourceMailbox to check for |
|
208 // more messages to copy (from other source folders) |
|
209 iProgressState = TImap4GenericProgress::ECopying; |
|
210 iNextStep = ESetSourceMailbox; |
|
211 } |
|
212 SetActive(); |
|
213 break; |
|
214 } |
|
215 |
|
216 case EDeleteMessage: // asynchronous |
|
217 { |
|
218 MOBILITY_TEST_MTM_STATE(iImapSettings.ServiceId(), KMobilityTestMtmStateImapCopyWithinService3); // STORE /deleted flag (move only) |
|
219 // Deleting a message is a two-stage operation: |
|
220 // 1. STORE the /deleted flag on the remote server. |
|
221 // 2.a) EXPUNGE the messages |
|
222 //or |
|
223 // 2.b) CLOSE the folder and then SELECT the folder |
|
224 // 2a) or 2b) used is dependent on the KImap4EmailExpungeFlag in CImImap4Settings. |
|
225 MarkMessageForDeletesL(); |
|
226 |
|
227 if (iImapSettings.UseExpunge()) |
|
228 { |
|
229 iNextStep=EExpunge; |
|
230 } |
|
231 else |
|
232 { |
|
233 iNextStep=ECloseFolder; |
|
234 } |
|
235 |
|
236 SetActive(); |
|
237 break; |
|
238 } |
|
239 |
|
240 case EExpunge: // asynchronous |
|
241 { |
|
242 MOBILITY_TEST_MTM_STATE(iImapSettings.ServiceId(), KMobilityTestMtmStateImapCopyWithinService4); // EXPUNGE source folder (move only) |
|
243 iSession->ExpungeL(iStatus); |
|
244 iNextStep = EDeleteLocalMessage; |
|
245 SetActive(); |
|
246 break; |
|
247 } |
|
248 |
|
249 case ECloseFolder: |
|
250 { |
|
251 MOBILITY_TEST_MTM_STATE(iImapSettings.ServiceId(), KMobilityTestMtmStateImapCopyWithinService7); // CLOSE FOLDER (move only) |
|
252 //Permanently removes all messages that have the deleted flag set |
|
253 //from the currently selected mailbox |
|
254 iSession->CloseL(iStatus); |
|
255 iNextStep=ESelectFolderAfterClose; |
|
256 SetActive(); |
|
257 break; |
|
258 } |
|
259 |
|
260 case ESelectFolderAfterClose: |
|
261 { |
|
262 MOBILITY_TEST_MTM_STATE(iImapSettings.ServiceId(), KMobilityTestMtmStateImapCopyWithinService8); // SELECT FOLDER (move only) |
|
263 //Selecting a mailbox so that messages in the mailbox can be accessed. |
|
264 iSourceFolder->SelectL(iStatus, *iSession); |
|
265 iNextStep=EDeleteLocalMessage; |
|
266 SetActive(); |
|
267 break; |
|
268 } |
|
269 |
|
270 case EDeleteLocalMessage: // synchonous |
|
271 { |
|
272 // Delete the messages locally |
|
273 DeleteMovedMessagesL(); |
|
274 // immediately proceed to the next step |
|
275 iNextStep = ESetSourceMailbox; |
|
276 return EFalse; |
|
277 } |
|
278 |
|
279 case ESelectDestinationMailboxRO: |
|
280 { |
|
281 MOBILITY_TEST_MTM_STATE(iImapSettings.ServiceId(), KMobilityTestMtmStateImapCopyWithinService5); // SELECT destination folder |
|
282 iDestinationFolder->ExamineL(iStatus, *iSession); |
|
283 iNextStep = ENewSyncFolder; |
|
284 SetActive(); |
|
285 break; |
|
286 } |
|
287 |
|
288 case ENewSyncFolder: |
|
289 { |
|
290 MOBILITY_TEST_MTM_STATE(iImapSettings.ServiceId(), KMobilityTestMtmStateImapCopyWithinService6); // sync'ing destination folder |
|
291 // if the current folder hasn't actually changed then don't |
|
292 // bother with the Sync |
|
293 iNextStep = EFinished; |
|
294 if (iDestinationFolder->Changed(*iSession)) |
|
295 { |
|
296 iSyncProgressState=TImap4SyncProgress::ESyncOther; |
|
297 iDestinationFolder->SynchroniseL(iStatus, *iSession, ETrue, 0); |
|
298 SetActive(); |
|
299 } |
|
300 break; |
|
301 } |
|
302 |
|
303 case EFinished: |
|
304 { |
|
305 __LOG_TEXT(iSession->LogId(), "CImapCompoundCopyWithinService::Completing OK"); |
|
306 iProgressState = TImap4GenericProgress::EIdle; |
|
307 iSyncProgressState = TImap4SyncProgress::EIdle; |
|
308 |
|
309 Complete(KErrNone); |
|
310 return ETrue; |
|
311 } |
|
312 |
|
313 default: |
|
314 { |
|
315 __ASSERT_DEBUG(EFalse, TImapServerPanic::ImapPanic(TImapServerPanic::ECopyWithinServiceCompoundUnexpectedState)); |
|
316 // unexpected state - complete the request |
|
317 iProgressState = TImap4GenericProgress::EIdle; |
|
318 return ETrue; |
|
319 } |
|
320 } // end switch (iCurrentStep) |
|
321 return EFalse; |
|
322 } |
|
323 |
|
324 /** |
|
325 May be called in case of a genuine cancel or a cancel for migrate. |
|
326 Following a genuine cancel, the compound operation will be deleted. |
|
327 Following a cancel for migrate, the compound operation will be resumed, |
|
328 so the iNextState is updated here to ensure the operation is |
|
329 correctly restarted. |
|
330 |
|
331 In either case, CMsgActive::DoCancel() is called to complete the |
|
332 user request with KErrCancel. |
|
333 |
|
334 Note that if the default CMsgActive::DoComplete() is overridden, |
|
335 then that must also be modified to handle either case described above. |
|
336 */ |
|
337 void CImapCompoundCopyWithinService::DoCancel() |
|
338 { |
|
339 switch (iCurrentStep) |
|
340 { |
|
341 case ESelectSourceMailboxRW: |
|
342 { |
|
343 iSession->Cancel(); |
|
344 iNextStep = ESelectSourceMailboxRW; // just resume |
|
345 break; |
|
346 } |
|
347 case ESelectSourceMailboxRO: |
|
348 { |
|
349 iSession->Cancel(); |
|
350 iNextStep = ESelectSourceMailboxRO; // just resume |
|
351 break; |
|
352 } |
|
353 case ECopyMessage: |
|
354 { |
|
355 iSession->Cancel(); |
|
356 iMsgsCopied = 0; // reset copied count |
|
357 iNextStep = ECopyMessage; // reSELECT source |
|
358 break; |
|
359 } |
|
360 case EDeleteMessage: |
|
361 { |
|
362 iSession->Cancel(); |
|
363 iNextStep = EDeleteMessage; // reSELECT source |
|
364 break; |
|
365 } |
|
366 case EExpunge: |
|
367 { |
|
368 iSession->Cancel(); |
|
369 iNextStep = EExpunge; // reSELECT source |
|
370 break; |
|
371 } |
|
372 case ECloseFolder: |
|
373 { |
|
374 iSession->Cancel(); |
|
375 iNextStep = ECloseFolder; |
|
376 break; |
|
377 } |
|
378 case ESelectFolderAfterClose: |
|
379 { |
|
380 iSession->Cancel(); |
|
381 iNextStep = ESelectFolderAfterClose; |
|
382 break; |
|
383 } |
|
384 case ESelectDestinationMailboxRO: |
|
385 { |
|
386 iSession->Cancel(); |
|
387 iNextStep = ESelectDestinationMailboxRO; // just restart |
|
388 break; |
|
389 } |
|
390 case ENewSyncFolder: |
|
391 { |
|
392 iDestinationFolder->Cancel(); |
|
393 iNextStep = ESelectDestinationMailboxRO; // just restart |
|
394 break; |
|
395 } |
|
396 case ECheckDestinationMailbox: |
|
397 case ESetSourceMailbox: |
|
398 case EDeleteLocalMessage: |
|
399 case EFinished: |
|
400 // self-completed or no outstanding request. |
|
401 case ESuspendedForMigrate: |
|
402 default: |
|
403 { |
|
404 __ASSERT_DEBUG(EFalse, TImapServerPanic::ImapPanic(TImapServerPanic::ECopyWithinServiceCompoundCancelUnexpectedState)); |
|
405 iNextStep = ESetSourceMailbox; |
|
406 // starting a new copy operation... |
|
407 iMsgsCopied = 0; |
|
408 break; |
|
409 } |
|
410 } // end switch (iCurrentStep) |
|
411 |
|
412 if (!iCancelForMigrate) |
|
413 { |
|
414 // genuine cancel - update progress |
|
415 iProgressErrorCode = KErrCancel; |
|
416 } |
|
417 CMsgActive::DoCancel(); |
|
418 } |
|
419 |
|
420 void CImapCompoundCopyWithinService::Progress(TImap4CompoundProgress& aCompoundProgress) |
|
421 { |
|
422 if (iIsMove) |
|
423 { |
|
424 aCompoundProgress.iGenericProgress.iOperation = TImap4GenericProgress::EMoveWithinService; |
|
425 } |
|
426 else |
|
427 { |
|
428 aCompoundProgress.iGenericProgress.iOperation = TImap4GenericProgress::ECopyWithinService; |
|
429 } |
|
430 |
|
431 // Progress through the received selection |
|
432 aCompoundProgress.iGenericProgress.iTotalSize = iTotalSize; |
|
433 aCompoundProgress.iGenericProgress.iMsgsToDo = iMsgsToDo; |
|
434 aCompoundProgress.iGenericProgress.iMsgsDone = iMsgsDone; |
|
435 |
|
436 aCompoundProgress.iSyncProgress.iState=iSyncProgressState; |
|
437 |
|
438 //if currently syncing then get the latest progress |
|
439 if(iSyncProgressState!=TImap4SyncProgress::EIdle) |
|
440 { |
|
441 iDestinationFolder->Progress(aCompoundProgress.iSyncProgress); |
|
442 } |
|
443 |
|
444 |
|
445 // Put error into progress buffer |
|
446 if( aCompoundProgress.iGenericProgress.iErrorCode == KErrNone ) |
|
447 { |
|
448 aCompoundProgress.iGenericProgress.iErrorCode = iProgressErrorCode; |
|
449 } |
|
450 } |
|
451 |
|
452 /** |
|
453 Builds an array of messages within the same source folder that can be copied |
|
454 with a single command to the remote server. |
|
455 */ |
|
456 void CImapCompoundCopyWithinService::CopyMessagesL( ) |
|
457 { |
|
458 iMessageUids.Reset(); |
|
459 // build an array of the UIDs to copy, |
|
460 TInt i = 0; |
|
461 TInt count = iSourceSel->Count(); |
|
462 |
|
463 TBool sameParent = ETrue; |
|
464 while(i<count && sameParent) |
|
465 { |
|
466 SetEntryL((*iSourceSel)[i]); |
|
467 TMsvEmailEntry entry = iServerEntry.Entry(); |
|
468 if (entry.Parent()==iSourceFolderId) |
|
469 { |
|
470 TUint id = entry.UID(); |
|
471 iMessageUids.AppendL(id); |
|
472 ++iMsgsCopied; |
|
473 } |
|
474 else |
|
475 { |
|
476 sameParent=EFalse; |
|
477 } |
|
478 ++i; |
|
479 } |
|
480 |
|
481 // store the UID sequence array - we will need to reuse it to |
|
482 // STORE the delete flag if we are performing a move. |
|
483 delete iUidSeq; |
|
484 iUidSeq = CImapSession::CreateSequenceSetLC(iMessageUids); |
|
485 CleanupStack::Pop(iUidSeq); |
|
486 |
|
487 // issue the store command |
|
488 iSession->CopyL(iStatus, *iUidSeq, iDestinationFolder->FullFolderPathL()); |
|
489 } |
|
490 |
|
491 /* |
|
492 Marks the messages that have been copied as deleted locally. |
|
493 |
|
494 Takes the uids in iMessageUids and marks messages for delete locally, |
|
495 and issues STORE command to mark it for delete remotely. |
|
496 */ |
|
497 void CImapCompoundCopyWithinService::MarkMessageForDeletesL() |
|
498 { |
|
499 for (TInt i=0 ; i<iMsgsCopied ; ++i) |
|
500 { |
|
501 // Move to the entry in question |
|
502 SetEntryL((*iSourceSel)[i]); |
|
503 |
|
504 // Set deleted flag on this entry |
|
505 TMsvEmailEntry entry = iServerEntry.Entry(); |
|
506 entry.SetDeletedIMAP4Flag(ETrue); |
|
507 User::LeaveIfError(iServerEntry.ChangeEntry(entry)); |
|
508 } |
|
509 |
|
510 iSession->StoreL( iStatus, |
|
511 *iUidSeq, |
|
512 KMessageDataItem, |
|
513 KDeleteValue, |
|
514 ETrue, |
|
515 iOutMessageFlagInfo ); |
|
516 } |
|
517 |
|
518 /** |
|
519 Deletes the local copy of messages that have been expunged on the remote server. |
|
520 */ |
|
521 void CImapCompoundCopyWithinService::DeleteMovedMessagesL() |
|
522 { |
|
523 // move to parent |
|
524 SetEntryL(iSourceFolderId); |
|
525 |
|
526 TInt messagesToDelete = iMsgsCopied - iMsgsDone ; |
|
527 for (TInt i=0 ; i<messagesToDelete ; ++i) |
|
528 { |
|
529 TMsvId msgId = (*iSourceSel)[i]; |
|
530 TInt err (iServerEntry.DeleteEntry(msgId)); |
|
531 |
|
532 // Do not leave when entry is in use |
|
533 if(err == KErrInUse) |
|
534 { |
|
535 // Dont leave if err = KErrInUse |
|
536 } |
|
537 else |
|
538 { |
|
539 User::LeaveIfError(err); |
|
540 } |
|
541 } |
|
542 } |
|
543 |
|
544 |
|
545 /** |
|
546 Find the parent folder |
|
547 @return ETrue if the source folder has changed since the last message operated on |
|
548 always true on the first call after creation. |
|
549 @post iSourceFolderId - The TMsvId of the source folder for the message. May be NULL |
|
550 @post iSourceFolder - CImapFolder pointer for the parent folder. May be NULL. |
|
551 */ |
|
552 TBool CImapCompoundCopyWithinService::SetSourceFolderL(const TMsvId aMessage) |
|
553 { |
|
554 TMsvId parentFolder = FindFolderL(aMessage); |
|
555 if (parentFolder==iSourceFolderId) |
|
556 { |
|
557 // Same folder as last message copied. |
|
558 return EFalse; |
|
559 } |
|
560 // otherwise, update to the new folder. |
|
561 iSourceFolderId = parentFolder; |
|
562 if (iSourceFolderId!=NULL) |
|
563 { |
|
564 iSourceFolder = iSyncManager.GetFolderL(iSourceFolderId); |
|
565 } |
|
566 return ETrue; |
|
567 } |
|
568 |
|
569 /** |
|
570 Handles NO/BAD responses according to current step. |
|
571 Negative server responses are not fatal - the error is saved in |
|
572 the message currently being operated on and the state machine pushed |
|
573 on to process the next message in the requested selection. |
|
574 |
|
575 @return KErrNone if the error has been handled |
|
576 Completion error code otherwise. |
|
577 */ |
|
578 TInt CImapCompoundCopyWithinService::ProcessNegativeServerResponse() |
|
579 { |
|
580 TInt err = iStatus.Int(); |
|
581 switch (iCurrentStep) |
|
582 { |
|
583 case ESelectSourceMailboxRW: |
|
584 case ESelectSourceMailboxRO: |
|
585 case ESelectDestinationMailboxRO: |
|
586 case ESelectFolderAfterClose: |
|
587 { |
|
588 if (err == KErrImapNo) |
|
589 { |
|
590 err = KErrNotFound; |
|
591 } |
|
592 } // fall through |
|
593 case ECopyMessage: |
|
594 case EDeleteMessage: |
|
595 case EExpunge: |
|
596 case ECloseFolder: |
|
597 case ENewSyncFolder: |
|
598 { |
|
599 // save the error with the associated message |
|
600 TRAP_IGNORE(MessageErrorL(iCurrentMsgId, err)); |
|
601 // Skip to the next message, or finish |
|
602 iNextStep = EFinished; |
|
603 break; |
|
604 } |
|
605 case ESuspendedForMigrate: |
|
606 case ESetSourceMailbox: |
|
607 case EFinished: |
|
608 default: |
|
609 { |
|
610 // positive error code not expected, |
|
611 // self-completed states or no outstanding request. |
|
612 TImapServerPanic::ImapPanic(TImapServerPanic::ECopyWithinServiceCompoundUnexpectedState); |
|
613 break; |
|
614 } |
|
615 } // end switch (iCurrentStep) |
|
616 iProgressErrorCode = err; |
|
617 return KErrNone; |
|
618 } |
|
619 |
|
620 |
|
621 /** |
|
622 Increments the progress count and removes the copied/moved messages |
|
623 from the source selection. |
|
624 |
|
625 @param aNum - number of message copied/moved/otherwise managed. |
|
626 */ |
|
627 void CImapCompoundCopyWithinService::IncrementProgress(TInt aNum) |
|
628 { |
|
629 if (aNum>0) |
|
630 { |
|
631 iMsgsDone+=aNum; |
|
632 iSourceSel->Delete(0,aNum); |
|
633 } |
|
634 } |
|
635 |
|
636 |
|
637 /** |
|
638 Called to resume the compound operation following a bearer migration. |
|
639 */ |
|
640 void CImapCompoundCopyWithinService::ResumeOperationL(TRequestStatus& aStatus, CImapSession& aSession) |
|
641 { |
|
642 iSession = &aSession; |
|
643 __LOG_TEXT(iSession->LogId(), "CImapCompoundCopyWithinService::Resuming"); |
|
644 __ASSERT_DEBUG(iCurrentStep==ESuspendedForMigrate, TImapServerPanic::ImapPanic(TImapServerPanic::ECopyWithinServiceCompoundUnexpectedState)); |
|
645 iStopForMigrate = EFalse; |
|
646 |
|
647 switch (iNextStep) |
|
648 { |
|
649 case ESelectSourceMailboxRW: |
|
650 case ESelectSourceMailboxRO: |
|
651 case ESelectDestinationMailboxRO: |
|
652 case ENewSyncFolder: |
|
653 case ESelectFolderAfterClose: |
|
654 { |
|
655 CompleteSelf(); |
|
656 break; |
|
657 } |
|
658 case ECopyMessage: |
|
659 case EDeleteMessage: |
|
660 case EExpunge: |
|
661 case ECloseFolder: |
|
662 { |
|
663 iSourceFolder->SelectL(iStatus, *iSession); |
|
664 iCurrentStep = ESelectSourceMailboxRW; |
|
665 SetActive(); |
|
666 break; |
|
667 } |
|
668 case ECheckDestinationMailbox: |
|
669 case ESetSourceMailbox: |
|
670 case EDeleteLocalMessage: |
|
671 case EFinished: |
|
672 // self-completed or no outstanding request. |
|
673 default: |
|
674 { |
|
675 __ASSERT_DEBUG(EFalse, TImapServerPanic::ImapPanic(TImapServerPanic::ECopyWithinServiceCompoundCancelUnexpectedState)); |
|
676 // abandon the compound operation |
|
677 iNextStep=EFinished; |
|
678 CompleteSelf(); |
|
679 break; |
|
680 } |
|
681 } // end switch (iNextStep) |
|
682 Queue(aStatus); |
|
683 } |
|
684 |