diff -r 000000000000 -r e686773b3f54 phonebookengines/contactsmodel/cntvcard/cntvcardexport.cpp --- /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 +#include +#include +#include +#include "cntvcardutils.h" +#include +#include +#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* 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* 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 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& 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 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* arrayOfParams = new(ELeave) CArrayPtrFlat(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* arrayOfParams = new(ELeave) CArrayPtrFlat(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* arrayOfParams = new(ELeave) CArrayPtrFlat(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 name; + TUid propertyUid=KNullUid; + CArrayPtr* arrayOfParams=new(ELeave)CArrayPtrFlat(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 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* 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;iiRecognizeToken(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& 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 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* arrayOfParams = new(ELeave) CArrayPtrFlat(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* 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); + } + } + }