pimprotocols/phonebooksync/Server/SyncEngineServer.cpp
changeset 0 e686773b3f54
child 81 640d30f4fb64
equal deleted inserted replaced
-1:000000000000 0:e686773b3f54
       
     1 // Copyright (c) 2002-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 // Implementation of the Background Sync Engine server. The engine provides
       
    15 // the ability to perform Phonebook Sync's long running operations (e.g. Sync,
       
    16 // write contact and delete contact).
       
    17 // 
       
    18 //
       
    19 
       
    20 /**
       
    21  @file
       
    22  @internalComponent
       
    23 */
       
    24 
       
    25 #include <connect/sbdefs.h>
       
    26 #include <commsdattypesv1_1.h>
       
    27 #include <cdblen.h>
       
    28 
       
    29 #include "common.h"
       
    30 #include "PhonebookManager.h"
       
    31 #include "SyncContactICCEntry.h"
       
    32 #include "phbksynclog.h"
       
    33 #include "SyncEngineServer.h"
       
    34 #include "SyncEngineSession.h"
       
    35 #include "SyncContactsWithICC.h"
       
    36 #include "WriteContactToICC.h"
       
    37 #include "DeleteContactFromICC.h"
       
    38 
       
    39 
       
    40 using namespace CommsDat;
       
    41 
       
    42 
       
    43 /**
       
    44  * Number of retries for connecting to Etel.
       
    45  */
       
    46 const TInt KMaxConnectToEtelRetries = 3;
       
    47 
       
    48 
       
    49 //
       
    50 // Teleplate names.  Should be in a resource file for localisation really!
       
    51 //
       
    52 _LIT(KPhbkTemplateADN, "SIM Card Contacts ADN");
       
    53 _LIT(KPhbkTemplateSDN, "SIM Card Contacts SDN");
       
    54 _LIT(KPhbkTemplateLND, "SIM Card Contacts LND");
       
    55 _LIT(KPhbkTemplateUSimApp, "SIM Card Contacts USIMAPP");
       
    56 _LIT(KPhbkTemplateFDN, "SIM Card Contacts FDN");
       
    57 _LIT(KPhbkTemplateNotSpecified, "SIM Card Contacts Name Not Specified");
       
    58 
       
    59 
       
    60 //
       
    61 // Constants for encoding contacts...
       
    62 //
       
    63 _LIT(KEngineInternationalPrefix,"+");
       
    64 
       
    65 
       
    66 //
       
    67 //  Definition of iPolicy dictating the capability checking for phbksyncsvr...
       
    68 //
       
    69 const TUint iEngineRangeCount = 10;
       
    70 	
       
    71 const TInt CSyncEngineServer::iRanges[iEngineRangeCount] = 
       
    72 	{
       
    73 	0,		//range is 0
       
    74 	1,		//range is 1-3 inclusive
       
    75 	4,		//range is 4-5 inclusive
       
    76 	6,		//range is 6
       
    77 	7,		//range is 7-13 inclusive
       
    78 	14,		//range is 14
       
    79 	15,		//range is 15-16 inclusive
       
    80 	17,		//range is 17-24 inclusive
       
    81 	25,		//range is 25 inclusive
       
    82 	26,		//range is 26-KMaxTInt inclusive
       
    83 	};
       
    84 
       
    85 const TUint8 CSyncEngineServer::iElementsIndex[iEngineRangeCount] = 
       
    86 	{
       
    87 	0,
       
    88 	1,
       
    89 	2,
       
    90 	3,
       
    91 	4,
       
    92 	5,
       
    93 	6,
       
    94 	7,
       
    95 	8,
       
    96 	CPolicyServer::ENotSupported,
       
    97 	};
       
    98 
       
    99 const CPolicyServer::TPolicyElement CSyncEngineServer::iElements[] = 
       
   100 	{
       
   101 	{ _INIT_SECURITY_POLICY_C2( ECapabilityReadUserData, ECapabilityWriteUserData), CPolicyServer::EFailClient},	// policy 0:  range 0 - 0
       
   102 	{ _INIT_SECURITY_POLICY_C1( ECapability_None), CPolicyServer::EFailClient},	// policy 1:  range 1 - 3
       
   103 	{ _INIT_SECURITY_POLICY_C1( ECapabilityWriteUserData), CPolicyServer::EFailClient},	// policy 2:  range 4 - 5
       
   104 	{ _INIT_SECURITY_POLICY_C1( ECapabilityReadUserData), CPolicyServer::EFailClient},	// policy 3:  range 6 - 6
       
   105 	{ _INIT_SECURITY_POLICY_C1( ECapability_None), CPolicyServer::EFailClient},	// policy 4:  range 7 - 13
       
   106 	{ _INIT_SECURITY_POLICY_C2( ECapabilityReadUserData, ECapabilityWriteUserData), CPolicyServer::EFailClient},	// policy 5:  range 14 - 14
       
   107 	{ _INIT_SECURITY_POLICY_C1( ECapabilityWriteUserData), CPolicyServer::EFailClient},	// policy 6:  range 15 - 16
       
   108 	{ _INIT_SECURITY_POLICY_C1( ECapability_None), CPolicyServer::EFailClient},	// policy 7:  range 17 - 24
       
   109 #ifdef _DEBUG
       
   110 	{ _INIT_SECURITY_POLICY_C1( ECapability_None), CPolicyServer::EFailClient}, // policy 8: range 25
       
   111 #else
       
   112 	{ _INIT_SECURITY_POLICY_FAIL}, // policy 8: range 25
       
   113 #endif
       
   114 	};
       
   115 
       
   116 const CPolicyServer::TPolicy CSyncEngineServer::iPolicy = 
       
   117 	{
       
   118 	CPolicyServer::EAlwaysPass ,
       
   119 	iEngineRangeCount,
       
   120 	iRanges,
       
   121 	iElementsIndex,
       
   122 	iElements
       
   123 	};
       
   124 
       
   125 
       
   126 /**
       
   127  *  Static factory method used to create a CSyncEngineServer object.
       
   128  *
       
   129  *  @param aPhoneBookManager  Reference to the front-end servers's phonebook
       
   130  *                            manager.
       
   131  *
       
   132  *  @return  Pointer to the created CSyncEngineServer object, or NULL.
       
   133  */
       
   134 CSyncEngineServer* CSyncEngineServer::NewL(CPhoneBookManager& aPhoneBookManager)
       
   135 	{
       
   136 	LOGENGINE1(_L8("NewL()"));
       
   137 
       
   138 	CSyncEngineServer*  self = new (ELeave) CSyncEngineServer(aPhoneBookManager);
       
   139 	CleanupStack::PushL(self);
       
   140 	self->ConstructL();
       
   141 	CleanupStack::Pop(self);
       
   142 
       
   143 	return self;
       
   144 	} // CSyncEngineServer::NewL
       
   145 
       
   146 
       
   147 /**
       
   148  *  Standard constructor.
       
   149  *
       
   150  *  @param aPhoneBookManager  Reference to the front-end servers's phonebook
       
   151  *                            manager.
       
   152  */
       
   153 CSyncEngineServer::CSyncEngineServer(CPhoneBookManager& aPhoneBookManager)
       
   154 	: CPolicyServer(EPriorityNormal, iPolicy, ESharableSessions), 
       
   155 	iICCCaps(RMobilePhone::KCapsSimAccessSupported), 
       
   156 	iPhoneBookSyncEngineStarter(NULL),
       
   157 	iConnectedSession(NULL),
       
   158 	iPhonebookManager(aPhoneBookManager),
       
   159 	iSyncContactsWithICC(NULL),
       
   160 	iWriteContactToICC(NULL),
       
   161 	iDeleteContactFromICC(NULL)
       
   162 	{
       
   163 	__DECLARE_NAME(_L("CSyncEngineServer"));
       
   164 	} // CSyncEngineServer::CSyncEngineServer
       
   165 
       
   166 
       
   167 /**
       
   168  *  Second phase constructor. Ensures the server is created and ready to run.
       
   169  */
       
   170 void CSyncEngineServer::ConstructL()
       
   171 	{
       
   172 	StartL(PHBKSYNC_ENGINE_NAME);
       
   173 	} // CSyncEngineServer::ConstructL
       
   174 
       
   175 
       
   176 /**
       
   177  *  Destructor.
       
   178  */
       
   179 CSyncEngineServer::~CSyncEngineServer()
       
   180 	{
       
   181 	//
       
   182 	// Stop the engine from starting if it has initiated a startup.
       
   183 	//
       
   184 	delete iPhoneBookSyncEngineStarter;
       
   185 	iPhoneBookSyncEngineStarter = NULL;
       
   186 	
       
   187 	//
       
   188 	// Unconfigure the engine if needed...
       
   189 	//
       
   190 	TRAP_IGNORE(UnconfigureEngineL());
       
   191 
       
   192 	delete iSyncContactsWithICC;
       
   193 	delete iWriteContactToICC;
       
   194 	delete iDeleteContactFromICC;
       
   195 	} // CSyncEngineServer::~CSyncEngineServer
       
   196 
       
   197 
       
   198 /**
       
   199  *  Configures the engine for use. This includes opening the ETel handles,
       
   200  *  connecting to the contacts database and opening the phonebook stores.
       
   201  */
       
   202 void CSyncEngineServer::ConfigureEngineL()
       
   203 	{
       
   204 	LOGENGINE1(_L8("CSyncEngineServer::ConfigureEngineL()"));
       
   205 
       
   206 	//
       
   207 	// Connect to ETel...
       
   208 	//
       
   209 	TInt  etelErr(KErrNone), retryCount;
       
   210 
       
   211 	for (retryCount = 0;  retryCount < KMaxConnectToEtelRetries;  retryCount++)
       
   212 		{
       
   213 		TRAP(etelErr, ConnectToEtelL());	//This can leave due to a denied access 										
       
   214 											//to CommDb or Etel
       
   215 		if (etelErr == KErrNone)
       
   216 			{
       
   217 			break;
       
   218 			}
       
   219 
       
   220 		if (retryCount < KMaxConnectToEtelRetries - 1)
       
   221 			{
       
   222 			User::After(1000000);
       
   223 			}
       
   224 		}
       
   225 	User::LeaveIfError(etelErr);
       
   226 
       
   227 	//
       
   228 	// Open the Contacts DB...
       
   229 	//
       
   230 	TInt  dbErr(KErrNone);
       
   231 
       
   232 	for (retryCount = 0;  retryCount < KMaxDbAccessRetryCount;  retryCount++)
       
   233 		{
       
   234 		TRAP(dbErr, iDb = CContactDatabase::OpenL());	// First try to open existing database
       
   235 		
       
   236 		if (dbErr == KErrNotFound)
       
   237 			{
       
   238 			TRAP(dbErr, iDb = CContactDatabase::CreateL()); // Database does not exist so create and open new one
       
   239 			}
       
   240 		
       
   241 		if (dbErr == KErrNone)
       
   242 			{
       
   243 			break;
       
   244 			}
       
   245 
       
   246 		if (retryCount < KMaxDbAccessRetryCount - 1)
       
   247 			{
       
   248 			User::After(1000000);
       
   249 			}
       
   250 		}
       
   251 	User::LeaveIfError(dbErr);
       
   252 
       
   253 	//
       
   254 	// Setup the phonebook parameters, read the settings from the INI
       
   255 	// file and create the phonebook group IDs...
       
   256 	//
       
   257 	if (iPhone.GetIccAccessCaps(iICCCaps) != KErrNone) // Get type of ICC that is being used 
       
   258 		{
       
   259 		iICCCaps = RMobilePhone::KCapsSimAccessSupported; // set default value
       
   260 		}
       
   261 
       
   262 	CreatePhoneBookIdsL();
       
   263 	} // CSyncEngineServer::ConfigureEngineL
       
   264 
       
   265 
       
   266 /**
       
   267  *  Unconfigures the engine ready to shutdown.
       
   268  */
       
   269 void CSyncEngineServer::UnconfigureEngineL()
       
   270 	{
       
   271 	LOGENGINE1(_L8("CSyncEngineServer::UnconfigureEngineL()"));
       
   272 
       
   273 	iPhonebookManager.ClosePhoneBookStores();
       
   274 
       
   275 	delete iDb;
       
   276 	iDb = NULL;
       
   277 
       
   278 	iPhone.Close();
       
   279 	iEtelServer.Close();
       
   280 	} // CSyncEngineServer::UnconfigureEngineL
       
   281 
       
   282 
       
   283 /**
       
   284  *  Create a Template ID for the specified phonebook.
       
   285  *
       
   286  *  @param aPhonebookUid  UID of the phonebook to create an ID for.
       
   287  *  @param aICCCaps       The capabilities of the phone.
       
   288  */
       
   289 void CSyncEngineServer::CreateTemplateIdL(TUid aPhonebookUid,
       
   290 										  TUint32 aICCCaps)
       
   291 	{
       
   292 	LOGENGINE2(_L8("CreateTemplateIdL(0x%08x)"), aPhonebookUid);
       
   293 
       
   294 	TContactItemId  templateId(KNullContactId);
       
   295 	
       
   296 	//
       
   297 	// Check if there is an existing template in the contact database for
       
   298 	// this phonebook...
       
   299 	//
       
   300 	CContactIdArray*  idList = iDb->GetCardTemplateIdListL();
       
   301 	CleanupStack::PushL(idList);	
       
   302 	
       
   303 	if (idList != NULL  &&  idList->Count() > 0)
       
   304 		{
       
   305 		TInt  idCount = idList->Count();
       
   306 
       
   307 		for (TInt index = 0;  index < idCount;  index++)
       
   308 			{
       
   309 			CContactCardTemplate* item = static_cast<CContactCardTemplate*> (iDb->ReadContactLC((*idList)[index]));
       
   310 
       
   311 			if ((aPhonebookUid == KUidIccGlobalAdnPhonebook  && 
       
   312 				 item->GetTemplateLabelL() == KPhbkTemplateADN)  ||
       
   313 				(aPhonebookUid == KUidIccGlobalSdnPhonebook  && 
       
   314 				 item->GetTemplateLabelL() == KPhbkTemplateSDN)  ||
       
   315 				(aPhonebookUid == KUidIccGlobalLndPhonebook  && 
       
   316 				 item->GetTemplateLabelL() == KPhbkTemplateLND)  ||
       
   317 				(aPhonebookUid == KUidUsimAppAdnPhonebook  && 
       
   318 				 item->GetTemplateLabelL() == KPhbkTemplateUSimApp)  ||
       
   319 				(aPhonebookUid == KUidIccGlobalFdnPhonebook  && 
       
   320 				 item->GetTemplateLabelL() == KPhbkTemplateFDN))
       
   321 				{
       
   322 				templateId = (*idList)[index];
       
   323 
       
   324 				User::LeaveIfError(iPhonebookManager.SetTemplateId(aPhonebookUid,
       
   325 																   templateId));
       
   326 
       
   327 				index = idCount; // to terminate loop
       
   328 				}
       
   329 			CleanupStack::PopAndDestroy(item);
       
   330 			}
       
   331 		}
       
   332 	CleanupStack::PopAndDestroy(idList);
       
   333 
       
   334 	//
       
   335 	// If no suitable template been found create a new one...
       
   336 	//
       
   337 	if (templateId == KNullContactId)
       
   338 		{
       
   339 		LOGENGINE2(_L8("CreateTemplateIdL(0x%08x): Creating template."),
       
   340 				   aPhonebookUid);
       
   341 
       
   342 		CContactItem*  newTemplate;
       
   343 
       
   344 		if (aPhonebookUid == KUidIccGlobalAdnPhonebook)
       
   345 			{
       
   346 			newTemplate = iDb->CreateContactCardTemplateLC(KPhbkTemplateADN);
       
   347 			}
       
   348 		else if (aPhonebookUid == KUidIccGlobalSdnPhonebook)
       
   349 			{
       
   350 			newTemplate = iDb->CreateContactCardTemplateLC(KPhbkTemplateSDN);
       
   351 			}
       
   352 		else if (aPhonebookUid == KUidIccGlobalLndPhonebook)
       
   353 			{
       
   354 			newTemplate = iDb->CreateContactCardTemplateLC(KPhbkTemplateLND);
       
   355 			}
       
   356 		else if (aPhonebookUid == KUidUsimAppAdnPhonebook)
       
   357 			{
       
   358 			newTemplate = iDb->CreateContactCardTemplateLC(KPhbkTemplateUSimApp);
       
   359 			}
       
   360 		else if (aPhonebookUid == KUidIccGlobalFdnPhonebook)
       
   361 			{
       
   362 			newTemplate = iDb->CreateContactCardTemplateLC(KPhbkTemplateFDN);
       
   363 			}
       
   364 		else
       
   365 			{
       
   366 			newTemplate = iDb->CreateContactCardTemplateLC(KPhbkTemplateNotSpecified);
       
   367 			}
       
   368 
       
   369 		templateId = newTemplate->Id();
       
   370 		CleanupStack::PopAndDestroy(newTemplate);
       
   371 
       
   372 		//
       
   373 		// Remove all the unnecessary fields...
       
   374 		//
       
   375 		newTemplate = iDb->OpenContactLX(templateId);
       
   376 		CleanupStack::PushL(newTemplate);	
       
   377 		const TInt fieldCount = newTemplate->CardFields().Count();
       
   378 		for(TInt i=fieldCount-1;i>=0;i--)
       
   379 			{
       
   380 			newTemplate->RemoveField(i);
       
   381 			}
       
   382 
       
   383 		//
       
   384 		// Add default name field...
       
   385 		//
       
   386 		CContactItemField* name = CContactItemField::NewLC(KStorageTypeText,KUidContactFieldFamilyName);
       
   387 		name->SetMapping(KUidContactFieldVCardMapUnusedN);
       
   388 		newTemplate->AddFieldL(*name);
       
   389 		CleanupStack::Pop(name);
       
   390 			
       
   391 		//
       
   392 		// Add second name field...
       
   393 		//
       
   394 		CContactItemField* secondName = CContactItemField::NewLC(KStorageTypeText,KUidContactFieldSecondName);
       
   395 		secondName->SetMapping(KUidContactFieldVCardMapSECONDNAME);
       
   396 		secondName->SetUserFlags(EContactCategoryHome);
       
   397 		newTemplate->AddFieldL(*secondName);
       
   398 		CleanupStack::Pop(secondName);
       
   399 			
       
   400 		//
       
   401 		// Add default number field...
       
   402 		//
       
   403 		CContactItemField* number = CContactItemField::NewLC(KStorageTypeText,KUidContactFieldPhoneNumber);
       
   404 		number->SetMapping(KUidContactFieldVCardMapTEL);
       
   405 		number->AddFieldTypeL(KUidContactFieldVCardMapWORK);
       
   406 		number->AddFieldTypeL(KUidContactFieldVCardMapVOICE);
       
   407 		number->AddFieldTypeL(KUidContactFieldVCardMapCELL);
       
   408 		newTemplate->AddFieldL(*number);
       
   409 		CleanupStack::Pop(number);
       
   410 
       
   411 		//
       
   412 		// Add Slot Number field...
       
   413 		//
       
   414 		CContactItemField* slotnum = CContactItemField::NewLC(KStorageTypeText,KUidContactFieldICCSlot);
       
   415 		slotnum->SetMapping(KUidContactFieldVCardMapNotRequired);
       
   416 		newTemplate->AddFieldL(*slotnum);
       
   417 		CleanupStack::Pop(slotnum);
       
   418 
       
   419 		//
       
   420 		// Add Phonebook type field...
       
   421 		//
       
   422 		CContactItemField* phonebook = CContactItemField::NewLC(KStorageTypeText,KUidContactFieldICCPhonebook);
       
   423 		phonebook->SetMapping(KUidContactFieldVCardMapNotRequired);
       
   424 		newTemplate->AddFieldL(*phonebook);
       
   425 		CleanupStack::Pop(phonebook);
       
   426 
       
   427 		//
       
   428 		// 3G ICC so there are additional fields for ADN and USIM App
       
   429 		// phonebooks.
       
   430 		//
       
   431 		if (aICCCaps & RMobilePhone::KCapsUSimAccessSupported)
       
   432 			{
       
   433 			if (aPhonebookUid == KUidIccGlobalAdnPhonebook  || 
       
   434 			    aPhonebookUid == KUidUsimAppAdnPhonebook)
       
   435 				{
       
   436 				//
       
   437 				// Add e-mail field...
       
   438 				//
       
   439 				CContactItemField* emailField = CContactItemField::NewLC(KStorageTypeText,KUidContactFieldEMail);
       
   440 				emailField->SetMapping(KUidContactFieldVCardMapUnusedN);
       
   441 				newTemplate->AddFieldL(*emailField);
       
   442 				CleanupStack::Pop(emailField);
       
   443 
       
   444 				//
       
   445 				// Add group field - this is different from contacts group.
       
   446 				// This field indicates group that this ICC entry belongs to.
       
   447 				// User can add this entry to a number of groups on ICC i.e.
       
   448 				// business, private, etc. 
       
   449 				//
       
   450 				CContactItemField* group = CContactItemField::NewLC(KStorageTypeText,KUidContactFieldICCGroup);
       
   451 				group->SetMapping(KUidContactFieldVCardMapUnusedN);
       
   452 				newTemplate->AddFieldL(*group);
       
   453 				CleanupStack::Pop(group);
       
   454 				}
       
   455 			}
       
   456 
       
   457 		//
       
   458 		// Store the new Template ID...
       
   459 		//
       
   460 		User::LeaveIfError(iPhonebookManager.SetTemplateId(aPhonebookUid, templateId));
       
   461 
       
   462 		iDb->CommitContactL(*newTemplate);
       
   463 		CleanupStack::PopAndDestroy(2); // newTemplate plus locked record
       
   464 		}
       
   465 	} // CSyncEngineServer::CreateTemplateIdL
       
   466 
       
   467 		
       
   468 /**
       
   469  *  Create a Group ID for the specified phonebook.
       
   470  *
       
   471  *  @param aPhonebookUid  UID of the phonebook to create an ID for.
       
   472  */
       
   473 void CSyncEngineServer::CreateGroupIdL(TUid aPhonebookUid)
       
   474 	{
       
   475 	LOGENGINE2(_L8("CreateGroupIdL(0x%08x)"), aPhonebookUid);
       
   476 
       
   477 	TContactItemId  groupId(KNullContactId);
       
   478 
       
   479 	//
       
   480 	// Check if there is an existing group in the contact database for this
       
   481 	// phonebook...
       
   482 	//
       
   483 	CContactIdArray*  idList = iDb->GetGroupIdListL();
       
   484 	CleanupStack::PushL(idList);
       
   485 
       
   486 	if (idList != NULL  &&  idList->Count() > 0)
       
   487 		{
       
   488 		LOGENGINE2(_L8("CreateGroupIdL(0x%08x): Creating template."),
       
   489 				   aPhonebookUid);
       
   490 
       
   491 		TInt  idCount = idList->Count();
       
   492 
       
   493 		for (TInt index = 0;  index < idCount;  index++)
       
   494 			{
       
   495 			//
       
   496 			// Retrieve the first entry in each group, obtain that entry's
       
   497 			// template ID and check the template label to confirm if it
       
   498 			// relates to this phonebook.
       
   499 			//
       
   500 			CContactGroup*  group = static_cast<CContactGroup*> (iDb->ReadContactLC((*idList)[index]));
       
   501 			CContactIdArray*  itemList = group->ItemsContainedLC();
       
   502 
       
   503 			if (itemList->Count() > 0)
       
   504 				{
       
   505 				CContactItem*  groupItem = iDb->ReadContactLC((*itemList)[0]);
       
   506 				TContactItemId templateId = groupItem->TemplateRefId();
       
   507 				if (templateId != KNullContactId)
       
   508 					{
       
   509 					CContactCardTemplate*  tempItem = static_cast<CContactCardTemplate*> (iDb->ReadContactLC(templateId));
       
   510 					
       
   511 					TPtrC templateLabel;
       
   512 					TRAPD(errorCheck, templateLabel.Set(tempItem->GetTemplateLabelL()));
       
   513 					
       
   514 					// Check if the first item in the group uses a template with a label then check to see if the
       
   515 					// label matches one of the Phonebook template labels
       
   516 					if(errorCheck != KErrNotFound)
       
   517 						{
       
   518 						if(	(aPhonebookUid == KUidIccGlobalAdnPhonebook && templateLabel == KPhbkTemplateADN) ||
       
   519 				   			(aPhonebookUid == KUidIccGlobalSdnPhonebook && templateLabel == KPhbkTemplateSDN) ||
       
   520 						   	(aPhonebookUid == KUidIccGlobalLndPhonebook && templateLabel == KPhbkTemplateLND) ||
       
   521 						   	(aPhonebookUid == KUidIccGlobalFdnPhonebook && templateLabel == KPhbkTemplateFDN) ||
       
   522 							(aPhonebookUid == KUidUsimAppAdnPhonebook   && templateLabel == KPhbkTemplateUSimApp))
       
   523 							{
       
   524 							groupId = (*idList)[index];
       
   525 							User::LeaveIfError(iPhonebookManager.SetGroupId(aPhonebookUid,groupId));
       
   526 							index = idCount; // to terminate loop
       
   527 							}
       
   528 						}
       
   529 					CleanupStack::PopAndDestroy(tempItem);	
       
   530 					}
       
   531 				CleanupStack::PopAndDestroy(groupItem);
       
   532 				}
       
   533 			CleanupStack::PopAndDestroy(2, group); // itemList, group
       
   534 			}
       
   535 		}
       
   536 
       
   537 	//
       
   538 	// If no suitable group has been found create a new one...
       
   539 	//
       
   540 	if (groupId == KNullContactId)
       
   541 		{
       
   542 		//
       
   543 		// Store the new group ID...
       
   544 		//
       
   545  		CContactItem*  group = iDb->CreateContactGroupLC(KNullDesC);
       
   546  		groupId = group->Id();
       
   547 
       
   548 		User::LeaveIfError(iPhonebookManager.SetGroupId(aPhonebookUid, groupId));
       
   549  		CleanupStack::PopAndDestroy(group);
       
   550 		}
       
   551 
       
   552 	CleanupStack::PopAndDestroy(idList);
       
   553 	} // CSyncEngineServer::CreateGroupIdL
       
   554 
       
   555 
       
   556 /**
       
   557  *  Create the template ID and group ID for all supported phonebooks. These
       
   558  *  IDs are to be used with the entries that reside on a particular phonebook.
       
   559  */
       
   560 void CSyncEngineServer::CreatePhoneBookIdsL()
       
   561 	{
       
   562 	LOGENGINE1(_L8("CreatePhoneBookIdsL()"));
       
   563 
       
   564 	//
       
   565 	// Ensure each phonebook has its templates created...
       
   566 	//
       
   567 	TInt  phonebookUidCount(iPhonebookManager.GetPhonebookCount());
       
   568 	
       
   569 	for (TInt index = 0;  index < phonebookUidCount;  index++)
       
   570 		{
       
   571 		TUid  phonebookUid;
       
   572 		
       
   573 		User::LeaveIfError(iPhonebookManager.GetPhonebookUid(index,
       
   574 															 phonebookUid));
       
   575 
       
   576 		LOGENGINE2(_L8("CreatePhoneBookIdsL: Phonebook=0x%08x"), phonebookUid);
       
   577 
       
   578 		//
       
   579 		// Get the template ID...
       
   580 		//
       
   581 		TContactItemId  templateId;
       
   582 		
       
   583 		User::LeaveIfError(iPhonebookManager.GetTemplateId(phonebookUid,
       
   584 														   templateId));
       
   585 
       
   586 		//
       
   587 		// Validate any template ID already provided in INI file
       
   588 		//
       
   589 		if (templateId != KNullContactId)
       
   590 			{
       
   591 			CContactItem*  item(NULL);
       
   592 			
       
   593 			TRAPD(err, item = iDb->ReadContactL(templateId));
       
   594 			CleanupStack::PushL(item);
       
   595 			
       
   596 			if (err == KErrNotFound)
       
   597 				{
       
   598  				User::LeaveIfError(iPhonebookManager.SetTemplateId(phonebookUid,
       
   599  																   KNullContactId));
       
   600 				templateId = KNullContactId;
       
   601 				}
       
   602 			else if (err != KErrNone)
       
   603 				{
       
   604 				User::Leave(err);
       
   605 				}
       
   606 			else if (item == NULL  ||  item->Type() != KUidContactCardTemplate)
       
   607 				{
       
   608  				User::LeaveIfError(iPhonebookManager.SetTemplateId(phonebookUid,
       
   609  																   KNullContactId));
       
   610 				templateId = KNullContactId;
       
   611 				}
       
   612 			else
       
   613 				{
       
   614 				TPtrC  label = static_cast<CContactCardTemplate*>(item)->GetTemplateLabelL();
       
   615 				
       
   616 				//
       
   617 				// The following test confirms if a template ID relates to this
       
   618 				// phonebook's template by checking the label employed.
       
   619 				//
       
   620 				if (!((phonebookUid == KUidIccGlobalAdnPhonebook  &&  label == KPhbkTemplateADN)  ||
       
   621 					  (phonebookUid == KUidIccGlobalSdnPhonebook  &&  label == KPhbkTemplateSDN)  ||
       
   622 					  (phonebookUid == KUidIccGlobalLndPhonebook  &&  label == KPhbkTemplateLND)  ||
       
   623 					  (phonebookUid == KUidUsimAppAdnPhonebook  &&  label == KPhbkTemplateUSimApp)  ||
       
   624 					  (phonebookUid == KUidIccGlobalFdnPhonebook  &&  label == KPhbkTemplateFDN)))
       
   625 					{
       
   626 	 				User::LeaveIfError(iPhonebookManager.SetTemplateId(phonebookUid,
       
   627  																	   KNullContactId));
       
   628 					templateId = KNullContactId;
       
   629 					}
       
   630 				}
       
   631 
       
   632 			CleanupStack::PopAndDestroy(item);
       
   633 			}
       
   634 
       
   635 		//
       
   636 		// If we don't have a template ID, then create a template...
       
   637 		//
       
   638 		if (templateId == KNullContactId)
       
   639 			{
       
   640 			CreateTemplateIdL(phonebookUid, iICCCaps);
       
   641 			}
       
   642 
       
   643 		//
       
   644 		// Get the group ID...
       
   645 		//
       
   646 		TContactItemId  groupId;
       
   647 		
       
   648 		User::LeaveIfError(iPhonebookManager.GetGroupId(phonebookUid, groupId));
       
   649 
       
   650 		//
       
   651 		// Validate any group ID already provided in INI file
       
   652 		//
       
   653 		if (groupId != KNullContactId)
       
   654 			{
       
   655 			CContactItem*  item = NULL;
       
   656 			TRAPD(err, item = iDb->ReadContactL(groupId));
       
   657 			CleanupStack::PushL(item);
       
   658 
       
   659 			if (err == KErrNotFound)
       
   660 				{
       
   661 				User::LeaveIfError(iPhonebookManager.SetGroupId(phonebookUid,
       
   662 																KNullContactId));
       
   663 				groupId = KNullContactId;
       
   664 				}
       
   665 			else if (err != KErrNone)
       
   666 				{
       
   667 				User::Leave(err);
       
   668 				}
       
   669 			else if (item == NULL  ||  item->Type() != KUidContactGroup)
       
   670 				{
       
   671 				User::LeaveIfError(iPhonebookManager.SetGroupId(phonebookUid,
       
   672 																KNullContactId));
       
   673 				groupId = KNullContactId;
       
   674 				}
       
   675 			else
       
   676 				{
       
   677 				//
       
   678 				// The following test is a simplistic method to determine
       
   679 				// if the group ID represents a phonebook group - as
       
   680 				// employed by LPD for Linnea. It does not attempt to check
       
   681 				// if it relates to the correct type of phonebook.
       
   682 				//
       
   683 				if (static_cast<CContactGroup*>(item)->GetGroupLabelL() != KNullDesC)
       
   684 					{
       
   685 					User::LeaveIfError(iPhonebookManager.SetGroupId(phonebookUid,
       
   686 																	KNullContactId));
       
   687 					groupId = KNullContactId;
       
   688 					}
       
   689 				}
       
   690 			CleanupStack::PopAndDestroy(item);
       
   691 			}
       
   692 
       
   693 		if (groupId == KNullContactId)
       
   694 			{
       
   695 			CreateGroupIdL(phonebookUid);
       
   696 			}
       
   697 		}
       
   698 	} // CSyncEngineServer::CreatePhoneBookIdsL
       
   699 
       
   700 
       
   701 /**
       
   702  *  Removes all the contact entries for a phonebook. This is called when a
       
   703  *  sync request is made on an unsupported phonebook so that it can be
       
   704  *  cleared.
       
   705  *
       
   706  *  @param aPhonebookUid  UID of the ICC phonebook to perform the operation on.
       
   707  */
       
   708 void CSyncEngineServer::RemoveAllContactsForPhoneBookL(TUid aPhonebookUid)
       
   709 	{
       
   710 	LOGENGINE2(_L8("RemoveAllContactsForPhoneBookL(0x%08x)"), aPhonebookUid);
       
   711 
       
   712 	//
       
   713 	// Get the Group ID to search for entries. If no ID exists then the
       
   714 	// database does not contain any entries.
       
   715 	//
       
   716 	TContactItemId  groupId;
       
   717 	
       
   718 	User::LeaveIfError(iPhonebookManager.GetGroupId(aPhonebookUid, groupId));
       
   719 
       
   720  	//
       
   721  	// Delete all entries for this group ID...
       
   722  	//
       
   723  	if (groupId != KNullContactId  &&  groupId != KGoldenTemplateId)
       
   724 		{
       
   725  		CContactItem*  group = iDb->ReadContactLC(groupId);
       
   726  		const CContactIdArray*  members = static_cast<CContactGroup*>(group)->ItemsContained();
       
   727  		const TInt  count = members->Count();
       
   728 
       
   729 		for (TInt item = 0;  item < count;  item++)
       
   730 			{
       
   731 			iDb->DeleteContactL((*members)[item]);
       
   732 			}
       
   733 
       
   734 		CleanupStack::PopAndDestroy(group);
       
   735 
       
   736 		//
       
   737 		// Compress the database if needed and we are finished!
       
   738 		//
       
   739 		if (iDb->CompressRequired())
       
   740 			{
       
   741 			TRAP_IGNORE(iDb->CompactL());
       
   742 			}
       
   743 		}
       
   744 	} // CSyncEngineServer::RemoveAllContactsForPhoneBookL
       
   745 
       
   746 
       
   747 /**
       
   748  *  This method synchronises the specified phonebook. The synchronisation is
       
   749  *  done by creating an instance of the CSyncContactsWithICC Active Object 
       
   750  *  class and then starting it.
       
   751  *
       
   752  *  @param aMessage       A reference to the front-end server request.
       
   753  *  @param aPhonebookUid  UID of the ICC phonebook to perform the operation on.
       
   754  */
       
   755 void CSyncEngineServer::DoSynchronisationL(const RMessage2& aMessage,
       
   756 										   TUid aPhonebookUid)
       
   757 	{
       
   758 	LOGENGINE2(_L8("DoSynchronisationL(0x%08x)"), aPhonebookUid);
       
   759 
       
   760 	//
       
   761 	// Set the cache state to unsynchronised to start with.
       
   762 	//
       
   763 	TInt  result;
       
   764 
       
   765 	result = iPhonebookManager.SetSyncState(aPhonebookUid,
       
   766 											RPhoneBookSession::EUnsynchronised);
       
   767 	if (result != KErrNone)
       
   768 		{
       
   769 		iConnectedSession->CompleteRequest(aMessage, result);
       
   770 		return;
       
   771 		}
       
   772 
       
   773 	//
       
   774 	// Has the PhBkInfo structure been received yet? If not then this
       
   775 	// phonebook is not usable...
       
   776 	//
       
   777 	TInt  phBkInfoRetrievedResult;
       
   778 	
       
   779 	result = iPhonebookManager.GetPhBkInfoRetrievedResult(aPhonebookUid,
       
   780 														  phBkInfoRetrievedResult);
       
   781 	if (result != KErrNone)
       
   782 		{
       
   783 		iPhonebookManager.SetLastSyncError(aPhonebookUid, result);
       
   784    		iPhonebookManager.SetSyncState(aPhonebookUid, RPhoneBookSession::EErrorDuringSync);
       
   785 
       
   786 		iConnectedSession->CompleteRequest(aMessage, result);
       
   787 		return;
       
   788 		}
       
   789 	
       
   790 	if (phBkInfoRetrievedResult != KErrNone)
       
   791 		{
       
   792 		//		
       
   793 		// The phonebook has been found to not exist, and a sync has been
       
   794 		// requested, so remove all entries from the database.
       
   795 		//
       
   796 		RemoveAllContactsForPhoneBookL(aPhonebookUid);
       
   797 
       
   798 		iPhonebookManager.SetLastSyncError(aPhonebookUid, phBkInfoRetrievedResult);
       
   799    		iPhonebookManager.SetSyncState(aPhonebookUid, RPhoneBookSession::EErrorDuringSync);
       
   800 
       
   801 		iConnectedSession->CompleteRequest(aMessage, phBkInfoRetrievedResult);
       
   802 		return;
       
   803 		}
       
   804 
       
   805 	//
       
   806 	// Check that the phone store was opened...
       
   807 	//
       
   808 	RMobilePhoneBookStore  phonebookStore;
       
   809 
       
   810 	result = iPhonebookManager.GetPhoneBookStore(aPhonebookUid, iPhone,
       
   811 												 phonebookStore);
       
   812 	if (result != KErrNone)
       
   813 		{
       
   814 		iPhonebookManager.SetLastSyncError(aPhonebookUid, result);
       
   815    		iPhonebookManager.SetSyncState(aPhonebookUid, RPhoneBookSession::EErrorDuringSync);
       
   816 
       
   817 		iConnectedSession->CompleteRequest(aMessage, result);
       
   818 		return;
       
   819 		}
       
   820 
       
   821 	if (phonebookStore.SubSessionHandle() == 0)
       
   822 		{
       
   823 		//		
       
   824 		// The phonebook is not supported and a sync has been
       
   825 		// requested, so remove all entries from the database.
       
   826 		//
       
   827 		RemoveAllContactsForPhoneBookL(aPhonebookUid);
       
   828 
       
   829 		iPhonebookManager.SetLastSyncError(aPhonebookUid, KErrNotSupported);
       
   830    		iPhonebookManager.SetSyncState(aPhonebookUid, RPhoneBookSession::EErrorDuringSync);
       
   831 
       
   832 		iConnectedSession->CompleteRequest(aMessage, KErrNotSupported);
       
   833 		return;
       
   834 		}
       
   835 
       
   836 	//
       
   837 	// Ensure there is no left sync in progress (there should not be!)...
       
   838 	//
       
   839 	if (iSyncContactsWithICC != NULL)
       
   840 		{
       
   841 		iPhonebookManager.SetLastSyncError(aPhonebookUid, KErrServerBusy);
       
   842    		iPhonebookManager.SetSyncState(aPhonebookUid, RPhoneBookSession::EErrorDuringSync);
       
   843 
       
   844 		iConnectedSession->CompleteRequest(aMessage, KErrServerBusy);
       
   845 		return;
       
   846 		}
       
   847 
       
   848 	//
       
   849 	// Create the Active Object that will perform the sync...
       
   850 	//
       
   851 	iSyncContactsWithICC = CSyncContactsWithICC::NewL(*iConnectedSession,
       
   852 													  iPhonebookManager,
       
   853 													  *iDb,
       
   854 													  iPhone,
       
   855 													  aPhonebookUid,
       
   856 													  aMessage);
       
   857 
       
   858 	//
       
   859 	// Start reading phonebook entries and populating Contacts DB...
       
   860 	//	
       
   861 	TRAPD(error, iSyncContactsWithICC->SyncContactsWithICCL());
       
   862 	if (error != KErrNone)
       
   863 		{
       
   864 		CompleteDoSync(error);
       
   865 		}
       
   866 	} // CSyncEngineServer::DoSynchronisationL
       
   867 
       
   868 
       
   869 /**
       
   870  *  Delete an entry specified by aContactId from the ICC phonebook store
       
   871  *  specified. It performs the opperation by creating a CDeleteContactFromICC
       
   872  *  Active Object and starting it.
       
   873  *
       
   874  *  @param aMessage       A reference to the front-end server request.
       
   875  *  @param aPhonebookUid  UID of the phonebook containing the entry.
       
   876  *  @param aContactId     ID of the contact to delete.
       
   877  */
       
   878 void CSyncEngineServer::DeleteCntFromICCL(const RMessage2& aMessage,
       
   879 										  TUid aPhonebookUid,
       
   880 										  TContactItemId  aContactId)
       
   881 	{
       
   882 	LOGENGINE2(_L8("DeleteCntFromICCL(0%d)"), aContactId);
       
   883 
       
   884 	//
       
   885 	// This request can only proceed if the cache is valid...
       
   886 	//
       
   887 	RPhoneBookSession::TSyncState  syncState;
       
   888 	TInt  result;
       
   889 	
       
   890 	result = iPhonebookManager.GetSyncState(aPhonebookUid, syncState);
       
   891 	if (result != KErrNone)
       
   892 		{
       
   893 		iConnectedSession->CompleteRequest(aMessage, result);
       
   894 		return;
       
   895 		}
       
   896 	
       
   897 	if (syncState != RPhoneBookSession::ECacheValid)
       
   898 		{
       
   899 		iConnectedSession->CompleteRequest(aMessage, KErrNotReady);
       
   900 		return;
       
   901 		}
       
   902 
       
   903 	//
       
   904 	// Check that ICC is not locked, blocked OR pin protected...
       
   905 	//
       
   906 	if (iPhonebookManager.IsPin1Valid() == EFalse)
       
   907 		{
       
   908 		iConnectedSession->CompleteRequest(aMessage, KErrAccessDenied);
       
   909 		return;
       
   910 		}
       
   911 
       
   912 	//
       
   913 	// If this is a USIM App ADN phonebook then check that USIM PIN is valid...
       
   914 	//
       
   915 	if (aPhonebookUid == KUidUsimAppAdnPhonebook  && 
       
   916 		iPhonebookManager.IsUsimAppPinValid() == EFalse)
       
   917 		{
       
   918 		iConnectedSession->CompleteRequest(aMessage, KErrAccessDenied);
       
   919 		return;
       
   920 		}
       
   921 				
       
   922 	//
       
   923 	// If this is the FDN phonebook then check that PIN2 is valid...
       
   924 	//
       
   925 	if (aPhonebookUid == KUidIccGlobalFdnPhonebook  && 
       
   926 		iPhonebookManager.IsPin2Valid() == EFalse)
       
   927 		{
       
   928 		iConnectedSession->CompleteRequest(aMessage, KErrAccessDenied);
       
   929 		return;
       
   930 		}
       
   931 				
       
   932 	//
       
   933 	// Now create and run the Active Object which will process this
       
   934 	// delete request...
       
   935 	//
       
   936 	if (iDeleteContactFromICC != NULL)
       
   937 		{
       
   938 		iConnectedSession->CompleteRequest(aMessage, KErrServerBusy);
       
   939 		return;
       
   940 		}
       
   941 
       
   942 	iDeleteContactFromICC = CDeleteContactFromICC::NewL(*iConnectedSession,
       
   943 														iPhonebookManager,
       
   944 														*iDb,
       
   945 														iPhone,
       
   946 														aPhonebookUid,
       
   947 														aMessage); 
       
   948 	iDeleteContactFromICC->DoIccDelete(aContactId);
       
   949 	} // CSyncEngineServer::DeleteCntFromICCL
       
   950 
       
   951 
       
   952 /**
       
   953  *  Completes an outstanding Delete-from-ICC request. It is called by the
       
   954  *  active object CPhoneBookDoIccDelete class when it has finished its task.
       
   955  *  The functin completes the front-end server's DeleteContact request.
       
   956  * 
       
   957  *  @param aRetVal  Complete-request error code.
       
   958  */
       
   959 void CSyncEngineServer::CompleteDoIccDelete(TInt aRetVal)
       
   960 	{
       
   961 	LOGENGINE2(_L8("CompleteDoIccDelete(%d)"), aRetVal);
       
   962 
       
   963 	//
       
   964 	// Complete the session request and delete the Active Object...
       
   965 	//
       
   966 	iConnectedSession->CompleteRequest(iDeleteContactFromICC->ClientMessage(),
       
   967 									   aRetVal);
       
   968 
       
   969 	delete iDeleteContactFromICC;
       
   970 	iDeleteContactFromICC = NULL;
       
   971 	} // CSyncEngineServer::CompleteDoIccDelete
       
   972 
       
   973 
       
   974 /**
       
   975  *  Write an entry to the ICC phonebook store. This is performed by creating an
       
   976  *  Active Object to request the write via ETel. The PIN1 and PIN2 (if FDN)
       
   977  *  must be valid to perform such a request.
       
   978  *
       
   979  *  @param aMessage     A reference to the front-end server request.
       
   980  *  @param aTemplateId  ID of the template to use.
       
   981  *  @param aBufferSize  Size of the streamed ICC buffer.
       
   982  */
       
   983 void CSyncEngineServer::WriteCntToICCL(const RMessage2& aMessage,
       
   984 									   TContactItemId aTemplateId,
       
   985 									   TInt aBufferSize)
       
   986 	{
       
   987 	LOGENGINE3(_L8("CSyncEngineServer::WriteCntToICCL(): %d 0x%08x %d"),
       
   988 			   aTemplateId, aBufferSize);
       
   989 
       
   990 	//
       
   991 	// Is the ICC still in usable state for this phonebook?
       
   992 	//
       
   993 	TUid  phonebookUid = iPhonebookManager.GetPhonebookUidFromTemplateId(aTemplateId);
       
   994 
       
   995 	if (iPhonebookManager.IsPin1Valid() == EFalse  ||
       
   996 	    (phonebookUid == KUidUsimAppAdnPhonebook  &&
       
   997 	     iPhonebookManager.IsUsimAppPinValid() == EFalse)  ||
       
   998 	    (phonebookUid == KUidIccGlobalFdnPhonebook  &&
       
   999 	     iPhonebookManager.IsPin2Valid() == EFalse))
       
  1000 		{
       
  1001 		iConnectedSession->CompleteRequest(aMessage, KErrAccessDenied);
       
  1002 		return;
       
  1003 		}
       
  1004 
       
  1005 	//
       
  1006 	// Create the Active Object which will process this Write request...
       
  1007 	//
       
  1008 	if (iWriteContactToICC != NULL)
       
  1009 		{
       
  1010 		iConnectedSession->CompleteRequest(aMessage, KErrServerBusy);
       
  1011 		return;
       
  1012 		}
       
  1013 
       
  1014 	iWriteContactToICC = CWriteContactToICC::NewL(*iConnectedSession,
       
  1015 											 	  aBufferSize,
       
  1016 											 	  iPhonebookManager,
       
  1017 											 	  iPhone,
       
  1018 											 	  phonebookUid,
       
  1019 											 	  aMessage);
       
  1020 											 	  
       
  1021 	//
       
  1022 	// Setup the Active Object and begin...
       
  1023 	//
       
  1024 	TRAPD(error, iWriteContactToICC->DoIccWriteL());
       
  1025 	if (error != KErrNone)
       
  1026 		{
       
  1027 		CompleteWriteContactToICC(error);
       
  1028 		}
       
  1029 	} // CSyncEngineServer::WriteCntToICCL
       
  1030 
       
  1031 
       
  1032 /**
       
  1033  *  Complete an outstanding Write-to-ICC request. It is called by the Active
       
  1034  *  Object CWriteContactToICC class when it has finished its task. The ICC
       
  1035  *  slot number is written back to the front-end address space and the
       
  1036  *  request is completed.
       
  1037  *
       
  1038  *  @param aRetVal  Complete-request error code.
       
  1039  */
       
  1040 void CSyncEngineServer::CompleteWriteContactToICC(TInt aRetVal)
       
  1041 	{
       
  1042 	LOGENGINE2(_L8("CompleteWriteContactToICC(%d)"), aRetVal);
       
  1043 
       
  1044 	if (aRetVal == KErrNone)
       
  1045 		{
       
  1046 		TPckg<TInt>  indexPckg(iWriteContactToICC->SlotNum());
       
  1047 		TPckg<TUid>  phonebookUidPckg(iWriteContactToICC->PhonebookUid());
       
  1048 
       
  1049 		TRAPD(err1, iWriteContactToICC->ClientMessage().WriteL(1, indexPckg));
       
  1050 		TRAPD(err2, iWriteContactToICC->ClientMessage().WriteL(2, phonebookUidPckg));
       
  1051 
       
  1052 		__ASSERT_ALWAYS(err1 == KErrNone  &&  err2 == KErrNone,
       
  1053 						PhBkSyncPanic(EPhBkSyncPanicBadDescriptor));
       
  1054 		}
       
  1055 
       
  1056 	//
       
  1057 	// Complete the session request and delete the Active Object...
       
  1058 	//
       
  1059 	iConnectedSession->CompleteRequest(iWriteContactToICC->ClientMessage(),
       
  1060 									   aRetVal);
       
  1061 	
       
  1062     delete iWriteContactToICC;
       
  1063 	iWriteContactToICC = NULL;
       
  1064 	} // CSyncEngineServer::CompleteWriteContactToICC
       
  1065 
       
  1066 
       
  1067 /**
       
  1068  *  Cancel a previous synchronisation request.
       
  1069  *
       
  1070  *  @param aPhonebookUid  UID of the ICC phonebook to cancel the sync request.
       
  1071  *
       
  1072  *  @return KErrNone if the request was cancelled, otherwise returns an error.
       
  1073  */
       
  1074 TInt CSyncEngineServer::DoSynchronisationCancelL(TUid aPhonebookUid)
       
  1075 	{
       
  1076 	LOGENGINE1(_L8("CSyncEngineServer::DoSynchronisationCancelL()"));
       
  1077 
       
  1078 	if (iSyncContactsWithICC != NULL  &&
       
  1079 	    iSyncContactsWithICC->PhonebookUid() == aPhonebookUid)
       
  1080 		{
       
  1081 		//
       
  1082 		// Cancel the Active Object which is used to sync the ICC.
       
  1083 		// We call DoCancel() rather than Cancel() for two reasons:
       
  1084 		//
       
  1085 		//  1) It allows the cancel to be asynchronous, which is important
       
  1086 		//     for TSY requests that may take a long time.
       
  1087 		//
       
  1088 		//  2) It ensures the RunL is called which will call the complete
       
  1089 		//     function and hence pass the request completion to the client.
       
  1090 		//
       
  1091 		iSyncContactsWithICC->DoCancel();
       
  1092 		}
       
  1093 
       
  1094 	return(KErrNone);
       
  1095 	} // CSyncEngineServer::DoSynchronisationCancelL
       
  1096 
       
  1097 
       
  1098 /**
       
  1099  *  Cancel a previous delete request.
       
  1100  *
       
  1101  *  @param aPhonebookUid  UID of the ICC phonebook to cancel the delete request.
       
  1102  *
       
  1103  *  @return KErrNone if the request was cancelled, otherwise returns an error.
       
  1104  */
       
  1105 TInt CSyncEngineServer::DeleteCntFromICCCancelL(TUid aPhonebookUid)
       
  1106 	{
       
  1107 	LOGENGINE2(_L8("DeleteCntFromICCCancelL(0x%08x)"), aPhonebookUid);
       
  1108 
       
  1109 	if (iDeleteContactFromICC != NULL  &&
       
  1110 		iDeleteContactFromICC->PhonebookUid() == aPhonebookUid)
       
  1111 		{
       
  1112 		//
       
  1113 		// Cancel the Active Object which is used to delete the ICC entry.
       
  1114 		// We call DoCancel() rather than Cancel() for two reasons:
       
  1115 		//
       
  1116 		//  1) It allows the cancel to be asynchronous, which is important
       
  1117 		//     for TSY requests that may take a long time.
       
  1118 		//
       
  1119 		//  2) It ensures the RunL is called which will call the complete
       
  1120 		//     function and hence pass the request completion to the client.
       
  1121 		//
       
  1122 		iDeleteContactFromICC->DoCancel();
       
  1123 		}
       
  1124 
       
  1125 	return(KErrNone);
       
  1126 	} // CSyncEngineServer::DeleteCntFromICCCancelL
       
  1127 
       
  1128 
       
  1129 /**
       
  1130  *  Cancel a previous write request.
       
  1131  *
       
  1132  *  @param aPhonebookUid  UID of the ICC phonebook to cancel the write request.
       
  1133  *
       
  1134  *  @return KErrNone if the request was cancelled, otherwise returns an error.
       
  1135  */
       
  1136 TInt CSyncEngineServer::WriteCntToICCCancelL(TUid aPhonebookUid)
       
  1137 	{
       
  1138 	LOGENGINE2(_L8("WriteCntToICCCancelL(0x%08x)"), aPhonebookUid);
       
  1139 
       
  1140 	if (iWriteContactToICC != NULL  &&
       
  1141 		iWriteContactToICC->PhonebookUid() == aPhonebookUid)
       
  1142 		{
       
  1143 		//
       
  1144 		// Cancel the Active Object which is used to write the ICC entry.
       
  1145 		// We call DoCancel() rather than Cancel() for two reasons:
       
  1146 		//
       
  1147 		//  1) It allows the cancel to be asynchronous, which is important
       
  1148 		//     for TSY requests that may take a long time.
       
  1149 		//
       
  1150 		//  2) It ensures the RunL is called which will call the complete
       
  1151 		//     function and hence pass the request completion to the client.
       
  1152 		//
       
  1153 		iWriteContactToICC->DoCancel();
       
  1154 		}
       
  1155 
       
  1156 	return(KErrNone);
       
  1157 	} // CSyncEngineServer::WriteCntToICCCancelL
       
  1158 
       
  1159 
       
  1160 /**
       
  1161  *  Connect to the ETel Sever, obtains the name of the currently selected TSY
       
  1162  *  and then load the TSY.
       
  1163  *
       
  1164  *  @return KErrNone if connected successfully, otherwise return error.
       
  1165  */
       
  1166 void CSyncEngineServer::ConnectToEtelL()
       
  1167 	{
       
  1168 	LOGENGINE1(_L8("ConnectToEtelL()"));
       
  1169 	
       
  1170 	//
       
  1171 	// Obtain the name of the currently selected TSY...
       
  1172 	//
       
  1173 #ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
       
  1174 	CMDBSession* db = CMDBSession::NewLC(KCDVersion1_2);
       
  1175 #else
       
  1176 	CMDBSession* db = CMDBSession::NewLC(KCDVersion1_1);
       
  1177 #endif
       
  1178 	
       
  1179 	CMDBField<TUint32>* globalSettingField = new(ELeave) CMDBField<TUint32>(KCDTIdModemPhoneServicesSMS);
       
  1180 	CleanupStack::PushL(globalSettingField);
       
  1181 
       
  1182 	globalSettingField->SetRecordId(1);
       
  1183 	globalSettingField->LoadL(*db);
       
  1184 	TUint32 modemId = *globalSettingField;
       
  1185 
       
  1186 	CMDBField<TDesC>* tsyField = new(ELeave) CMDBField<TDesC>(KCDTIdTsyName);
       
  1187 	CleanupStack::PushL(tsyField);
       
  1188 
       
  1189 	tsyField->SetRecordId(modemId);
       
  1190 	TRAPD(err, tsyField->LoadL(*db));
       
  1191 	if (err != KErrNone)
       
  1192 		{
       
  1193 		LOGENGINE1(_L8("Unable to get default TSY"));
       
  1194 		}
       
  1195 	User::LeaveIfError(err);
       
  1196 
       
  1197 	TBuf<KCommsDbSvrMaxFieldLength> tsyName;
       
  1198 	tsyName = *tsyField;
       
  1199 
       
  1200 	CleanupStack::PopAndDestroy(3, db); // db, tsyField & globalSettingField
       
  1201 	
       
  1202 	TInt ret(iEtelServer.Connect()); // First connect to the ETel server
       
  1203 	if(ret==KErrNone)
       
  1204 		{
       
  1205 		LOGENGINE1(_L8("Loading TSY")); // Now load the TSY 
       
  1206 		ret=iEtelServer.LoadPhoneModule(tsyName);
       
  1207 		RTelServer::TPhoneInfo phoneInfo;
       
  1208 		if(ret==KErrNone)
       
  1209 			{
       
  1210 			// Determine if TSY supports V2 functionality
       
  1211 			// in event of a problem here assume that it does not
       
  1212 			ret = iEtelServer.IsSupportedByModule(tsyName, KETelExtMultimodeV2, iIsV2Tsy);
       
  1213 			if (ret != KErrNone)
       
  1214 				{
       
  1215 				iIsV2Tsy = EFalse;
       
  1216 				}
       
  1217 
       
  1218 			TInt phoneIndex(0);
       
  1219 			iEtelServer.EnumeratePhones(phoneIndex); // Get total number of phones supported by all currently loaded TSY modules
       
  1220 			while(phoneIndex-->0)
       
  1221 				{
       
  1222 				TName searchTsyName;
       
  1223 				// Check whether this phone belongs to loaded TSY
       
  1224 				if((iEtelServer.GetTsyName(phoneIndex,searchTsyName)==KErrNone) && (searchTsyName.CompareF(tsyName)==KErrNone)) 
       
  1225 					break;
       
  1226 				}
       
  1227 			iEtelServer.GetPhoneInfo(phoneIndex,phoneInfo); // Get information associated with specified phone
       
  1228 
       
  1229 			LOGENGINE1(_L8("Open the phone"));
       
  1230 			ret = iPhone.Open(iEtelServer,phoneInfo.iName); // Open and intialise the phone
       
  1231 			if (ret!=KErrNone)
       
  1232 				{
       
  1233 				LOGENGINE2(_L8("Open phone failed (ret=%d)"), ret);
       
  1234 				}
       
  1235 
       
  1236 			ret = iEtelServer.SetExtendedErrorGranularity(RTelServer::EErrorExtended);
       
  1237 			if (ret!=KErrNone)
       
  1238 				{
       
  1239 				LOGENGINE2(_L8("Cannot request Extended Errors (ret=%d)"), ret);
       
  1240 				}
       
  1241 			}
       
  1242 		else
       
  1243 			{
       
  1244 			LOGENGINE2(_L8("Could not load the TSY (ret=%d)"), ret);
       
  1245 			}
       
  1246 		}
       
  1247 	else
       
  1248 		{
       
  1249 		LOGENGINE2(_L8("Could not connect to ETel (ret=%d)"), ret);
       
  1250 		}
       
  1251 
       
  1252 	User::LeaveIfError(ret);
       
  1253 	} // CSyncEngineServer::ConnectToEtelL
       
  1254 
       
  1255 
       
  1256 /**
       
  1257  *  Append additional field types according to textual alpha tags.
       
  1258  *  The field will contain next types:
       
  1259  *  TEL {HOME|WORK} {VOICE|CELL|FAX|....}
       
  1260  *
       
  1261  *  @param  aTextTag    String that is supposed to contain tags.
       
  1262  *  @param  aCurrField  Pointer to the contact item field to which optional
       
  1263  *                      types will be added.
       
  1264  */
       
  1265 void CSyncEngineServer::AssignAlphaTagsToFieldTypeL(const TDesC16 &aTextTag,
       
  1266 												    CContactItemField* aCurrField)
       
  1267 {
       
  1268 	//
       
  1269 	// Exit immediately if there is no field pointer value...
       
  1270 	//
       
  1271 	if (aCurrField == NULL) 
       
  1272 		{
       
  1273 		return;
       
  1274 		}
       
  1275 
       
  1276 	TFieldType alphaTagUID(KUidContactFieldVCardMapHOME); // Assume HOME by default
       
  1277 
       
  1278 	CSyncContactICCEntry::TSyncEntryName textTag(aTextTag);
       
  1279 	textTag.UpperCase(); // convert text tag(s) to upper case, because later we will use KVersitParam* constants from "cntdef.h"
       
  1280 
       
  1281 	//-- try to find out the main type of the phone (WORK/HOME). Assume HOME by default
       
  1282 	if(textTag.Find(KVersitParamWork)  >= 0) 
       
  1283 		alphaTagUID = KUidContactFieldVCardMapWORK; //-- found WORK tag, assume the work phone.
       
  1284 
       
  1285 	if (!aCurrField->ContentType().ContainsFieldType(alphaTagUID))
       
  1286 		{
       
  1287 		aCurrField->AddFieldTypeL(alphaTagUID);        //-- append field type WORK/HOME
       
  1288 		}
       
  1289 
       
  1290 	//-- now try to find more additional tags VOICE/FAX/CELL etc. Assume nothing by default.
       
  1291 	alphaTagUID = TUid::Null();
       
  1292 
       
  1293 	if (textTag.Find(KVersitParamMsg) >= 0)
       
  1294 		{
       
  1295 		alphaTagUID = KUidContactFieldVCardMapMSG;
       
  1296 		}
       
  1297 	else if (textTag.Find(KVersitParamVoice) >= 0)
       
  1298 		{
       
  1299 		alphaTagUID = KUidContactFieldVCardMapVOICE;
       
  1300 		}  
       
  1301 	else if (textTag.Find(KVersitParamFax) >= 0)
       
  1302 		{
       
  1303 		alphaTagUID = KUidContactFieldVCardMapFAX;
       
  1304 		}  
       
  1305 	else if (textTag.Find(KVersitParamPref) >= 0)
       
  1306 		{
       
  1307 		alphaTagUID = KUidContactFieldVCardMapPREF;
       
  1308 		}  
       
  1309 	else if (textTag.Find(KVersitParamCell) >= 0)
       
  1310 		{
       
  1311 		alphaTagUID = KUidContactFieldVCardMapCELL;
       
  1312 		}  
       
  1313 	else if (textTag.Find(KVersitParamPager) >= 0)
       
  1314 		{
       
  1315 		alphaTagUID = KUidContactFieldVCardMapPAGER;
       
  1316 		}  
       
  1317 	else if (textTag.Find(KVersitParamBbs) >= 0)
       
  1318 		{
       
  1319 		alphaTagUID = KUidContactFieldVCardMapBBS;
       
  1320 		}  
       
  1321 	else if (textTag.Find(KVersitParamModem) >= 0)
       
  1322 		{
       
  1323 		alphaTagUID = KUidContactFieldVCardMapMODEM;
       
  1324 		}  
       
  1325 	else if (textTag.Find(KVersitParamCar) >= 0)
       
  1326 		{
       
  1327 		alphaTagUID = KUidContactFieldVCardMapCAR;
       
  1328 		}  
       
  1329 	else if (textTag.Find(KVersitParamIsdn)  >= 0)
       
  1330 		{
       
  1331 		alphaTagUID = KUidContactFieldVCardMapISDN;
       
  1332 		}  
       
  1333 	else if (textTag.Find(KVersitParamVideo) >= 0)
       
  1334 		{
       
  1335 		alphaTagUID = KUidContactFieldVCardMapVIDEO;
       
  1336 		}  
       
  1337 
       
  1338 	if (alphaTagUID != TUid::Null())
       
  1339 		{
       
  1340 		//
       
  1341 		// Append additional field type...
       
  1342 		//
       
  1343 		if (!aCurrField->ContentType().ContainsFieldType(alphaTagUID))
       
  1344 			{
       
  1345 			aCurrField->AddFieldTypeL(alphaTagUID);
       
  1346 			}
       
  1347 		}
       
  1348 	} // CSyncEngineServer::AssignAlphaTagsToFieldTypeL
       
  1349 
       
  1350 
       
  1351 /**
       
  1352  *  Decide whether the entry needs to be added to the contacts database or
       
  1353  *  the existing one needs to be updated by comparing it to the one already
       
  1354  *  stored in the database. 
       
  1355  *
       
  1356  *  Work out the write action required for this entry.
       
  1357  *
       
  1358  *  There are 3 possibilities when searching for this item in the lookup table:
       
  1359  *    1 - item is not found - needs to be added
       
  1360  *    2 - item is found and identical - no action required
       
  1361  *    3 - item is found and different - needs to be updated
       
  1362  *
       
  1363  *
       
  1364  *  Create an CContactICCEntry using the data provided by aContactItem and then
       
  1365  *  write the entry to the Contacts Database.
       
  1366  *
       
  1367  *  If it is a new entry then create an CContactICCEntry using the data provided
       
  1368  *  by aContactItem and then write to the Contacts Database. Otherwise edit the
       
  1369  *  existing ICC contact item and commit the changes to the database. 
       
  1370  * 
       
  1371  *  If the entry is hidden it will be stored in the contacts database, but the
       
  1372  *  server will also set the contact item's hidden attribute.
       
  1373  *
       
  1374  *  This means that the item will not be displayed if the view definition
       
  1375  *  excludes hidden fields. 
       
  1376  *
       
  1377  * @param aICCEntry  Phonebook Server internal format for ICC Entry 
       
  1378  *
       
  1379  * @return Contacts ID if operation was successful, otherwise a NULL ID.
       
  1380  */
       
  1381 TContactItemId CSyncEngineServer::WriteICCContactToDBL(CSyncContactICCEntry& aICCEntry)
       
  1382 	{
       
  1383 	LOGENGINE2(_L8("WriteICCContactToDBL(): 0x%08x"), aICCEntry.iPhonebookUid);
       
  1384 	
       
  1385 	//
       
  1386 	// Check if the ID does not yet exist, or is identical, to see what needs
       
  1387 	// to be done.
       
  1388 	//
       
  1389 	TInt  result;
       
  1390 	
       
  1391 	result = iPhonebookManager.GetContactIdFromSlotNum(aICCEntry.iPhonebookUid,
       
  1392 													   aICCEntry.iSlotNum,
       
  1393 													   aICCEntry.iContactId);
       
  1394 	if (result != KErrNone  &&  result != KErrNotFound)
       
  1395 		{
       
  1396 		User::Leave(result);
       
  1397 		}
       
  1398 
       
  1399 	if (result == KErrNotFound)
       
  1400 		{
       
  1401 		//
       
  1402 		// The contact doesn't exist, we will continue and add it...
       
  1403 		//
       
  1404 		LOGENGINE2(_L8("WriteICCContactToDBL(): Slot %d add"), aICCEntry.iSlotNum);
       
  1405 		aICCEntry.iContactId = KNullContactId;
       
  1406 		}
       
  1407 	else if (EntriesIdenticalL(aICCEntry, aICCEntry.iContactId))
       
  1408 		{
       
  1409 		//
       
  1410 		// The contact exists, and is identical so there is nothing to do. We
       
  1411 		// can return now...
       
  1412 		//
       
  1413 		LOGENGINE2(_L8("WriteICCContactToDBL(): Slot %d nothing to do"), aICCEntry.iSlotNum);
       
  1414 
       
  1415 		return aICCEntry.iContactId;
       
  1416 		}
       
  1417 	else
       
  1418 		{
       
  1419 		//
       
  1420 		// The entry needs to be updated. In this case, we will delete it now and then
       
  1421 		// continue and add it again (which is easier than clearing out all the fields
       
  1422 		// and lists etc.)...
       
  1423 		//
       
  1424 		LOGENGINE2(_L8("WriteICCContactToDBL(): Slot %d delete and add"), aICCEntry.iSlotNum);
       
  1425 
       
  1426 		iDb->DeleteContactL(aICCEntry.iContactId);
       
  1427 		aICCEntry.iContactId = KNullContactId;
       
  1428 		}
       
  1429 
       
  1430 	//
       
  1431 	// Get the template and group IDs...
       
  1432 	//
       
  1433 	TContactItemId  templateId;
       
  1434 	TContactItemId  groupId;
       
  1435 			
       
  1436 	User::LeaveIfError(iPhonebookManager.GetTemplateId(aICCEntry.iPhonebookUid, templateId));
       
  1437 	User::LeaveIfError(iPhonebookManager.GetGroupId(aICCEntry.iPhonebookUid, groupId));
       
  1438 
       
  1439 	//
       
  1440 	// Create template for ICC contacts items...
       
  1441 	//
       
  1442 	CContactItem* iccTemplate = iDb->ReadContactL(templateId);
       
  1443 	CleanupStack::PushL(iccTemplate); 
       
  1444 
       
  1445 	CContactICCEntry*  item = CContactICCEntry::NewL(*iccTemplate);
       
  1446 	CleanupStack::PopAndDestroy(iccTemplate); 
       
  1447 	CleanupStack::PushL(item); 
       
  1448 
       
  1449 	//
       
  1450 	// Create phone number field(s)
       
  1451 	//
       
  1452 
       
  1453 	// Default number 
       
  1454 	if (aICCEntry.iNumber.Length() != 0)
       
  1455 		{
       
  1456 		TBuf<RMobilePhone::KMaxMobileTelNumberSize>  number;
       
  1457 		if ((aICCEntry.iTON==RMobilePhone::EInternationalNumber) && (aICCEntry.iNumber[0] != KEngineInternationalPrefix()[0]))
       
  1458 			{
       
  1459 			number.Append(KEngineInternationalPrefix); // Append '+' prefix if International Number
       
  1460 			}
       
  1461 		number.Append(aICCEntry.iNumber);
       
  1462 		AddTextFieldToIccContactL(KStorageTypeText, KUidContactFieldPhoneNumber, KUidContactFieldVCardMapTEL, number, item, 0);
       
  1463 		}
       
  1464 
       
  1465 	// Check whether this is hidden entry and set its hidden attributes 
       
  1466 	if (aICCEntry.iIsHidden)
       
  1467 		{
       
  1468 		item->SetHidden(ETrue);
       
  1469 		}
       
  1470 
       
  1471 	// Additional numbers 
       
  1472 	TInt count(aICCEntry.iNumberList->Count());
       
  1473 	for (TInt i=0; i<count; ++i)
       
  1474 		{
       
  1475 		CSyncContactICCEntry::TSyncAdditionalNumber  additionalNum(aICCEntry.iNumberList->At(i));
       
  1476 
       
  1477 		// Actual number
       
  1478 		TBuf<RMobilePhone::KMaxMobileTelNumberSize> number;
       
  1479 		if((additionalNum.iTON==RMobilePhone::EInternationalNumber) && (additionalNum.iNumber[0] != KEngineInternationalPrefix()[0])) 
       
  1480 			{
       
  1481 			number.Append(KEngineInternationalPrefix); // Append '+' prefix if International Number
       
  1482 			}	
       
  1483 		number.Append(additionalNum.iNumber);
       
  1484 
       
  1485 		//-- add or modify existing text field in CContactICCEntry* item fieldset
       
  1486 		CContactItemField *pCurrField = 
       
  1487 		  AddTextFieldToIccContactL(KStorageTypeText, 
       
  1488 					    KUidContactFieldPhoneNumber, 
       
  1489 					    KUidContactFieldVCardMapTEL, 
       
  1490 					    number, 
       
  1491 					    item, 
       
  1492 					    i + 1);   // Here, 1 is used to distinguish the 
       
  1493 		                                      // default number and additional number. 
       
  1494 		                                      // The reason is that they share the
       
  1495 		                                      // same field type (see comments in 
       
  1496 		                                      // method AddTextFieldToIccContactL).
       
  1497 
       
  1498 		
       
  1499 		//-- append additional field type to the current field if any.
       
  1500 		//-- this field type is obtained from additional number alpha tag 
       
  1501 		if(pCurrField)
       
  1502 			{
       
  1503 		 	AssignAlphaTagsToFieldTypeL(additionalNum.iNumberString, pCurrField);
       
  1504 			}
       
  1505 		}
       
  1506 
       
  1507 	// Create name field
       
  1508 	if (aICCEntry.iName.Length() > 0)
       
  1509 		{
       
  1510 		AddTextFieldToIccContactL(KStorageTypeText, KUidContactFieldFamilyName, KUidContactFieldVCardMapUnusedN, aICCEntry.iName, item, 0);
       
  1511 		}
       
  1512 
       
  1513 	// Create second name field
       
  1514 	if (aICCEntry.iSecondName.Length() > 0)
       
  1515 		{
       
  1516 		AddTextFieldToIccContactL(KStorageTypeText, KUidContactFieldSecondName, KUidContactFieldVCardMapSECONDNAME, aICCEntry.iSecondName, item, 0);
       
  1517 		}
       
  1518 
       
  1519 	// Create group field(s)
       
  1520 	count = aICCEntry.iGroupList->Count();
       
  1521 	for(TInt i=0; i<count; ++i)
       
  1522 		{
       
  1523 		CSyncContactICCEntry::TSyncEntryName groupField;
       
  1524 		groupField.Copy(aICCEntry.iGroupList->At(i));
       
  1525 		AddTextFieldToIccContactL(KStorageTypeText, KUidContactFieldICCGroup, KUidContactFieldVCardMapUnusedN, groupField, item, i);
       
  1526 		}
       
  1527 
       
  1528 	// Create e-mail field(s)
       
  1529 	count = aICCEntry.iEmailList->Count();
       
  1530 	for(TInt i=0; i<count; ++i)
       
  1531 		{
       
  1532 		CSyncContactICCEntry::TSyncEntryName emailField;
       
  1533 		emailField.Copy(aICCEntry.iEmailList->At(i));
       
  1534 		AddTextFieldToIccContactL(KStorageTypeText, KUidContactFieldEMail, KUidContactFieldVCardMapEMAILINTERNET, emailField, item, i);
       
  1535 		}
       
  1536 
       
  1537 	// Create slot number field
       
  1538 	TBuf<KTemplateFieldLength> buf;
       
  1539 	buf.AppendNum(aICCEntry.iSlotNum);
       
  1540 	AddTextFieldToIccContactL(KStorageTypeText, KUidContactFieldICCSlot, KUidContactFieldVCardMapNotRequired, buf, item, 0);
       
  1541 
       
  1542 	// Create phonebook type field
       
  1543 	buf.FillZ();
       
  1544 	buf.Zero();
       
  1545 
       
  1546 	buf.AppendNum(aICCEntry.iPhonebookUid.iUid);
       
  1547 	AddTextFieldToIccContactL(KStorageTypeText, KUidContactFieldICCPhonebook, KUidContactFieldVCardMapNotRequired, buf, item, 0);
       
  1548 
       
  1549 	//
       
  1550 	// Write the contact to the database...
       
  1551 	//
       
  1552 	LOGENGINE1(_L8("WriteICCContactToDBL(): Adding contact to database"));
       
  1553 
       
  1554 	iDb->DatabaseBeginL(EFalse); // Start the transaction
       
  1555 	iIsInTransaction = ETrue; 
       
  1556 
       
  1557 	aICCEntry.iContactId = iDb->doAddNewContactL(*item, EFalse, ETrue); // Add that new contact to Contact DB 
       
  1558 	CleanupStack::PopAndDestroy(item);
       
  1559 
       
  1560 	// Add the contact to the correct group now because during
       
  1561 	// synchronisation the contacts model can't do it since the 
       
  1562 	// plug-in won't have a connection to the server (and therefore know 
       
  1563 	// which group to add it to).
       
  1564 	iDb->AddContactToGroupL(aICCEntry.iContactId, groupId, ETrue);
       
  1565 	CommitIccTransactionL();			
       
  1566 
       
  1567 	return aICCEntry.iContactId;
       
  1568 	} // CSyncEngineServer::WriteICCContactToDBL
       
  1569 
       
  1570 
       
  1571 /**
       
  1572  *  Checks if an ICC entry is the same as one in the database.
       
  1573  *
       
  1574  *  @param aICCEntry  CSyncContactICCEntry reference.
       
  1575  *  @param aId        TContactItemId reference.
       
  1576  *
       
  1577  *  @return Boolean stating if entries match.
       
  1578  */
       
  1579 TBool CSyncEngineServer::EntriesIdenticalL(CSyncContactICCEntry& aICCEntry,
       
  1580 										   TContactItemId& aId)
       
  1581 	{
       
  1582 	LOGENGINE3(_L8("EntriesIdenticalL(): 0x%08x %d"), aICCEntry.iPhonebookUid,
       
  1583 			   aId);
       
  1584 	
       
  1585 	//
       
  1586 	// Get the entry from the contacts database...
       
  1587 	//
       
  1588 	CContactItem* contactEntry=iDb->ReadContactLC(aId);
       
  1589 	CContactItemFieldSet& fieldSet = contactEntry->CardFields();
       
  1590 
       
  1591 	// Note: We have already matched the slot number field.
       
  1592 	
       
  1593 	// Check if the same amount of information is provided.
       
  1594 	// This will reduce time for comparison when there is a lot of additional
       
  1595 	// information but a small mismatch in the number of additional fields.
       
  1596 	TInt index;
       
  1597 	
       
  1598 	// Obtain number count
       
  1599 	TInt iccNumCount(aICCEntry.iNumberList->Count() + 1); // first phone number is not in additional number list
       
  1600 	TInt contactNumCount(0);
       
  1601 	index = -1;
       
  1602 	while((index = fieldSet.FindNext(KUidContactFieldPhoneNumber, index+1)) != KErrNotFound)
       
  1603 		{
       
  1604 		contactNumCount++;
       
  1605 		}
       
  1606 	
       
  1607 	// Obtain group count
       
  1608 	TInt iccGrpCount(aICCEntry.iGroupList->Count());
       
  1609 	TInt contactGrpCount(0);
       
  1610 	index = -1;
       
  1611 	while((index = fieldSet.FindNext(KUidContactFieldICCGroup, index+1)) != KErrNotFound)
       
  1612 		{
       
  1613 		const CContactItemField& testField = fieldSet[index];
       
  1614 		TPtrC testFieldPtr(testField.TextStorage()->Text());
       
  1615 		if (testFieldPtr.Length() > 0) // entry for SDN & LND will have group field but it will be empty
       
  1616 			{
       
  1617 			contactGrpCount++;
       
  1618 			}
       
  1619 		}
       
  1620 		
       
  1621 	// Obtain email count
       
  1622 	TInt iccEmailCount(aICCEntry.iEmailList->Count());
       
  1623 	TInt contactEmailCount(0);
       
  1624 	index = -1;
       
  1625 	while((index = fieldSet.FindNext(KUidContactFieldEMail, index+1)) != KErrNotFound)
       
  1626 		{
       
  1627 		const CContactItemField& testField = fieldSet[index];
       
  1628 		TPtrC testFieldPtr(testField.TextStorage()->Text());
       
  1629 		if (testFieldPtr.Length() > 0)  // entry for SDN & LND will have email field but it will be empty
       
  1630 			{
       
  1631 			contactEmailCount++;
       
  1632 			}
       
  1633 		}
       
  1634 		
       
  1635 	// Test field counts and exit if these don't match
       
  1636 	if(	(contactNumCount != iccNumCount) ||
       
  1637 		(contactGrpCount != iccGrpCount) ||
       
  1638 		(contactEmailCount != iccEmailCount) ||
       
  1639 		(contactNumCount < 1))
       
  1640 		{
       
  1641 		CleanupStack::PopAndDestroy(contactEntry);
       
  1642 		return EFalse;
       
  1643 		}
       
  1644 		
       
  1645 	// Detailed test of first representation of name
       
  1646 	TInt loop(0);
       
  1647 	TBool contentMatch(ETrue);
       
  1648 
       
  1649 	index = fieldSet.Find(KUidContactFieldFamilyName); // start with family name
       
  1650 	if (index != KErrNotFound) 
       
  1651 		{
       
  1652 		const CContactItemField& testField1 = fieldSet[index];
       
  1653 		TPtrC testFieldPtr1(testField1.TextStorage()->Text());
       
  1654 		if (testFieldPtr1.Compare(aICCEntry.iName) != 0)
       
  1655 			{
       
  1656 			contentMatch = EFalse;
       
  1657 			}
       
  1658 		}
       
  1659 	else if (aICCEntry.iName.Length() > 0)
       
  1660 		{
       
  1661 		contentMatch = EFalse;
       
  1662 		}
       
  1663 
       
  1664 	// Detailed test of second representation of name
       
  1665 	if (contentMatch)
       
  1666 		{
       
  1667 		index = fieldSet.Find(KUidContactFieldSecondName); // get second name
       
  1668 		if (index != KErrNotFound)
       
  1669 			{
       
  1670 			const CContactItemField& testField1 = fieldSet[index];
       
  1671 			TPtrC testFieldPtr1(testField1.TextStorage()->Text());
       
  1672 			if (testFieldPtr1.Compare(aICCEntry.iSecondName) != 0)
       
  1673 				{
       
  1674 				contentMatch = EFalse;
       
  1675 				}
       
  1676 			}
       
  1677 		else if (aICCEntry.iSecondName.Length() > 0)
       
  1678 			{
       
  1679 			contentMatch = EFalse;
       
  1680 			}
       
  1681 		}
       
  1682 
       
  1683 	if (contentMatch)
       
  1684 		{
       
  1685 		// Detailed test of phone number information
       
  1686 		// Note: the first phone number is stored separately from additional numbers
       
  1687 		//       and as a result this loop treats it differently.  The loop counter
       
  1688 		//       is adjusted to allow for this number not being in the additional number list
       
  1689 		index = fieldSet.Find(KUidContactFieldPhoneNumber);
       
  1690 		for (loop = 0;
       
  1691 			 (loop < iccNumCount) && (index != KErrNotFound) && contentMatch; 
       
  1692 			 loop++)
       
  1693 			{
       
  1694 			const CContactItemField& testField2 = fieldSet[index];
       
  1695 			TBuf<RMobilePhone::KMaxMobileTelNumberSize> testFieldPtr2 = testField2.TextStorage()->Text();
       
  1696 			TBool isInternationalCntNumber(EFalse);
       
  1697 
       
  1698 			if (testFieldPtr2.Find(KEngineInternationalPrefix)!=KErrNotFound)
       
  1699 				{
       
  1700 				testFieldPtr2 = testFieldPtr2.Mid(1);
       
  1701 				isInternationalCntNumber = ETrue;
       
  1702 				}
       
  1703 
       
  1704 			// retrieving the number from the ICC entry
       
  1705 			TBool isInternationalICCNumber;
       
  1706 			TBuf<RMobilePhone::KMaxMobileTelNumberSize> testFieldPtr5; 
       
  1707 			if (loop == 0) // first phone number is stored separately
       
  1708 				{
       
  1709 				testFieldPtr5 = aICCEntry.iNumber;
       
  1710 				isInternationalICCNumber = (aICCEntry.iTON==RMobilePhone::EInternationalNumber);
       
  1711 				}
       
  1712 			else 
       
  1713 				{
       
  1714 				testFieldPtr5 = aICCEntry.iNumberList->At(loop - 1).iNumber;
       
  1715 				isInternationalICCNumber = (aICCEntry.iNumberList->At(loop - 1).iTON==RMobilePhone::EInternationalNumber);
       
  1716 				}
       
  1717 
       
  1718 			// Does the ICC number contain a prefix? (apparently, some TSYs are designed to keep it)
       
  1719 			if (testFieldPtr5.Find(KEngineInternationalPrefix)!=KErrNotFound)
       
  1720 				{
       
  1721 				// If it does, strip it
       
  1722 				testFieldPtr5 = testFieldPtr5.Mid(1);
       
  1723 				// Also implies that it is international too, regardless of the aICCEntry.iTON flag value
       
  1724 				isInternationalICCNumber = ETrue;
       
  1725 				}
       
  1726 			
       
  1727 			// comparing the numbers
       
  1728 			if (  	(isInternationalCntNumber!=isInternationalICCNumber) ||
       
  1729 					(testFieldPtr2.Compare(testFieldPtr5) != 0) ) 
       
  1730 				{
       
  1731 				contentMatch = EFalse;
       
  1732 				}
       
  1733 			index = fieldSet.FindNext(KUidContactFieldPhoneNumber, index+1);  // get next additional number
       
  1734 			}
       
  1735 
       
  1736 		if (contentMatch)
       
  1737 			{
       
  1738 			// Detailed test of group information
       
  1739 			index = fieldSet.Find(KUidContactFieldICCGroup);
       
  1740 			for (	loop = 0;
       
  1741 					(loop < iccGrpCount) && (index != KErrNotFound) && contentMatch; 
       
  1742 					loop++)
       
  1743 				{
       
  1744 				const CContactItemField& testField3 = fieldSet[index];
       
  1745 				TPtrC testFieldPtr3(testField3.TextStorage()->Text());
       
  1746 
       
  1747 				// Ignore blank group entries...
       
  1748 				if (testFieldPtr3.Length() == 0)
       
  1749 					{
       
  1750 					index = fieldSet.FindNext(KUidContactFieldICCGroup, index+1);
       
  1751 					loop--;
       
  1752 					continue;
       
  1753 					}
       
  1754 
       
  1755 				if (testFieldPtr3.Compare(aICCEntry.iGroupList->At(loop)) != 0)
       
  1756 					{
       
  1757 					contentMatch = EFalse;
       
  1758 					}
       
  1759 				index = fieldSet.FindNext(KUidContactFieldICCGroup, index+1);
       
  1760 				}
       
  1761 			
       
  1762 			if (contentMatch)
       
  1763 				{
       
  1764 				// Detailed test of Email information
       
  1765 				index = fieldSet.Find(KUidContactFieldEMail);
       
  1766 				for (loop = 0;
       
  1767 					 (loop < iccEmailCount) && (index != KErrNotFound) && contentMatch; 
       
  1768 					 loop++)
       
  1769 					{
       
  1770 					const CContactItemField& testField4 = fieldSet[index];
       
  1771 					TPtrC testFieldPtr4(testField4.TextStorage()->Text());
       
  1772 
       
  1773 					// Ignore blank email entries...
       
  1774 					if (testFieldPtr4.Length() == 0)
       
  1775 						{
       
  1776 						index = fieldSet.FindNext(KUidContactFieldEMail, index+1);
       
  1777 						loop--;
       
  1778 						continue;
       
  1779 						}
       
  1780 
       
  1781 					if (testFieldPtr4.Compare(aICCEntry.iEmailList->At(loop)) != 0)
       
  1782 						{
       
  1783 						contentMatch = EFalse;
       
  1784 						}
       
  1785 					index = fieldSet.FindNext(KUidContactFieldEMail, index+1);
       
  1786 					}
       
  1787 				}
       
  1788 			}
       
  1789 		}
       
  1790 
       
  1791 	// Cleanup and return result		
       
  1792 	CleanupStack::PopAndDestroy(contactEntry);
       
  1793 
       
  1794 	return contentMatch;
       
  1795 	} // CSyncEngineServer::EntriesIdenticalL
       
  1796 
       
  1797 
       
  1798 /**
       
  1799  *  Commit the current transaction. 
       
  1800  */
       
  1801 void CSyncEngineServer::CommitIccTransactionL()
       
  1802 	{
       
  1803 	if (iIsInTransaction)
       
  1804 		{
       
  1805 		LOGENGINE1(_L8("Commit Icc Transaction"));
       
  1806 		iDb->DatabaseCommitL(EFalse);
       
  1807 		iIsInTransaction =  EFalse;
       
  1808 		}
       
  1809 	} // CSyncEngineServer::CommitIccTransactionL
       
  1810 
       
  1811 
       
  1812 /**
       
  1813  *  Rollback the current transaction. 
       
  1814  */
       
  1815 void CSyncEngineServer::RollbackIccTransaction()
       
  1816 	{
       
  1817 	if (iIsInTransaction)
       
  1818 		{
       
  1819 		LOGENGINE1(_L8("Rollback Icc Transaction"));
       
  1820 
       
  1821 		//
       
  1822 		// Transaction must be rolled back if a failure occurs otherwise
       
  1823 		// Contacts Database will become corrupt...
       
  1824 		//
       
  1825 		iDb->DatabaseRollback();
       
  1826 
       
  1827 		//
       
  1828 		// Check whether database is damaged and needs to be recovered. This
       
  1829 		// should never happen...
       
  1830 		//
       
  1831 		if (iDb->IsDamaged())
       
  1832 			{
       
  1833 			TRAPD(recoverErr, iDb->RecoverL());
       
  1834 			if (recoverErr == KErrDiskFull)
       
  1835 				{
       
  1836 				//
       
  1837 				// The disk is full, compact the database and check for
       
  1838 				// damage again. Not much else we can do!
       
  1839 				//
       
  1840 				TRAPD(compactErr, iDb->CompactL());
       
  1841 
       
  1842 				if (compactErr != KErrNone  &&  iDb->IsDamaged())
       
  1843 					{
       
  1844 					TRAPD(recoverErr2, iDb->RecoverL());
       
  1845 					if (recoverErr2 == KErrDiskFull)
       
  1846 						{
       
  1847 						TRAP_IGNORE(iDb->CompactL());
       
  1848 						}
       
  1849 					}
       
  1850 				}
       
  1851 			}
       
  1852 		
       
  1853 		//
       
  1854 		// We're no longer in a transaction...
       
  1855 		//
       
  1856 		iIsInTransaction = EFalse;
       
  1857 		}
       
  1858 	} // CSyncEngineServer::RollbackIccTransaction
       
  1859 
       
  1860 
       
  1861 /**
       
  1862  *  Add a new text field (aField) to the CContactICCEntry supplied by aIccEntry. 
       
  1863  *
       
  1864  * @param aType       Field Storage type 
       
  1865  * @param aFieldType  Field type
       
  1866  * @param aMapping    Mapping for the field's content type
       
  1867  * @param aField      Field data
       
  1868  * @param aIccEntry   CContactICCEntry item
       
  1869  * @param aCount      Identifies which instance of field is to be used. Actually
       
  1870  *					  it is an index of an object in one of vectors from
       
  1871  *					  CSyncContactICCEntry class.
       
  1872  *
       
  1873  * @return            Pointer to the current (modified or added) field in
       
  1874  *                    aIccEntry fieldset so that it is possible to get access
       
  1875  *                    to this field later. Can be NULL.
       
  1876  */ 
       
  1877 CContactItemField* CSyncEngineServer::AddTextFieldToIccContactL(TStorageType aType,
       
  1878 																TFieldType aFieldType,
       
  1879 																TUid aMapping,
       
  1880 																TDesC& aField,
       
  1881 																CContactICCEntry* aIccEntry,
       
  1882 																TInt aCount)
       
  1883 	{
       
  1884 	CContactItemFieldSet& fieldSet = aIccEntry->CardFields();
       
  1885 	TInt pos(KErrNotFound);
       
  1886 	for (TInt i = 0; i <= aCount; i++)
       
  1887 		{
       
  1888 		// "pos+1" below provides a new start position for the FindNext.
       
  1889 		pos = fieldSet.FindNext(aFieldType, pos + 1); 
       
  1890 		if (pos == KErrNotFound)
       
  1891 			break;
       
  1892 		}
       
  1893 
       
  1894     CContactItemField   *pCurrField = NULL;  // pointer to the current field in fieldset
       
  1895 
       
  1896     if (pos!=KErrNotFound) // Field already present. Note, Contacts model reads all fields
       
  1897 			   // in template and adds them as empty fields in ICC item
       
  1898 		{
       
  1899 		// If the "aCount" identified instance field already exists in the "fieldSet",
       
  1900 		// then update it.
       
  1901 
       
  1902 		CContactItemField& field=fieldSet[pos];
       
  1903 		field.TextStorage()->SetTextL(aField);
       
  1904 		
       
  1905         pCurrField = &field;
       
  1906         }
       
  1907 	else
       
  1908 		{
       
  1909 		// If there is no field in the "fieldSet" whose type is the given "aFieldType",
       
  1910 		// then create a new field and add it into the "fieldSet". 
       
  1911 		// Or
       
  1912 		// If the "aCount" identified instance field does not exist in the "fieldSet",
       
  1913 		// then create a new field and add it into the "fieldSet".
       
  1914 
       
  1915 		CContactItemField* field=CContactItemField::NewLC(aType, aFieldType);
       
  1916 		field->SetMapping(aMapping);
       
  1917 		field->AddFieldTypeL(aFieldType); // Appends a field type to the field's content type
       
  1918 		field->TextStorage()->SetTextL(aField);
       
  1919 		aIccEntry->AddFieldL(*field);
       
  1920 		CleanupStack::Pop(field); // No need to destroy it since contact item takes ownership of field
       
  1921 		
       
  1922         pCurrField = field;
       
  1923         }
       
  1924 
       
  1925 	return pCurrField;
       
  1926 	} // CSyncEngineServer::AddTextFieldToIccContactL
       
  1927 
       
  1928 
       
  1929 /**
       
  1930  *  Create a new client session.
       
  1931  */
       
  1932 CSession2* CSyncEngineServer::NewSessionL(const TVersion& /*aVersion*/,
       
  1933 										  const RMessage2& /*aMessage*/) const
       
  1934 	{
       
  1935 	LOGENGINE1(_L8("CSyncEngineServer::NewSessionL"));
       
  1936 
       
  1937 	//
       
  1938 	// Only one session connection is allowed!!!
       
  1939 	//
       
  1940 	if (iConnectedSession != NULL)
       
  1941 		{
       
  1942 		User::Leave(KErrPermissionDenied);
       
  1943 		}
       
  1944 		
       
  1945 	return new(ELeave) CSyncEngineSession();
       
  1946 	} // CSyncEngineServer::NewSessionL
       
  1947 
       
  1948 
       
  1949 /**
       
  1950  *  Called when a new session is being created.
       
  1951  *
       
  1952  *  @param aSession  Server side session.
       
  1953  */
       
  1954 void CSyncEngineServer::AddSessionL(CSyncEngineSession* aSession)
       
  1955 	{
       
  1956 	LOGENGINE1(_L8("CSyncEngineServer::AddSession"));
       
  1957 	
       
  1958 	//
       
  1959 	// Store the session pointer...
       
  1960 	//
       
  1961 	iConnectedSession = aSession;
       
  1962 
       
  1963 	//
       
  1964 	// Queue an Active Object to configure the engine straight after this
       
  1965 	// session is created.
       
  1966 	//
       
  1967 	if (iPhoneBookSyncEngineStarter == NULL)
       
  1968 		{
       
  1969 		iPhoneBookSyncEngineStarter = new (ELeave) CPhoneBookSyncEngineStarter(*this);
       
  1970 		iPhoneBookSyncEngineStarter->Call();
       
  1971 		}
       
  1972 	} // CSyncEngineServer::AddSessionL
       
  1973 
       
  1974 
       
  1975 /**
       
  1976  *  Called when a session is being destroyed.
       
  1977  */
       
  1978 void CSyncEngineServer::DropSession(CSyncEngineSession* /*aSession*/)
       
  1979 	{
       
  1980 	LOGENGINE1(_L8("CSyncEngineServer::DropSession"));
       
  1981 
       
  1982 	iConnectedSession = NULL;
       
  1983 	TRAP_IGNORE(UnconfigureEngineL());
       
  1984 
       
  1985 	CActiveScheduler::Stop();
       
  1986 	} // CSyncEngineServer::DropSession
       
  1987 
       
  1988 
       
  1989 /**
       
  1990  *  Standard Active Object RunError() method, called when the RunL() method
       
  1991  *  leaves, which will be when the CPhoneBookSession::ServiceL() leaves.
       
  1992  *
       
  1993  *  Find the current message and complete it before restarting the server.
       
  1994  *
       
  1995  *  @param aError  Leave code from CPhoneBookSession::ServiceL().
       
  1996  *
       
  1997  *  @return KErrNone
       
  1998  */
       
  1999 TInt CSyncEngineServer::RunError(TInt aError)
       
  2000 	{
       
  2001 	LOGENGINE2(_L8("CSyncEngineServer::RunError %d"),aError);
       
  2002 
       
  2003 	//
       
  2004 	// Complete the request with the available error code.
       
  2005 	//
       
  2006 	if (Message().IsNull() == EFalse)
       
  2007 		{
       
  2008 		Message().Complete(aError);
       
  2009 		}
       
  2010 
       
  2011 	//
       
  2012 	// The leave will result in an early return from CServer::RunL(), skipping
       
  2013 	// the call to request another message. So do that now in order to keep the
       
  2014 	// server running.
       
  2015 	//
       
  2016 	ReStart();
       
  2017 	
       
  2018 	return KErrNone;
       
  2019 	} // CSyncEngineServer::RunError
       
  2020 
       
  2021 
       
  2022 /**
       
  2023  *  This method begins the completion of a synchronisation operation. It is
       
  2024  *  called when the CSyncContactsWithICC Active Object has finished its task.
       
  2025  *
       
  2026  *  @param aRetVal  Complete-request error code.
       
  2027  */
       
  2028 void CSyncEngineServer::CompleteDoSync(TInt aRetVal)
       
  2029 	{
       
  2030 	TUid  phonebookUid = iSyncContactsWithICC->PhonebookUid();
       
  2031 	
       
  2032 	LOGENGINE3(_L8("CompleteDoSync(%d): 0x%08x"), aRetVal, phonebookUid);
       
  2033 
       
  2034 	//
       
  2035 	// Store the result of the synchronisation operation...
       
  2036 	//
       
  2037 	if (aRetVal == KErrNone)
       
  2038 		{
       
  2039 		iPhonebookManager.SetLastSyncError(phonebookUid, KErrNone);
       
  2040    		iPhonebookManager.SetSyncState(phonebookUid,
       
  2041    									   RPhoneBookSession::ECacheValid);
       
  2042 		}
       
  2043 	else if (aRetVal == KErrCancel)
       
  2044 		{
       
  2045 		iPhonebookManager.SetLastSyncError(phonebookUid, KErrCancel);
       
  2046    		iPhonebookManager.SetSyncState(iSyncContactsWithICC->PhonebookUid(),
       
  2047    									   RPhoneBookSession::EUnsynchronised);
       
  2048 		}
       
  2049    	else
       
  2050 		{
       
  2051 		iPhonebookManager.SetLastSyncError(phonebookUid, aRetVal);
       
  2052    		iPhonebookManager.SetSyncState(phonebookUid,
       
  2053    									   RPhoneBookSession::EErrorDuringSync);
       
  2054 		}
       
  2055 
       
  2056 	//
       
  2057 	// For debug purposes print out the new Look Up Table for this phonebook...
       
  2058 	//
       
  2059 #ifdef _DEBUG
       
  2060 	iPhonebookManager.LogLookUpTable(iSyncContactsWithICC->PhonebookUid());
       
  2061 #endif	
       
  2062 
       
  2063 	//
       
  2064 	// Complete this request and release the Active Object's memory...
       
  2065 	//
       
  2066 	iConnectedSession->CompleteRequest(iSyncContactsWithICC->ClientMessage(),
       
  2067 									   aRetVal);
       
  2068 
       
  2069 	delete iSyncContactsWithICC;
       
  2070 	iSyncContactsWithICC = NULL;
       
  2071 	} // CSyncEngineServer::CompleteDoSync
       
  2072 
       
  2073 
       
  2074 /**
       
  2075  *  Create and install the active scheduler.
       
  2076  */
       
  2077 CSyncEngineScheduler* CSyncEngineScheduler::New()
       
  2078 	{
       
  2079 	LOGENGINE1(_L8("CSyncEngineScheduler::New()"));
       
  2080 
       
  2081 	CSyncEngineScheduler*  scheduler = new CSyncEngineScheduler;
       
  2082 
       
  2083 	if (scheduler != NULL)
       
  2084 		{
       
  2085 		CSyncEngineScheduler::Install(scheduler);
       
  2086 		}
       
  2087 
       
  2088 	return scheduler;
       
  2089 	} // CSyncEngineScheduler::New
       
  2090 
       
  2091 
       
  2092 /**
       
  2093  *  Called if any RunL() method leaves.
       
  2094  */
       
  2095 void CSyncEngineScheduler::Error(TInt aError) const
       
  2096 	{
       
  2097 #ifdef _DEBUG
       
  2098 	LOGENGINE2(_L8("CSyncEngineScheduler::Error(%d)"), aError);
       
  2099 #else
       
  2100 	(void) aError;
       
  2101 #endif
       
  2102 
       
  2103 	PhBkSyncPanic(EPhBkSyncPanicUnexpectedLeave);
       
  2104 	} // CSyncEngineScheduler::Error
       
  2105 
       
  2106 
       
  2107 /**
       
  2108  *  Standard constructor.
       
  2109  *
       
  2110  *  @param aEngine  Reference to the engine.
       
  2111  */
       
  2112 CPhoneBookSyncEngineStarter::CPhoneBookSyncEngineStarter(CSyncEngineServer& aEngine)
       
  2113   : CAsyncOneShot(EPriorityHigh),
       
  2114     iEngine(aEngine)
       
  2115 	{
       
  2116 	// NOP
       
  2117 	} // CPhoneBookSyncEngineStarter::CPhoneBookSyncEngineStarter
       
  2118 
       
  2119 
       
  2120 /**
       
  2121  *  RunL() for the starter object. This configures the engine fully or
       
  2122  *  shuts it down.
       
  2123  */
       
  2124 void CPhoneBookSyncEngineStarter::RunL()
       
  2125 	{
       
  2126 	LOGENGINE2(_L8("CPhoneBookSyncEngineStarter::RunL(): iStatus=%d."), iStatus.Int());
       
  2127 
       
  2128 	//
       
  2129 	// Configure the engine...
       
  2130 	//
       
  2131 	TRAPD(configErr, iEngine.ConfigureEngineL());
       
  2132 	if (configErr != KErrNone)
       
  2133 		{
       
  2134 		LOGENGINE2(_L8("ConfigureEngineL() failed with error %d."), configErr);
       
  2135 
       
  2136 		//
       
  2137 		// Shutdown the engine in this case, so it can be restarted later.
       
  2138 		//
       
  2139 		TRAP_IGNORE(iEngine.UnconfigureEngineL());
       
  2140 		CActiveScheduler::Stop();
       
  2141 		}
       
  2142 	} // CPhoneBookSyncEngineStarter::RunL
       
  2143