phonebookengines/contactsmodel/cntvcard/cntvcardexport.cpp
changeset 0 e686773b3f54
child 24 0ba2181d7c28
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/phonebookengines/contactsmodel/cntvcard/cntvcardexport.cpp	Tue Feb 02 10:12:17 2010 +0200
@@ -0,0 +1,1490 @@
+// Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+#include <badesca.h>
+#include <vtoken.h>
+#include <cntfldst.h>
+#include <cntfield.h>
+#include "cntvcardutils.h"
+#include <cntdef.h>
+#include <cntitem.h>
+#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
+#include "vcard3.h"
+#include "cntdb_internal.h"
+#endif
+
+
+
+/**
+ * Destructor
+ */
+CContactsAppToVCardConverter::~CContactsAppToVCardConverter()
+    {
+    delete iVCard;
+    }
+
+
+/** 
+ * Constructor
+ * 
+ * @param aMachineUniqueId Integer unique to the database
+ * @param aCharSet Default character set to pass to Versit parser component
+ * @param aVCardVersion Version of vCard being exported
+ */
+CContactsAppToVCardConverter::CContactsAppToVCardConverter(TInt64 aMachineUniqueId, Versit::TVersitCharSet aCharSet, TVCardVersion aVCardVersion) :
+	iMachineUniqueId(aMachineUniqueId),
+	iCharSet(aCharSet),
+	iVCardVersion(aVCardVersion),
+	iFilter(0)
+	{
+	}
+
+
+/** 
+ * Convert a contact item into a vCard.
+ * 
+ * @param aMainItem Contact item to convert
+ * @param aAgentItem Agent contact item to convert
+ * @param aOption Export preferences (options available defined in CContactDatabase::TOptions)
+ * @param aExportPrivateFields Specify whether private fields are exported
+ * @return vCard representation of contact item
+ */
+CParserVCard* CContactsAppToVCardConverter::GetContactItemAsVCardL(CContactItem* aMainItem, CArrayPtr<CContactItem>* aAgentItemArray, TInt aOption, TBool aExportPrivateFields)
+    {
+    switch(iVCardVersion)
+		{
+		case EVCard21:
+		case EPBAPVCard21:
+			iVCard = CParserVCard::NewL();
+		break;
+		
+		case EPBAPVCard30:
+			iVCard = CParserVCard3::NewL();
+		break;
+		
+		default:
+		User::Leave(KErrArgument);
+		break;
+		}
+	iVCard->SetDefaultCharSet(iCharSet);
+	EncodeItemPropertiesL(*aMainItem,aOption);
+	EncodeFieldPropertiesL(*aMainItem, aAgentItemArray, aOption, aExportPrivateFields);
+    CParserVCard* vCard=iVCard;
+    iVCard=NULL;
+    return vCard;
+    }
+
+
+/** 
+ * Encode the properties associated with a contact item which are not fields
+ * 
+ * @param aContactItem Contact item to export
+ * @param aOption Export preferences (options available defined in CContactDatabase::TOptions)
+ */
+void CContactsAppToVCardConverter::EncodeItemPropertiesL(const CContactItem& aContactItem,TInt aOption)
+	{
+	TBool pbapExp = IsPBAPExport();
+	if( !pbapExp || (pbapExp && NeedsToBeExported(EPropertyREV)) )
+		{
+		// PREQ234 stipulates that times are stored as UTC time; as long as we
+		// put UTC time, we can assume that it's UTC time out.
+		CParserPropertyValueDateTime* valueDateTime = CreateDateTimePropertyL(aContactItem.LastModified(), TVersitDateTime::EIsUTC);
+		CleanupStack::PushL(valueDateTime);
+		CParserProperty* property = CParserGroupedProperty::NewL(*valueDateTime, KVersitTokenREV, NULL, NULL);
+		CleanupStack::Pop(valueDateTime);	
+		iVCard->AddPropertyL(property); //takes ownership
+		}
+	if (!(aOption & CContactVCardConverter::EExcludeUid))
+		{
+		TPtrC guid=aContactItem.UidStringL(iMachineUniqueId);
+		CParserPropertyValueHBufC* uidValue=CParserPropertyValueHBufC::NewL(guid);
+		CleanupStack::PushL(uidValue);
+		CParserProperty* uidproperty=CParserGroupedProperty::NewL(*uidValue,KVersitTokenUID,NULL,NULL);
+		CleanupStack::Pop(uidValue);	
+		iVCard->AddPropertyL(uidproperty); //takes ownership
+		}
+	}
+
+    
+/** 
+ * Convert all CContactItemFields into VCard properties and add them to iVCard.
+ * Contact fields with no value (ie. empty fields) are not exported.
+ * 
+ * @param aMainItem Contact item to convert
+ * @param aAgentItem Agent contact item to convert
+ * @param aOption Export preferences (options available defined in CContactDatabase::TOptions)
+ * @param aExportPrivateFields Specify whether private fields are exported
+ */
+void CContactsAppToVCardConverter::EncodeFieldPropertiesL(const CContactItem& aContactItem, CArrayPtr<CContactItem>* aAgentItemArray, TInt aOption, TBool aExportPrivateFields)
+	{
+	CContactItemFieldSet& fieldSet = aContactItem.CardFields();
+	TBool pbapExp = IsPBAPExport();
+	// Name
+	GetVCardNameL(fieldSet, aOption, aExportPrivateFields);
+	if(GetExportVersion() == EVCard21)
+		{
+		GetVCardFormattedNameL(fieldSet,aOption,aExportPrivateFields);
+		GetVCardNamePrnL(fieldSet, aOption, aExportPrivateFields);
+		// Addresses (home, work, pref and general)
+		GetVCardAddressL(aContactItem, KUidContactFieldVCardMapHOME, KVersitParam8Home, aOption, aExportPrivateFields);
+		GetVCardAddressL(aContactItem, KUidContactFieldVCardMapWORK, KVersitParam8Work, aOption, aExportPrivateFields);
+		GetVCardAddressL(aContactItem, KUidContactFieldVCardMapPREF, KVersitParam8Pref, aOption, aExportPrivateFields);
+		GetVCardAddressL(aContactItem, KNullUid, KNullDesC8, aOption, aExportPrivateFields);
+		// Organization Information (Company Name and Department Name)
+		GetVCardOrgInfoL(fieldSet, aOption, aExportPrivateFields);
+		}
+	else if(pbapExp)
+		{
+		//check if the mapping is contained in the filter
+		if(NeedsToBeExported(EPropertyFN))				
+			{
+			GetVCardFormattedNameL(fieldSet, aOption, aExportPrivateFields);
+			}
+		if(NeedsToBeExported(EPropertySOUND))
+			{
+			GetVCardNamePrnL(fieldSet, aOption, aExportPrivateFields);	
+			}
+		// Addresses (home, work, pref and general)
+		if(NeedsToBeExported(EPropertyADR))
+			{
+			GetVCardAddressL(aContactItem, KUidContactFieldVCardMapHOME, KVersitParam8Home, aOption, aExportPrivateFields);
+			GetVCardAddressL(aContactItem, KUidContactFieldVCardMapWORK, KVersitParam8Work, aOption, aExportPrivateFields);
+			GetVCardAddressL(aContactItem, KUidContactFieldVCardMapPREF, KVersitParam8Pref, aOption, aExportPrivateFields);
+			GetVCardAddressL(aContactItem, KNullUid, KNullDesC8, aOption, aExportPrivateFields);	
+			}
+		if(NeedsToBeExported(EPropertyORG))
+			{
+			// Organization Information (Company Name and Department Name)
+			GetVCardOrgInfoL(fieldSet, aOption, aExportPrivateFields);	
+			}
+		}
+		
+	CContactItem* agentItem;
+	TInt numAgent = 0;
+	// Other fields
+	TBool telFound = EFalse;
+	const TInt count = fieldSet.Count();
+	TInt agentcount=0;
+	if(aAgentItemArray &&  aAgentItemArray->Count())
+	agentcount = aAgentItemArray->Count();
+	for (TInt ii = 0; ii < count; ++ii)
+
+		{
+		agentItem = NULL;
+
+		const CContactItemField& field = fieldSet[ii];
+		if (!field.Storage()->IsFull())
+			continue;
+
+		const CContentType& content=field.ContentType();
+		TInt before=1;
+		TInt total=0;
+
+		for (TInt jj=0; jj<count; ++jj)
+			{
+			// This content type comparison should ignore insignificant content types (e.g. Pref et al).
+			if (content==fieldSet[jj].ContentType())
+				{
+				if (jj<ii)
+					{
+					++before;
+					}
+				++total;
+				}
+			}
+		if (total==1)
+			{
+			before=0;
+			}
+	
+		if(field.StorageType() == KStorageTypeContactItemId && agentcount > 0)
+			{
+			agentItem = aAgentItemArray->At(numAgent);
+			++numAgent;
+			}
+
+		MapContactFieldToVCardPropertyL(field, agentItem, aOption, before, aExportPrivateFields);
+	
+		if (field.ContentType().Mapping() == KUidContactFieldVCardMapTEL)
+			{//at least one non empty telephone field exists
+			telFound = ETrue;
+			}
+	    }
+	    	
+	//if the TEL property has been requested then it must be exported. If no non-empty
+	//telephone fields have been found at this point create a single empty TEL property
+	if (NeedsToBeExported(EPropertyTEL) && !telFound)
+		{
+		CParserPropertyValue* value = CParserPropertyValueHBufC::NewL(KNullDesC);	
+		CleanupStack::PushL(value);
+		CParserGroupedProperty* property = CParserGroupedProperty::NewL(*value, KVersitTokenTEL, NULL, NULL);
+		CleanupStack::Pop(value);
+		//ownership passed
+		iVCard->AddPropertyL(property);	
+	    }
+    }
+
+/**
+ * Find an address field which does not correspond to the HOME or WORK field type
+ * (i.e. a General Address).
+ *
+ * @return The index into the field set of the located field, or KErrNotFound if the field was not located
+ */
+TInt CContactsAppToVCardConverter::FindAddressFieldByMappingAndType(const CContactItemFieldSet& aFields, TFieldType aFieldType, TUid aMapping)
+	{
+	TInt pos = 0;
+	if (aFieldType != KNullUid)
+		{
+		pos = aFields.Find(aFieldType, aMapping);
+		}
+	else
+		{
+		TBool fieldFound = EFalse;
+		TInt startPos = KContactFieldSetSearchAll;
+				
+		while(!fieldFound && !(pos == KErrNotFound))
+			{
+			pos = aFields.FindNext(aMapping, startPos);
+			startPos = pos + 1;
+			if (pos != KErrNotFound )
+				{
+				const CContactItemField& tempField = aFields[pos];
+				const CContentType& tempContentType = tempField.ContentType();
+				TBool additionalMapFound = EFalse;
+				additionalMapFound |= tempContentType.ContainsFieldType(KUidContactFieldVCardMapHOME);
+				additionalMapFound |= tempContentType.ContainsFieldType(KUidContactFieldVCardMapWORK);
+				additionalMapFound |= tempContentType.ContainsFieldType(KUidContactFieldVCardMapPREF);
+				if (!additionalMapFound)
+					{
+					fieldFound = ETrue;
+					}
+				}
+			}
+		}
+	return pos;
+	}
+
+
+/**
+ * Retrieve an address field from the contact card's field set
+ * 
+ * @param aFields Contact item field set
+ * @param aParams Array of CParserParam
+ * @param aDesArray Descriptor array
+ * @param aUid1 Contact model vCard mapping (ie. KUidContactFieldVCardMapXXX)
+ * @param aUid2 Contact model vCard mapping (ie. KUidContactFieldVCardMapXXX)
+ * @param aLabel Label name to append to standard KContactVCardXDashEPOCCNTMODEL property parameter extension 
+ * @param aOption Export preferences (options available defined in CContactvCardConverter::TOptions)
+ * @param aFound Field was found and is not empty
+ * @param aExportPrivateFields Specify whether private fields are included
+ * @param aWithoutPref If ETrue exclude preferred fields
+ */
+void CContactsAppToVCardConverter::RetrieveAddressFieldL(const CContactItemFieldSet& aFields, CArrayPtr<CParserParam>& aParams, CDesCArrayFlat& aDesArray, TFieldType aFieldType, TUid aMapping, const TDesC& aLabel, TInt aOption, TBool& aFound, TBool aExportPrivateFields, TBool aWithoutPref) const
+	{
+	const TInt pos = FindAddressFieldByMappingAndType(aFields, aFieldType, aMapping);
+	const TBool processWhitespace = (aOption & CContactVCardConverter::EConnectWhitespace);
+	if	(pos == KErrNotFound)
+		{
+		if (processWhitespace)
+			{
+			aDesArray.AppendL(KContactVCardCompositeSupportedButEmptyFieldValue);
+			}
+		else
+			{
+			aDesArray.AppendL(KNullDesC);
+			}
+		return;
+		}
+	
+	const CContactItemField& field = aFields[pos];
+	if (aFieldType == KUidContactFieldVCardMapHOME && field.ContentType().ContainsFieldType(KUidContactFieldVCardMapWORK))
+		{
+		// Only want to skip this field if it contains both the work mapping and 
+		// we have searched on the home mapping.
+		// 
+		// Next time we come into this function it will be looking for the work mapping
+		// i.e. aUid1==KUidContactFieldVCardMapWORK that way if an ADR is both work and home
+		// it will only be processed once
+		if (processWhitespace)
+			{
+			aDesArray.AppendL(KContactVCardCompositeSupportedButEmptyFieldValue);
+			}
+		else
+			{
+			aDesArray.AppendL(KNullDesC);
+			}
+		return;
+		}
+
+	if (aWithoutPref && field.ContentType().ContainsFieldType(KUidContactFieldVCardMapPREF))
+		{
+		if (processWhitespace)
+			{
+			aDesArray.AppendL(KContactVCardCompositeSupportedButEmptyFieldValue);
+			}
+		return;
+		}
+
+	// Assume we're not going to export this field - unless we find some real data
+	TBool validItemToExport = EFalse;
+
+	if (!field.IsPrivate() || aExportPrivateFields)
+		{
+		TBool onCleanupStack = EFalse;
+		TPtrC pText(KNullDesC);
+		// If the field contains text, then get the text and examine it depending on the flags.
+		// Note that the text is created in another buffer, which is pushed onto the stack. This
+		// will only happen if there is actually text - thus the need for the onCleanupStack flag.
+		if	(field.TextStorage() && field.TextStorage()->IsFull())
+			{
+			// This step puts the std text onto the cleanup stack - set the flag so it can be 
+			// cleaned up later.
+			pText.Set(field.TextStorage()->StandardTextLC());
+			onCleanupStack = ETrue;
+			if (processWhitespace)
+				{
+				validItemToExport = CContactVCardConverter::ContainsExportableData(pText);
+				}
+			else
+				{
+				validItemToExport = ETrue;
+				}
+			}
+		if	(validItemToExport)
+			{
+			aFound = ETrue;
+			aDesArray.AppendL(pText);
+			//
+			const TBool includeX = aOption & CContactDatabase::EIncludeX;
+ 			const TPtrC label = field.Label();
+  			if	(label.Size() && includeX && field.OverRidesLabel())
+   				{
+				TBuf8<KContactMaxVCardPropertyNameLength> param(KContactVCardXDashEPOCCNTMODEL);
+   				param.Append(aLabel);
+				//
+				CParserParam* parserParam = CParserParam::NewL(param, label);
+				CleanupStack::PushL(parserParam);
+   				aParams.AppendL(parserParam);
+				CleanupStack::Pop(parserParam);
+   				}
+			}
+		if	(onCleanupStack)
+			{
+			CleanupStack::PopAndDestroy(); // StandardText
+			}
+		}
+	if (!validItemToExport)
+		{
+		if (processWhitespace)
+			{
+			aDesArray.AppendL(KContactVCardCompositeSupportedButEmptyFieldValue);
+			}
+		else
+			{
+			aDesArray.AppendL(KNullDesC);
+			}
+		}
+	}
+
+
+/** 
+ * Build up name of VCard from the N and FN properties 
+ * 
+ * @param aContact Contact item to export
+ * @param aOption Export preferences (options available defined in CContactDatabase::TOptions)
+ * @param aExportPrivateFields Specify whether private fields are included
+ */ 
+void CContactsAppToVCardConverter::GetVCardNamePrnL(CContactItemFieldSet& aFields,TInt aOption,TBool aExportPrivateFields)
+	{
+	// For property parameters (should they be necessary) for this exported property
+	CArrayPtr<CParserParam>* arrayOfParams = new(ELeave) CArrayPtrFlat<CParserParam>(5);
+	CleanupStack::PushL(TCleanupItem(CleanUpResetAndDestroy,arrayOfParams));
+
+	// For the property value itself
+	CDesCArrayFlat* desArray=new (ELeave)CDesCArrayFlat(4);
+	CleanupStack::PushL(desArray);
+   
+	// Export each item in turn (where the field of the specified type is found 
+	// in the contact card).
+	TInt foundCount = 0;
+	foundCount += LocateSpecificNameValueL(aFields, KUidContactFieldFamilyNamePronunciation,	*desArray, *arrayOfParams, KContactVCardLABEL0, aOption, aExportPrivateFields);
+	foundCount += LocateSpecificNameValueL(aFields, KUidContactFieldGivenNamePronunciation,		*desArray, *arrayOfParams, KContactVCardLABEL1, aOption, aExportPrivateFields);
+
+  	if (foundCount > 0)
+		{
+		CParserPropertyValue* value = new(ELeave) CParserPropertyValueCDesCArray(desArray);
+	  	CleanupStack::Pop(desArray);
+		//
+	  	CleanupStack::PushL(value);
+	  	CParserGroupedProperty* property = CParserGroupedProperty::NewL(*value,KVersitTokenSOUND, NULL, arrayOfParams);
+	  	CleanupStack::Pop(2, arrayOfParams); // value, arrayOfParams
+		CleanupStack::PushL(property);
+  		CParserParam* param = CParserParam::NewL(KVersitParam8NamePrn, KNullDesC8);
+		CleanupStack::PushL(param);
+		property->AddParamL(param);
+		CleanupStack::Pop(2,property); // + param
+		// This pushes property before anything can leave...
+		iVCard->AddPropertyL(property);
+		}
+	else
+		{
+  		CleanupStack::PopAndDestroy(2, arrayOfParams); // desArray, arrayOfParams
+  		}
+	}
+
+/** 
+ * Build up name of VCard from the N and FN properties 
+ * 
+ * @param aContact Contact item to export
+ * @param aOption Export preferences (options available defined in CContactDatabase::TOptions)
+ * @param aExportPrivateFields Specify whether private fields are included
+ */ 
+void CContactsAppToVCardConverter::GetVCardNameL(CContactItemFieldSet& aFields,TInt aOption,TBool aExportPrivateFields)
+	{
+	// For property parameters (should they be necessary) for this exported property
+	CArrayPtr<CParserParam>* arrayOfParams = new(ELeave) CArrayPtrFlat<CParserParam>(5);
+	CleanupStack::PushL(TCleanupItem(CleanUpResetAndDestroy,arrayOfParams));
+
+	// For the property value itself
+	CDesCArrayFlat* desArray=new (ELeave)CDesCArrayFlat(4);
+	CleanupStack::PushL(desArray);
+   
+	// Export each item in turn (where the field of the specified type is found 
+	// in the contact card).
+	TInt foundCount = 0;
+
+	foundCount += LocateSpecificNameValueL(aFields, KUidContactFieldFamilyName,		*desArray, *arrayOfParams, KContactVCardLABEL0, aOption, aExportPrivateFields);
+	foundCount += LocateSpecificNameValueL(aFields, KUidContactFieldGivenName,		*desArray, *arrayOfParams, KContactVCardLABEL1, aOption, aExportPrivateFields);
+	foundCount += LocateSpecificNameValueL(aFields, KUidContactFieldAdditionalName,	*desArray, *arrayOfParams, KContactVCardLABEL2, aOption, aExportPrivateFields);
+	foundCount += LocateSpecificNameValueL(aFields, KUidContactFieldPrefixName,		*desArray, *arrayOfParams, KContactVCardLABEL3, aOption, aExportPrivateFields);
+	foundCount += LocateSpecificNameValueL(aFields, KUidContactFieldSuffixName,		*desArray, *arrayOfParams, KContactVCardLABEL4, aOption, aExportPrivateFields);
+	
+	//The N property must be exported even if empty for vCard 2.1 and 3.0 
+	//as per PBAP specification.
+	if (foundCount == 0 && IsPBAPExport())
+		{
+		//replace with single empty name value so that property is N: instead of N:;;;;
+		desArray->Reset();
+		desArray->AppendL(KNullDesC);
+		foundCount = 1; //forces the property to be created
+		}
+	
+	if (foundCount > 0)
+		{
+		CParserPropertyValue* value = new(ELeave) CParserPropertyValueCDesCArray(desArray);
+	  	CleanupStack::Pop(desArray);
+		//
+	  	CleanupStack::PushL(value);
+	  	CParserGroupedProperty* property = CParserGroupedProperty::NewL(*value,KVersitTokenN, NULL, arrayOfParams);
+
+	  	CleanupStack::Pop(2, arrayOfParams); // value, arrayOfParams
+		// This pushes property before anything can leave...
+		iVCard->AddPropertyL(property);
+		}
+	else
+		{
+  		CleanupStack::PopAndDestroy(2, arrayOfParams); // desArray, arrayOfParams
+  		}
+	}
+
+
+/** 
+ * Export address fields. This method exports the 7 address fields in the contact.
+ * 
+ * @param aContact Contact item to export
+ * @param aVCardMapping UID specifying whether this is a HOME, WORK or PREF address
+ * @param aToken The name of the vCard property parameter (eg. HOME, WORK, PREF)
+ * @param aOption Export preferences (options available defined in CContactDatabase::TOptions)
+ * @param aExportPrivateFields Specify whether private fields are included
+ */ 
+void CContactsAppToVCardConverter::GetVCardAddressL(const CContactItem& aContact, TUid aVCardMapping, const TDesC8& aToken, TInt aOption, TBool aExportPrivateFields)
+	{
+    CArrayPtr<CParserParam>* arrayOfParams = new(ELeave) CArrayPtrFlat<CParserParam>(5);
+	CleanupStack::PushL(TCleanupItem(CleanUpResetAndDestroy, arrayOfParams));
+
+	if	(aToken.Length())
+		{	
+		CParserParam* parserParam;
+		//nameless parameters not allowed for vCard 3.0, so add "TYPE" parameter name 
+		if (GetExportVersion() == EPBAPVCard30)
+			{
+			parserParam = CParserParam::NewL(KVersitTokenTYPE, aToken);
+			}
+		else
+			{
+			parserParam = CParserParam::NewL(aToken, KNullDesC);	
+			}
+		CleanupStack::PushL(parserParam);
+		arrayOfParams->AppendL(parserParam);
+		CleanupStack::Pop(parserParam);
+		}
+
+    const CContactItemFieldSet& fields = aContact.CardFields();
+	CDesCArrayFlat* desArray = new(ELeave) CDesCArrayFlat(4);
+	CleanupStack::PushL(desArray);
+
+	TBool found = EFalse;
+	RetrieveAddressFieldL(fields, *arrayOfParams, *desArray, aVCardMapping, KUidContactFieldVCardMapPOSTOFFICE, KContactVCardLABEL0, aOption, found, aExportPrivateFields,EFalse);
+	RetrieveAddressFieldL(fields, *arrayOfParams, *desArray, aVCardMapping, KUidContactFieldVCardMapEXTENDEDADR, KContactVCardLABEL1, aOption, found, aExportPrivateFields,EFalse);
+	RetrieveAddressFieldL(fields, *arrayOfParams, *desArray, aVCardMapping, KUidContactFieldVCardMapADR, KContactVCardLABEL2, aOption, found, aExportPrivateFields,EFalse);
+	RetrieveAddressFieldL(fields, *arrayOfParams, *desArray, aVCardMapping, KUidContactFieldVCardMapLOCALITY, KContactVCardLABEL3, aOption, found, aExportPrivateFields,EFalse);
+	RetrieveAddressFieldL(fields, *arrayOfParams, *desArray, aVCardMapping, KUidContactFieldVCardMapREGION, KContactVCardLABEL4, aOption, found, aExportPrivateFields,EFalse);
+	RetrieveAddressFieldL(fields, *arrayOfParams, *desArray, aVCardMapping, KUidContactFieldVCardMapPOSTCODE, KContactVCardLABEL5, aOption, found, aExportPrivateFields,EFalse);
+	RetrieveAddressFieldL(fields, *arrayOfParams, *desArray, aVCardMapping, KUidContactFieldVCardMapCOUNTRY, KContactVCardLABEL6, aOption, found, aExportPrivateFields,EFalse);
+
+	if (found)
+		{
+	    CParserPropertyValue* value = new (ELeave) CParserPropertyValueCDesCArray(desArray);
+	  	CleanupStack::Pop(desArray); 
+	  	CleanupStack::PushL(value); 
+		CParserGroupedProperty* property = CParserGroupedProperty::NewL(*value, KVersitTokenADR, NULL, arrayOfParams);
+	  	CleanupStack::Pop(2); //value, arrayOfParams
+		iVCard->AddPropertyL(property);
+		}
+	else
+  		CleanupStack::PopAndDestroy(2); // desArray,arrayOfParams
+	}
+
+
+/** 
+ * Convert CContactItemField into a VCard property and add it to iVCard 	
+ *
+ * @param aField Contact field
+ * @param aAgent Agent item
+ * @param aOption Export preferences (options available defined in CContactDatabase::TOptions)
+ * @param aDuplicateCount Number of fields of this field type in the contact item
+ * @param aExportPrivateFields Specify whether private fields are included
+ */
+void CContactsAppToVCardConverter::MapContactFieldToVCardPropertyL(const CContactItemField& aField,CContactItem* aAgent,TInt aOption,TInt aDuplicateCount,TBool aExportPrivateFields)
+	{
+	if (aField.IsPrivate() && !aExportPrivateFields)
+		{
+		return; // If aExportPrivateFields==EFalse, do not export private fields	
+		}
+		
+	TUid mapping=aField.ContentType().Mapping();
+	
+	//check if the mapping is contained in the filter
+	if(IsPBAPExport() && !NeedsToBeExported(AttributeFromMapping(mapping))) 
+		{
+			return;		
+		}
+	
+	if ((mapping==KUidContactFieldVCardMapUnusedN) ||  
+			(mapping==KUidContactFieldVCardMapADR) || (mapping==KUidContactFieldVCardMapPOSTOFFICE) ||
+			(mapping==KUidContactFieldVCardMapEXTENDEDADR) ||   (mapping==KUidContactFieldVCardMapLOCALITY)  ||
+			(mapping==KUidContactFieldVCardMapREGION) || (mapping==KUidContactFieldVCardMapPOSTCODE)  ||
+			(mapping==KUidContactFieldVCardMapCOUNTRY )||  // Above are dealt with in GetVCardNameL() or GetVCardAddressL()
+			(mapping == KUidContactFieldVCardMapUnknownXDash) || (mapping == KUidContactFieldVCardMapUnknown) || // unused
+			(mapping == KUidContactFieldVCardMapORG) || (mapping == KUidContactFieldVCardMapDepartment)|| // These are dealt with in GetVcardOrgInfoL() 
+			(mapping == KUidContactFieldVCardMapUnusedFN))// dealt with in GetVCardFormattedNameL
+		return; 
+
+	TBuf8<KContactMaxVCardPropertyNameLength> name;
+	TUid propertyUid=KNullUid;
+	CArrayPtr<CParserParam>* arrayOfParams=new(ELeave)CArrayPtrFlat<CParserParam>(5);
+	CleanupStack::PushL(TCleanupItem(CleanUpResetAndDestroy,arrayOfParams));
+
+	MapContactMappingToVCardPropertyNameAndTypeL(aField.ContentType(),name,propertyUid,arrayOfParams);
+	CParserPropertyValue* value=NULL;
+	TStorageType storage=aField.StorageType();
+	switch(propertyUid.iUid)
+		{
+		case KVersitPropertyCDesCArrayUid:
+		case KVCardPropertySoundUid:
+			if (storage==KStorageTypeText)
+				{
+				CDesCArrayFlat* desArray=new (ELeave)CDesCArrayFlat(4);
+				CleanupStack::PushL(desArray);
+				const TPtrC KArrayField(aField.TextStorage()->StandardTextLC());
+				switch (mapping.iUid)
+					{
+					case KIntContactFieldVCardMapORGPronunciation:
+						{
+						RemoveNewLineL(*desArray, KArrayField);
+						}
+						break;	// KIntContactFieldVCardMapORGPronunciation
+						
+					case KIntContactFieldVCardMapADR:
+						desArray->AppendL(KNullDesC);			//first sub field is empty
+						desArray->AppendL(KNullDesC);			//second sub field is empty
+						RemoveNewLineL(*desArray, KArrayField);
+						desArray->AppendL(KNullDesC);			
+						desArray->AppendL(KNullDesC);			
+						desArray->AppendL(KNullDesC);			
+						break;	// 
+						
+					default:
+						RemoveNewLineL(*desArray, KArrayField);
+						break;
+					}
+				value=new (ELeave) CParserPropertyValueCDesCArray(desArray);
+				CleanupStack::PopAndDestroy();
+				CleanupStack::Pop();	// desArray
+				}
+    			/*else if (storage==KStorageTypeStore)
+				{}	*/	// zzz does nothing    		(aField.StoreStorage()->Thing()); //value=??
+    			break;	//KVersitPropertyCDesCArrayUid
+    			
+		case KVersitPropertyDateUid:
+			if (storage==KStorageTypeDateTime)
+				{
+				//After fixing defect DEF035264, the local time is stored instead of UTC.
+				//Continue to store time as local time, as the only date field that is stored
+				//is birthday.
+				value = CreateDatePropertyL(aField.DateTimeStorage()->Time());    	
+				}
+			else if (storage==KStorageTypeText)
+				{
+				const TPtrC pText(aField.TextStorage()->StandardTextLC());
+				
+				if (aOption & CContactVCardConverter::EConnectWhitespace)
+					{
+					if (CContactVCardConverter::ContainsExportableData(pText))
+						{
+						value = CParserPropertyValueHBufC::NewL(pText);
+						}
+					}
+				else
+					{
+					value = CParserPropertyValueHBufC::NewL(pText);
+					}
+
+				CleanupStack::PopAndDestroy(); // StandardTextLC
+				}
+
+			break;	//KVersitPropertyDateUid
+		case KVCardPropertyAgentUid:
+			if ((storage == KStorageTypeContactItemId) && aAgent)
+				{
+				CParserVCard * agentcard=NULL;
+				CContactsAppToVCardConverter* converter = new(ELeave)CContactsAppToVCardConverter(iMachineUniqueId, iCharSet, GetExportVersion()); 
+				CleanupStack::PushL(converter);
+				agentcard=converter->GetContactItemAsVCardL(aAgent,NULL,aOption,aExportPrivateFields);
+				CleanupStack::PushL(agentcard);
+				value=new(ELeave) CParserPropertyValueAgent(agentcard);
+				CleanupStack::Pop();	// agentcard
+				CleanupStack::PopAndDestroy(1); 
+				}
+			break;	// KVCardPropertyAgentUid
+			
+		case KVersitPropertyHBufCUid:
+			if (storage==KStorageTypeText)
+				{
+	 			const TPtrC pText(aField.TextStorage()->StandardTextLC());
+				if (aOption & CContactVCardConverter::EConnectWhitespace)
+					{
+					if (CContactVCardConverter::ContainsExportableData(pText))
+						{
+						value = CParserPropertyValueHBufC::NewL(pText);
+						}	
+					}
+				else
+					{
+					value = CParserPropertyValueHBufC::NewL(pText);
+					}
+				CleanupStack::PopAndDestroy(); //arrayOfParams
+				}
+			else if (storage==KStorageTypeStore)
+				{
+	    			value=CParserPropertyValueBinary::NewL(*(aField.StoreStorage()->Thing()));
+				}
+		    	break; 		//KVersitPropertyHBufCUid
+		case KVersitPropertyBinaryUid:
+			if (storage==KStorageTypeStore)
+				{
+				value=CParserPropertyValueBinary::NewL(*(aField.StoreStorage()->Thing()));
+				}	
+			break;		// KVersitPropertyBinaryUid
+			
+		default:
+    			break;
+    		}
+    		
+	if (value)
+		{
+		CleanupStack::PushL(value);
+  		if ((aOption & CContactVCardConverter::EIncludeX) && aField.OverRidesLabel())
+  			{
+			TBuf8<KContactMaxVCardPropertyNameLength> param;
+			TPtrC label=aField.Label();
+			if (label.Size())
+				{
+				param=KContactVCardXDashEPOCCNTMODEL;
+				param.Append(KContactVCardFIELDLABEL);
+
+				CParserParam* paramValue = CParserParam::NewL(param, label);
+				CleanupStack::PushL(paramValue);
+				arrayOfParams->AppendL(paramValue);
+				CleanupStack::Pop(paramValue);
+				}
+			if (aField.IsHidden())
+				{
+				param=KContactVCardXDashEPOCCNTMODEL;
+				param.Append(KContactVCardFIELDHIDDEN);
+				CParserParam* paramValue = CParserParam::NewL(param, KNullDesC8);
+				CleanupStack::PushL(paramValue);
+				arrayOfParams->AppendL(paramValue);
+				CleanupStack::Pop(paramValue);
+				}
+			if (aField.IsReadOnly())
+				{
+				param=KContactVCardXDashEPOCCNTMODEL;
+				param.Append(KContactVCardFIELDREADONLY);
+				CParserParam* paramValue = CParserParam::NewL(param, KNullDesC8);
+				CleanupStack::PushL(paramValue);
+				arrayOfParams->AppendL(paramValue);
+				CleanupStack::Pop(paramValue);
+				}
+			}
+		if ((aOption & CContactVCardConverter::ETTFormat) && aDuplicateCount>0)
+			{
+			//check if multiple field case
+			// export id for multiple fields.
+			TBuf8<4> valuebuffer;
+  			valuebuffer.Num(aDuplicateCount);
+			CParserParam* paramValue = CParserParam::NewL(valuebuffer, KNullDesC8);
+			CleanupStack::PushL(paramValue);
+			arrayOfParams->AppendL(paramValue);
+			CleanupStack::Pop(paramValue);
+    		}
+		CParserGroupedProperty *property=CParserGroupedProperty::NewL(*value,name,NULL,arrayOfParams);
+		CleanupStack::Pop(2); //arrayOfParams,value
+		iVCard->AddPropertyL(property);
+		}
+	else
+		{	
+		CleanupStack::PopAndDestroy(); //arrayOfParams
+		}
+    }
+  
+  	
+/**	
+ * Map contact field's content type to VCard Property name and a Property Uid.
+ * This method should be extended if new field types are added to Contacts 
+ * model.
+ * 
+ * @param aContactType Field content type 
+ * @param aName On return this contains the vCard property name
+ * @param aPropertyUid On return this contains the vCard property UID
+ * @param aArrayOfParams On return this array contains the property parameters for the field
+ */
+void CContactsAppToVCardConverter::MapContactMappingToVCardPropertyNameAndTypeL(const CContentType& aContactType,TDes8& aName,TUid& aPropertyUid,CArrayPtr<CParserParam>* aArrayOfParams) const
+    {
+    switch (aContactType.Mapping().iUid)
+    	{
+    case KIntContactFieldVCardMapADR:
+    	aName=KVersitTokenADR;
+    	break;
+    case KIntContactFieldVCardMapAGENT:
+    	aName=KVersitTokenAGENT;
+    	break;
+    case KIntContactFieldVCardMapBDAY:
+        aName=KVersitTokenBDAY;
+    	break;	
+    case KIntContactFieldVCardMapEMAILINTERNET:
+    	aName=KVersitTokenEMAIL;
+    	break;
+    case KIntContactFieldVCardMapGEO:
+    	aName=KVersitTokenGEO;
+    	break;
+    case KIntContactFieldVCardMapLABEL:
+    	aName=KVersitTokenLABEL;
+    	break;
+    case KIntContactFieldVCardMapLOGO:
+    	aName=KVersitTokenLOGO;
+		break;
+    case KIntContactFieldVCardMapMAILER:
+    	aName=KVersitTokenMAILER;
+    	break;
+    case KIntContactFieldVCardMapNOTE:
+    	aName=KVersitTokenNOTE;			
+    	break;
+    case KIntContactFieldVCardMapPHOTO:
+    	aName=KVersitTokenPHOTO;
+    	break;
+    case KIntContactFieldVCardMapROLE:
+    	aName=KVersitTokenROLE;
+    	break;
+    case KIntContactFieldVCardMapORGPronunciation:
+    	{
+    	CParserParam* param = CParserParam::NewL(KVersitParam8CompanyPrn, KNullDesC8);
+	CleanupStack::PushL(param);
+	aArrayOfParams->AppendL(param);	
+	CleanupStack::Pop(param);	
+	} // no break here. It's intentional
+    case KIntContactFieldVCardMapSOUND:
+    	aName=KVersitTokenSOUND;
+    	break;	
+    case KIntContactFieldVCardMapTITLE:
+    	aName=KVersitTokenTITLE;
+    	break;
+    case KIntContactFieldVCardMapURL:
+    	aName=KVersitTokenURL;
+    	break;
+    case KIntContactFieldVCardMapUnusedN:
+    	aName=KVersitTokenN;
+    	break;
+    case KIntContactFieldVCardMapUnusedFN:
+    	aName=KVersitTokenFN;
+    	break;
+	case KIntContactFieldVCardMapTEL:
+		aName=KVersitTokenTEL;
+    	/*embedded objects and rich text markup could be stored using X-?*/
+		break;
+	case KIntContactFieldVCardMapKEY:
+		aName=KVersitTokenKEY;
+    	break;
+	case KIntContactFieldVCardMapSECONDNAME:
+		aName=KVersitTokenSECONDNAME;
+		break;
+   	// vCard extension properties (like X-SIPID, X-WV-ID) are not recognised
+   	// as tokens by Versit. So, we need to assign the property UID.
+    case KIntContactFieldVCardMapSIPID:
+    	{
+    	aName=KVersitTokenSIPID;
+    	aPropertyUid.iUid=KVersitPropertyHBufCUid;
+    	}
+    	break;
+    case KIntContactFieldVCardMapWV:
+    	{
+    	aName=KVersitTokenWVID;
+    	aPropertyUid.iUid=KVersitPropertyHBufCUid;
+    	}
+    	break;
+	case KIntContactFieldVCardMapAssistant:
+		{
+		aName = KVersitTokenAssistant;
+		aPropertyUid.iUid = KVersitPropertyHBufCUid;
+		}
+		break;
+	case KIntContactFieldVCardMapAssistantTel:
+		{
+		aName = KVersitTokenAssistantTel;
+		aPropertyUid.iUid = KVersitPropertyHBufCUid;
+		}
+		break;
+	case KIntContactFieldVCardMapAnniversary:
+		{
+		aName = KVersitTokenAnniversary;
+		aPropertyUid.iUid = KVersitPropertyDateUid;
+		}
+		break;
+	case KIntContactFieldVCardMapSpouse:
+		{
+		aName = KVersitTokenSpouse;
+		aPropertyUid.iUid = KVersitPropertyHBufCUid;
+		}
+		break;
+	case KIntContactFieldVCardMapChildren:
+		{
+		aName = KVersitTokenChildren;
+		aPropertyUid.iUid = KVersitPropertyCDesCArrayUid;
+		}
+		break;
+	case KIntContactFieldVCardMapClass:
+		{
+		aName = KVersitTokenClass;
+		aPropertyUid.iUid = KVersitPropertyHBufCUid;
+		}
+		break;
+    default: 
+		break;
+    	};
+
+	// Check vCard mappings for contact field
+	TInt ii;
+	const TInt count=aContactType.FieldTypeCount();
+	for (ii=0;ii<count;ii++)
+		{
+		TPtrC8 name;
+		TPtrC8 value;
+		switch (aContactType.FieldType(ii).iUid)
+			{
+		case KIntContactFieldVCardMapWORK:
+			name.Set(KVersitParam8Work);
+			break;
+		case KIntContactFieldVCardMapHOME:
+			name.Set(KVersitParam8Home);		
+			break;
+		case KIntContactFieldVCardMapMSG:
+			name.Set(KVersitParam8Msg);		
+			break;
+		case KIntContactFieldVCardMapVOICE:
+			name.Set(KVersitParam8Voice);		
+			break;
+		case KIntContactFieldVCardMapFAX:
+			name.Set(KVersitParam8Fax);		
+			break;
+		case KIntContactFieldVCardMapPREF:
+			name.Set(KVersitParam8Pref);		
+			break;
+		case KIntContactFieldVCardMapCELL:
+			name.Set(KVersitParam8Cell);		
+			break;
+		case KIntContactFieldVCardMapPAGER:
+			name.Set(KVersitParam8Pager);		
+			break;
+		case KIntContactFieldVCardMapBBS:
+			name.Set(KVersitParam8Bbs);		
+			break;
+		case KIntContactFieldVCardMapMODEM:
+			name.Set(KVersitParam8Modem);		
+			break;
+		case KIntContactFieldVCardMapCAR:
+			name.Set(KVersitParam8Car);		
+			break;
+		case KIntContactFieldVCardMapISDN:
+			name.Set(KVersitParam8Isdn);		
+			break;
+		case KIntContactFieldVCardMapVIDEO:
+			name.Set(KVersitParam8Video);		
+			break;
+		case KIntContactFieldVCardMapDOM:
+			name.Set(KVersitParam8Dom);		
+			break;
+		case KUidContactFieldEMailValue:
+		    if (DefaultInternetParameterRequired(aContactType))
+		    	{//only create a default parameter of internet if one is required
+		    	 //else the other parameters in the list will be added instead
+		    	name.Set(KVersitTokenINTERNET);
+		    	} 
+			break;
+		// need to check all the graphics types
+		case KIntContactFieldVCardMapGIF:
+			value.Set(KVersitParam8Gif);
+			name.Set(KVersitTokenTYPE);
+			break;
+		case KIntContactFieldVCardMapCGM:
+			value.Set(KVersitParam8Cgm);
+			name.Set(KVersitTokenTYPE);
+			break;
+		case KIntContactFieldVCardMapWMF:
+			value.Set(KVersitParam8Wmf);
+			name.Set(KVersitTokenTYPE);
+			break;
+		case KIntContactFieldVCardMapBMP:
+			value.Set(KVersitParam8Bmp);
+			name.Set(KVersitTokenTYPE);
+			break;
+		case KIntContactFieldVCardMapMET:
+			value.Set(KVersitParam8Met);
+			name.Set(KVersitTokenTYPE);
+			break;
+		case KIntContactFieldVCardMapPMB:
+			value.Set(KVersitParam8Pmb);
+			name.Set(KVersitTokenTYPE);
+			break;
+		case KIntContactFieldVCardMapDIB:
+			value.Set(KVersitParam8Dib);
+			name.Set(KVersitTokenTYPE);
+			break;
+		case KIntContactFieldVCardMapPICT:
+			value.Set(KVersitParam8Pict);
+			name.Set(KVersitTokenTYPE);
+			break;
+		case KIntContactFieldVCardMapTIFF:
+			value.Set(KVersitParam8Tiff);
+			name.Set(KVersitTokenTYPE);
+			break;
+		case KIntContactFieldVCardMapPDF:
+			value.Set(KVersitParam8Pdf);
+			name.Set(KVersitTokenTYPE);
+			break;
+		case KIntContactFieldVCardMapPS:
+			value.Set(KVersitParam8Ps);
+			name.Set(KVersitTokenTYPE);
+			break;
+		case KIntContactFieldVCardMapJPEG:
+			value.Set(KVersitParam8Jpeg);
+			name.Set(KVersitTokenTYPE);
+			break;
+		case KIntContactFieldVCardMapMPEG:
+			value.Set(KVersitParam8Mpeg);
+			name.Set(KVersitTokenTYPE);
+			break;
+		case KIntContactFieldVCardMapMPEG2:
+			value.Set(KVersitParam8Mpeg2);
+			name.Set(KVersitTokenTYPE);
+			break;
+		case KIntContactFieldVCardMapAVI:
+			value.Set(KVersitParam8Avi);
+			name.Set(KVersitTokenTYPE);
+			break;
+		case KIntContactFieldVCardMapQTIME:
+			value.Set(KVersitParam8Qtime);
+			name.Set(KVersitTokenTYPE);
+			break;
+		case KIntContactFieldVCardMapX509:
+			name.Set(KVersitParam8X509);
+			break;
+		case KIntContactFieldVCardMapPGP:
+			name.Set(KVersitParam8PGP);
+			break;
+		case KIntContactFieldVCardMapPOC:
+			name.Set(KVersitParamPOC);
+			break;
+		case KIntContactFieldVCardMapSWIS:
+			name.Set(KVersitParamSWIS);
+			break;
+		case KIntContactFieldVCardMapVOIP:
+			name.Set(KVersitParamVOIP);
+			break;
+		case KIntContactFieldVCardMapINTERNET:
+		    name.Set(KVersitParam8Internet);
+		    break;
+			}
+
+		if (name.Length())
+			{
+			CParserParam* parserParam;
+			//nameless parameters not allowed for vCard 3.0, so add "TYPE" parameter name 
+			if (GetExportVersion() == EPBAPVCard30 && value.Length() == 0)
+				{
+				parserParam = CParserParam::NewL(KVersitTokenTYPE, name);
+				}
+			else
+				{
+				parserParam = CParserParam::NewL(name, value);
+				}
+			CleanupStack::PushL(parserParam);
+			
+			AddParamToArrayL(aArrayOfParams, parserParam, aContactType.Mapping().iUid, aContactType.FieldType(ii).iUid);
+				
+			CleanupStack::Pop(parserParam);	
+			}
+
+   		}
+
+	// For standard vCard properties RecognizeToken is called. 
+	// aPropertyUid will already be assigned for vCard extension 
+	// properties.
+   	if (aPropertyUid==KNullUid)
+   		{
+		aPropertyUid=iVCard->RecognizeToken(aName);
+		}
+    }
+    
+/** 
+ * Utility method to create a Versit date time property
+ * 
+ * @param aDateTime Date and Time
+ * @param aRelativeTime Specifies whether the date is in local or UTC time
+ * @return Versit date property corresponding to aDateTime
+ */
+ CParserPropertyValueDateTime* CContactsAppToVCardConverter::CreateDateTimePropertyL(const TTime& aDateTime, TVersitDateTime::TRelativeTime aRelativeTime)
+	{
+	TVersitDateTime* dateTime= new(ELeave)TVersitDateTime(aDateTime.DateTime(), aRelativeTime);
+	CleanupStack::PushL(dateTime);
+	CParserPropertyValueDateTime* dateTimeValue=new(ELeave) CParserPropertyValueDateTime(dateTime);
+	CleanupStack::Pop(dateTime);	
+	return dateTimeValue;
+	}
+
+
+CParserPropertyValueDate* CContactsAppToVCardConverter::CreateDatePropertyL(const TTime& aDateTime)	
+/** 
+ * Utility method to create a Versit date property.
+ * 
+ * @param aDateTime Date (and Time) in Local Time. The only property that uses this field is BDAY, which should continue to be stored as MachineLocal time.
+ * @return Versit date property corresponding to aDateTime which does not contain a time
+ */	
+	{
+	TVersitDateTime* dateTime= new(ELeave)TVersitDateTime(aDateTime.DateTime(), TVersitDateTime::EIsMachineLocal); 
+	CleanupStack::PushL(dateTime);
+	CParserPropertyValueDate* dateValue=new(ELeave) CParserPropertyValueDate(dateTime);
+	CleanupStack::Pop(dateTime);	
+	return dateValue;
+	}
+
+
+ /** 
+  * Searches the contacts field set for a particular 'name' field (e.g. searches for the given name,
+  * family name, etc) and should the field be located, its value is appended to the specified array.
+  * If the options specify that field labels should be exported, then an extension (X-Dash) property
+  * parameter is created that corresponds to the specified label, and is added to the property
+  * parameter array.
+  *
+  * If no matching field is found, then KNullDesC is added to the specified array to preserve the
+  * vCard 2.1 ordering associated with the N 'name' property.
+  *
+  * @param aFieldSet The contact card fields
+  * @param aSearchField The field being searched for
+  * @param aPropValueArray The array to append the field's value to, should it be located.
+  * @param aPropParamArray The array to append the label property parameter to, should it be necessary
+  * @param aLabelPrefix The label value used to create the property parameter value
+  * @param aOption The options required when processing the fields
+  * @param aExportPrivateFields Whether or not private fields should be allowed to be exported
+  * @return Whether the specified field was located and added to the property value array
+  */
+TBool CContactsAppToVCardConverter::LocateSpecificNameValueL(const CContactItemFieldSet& aFieldSet, TUid aSearchField, CDesCArray& aPropValueArray, CArrayPtr<CParserParam>& aPropParamArray, const TDesC& aLabelPrefix, TInt aOption, TBool aExportPrivateFields)
+	{
+	const TBool processWhitespace = (aOption & CContactVCardConverter::EConnectWhitespace);
+	TBool foundExportableItem = EFalse;
+	//
+	TInt pos = aFieldSet.Find(aSearchField);
+	//
+	while(!foundExportableItem && pos != KErrNotFound)
+		{
+		const CContactItemField& field = aFieldSet[pos];
+		const TBool isPrivate = field.IsPrivate();
+		//
+		if	(!isPrivate || aExportPrivateFields)
+			{
+			const TPtrC pFieldContents(field.TextStorage()->StandardTextLC());
+			if (processWhitespace)
+				{
+				foundExportableItem = CContactVCardConverter::ContainsExportableData(pFieldContents);
+				}
+			else
+				{
+				foundExportableItem = (pFieldContents.Length() > 0);
+				}
+			if	(foundExportableItem)
+				{
+				RemoveNewLineL(aPropValueArray, pFieldContents);
+				//
+				const TPtrC& label = field.Label();
+				if	(label.Length() && (aOption & CContactVCardConverter::EIncludeX) && field.OverRidesLabel())
+					{
+					TBuf8<KContactMaxVCardPropertyNameLength> param(KContactVCardXDashEPOCCNTMODEL);
+					param.Append(aLabelPrefix);
+					//
+					CParserParam* parserParam = CParserParam::NewL(param, label);
+					CleanupStack::PushL(parserParam);
+					aPropParamArray.AppendL(parserParam);
+					CleanupStack::Pop(parserParam);
+					}
+				}
+			CleanupStack::PopAndDestroy(); // field contents heap descriptor
+			}
+        
+        //find next matched name fields
+        pos = aFieldSet.FindNext(aSearchField, pos + 1);			
+		}
+
+	// If we didn't find something valid to export, then we write the composite "supported
+	// but empty" marker to the array in order to preserve the correct sub-property
+	// ordering, i.e. Given Name;First Name;Additional Name;Prefix;Suffix.
+	if	(!foundExportableItem)
+		{
+		if (processWhitespace)
+			{
+			aPropValueArray.AppendL(KContactVCardCompositeSupportedButEmptyFieldValue);
+			}
+		else
+			{
+			aPropValueArray.AppendL(KNullDesC);
+			}
+		}
+	//
+	return foundExportableItem;
+	}
+
+/** 
+ * Extract Organization information like Company Name & Department Name 
+ * 
+ * @param aFields Contact item field set
+ * @param aOption Export preferences (options available defined in CContactDatabase::TOptions)
+ * @param aExportPrivateFields Specify whether private fields are included
+ */ 
+void CContactsAppToVCardConverter::GetVCardOrgInfoL(const CContactItemFieldSet& aFields,TInt aOption,TBool aExportPrivateFields)
+	{
+	CDesCArrayFlat* desArray = new (ELeave)CDesCArrayFlat(4);
+	CleanupStack::PushL(desArray);
+
+	CArrayPtr<CParserParam>* arrayOfParams = new(ELeave) CArrayPtrFlat<CParserParam>(5);
+	CleanupStack::PushL(TCleanupItem(CleanUpResetAndDestroy,arrayOfParams));
+
+	TInt foundCount = 0;
+	foundCount += LocateSpecificNameValueL(aFields, KUidContactFieldCompanyName, *desArray, *arrayOfParams, KNullDesC, aOption, aExportPrivateFields);
+	
+	foundCount += LocateSpecificNameValueL(aFields, KUidContactFieldDepartmentName, *desArray, *arrayOfParams, KNullDesC, aOption, aExportPrivateFields);
+	
+	if(foundCount == 0)
+		{
+		desArray->AppendL(KNullDesC);
+		}
+	CleanupStack::PopAndDestroy(arrayOfParams);
+	if (foundCount > 0)
+		{
+		CParserPropertyValue* value = new(ELeave) CParserPropertyValueCDesCArray(desArray);
+	  	CleanupStack::Pop(desArray);
+	  	CleanupStack::PushL(value);
+	  	CParserGroupedProperty* property = CParserGroupedProperty::NewL(*value,KVersitTokenORG, NULL, NULL);
+	  	CleanupStack::Pop(value); // value
+		iVCard->AddPropertyL(property);
+		}
+	else
+		{
+  		CleanupStack::PopAndDestroy(desArray); // desArray
+  		}
+	}
+
+/** 
+  * Removes any NewLine character found in the Contact Field content 
+  * and appends the content to the Property Array
+  * @param aPropValueArray The array to append the field's value to.
+  * @param aFieldContents Contact field content
+  */
+void CContactsAppToVCardConverter::RemoveNewLineL(CDesCArray& aPropValueArray, const TPtrC& aFieldContents)
+	{
+	TBool arrayFlag = ETrue;
+	HBufC* buf = HBufC::NewLC(256);
+	TPtr newCompanyField(buf->Des());
+	const TUint length = aFieldContents.Length();
+	for(TInt i = 0; i < length; i++)
+		{
+		if((i < length-1) && (aFieldContents[i] == 0x0D) && (aFieldContents[i+1] == 0x0A))
+			{
+			i++;
+			aPropValueArray.AppendL(newCompanyField);
+			newCompanyField.Zero();
+			arrayFlag = EFalse;
+			continue;
+			}
+		else
+			{
+			newCompanyField.Append(aFieldContents[i]);
+			arrayFlag = ETrue;
+			}
+		}
+	if(arrayFlag)
+		{
+		aPropValueArray.AppendL(newCompanyField);		
+		}
+	CleanupStack::PopAndDestroy(); // buf.
+	}
+
+
+TVCardVersion CContactsAppToVCardConverter::GetExportVersion()const
+	{
+		return iVCardVersion;
+	}
+
+/** 
+Create formatted name (FN) property. An empty value maybe exported
+@param aFields Contact item fields to be exported
+*/ 
+void CContactsAppToVCardConverter::GetVCardFormattedNameL(CContactItemFieldSet& aFields, TInt aOption, TBool aExportPrivateFields)
+	{
+	TBool pos = KErrNotFound;
+	const TInt count = aFields.Count();
+	for (TInt ii = 0; ii < count; ++ii)
+		{
+		const CContactItemField& field = aFields[ii];
+		if (field.ContentType().Mapping() == KUidContactFieldVCardMapUnusedFN &&
+			field.TextStorage() && field.Storage()->IsFull() &&
+			(!field.IsPrivate() || aExportPrivateFields))
+			{
+			//found a valid formatted name, stop searching
+			pos = ii;
+			break;
+			}
+		}
+	
+	CParserPropertyValue* value = NULL;
+	if (pos != KErrNotFound)
+		{
+		const CContactItemField& field = aFields[pos];
+	 	const TPtrC pText(field.TextStorage()->StandardTextLC());
+	 	if (aOption & CContactVCardConverter::EConnectWhitespace)
+			{
+			if (CContactVCardConverter::ContainsExportableData(pText))
+				{
+				value = CParserPropertyValueHBufC::NewL(pText);
+				}	
+			}
+			else
+			{
+				value = CParserPropertyValueHBufC::NewL(pText);
+			}
+
+		CleanupStack::PopAndDestroy(); //field text
+		}
+	else
+		{
+		//FN is mandatory for vCard 3.0 so send empty value, otherwise do nothing
+		if (GetExportVersion() != EPBAPVCard30)
+			{
+			return;
+			}
+		value = CParserPropertyValueHBufC::NewL(KNullDesC);
+		}
+	CleanupStack::PushL(value);
+	CParserGroupedProperty* property = CParserGroupedProperty::NewL(*value, KVersitTokenFN, NULL, NULL);
+	CleanupStack::Pop(value);
+	//ownership passed
+	iVCard->AddPropertyL(property);
+	}
+
+void CContactsAppToVCardConverter::SetFilter(TInt64 aFilter)
+	{
+	iFilter = aFilter;
+	}
+
+/**
+Convert contacts model vCard mapping uids to PBAP filter attributes
+@param TUid aMapping Mapping for a contact field.
+*/	
+TPBAPProperties CContactsAppToVCardConverter::AttributeFromMapping(TUid aMapping) const
+	{
+	TPBAPProperties attribute = (TPBAPProperties)0;
+    switch (aMapping.iUid)
+    	{
+		case KIntContactFieldVCardMapADR:
+			attribute = EPropertyADR;
+			break;
+		case KIntContactFieldVCardMapAGENT:
+			attribute = EPropertyAGENT;
+			break;
+		case KIntContactFieldVCardMapBDAY:
+			attribute = EPropertyBDAY;
+			break;	
+		case KIntContactFieldVCardMapEMAILINTERNET:
+			attribute = EPropertyEMAIL;
+			break;
+		case KIntContactFieldVCardMapGEO:
+			attribute = EPropertyGEO;
+			break;
+		case KIntContactFieldVCardMapLABEL:
+			attribute = EPropertyLABEL;
+			break;
+		case KIntContactFieldVCardMapLOGO:
+			attribute = EPropertyLOGO;
+			break;
+		case KIntContactFieldVCardMapMAILER:
+			attribute = EPropertyMAILER;
+			break;
+		case KIntContactFieldVCardMapNOTE:
+			attribute = EPropertyNOTE;			
+			break;
+		case KIntContactFieldVCardMapPHOTO:
+			attribute = EPropertyPHOTO;
+			break;
+		case KIntContactFieldVCardMapROLE:
+			attribute = EPropertyROLE;
+			break;
+		case KIntContactFieldVCardMapORGPronunciation:
+		case KIntContactFieldVCardMapSOUND:
+			attribute = EPropertySOUND;
+			break;
+		case KIntContactFieldVCardMapTITLE:
+			attribute = EPropertyTITLE;
+			break;
+		case KIntContactFieldVCardMapURL:
+			attribute = EPropertyURL;
+			break;
+		case KIntContactFieldVCardMapUnusedN:
+			attribute = EPropertyN;
+			break;
+		case KIntContactFieldVCardMapUnusedFN:
+			attribute = EPropertyFN;
+			break;
+		case KIntContactFieldVCardMapTEL:
+			attribute = EPropertyTEL;
+			break;
+		case KIntContactFieldVCardMapKEY:
+			attribute = EPropertyKEY;
+			break;
+		case KIntContactFieldVCardMapClass:
+			attribute = EPropertyCLASS;
+			break;		
+		default:
+			break;
+    	};
+    return attribute;	
+	}
+	
+TBool CContactsAppToVCardConverter::NeedsToBeExported(TPBAPProperties aProp) const
+	{
+	return iFilter & aProp;
+	}
+
+TBool CContactsAppToVCardConverter::IsPBAPExport() const
+	{
+	return (iVCardVersion == EPBAPVCard21 || iVCardVersion == EPBAPVCard30);
+	}
+
+TBool CContactsAppToVCardConverter::DefaultInternetParameterRequired(const CContentType& aContactType) const
+	{
+	if (aContactType.ContainsFieldType(KUidContactFieldVCardMapINTERNET) || aContactType.ContainsFieldType(KUidContactFieldVCardMapCELL)
+		|| 	aContactType.ContainsFieldType(KUidContactFieldVCardMapHOME) || aContactType.ContainsFieldType(KUidContactFieldVCardMapWORK))
+		{
+		return EFalse; // don't need to do anything as a type fieldtype is present and that parameter will be added.
+		}
+	return ETrue; // we need to add a default internet parameter
+	}
+
+/**
+The PREF parameter is inserted as the first one in the array of params to ensure it appears first in the VCard.
+The ordering of the parameters is usually preserved, however for TEL there is a specific sequencing.
+The vObject minimum interoperability profile from the OMA specifies the following parameter sequence for the TEL property
+TEL;["PREF;"]["WORK;"/"HOME;"]"VOICE;"/"FAX;"/"MSG;"/"CELL;"/"PAGER;"/"BBS;"/"MODEM;"/"CAR;"/"ISDN;"/"VIDEO;"
+@param aArrayOfParams An array of CParserParam
+@param aParserParam const CParserParam*
+@param aMappingUid mapping uid used to check if it is the TEL property
+@param aFieldTypeUid fieldtype uid used to check for PREF, HOME and WORK field types
+*/
+void CContactsAppToVCardConverter::AddParamToArrayL(CArrayPtr<CParserParam>* aArrayOfParams, CParserParam* aParserParam, TInt32 aMappingUid, TInt32 aFieldTypeUid) const
+	{
+	// PREF parameter should be the first parameter in the list, so insert in first position.
+	if (aFieldTypeUid == KIntContactFieldVCardMapPREF)
+		{
+	 	aArrayOfParams->InsertL(0, aParserParam);
+	 	return;
+		}
+	// Sequencing only applies for the TEL property for its HOME and WORK parameters
+    // otherwise just preserve ordering.
+	if (aMappingUid != KIntContactFieldVCardMapTEL)
+		{
+		aArrayOfParams->AppendL(aParserParam);
+		}
+	else
+		{
+		//This is a TEL property so need to do some sequencing 
+		if (aFieldTypeUid == KIntContactFieldVCardMapHOME || aFieldTypeUid == KIntContactFieldVCardMapWORK)
+			{
+			//contains HOME or WORK  so must insert either in first or second place
+			if (aArrayOfParams->Count())
+				{
+				CParserParam* parserParam = aArrayOfParams->At(0);
+				if (parserParam->Name().CompareF(KVersitParam8Pref)==0)
+					{
+					aArrayOfParams->InsertL(1, aParserParam);
+					}
+				else if (parserParam->Name().CompareF(KVersitTokenTYPE)==0)//vCard version 3.0 
+					{
+					if (parserParam->Value().CompareF(KVersitParam8Pref)==0)
+						{
+						aArrayOfParams->InsertL(1, aParserParam);
+						}
+					}
+				else
+					{
+					aArrayOfParams->InsertL(0, aParserParam);
+					}
+				}
+			else
+				{//No params present so can just append.
+				aArrayOfParams->AppendL(aParserParam);
+				}
+			}
+		else
+			{// Does not contain HOME or WORK so just append to preserve order of parameters.
+			aArrayOfParams->AppendL(aParserParam);
+			}
+		}
+	}