phonebookengines_old/contactsmodel/cntvcard/cntvcardimport.cpp
changeset 40 b46a585f6909
equal deleted inserted replaced
37:fd64c38c277d 40:b46a585f6909
       
     1 // Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 #include "cntvcardutils.h"
       
    17 
       
    18 // System includes
       
    19 #include <badesca.h>
       
    20 #include <conlist.h>
       
    21 #include <s32mem.h> 
       
    22 
       
    23 
       
    24 // User includes
       
    25 #include <cntfldst.h>
       
    26 #include <cntfield.h>
       
    27 #include <cntdef.h>
       
    28 #include <cntitem.h>
       
    29 
       
    30 
       
    31 // Constants
       
    32 const TInt KVCardImportAddressArrayGranularity = 4;
       
    33 const TInt KContactGivenName = 1;
       
    34 const TInt KContactFamilyName = 0;
       
    35 const TInt KContactAdditionalName = 2;
       
    36 const TInt KContactPrefixName = 3;
       
    37 const TInt KContactSuffixName = 4;
       
    38 const TInt KContactPostOffice = 0;
       
    39 const TInt KContactExtendedAddress = 1;
       
    40 const TInt KContactAddress = 2;
       
    41 const TInt KContactLocality = 3;
       
    42 const TInt KContactRegion = 4;
       
    43 const TInt KContactPostcode = 5;
       
    44 const TInt KContactCountry = 6;
       
    45 
       
    46 #ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
       
    47 const TInt KContactMaxFieldNumber = 32;
       
    48 #endif
       
    49 
       
    50 /**
       
    51  * Delete name fields from a contact
       
    52  *
       
    53  * @param aContact Contact item
       
    54  */
       
    55 void CVCardToContactsAppConverter::DeleteNameFields(CContactItem& aContact)
       
    56 	{
       
    57 	const CContactItemFieldSet& fieldSet = aContact.CardFields();
       
    58 	//
       
    59 	DeleteField(aContact, fieldSet, KUidContactFieldGivenName, KUidContactFieldVCardMapUnusedN);
       
    60 	DeleteField(aContact, fieldSet, KUidContactFieldFamilyName, KUidContactFieldVCardMapUnusedN);
       
    61 	DeleteField(aContact, fieldSet, KUidContactFieldAdditionalName, KUidContactFieldVCardMapUnusedN);
       
    62 	DeleteField(aContact, fieldSet, KUidContactFieldPrefixName, KUidContactFieldVCardMapUnusedN);
       
    63 	DeleteField(aContact, fieldSet, KUidContactFieldSuffixName, KUidContactFieldVCardMapUnusedN);
       
    64 	}
       
    65 
       
    66 
       
    67 /**
       
    68  * Delete a specific field from the contact card
       
    69  *
       
    70  * @param aContact The contact
       
    71  * @param aFieldSet The contact's field set
       
    72  * @param aFieldType The type of field to delete from the field set
       
    73  * @param aMapping The additional mapping which the field must contain for it to be deleted
       
    74  */
       
    75 void CVCardToContactsAppConverter::DeleteField(CContactItem& aContact, const CContactItemFieldSet& aFieldSet, TFieldType aFieldType, TUid aMapping)
       
    76 	{
       
    77 	const TInt pos = aFieldSet.Find(aFieldType, aMapping);
       
    78 	if	(pos != KErrNotFound)
       
    79 		aContact.RemoveField(pos);
       
    80 	}
       
    81 
       
    82 
       
    83 void CVCardToContactsAppConverter::MergeSpecifiedNameFieldL(CContactItem& aContact, TFieldType aFieldType, CVCardItemAndLabel& aNames, TInt aOption, TInt aNameIndex)
       
    84 /**
       
    85  * Merge specific name fields from a contact
       
    86  *
       
    87  * @param aContact Contact item to add fields to
       
    88  * @param aFieldType Field type of field to add (TFieldType)
       
    89  * @param aNames An object containing the name and labels for 'N' property fields
       
    90  * @param aOption Import preferences (available options defined in CContactDatabase::TOptions)
       
    91  * @param aNameIndex Index into aNames
       
    92  */
       
    93 	{
       
    94 	CContactItemFieldSet& oldfieldset=aContact.CardFields();
       
    95 	const TInt pos = oldfieldset.Find(aFieldType, KUidContactFieldVCardMapUnusedN);
       
    96 	const TBool processWhitespace = (aOption & CContactVCardConverter::EConnectWhitespace);
       
    97 
       
    98 	// First check whether the field is present in the contact card
       
    99 	// Also verify that the array of address sub-values actually contains a specific
       
   100 	// value for the requested index.
       
   101 	if (aNames.ItemCount() > aNameIndex)
       
   102 		{
       
   103 		const TPtrC pValue = aNames.Item(aNameIndex);
       
   104 		const TInt length = pValue.Length();
       
   105 		if (processWhitespace)
       
   106 			{
       
   107 			TBool isSingleSpace = EFalse;
       
   108 			if (length == 1)
       
   109 				{
       
   110 				isSingleSpace = (pValue[0] == KContactVCardSpaceCharacter);
       
   111 				}
       
   112 			if	((pos != KErrNotFound) && (length || isSingleSpace))
       
   113 				{
       
   114 				// This means the PC side field is empty, so delete the corresponding device-side field.
       
   115 				aContact.RemoveField(pos);
       
   116 				}
       
   117 			if	(length && !isSingleSpace)
       
   118 				{
       
   119 				// This means the PC side field is unsupported, so ignore the corresponding contents.
       
   120 				TInt insertPos = 0;
       
   121 				SetNameFieldL(aNames, aContact, aOption, aNameIndex, aFieldType, insertPos);
       
   122 				}
       
   123 			}
       
   124 		else
       
   125 			{
       
   126 			if (pos != KErrNotFound)
       
   127 				{
       
   128 				// This means the PC side field is empty, so delete the corresponding device-side field.
       
   129 				aContact.RemoveField(pos);
       
   130 				}
       
   131 			if (length)
       
   132 				{
       
   133 				// This means the PC side field is not empty, so add the corresponding contents.
       
   134 				TInt insertPos = 0;
       
   135 				SetNameFieldL(aNames, aContact, aOption, aNameIndex, aFieldType, insertPos);
       
   136 				}
       
   137 			}
       
   138 		}
       
   139 	}
       
   140 
       
   141 
       
   142 void CVCardToContactsAppConverter::MergeNameFieldsL(CContactItem& aContact, CVCardItemAndLabel& aNames, TInt aOption, TBool aTreatAsPrn)
       
   143 /**
       
   144  * Merge name fields from a contact
       
   145  *
       
   146  * @param aContact Contact item to add fields to
       
   147  * @param aNames An object containing the name and labels for 'N' property fields
       
   148  * @param aOption Import preferences (available options defined in CContactDatabase::TOptions)
       
   149  */
       
   150 	{
       
   151 	if(aTreatAsPrn)
       
   152 		{
       
   153 		MergeSpecifiedNameFieldL(aContact, KUidContactFieldGivenNamePronunciation,	aNames, aOption, KContactGivenName);
       
   154 		MergeSpecifiedNameFieldL(aContact, KUidContactFieldFamilyNamePronunciation,	aNames, aOption, KContactFamilyName);
       
   155 		}
       
   156 	else
       
   157 		{
       
   158 		MergeSpecifiedNameFieldL(aContact, KUidContactFieldPrefixName,		aNames, aOption, KContactPrefixName);
       
   159 		MergeSpecifiedNameFieldL(aContact, KUidContactFieldGivenName,		aNames, aOption, KContactGivenName);
       
   160 		MergeSpecifiedNameFieldL(aContact, KUidContactFieldAdditionalName,	aNames, aOption, KContactAdditionalName);
       
   161 		MergeSpecifiedNameFieldL(aContact, KUidContactFieldFamilyName,		aNames, aOption, KContactFamilyName);
       
   162 		MergeSpecifiedNameFieldL(aContact, KUidContactFieldSuffixName,		aNames, aOption, KContactSuffixName);
       
   163 		}
       
   164 	}
       
   165 
       
   166 
       
   167 void CVCardToContactsAppConverter::MergeSpecifiedAddressFieldL(CContactItem& aContact, const CVCardAddress& aAddress, const TUid& aFieldUid, const TUid& aMappingUid, TInt aAddressIndex, TInt aOption)
       
   168 /**
       
   169  * Merge specific address fields from a contact
       
   170  *
       
   171  * @param aContact Contact item to add fields to
       
   172  * @param aUid The Uid of the contact
       
   173  * @param aFieldUid Contacts database Field ID
       
   174  * @param aMappingUid VCard Mapping ID
       
   175  * @param aAddress An object containing the name and labels for 'ADR' property fields
       
   176  * @param aAddressIndex Index into aAddress
       
   177  * @param aOption Import preferences (available options defined in CContactDatabase::TOptions)
       
   178  */
       
   179 	{
       
   180 	CContactItemFieldSet& oldfieldset = aContact.CardFields();
       
   181 	TInt pos = 0;
       
   182 	const TBool processWhitespace = (aOption & CContactVCardConverter::EConnectWhitespace);
       
   183 
       
   184 	if (aAddress.Mapping() == KNullUid)
       
   185 		{
       
   186 		TBool fieldFound = EFalse;
       
   187 		TInt startPos = KContactFieldSetSearchAll;
       
   188 
       
   189 		while(!fieldFound && !(pos == KErrNotFound))
       
   190 			{
       
   191 			pos = oldfieldset.FindNext(aMappingUid, startPos);
       
   192 			startPos = pos + 1;
       
   193 			if (pos != KErrNotFound )
       
   194 				{
       
   195 				CContactItemField& tempField = oldfieldset[pos];
       
   196 				const CContentType& tempContentType = tempField.ContentType();
       
   197 				TBool additionalMapFound = EFalse;
       
   198 				additionalMapFound |= tempContentType.ContainsFieldType(KUidContactFieldVCardMapHOME);
       
   199 				additionalMapFound |= tempContentType.ContainsFieldType(KUidContactFieldVCardMapWORK);
       
   200 				additionalMapFound |= tempContentType.ContainsFieldType(KUidContactFieldVCardMapPREF);
       
   201 				if (!additionalMapFound)
       
   202 					{
       
   203 					fieldFound = ETrue;
       
   204 					}
       
   205 				}
       
   206 			}
       
   207 		}
       
   208 	else
       
   209 		{
       
   210 		pos = oldfieldset.Find(aAddress.Mapping(), aMappingUid);
       
   211 		}
       
   212 
       
   213 	// First check whether the field is present in the contact card
       
   214 	// Also verify that the array of address sub-values actually contains a specific
       
   215 	// value for the requested index.
       
   216 	if (aAddress.ItemCount() > aAddressIndex)
       
   217 		{
       
   218 		const TPtrC pValue = aAddress.Item(aAddressIndex);
       
   219 		const TInt length = pValue.Length();
       
   220 		if (processWhitespace)
       
   221 			{
       
   222 			TBool isSingleSpace = EFalse;
       
   223 			if (length == 1)
       
   224 				{
       
   225 				isSingleSpace = (pValue[0] == KContactVCardSpaceCharacter);
       
   226 				}
       
   227 			if	((length || isSingleSpace) && (pos != KErrNotFound))
       
   228 				{
       
   229 				// This means the PC side field is empty, so delete the corresponding device-side field.
       
   230 				aContact.RemoveField(pos);
       
   231 				}
       
   232 			if	(length && !isSingleSpace)
       
   233 				{
       
   234 				TInt insertPos = 0;
       
   235 				SetAddressFieldL(aAddress, aContact, aOption, aAddressIndex, aFieldUid, insertPos, aMappingUid);
       
   236 				}
       
   237 			}
       
   238 		else
       
   239 			{
       
   240 			if (pos != KErrNotFound)
       
   241 				{
       
   242 				// This means the PC side field is empty, so delete the corresponding device-side field.
       
   243 				aContact.RemoveField(pos);
       
   244 				}
       
   245 			if (length)
       
   246 				{
       
   247 				// This means the PC side field is not empty, so add the corresponding contents.
       
   248 				TInt insertPos = 0;
       
   249 				SetAddressFieldL(aAddress, aContact, aOption, aAddressIndex, aFieldUid, insertPos, aMappingUid);
       
   250 				}
       
   251 			}
       
   252 		}
       
   253 	}
       
   254 
       
   255 
       
   256 void CVCardToContactsAppConverter::MergeAddressFieldsL(CContactItem& aContact, const CVCardAddress& aAddress, TInt aOption)
       
   257 /**
       
   258  * Merge a specific field from the contact card
       
   259  *
       
   260  * @param aContact Contact item to add fields to
       
   261  * @param aUid The Uid of the contact
       
   262  * @param aAddresses Address of locally stored contact
       
   263  * @param aOption Import preferences (available options defined in CContactDatabase::TOptions)
       
   264  */
       
   265 	{
       
   266 	MergeSpecifiedAddressFieldL(aContact, aAddress, KUidContactFieldPostOffice, KUidContactFieldVCardMapPOSTOFFICE, KContactPostOffice, aOption);
       
   267 	MergeSpecifiedAddressFieldL(aContact, aAddress, KUidContactFieldExtendedAddress, KUidContactFieldVCardMapEXTENDEDADR, KContactExtendedAddress, aOption);
       
   268 	MergeSpecifiedAddressFieldL(aContact, aAddress, KUidContactFieldAddress, KUidContactFieldVCardMapADR, KContactAddress, aOption);
       
   269 	MergeSpecifiedAddressFieldL(aContact, aAddress, KUidContactFieldLocality, KUidContactFieldVCardMapLOCALITY, KContactLocality, aOption);
       
   270 	MergeSpecifiedAddressFieldL(aContact, aAddress, KUidContactFieldRegion, KUidContactFieldVCardMapREGION, KContactRegion, aOption);
       
   271 	MergeSpecifiedAddressFieldL(aContact, aAddress, KUidContactFieldPostcode, KUidContactFieldVCardMapPOSTCODE, KContactPostcode, aOption);
       
   272 	MergeSpecifiedAddressFieldL(aContact, aAddress, KUidContactFieldCountry, KUidContactFieldVCardMapCOUNTRY, KContactCountry, aOption);
       
   273 	}
       
   274 
       
   275 
       
   276 TBool CVCardToContactsAppConverter::MergeVCardWithContactItemL(CContactItem &aContact, CParserVCard& aVCard, TUnknownPropertyBehaviour aUnknownPropertyBehaviour, TInt aOption)
       
   277 /**
       
   278  * Merge a vCard with an existing contact item
       
   279  *
       
   280  * @param aContact Contact item to add fields to
       
   281  * @param aVCard vCard parser object
       
   282  * @param aUnknownPropertyBehaviour Specifies how extension properties are handled
       
   283  * @param aOption Import preferences (available options defined in CContactDatabase::TOptions)
       
   284  * @return ETrue if contact item should be deleted, EFalse otherwise
       
   285  */
       
   286 	{
       
   287 	TInt ii = 0;
       
   288 	TInt count = 0;
       
   289 	//
       
   290 	TBool deleteContact = ETrue;
       
   291 	iUnknownPropertyBehaviour = aUnknownPropertyBehaviour;
       
   292 	TTime lastModified;
       
   293 	GetVCardModifiedTimeL(aVCard, lastModified);
       
   294 
       
   295 	// We're performing a merge
       
   296 	SetImportType(ECntVCardImportTypeMerge);
       
   297 
       
   298 	// Get Name
       
   299 	CVCardItemAndLabel* names = GetContactNameLC(aVCard, aOption);
       
   300 	if	(names && names->ItemCount())
       
   301 		{
       
   302 		MergeNameFieldsL(aContact, *names, aOption);
       
   303 		deleteContact = EFalse;
       
   304 		}
       
   305 	CleanupStack::PopAndDestroy(names);
       
   306 	// Get Name pronunciation
       
   307  	names = GetContactNamePrnLC(aVCard, aOption);
       
   308  	if (names && names->ItemCount())
       
   309  		{
       
   310  		MergeNameFieldsL(aContact, *names, aOption, ETrue);
       
   311  		}
       
   312  	CleanupStack::PopAndDestroy(names);
       
   313 
       
   314 	// Create address container
       
   315 	RPointerArray<CVCardAddress> addresses(KVCardImportAddressArrayGranularity);
       
   316 	CleanupStack::PushL(TCleanupItem(CVCardItemAndLabel::CleanUpResetDestroyAndCloseArray, &addresses));
       
   317 
       
   318 	// Get addresses from the vCard. This actually only retrieves four types of addresses:
       
   319 	// HOME, WORK, PREF and now additionally, 'general' addresses
       
   320 	GetAddressesL(aVCard, aOption, addresses);
       
   321 
       
   322 	// Import each of the located address field into the contact card
       
   323 	count = addresses.Count();
       
   324     for (ii=0; ii<count; ii++)
       
   325 		{
       
   326 		const CVCardAddress* address = addresses[ii];
       
   327 		MergeAddressFieldsL(aContact, *address, aOption);
       
   328 		deleteContact = EFalse;
       
   329 		}
       
   330 
       
   331 	// Finished with addresses now, so clean up
       
   332 	CleanupStack::PopAndDestroy(&addresses);
       
   333 
       
   334 	// Get Organization related information from the vCard. This actually only retrieves the Company and the Department Name
       
   335 	CDesCArrayFlat* orgList = new (ELeave)CDesCArrayFlat(4);
       
   336 	CleanupStack::PushL(orgList);
       
   337 	TInt orgCount = GetVCardPropertyAsArrayOfValuesL(aVCard, KVersitTokenORG, *orgList);
       
   338 	if(orgCount)
       
   339 		{
       
   340 		MergeOrgDetailsL(aContact,*orgList,aOption);
       
   341 		deleteContact = EFalse;
       
   342 		}
       
   343 	CleanupStack::PopAndDestroy(orgList); // orgList
       
   344 	
       
   345 	// Get Single Instance of Class Field from the vCard.
       
   346 	HBufC* singleClass = NULL;
       
   347 	singleClass = HBufC::NewLC(256);
       
   348    	TPtr ptr(singleClass->Des());
       
   349 
       
   350 	TInt classCount = GetSingleInstanceL(aVCard, KVersitTokenClass, ptr);
       
   351 	if(classCount)
       
   352 		{
       
   353 		MergeSingleInstanceL(aContact,ptr,KUidContactFieldClass, KUidContactFieldVCardMapClass,aOption);
       
   354 		deleteContact = EFalse;
       
   355 		}
       
   356 	CleanupStack::PopAndDestroy(singleClass);
       
   357 
       
   358 	// Get other properties
       
   359 	CArrayPtr<CParserProperty>* arrayOfProperties = aVCard.ArrayOfProperties();
       
   360 	CleanupStack::PushL(TCleanupItem(CleanUpResetAndDestroy, arrayOfProperties));
       
   361 	count = arrayOfProperties->Count();
       
   362 
       
   363 	//Within this loop we store the content type of the last field updated.
       
   364 	//If the content type of the current field matches, we update fieldCount
       
   365 	//This holds the position of the field to update, to prevent us from
       
   366 	//overwriting the field we just updated.
       
   367 
       
   368 	TInt fieldCount = 0;
       
   369 	CContactItemField* oldField = NULL;
       
   370 	CContactItemField* newField = NULL;
       
   371 
       
   372 	for (ii = 0; ii < count; ii++)
       
   373  	  	{
       
   374         if (((*arrayOfProperties)[ii]->Name() != KVersitTokenADR) && ((*arrayOfProperties)[ii]->Name() != KVersitTokenORG) && ((*arrayOfProperties)[ii]->Name() != KVersitTokenClass))
       
   375 		 {
       
   376 		  TBool unsupportedProperty=EFalse;
       
   377 		 
       
   378 			newField = GetVCardPropertyAsContactFieldLC((*arrayOfProperties)[ii], aOption,unsupportedProperty);
       
   379 			if (newField)
       
   380 				{
       
   381 				TInt ttnumber;
       
   382 				if (!oldField)
       
   383 					{
       
   384 					fieldCount = 1;
       
   385 					ttnumber = 1;
       
   386 					if (aOption & CContactVCardConverter::ETTFormat)
       
   387 						{
       
   388 						ttnumber = GetVCardPropertyTTNumber((*arrayOfProperties)[ii]);
       
   389 						}
       
   390 					}
       
   391 				else if (newField->ContentType().IsEqualForSyncUpdate(oldField->ContentType()))
       
   392 					{
       
   393 					ttnumber = ++fieldCount;
       
   394 					}
       
   395 				else
       
   396 					{
       
   397 					fieldCount = 1;
       
   398 					ttnumber = 1;
       
   399 					if (aOption & CContactVCardConverter::ETTFormat)
       
   400 						{
       
   401 						ttnumber = GetVCardPropertyTTNumber((*arrayOfProperties)[ii]);
       
   402 						}
       
   403 					}
       
   404 				if (oldField)
       
   405 					{
       
   406 					CleanupStack::Pop(); //newField
       
   407 					CleanupStack::PopAndDestroy(oldField);
       
   408 					oldField = NULL;
       
   409 					CleanupStack::PushL(newField);
       
   410 					}
       
   411 				oldField = newField;
       
   412 				aContact.CardFields().UpdateFieldSyncL(*newField, ttnumber);
       
   413 				if(newField->Storage()->IsFull())
       
   414 					{
       
   415 					deleteContact = EFalse;
       
   416 					}
       
   417 				newField = NULL;	
       
   418 				}
       
   419 			else if (unsupportedProperty)
       
   420 				{
       
   421 				CleanupStack::Pop();
       
   422 				deleteContact = EFalse;
       
   423 				}
       
   424 			else{
       
   425 				CleanupStack::Pop();
       
   426 				}
       
   427 			}
       
   428     	}
       
   429     //Remove all empty fields after merge
       
   430     CContactItemFieldSet &fieldset = aContact.CardFields();
       
   431     TInt i = 0;
       
   432     for(; i < fieldset.Count(); ++i)
       
   433     	{
       
   434     	if( !fieldset[i].Storage()->IsFull() )
       
   435     		{
       
   436     		fieldset.Remove( i-- );
       
   437     		}
       
   438     	}
       
   439 
       
   440 	if (newField)
       
   441 		//coverity [dead_error_begin]
       
   442 		{	
       
   443 		CleanupStack::PopAndDestroy(newField);
       
   444 		newField = NULL;
       
   445 		}
       
   446 
       
   447 	if (oldField)
       
   448 		{
       
   449 		CleanupStack::PopAndDestroy(oldField);
       
   450 		oldField = NULL;
       
   451 		}
       
   452 	
       
   453 	if (lastModified != Time::NullTTime())
       
   454 		{
       
   455     	aContact.SetLastModified(lastModified);
       
   456 		}
       
   457     CleanupStack::PopAndDestroy(arrayOfProperties);
       
   458 	return(deleteContact);
       
   459 	}
       
   460 /**
       
   461  * Set a name field. Only creates a field if the specified name text is not empty.
       
   462  *
       
   463  * @param aNames An object containing the name and labels for 'N' property fields
       
   464  * @param aContact Contact item to add fields to
       
   465  * @param aOption Import preferences (available options defined in CContactDatabase::TOptions)
       
   466  * @param aIndex Array position of field to use
       
   467  * @param aFieldType Field type of field to add (TFieldType)
       
   468  * @param aInsertPos Position in contact field set to add field
       
   469 */
       
   470 void CVCardToContactsAppConverter::SetNameFieldL(const CVCardItemAndLabel& aNames, CContactItem& aContact, TInt aOption, TInt aIndex, TFieldType aFieldType, TInt& aInsertPos) const
       
   471 	{
       
   472 	const TInt count = aNames.ItemCount();
       
   473 	const TInt labelCount = aNames.LabelCount();
       
   474 	//
       
   475 	if	(aIndex >= 0 && aIndex < count)
       
   476 		{
       
   477 		const TPtrC pFieldText(aNames.Item(aIndex));
       
   478 		TBool addField = EFalse;
       
   479 
       
   480 		if (CContactVCardConverter::EConnectWhitespace & aOption)
       
   481 			{
       
   482 			addField = CContactVCardConverter::ContainsImportableData(pFieldText, CContactVCardConverter::EPropertyValueComposite, ImportType());
       
   483 			}
       
   484 		else
       
   485 			{
       
   486 			addField = (pFieldText.Length());
       
   487 			}
       
   488 		// Only add the field if it contains some data
       
   489 		if	(addField)
       
   490 			{
       
   491 			CContactItemField* contactItemField = CContactItemField::NewLC(KStorageTypeText, aFieldType);
       
   492 			contactItemField->SetMapping(KUidContactFieldVCardMapUnusedN);
       
   493 			if ((aOption & CContactVCardConverter::EIncludeX) && (aIndex >= 0 && aIndex < labelCount))
       
   494 				contactItemField->SetLabelL(aNames.Label(aIndex));
       
   495 			//
       
   496 			HBufC* encodedText = EncodeL(pFieldText, ETrue);
       
   497 			contactItemField->TextStorage()->SetText(encodedText); // takes ownership
       
   498 			
       
   499 			aContact.InsertFieldL(*contactItemField, aInsertPos++);
       
   500 			CleanupStack::Pop(contactItemField);
       
   501 			}
       
   502 		}
       
   503 	}
       
   504 
       
   505 HBufC* CVCardToContactsAppConverter::EncodeL(const TDesC& aText, TBool aTextTobeTruncated) const
       
   506 	{
       
   507 	const TUid KUidTextToEtextNoTrim={0x10281B4C};
       
   508 	
       
   509 	// Make a copy of aText and truncate if necessary.
       
   510 	TPtr truncText(const_cast<TUint16*>(aText.Ptr()),aText.Length());
       
   511 	
       
   512 	if(aTextTobeTruncated)
       
   513 		truncText.SetLength(aText.Length()>KCntMaxTextFieldLength ? KCntMaxTextFieldLength : aText.Length());
       
   514 	else
       
   515 		truncText.SetLength(aText.Length());
       
   516 			
       
   517 	HBufC8* text=HBufC8::NewLC(truncText.Length()*2);
       
   518 	TPtr8 ptr = text->Des();
       
   519 	TInt i;
       
   520 	for (i=0; i < truncText.Length(); i++)
       
   521 		{
       
   522 		ptr.Append(truncText[i] & 0x00FF);
       
   523 		ptr.Append((truncText[i] >> 8) & 0x00FF);
       
   524 		}
       
   525 	CCnaConverterList* convList=CCnaConverterList::NewLC(); 
       
   526 	CConverterBase* conv = convList->NewConverterL(KUidTextToEtextNoTrim); 
       
   527 	if (!conv)
       
   528 		{
       
   529 		CleanupStack::PopAndDestroy();          // convList 
       
   530 		User::Leave(KErrNotSupported);
       
   531 		}
       
   532 	CleanupStack::PushL(conv);
       
   533 	CBufFlat* decodeBuffer = CBufFlat::NewL(256); 
       
   534 	CleanupStack::PushL(decodeBuffer);
       
   535 	CBufFlat* encodedBuffer = CBufFlat::NewL(256); 
       
   536 	CleanupStack::PushL(encodedBuffer);
       
   537 	decodeBuffer->InsertL(0,ptr);
       
   538 	RBufReadStream readStream;
       
   539 	RBufWriteStream writeStream;
       
   540 	readStream.Open(*decodeBuffer);
       
   541 	writeStream.Open(*encodedBuffer);
       
   542 	conv->ConvertObjectL(readStream, writeStream); 
       
   543 	readStream.Close();
       
   544 	TInt size=encodedBuffer->Size();
       
   545 	HBufC* writeBuf=HBufC::NewLC(size); 
       
   546 	TPtr resulttext = writeBuf->Des();
       
   547 	for(i = 0; i < (size - 1); i += 2)
       
   548 		{
       
   549 		resulttext.Append((encodedBuffer->Ptr(0)[i + 1] << 8) | 
       
   550 		encodedBuffer->Ptr(0)[i]);
       
   551 		}
       
   552 
       
   553 	writeStream.CommitL();
       
   554 	writeStream.Close();
       
   555 	CleanupStack::Pop(); // writebuf
       
   556 	CleanupStack::PopAndDestroy(2); // buffers 
       
   557 	CleanupStack::PopAndDestroy(2); //conv+convList 
       
   558 	CleanupStack::PopAndDestroy();  //text
       
   559 	return writeBuf;
       
   560 	}
       
   561 
       
   562 /**
       
   563  * Set name fields
       
   564  *
       
   565  * @param aNames An object containing the name and labels for 'N' property fields
       
   566  * @param aContact Contact item to add fields to
       
   567  * @param aOption Import preferences (available options defined in CContactDatabase::TOptions)
       
   568  * @param aTreatAsPronunciation If true, save name data in pronunciation fields, otherwise save as an actual name (the default)
       
   569  */
       
   570 void CVCardToContactsAppConverter::SetNameFieldsL(const CVCardItemAndLabel& aNames, CContactItem& aContact, TInt aOption, TBool aTreatAsPronunciation) const
       
   571 	{
       
   572 	TInt insertPos=0;
       
   573 	if( aTreatAsPronunciation )
       
   574 		{
       
   575 		SetNameFieldL(aNames, aContact, aOption, KContactGivenName, KUidContactFieldGivenNamePronunciation, insertPos);
       
   576 		SetNameFieldL(aNames, aContact, aOption, KContactFamilyName, KUidContactFieldFamilyNamePronunciation, insertPos);
       
   577 		}
       
   578 	else
       
   579 		{
       
   580 		SetNameFieldL(aNames, aContact, aOption, KContactPrefixName, KUidContactFieldPrefixName, insertPos);
       
   581 		SetNameFieldL(aNames, aContact, aOption, KContactGivenName, KUidContactFieldGivenName, insertPos);
       
   582 		SetNameFieldL(aNames, aContact, aOption, KContactAdditionalName, KUidContactFieldAdditionalName, insertPos);
       
   583 		SetNameFieldL(aNames, aContact, aOption, KContactFamilyName, KUidContactFieldFamilyName, insertPos);
       
   584 		SetNameFieldL(aNames, aContact, aOption, KContactSuffixName, KUidContactFieldSuffixName, insertPos);
       
   585 		}
       
   586 	}
       
   587 
       
   588 
       
   589 
       
   590 void CVCardToContactsAppConverter::SetAddressFieldL(const CVCardAddress& aAddress, CContactItem& aContact, TInt aOption, TInt aIndex, TFieldType aFieldType, TInt& aInsertPos, TUid aMapping) const
       
   591 /**
       
   592  * Set an address field
       
   593  *
       
   594  * @param aAddress An object containing the name and labels for 'ADR' property fields
       
   595  * @param aContact Contact item to add fields to
       
   596  * @param aOption Import preferences (available options defined in CContactVCardConverter::TOptions)
       
   597  * @param aIndex Array position of field to use
       
   598  * @param aFieldType Contact field type for address field
       
   599  * @param aInsertPos Position in contact field set to add field
       
   600  * @param aMapping vCard field mapping (eg. KUidContactFieldVCardMapPOSTCODE)
       
   601  */
       
   602 	{
       
   603 	const TInt count = aAddress.ItemCount();
       
   604 	if	(aIndex >= 0 && aIndex < count)
       
   605 		{
       
   606 		const TPtrC pFieldText(aAddress.Item(aIndex));
       
   607 		TBool doInsert = ETrue; // By default we process the data, but if the TimeIS flag is set, then we need to check the content first.
       
   608 
       
   609 		if (CContactVCardConverter::EConnectWhitespace & aOption)
       
   610 			{
       
   611 			doInsert = (CContactVCardConverter::ContainsImportableData(pFieldText, CContactVCardConverter::EPropertyValueComposite, ImportType()));
       
   612 			}
       
   613 		if (doInsert)
       
   614 			{
       
   615 			CContentType* content = CContentType::NewL(aFieldType, aMapping);
       
   616 			CleanupStack::PushL(content);
       
   617 
       
   618 			if	(aAddress.Mapping() != KNullUid) // KNullUid corresponds to general address
       
   619 				{
       
   620 				content->AddFieldTypeL(aAddress.Mapping());
       
   621 				}
       
   622 
       
   623 			CContactItemField* contactItemField = CContactItemField::NewLC(KStorageTypeText, *content);
       
   624 			if ((aOption & CContactVCardConverter::EIncludeX) && (aIndex >= 0 && aIndex < aAddress.LabelCount()))
       
   625 				{
       
   626 				// get the correct label
       
   627 				TBuf<25> labelName(KContactVarVCardXDashEPOCCNTMODEL);
       
   628 				labelName.AppendFormat(KContactVarVCardLABELn, aIndex);
       
   629 				TInt position=KErrNotFound;
       
   630 				TInt err = aAddress.FindLabel(labelName, position);
       
   631 				if	(err==KErrNone && position!=KErrNotFound)
       
   632 					contactItemField->SetLabelL(aAddress.Label(position));
       
   633 				}
       
   634 			
       
   635 			HBufC* encodedText = EncodeL(pFieldText, ETrue);
       
   636 			contactItemField->TextStorage()->SetText(encodedText); // takes ownership
       
   637 			
       
   638 			// The contact takes ownership of the field.
       
   639 			aContact.InsertFieldL(*contactItemField, aInsertPos++);
       
   640 			CleanupStack::Pop(contactItemField);
       
   641 			CleanupStack::PopAndDestroy(content);
       
   642 			}
       
   643 		}
       
   644 	}
       
   645 
       
   646 
       
   647 void CVCardToContactsAppConverter::SetAddressFieldsL(const CVCardAddress& aAddress, CContactItem& aContact, TInt aOption) const
       
   648 /**
       
   649  * Set the address fields
       
   650  *
       
   651  * @param aAddressses An object containing the name and labels for 'ADR' property fields
       
   652  * @param aContact Contact item to add fields to
       
   653  * @param aOption Import preferences (available options defined in CContactDatabase::TOptions)
       
   654  */
       
   655 	{
       
   656 	TInt insertPos = 0;
       
   657 	SetAddressFieldL(aAddress, aContact, aOption, KContactPostOffice, KUidContactFieldPostOffice, insertPos, KUidContactFieldVCardMapPOSTOFFICE);
       
   658 	SetAddressFieldL(aAddress, aContact, aOption, KContactExtendedAddress, KUidContactFieldExtendedAddress, insertPos, KUidContactFieldVCardMapEXTENDEDADR);
       
   659 	SetAddressFieldL(aAddress, aContact, aOption, KContactAddress, KUidContactFieldAddress, insertPos, KUidContactFieldVCardMapADR);
       
   660 	SetAddressFieldL(aAddress, aContact, aOption, KContactLocality, KUidContactFieldLocality, insertPos, KUidContactFieldVCardMapLOCALITY);
       
   661 	SetAddressFieldL(aAddress, aContact, aOption, KContactRegion, KUidContactFieldRegion, insertPos, KUidContactFieldVCardMapREGION);
       
   662 	SetAddressFieldL(aAddress, aContact, aOption, KContactPostcode, KUidContactFieldPostcode, insertPos, KUidContactFieldVCardMapPOSTCODE);
       
   663 	SetAddressFieldL(aAddress, aContact, aOption, KContactCountry, KUidContactFieldCountry, insertPos, KUidContactFieldVCardMapCOUNTRY);
       
   664 	}
       
   665 
       
   666 
       
   667 /**
       
   668  * Convert aVCard into a ContactItem. This method leaves a CContactItem instance on the cleanup stack upon exit.
       
   669  *
       
   670  * @param aVCard					vCard parser object
       
   671  * @param aAgentContact             Agent contact item. Note that this object is passed by reference but is not
       
   672  *                                  left on the cleanup stack upon exit from this function. Clients shoul re-Push
       
   673  *									this object if needed.
       
   674  * @param aUnknownPropertyBehaviour Specifies how extension properties are handled
       
   675  * @param aOption                   Import preferences (available options defined in CContactDatabase::TOptions)
       
   676  *
       
   677  * @return                          A CContactItem instance (on the cleanup stack) that has been constructed from
       
   678  *                                  the vCard data.
       
   679  */
       
   680 CContactItem* CVCardToContactsAppConverter::GetVCardAsContactItemLC(CParserVCard& aVCard, TUnknownPropertyBehaviour aUnknownPropertyBehaviour, TInt aOption)
       
   681 	{
       
   682 	TInt ii=0;
       
   683 	TInt count = 0;
       
   684 	//
       
   685 	iUnknownPropertyBehaviour = aUnknownPropertyBehaviour;
       
   686 	TTime lastModified;
       
   687 	TBuf<KUidStringLength> uidstring;
       
   688 	GetVCardModifiedTimeL(aVCard, lastModified);
       
   689 	GetVCardUidStringL(aVCard, uidstring);
       
   690 
       
   691 	//
       
   692 	CContactCard* mainContact = CContactCard::NewLC();
       
   693 	//
       
   694 	// We're performing an initial import
       
   695 	SetImportType(ECntVCardImportTypeFirstSync);
       
   696 
       
   697 	// Get Name
       
   698 	CVCardItemAndLabel* names = GetContactNameLC(aVCard, aOption);
       
   699 	if (names && names->ItemCount())
       
   700 		SetNameFieldsL(*names, *mainContact, aOption);
       
   701 	CleanupStack::PopAndDestroy(names);
       
   702 
       
   703 	// Get Name pronunciation
       
   704 	names = GetContactNamePrnLC(aVCard, aOption);
       
   705 	if (names && names->ItemCount())
       
   706 		{
       
   707 		SetNameFieldsL(*names, *mainContact, aOption, ETrue);
       
   708 		}
       
   709 	CleanupStack::PopAndDestroy(names);
       
   710 
       
   711 	// Create address container
       
   712 	RPointerArray<CVCardAddress> addresses(KVCardImportAddressArrayGranularity);
       
   713 	CleanupStack::PushL(TCleanupItem(CVCardItemAndLabel::CleanUpResetDestroyAndCloseArray, &addresses));
       
   714 
       
   715 	// Get addresses
       
   716 	GetAddressesL(aVCard, aOption, addresses);
       
   717 
       
   718 	// Import each address field into the contact card
       
   719 	count = addresses.Count();
       
   720     for (ii=0; ii<count; ii++)
       
   721 		{
       
   722 		const CVCardAddress* address = addresses[ii];
       
   723 		SetAddressFieldsL(*address, *mainContact, aOption);
       
   724 		}
       
   725 
       
   726 	// Finished with addresses now, so clean up
       
   727 	CleanupStack::PopAndDestroy(&addresses);
       
   728 
       
   729 // Get Organization related information from the vCard. This actually only retrieves the Company and the Department Name
       
   730 	CDesCArrayFlat* orgList = new (ELeave)CDesCArrayFlat(4);
       
   731 	CleanupStack::PushL(orgList);
       
   732 	TInt orgCount = GetVCardPropertyAsArrayOfValuesL(aVCard, KVersitTokenORG, *orgList);
       
   733 	if(orgCount)
       
   734 		{
       
   735 		SetOrgDetailsL(*mainContact, *orgList, aOption);
       
   736 		}
       
   737 	CleanupStack::PopAndDestroy(orgList); // orgList
       
   738 
       
   739 // Get Single Instance of Class Field from the vCard.
       
   740 	HBufC* singleClass = NULL;
       
   741 	singleClass = HBufC::NewLC(256);
       
   742 	TPtr ptr(singleClass->Des());
       
   743 
       
   744 	TInt classCount = GetSingleInstanceL(aVCard, KVersitTokenClass, ptr);
       
   745 	if(classCount)
       
   746 		{
       
   747 		SetSingleInstanceL(*mainContact, ptr, KUidContactFieldClass, KUidContactFieldVCardMapClass,aOption);
       
   748 		}
       
   749 	CleanupStack::PopAndDestroy(singleClass);
       
   750 
       
   751 	// Get other properties
       
   752     CArrayPtr<CParserProperty>* arrayOfProperties = aVCard.ArrayOfProperties();
       
   753 	CleanupStack::PushL(TCleanupItem(CleanUpResetAndDestroy,arrayOfProperties));
       
   754 	//
       
   755 	if	(arrayOfProperties)
       
   756 		{
       
   757 		count = arrayOfProperties->Count();
       
   758 		for (ii=0; ii<count; ii++)
       
   759 			{
       
   760 			CParserProperty* property = arrayOfProperties->At(ii);
       
   761 			// Address fields are handled in the above sections
       
   762 			if	((property->Name() != KVersitTokenADR) && (property->Name() != KVersitTokenORG) && (property->Name() != KVersitTokenClass))
       
   763 				{
       
   764 				// NOTE: This method can return a NULL object pushed onto the cleanup stack, so must
       
   765 				// always be popped!
       
   766 				TBool unsupportedProperty=EFalse;
       
   767 				CContactItemField* field = GetVCardPropertyAsContactFieldLC(property, aOption,unsupportedProperty);
       
   768 				if	(field)
       
   769 					{
       
   770 					mainContact->AddFieldL(*field);
       
   771 					}
       
   772 				CleanupStack::Pop(field);
       
   773 				}
       
   774 			}
       
   775 		// Email and Tel properties should only have a single Pref parameter
       
   776 		AdjustForPrefRule(*mainContact, KUidContactFieldEMail, KUidContactFieldVCardMapEMAILINTERNET);
       
   777 		AdjustForPrefRule(*mainContact, KUidContactFieldPhoneNumber, KUidContactFieldVCardMapTEL);
       
   778 		}
       
   779 	//
       
   780     if	(lastModified != Time::NullTTime())
       
   781     	{
       
   782     	mainContact->SetLastModified(lastModified);
       
   783     	}
       
   784 	//
       
   785 	mainContact->SetUidStringL(uidstring);
       
   786 	//
       
   787     CleanupStack::PopAndDestroy(); // arrayOfProperties->ResetAndDestroy()
       
   788 	//
       
   789 	return mainContact;
       
   790     }
       
   791 
       
   792 
       
   793 /**
       
   794  * Extract the last modified date of the vCard.
       
   795  * If there is no 'REV' property the last modified time is returned as as NULL TTime value.
       
   796  *
       
   797  * @param aVCard vCard parser object
       
   798  * @param aLastModified Last modified time
       
   799  */
       
   800 void CVCardToContactsAppConverter::GetVCardModifiedTimeL(CParserVCard& aVCard,TTime& aLastModified)
       
   801 	{
       
   802 	CArrayPtr<CParserProperty>* arrayOfRevisions=aVCard.PropertyL(KVersitTokenREV,TUid::Uid(KVersitPropertyDateTimeUid),EFalse);
       
   803 	if (arrayOfRevisions && arrayOfRevisions->Count())
       
   804 		{
       
   805 		CleanupStack::PushL(arrayOfRevisions);
       
   806    		CParserPropertyValueDateTime* revision=(static_cast<CParserPropertyValueDateTime*>((*arrayOfRevisions)[0]->Value()));
       
   807 
       
   808    		aLastModified=revision->Value()->iDateTime;
       
   809 		if (revision->Value()->iRelativeTime != TVersitDateTime::EIsUTC )
       
   810 			// The REV property isn't in UTC time, so let's (try to) convert it
       
   811 			{
       
   812 			CArrayPtr<CParserProperty>* arrayOfTimeZones=aVCard.PropertyL(KVersitTokenTZ, TUid::Uid(KVersitPropertyTimeZoneUid),EFalse);
       
   813 			if (arrayOfTimeZones && arrayOfTimeZones->Count())
       
   814 				// If we have the TZ property, adjust the machine local timestamp.
       
   815 				// If we don't have the TZ property, we'll just pretend that the REV
       
   816 				// property was already a UTC value.
       
   817 				{
       
   818 				CleanupStack::PushL(arrayOfTimeZones);
       
   819 				CParserPropertyValueTimeZone* timeZone =
       
   820 						static_cast<CParserPropertyValueTimeZone*> ((*arrayOfTimeZones)[0]->Value());
       
   821 				// Subtract the offset: UTC + Offset = Local => UTC = Local - Offset.
       
   822 				TTimeIntervalSeconds utcOffset = timeZone->Value().Int();
       
   823 				aLastModified -= utcOffset;
       
   824 				CleanupStack::PopAndDestroy(arrayOfTimeZones);
       
   825 				}
       
   826 			}
       
   827 		CleanupStack::PopAndDestroy(arrayOfRevisions);
       
   828    		}
       
   829    	else
       
   830 		{
       
   831    		aLastModified=Time::NullTTime();
       
   832 		}
       
   833     }
       
   834 
       
   835 
       
   836 /**
       
   837  * Extract the vCard 'UID' property from the vCard.
       
   838  *
       
   839  * @param aVCard vCard parser object
       
   840  * @param aUidString UID property value
       
   841  */
       
   842 void CVCardToContactsAppConverter::GetVCardUidStringL(CParserVCard& aVCard,TDes& aUidString) const
       
   843 	{
       
   844 	const CArrayPtr<CParserProperty>* arrayOfProperties=aVCard.PropertyL(KVersitTokenUID,TUid::Uid(KVersitPropertyHBufCUid),EFalse);
       
   845     if (arrayOfProperties)
       
   846     	{
       
   847     	TInt count=arrayOfProperties->Count();
       
   848     	if (count)
       
   849     		{
       
   850     		CParserPropertyValueHBufC* uidstring=(STATIC_CAST(CParserPropertyValueHBufC*,(*arrayOfProperties)[0]->Value()));
       
   851 			if (uidstring->Value().Length() > KUidStringLength )
       
   852 				aUidString=uidstring->Value().Left(KUidStringLength) ; // truncate
       
   853 			else
       
   854 				aUidString=uidstring->Value();
       
   855     		}
       
   856     	delete arrayOfProperties;
       
   857     	}
       
   858     }
       
   859 
       
   860 
       
   861 /**
       
   862  * Convert aVCardProperty into contact field.
       
   863  *
       
   864  * @param aProperty vCard property
       
   865  * @param aOption Import preferences (available options defined in CContactDatabase::TOptions)
       
   866  * @param aUnsupportedProperty Return whether or not the field is supported by the PC PIM, only relevant when using the EConnectWhitespace flag
       
   867  * @return Contact field or a NULL pointer (pushed onto the cleanup stack) in the case where
       
   868  *         it wasn't possible to create a contact field for this vCard property.
       
   869  */
       
   870 CContactItemField* CVCardToContactsAppConverter::GetVCardPropertyAsContactFieldLC(CParserProperty* aProperty,TInt aOption,TBool& aUnsupportedProperty)
       
   871  	{
       
   872 	TUid mappingUid;
       
   873 	TStorageType storageType;
       
   874 	CContentType* content=MapVCardPropertyToContentAndStorageTypeL(*aProperty,storageType);
       
   875 	CleanupStack::PushL(content);
       
   876 	mappingUid=content->Mapping();
       
   877 	TBool noConversion=EFalse;
       
   878 	aUnsupportedProperty=EFalse;
       
   879 
       
   880 	if (mappingUid==KUidContactFieldVCardMapNotRequired)
       
   881 		{
       
   882 		noConversion=ETrue;
       
   883 		}
       
   884 	else
       
   885 		{	/*Could preserve unknown non X- if VCard version no>2.1*/
       
   886 		switch (iUnknownPropertyBehaviour)
       
   887 			{
       
   888 			case EDiscardAllUnknownProperties:
       
   889 				if (mappingUid==KUidContactFieldVCardMapUnknownXDash)
       
   890 					noConversion=ETrue;
       
   891 					/* fall through */
       
   892 			case EDiscardNonXDashUnknownProperties:
       
   893 				if (mappingUid==KUidContactFieldVCardMapUnknown)
       
   894 					noConversion=ETrue;
       
   895 					/* fall through */
       
   896 			default:
       
   897 				break;
       
   898 			}
       
   899 		}
       
   900 
       
   901 	CContactItemField* contactItemField=NULL;
       
   902 	if (!noConversion)
       
   903 		{
       
   904 		TBool validImportableDataFound = ETrue;
       
   905 		contactItemField=CContactItemField::NewLC(storageType,*content);
       
   906 		if ((mappingUid==KUidContactFieldVCardMapUnknown) ||(mappingUid==KUidContactFieldVCardMapUnknownXDash))
       
   907 	    		{
       
   908 	    		TBool propertyTobeTruncated = PropertyTobeTruncated(aProperty->Name());
       
   909 	    		HBufC* encodedText = EncodeL(STATIC_CAST(CParserPropertyValueHBufC*,aProperty->Value())->Value(), propertyTobeTruncated);
       
   910 	    		contactItemField->TextStorage()->SetText(encodedText); // takes ownership
       
   911 				
       
   912 	    		contactItemField->SetHidden(ETrue);
       
   913 	    		}
       
   914 		else
       
   915 			{
       
   916 	    		switch (contactItemField->StorageType())
       
   917 	    			{
       
   918 	    			case KStorageTypeText:
       
   919 	    				{
       
   920 					TInt id = aProperty->Value()->Uid().iUid;
       
   921 					if(mappingUid == KUidContactFieldVCardMapORGPronunciation)
       
   922 						{ // this should be treated as an array instead of a single string
       
   923 						id = KVersitPropertyCDesCArrayUid;
       
   924 						}
       
   925 	    				switch (id)
       
   926 	    					{
       
   927 	    					case KVersitPropertyCDesCArrayUid:
       
   928 	    						{
       
   929 								TBool doConvert = ETrue;
       
   930 								 TBool pushed = EFalse;
       
   931 								CParserPropertyValueCDesCArray* propertyValueWrapper=NULL;
       
   932 								if(mappingUid == KUidContactFieldVCardMapORGPronunciation)
       
   933 									{ // Treat a SOUND with X-IRMC-ORG param as an array
       
   934 									const CParserPropertyValueHBufC* valueScalar = static_cast<CParserPropertyValueHBufC*>(aProperty->Value());
       
   935 									if(valueScalar)
       
   936 										{
       
   937 										propertyValueWrapper = valueScalar->TreatAsArrayPropertyLC(*aProperty);
       
   938 										pushed= ETrue;
       
   939 										}
       
   940 									}
       
   941 								else
       
   942 									{
       
   943 									propertyValueWrapper = static_cast<CParserPropertyValueCDesCArray*>(aProperty->Value());
       
   944 									}
       
   945 								CDesCArray* propertyValue = NULL;
       
   946 								if	(propertyValueWrapper)
       
   947 									{
       
   948 									propertyValue = propertyValueWrapper->Value();
       
   949 									}
       
   950 
       
   951 								if ((CContactVCardConverter::EConnectWhitespace & aOption) && propertyValue)
       
   952 									{
       
   953 									doConvert = TextArrayContainsImportableData(*propertyValue);
       
   954 									if (doConvert)
       
   955 										{
       
   956 										RemoveWhitespaceFromCompositePropertyL(*propertyValue);
       
   957 										}
       
   958 									}
       
   959 								if (doConvert && propertyValue)
       
   960 									{
       
   961 	   								TInt count = propertyValue->MdcaCount();
       
   962 								    HBufC *txt=HBufC::NewL(0);
       
   963 									CleanupStack::PushL(txt);
       
   964 									// concatenate the array
       
   965 								    for (TInt ii=0;ii<count;ii++)
       
   966 								    	{
       
   967 										TInt mdcaLen=propertyValue->MdcaPoint(ii).Size();
       
   968 										if (mdcaLen>0)
       
   969 											{
       
   970 								    			if (txt->Length()>0)
       
   971 												{
       
   972 												txt->Des().Append(TChar('\n'));
       
   973 												}
       
   974 											txt=txt->ReAllocL(txt->Length()+mdcaLen+1);	// +1 In case we add '\n'
       
   975 											CleanupStack::Pop();	// txt(old value)
       
   976 											CleanupStack::PushL(txt);
       
   977 											TPtrC temp(propertyValue->MdcaPoint(ii));
       
   978 											txt->Des().Append(temp);
       
   979 											}
       
   980 								    	}
       
   981 			   						TBool propertyTobeTruncated = PropertyTobeTruncated(aProperty->Name());
       
   982 			   						HBufC* encodedText = EncodeL(*txt, propertyTobeTruncated);
       
   983 			   						CleanupStack::PopAndDestroy(txt);
       
   984 			   						contactItemField->TextStorage()->SetText(encodedText); // takes ownership
       
   985 									}
       
   986 								else
       
   987 									{
       
   988 									validImportableDataFound = EFalse;
       
   989 									}
       
   990 								if(pushed)
       
   991 									{
       
   992 									CleanupStack::PopAndDestroy(propertyValueWrapper);
       
   993 									}
       
   994 	    						}
       
   995 			    				break;
       
   996 	   					case KVersitPropertyHBufCUid:
       
   997 							{
       
   998 							TBool doConvert = ETrue;
       
   999 
       
  1000 							CParserPropertyValueHBufC* propertyValueWrapper = static_cast<CParserPropertyValueHBufC*>(aProperty->Value());
       
  1001 							const TPtrC propertyValue(propertyValueWrapper->Value());
       
  1002 
       
  1003 							if (CContactVCardConverter::EConnectWhitespace & aOption)
       
  1004 								{
       
  1005 								if (propertyValue==KSingleSpacePropertyValue)
       
  1006 									{
       
  1007 									aUnsupportedProperty=ETrue;
       
  1008 									}
       
  1009 								doConvert = (CContactVCardConverter::ContainsImportableData(propertyValue, CContactVCardConverter::EPropertyValueSingle, ImportType()));
       
  1010 								}
       
  1011 							if (doConvert)
       
  1012 								{
       
  1013 								TBool propertyTobeTruncated = PropertyTobeTruncated(aProperty->Name());
       
  1014 								HBufC* encodedText = EncodeL(propertyValue, propertyTobeTruncated);
       
  1015 								contactItemField->TextStorage()->SetText(encodedText); // takes ownership
       
  1016 								}
       
  1017 							else
       
  1018 								{
       
  1019 								validImportableDataFound = EFalse;
       
  1020 								}
       
  1021 							}
       
  1022 			    				break;
       
  1023 		   				default:;
       
  1024 	    					}
       
  1025 	    				}
       
  1026 		    			break;
       
  1027 		    		case KStorageTypeDateTime:
       
  1028 	    				{
       
  1029 		    			switch (aProperty->Value()->Uid().iUid)
       
  1030 		    				{
       
  1031 		    				case KVersitPropertyDateTimeUid:
       
  1032 		    					STATIC_CAST(CContactDateField*,contactItemField->Storage())->SetTime(STATIC_CAST(CParserPropertyValueDateTime*,aProperty->Value())->Value()->iDateTime);
       
  1033 		    					break;
       
  1034 						case KVersitPropertyDateUid:
       
  1035 							STATIC_CAST(CContactDateField*,contactItemField->Storage())->SetTime(STATIC_CAST(CParserPropertyValueDate*,aProperty->Value())->Value()->iDateTime);
       
  1036 							break;
       
  1037 		    				default:
       
  1038 			    				break;
       
  1039 		    				}
       
  1040 		    			}
       
  1041 	    				break;
       
  1042 		    		case KStorageTypeStore:
       
  1043 		    			{
       
  1044 		    			STATIC_CAST(CContactStoreField*,contactItemField->Storage())->SetThingL(STATIC_CAST(CParserPropertyValueBinary*,aProperty->Value())->Value());
       
  1045 		    			}
       
  1046 		    			break;
       
  1047 		    		default:
       
  1048 		    			break;
       
  1049 		    		}
       
  1050 	    		}
       
  1051 		if (aOption & CContactVCardConverter::EIncludeX)
       
  1052 			{
       
  1053 			TBuf8<KContactMaxVCardPropertyNameLength> paramName;
       
  1054 			paramName=KContactVCardXDashEPOCCNTMODEL;
       
  1055 			paramName.Append(KContactVCardFIELDHIDDEN);
       
  1056 			if (aProperty->Param(paramName))
       
  1057 				contactItemField->SetHidden(ETrue);
       
  1058 			paramName.Zero();
       
  1059 			paramName=KContactVCardXDashEPOCCNTMODEL;
       
  1060 			paramName.Append(KContactVCardFIELDREADONLY);
       
  1061 			if (aProperty->Param(paramName))
       
  1062 				contactItemField->SetReadOnly(ETrue);
       
  1063 			paramName.Zero();
       
  1064 			paramName=KContactVCardXDashEPOCCNTMODEL;
       
  1065 			paramName.Append(KContactVCardFIELDLABEL);
       
  1066 			if (aProperty->Param(paramName))
       
  1067 				contactItemField->SetLabel(aProperty->Param(paramName)->ValueL());
       
  1068 			}
       
  1069 		CleanupStack::Pop(contactItemField);
       
  1070 	// The field is only added to the contact card if it was found to contain
       
  1071 	// legitimate importable data (i.e. has content that does not simply consist of LWSP characters).
       
  1072 	// This is important, since TimeIS sync drivers can create vCard objects (pushed over to the device)
       
  1073 	// that contain only space characters for their Versit 'Property Parameter Values'.
       
  1074 		if (!validImportableDataFound)
       
  1075 			{
       
  1076 			delete contactItemField;
       
  1077 			contactItemField = NULL;
       
  1078 			}
       
  1079 		}
       
  1080 	CleanupStack::PopAndDestroy(content);
       
  1081 	// We may be pushing a NULL pointer back onto the cleanup stack, but clients of this
       
  1082 	// method understand this feature.
       
  1083 	CleanupStack::PushL(contactItemField);
       
  1084 	return(contactItemField);
       
  1085     }
       
  1086 
       
  1087 
       
  1088 /**
       
  1089  * Find a vCard property parameter in a vCard property
       
  1090  *
       
  1091  * @param aVCardProperty vCard property
       
  1092  * @return Property parameter number
       
  1093  */
       
  1094 TInt CVCardToContactsAppConverter::GetVCardPropertyTTNumber(CParserProperty* aVCardProperty)
       
  1095     {
       
  1096     TInt ii;
       
  1097 	TBuf8<KContactMaxVCardPropertyNameLength> paramName;
       
  1098 	for (ii=1;ii<=KContactMaxFieldNumber;ii++)
       
  1099 		{
       
  1100 		paramName.Format(_L8("%d"),ii);
       
  1101 		if (aVCardProperty->Param(paramName))
       
  1102 			{
       
  1103 			return (ii);
       
  1104 			}
       
  1105 		}
       
  1106 	return 1;	// Default to 1 if no number found
       
  1107 	}
       
  1108 
       
  1109 
       
  1110 /**
       
  1111  * Extract the contact name fields from the vCard 'N' property.
       
  1112  * This method takes values from the 'N' vCard property and returns the family name,
       
  1113  * given name, middle name, prefix and suffix.
       
  1114  *
       
  1115  * Only the first instance of the 'N' property is used.
       
  1116  *
       
  1117  * @param aVCard vCard parser object
       
  1118  * @param aOption Import preferences (available options defined in CContactDatabase::TOptions)
       
  1119  * @return An instance of CVCardItemAndLabel which encapsulates the names and their associated
       
  1120  *         labels contained within the vCard or a NULL pointer pushed onto the cleanup stack
       
  1121  *         if it wasn't possible to construct the object.
       
  1122  */
       
  1123 CVCardItemAndLabel* CVCardToContactsAppConverter::GetContactNameLC(CParserVCard& aVCard, TInt aOption)
       
  1124     {
       
  1125 	CVCardItemAndLabel* names = NULL;
       
  1126 
       
  1127 	CArrayPtr<CParserProperty>* arrayOfProperties=aVCard.PropertyL(KVersitTokenN,TUid::Uid(KVersitPropertyCDesCArrayUid));
       
  1128   	if (arrayOfProperties && arrayOfProperties->Count())
       
  1129 		{
       
  1130 		CleanupStack::PushL(TCleanupItem(CleanUpResetAndDestroy,arrayOfProperties));
       
  1131 		//
       
  1132 		//
       
  1133 		CParserProperty* property = arrayOfProperties->At(0);
       
  1134 		CDesCArray& items = *static_cast<CParserPropertyValueCDesCArray*>(property->Value())->Value();
       
  1135 		names = MakeNamesFromItemsL(items, aOption, property );
       
  1136 		CleanupStack::PopAndDestroy(arrayOfProperties);
       
  1137     	}
       
  1138 
       
  1139 	// Clients of this method assume that something is pushed onto the Cleanup Stack, so
       
  1140 	// this might potentially be NULL.
       
  1141 	CleanupStack::PushL(names);
       
  1142 	return names;
       
  1143     }
       
  1144 
       
  1145 
       
  1146 
       
  1147 /**
       
  1148  * Extract the contact name fields from the vCard 'N' property.
       
  1149  * This method takes values from the 'N' vCard property and returns the family name,
       
  1150  * given name, middle name, prefix and suffix.
       
  1151  *
       
  1152  * Only the first instance of the 'N' property is used.
       
  1153  *
       
  1154  * @param aVCard vCard parser object
       
  1155  * @param aOption Import preferences (available options defined in CContactDatabase::TOptions)
       
  1156  * @return An instance of CVCardItemAndLabel which encapsulates the names and their associated
       
  1157  *         labels contained within the vCard or a NULL pointer pushed onto the cleanup stack
       
  1158  *         if it wasn't possible to construct the object.
       
  1159  */
       
  1160 CVCardItemAndLabel* CVCardToContactsAppConverter::GetContactNamePrnLC(CParserVCard& aVCard, TInt aOption)
       
  1161 	{
       
  1162 	CVCardItemAndLabel* names = NULL;
       
  1163 
       
  1164 	CArrayPtr<CParserProperty>* arrayOfProperties=aVCard.PropertyL(KVersitTokenSOUND,TUid::Uid(KVersitPropertyHBufCUid), EFalse);
       
  1165 
       
  1166 	if (arrayOfProperties )
       
  1167 		{
       
  1168 		CleanupStack::PushL(arrayOfProperties);
       
  1169 		TInt count = arrayOfProperties->Count();
       
  1170 		const CParserProperty* property=NULL;
       
  1171 		for (TInt index=0;index<count;index++)
       
  1172 			{
       
  1173 			property = arrayOfProperties->At(index);
       
  1174 			if(property->Param(KVersitParam8NamePrn))
       
  1175 				{
       
  1176 				index=count;
       
  1177 				}
       
  1178 			else
       
  1179 				{
       
  1180 				property=NULL;
       
  1181 				}
       
  1182 			}
       
  1183 		if (property) // property is the 1st SOUND property with an X-IRMC-N parameter
       
  1184 			{
       
  1185 			const CParserPropertyValueHBufC* valueScalar = static_cast<CParserPropertyValueHBufC*>(property->Value());
       
  1186 			if(valueScalar)
       
  1187 				{
       
  1188 				CParserPropertyValueCDesCArray* valueArray = valueScalar->TreatAsArrayPropertyLC(*property);
       
  1189 				names = MakeNamesFromItemsL( *valueArray->Value(), aOption, property );// valueArray will never be NULL
       
  1190 				CleanupStack::PopAndDestroy(valueArray);
       
  1191 				}
       
  1192 			}
       
  1193 		CleanupStack::PopAndDestroy(arrayOfProperties);
       
  1194     		}
       
  1195 
       
  1196 	// Clients of this method assume that something is pushed onto the Cleanup Stack, so
       
  1197 	// this might potentially be NULL.
       
  1198 	CleanupStack::PushL(names);
       
  1199 	return names;
       
  1200 	}
       
  1201 
       
  1202 CVCardItemAndLabel* CVCardToContactsAppConverter::MakeNamesFromItemsL(const CDesCArray& aItems, TInt aOption, const CParserProperty* aProperty )
       
  1203 	{
       
  1204 	CVCardItemAndLabel* names = CVCardItemAndLabel::NewLC();
       
  1205 
       
  1206 	const TInt fieldcount = aItems.Count();
       
  1207 	//
       
  1208     	for(TInt ii=0; ii<fieldcount; ii++)
       
  1209     		{
       
  1210 		const TPtrC pField(aItems.MdcaPoint(ii));
       
  1211     		names->AddItemL(pField);
       
  1212 		if (aOption & CContactVCardConverter::EIncludeX)
       
  1213 			{
       
  1214 			TBuf8<KContactMaxVCardPropertyNameLength> paramName(KContactVCardXDashEPOCCNTMODEL);
       
  1215 			paramName.AppendFormat(KContactVCardLABELn,ii);
       
  1216 			//
       
  1217 			if(aProperty->Param(paramName))
       
  1218 				{
       
  1219 				HBufC* value = aProperty->Param(paramName)->ValueL();
       
  1220 				CleanupStack::PushL(value);
       
  1221 				names->AddLabelL(*value);
       
  1222 				CleanupStack::PopAndDestroy(value);
       
  1223 				}
       
  1224     			}
       
  1225 		}
       
  1226 	CleanupStack::Pop(names);
       
  1227 	return names;
       
  1228 	}
       
  1229 
       
  1230 /**
       
  1231  * Extract specific address properties
       
  1232 
       
  1233  * @param aProperties An array of vCard properties which should be searched
       
  1234  * @param aOption Import preferences (available options defined in CContactDatabase::TOptions)
       
  1235  * @param aParamMustMatch A property parameter which must be found in the specified vCard property. If this
       
  1236  *                        has a NULL (KNullDesC) value then the property is treated as satisfying this condition
       
  1237  * @param aParamMustNotMatch1 A property parameter which must not be found in the specified vCard property. If this
       
  1238  *                        has a NULL (KNullDesC) value then the property is treated as satisfying this condition
       
  1239  * @param aParamMustNotMatch2 Another property parameter which must not be found in the specified vCard property. If this
       
  1240  *                        has a NULL (KNullDesC) value then the property is treated as satisfying this condition
       
  1241  * @param aMapping The address mapping which is being searched for (e.g. HOME, WORK, etc)
       
  1242  * @return An address object which contains the name and labels (optionally) located in aProperties for this particular mapping
       
  1243  */
       
  1244 CVCardAddress* CVCardToContactsAppConverter::GetSpecifiedAddressLC(const CArrayPtr<CParserProperty>& aProperties, TInt aOption, const TDesC8& aParamMustMatch, const TDesC8& aParamMustNotMatch1, const TDesC8& aParamMustNotMatch2, TUid aMapping)
       
  1245 	{
       
  1246 	CVCardAddress* address = NULL;
       
  1247 	const TInt propertyCount = aProperties.Count();
       
  1248 	//
       
  1249 	for (TInt ii=0; ii<propertyCount; ii++)
       
  1250 		{
       
  1251 		CParserProperty* property = aProperties[ii];
       
  1252 		
       
  1253 		// DEF084708, also get and compare for ADDR;TYPE=HOME etc in addition to ADDR;HOME. 
       
  1254 		// The param to be matched (or not matched) can be found either as the param name (ADDR;HOME)
       
  1255 		// or in the param value of param name - TYPE (case ADDR;TYPE=HOME)
       
  1256 		CParserParam* paramType = property->Param(KVersitParam8Type);
       
  1257 		if (
       
  1258 			(property->Name() == KVersitTokenADR) &&
       
  1259 			(property->Value()->Uid() == TUid::Uid(KVersitPropertyCDesCArrayUid)) &&
       
  1260 			
       
  1261 			(!aParamMustMatch.Length()     || property->Param(aParamMustMatch) != NULL ||
       
  1262 			(paramType != NULL && paramType->Value().CompareF(aParamMustMatch) == 0)) &&
       
  1263 			
       
  1264 			(!aParamMustNotMatch1.Length() || (property->Param(aParamMustNotMatch1) == NULL &&
       
  1265 			(paramType == NULL || paramType->Value().CompareF(aParamMustNotMatch1) != 0))) &&
       
  1266 			
       
  1267 			(!aParamMustNotMatch2.Length() || (property->Param(aParamMustNotMatch2) == NULL &&
       
  1268 			(paramType == NULL || paramType->Value().CompareF(aParamMustNotMatch2) != 0)))
       
  1269 			)
       
  1270 			{
       
  1271 			
       
  1272 			CDesCArray& items = *static_cast<CParserPropertyValueCDesCArray*>(property->Value())->Value();
       
  1273 			const TInt fieldcount = items.Count();
       
  1274 
       
  1275 			// Create the address
       
  1276 			address = CVCardAddress::NewLC(aMapping);
       
  1277 
       
  1278 			for(TInt jj = 0; jj < fieldcount; jj++)
       
  1279     			{
       
  1280 				const TPtrC pField(items.MdcaPoint(jj));
       
  1281     			address->AddItemL(pField);
       
  1282 				//
       
  1283 				if	(aOption & CContactVCardConverter::EIncludeX)
       
  1284 					{
       
  1285 					TBuf8<KContactMaxVCardPropertyNameLength> paramName(KContactVCardXDashEPOCCNTMODEL);
       
  1286 					paramName.AppendFormat(KContactVCardLABELn, jj);
       
  1287 					//
       
  1288 					if	(property->Param(paramName))
       
  1289 						{
       
  1290 						HBufC* value = property->Param(paramName)->ValueL();
       
  1291 						CleanupStack::PushL(value);
       
  1292 						address->AddLabelL(*value);
       
  1293 						CleanupStack::PopAndDestroy(value);
       
  1294 						}
       
  1295     				}
       
  1296 				}
       
  1297 
       
  1298 			// End for-loop now we've found the specified item
       
  1299 			break;
       
  1300 			}
       
  1301 		}
       
  1302 
       
  1303 	// Have to push something to ensure cleanup stack is balanced
       
  1304 	if	(!address)
       
  1305 		CleanupStack::PushL((TAny*) NULL);
       
  1306 	return address;
       
  1307 	}
       
  1308 
       
  1309 
       
  1310 /**
       
  1311  * Extract home and work address properties from the vCard
       
  1312  *
       
  1313  * @param aVCard vCard parser object
       
  1314  * @param aOption Import preferences (available options defined in CContactDatabase::TOptions)
       
  1315  * @param aAddresses An array reference which contains any located address fields upon exit from this method
       
  1316  */
       
  1317 void CVCardToContactsAppConverter::GetAddressesL(CParserVCard& aVCard, TInt aOption, RPointerArray<CVCardAddress>& aAddresses)
       
  1318     {
       
  1319 	CArrayPtr<CParserProperty>* arrayOfProperties = aVCard.ArrayOfProperties(EFalse);
       
  1320 	if	(arrayOfProperties)
       
  1321 		{
       
  1322 		// Find ADR;HOME
       
  1323 		CVCardAddress* home = GetSpecifiedAddressLC(*arrayOfProperties,
       
  1324 													aOption,
       
  1325 													KVersitParam8Home, // Must be ADR;HOME and not ADR;HOME;WORK
       
  1326 													KVersitParam8Work,
       
  1327 													KNullDesC8,
       
  1328 													KUidContactFieldVCardMapHOME
       
  1329 													);
       
  1330 		if	(home)
       
  1331 			User::LeaveIfError(aAddresses.Append(home));
       
  1332 		CleanupStack::Pop(home);
       
  1333 
       
  1334 		// Find ADR;WORK
       
  1335 		CVCardAddress* work = GetSpecifiedAddressLC(*arrayOfProperties,
       
  1336 													aOption,
       
  1337 													KVersitParam8Work, // Must be ADR;WORK
       
  1338 													KNullDesC8,
       
  1339 													KNullDesC8,
       
  1340 													KUidContactFieldVCardMapWORK
       
  1341 													);
       
  1342 		if	(work)
       
  1343 			User::LeaveIfError(aAddresses.Append(work));
       
  1344 		CleanupStack::Pop(work);
       
  1345 
       
  1346 		// Find ADR;PREF
       
  1347 		CVCardAddress* pref = GetSpecifiedAddressLC(*arrayOfProperties,
       
  1348 													aOption,
       
  1349 													KVersitParam8Pref, // Must be ADR;PREF and not ADR;HOME or ADR;WORK
       
  1350 													KVersitParam8Home,
       
  1351 													KVersitParam8Work,
       
  1352 													KUidContactFieldVCardMapPREF
       
  1353 													);
       
  1354 		if	(pref)
       
  1355 			User::LeaveIfError(aAddresses.Append(pref));
       
  1356 		CleanupStack::Pop(pref);
       
  1357 
       
  1358 		// Find general ADR: address
       
  1359 		CVCardAddress* general = GetSpecifiedAddressLC(*arrayOfProperties,
       
  1360 													aOption,
       
  1361 													KNullDesC8, // Just has to be ADR
       
  1362 													KVersitParam8Home,
       
  1363 													KVersitParam8Work,
       
  1364 													KNullUid
       
  1365 													);
       
  1366 		if	(general)
       
  1367 			User::LeaveIfError(aAddresses.Append(general));
       
  1368 		CleanupStack::Pop(general);
       
  1369 		}
       
  1370 	}
       
  1371 
       
  1372 
       
  1373 
       
  1374 /**
       
  1375  * Map vCard property to contacts field content and storage type
       
  1376  *
       
  1377  * @param aVCardProperty vCard property
       
  1378  * @param aStorageType Type of contact field storage (TStorageType)
       
  1379  * @return Content type for vCard property
       
  1380  */
       
  1381 CContentType* CVCardToContactsAppConverter::MapVCardPropertyToContentAndStorageTypeL(const CParserProperty& aVCardProperty, TStorageType& aStorageType)
       
  1382     {
       
  1383 	TUid mapping=KUidContactFieldNone;
       
  1384 	TFieldType fieldType=KUidContactFieldNone;
       
  1385 	TPtrC8 vpropNameConst = aVCardProperty.Name();
       
  1386     aStorageType=KStorageTypeStore;
       
  1387 
       
  1388 	switch (aVCardProperty.Value()->Uid().iUid)
       
  1389     	{
       
  1390     case KVersitPropertyCDesCArrayUid:
       
  1391     	{
       
  1392     	aStorageType=KStorageTypeText;
       
  1393     	if (vpropNameConst.CompareF(KVersitTokenN)==0)
       
  1394 			{
       
  1395     		fieldType=KUidContactFieldFamilyName;
       
  1396 			mapping=KUidContactFieldVCardMapUnusedN;
       
  1397 			}
       
  1398     	else if (vpropNameConst.CompareF(KVersitTokenADR)==0)
       
  1399 			{
       
  1400     		fieldType=KUidContactFieldAddress;
       
  1401 			mapping=KUidContactFieldVCardMapADR;
       
  1402 			}
       
  1403  		else if (vpropNameConst.CompareF(KVersitTokenChildren) == 0)
       
  1404  			{
       
  1405  			mapping = KUidContactFieldVCardMapChildren;
       
  1406  			fieldType = KUidContactFieldChildren;
       
  1407  			}
       
  1408     	}
       
  1409     	break;
       
  1410     case KVersitPropertyDateTimeUid:
       
  1411     	aStorageType=KStorageTypeDateTime;
       
  1412     	if (vpropNameConst.CompareF(KVersitTokenREV)==0)
       
  1413     		mapping=KUidContactFieldVCardMapNotRequired;
       
  1414     	break;
       
  1415     case KVersitPropertyDateUid:
       
  1416     	aStorageType=KStorageTypeDateTime;
       
  1417     	if (vpropNameConst.CompareF(KVersitTokenBDAY)==0)
       
  1418 			{
       
  1419     		mapping=KUidContactFieldVCardMapBDAY;
       
  1420 			fieldType=KUidContactFieldBirthday;
       
  1421 			}
       
  1422  		else if (vpropNameConst.CompareF(KVersitTokenAnniversary) == 0)
       
  1423  			{
       
  1424  			mapping = KUidContactFieldVCardMapAnniversary;
       
  1425  			fieldType = KUidContactFieldAnniversary;
       
  1426  			}
       
  1427     	break;
       
  1428     case KVCardPropertyAgentUid:
       
  1429 		aStorageType = KStorageTypeContactItemId ; 
       
  1430 		if (vpropNameConst.CompareF(KVersitTokenAGENT) == 0)
       
  1431 			{
       
  1432 			mapping = KUidContactFieldVCardMapAGENT;
       
  1433 			}
       
  1434     	break;
       
  1435 
       
  1436     case KVersitPropertyTimeZoneUid:
       
  1437     	aStorageType=KStorageTypeStore;
       
  1438 
       
  1439     	if(vpropNameConst.CompareF(KVersitTokenTZ) == 0)
       
  1440     		{
       
  1441     		mapping=KUidContactFieldVCardMapNotRequired;
       
  1442     		}
       
  1443     	break;
       
  1444 //
       
  1445     default:	// aka case KVersitPropertyHBufCUid:
       
  1446     	aStorageType=KStorageTypeText;
       
  1447 		mapping = KUidContactFieldVCardMapUnknown; // Initialize to something sensible
       
  1448 		switch (vpropNameConst[0])
       
  1449 			{
       
  1450 		case 'B':
       
  1451 		case 'b':
       
  1452 			if (vpropNameConst.CompareF(KVersitTokenBDAY)==0)
       
  1453 				{
       
  1454     			mapping=KUidContactFieldVCardMapBDAY;
       
  1455 				fieldType=KUidContactFieldBirthday;
       
  1456 				}
       
  1457 			break;
       
  1458     	case 'E':
       
  1459     	case 'e':
       
  1460 			if (vpropNameConst.CompareF(KVersitTokenEMAIL)==0)
       
  1461 				{
       
  1462     			fieldType=KUidContactFieldEMail;
       
  1463     			mapping=KUidContactFieldVCardMapEMAILINTERNET;
       
  1464 				}
       
  1465 			break;
       
  1466     	case 'F':
       
  1467     	case 'f':
       
  1468 			if (vpropNameConst.CompareF(KVersitTokenFN)==0)
       
  1469     			mapping=KUidContactFieldVCardMapUnusedFN;
       
  1470 			break;
       
  1471     	case 'G':
       
  1472     	case 'g':
       
  1473 			if (vpropNameConst.CompareF(KVersitTokenGEO)==0)
       
  1474 				{
       
  1475 				fieldType=KUidContactFieldGEO;
       
  1476     			mapping=KUidContactFieldVCardMapGEO;
       
  1477 				}
       
  1478 			break;
       
  1479     	case 'K':
       
  1480     	case 'k':
       
  1481 			if (vpropNameConst.CompareF(KVersitTokenKEY)==0)
       
  1482 				{
       
  1483 				if(aVCardProperty.Value()->Uid().iUid == KVersitPropertyBinaryUid)
       
  1484 					{					
       
  1485 					aStorageType = KStorageTypeStore;
       
  1486 			 		}
       
  1487     			mapping=KUidContactFieldVCardMapKEY;
       
  1488 				}
       
  1489 			break;
       
  1490     	case 'L':
       
  1491     	case 'l':
       
  1492 			if (vpropNameConst.CompareF(KVersitTokenLABEL)==0)
       
  1493     			mapping=KUidContactFieldVCardMapLABEL;
       
  1494 			else if (vpropNameConst.CompareF(KVersitTokenLOGO)==0)
       
  1495 				{
       
  1496 				aStorageType=KStorageTypeStore;
       
  1497     			mapping=KUidContactFieldVCardMapLOGO;
       
  1498 				}
       
  1499     		break;
       
  1500     	case 'M':
       
  1501     	case 'm':
       
  1502 			if  (vpropNameConst.CompareF(KVersitTokenMAILER)==0)
       
  1503     			mapping=KUidContactFieldVCardMapMAILER;
       
  1504 			break;
       
  1505     	case 'N':
       
  1506     	case 'n':
       
  1507 			if (vpropNameConst.CompareF(KVersitTokenNOTE)==0)
       
  1508 				{
       
  1509 				fieldType=KUidContactFieldNote;
       
  1510     				mapping=KUidContactFieldVCardMapNOTE;
       
  1511 				}
       
  1512 			break;
       
  1513     	case 'P':
       
  1514     	case 'p':
       
  1515 			if (vpropNameConst.CompareF(KVersitTokenPHOTO)==0)
       
  1516 				{
       
  1517     			mapping=KUidContactFieldVCardMapPHOTO;
       
  1518 				aStorageType=KStorageTypeStore;
       
  1519 				}
       
  1520 			break;
       
  1521     	case 'R':
       
  1522     	case 'r':
       
  1523 			if (vpropNameConst.CompareF(KVersitTokenROLE)==0)
       
  1524     			mapping=KUidContactFieldVCardMapROLE;
       
  1525 			break;
       
  1526     	case 'S':
       
  1527     	case 's':
       
  1528 			if (vpropNameConst.CompareF(KVersitTokenSOUND)==0)
       
  1529 				{
       
  1530 				if(aVCardProperty.Param(KVersitParam8CompanyPrn))
       
  1531 					{
       
  1532 					mapping = KUidContactFieldVCardMapORGPronunciation;
       
  1533 					fieldType=KUidContactFieldCompanyNamePronunciation;
       
  1534 					}
       
  1535 				else if(aVCardProperty.Param(KVersitParam8NamePrn))
       
  1536 					{// this is handled elsewhere
       
  1537 					mapping = KUidContactFieldVCardMapNotRequired;
       
  1538 					}
       
  1539 				else // if we ever support any of the other pronunication extensions we'd have to add the checking here
       
  1540 					{
       
  1541 					mapping=KUidContactFieldVCardMapSOUND;
       
  1542 					}
       
  1543 				}
       
  1544 			break;
       
  1545     	case 'T':
       
  1546     	case 't':    	
       
  1547 			 if (vpropNameConst.CompareF(KVersitTokenTEL)==0)
       
  1548     			{
       
  1549     			fieldType=KUidContactFieldPhoneNumber;
       
  1550 				mapping=KUidContactFieldVCardMapTEL;
       
  1551     			}
       
  1552 			 else if (vpropNameConst.CompareF(KVersitTokenTITLE)==0)
       
  1553 				{
       
  1554 				fieldType=KUidContactFieldJobTitle;
       
  1555 				mapping=KUidContactFieldVCardMapTITLE;
       
  1556 				}
       
  1557 			 else if (vpropNameConst.CompareF(KVersitTokenTZ)==0)
       
  1558 				{
       
  1559 				mapping=KUidContactFieldVCardMapNotRequired;
       
  1560 				}
       
  1561 			break;
       
  1562     	case 'U':
       
  1563     	case 'u':    	
       
  1564 			if (vpropNameConst.CompareF(KVersitTokenURL)==0)
       
  1565 				{
       
  1566     			mapping=KUidContactFieldVCardMapURL;
       
  1567 				fieldType=KUidContactFieldUrl;
       
  1568 				}
       
  1569 			else if (vpropNameConst.CompareF(KVersitTokenUID)==0)
       
  1570 				{
       
  1571 				mapping=KUidContactFieldVCardMapNotRequired;
       
  1572 				}
       
  1573 			break;
       
  1574     	case 'V':
       
  1575     	case 'v':    	
       
  1576 			if (vpropNameConst.CompareF(KVersitTokenVERSION)==0)
       
  1577 				{
       
  1578     			mapping=KUidContactFieldVCardMapNotRequired;
       
  1579 				}
       
  1580 			break;
       
  1581     	case 'X':
       
  1582     	case 'x':    	
       
  1583 			if (vpropNameConst.CompareF(KVersitTokenSECONDNAME)==0)
       
  1584 				{
       
  1585 				mapping=KUidContactFieldVCardMapSECONDNAME;
       
  1586 				fieldType=KUidContactFieldSecondName;
       
  1587 				}
       
  1588 			else if (vpropNameConst.CompareF(KVersitTokenSIPID)==0)
       
  1589 				{
       
  1590 				mapping=KUidContactFieldVCardMapSIPID;
       
  1591 				fieldType=KUidContactFieldSIPID;
       
  1592 				}
       
  1593 			else if (vpropNameConst.CompareF(KVersitTokenWVID)==0)
       
  1594 				{
       
  1595 				mapping=KUidContactFieldVCardMapWV;
       
  1596 				fieldType=KUidContactFieldIMAddress;
       
  1597 				}
       
  1598 			else if (vpropNameConst.CompareF(KVersitTokenAssistant) == 0)
       
  1599 				{
       
  1600 				mapping = KUidContactFieldVCardMapAssistant;
       
  1601 				fieldType = KUidContactFieldAssistant;
       
  1602 				}
       
  1603 			else if (vpropNameConst.CompareF(KVersitTokenAssistantTel) == 0)
       
  1604 				{
       
  1605 				mapping = KUidContactFieldVCardMapAssistantTel;
       
  1606 				fieldType = KUidContactFieldPhoneNumber;
       
  1607 				}
       
  1608 			else if (vpropNameConst.CompareF(KVersitTokenAnniversary) == 0)
       
  1609 				{
       
  1610 				mapping = KUidContactFieldVCardMapAnniversary;
       
  1611 				fieldType = KUidContactFieldAnniversary;
       
  1612 				}
       
  1613 			else if (vpropNameConst.CompareF(KVersitTokenSpouse) == 0)
       
  1614 				{
       
  1615 				mapping = KUidContactFieldVCardMapSpouse;
       
  1616 				fieldType = KUidContactFieldSpouse;
       
  1617 				}
       
  1618 			else if (vpropNameConst.Length()>=2)
       
  1619     			{
       
  1620     			if (vpropNameConst.Left(2).CompareF(KVersitTokenXDash)==0)
       
  1621     				mapping=KUidContactFieldVCardMapUnknownXDash;
       
  1622 				else
       
  1623  					mapping=KUidContactFieldVCardMapUnknown;
       
  1624 				}
       
  1625 			break;
       
  1626     	default:
       
  1627 			break; // Leave mapping set to KUidContactFieldVCardMapUnknown
       
  1628 			};
       
  1629 		};
       
  1630 
       
  1631 	CContentType* type=CContentType::NewL();
       
  1632 	CleanupStack::PushL( type );
       
  1633 	type->SetMapping(mapping);
       
  1634 	if (mapping==KUidContactFieldVCardMapPHOTO || mapping==KUidContactFieldVCardMapLOGO)
       
  1635 		{
       
  1636 		type->AddFieldTypeL(KUidContactFieldPicture);
       
  1637         TFieldType bitmapFormat;
       
  1638         GetBitMapFormat(aVCardProperty, bitmapFormat);
       
  1639            
       
  1640         if (bitmapFormat.iUid!=KUidContactFieldNone.iUid)
       
  1641 			{
       
  1642             type->AddFieldTypeL(bitmapFormat);
       
  1643 			}
       
  1644 		}
       
  1645 	if(fieldType!=KUidContactFieldNone)
       
  1646 		{
       
  1647 		type->AddFieldTypeL(fieldType);
       
  1648 		}
       
  1649 
       
  1650 	CArrayPtr<CParserParam>* paramArray = NULL ;
       
  1651 	paramArray = aVCardProperty.ParamArray();
       
  1652 
       
  1653 	// parameters
       
  1654 	if (IsParameterValuePresent(paramArray, KVersitTokenTYPE, KVersitParam8Internet))
       
  1655 		{
       
  1656 		type->AddFieldTypeL(KUidContactFieldVCardMapINTERNET);
       
  1657 		}
       
  1658 	if  (IsParameterValuePresent(paramArray, KVersitTokenTYPE, KVersitParam8Home))
       
  1659 		{
       
  1660 		type->AddFieldTypeL(KUidContactFieldVCardMapHOME);
       
  1661 		}
       
  1662     if 	(IsParameterValuePresent(paramArray, KVersitTokenTYPE, KVersitParam8Work))
       
  1663 		{
       
  1664 		type->AddFieldTypeL(KUidContactFieldVCardMapWORK);
       
  1665 		}
       
  1666     if 	(IsParameterValuePresent(paramArray, KVersitTokenTYPE, KVersitParam8Voice))
       
  1667 		{
       
  1668 		type->AddFieldTypeL(KUidContactFieldVCardMapVOICE);
       
  1669 		}
       
  1670     if 	(IsParameterValuePresent(paramArray, KVersitTokenTYPE, KVersitParam8Fax))
       
  1671         {
       
  1672         type->RemoveFieldType(KUidContactFieldPhoneNumber);
       
  1673         type->AddFieldTypeL(KUidContactFieldFax);
       
  1674         type->AddFieldTypeL(KUidContactFieldVCardMapFAX);
       
  1675         }
       
  1676     if 	(IsParameterValuePresent(paramArray, KVersitTokenTYPE, KVersitParam8Pref))
       
  1677 		{
       
  1678 		type->AddFieldTypeL(KUidContactFieldVCardMapPREF);
       
  1679 		}
       
  1680     if 	(IsParameterValuePresent(paramArray, KVersitTokenTYPE, KVersitParam8Cell))
       
  1681 		{
       
  1682 		type->AddFieldTypeL(KUidContactFieldVCardMapCELL);
       
  1683 		}
       
  1684     if 	(IsParameterValuePresent(paramArray, KVersitTokenTYPE, KVersitParam8Pager))
       
  1685 		{
       
  1686 		type->AddFieldTypeL(KUidContactFieldVCardMapPAGER);
       
  1687 		}
       
  1688     if 	(IsParameterValuePresent(paramArray, KVersitTokenTYPE, KVersitParam8Bbs))
       
  1689 		{
       
  1690 		type->AddFieldTypeL(KUidContactFieldVCardMapBBS);
       
  1691 		}
       
  1692     if 	(IsParameterValuePresent(paramArray, KVersitTokenTYPE, KVersitParam8Modem))
       
  1693 		{
       
  1694 		type->AddFieldTypeL(KUidContactFieldVCardMapMODEM);
       
  1695 		}
       
  1696     if 	(IsParameterValuePresent(paramArray, KVersitTokenTYPE, KVersitParam8Car))
       
  1697 		{
       
  1698 		type->AddFieldTypeL(KUidContactFieldVCardMapCAR);
       
  1699 		}
       
  1700     if 	(IsParameterValuePresent(paramArray, KVersitTokenTYPE, KVersitParam8Isdn))
       
  1701 		{
       
  1702 		type->AddFieldTypeL(KUidContactFieldVCardMapISDN);
       
  1703 		}
       
  1704     if 	(IsParameterValuePresent(paramArray, KVersitTokenTYPE, KVersitParam8Video))
       
  1705 		{
       
  1706 		type->AddFieldTypeL(KUidContactFieldVCardMapVIDEO);
       
  1707 		}
       
  1708 	if 	(IsParameterValuePresent(paramArray, KVersitTokenTYPE, KVersitParam8Msg))
       
  1709 		{
       
  1710 		type->AddFieldTypeL(KUidContactFieldVCardMapMSG);
       
  1711 		}
       
  1712 	if 	(IsParameterValuePresent(paramArray, KVersitTokenTYPE, KVersitParam8Dom))
       
  1713 		{
       
  1714 		type->AddFieldTypeL(KUidContactFieldVCardMapDOM);
       
  1715 		}
       
  1716 	if 	(IsParameterValuePresent(paramArray, KVersitTokenTYPE, KVersitParam8X509))
       
  1717 		{
       
  1718     	type->AddFieldTypeL(KUidContactFieldVCardMapX509);
       
  1719 		}
       
  1720 	if 	(IsParameterValuePresent(paramArray, KVersitTokenTYPE, KVersitParam8PGP))
       
  1721 		{
       
  1722     	type->AddFieldTypeL(KUidContactFieldVCardMapPGP);
       
  1723 		}
       
  1724 	if (IsParameterValuePresent(paramArray, KVersitTokenTYPE, KVersitParamPOC))
       
  1725 		{
       
  1726 		type->AddFieldTypeL(KUidContactFieldVCardMapPOC);
       
  1727 		}
       
  1728 	if (IsParameterValuePresent(paramArray, KVersitTokenTYPE, KVersitParamSWIS))
       
  1729 		{
       
  1730 		type->AddFieldTypeL(KUidContactFieldVCardMapSWIS);
       
  1731 		}
       
  1732 	if (IsParameterValuePresent(paramArray, KVersitTokenTYPE, KVersitParamVOIP))
       
  1733 		{
       
  1734 		type->AddFieldTypeL(KUidContactFieldVCardMapVOIP);
       
  1735 		}
       
  1736 	
       
  1737 
       
  1738 	CleanupStack::Pop(type);
       
  1739 	return(type);
       
  1740     }
       
  1741 
       
  1742 /*
       
  1743  * Gets the bitmap format. This is done by looking for the name and value items in the parameter eg. TYPE=GIF
       
  1744  * the if construct assumes that this is  present in the vcf file. It is also possible to just have the format without
       
  1745  * the TYPE string and this is stored in the name part of the parameter so need to check through all supported formats
       
  1746  * to find if one is present, this is done in the else construct.
       
  1747  *
       
  1748  * @param aVCardProperty and aBitmapFormat
       
  1749  * @return void.
       
  1750  */   
       
  1751 void CVCardToContactsAppConverter::GetBitMapFormat(const CParserProperty& aVCardProperty, TFieldType& aBitmapFormat)
       
  1752     {
       
  1753     aBitmapFormat.iUid=KUidContactFieldNone.iUid;
       
  1754    
       
  1755     CParserParam* param=aVCardProperty.Param(KVersitTokenTYPE);
       
  1756     if (param)
       
  1757         {
       
  1758         TFieldType bitmapFormat=MapVCardPhotoTypeToFieldType(param->Value());
       
  1759         if (bitmapFormat.iUid!=KUidContactFieldNone.iUid)
       
  1760             {
       
  1761             aBitmapFormat.iUid = bitmapFormat.iUid;
       
  1762             }
       
  1763         } //if
       
  1764     else
       
  1765         {   
       
  1766             const TInt KNumberOfBitmaps = 16;
       
  1767             //Set up table of bitmap formats
       
  1768             const TBufC8<5> bitmapString[] =
       
  1769             {
       
  1770                 KVersitParam8Gif(),
       
  1771                 KVersitParam8Jpeg(),
       
  1772                 KVersitParam8Bmp(),
       
  1773                 KVersitParam8Tiff(),
       
  1774                 KVersitParam8Pict(),
       
  1775                 KVersitParam8Cgm(),
       
  1776                 KVersitParam8Wmf(),
       
  1777                 KVersitParam8Ps(),
       
  1778                 KVersitParam8Pdf(),
       
  1779                 KVersitParam8Mpeg(),
       
  1780                 KVersitParam8Mpeg2(),
       
  1781                 KVersitParam8Avi(),
       
  1782                 KVersitParam8Qtime(),   
       
  1783                 KVersitParam8Dib(),
       
  1784                 KVersitParam8Pmb(),
       
  1785                 KVersitParam8Met()     
       
  1786             };
       
  1787            
       
  1788             // Loop through the table looking for a param whose name matches the bitmap format
       
  1789             for (TInt i=0; i < KNumberOfBitmaps - 1; ++i)
       
  1790                 {
       
  1791                 CParserParam* paramNameCheck = aVCardProperty.Param(bitmapString[i]);
       
  1792                 if (paramNameCheck)
       
  1793                     {//ok found something
       
  1794                     TFieldType bitmapFormat=MapVCardPhotoTypeToFieldType(paramNameCheck->Name());
       
  1795                     aBitmapFormat.iUid = bitmapFormat.iUid;
       
  1796                     break;
       
  1797                     }
       
  1798                 }   
       
  1799         } //else
       
  1800    
       
  1801     }
       
  1802 
       
  1803 TFieldType CVCardToContactsAppConverter::MapVCardPhotoTypeToFieldType(/*const CParserParam& aParserParam*/TPtrC8 aBitmapStringPtr)
       
  1804 	{
       
  1805     if (aBitmapStringPtr.Length()<2)
       
  1806 		{
       
  1807 		return KUidContactFieldNone; //no bitmap type token are less than 2 characters long
       
  1808 		}
       
  1809 
       
  1810     TChar firstChar(aBitmapStringPtr[0]);
       
  1811 	firstChar=firstChar.GetUpperCase();
       
  1812 
       
  1813 	switch (firstChar)
       
  1814 		{
       
  1815 	case 'G':
       
  1816 		return KUidContactFieldVCardMapGIF;
       
  1817 	case 'C':
       
  1818 		return KUidContactFieldVCardMapCGM;
       
  1819 	case 'W':
       
  1820 		return KUidContactFieldVCardMapWMF;
       
  1821 	case 'B':
       
  1822 		return KUidContactFieldVCardMapBMP;
       
  1823 	case 'D':
       
  1824 		return KUidContactFieldVCardMapDIB;
       
  1825 	case 'P':
       
  1826 		{
       
  1827 	    TChar secondChar(aBitmapStringPtr[1]);
       
  1828 		switch (secondChar.GetUpperCase())
       
  1829 			{
       
  1830 		case 'S':
       
  1831 			return KUidContactFieldVCardMapPS;
       
  1832 		case 'M':
       
  1833 			return KUidContactFieldVCardMapPMB;
       
  1834 		case 'D':
       
  1835 			return KUidContactFieldVCardMapPDF;
       
  1836 		case 'I':
       
  1837 			return KUidContactFieldVCardMapPICT;
       
  1838 		default:
       
  1839 			return KUidContactFieldNone;
       
  1840 			}				
       
  1841 		}
       
  1842 	case 'T':
       
  1843 		return KUidContactFieldVCardMapTIFF;
       
  1844 	case 'J':
       
  1845 		return KUidContactFieldVCardMapJPEG;
       
  1846 	case 'M':
       
  1847         switch (aBitmapStringPtr.Length())
       
  1848 			{
       
  1849 		case 3:
       
  1850 			return KUidContactFieldVCardMapMET;
       
  1851 		case 4:
       
  1852 			return KUidContactFieldVCardMapMPEG;
       
  1853 		case 5:
       
  1854 			return KUidContactFieldVCardMapMPEG2;
       
  1855 		default:
       
  1856 			return KUidContactFieldNone;
       
  1857 			}
       
  1858 	case 'A':
       
  1859 		return KUidContactFieldVCardMapAVI;
       
  1860 	case 'Q':
       
  1861 		return KUidContactFieldVCardMapQTIME;
       
  1862 	default:
       
  1863 		return KUidContactFieldNone;
       
  1864 		}
       
  1865 	}
       
  1866 
       
  1867 
       
  1868 /**
       
  1869  * Checks each field in an array to see if one or more contain importable data. Assuming one field within
       
  1870  * the array does, then the whole array should be imported.
       
  1871  *
       
  1872  * @param aArray The array of text fields to be checked for importable data
       
  1873  * @return Whether the array should be imported.
       
  1874  */
       
  1875 TBool CVCardToContactsAppConverter::TextArrayContainsImportableData(const CDesCArray& aArray) const
       
  1876 	{
       
  1877 	// Text arrays are implicitly composite in nature
       
  1878 	const TInt count = aArray.Count();
       
  1879 	for(TInt i=0; i<count; i++)
       
  1880 		{
       
  1881 		const TPtrC pItem(aArray.MdcaPoint(i));
       
  1882 		if	(CContactVCardConverter::ContainsImportableData(pItem, CContactVCardConverter::EPropertyValueComposite, ImportType()))
       
  1883 			return ETrue;
       
  1884 		}
       
  1885 	//
       
  1886 	return EFalse;
       
  1887 	}
       
  1888 
       
  1889 /**
       
  1890  * Remove single space character entries from the specified composite property array and replace them
       
  1891  * with null values.
       
  1892  *
       
  1893  * The TimeIS sync engines use spaces and NULLs to indicate special behaviour. Space = supported
       
  1894  * but empty property. NULL = unsupported property.
       
  1895  *
       
  1896  * Contacts model fields do not support composite properties themselves. Instead, the following
       
  1897  * method is used to converted a composite (array) property to a non composite value:
       
  1898  *
       
  1899  * CContactTextField::SetStandardTextArray(...)
       
  1900  *
       
  1901  * This method simply concatenates all the array values into one non-composite value. A CRLF
       
  1902  * is added between each sub-field. Therefore, if a composite property reads thus:
       
  1903  *
       
  1904  * {"A","B"}
       
  1905  *
       
  1906  * contacts model will store the result as "A\r\n\B".
       
  1907  *
       
  1908  * In the case where a composite property from TimeIS contains a supported but empty field value,
       
  1909  * without special handling, the space character (implicit meaning: "supported but empty")
       
  1910  * will be interpreted literally and stored within the contacts model field as real data.
       
  1911  *
       
  1912  * For example: {"Symbian"," "}
       
  1913  *
       
  1914  * The implied meaning of this (in terms of PC sync) is:
       
  1915  *
       
  1916  * OrgName: Symbian
       
  1917  * OrgUnit: (a supported field of the PC PIM, but contains no data at this time).
       
  1918  *
       
  1919  * In the above example, without special processing, the resultant contacts model field would read thus:
       
  1920  *
       
  1921  * "Symbian\r\n "
       
  1922  *
       
  1923  * The trailing space would also be exported during any synchronisation, and therefore introduce
       
  1924  * unexpected data in the sync chain.
       
  1925  *
       
  1926  * This method simply ensures that single space characters are mapped back to their 'real' meaning,
       
  1927  * i.e. a NULL.
       
  1928  *
       
  1929  * @param aArray The composite property which needs fixing up
       
  1930  */
       
  1931 void CVCardToContactsAppConverter::RemoveWhitespaceFromCompositePropertyL(CDesCArray& aArray)
       
  1932 	{
       
  1933 	const TInt count = aArray.Count();
       
  1934 	for(TInt i=0; i<count; i++)
       
  1935 		{
       
  1936 		TPtrC pItem(aArray[i]);
       
  1937 		if	(pItem == KContactVCardCompositeSupportedButEmptyFieldValue)
       
  1938 			{
       
  1939 			aArray.Delete(i);
       
  1940 			aArray.InsertL(i, KContactVCardEmptyFieldValue);
       
  1941 			}
       
  1942 		}
       
  1943 	}
       
  1944 
       
  1945 /**
       
  1946  * Get a Pointer to the First Instance of the specified Property's value in the VCard Object
       
  1947  *
       
  1948  * @param aVCard A vCard Object containing Array of Properties
       
  1949  * @param aToken A String with desired Property Name
       
  1950  * @param A buffer descriptor expected to contain the first instance of desired property Value on return
       
  1951  * @return Count of Class Properties found
       
  1952  */
       
  1953 TInt CVCardToContactsAppConverter::GetSingleInstanceL(const CParserVCard& aVCard,const TDesC8& aToken, TDes& aClass)
       
  1954 	{
       
  1955 	CArrayPtr<CParserProperty>* arrayOfProp=aVCard.PropertyL(aToken, TUid::Uid(KVersitPropertyHBufCUid), EFalse);
       
  1956 	if(arrayOfProp)
       
  1957 		{
       
  1958 		CleanupStack::PushL(arrayOfProp);
       
  1959 		TInt propCount = arrayOfProp->Count();
       
  1960 		CParserProperty* property = arrayOfProp->At(0);
       
  1961 		CParserPropertyValueHBufC* propertyAsHBufC = static_cast<CParserPropertyValueHBufC*>(property->Value());
       
  1962 		aClass = propertyAsHBufC->Value();
       
  1963 		if( !aClass.Length() )
       
  1964 			{
       
  1965 			propCount = 0;
       
  1966 			}
       
  1967 		CleanupStack::PopAndDestroy(arrayOfProp);
       
  1968 		return 	propCount;
       
  1969 		}
       
  1970 	return 0;
       
  1971 	}
       
  1972 
       
  1973 /**
       
  1974  * Add a specific field into a contact
       
  1975  *
       
  1976  * @param aContact Contact item to add fields to
       
  1977  * @param aValue Reference to first Instance of the Property Value
       
  1978  * @param aFieldType Field type of field to add (TFieldType)
       
  1979  * @param aMapping vCard mapping Id of the field to add.
       
  1980  * @param aNames An object containing the name and labels for 'N' property fields
       
  1981  * @param aOption Import preferences (available options defined in CContactDatabase::TOptions)
       
  1982  */
       
  1983 void CVCardToContactsAppConverter::SetSingleInstanceL(CContactItem& aContact,const TDes& aValue,const TFieldType& aFieldType, const TUid& aMapping, TInt aOption)
       
  1984 	{
       
  1985 	//
       
  1986 	TBool addField = EFalse;
       
  1987 	if (CContactVCardConverter::EConnectWhitespace & aOption)
       
  1988 		{
       
  1989 		addField = CContactVCardConverter::ContainsImportableData(aValue, CContactVCardConverter::EPropertyValueSingle, ImportType());
       
  1990 		}
       
  1991 	else
       
  1992 		{
       
  1993 		addField = (aValue.Length());
       
  1994 		}
       
  1995 	// Only add the field if it contains some data
       
  1996 	if	(addField)
       
  1997 		{
       
  1998 		CContactItemField* contactItemField = CContactItemField::NewLC(KStorageTypeText, aFieldType);
       
  1999 		contactItemField->SetMapping(aMapping);
       
  2000 		contactItemField->TextStorage()->SetStandardTextL(aValue);
       
  2001 		aContact.AddFieldL(*contactItemField);
       
  2002 		CleanupStack::Pop(contactItemField);
       
  2003 		}
       
  2004 	}
       
  2005 
       
  2006 /**
       
  2007  * Merge a specific field from a contact
       
  2008  *
       
  2009  * @param aContact Contact item to add fields to
       
  2010  * @param aValue Pointer to first Instance of the Property Value
       
  2011  * @param aFieldType Field type of field to add (TFieldType)
       
  2012  * @param aMapping vCard mapping Id of the field to add.
       
  2013  * @param aNames An object containing the name and labels for 'N' property fields
       
  2014  * @param aOption Import preferences (available options defined in CContactDatabase::TOptions)
       
  2015  */
       
  2016 void CVCardToContactsAppConverter::MergeSingleInstanceL(CContactItem& aContact, const TDes& aValue,const TFieldType& aFieldType, const TUid& aMapping, TInt aOption)
       
  2017 	{
       
  2018 	CContactItemFieldSet& oldfieldset = aContact.CardFields();
       
  2019 	const TInt pos = oldfieldset.Find(aFieldType, aMapping);
       
  2020 	const TBool processWhitespace = (aOption & CContactVCardConverter::EConnectWhitespace);
       
  2021 
       
  2022 	// First check whether the field is present in the contact card
       
  2023 	// Also verify that the array of address sub-values actually contains a specific
       
  2024 	// value for the requested index.
       
  2025 	const TInt Klength = aValue.Length();
       
  2026 	if (processWhitespace)
       
  2027 		{
       
  2028 		TBool isSingleSpace = EFalse;
       
  2029 		if (Klength == 1)
       
  2030 			{
       
  2031 			isSingleSpace = (aValue[0] == KContactVCardSpaceCharacter);
       
  2032 			}
       
  2033 		if	((pos != KErrNotFound) && (Klength || isSingleSpace))
       
  2034 			{
       
  2035 			// This means the PC side field is empty, so delete the corresponding device-side field.
       
  2036 			aContact.RemoveField(pos);
       
  2037 			}
       
  2038 		if	(Klength && !isSingleSpace)
       
  2039 			{
       
  2040 			// This means the PC side field is unsupported, so ignore the corresponding contents.
       
  2041 			SetSingleInstanceL(aContact, aValue, aFieldType,aMapping,aOption);
       
  2042 			}
       
  2043 		}
       
  2044 	else
       
  2045 		{
       
  2046 		if (pos != KErrNotFound)
       
  2047 			{
       
  2048 			// This means the PC side field is empty, so delete the corresponding device-side field.
       
  2049 			aContact.RemoveField(pos);
       
  2050 			}
       
  2051 		if (Klength)
       
  2052 			{
       
  2053 			// This means the PC side field is not empty, so add the corresponding contents.
       
  2054 			SetSingleInstanceL(aContact, aValue, aFieldType,aMapping,aOption);
       
  2055 			}
       
  2056 		}
       
  2057 	}
       
  2058 
       
  2059 /**
       
  2060  * Get an Array containing Property's values from a VCard
       
  2061  *
       
  2062  * @param aVCard A vCard Object containing Array of Properties
       
  2063  * @param aToken A String with desired Property Name
       
  2064  * @param A Composite Descriptor array with desired vCard Property's Values on return
       
  2065  * @return Count of desired properties found.
       
  2066  */
       
  2067 
       
  2068 TInt CVCardToContactsAppConverter::GetVCardPropertyAsArrayOfValuesL(const CParserVCard& aVCard, const TDesC8& aToken, CDesCArray& aItems)
       
  2069 	{
       
  2070 	CArrayPtr<CParserProperty>* arrayOfProp =aVCard.PropertyL(aToken,TUid::Uid(KVersitPropertyCDesCArrayUid),EFalse);
       
  2071 	TInt propCount = 0;
       
  2072 	if(arrayOfProp)
       
  2073 		{
       
  2074 		CleanupStack::PushL(arrayOfProp);
       
  2075 		propCount = arrayOfProp->Count();
       
  2076 		CParserProperty* property = arrayOfProp->At(0);
       
  2077 		CDesCArray& value = *static_cast<CParserPropertyValueCDesCArray*>(property->Value())->Value();
       
  2078 		if(value.Count())
       
  2079 			{
       
  2080 			for(TInt i = 0;i < value.Count();i++)
       
  2081 				{
       
  2082 				aItems.AppendL(value.MdcaPoint(i));
       
  2083 				}
       
  2084 			}
       
  2085 		else
       
  2086 			{
       
  2087 			propCount = 0;
       
  2088 			}
       
  2089 		CleanupStack::PopAndDestroy(arrayOfProp);
       
  2090 		}
       
  2091 
       
  2092 	return propCount;
       
  2093 	}
       
  2094 
       
  2095 /**
       
  2096  * Add Organization Information like Company Name and Department Name into contact
       
  2097  *
       
  2098  * @param aContact Contact item to add fields to
       
  2099  * @param aItems A CDesC Array containing the Property's value
       
  2100  * @param aOption Import preferences (available options defined in CContactDatabase::TOptions)
       
  2101  */
       
  2102 void CVCardToContactsAppConverter::SetOrgDetailsL(CContactItem& aContact,CDesCArray& aItems,const TInt aOption)
       
  2103 	{
       
  2104 	TInt orgCount = aItems.MdcaCount();
       
  2105 	SetSpecificFieldL(aContact, aItems, KUidContactFieldCompanyName, KUidContactFieldVCardMapORG, aOption, 0, 1);
       
  2106 	SetSpecificFieldL(aContact, aItems, KUidContactFieldDepartmentName,	KUidContactFieldVCardMapDepartment, aOption, 1, orgCount);
       
  2107 	}
       
  2108 
       
  2109 /**
       
  2110  * Add a specific field from the Array of Property's values into contact
       
  2111  *
       
  2112  * @param aContact Contact item to add fields to
       
  2113  * @param aItems A CDesC Array containing the Property's values
       
  2114  * @param aFieldType Field type of field to add (TFieldType)
       
  2115  * @param aMapping vCardMapping Id of field to add
       
  2116  * @param aOption Import preferences (available options defined in CContactDatabase::TOptions)
       
  2117  * @param aStartIndex Starting Index in the Property Value Array
       
  2118  * @param aEndIndex   Ending Index in the Property Value Array
       
  2119  */
       
  2120 void CVCardToContactsAppConverter::SetSpecificFieldL(CContactItem& aContact,CDesCArray& aItems,const TUid& aFieldType,const TUid& aMapping,TInt aOption, TInt aStartIndex, TInt aEndIndex)
       
  2121 	{
       
  2122 	TBool doConvert = ETrue;
       
  2123 	TInt ii = 0;
       
  2124 
       
  2125 	CDesCArrayFlat* orgList = new (ELeave)CDesCArrayFlat(4);
       
  2126 	CleanupStack::PushL(orgList);
       
  2127 
       
  2128     for (ii = aStartIndex;ii < aEndIndex;ii++)
       
  2129     	{
       
  2130     	orgList->AppendL(aItems.MdcaPoint(ii));
       
  2131     	}
       
  2132 	if ((CContactVCardConverter::EConnectWhitespace & aOption) && orgList)
       
  2133 		{
       
  2134 		doConvert = TextArrayContainsImportableData(*orgList);
       
  2135 		if (doConvert)
       
  2136 			{
       
  2137 			RemoveWhitespaceFromCompositePropertyL(*orgList);
       
  2138 			}
       
  2139 		}
       
  2140 	if (doConvert)
       
  2141 		{
       
  2142 		CContactItemField* contactItemField = CContactItemField::NewLC(KStorageTypeText, aFieldType);
       
  2143 		contactItemField->SetMapping(aMapping);
       
  2144 		contactItemField->TextStorage()->SetStandardTextArray(orgList);
       
  2145 		aContact.AddFieldL(*contactItemField);
       
  2146 		CleanupStack::Pop(contactItemField);
       
  2147 		}
       
  2148 
       
  2149 	CleanupStack::PopAndDestroy(orgList); // orgList
       
  2150 }
       
  2151 
       
  2152 /**
       
  2153  * Merge Organization Information like Company Name and Department Name into contact
       
  2154  *
       
  2155  * @param aContact Contact item to add fields to
       
  2156  * @param aItems A CDesC Array containing the Property's value
       
  2157  * @param aFieldType Field type of field to add (TFieldType)
       
  2158  * @param aMapping vCardMapping Id of field to add
       
  2159  * @param aOption Import preferences (available options defined in CContactDatabase::TOptions)
       
  2160  * @param aStartIndex Starting Index in the Property Value Array
       
  2161  * @param aEndIndex   Ending Index in the Property Value Array
       
  2162  */
       
  2163 void CVCardToContactsAppConverter::MergeOrgDetailsL(CContactItem& aContact, CDesCArray& aItems, TInt aOption)
       
  2164 	{
       
  2165 	TInt orgCount = aItems.MdcaCount();
       
  2166 	MergeSpecificFieldL(aContact, aItems, KUidContactFieldCompanyName,	KUidContactFieldVCardMapORG, aOption, 0, 1);
       
  2167 	MergeSpecificFieldL(aContact, aItems, KUidContactFieldDepartmentName,	KUidContactFieldVCardMapDepartment, aOption, 1, orgCount);
       
  2168 	}
       
  2169 
       
  2170 /**
       
  2171  * Merge specific Field from the array of Property's values into contact
       
  2172  *
       
  2173  * @param aContact Contact item to add fields to
       
  2174  * @param aItems A CDesC Array containing the Property's value
       
  2175  * @param aFieldType Field type of field to add (TFieldType)
       
  2176  * @param aMapping vCardMapping Id of field to add
       
  2177  * @param aOption Import preferences (available options defined in CContactDatabase::TOptions)
       
  2178  * @param aStartIndex Starting Index in the Property Value Array
       
  2179  * @param aEndIndex   Ending Index in the Property Value Array
       
  2180  */
       
  2181 void CVCardToContactsAppConverter::MergeSpecificFieldL(CContactItem& aContact, CDesCArray& aItems, const TFieldType& aFieldType, const TUid& aMapping, TInt aOption, TInt aStartIndex, TInt aEndIndex)
       
  2182 	{
       
  2183 	CContactItemFieldSet& oldfieldset = aContact.CardFields();
       
  2184 	const TInt pos = oldfieldset.Find(aFieldType, aMapping);
       
  2185 	const TBool processWhitespace = (aOption & CContactVCardConverter::EConnectWhitespace);
       
  2186 
       
  2187 	// First check whether the field is present in the contact card
       
  2188 	// Also verify that the array of address sub-values actually contains a specific
       
  2189 	// value for the requested index.
       
  2190 	
       
  2191 	if(aItems.MdcaCount() > aStartIndex)
       
  2192 		{	
       
  2193 		const TPtrC pValue = aItems.MdcaPoint(aStartIndex);
       
  2194 		const TInt Klength = pValue.Length();
       
  2195 		if (processWhitespace)
       
  2196 			{
       
  2197 			TBool isSingleSpace = EFalse;
       
  2198 			if (Klength == 1)
       
  2199 				{
       
  2200 				isSingleSpace = (pValue[0] == KContactVCardSpaceCharacter);
       
  2201 				}
       
  2202 			if	((pos != KErrNotFound) && (Klength || isSingleSpace))
       
  2203 				{
       
  2204 				// This means the PC side field is empty, so delete the corresponding device-side field.
       
  2205 				aContact.RemoveField(pos);
       
  2206 				}
       
  2207 			if	(Klength && !isSingleSpace)
       
  2208 				{
       
  2209 				// This means the PC side field is unsupported, so ignore the corresponding contents.
       
  2210 				SetSpecificFieldL(aContact, aItems, aFieldType,	aMapping, aOption, aStartIndex, aEndIndex);
       
  2211 				}
       
  2212 			}
       
  2213 		else
       
  2214 			{
       
  2215 			if (pos != KErrNotFound)
       
  2216 				{
       
  2217 				// This means the PC side field is empty, so delete the corresponding device-side field.
       
  2218 				aContact.RemoveField(pos);
       
  2219 				}
       
  2220 			if (Klength)
       
  2221 				{
       
  2222 				// This means the PC side field is not empty, so add the corresponding contents.
       
  2223 				SetSpecificFieldL(aContact, aItems, aFieldType,	aMapping, aOption, aStartIndex, aEndIndex);
       
  2224 				}
       
  2225 			}
       
  2226 		}
       
  2227 	else if(pos != KErrNotFound)
       
  2228 		{
       
  2229 		aContact.RemoveField(pos);
       
  2230 		}
       
  2231 	}		
       
  2232 
       
  2233 /**
       
  2234  * Check if a specific field from vCard should be truncated or not.
       
  2235  *
       
  2236  * @param aPropertyName vCard property's name
       
  2237  *
       
  2238  * @return ETrue if the property must be truncated and EFalse otherwise
       
  2239  *
       
  2240  */
       
  2241 TBool CVCardToContactsAppConverter::PropertyTobeTruncated(const TPtrC8& aPropertyName) const
       
  2242 	{
       
  2243 	//Test is the field is one that has to be truncated
       
  2244 	if( aPropertyName == KVersitTokenN || aPropertyName == KVersitTokenORG || 
       
  2245 		aPropertyName == KVersitTokenTEL || aPropertyName == KVersitTokenEMAIL )
       
  2246 		return ETrue;
       
  2247 	//	
       
  2248 	return EFalse;
       
  2249 	}
       
  2250 
       
  2251 /**
       
  2252  * Check if a specific parameter value exists in a parameter array.
       
  2253  *
       
  2254  * @param aParamArray Array of property parameters in which value has to be searched.
       
  2255  * @param aParamName A parameter name whose corresponding parameter value present in aParamArray has to be matched with aParamValue.
       
  2256  * @param aParamValue A parameter value which will be used to search.
       
  2257  * @return TBool ETrue if value is found in parameter array, otherwise EFalse.
       
  2258  */
       
  2259 TBool CVCardToContactsAppConverter::IsParameterValuePresent(CArrayPtr<CParserParam>* aParamArray, const TDesC8& aParamName, const TDesC8& aParamValue)
       
  2260 	{
       
  2261 	if(!aParamArray)
       
  2262 		{
       
  2263 		return EFalse;
       
  2264 		}
       
  2265 	const TInt count = aParamArray->Count();
       
  2266 	for (TInt ii = 0; ii < count; ii++)
       
  2267 		{
       
  2268 		if((*aParamArray)[ii]->Name().CompareF(aParamValue) == 0)
       
  2269 			{
       
  2270 			return ETrue;		
       
  2271 			}
       
  2272 		else if((*aParamArray)[ii]->Name().CompareF(aParamName) == 0)
       
  2273 			{
       
  2274 			if((*aParamArray)[ii]->Value().CompareF(aParamValue) == 0)
       
  2275 				{
       
  2276 				return ETrue;		
       
  2277 				}	
       
  2278 			}
       
  2279 		}
       
  2280 	return EFalse;	
       
  2281 	}
       
  2282 
       
  2283 /**
       
  2284  * If there are multiple EMAIL and TEL properties in a vCard, then there should only be a single EMAIL or TEL property 
       
  2285  * with a PREF parameter. If more than one EMAIL or TEL properties contain a PREF parameter,then only the first property
       
  2286  * with the PREF parameter is stored and the other properties are stored with their other parameters but without the
       
  2287  * PREF parameter.
       
  2288  * 
       
  2289  * @param aMainContact, Contact item for the vCard
       
  2290  * @param aFieldType, the fieldtype in conjuction with the mapping is used to search for fields.
       
  2291  * @param aMapping, the mapping is used for searching a field i.e. EMAIL or TEL fields.
       
  2292  */
       
  2293 
       
  2294 void CVCardToContactsAppConverter::AdjustForPrefRule(CContactItem& aContact, TFieldType aFieldType, TUid aMapping)
       
  2295 	{
       
  2296 	TInt pos = 0;
       
  2297 	TInt prefCount = 0;
       
  2298 	CContactItemFieldSet& contactItemFieldSet = aContact.CardFields();
       
  2299 	pos = contactItemFieldSet.FindNext(aFieldType, aMapping, pos);
       
  2300 	while (pos != KErrNotFound)
       
  2301 		{
       
  2302 		CContactItemField& contactItemField = contactItemFieldSet[pos];
       
  2303 		const CContentType& contentType = contactItemField.ContentType();
       
  2304 		TBool pref = contentType.ContainsFieldType(KUidContactFieldVCardMapPREF);
       
  2305 		if (pref)
       
  2306 			{
       
  2307 			++prefCount;
       
  2308 			if (prefCount > 1)
       
  2309 				{
       
  2310 				contactItemField.RemoveFieldType(KUidContactFieldVCardMapPREF);
       
  2311 				}
       
  2312 			}
       
  2313 		++pos;
       
  2314 		pos = contactItemFieldSet.FindNext(aFieldType, aMapping, pos);
       
  2315 		}
       
  2316 	}