|
1 // Copyright (c) 1999-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 "cimapopsyncfoldertree.h" |
|
17 |
|
18 #include "cimapsettings.h" |
|
19 #include "cimapsession.h" |
|
20 #include "cimapfolder.h" |
|
21 #include "cimaplogger.h" |
|
22 |
|
23 _LIT(KImapInbox, "INBOX"); |
|
24 |
|
25 /** |
|
26 Factory constructor |
|
27 |
|
28 @param aEntry Server entry |
|
29 @param aSession IMAP session |
|
30 @param aSyncMan Sync manager |
|
31 @param aImapSettings IMAP settings |
|
32 |
|
33 @return Instance of class created on heap |
|
34 */ |
|
35 CImapOpSyncFolderTree* CImapOpSyncFolderTree::NewL(CMsvServerEntry& aEntry, CImapSession& aSession, CImapSyncManager& aSyncMan, CImapSettings& aImapSettings) |
|
36 { |
|
37 CImapOpSyncFolderTree* self=NewLC(aEntry, aSession, aSyncMan, aImapSettings); |
|
38 CleanupStack::Pop(); |
|
39 |
|
40 return self; |
|
41 } |
|
42 |
|
43 /** |
|
44 Factory constructor |
|
45 |
|
46 @param aEntry Server entry |
|
47 @param aSession IMAP session |
|
48 @param aSyncMan Sync manager |
|
49 @param aImapSettings IMAP settings |
|
50 |
|
51 @return Instance of class created on heap |
|
52 */ |
|
53 CImapOpSyncFolderTree* CImapOpSyncFolderTree::NewLC(CMsvServerEntry& aEntry, CImapSession& aSession, CImapSyncManager& aSyncMan, CImapSettings& aImapSettings) |
|
54 { |
|
55 CImapOpSyncFolderTree* self=new (ELeave) CImapOpSyncFolderTree(aEntry, aSession, aSyncMan, aImapSettings); |
|
56 CleanupStack::PushL(self); |
|
57 |
|
58 // Non-trivial constructor |
|
59 self->ConstructL(); |
|
60 |
|
61 return self; |
|
62 } |
|
63 |
|
64 /** |
|
65 Constructor |
|
66 */ |
|
67 CImapOpSyncFolderTree::CImapOpSyncFolderTree(CMsvServerEntry& aEntry, CImapSession& aSession, CImapSyncManager& aSyncMan, CImapSettings& aImapSettings) |
|
68 : CImapSyncOperation(aEntry, aSession, aSyncMan, aImapSettings, EPriorityLow) |
|
69 { |
|
70 } |
|
71 |
|
72 /** |
|
73 Second phase constructor |
|
74 */ |
|
75 void CImapOpSyncFolderTree::ConstructL() |
|
76 { |
|
77 // Create some paths that are used in folder name pattern matching |
|
78 |
|
79 // Create a path constisting of the inbox followed by the hierarchy |
|
80 // separator |
|
81 iInboxPathWithSeparator = HBufC::NewL(KImapInbox().Length() + iImapSettings.PathSeparator().Length()); |
|
82 TPtr inboxPathPtr = iInboxPathWithSeparator->Des(); |
|
83 inboxPathPtr.Copy(KImapInbox()); |
|
84 inboxPathPtr.Append(iImapSettings.PathSeparator()); |
|
85 |
|
86 // If the settings folder path is defined, create one path consisting of |
|
87 // the folder path followed by the hierarchy separator, and one path |
|
88 // consisting of the folder path only. |
|
89 if (iImapSettings.FolderPath().Length() > 0) |
|
90 { |
|
91 iFolderPathWithSeparator = HBufC::NewL(iImapSettings.FolderPath().Length() + iImapSettings.PathSeparator().Length()); |
|
92 TPtr folderPathPtr = iFolderPathWithSeparator->Des(); |
|
93 folderPathPtr.Copy(iImapSettings.FolderPath()); |
|
94 |
|
95 iFolderPath.Set(folderPathPtr); |
|
96 |
|
97 folderPathPtr.Append(iImapSettings.PathSeparator()); |
|
98 } |
|
99 |
|
100 // We're an active object... |
|
101 CActiveScheduler::Add(this); |
|
102 } |
|
103 |
|
104 /** |
|
105 Destructor |
|
106 */ |
|
107 CImapOpSyncFolderTree::~CImapOpSyncFolderTree() |
|
108 { |
|
109 Cancel(); |
|
110 |
|
111 iImapListFolderInfo.ResetAndDestroy(); |
|
112 iFolderList.ResetAndDestroy(); |
|
113 |
|
114 delete iSelection; |
|
115 delete iSearchFolder; |
|
116 delete iInboxPathWithSeparator; |
|
117 delete iFolderPathWithSeparator; |
|
118 } |
|
119 |
|
120 /** |
|
121 Start tree synchronisation |
|
122 |
|
123 @param aStatus Caller's request status |
|
124 */ |
|
125 void CImapOpSyncFolderTree::SynchroniseTreeL(TRequestStatus& aStatus) |
|
126 { |
|
127 __LOG_TEXT(iSession.LogId(), "CImapOpSyncFolderTree::SynchroniseTreeL"); |
|
128 StartBuildingLocalFolderListL(); |
|
129 Queue(aStatus); |
|
130 } |
|
131 |
|
132 /** |
|
133 Called when async child completes with >=KErrNone |
|
134 */ |
|
135 void CImapOpSyncFolderTree::DoRunL() |
|
136 { |
|
137 // Finish if any server errors. |
|
138 if (iStatus.Int()!=KErrNone) |
|
139 { |
|
140 Complete(iStatus.Int()); |
|
141 return ; |
|
142 } |
|
143 |
|
144 switch (iState) |
|
145 { |
|
146 case EStateBuildingLocalFolderList: |
|
147 { |
|
148 ProcessNextFolderInLocalFolderListL(); |
|
149 break; |
|
150 } |
|
151 |
|
152 case EStateFetchingFolderList: |
|
153 { |
|
154 StartProcessingReceivedFolderListL(); |
|
155 break; |
|
156 } |
|
157 |
|
158 case EStateProcessingReceivedFolders: |
|
159 { |
|
160 ProcessNextFolderInReceivedFolderListL(); |
|
161 break; |
|
162 } |
|
163 |
|
164 case EStateIdle: |
|
165 default: |
|
166 { |
|
167 __ASSERT_DEBUG(EFalse, TImapServerPanic::ImapPanic(TImapServerPanic::EUnexpectedStateSyncFolderTreeDoRunL)); |
|
168 break; |
|
169 } |
|
170 } |
|
171 } |
|
172 |
|
173 /** |
|
174 Cancels any outstanding asynchronous service requests. |
|
175 */ |
|
176 void CImapOpSyncFolderTree::DoCancel() |
|
177 { |
|
178 __LOG_TEXT(iSession.LogId(), "CImapOpSyncFolderTree::DoCancel"); |
|
179 |
|
180 switch (iState) |
|
181 { |
|
182 case EStateBuildingLocalFolderList: |
|
183 case EStateProcessingReceivedFolders: |
|
184 { |
|
185 // Self completing states |
|
186 break; |
|
187 } |
|
188 |
|
189 case EStateFetchingFolderList: |
|
190 { |
|
191 iSession.Cancel(); |
|
192 break; |
|
193 } |
|
194 |
|
195 case EStateIdle: |
|
196 default: |
|
197 { |
|
198 __ASSERT_DEBUG(EFalse, TImapServerPanic::ImapPanic(TImapServerPanic::EUnexpectedStateSyncFolderTreeDoCancel)); |
|
199 TRequestStatus* status = &iStatus; |
|
200 User::RequestComplete(status, KErrCancel); |
|
201 break; |
|
202 } |
|
203 } |
|
204 |
|
205 CMsgActive::DoCancel(); |
|
206 } |
|
207 |
|
208 /** |
|
209 Called when completing a client request |
|
210 |
|
211 @param aStatus Completion code |
|
212 */ |
|
213 #ifdef __IMAP_LOGGING |
|
214 void CImapOpSyncFolderTree::DoComplete(TInt& aStatus) |
|
215 #else //__IMAP_LOGGING |
|
216 void CImapOpSyncFolderTree::DoComplete(TInt& /*aStatus*/) |
|
217 #endif //__IMAP_LOGGING |
|
218 { |
|
219 __LOG_FORMAT((iSession.LogId(), "CImapOpSyncFolderTree::DoComplete - %d", aStatus)); |
|
220 |
|
221 iImapListFolderInfo.ResetAndDestroy(); |
|
222 iFolderList.ResetAndDestroy(); |
|
223 |
|
224 delete iSelection; |
|
225 iSelection = NULL; |
|
226 |
|
227 delete iSearchFolder; |
|
228 iSearchFolder = NULL; |
|
229 |
|
230 delete iInboxPathWithSeparator; |
|
231 iInboxPathWithSeparator = NULL; |
|
232 |
|
233 delete iFolderPathWithSeparator; |
|
234 iFolderPathWithSeparator = NULL; |
|
235 |
|
236 iState = EStateIdle; |
|
237 } |
|
238 |
|
239 /** |
|
240 Starts building a list of folders for this service that are in the |
|
241 message store |
|
242 */ |
|
243 void CImapOpSyncFolderTree::StartBuildingLocalFolderListL() |
|
244 { |
|
245 __LOG_TEXT(iSession.LogId(), "CImapOpSyncFolderTree::StartBuildingLocalFolderListL"); |
|
246 |
|
247 iState = EStateBuildingLocalFolderList; |
|
248 |
|
249 iFolderList.ResetAndDestroy(); |
|
250 iCurrentFolder = 0; |
|
251 |
|
252 User::LeaveIfError(iServerEntry.SetEntry(iImapSettings.ServiceId())); |
|
253 |
|
254 iSelection = new (ELeave) CMsvEntrySelection; |
|
255 |
|
256 // Get all the folders directly under the service entry |
|
257 User::LeaveIfError(iServerEntry.GetChildrenWithType(KUidMsvFolderEntry, *iSelection)); |
|
258 |
|
259 // If the inbox is in the selection, we want to remove it from the selction and |
|
260 // specifically add it to the folder list. This ensures that we use the uppercase |
|
261 // spelling of inbox and helps in the folder matching that is done against the list |
|
262 // of folders we receive from the server. |
|
263 for (TInt selLoop = 0; selLoop < iSelection->Count(); ++selLoop) |
|
264 { |
|
265 User::LeaveIfError(iServerEntry.SetEntry((*iSelection)[selLoop])); |
|
266 |
|
267 TMsvEmailEntry entry = iServerEntry.Entry(); |
|
268 if (entry.iDetails.CompareF(KImapInbox) == 0) |
|
269 { |
|
270 iSelection->Delete(selLoop); |
|
271 |
|
272 CImapFolder* tempFolder = CImapFolder::NewLC(iSyncMan, iServerEntry, entry, iImapSettings, KImapInbox()); |
|
273 tempFolder->SetFolderMatched(ETrue); |
|
274 iFolderList.AppendL(tempFolder); |
|
275 CleanupStack::Pop(tempFolder); |
|
276 break; |
|
277 } |
|
278 } |
|
279 |
|
280 // If the settings has a defined folder path, then append this at the start |
|
281 // of each new folder path. Where the settings has no folder path defined, |
|
282 // iFolderPath will just be an empty pointer. |
|
283 iCurrentPath.Set(iFolderPath); |
|
284 |
|
285 // We can now self complete to keep the state machine running. This will |
|
286 // cause the current selection of folders to be processed |
|
287 TRequestStatus* status = &iStatus; |
|
288 User::RequestComplete(status, KErrNone); |
|
289 SetActive(); |
|
290 } |
|
291 |
|
292 /** |
|
293 Process the current selection of folders. |
|
294 For each entry in the selection, add a new folder in the folder list. Then |
|
295 take the first entry in the folder list and create a selection of all its |
|
296 children folders. This process is then repeated until all the folders under |
|
297 the service have been found. |
|
298 */ |
|
299 void CImapOpSyncFolderTree::ProcessNextFolderInLocalFolderListL() |
|
300 { |
|
301 __LOG_TEXT(iSession.LogId(), "CImapOpSyncFolderTree::ProcessNextFolderInLocalFolderListL"); |
|
302 |
|
303 HBufC* newPath = NULL; |
|
304 TInt curPathLen = iCurrentPath.Length(); |
|
305 |
|
306 // Loop through every entry in the selection. Each one is a folder. |
|
307 for (TInt selLoop = 0; selLoop < iSelection->Count(); ++selLoop) |
|
308 { |
|
309 User::LeaveIfError(iServerEntry.SetEntry((*iSelection)[selLoop])); |
|
310 |
|
311 TMsvEmailEntry entry = iServerEntry.Entry(); |
|
312 |
|
313 // Create the full path name for this folder. This will be the path |
|
314 // name passed in (which is the path name of the parent) with the |
|
315 // folder name from the message store entry appended. |
|
316 newPath = HBufC::NewLC(curPathLen + 1 + entry.iDetails.Length()); |
|
317 newPath->Des().Copy(iCurrentPath); |
|
318 if (curPathLen > 0) |
|
319 { |
|
320 newPath->Des().Append(iImapSettings.PathSeparator()); |
|
321 } |
|
322 newPath->Des().Append(entry.iDetails); |
|
323 |
|
324 #ifdef __IMAP_LOGGING |
|
325 HBufC8* tempBuf = HBufC8::NewL(newPath->Length()); |
|
326 TPtr8 tempBufPtr = tempBuf->Des(); |
|
327 tempBufPtr.Copy(*newPath); |
|
328 __LOG_FORMAT((iSession.LogId(), "Adding Local Folder: - %S", &tempBufPtr)); |
|
329 delete tempBuf; |
|
330 #endif |
|
331 |
|
332 // Create new IMAP folder and insert into the list. |
|
333 CImapFolder* tempFolder = CImapFolder::NewLC(iSyncMan, iServerEntry, entry, iImapSettings, *newPath); |
|
334 iFolderList.AppendL(tempFolder); |
|
335 CleanupStack::Pop(tempFolder); |
|
336 CleanupStack::PopAndDestroy(newPath); |
|
337 newPath = NULL; |
|
338 } |
|
339 |
|
340 if (iCurrentFolder < iFolderList.Count()) |
|
341 { |
|
342 iCurrentPath.Set(iFolderList[iCurrentFolder]->FullFolderPathL()); |
|
343 iSelection->Reset(); |
|
344 |
|
345 User::LeaveIfError(iServerEntry.SetEntry(iFolderList[iCurrentFolder]->MailboxId())); |
|
346 User::LeaveIfError(iServerEntry.GetChildrenWithType(KUidMsvFolderEntry, *iSelection)); |
|
347 |
|
348 ++iCurrentFolder; |
|
349 |
|
350 // Self complete to go around again |
|
351 TRequestStatus* status = &iStatus; |
|
352 User::RequestComplete(status, KErrNone); |
|
353 SetActive(); |
|
354 } |
|
355 else |
|
356 { |
|
357 // We have created the folder list. Need to sort it into alphabetical |
|
358 // order. |
|
359 TLinearOrder<CImapFolder> sorter(CImapFolder::CompareByFolderName); |
|
360 iFolderList.Sort(sorter); |
|
361 |
|
362 delete iSelection; |
|
363 iSelection = NULL; |
|
364 |
|
365 // Now get the list of folders from the server |
|
366 SendListRequestL(); |
|
367 } |
|
368 } |
|
369 |
|
370 /** |
|
371 Sends the request to the server to get the list of folders |
|
372 */ |
|
373 void CImapOpSyncFolderTree::SendListRequestL() |
|
374 { |
|
375 __LOG_TEXT(iSession.LogId(), "CImapOpSyncFolderTree::SendListRequestL"); |
|
376 |
|
377 iState = EStateFetchingFolderList; |
|
378 |
|
379 iSession.ListL(iStatus, KNullDesC, KStarChar(), iImapListFolderInfo); |
|
380 SetActive(); |
|
381 } |
|
382 |
|
383 /** |
|
384 Starts processing the received list of folders on the server |
|
385 */ |
|
386 void CImapOpSyncFolderTree::StartProcessingReceivedFolderListL() |
|
387 { |
|
388 __LOG_TEXT(iSession.LogId(), "CImapOpSyncFolderTree::StartProcessingReceivedFolderListL"); |
|
389 |
|
390 iState = EStateProcessingReceivedFolders; |
|
391 |
|
392 iCurrentFolder = 0; |
|
393 |
|
394 // Create a temporary folder which will be used for subsequent searches |
|
395 User::LeaveIfError(iServerEntry.SetEntry(iImapSettings.ServiceId())); |
|
396 TMsvEmailEntry entry = iServerEntry.Entry(); |
|
397 iSearchFolder = CImapFolder::NewL(iSyncMan, iServerEntry, entry, iImapSettings, KNullDesC()); |
|
398 |
|
399 // Self complete to get the process moving |
|
400 TRequestStatus* status = &iStatus; |
|
401 User::RequestComplete(status, KErrNone); |
|
402 SetActive(); |
|
403 } |
|
404 |
|
405 /** |
|
406 Process next folder from the received folder list. |
|
407 Check if we know about the folder already or not. If we don't know about |
|
408 it, then we need to add a new folder. |
|
409 */ |
|
410 void CImapOpSyncFolderTree::ProcessNextFolderInReceivedFolderListL() |
|
411 { |
|
412 __LOG_TEXT(iSession.LogId(), "CImapOpSyncFolderTree::ProcessNextFolderInReceivedFolderListL"); |
|
413 |
|
414 if (iCurrentFolder < iImapListFolderInfo.Count()) |
|
415 { |
|
416 TPtrC currentFolderFullPath = iImapListFolderInfo[iCurrentFolder]->FolderName(); |
|
417 |
|
418 #ifdef __IMAP_LOGGING |
|
419 HBufC8* tempBuf = HBufC8::NewL(currentFolderFullPath.Length()); |
|
420 TPtr8 tempBufPtr = tempBuf->Des(); |
|
421 tempBufPtr.Copy(currentFolderFullPath); |
|
422 __LOG_FORMAT((iSession.LogId(), "Processing received folder: - %S", &tempBufPtr)); |
|
423 delete tempBuf; |
|
424 #endif |
|
425 |
|
426 if (currentFolderFullPath.Length() > 0) |
|
427 { |
|
428 TBool processFolder = ETrue; |
|
429 |
|
430 // If the settings has a defined folder path, don't process this |
|
431 // folder unless the first part of the folder name is the settings |
|
432 // folder path or is the inbox. |
|
433 if (iFolderPathWithSeparator) |
|
434 { |
|
435 // We don't need to do a case insensitive search for the inbox |
|
436 // because the iInboxPathWithSeparator was created using uppercase, |
|
437 // and the received folder list is change by the IMAP session to |
|
438 // ensure that the inbox folder is converted to uppercase. |
|
439 // Note also that this bit of code will result in the actual inbox |
|
440 // folder being removed as it does not have a separator character |
|
441 // on the end of it. This will not cause a problem because the |
|
442 // inbox has already been specifically added to the list of local |
|
443 // folders. |
|
444 if ((iFolderPathWithSeparator->Compare(currentFolderFullPath.Left(iFolderPathWithSeparator->Length())) != 0) && |
|
445 (iInboxPathWithSeparator->Compare(currentFolderFullPath.Left(iInboxPathWithSeparator->Length())) != 0)) |
|
446 { |
|
447 __LOG_TEXT(iSession.LogId(), "Ignoring non folder path folder"); |
|
448 processFolder = EFalse; |
|
449 } |
|
450 } |
|
451 |
|
452 if (processFolder) |
|
453 { |
|
454 // Try to find the received folder in the local folder list |
|
455 TLinearOrder<CImapFolder> sorter(CImapFolder::CompareByFolderName); |
|
456 iSearchFolder->SetFullFolderPathL(currentFolderFullPath); |
|
457 TInt pos = iFolderList.FindInOrder(iSearchFolder, sorter); |
|
458 |
|
459 if (pos != KErrNotFound) |
|
460 { |
|
461 // We already know about the folder. Just set its flag to indicate |
|
462 // we have matched it. |
|
463 iFolderList[pos]->SetFolderMatched(ETrue); |
|
464 __LOG_TEXT(iSession.LogId(), "Folder already known"); |
|
465 } |
|
466 else |
|
467 { |
|
468 AddReceivedFolderL(iImapListFolderInfo[iCurrentFolder], currentFolderFullPath); |
|
469 } |
|
470 } |
|
471 } |
|
472 |
|
473 ++iCurrentFolder; |
|
474 TRequestStatus* status = &iStatus; |
|
475 User::RequestComplete(status, KErrNone); |
|
476 SetActive(); |
|
477 } |
|
478 else |
|
479 { |
|
480 // All the folders have been done. We now need to remove any folders |
|
481 // that we have in the message store, that are no longer on the server. |
|
482 RemoveMissingFolders(); |
|
483 |
|
484 delete iSearchFolder; |
|
485 iSearchFolder = NULL; |
|
486 |
|
487 delete iInboxPathWithSeparator; |
|
488 iInboxPathWithSeparator = NULL; |
|
489 |
|
490 delete iFolderPathWithSeparator; |
|
491 iFolderPathWithSeparator = NULL; |
|
492 } |
|
493 } |
|
494 |
|
495 /** |
|
496 Add a new folder that is on the server but which we don't have stored locally |
|
497 |
|
498 @param aCurrentFolderInfo Received folder info of new folder |
|
499 @param aCurrentFolderFullPath Full path of new folder |
|
500 */ |
|
501 void CImapOpSyncFolderTree::AddReceivedFolderL(CImapListFolderInfo* aCurrentFolderInfo, const TDesC& aCurrentFolderFullPath) |
|
502 { |
|
503 __LOG_TEXT(iSession.LogId(), "CImapOpSyncFolderTree::AddReceivedFolderL"); |
|
504 |
|
505 CImapFolder* parentFolder = NULL; |
|
506 TBool rootFolder = EFalse; |
|
507 TPtrC parentFolderFullPath = aCurrentFolderFullPath; |
|
508 TPtrC folderName = aCurrentFolderFullPath; |
|
509 TLinearOrder<CImapFolder> sorter(CImapFolder::CompareByFolderName); |
|
510 |
|
511 // Try to split the folder path into the folder name and the path of |
|
512 // the parent folder by searching backwards from the end for the |
|
513 // hierarchy separator character |
|
514 TInt sepPos = parentFolderFullPath.LocateReverseF(aCurrentFolderInfo->iHierarchySeperator); |
|
515 |
|
516 if (sepPos != KErrNotFound) |
|
517 { |
|
518 // We found the hierarchy separator. Split the path into the folder name |
|
519 // and the parent path |
|
520 parentFolderFullPath.Set(parentFolderFullPath.Left(sepPos)); |
|
521 folderName.Set(folderName.Mid(sepPos + 1)); |
|
522 |
|
523 #ifdef __IMAP_LOGGING |
|
524 HBufC8* tempBuf = HBufC8::NewL(parentFolderFullPath.Length()); |
|
525 TPtr8 tempBufPtr = tempBuf->Des(); |
|
526 tempBufPtr.Copy(parentFolderFullPath); |
|
527 HBufC8* tempBuf2 = HBufC8::NewL(folderName.Length()); |
|
528 TPtr8 tempBufPtr2 = tempBuf2->Des(); |
|
529 tempBufPtr2.Copy(folderName); |
|
530 __LOG_FORMAT((iSession.LogId(), "Split path into %S and %S", &tempBufPtr, &tempBufPtr2)); |
|
531 delete tempBuf; |
|
532 delete tempBuf2; |
|
533 #endif |
|
534 |
|
535 // Check if this is directly under inbox |
|
536 if (parentFolderFullPath.CompareF(KImapInbox) == 0) |
|
537 { |
|
538 __LOG_TEXT(iSession.LogId(), "Parent is the inbox"); |
|
539 parentFolder = iSyncMan.Inbox(); |
|
540 } |
|
541 // Check if the parent path is the same as the settings folder path. |
|
542 // If so this is a root folder |
|
543 else if ((iFolderPath.Length() > 0) && |
|
544 (parentFolderFullPath.Compare(iFolderPath) == 0)) |
|
545 { |
|
546 __LOG_TEXT(iSession.LogId(), "Parent is settings folder path"); |
|
547 rootFolder = ETrue; |
|
548 } |
|
549 else |
|
550 { |
|
551 // Search for the parent folder in the folder list. |
|
552 // Note that the received list of folders from the server is in |
|
553 // alphabetical order, so the parent folder will have already |
|
554 // been created so we should be able to find it. |
|
555 iSearchFolder->SetFullFolderPathL(parentFolderFullPath); |
|
556 TLinearOrder<CImapFolder> sorter(CImapFolder::CompareByFolderName); |
|
557 TInt parentPos = iFolderList.FindInOrder(iSearchFolder, sorter); |
|
558 |
|
559 if (parentPos != KErrNotFound) |
|
560 { |
|
561 __LOG_FORMAT((iSession.LogId(), "Parent found at position %d", parentPos)); |
|
562 parentFolder = iFolderList[parentPos]; |
|
563 } |
|
564 } |
|
565 } |
|
566 else |
|
567 { |
|
568 // No hierarchy separator so this must be a root folder |
|
569 folderName.Set(aCurrentFolderFullPath); |
|
570 rootFolder = ETrue; |
|
571 } |
|
572 |
|
573 if (rootFolder || parentFolder) |
|
574 { |
|
575 if (rootFolder) |
|
576 { |
|
577 User::LeaveIfError(iServerEntry.SetEntry(iImapSettings.ServiceId())); |
|
578 } |
|
579 else |
|
580 { |
|
581 User::LeaveIfError(iServerEntry.SetEntry(parentFolder->MailboxId())); |
|
582 } |
|
583 |
|
584 TMsvEmailEntry entry; |
|
585 entry.iDetails.Set(folderName); |
|
586 entry.iType = KUidMsvFolderEntry; |
|
587 entry.iMtm = KUidMsgTypeIMAP4; |
|
588 entry.iServiceId = iImapSettings.ServiceId(); |
|
589 entry.iSize = 0; |
|
590 entry.SetUID(0); |
|
591 entry.SetValidUID(EFalse); |
|
592 entry.SetMailbox(!(aCurrentFolderInfo->QueryFlag(CImapListFolderInfo::ENoselect))); |
|
593 entry.SetLocalSubscription(EFalse); |
|
594 entry.SetComplete(ETrue); |
|
595 entry.SetVisible(EFalse); |
|
596 |
|
597 User::LeaveIfError(iServerEntry.CreateEntry(entry)); |
|
598 |
|
599 CImapFolder* tempFolder = CImapFolder::NewLC(iSyncMan, iServerEntry, entry, iImapSettings, aCurrentFolderInfo->FolderName()); |
|
600 tempFolder->SetFolderMatched(ETrue); |
|
601 iFolderList.InsertInOrderL(tempFolder, sorter); |
|
602 CleanupStack::Pop(tempFolder); |
|
603 |
|
604 __LOG_TEXT(iSession.LogId(), "Added folder"); |
|
605 } |
|
606 } |
|
607 |
|
608 /** |
|
609 Remove any local folders that are no longer on the server |
|
610 */ |
|
611 void CImapOpSyncFolderTree::RemoveMissingFolders() |
|
612 { |
|
613 __LOG_TEXT(iSession.LogId(), "CImapOpSyncFolderTree::RemoveMissingFolders"); |
|
614 |
|
615 // Remove in reverse order to ensure that children folders are removed |
|
616 // before their parent |
|
617 for (TInt folderLoop = iFolderList.Count() - 1; folderLoop >= 0; --folderLoop) |
|
618 { |
|
619 if (!iFolderList[folderLoop]->FolderMatched()) |
|
620 { |
|
621 #ifdef __IMAP_LOGGING |
|
622 HBufC8* tempBuf = HBufC8::NewL(iFolderList[folderLoop]->FullFolderPathL().Length()); |
|
623 TPtr8 tempBufPtr = tempBuf->Des(); |
|
624 tempBufPtr.Copy(iFolderList[folderLoop]->FullFolderPathL()); |
|
625 __LOG_FORMAT((iSession.LogId(), "Removing folder %S", &tempBufPtr)); |
|
626 delete tempBuf; |
|
627 #endif |
|
628 |
|
629 if (iServerEntry.SetEntry(iFolderList[folderLoop]->MailboxId()) == KErrNone) |
|
630 { |
|
631 if (iServerEntry.SetEntry(iServerEntry.Entry().Parent()) == KErrNone) |
|
632 { |
|
633 iServerEntry.DeleteEntry(iFolderList[folderLoop]->MailboxId()); |
|
634 } |
|
635 } |
|
636 |
|
637 delete iFolderList[folderLoop]; |
|
638 iFolderList.Remove(folderLoop); |
|
639 } |
|
640 } |
|
641 } |