email/imap4mtm/imapsyncmanager/src/cimapopsyncfoldertree.cpp
changeset 0 72b543305e3a
equal deleted inserted replaced
-1:000000000000 0:72b543305e3a
       
     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 	}