|
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 |