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