|
1 /* |
|
2 * Copyright (c) 2006-2007 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: Virtual Phonebook VCard compact BCard importer |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 |
|
20 // System includes |
|
21 #include <versit.h> |
|
22 |
|
23 #include "CVPbkVCardData.h" |
|
24 #include "CVPbkVCardCompactBCardImporter.h" |
|
25 #include "VPbkVCardEngError.h" |
|
26 #include "CVPbkVCardFieldTypeProperty.h" |
|
27 #include <VPbkEng.rsg> |
|
28 |
|
29 // From Virtual Phonebook engine |
|
30 #include <MVPbkContactFieldTextData.h> |
|
31 #include <MVPbkFieldType.h> |
|
32 #include <MVPbkSingleContactOperationObserver.h> |
|
33 #include <MVPbkStoreContactField.h> |
|
34 #include <MVPbkStoreContact.h> |
|
35 #include <MVPbkContactStore.h> |
|
36 #include <MVPbkContactStoreProperties.h> |
|
37 #include <MVPbkContactCopyPolicy.h> |
|
38 #include <MVPbkContactOperationBase.h> |
|
39 |
|
40 |
|
41 #ifdef _DEBUG |
|
42 using namespace VPbkVCardEngError; |
|
43 #endif // _DEBUG |
|
44 |
|
45 namespace |
|
46 { |
|
47 enum TVPbkBCardImporterState |
|
48 { |
|
49 EGetLine, |
|
50 EStartTitleCopy, |
|
51 EAddAddress, |
|
52 EStop |
|
53 }; |
|
54 |
|
55 _LIT(KBusinessCardText, "Business Card"); // Business card signature |
|
56 _LIT(KCloseParenthesis, ")"); |
|
57 _LIT(KTelText, "tel "); |
|
58 _LIT(KFaxText, "fax "); |
|
59 _LIT(KSeparatorText, ", "); |
|
60 const TText KOpenParenthesis = '('; |
|
61 // Assume compact business card is corrupted if single field length |
|
62 // exceeds 200 bytes. This value is not officially specified anywhere. |
|
63 const TInt KBufferSize = 200; |
|
64 const TInt KStartPosition = 4; |
|
65 const TInt KLabelStartPosition = 5; |
|
66 const TInt KLabelValueDelimiterLength = 2; |
|
67 const TInt KGranularity( 2 ); |
|
68 |
|
69 // Comapct business card fixed field line numbers. |
|
70 enum TVPbkCBCFieldLines |
|
71 { |
|
72 ECBCSignatureLine = 1, |
|
73 ECBCNameLine, |
|
74 ECBCCompanyLine, |
|
75 ECBCTitleLine |
|
76 }; |
|
77 } // namespace |
|
78 |
|
79 CVPbkVCardCompactBCardImporter::CVPbkVCardCompactBCardImporter( |
|
80 RPointerArray<MVPbkStoreContact>& aImportedContacts, |
|
81 MVPbkContactStore& aTargetStore, |
|
82 RReadStream &aSourceStream, |
|
83 CVPbkVCardData& aData ) |
|
84 : CActive( EPriorityStandard ), |
|
85 iImportedContacts( aImportedContacts ), |
|
86 iTargetStore(aTargetStore), |
|
87 iData( aData ), |
|
88 iSource( aSourceStream ) |
|
89 { |
|
90 } |
|
91 |
|
92 CVPbkVCardCompactBCardImporter* CVPbkVCardCompactBCardImporter::NewL( |
|
93 RPointerArray<MVPbkStoreContact>& aImportedContacts, |
|
94 MVPbkContactStore& aTargetStore, |
|
95 RReadStream &aSourceStream, |
|
96 CVPbkVCardData& aData ) |
|
97 { |
|
98 CVPbkVCardCompactBCardImporter* self = new (ELeave) |
|
99 CVPbkVCardCompactBCardImporter( |
|
100 aImportedContacts, |
|
101 aTargetStore, |
|
102 aSourceStream, |
|
103 aData ); |
|
104 CleanupStack::PushL( self ); |
|
105 self->ConstructL(); |
|
106 CleanupStack::Pop( self ); |
|
107 return self; |
|
108 } |
|
109 |
|
110 void CVPbkVCardCompactBCardImporter::ConstructL() |
|
111 { |
|
112 CActiveScheduler::Add(this); |
|
113 iAddressArray = new( ELeave ) CDesCArrayFlat( KGranularity ); |
|
114 iCopyPolicy = &iData.CopyPolicyL( iTargetStore.StoreProperties().Uri() ); |
|
115 } |
|
116 |
|
117 CVPbkVCardCompactBCardImporter::~CVPbkVCardCompactBCardImporter() |
|
118 { |
|
119 Cancel(); |
|
120 delete iAddToFieldOperation; |
|
121 delete iCurContact; |
|
122 delete iAddressArray; |
|
123 delete iValue; |
|
124 delete iLabel; |
|
125 delete iLine; |
|
126 } |
|
127 |
|
128 void CVPbkVCardCompactBCardImporter::StartL() |
|
129 { |
|
130 iCurContact = iTargetStore.CreateNewContactLC(); |
|
131 CleanupStack::Pop(); |
|
132 iState = EGetLine; |
|
133 IssueRequest(); |
|
134 } |
|
135 |
|
136 void CVPbkVCardCompactBCardImporter::SetObserver( |
|
137 MVPbkImportOperationObserver& aObserver ) |
|
138 { |
|
139 iObserver = &aObserver; |
|
140 } |
|
141 |
|
142 void CVPbkVCardCompactBCardImporter::RunL() |
|
143 { |
|
144 switch (iState) |
|
145 { |
|
146 case EGetLine: |
|
147 { |
|
148 if (GetLineL()) |
|
149 { |
|
150 ParseLineL(); |
|
151 } |
|
152 break; |
|
153 } |
|
154 case EAddAddress: |
|
155 { |
|
156 AddAddressL(); |
|
157 break; |
|
158 } |
|
159 case EStartTitleCopy: |
|
160 { |
|
161 StartTitleCopyL(); |
|
162 break; |
|
163 } |
|
164 case EStop: |
|
165 { |
|
166 iObserver->ContactsImportingCompleted(); |
|
167 break; |
|
168 } |
|
169 default: |
|
170 { |
|
171 // Do nothing |
|
172 break; |
|
173 } |
|
174 } |
|
175 } |
|
176 |
|
177 void CVPbkVCardCompactBCardImporter::DoCancel() |
|
178 { |
|
179 delete iAddToFieldOperation; |
|
180 iAddToFieldOperation = NULL; |
|
181 } |
|
182 |
|
183 TInt CVPbkVCardCompactBCardImporter::RunError(TInt aError) |
|
184 { |
|
185 iObserver->ContactImportingFailed( aError ); |
|
186 return KErrNone; |
|
187 } |
|
188 |
|
189 void CVPbkVCardCompactBCardImporter::FieldAddedToContact( |
|
190 MVPbkContactOperationBase& aOperation) |
|
191 { |
|
192 if ( &aOperation == iAddToFieldOperation ) |
|
193 { |
|
194 delete iAddToFieldOperation; |
|
195 iAddToFieldOperation = NULL; |
|
196 IssueRequest(); |
|
197 } |
|
198 } |
|
199 |
|
200 void CVPbkVCardCompactBCardImporter::FieldAddingFailed( |
|
201 MVPbkContactOperationBase& aOperation, TInt aError) |
|
202 { |
|
203 if ( &aOperation == iAddToFieldOperation ) |
|
204 { |
|
205 delete iAddToFieldOperation; |
|
206 iAddToFieldOperation = NULL; |
|
207 if (aError == KErrNotSupported ) |
|
208 { |
|
209 // Target contact didn't support field -> continue |
|
210 IssueRequest(); |
|
211 } |
|
212 else if ( aError == KErrOverflow ) |
|
213 { |
|
214 // Target contact is full of that field |
|
215 TRAPD( res, HandleContactSwitchL() ); |
|
216 HandleError( res ); |
|
217 } |
|
218 else |
|
219 { |
|
220 iObserver->ContactImportingFailed( aError ); |
|
221 } |
|
222 } |
|
223 } |
|
224 |
|
225 void CVPbkVCardCompactBCardImporter::FieldsCopiedToContact( |
|
226 MVPbkContactOperationBase& /*aOperation*/) |
|
227 { |
|
228 ++iTargetContactIndex; |
|
229 if ( iTargetContactIndex >= iImportedContacts.Count() ) |
|
230 { |
|
231 iObserver->ContactsImported(); |
|
232 } |
|
233 else |
|
234 { |
|
235 TRAPD( res, CopyTitleL() ); |
|
236 HandleError( res ); |
|
237 } |
|
238 } |
|
239 |
|
240 void CVPbkVCardCompactBCardImporter::FieldsCopyFailed( |
|
241 MVPbkContactOperationBase& /*aOperation*/, |
|
242 TInt aError) |
|
243 { |
|
244 HandleError( aError ); |
|
245 } |
|
246 |
|
247 void CVPbkVCardCompactBCardImporter::IssueRequest() |
|
248 { |
|
249 TRequestStatus* status = &iStatus; |
|
250 User::RequestComplete(status, KErrNone); |
|
251 SetActive(); |
|
252 } |
|
253 |
|
254 TBool CVPbkVCardCompactBCardImporter::GetLineL() |
|
255 { |
|
256 delete iLine; |
|
257 iLine = NULL; |
|
258 iLine = HBufC::NewL( KBufferSize ); |
|
259 TPtr line = iLine->Des(); |
|
260 |
|
261 TBool result = EFalse; |
|
262 TInt retVal( GetLineFromStreamL( line, iSource ) ); |
|
263 if ( retVal == KErrNone || retVal == KErrEof ) |
|
264 { |
|
265 if(line.Length() > 0) |
|
266 { |
|
267 ++iLineCount; |
|
268 result = ETrue; |
|
269 } |
|
270 else |
|
271 { |
|
272 iState = EStop; |
|
273 IssueRequest(); |
|
274 } |
|
275 |
|
276 } |
|
277 if(retVal == KErrEof && line.Length() > 0 ) |
|
278 { |
|
279 iState = EAddAddress; |
|
280 } |
|
281 |
|
282 return result; |
|
283 } |
|
284 |
|
285 void CVPbkVCardCompactBCardImporter::ParseLineL() |
|
286 { |
|
287 TPtr line = iLine->Des(); |
|
288 TInt resId( ResolveFieldTypeResIdL( line ) ); |
|
289 |
|
290 if ( resId == KErrNotFound ) |
|
291 { |
|
292 IssueRequest(); |
|
293 } |
|
294 else if ( resId == R_VPBK_FIELD_TYPE_LANDPHONEGEN || |
|
295 resId == R_VPBK_FIELD_TYPE_FAXNUMBERGEN ) |
|
296 { |
|
297 // Asynchronous |
|
298 ValueAndLabelToBufL( line, resId ); |
|
299 } |
|
300 else if ( resId == R_VPBK_FIELD_TYPE_ADDRLABELGEN ) |
|
301 { |
|
302 // Synchronous |
|
303 ValueToArrayL( line ); |
|
304 IssueRequest(); |
|
305 } |
|
306 else |
|
307 { |
|
308 // Asynchronous |
|
309 ValueToBufL( line, resId ); |
|
310 } |
|
311 } |
|
312 |
|
313 void CVPbkVCardCompactBCardImporter::ValueToBufL( |
|
314 const TDesC& aBuffer, TInt aResId ) |
|
315 { |
|
316 const MVPbkFieldType* fieldType = FindFieldTypeL( aResId ); |
|
317 __ASSERT_DEBUG( fieldType, |
|
318 VPbkVCardEngError::Panic( VPbkVCardEngError::ENullFieldType ) ); |
|
319 |
|
320 AddFieldWithValueL( *fieldType, aBuffer, NULL ); |
|
321 } |
|
322 |
|
323 void CVPbkVCardCompactBCardImporter::ValueToArrayL( const TDesC& aBuffer ) |
|
324 { |
|
325 // Address is saved after all other fields have been saved |
|
326 iAddressArray->AppendL( aBuffer ); |
|
327 |
|
328 if( iValueLength ) |
|
329 { |
|
330 iValueLength += KSeparatorText().Length(); |
|
331 } |
|
332 |
|
333 iValueLength += aBuffer.Length(); |
|
334 } |
|
335 |
|
336 void CVPbkVCardCompactBCardImporter::ValueAndLabelToBufL( |
|
337 const TDesC& aBuffer, TInt aResId ) |
|
338 { |
|
339 const MVPbkFieldType* fieldType = FindFieldTypeL( aResId ); |
|
340 __ASSERT_DEBUG( fieldType, |
|
341 VPbkVCardEngError::Panic( VPbkVCardEngError::ENullFieldType ) ); |
|
342 |
|
343 // Read tel num label |
|
344 TInt position( KStartPosition ); |
|
345 |
|
346 delete iLabel; |
|
347 iLabel = NULL; |
|
348 if( aBuffer[KStartPosition] == KOpenParenthesis ) |
|
349 { |
|
350 position = aBuffer.Find( KCloseParenthesis ); |
|
351 if( position == KErrNotFound ) |
|
352 { |
|
353 return; |
|
354 } |
|
355 iLabel = HBufC::NewL( position - KStartPosition ); |
|
356 TPtr writebuf = iLabel->Des(); |
|
357 writebuf = KNullDesC; |
|
358 for( TInt i = KLabelStartPosition; i<position; i++ ) |
|
359 { |
|
360 writebuf.Append( aBuffer[i] ); |
|
361 } |
|
362 // Jump few characters |
|
363 position += KLabelValueDelimiterLength; |
|
364 } |
|
365 |
|
366 // Read value |
|
367 delete iValue; |
|
368 iValue = NULL; |
|
369 iValue = HBufC::NewL( aBuffer.Length() - position ); |
|
370 TPtr writebuf = iValue->Des(); |
|
371 writebuf = KNullDesC; |
|
372 for( TInt i = position; i < aBuffer.Length(); i++ ) |
|
373 { |
|
374 writebuf.Append( aBuffer[i] ); |
|
375 } |
|
376 |
|
377 AddFieldWithValueL( *fieldType, *iValue, iLabel ); |
|
378 } |
|
379 |
|
380 void CVPbkVCardCompactBCardImporter::AddAddressL() |
|
381 { |
|
382 if ( iAddressArray->Count() > 0 ) |
|
383 { |
|
384 // Then concatenate them with commas into one string |
|
385 // and use that as field value. |
|
386 HBufC* fielddata = HBufC::NewLC( iValueLength ); |
|
387 TPtr writebuf = fielddata->Des(); |
|
388 writebuf = KNullDesC; |
|
389 TInt count = iAddressArray->Count(); |
|
390 for( TInt i = 0; i < count; ++i ) |
|
391 { |
|
392 if( i ) |
|
393 { |
|
394 writebuf.Append( KSeparatorText ); |
|
395 } |
|
396 writebuf.Append( iAddressArray->MdcaPoint( i ) ); |
|
397 } |
|
398 |
|
399 const MVPbkFieldType* fieldType = FindFieldTypeL( R_VPBK_FIELD_TYPE_ADDRLABELGEN ); |
|
400 __ASSERT_DEBUG( fieldType, |
|
401 VPbkVCardEngError::Panic( VPbkVCardEngError::ENullFieldType ) ); |
|
402 |
|
403 AddFieldWithValueL( *fieldType, *fielddata, NULL ); |
|
404 CleanupStack::PopAndDestroy( fielddata ); |
|
405 } |
|
406 else |
|
407 { |
|
408 IssueRequest(); |
|
409 } |
|
410 |
|
411 // Address is the last field so continue with titles after address |
|
412 // has been added, or not added |
|
413 iState = EStartTitleCopy; |
|
414 } |
|
415 |
|
416 TInt CVPbkVCardCompactBCardImporter::ResolveFieldTypeResIdL( const TDesC& aBuffer ) |
|
417 { |
|
418 TInt resId( KErrNotFound ); |
|
419 switch ( iLineCount ) |
|
420 { |
|
421 case ECBCSignatureLine: |
|
422 { |
|
423 if ( aBuffer.Match( KBusinessCardText() ) == KErrNotFound ) |
|
424 { |
|
425 User::Leave( KErrNotSupported ); |
|
426 } |
|
427 return resId; |
|
428 } |
|
429 |
|
430 case ECBCNameLine: // Name |
|
431 { |
|
432 resId = R_VPBK_FIELD_TYPE_LASTNAME; |
|
433 break; |
|
434 } |
|
435 |
|
436 case ECBCCompanyLine: // Company name |
|
437 { |
|
438 resId = R_VPBK_FIELD_TYPE_COMPANYNAME; |
|
439 break; |
|
440 } |
|
441 |
|
442 case ECBCTitleLine: // Title |
|
443 { |
|
444 resId = R_VPBK_FIELD_TYPE_JOBTITLE; |
|
445 break; |
|
446 } |
|
447 } |
|
448 |
|
449 if ( resId == KErrNotFound ) // Tel numbers |
|
450 { |
|
451 if ( aBuffer.Find( KTelText ) >= 0 ) |
|
452 { |
|
453 resId = R_VPBK_FIELD_TYPE_LANDPHONEGEN; |
|
454 } |
|
455 |
|
456 else if ( aBuffer.Find( KFaxText ) >= 0 ) |
|
457 { |
|
458 resId = R_VPBK_FIELD_TYPE_FAXNUMBERGEN; |
|
459 } |
|
460 } |
|
461 if ( !iEMailFetchedFlag && resId == KErrNotFound ) |
|
462 { |
|
463 resId = R_VPBK_FIELD_TYPE_EMAILGEN; // Email address |
|
464 iEMailFetchedFlag = ETrue; |
|
465 } |
|
466 |
|
467 if ( resId == KErrNotFound )// Postal address |
|
468 { |
|
469 resId = R_VPBK_FIELD_TYPE_ADDRLABELGEN; |
|
470 } |
|
471 |
|
472 return resId; |
|
473 } |
|
474 |
|
475 void CVPbkVCardCompactBCardImporter::AddFieldWithValueL( |
|
476 const MVPbkFieldType& aFieldType, const TDesC& aValue, HBufC* aLabel ) |
|
477 { |
|
478 __ASSERT_DEBUG( !iAddToFieldOperation, |
|
479 VPbkVCardEngError::Panic( |
|
480 VPbkVCardEngError::EAddToFieldOperationAlreadyExists ) ); |
|
481 |
|
482 iAddToFieldOperation = iCopyPolicy->AddFieldToContactL( |
|
483 *iCurContact, aFieldType, aValue, aLabel, NULL, *this); |
|
484 } |
|
485 |
|
486 void CVPbkVCardCompactBCardImporter::StartTitleCopyL() |
|
487 { |
|
488 MoveCurrentContactToImportsL(); |
|
489 |
|
490 // If vcard was split to multiple contacts then copy |
|
491 // title fields from the first imported contact to the other contacts. |
|
492 const TInt oneContactImported = 1; |
|
493 if ( iImportedContacts.Count() <= oneContactImported ) |
|
494 { |
|
495 iObserver->ContactsImported(); |
|
496 } |
|
497 else |
|
498 { |
|
499 iTargetContactIndex = oneContactImported; |
|
500 CopyTitleL(); |
|
501 } |
|
502 } |
|
503 |
|
504 const MVPbkFieldType* CVPbkVCardCompactBCardImporter::FindFieldTypeL( |
|
505 TInt aFieldIndex ) |
|
506 { |
|
507 return iData.SupportedFieldTypes().Find( aFieldIndex ); |
|
508 } |
|
509 |
|
510 TInt CVPbkVCardCompactBCardImporter::GetByteFromStream( |
|
511 TInt8& aByte, RReadStream& aSourceStream) |
|
512 { |
|
513 TRAPD(err, aByte = aSourceStream.ReadInt8L()); |
|
514 return err; |
|
515 } |
|
516 |
|
517 TInt CVPbkVCardCompactBCardImporter::GetLineFromStreamL( |
|
518 TDes& aBuf, RReadStream& aSourceStream) |
|
519 { |
|
520 aBuf.SetLength(0); |
|
521 TInt8 byte=0; |
|
522 TInt retVal( KErrNone ); |
|
523 while( ( retVal = GetByteFromStream(byte, aSourceStream) ) == KErrNone) |
|
524 { |
|
525 if(byte == EKeyLineFeed) |
|
526 { |
|
527 break; |
|
528 } |
|
529 if(byte != EKeyEnter) |
|
530 { |
|
531 if (aBuf.Length() < aBuf.MaxLength()) |
|
532 { |
|
533 aBuf.Append(byte); |
|
534 } |
|
535 else |
|
536 { |
|
537 User::Leave(KErrCorrupt); |
|
538 } |
|
539 } |
|
540 } |
|
541 |
|
542 return retVal; |
|
543 } |
|
544 |
|
545 void CVPbkVCardCompactBCardImporter::HandleContactSwitchL() |
|
546 { |
|
547 // Current contact is full -> Create a new contact and |
|
548 // add the same line to that one. |
|
549 MoveCurrentContactToImportsL(); |
|
550 iCurContact = iTargetStore.CreateNewContactLC(); |
|
551 CleanupStack::Pop(); |
|
552 if ( iLine && iLine->Length() > 0 ) |
|
553 { |
|
554 // Parse same line again |
|
555 ParseLineL(); |
|
556 } |
|
557 else |
|
558 { |
|
559 // End of file -> continue with address |
|
560 AddAddressL(); |
|
561 } |
|
562 } |
|
563 |
|
564 void CVPbkVCardCompactBCardImporter::CopyTitleL() |
|
565 { |
|
566 delete iAddToFieldOperation; |
|
567 iAddToFieldOperation = NULL; |
|
568 iAddToFieldOperation = iCopyPolicy->CopyTitleFieldsL( |
|
569 *iImportedContacts[0], |
|
570 *iImportedContacts[iTargetContactIndex], |
|
571 *this ); |
|
572 } |
|
573 |
|
574 void CVPbkVCardCompactBCardImporter::MoveCurrentContactToImportsL() |
|
575 { |
|
576 iImportedContacts.AppendL( iCurContact ); |
|
577 iCurContact = NULL; |
|
578 } |
|
579 |
|
580 void CVPbkVCardCompactBCardImporter::HandleError( TInt aError ) |
|
581 { |
|
582 if ( aError != KErrNone ) |
|
583 { |
|
584 iObserver->ContactImportingFailed( aError ); |
|
585 } |
|
586 } |
|
587 TBool CVPbkVCardCompactBCardImporter::IsOwncard() |
|
588 { |
|
589 return EFalse; |
|
590 } |
|
591 |
|
592 // End of file |