pimappsupport/vcardandvcal/src/VCARD.CPP
changeset 0 f979ecb2b13e
equal deleted inserted replaced
-1:000000000000 0:f979ecb2b13e
       
     1 // Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15  
       
    16 #include <vcard.h>
       
    17 
       
    18 #include <s32mem.h>
       
    19 
       
    20 #include <vutil.h>
       
    21 #include <vstaticutils.h>
       
    22 #include "verror.h"
       
    23 #include <vobserv.h>
       
    24 #include "vpbapplugin.h"
       
    25 #ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
       
    26 #include "vcard3.h"
       
    27 #endif
       
    28 
       
    29 _LIT(KVersitTokenVCard3VersionNo, "3.0");
       
    30 
       
    31 
       
    32 
       
    33 _LIT8(KVCard3LineBreakAndWSP,	"\r\n ");
       
    34 _LIT8(KVCard3TokenB, "b");
       
    35 
       
    36 const TUint KTokenNewLineVal = 'n';
       
    37 const TUint KTokenCarriageReturnVal = '\r';
       
    38 const TUint KTokenLineFeedVal = '\n';
       
    39 
       
    40 const TInt KMaxVCard3LineLength = 75; //line length recommended in RFC2426
       
    41 
       
    42 //
       
    43 // CParserVCard
       
    44 //
       
    45 EXPORT_C CParserVCard* CParserVCard::NewL()
       
    46 /** Allocates and constructs a vCard parser.
       
    47 
       
    48 @return A pointer to the newly constructed vCard parser. */
       
    49 	{
       
    50 	CParserVCard* self=new(ELeave) CParserVCard();
       
    51 	CleanupStack::PushL(self);
       
    52 	self->ConstructL();
       
    53 	CleanupStack::Pop(self);
       
    54 	return self;	
       
    55 	}
       
    56 
       
    57 CParserVCard* CParserVCard::NewL(TBool aParsingAgent)
       
    58 /* Allocates and constructs a vCard parser.
       
    59    This is used internally to limit the number of recursive AGENT vcards that
       
    60    may be found within an AGENT property */
       
    61 	{
       
    62 	CParserVCard* self=new(ELeave) CParserVCard(aParsingAgent);
       
    63 	CleanupStack::PushL(self);
       
    64 	self->ConstructL();
       
    65 	CleanupStack::Pop(self);
       
    66 	return self;	
       
    67 	}
       
    68 
       
    69 CParserVCard::CParserVCard()
       
    70 	: CVersitParser(ESupportsVersion), iParsingAgent(EFalse)
       
    71 	{
       
    72 	iDefaultVersion = KVersitTokenVCardVersionNo;
       
    73 	}
       
    74 
       
    75 CParserVCard::CParserVCard(TBool aParsingAgent)
       
    76 	: CVersitParser(ESupportsVersion), iParsingAgent(aParsingAgent)
       
    77 	{
       
    78 	iDefaultVersion = KVersitTokenVCardVersionNo;
       
    79 	}
       
    80 
       
    81 EXPORT_C CArrayPtr<CParserProperty>* CParserVCard::GroupOfPropertiesL(const TDesC8& aGroupName) const
       
    82 /** Gets an array of all properties in the named property group from the vCard entity.
       
    83 
       
    84 A property group is a collection of related properties, identified by a group name.
       
    85 
       
    86 Ownership of the properties is not transferred.
       
    87 
       
    88 @param aGroupName The name of the property group of interest.
       
    89 @return An array of all properties in the specified group. NULL if the named property 
       
    90 group was not found. */
       
    91 	{
       
    92 	if	(!iArrayOfProperties)
       
    93 		return NULL;
       
    94 
       
    95 	TInt properties=iArrayOfProperties->Count();
       
    96 	CArrayPtr<CParserProperty>* arrayOfGroupedProperties=new(ELeave) CArrayPtrFlat<CParserProperty>(5);
       
    97 	CleanupStack::PushL(arrayOfGroupedProperties);
       
    98 	TUid uid;
       
    99 	CParserGroupedProperty* groupedProperty;
       
   100 	for (TInt ii=0; ii<properties; ii++)
       
   101 		{
       
   102 		uid.iUid=KVersitGroupedPropertyUid;
       
   103 		if ((*iArrayOfProperties)[ii]->SupportsInterface(uid))
       
   104 			{
       
   105 			groupedProperty=STATIC_CAST(CParserGroupedProperty*,(*iArrayOfProperties)[ii]);
       
   106 			if(groupedProperty->Group(aGroupName))
       
   107 				arrayOfGroupedProperties->AppendL((*iArrayOfProperties)[ii]);
       
   108 			}
       
   109 		}
       
   110 	CleanupStack::Pop(arrayOfGroupedProperties);
       
   111 	if (arrayOfGroupedProperties->Count())
       
   112 		return arrayOfGroupedProperties;
       
   113 	delete arrayOfGroupedProperties;
       
   114 	return NULL;
       
   115 	}
       
   116 
       
   117 EXPORT_C void CParserVCard::InternalizeL(RReadStream& aStream)
       
   118 /** Internalises a vCard entity from a read stream. 
       
   119 
       
   120 The presence of this function means that the standard templated operator>>() 
       
   121 (defined in s32strm.h) is available to internalise objects of this class.
       
   122 
       
   123 @param aStream Stream from which the vCard entity should be internalised. 
       
   124 @see CVersitParser::InternalizeL() */
       
   125 	{
       
   126 	// Generic Internalize that loads properties\values with no extra processing
       
   127 	CVersitParser::InternalizeL(aStream);
       
   128 	}
       
   129 
       
   130 EXPORT_C void CParserVCard::ConvertDateTimesToMachineLocalAndDeleteTZL()
       
   131 /** Converts all date/time property values contained in the vCard entity into machine 
       
   132 local values (including all date/time values contained in agent properties).
       
   133 
       
   134 This conversion is needed because of differences in universal and local times 
       
   135 due to time zones.
       
   136 
       
   137 Finds the necessary increment to compensate for the time zone, using the value 
       
   138 given by the first time zone property (named KVersitTokenTZ) in the array 
       
   139 of properties. This increment is passed as a parameter to ConvertAllPropertyDateTimesToMachineLocalL(). 
       
   140 The CVersitDaylight* parameter passed to ConvertAllPropertyDateTimesToMachineLocalL() 
       
   141 is NULL, so no compensation can be made by this function for any daylight 
       
   142 saving (seasonal time shift). 
       
   143 @deprecated since 9.1
       
   144 */
       
   145 	{
       
   146 	CArrayPtr<CParserProperty>* arrayOfTimeZones = PropertyL(KVersitTokenTZ, TUid::Uid(KVersitPropertyTimeZoneUid),ETrue);
       
   147 	if	(!arrayOfTimeZones)
       
   148 		{
       
   149 		if (iFlags&EImportSyncML)
       
   150 			AdjustAllPropertyDateTimesToMachineLocalL();
       
   151 		return;
       
   152 		}
       
   153 
       
   154 	CleanupStack::PushL(TCleanupItem(ResetAndDestroyArrayOfProperties, arrayOfTimeZones));
       
   155 	CParserPropertyValueTimeZone* timeZone = STATIC_CAST(CParserPropertyValueTimeZone*, (*arrayOfTimeZones)[0]->Value());
       
   156 	TTimeIntervalSeconds increment = timeZone->Value().Int();
       
   157 	ConvertAllPropertyDateTimesToMachineLocalL(increment,NULL);
       
   158 	CleanupStack::PopAndDestroy(arrayOfTimeZones);
       
   159 	}
       
   160 
       
   161 EXPORT_C void CParserVCard::ExternalizeL(RWriteStream& aStream)
       
   162 /** Externalises a vCard entity (and all sub-entities) to a write stream.
       
   163 
       
   164 Sets the entity name to KVersitVarTokenVCARD if it hasn't already been set.
       
   165 
       
   166 Adds a version property to the start of the current entity's array of properties 
       
   167 if the entity supports this. (If there isn't an array of properties then one 
       
   168 is made).
       
   169 
       
   170 The presence of this function means that the standard templated operator<<() 
       
   171 (defined in s32strm.h) is available to externalise objects of this class.
       
   172 
       
   173 @param aStream Stream to which the vCard entity should be externalised. 
       
   174 @see CVersitParser::ExternalizeL() */
       
   175 	{
       
   176 	if	(!iEntityName)
       
   177 		SetEntityNameL(KVersitVarTokenVCARD);
       
   178 	CVersitParser::ExternalizeL(aStream);
       
   179 	}
       
   180 
       
   181 EXPORT_C void CParserVCard::ConvertAllPropertyDateTimesToMachineLocalL(const TTimeIntervalSeconds& aIncrement,const CVersitDaylight* aDaylight)
       
   182 /** Converts all date/time property values contained in the vCard entity into machine 
       
   183 local values (including all date/time values contained in agent properties).
       
   184 
       
   185 This conversion is needed because of differences in universal and local times 
       
   186 due to time zones and daylight savings (seasonal time shifts).
       
   187 
       
   188 If there is a daylight savings rule associated with the date/time (held in 
       
   189 the aDaylight parameter) then this will be used to compensate for differences 
       
   190 between universal and local times due to both time zones and the daylight 
       
   191 savings rule. Otherwise, the aIncrement parameter is used to compensate for 
       
   192 any difference due to time zones alone.
       
   193 
       
   194 @param aIncrement A time interval in seconds which represents the negative 
       
   195 of the time zone of the originating machine. For instance, if the time zone 
       
   196 is +04:30, aIncrement should be set to -04:30.
       
   197 @param aDaylight Pointer to the specification for daylight saving. If the date/time 
       
   198 value is within the period for daylight saving, the value is modified by the 
       
   199 daylight saving offset (which accounts for both the time zone and daylight 
       
   200 saving rule). 
       
   201 @deprecated since 9.1
       
   202 */
       
   203 	{
       
   204 	CVersitParser::ConvertAllPropertyDateTimesToMachineLocalL(aIncrement,aDaylight);
       
   205 	CArrayPtr<CParserProperty>* properties = PropertyL(KVersitTokenAGENT, TUid::Uid(KVCardPropertyAgentUid), EFalse);
       
   206 	if	(!properties)
       
   207 		return;
       
   208 	CleanupStack::PushL(properties);
       
   209 	TInt count = properties->Count();
       
   210 	CParserPropertyValueAgent* agent;
       
   211 	for (TInt ii = 0; ii < count; ii++)
       
   212 		{
       
   213 		agent = STATIC_CAST(CParserPropertyValueAgent*, (*properties)[ii]->Value());
       
   214 		if (agent && agent->Value())
       
   215 			agent->Value()->ConvertAllPropertyDateTimesToMachineLocalL(aIncrement, aDaylight);
       
   216 		}
       
   217 	CleanupStack::PopAndDestroy(properties);
       
   218 	}
       
   219 
       
   220 EXPORT_C CParserPropertyValue* CParserVCard::MakePropertyValueAgentL(TPtr16 aValue)
       
   221 	{
       
   222 	if(!iParsingAgent)
       
   223 		{
       
   224 		HBufC* entityName = NULL;
       
   225 		TInt start=aValue.Find(KVersitVarTokenBEGIN);
       
   226 		if (start>KErrNotFound)
       
   227 			{		//BEGIN is on the same line as AGENT
       
   228 			start+=KVersitVarTokenBEGIN.iTypeLength;
       
   229 			TInt length=aValue.Length()-start;
       
   230 			aValue.Set(&aValue[start],length,length);
       
   231 			start=aValue.Find(KVersitTokenColonUnicode);
       
   232 			if (start==KErrNotFound)
       
   233 				User::Leave(KErrNotFound);
       
   234 			start+=KVersitTokenColonUnicode.iTypeLength;
       
   235 			length=aValue.Length()-start;
       
   236 			if (length==0)
       
   237 				User::Leave(KErrNotFound);
       
   238 			aValue.Set(&aValue[start],length,length);
       
   239 			VersitUtils::StripWhiteSpace(aValue);
       
   240 			entityName=aValue.AllocLC();
       
   241 			}
       
   242 		else
       
   243 			{
       
   244 			TBool moreCharsOnLine = VersitUtils::IsNoneWhiteSpaceWideChar(aValue);
       
   245 			if( EFalse == moreCharsOnLine )
       
   246 				{		// ... rest of line is empty, so BEGIN is on a following line
       
   247 				CParserProperty* agentProperty=iCurrentProperty;
       
   248 				iCurrentProperty=NULL;
       
   249 				CleanupStack::PushL(agentProperty);
       
   250 				ParsePropertyL();
       
   251 				if (iCurrentProperty->NameUid().iUid!=KVersitTokenBeginUid)
       
   252 					User::Leave(KVersitErrNestedVcardExpected);
       
   253 				entityName=STATIC_CAST(CParserPropertyValueHBufC*,iCurrentProperty->Value())->TakeValueOwnership();
       
   254 				delete iCurrentProperty;
       
   255 				CleanupStack::Pop(agentProperty);
       
   256 				iCurrentProperty=agentProperty;
       
   257 				CleanupStack::PushL(entityName);
       
   258 				}
       
   259 			else
       
   260 				{	// ... rest of line contains non-standard data, ignore it.
       
   261 			User::Leave(KVersitErrNestedVcardExpected);
       
   262 				}
       
   263 			}
       
   264 	
       
   265 		//	create a parser setting iAgentParsing member variable to true
       
   266 		CParserVCard* parser=CParserVCard::NewL(ETrue);
       
   267 		CleanupStack::PushL(parser);
       
   268 		if (iObserver)
       
   269 			{
       
   270 			iObserver->NewParser(parser);
       
   271 			}
       
   272 		
       
   273 		parser->SetAutoDetect(iFlags&EUseAutoDetection,iAutoDetectCharSets);
       
   274 			
       
   275 		parser->CVersitParser::InternalizeL(entityName, iLineReader);
       
   276 		CleanupStack::Pop(2, entityName);
       
   277 		CleanupStack::PushL(parser);
       
   278 	
       
   279 		CParserPropertyValue* propertyValue=new(ELeave)CParserPropertyValueAgent(parser);
       
   280 		CleanupStack::Pop(parser);
       
   281 		return propertyValue;
       
   282 		}
       
   283 
       
   284 	// we leave if iParsingAgent is ETrue because we do not support nested agent properties
       
   285 	delete iCurrentProperty;
       
   286 	iCurrentProperty=NULL;
       
   287 	User::Leave(KErrNotSupported);
       
   288 	return NULL; // satisfy compiler
       
   289 	}
       
   290 		
       
   291 
       
   292 
       
   293 EXPORT_C CDesC8Array* CParserVCard::GetGroupNamesL(TPtr8& aGroupsAndName)
       
   294 	{
       
   295 	CDesC8Array* arrayOfGroups=NULL;
       
   296 	TInt periodPos;
       
   297 	TInt len;
       
   298 	FOREVER
       
   299 		{
       
   300 		periodPos=aGroupsAndName.Find(KVersitTokenPeriod);
       
   301 		if (periodPos==KErrNotFound)
       
   302 			break;
       
   303 		if (!arrayOfGroups)
       
   304 			{
       
   305 			arrayOfGroups=new(ELeave) CDesC8ArrayFlat(5);
       
   306 			CleanupStack::PushL(arrayOfGroups);
       
   307 			}
       
   308 		arrayOfGroups->AppendL(TPtrC8(&aGroupsAndName[0],periodPos));
       
   309 		len=aGroupsAndName.Length()-(++periodPos);
       
   310 		
       
   311 		// INC113960:vCard crash when parsing random data
       
   312 		//data cause crash:"ariat@etsi.fr=0D=0ATel.:"
       
   313 		//In the case there is no data after the KVersitTokenPeriod, don't set aGroupsAndName.
       
   314 		if (len ==0)
       
   315 			{
       
   316 			break;
       
   317 			}
       
   318 		
       
   319 		aGroupsAndName.Set(&aGroupsAndName[periodPos],len,len);
       
   320 		}
       
   321 	if (arrayOfGroups)
       
   322 		CleanupStack::Pop(arrayOfGroups);
       
   323 	return arrayOfGroups;
       
   324 	}
       
   325 
       
   326 EXPORT_C void CParserVCard::ParsePropertyL()
       
   327 	{
       
   328 	TInt valueStart;
       
   329 	TInt lenNameGroup;
       
   330 	CArrayPtr<CParserParam>* arrayOfParams=ReadLineAndDecodeParamsLC(valueStart,lenNameGroup);
       
   331 	TPtr8 propName(&BufPtr()[0],lenNameGroup,lenNameGroup);
       
   332 	CDesC8Array* arrayOfGroups=GetGroupNamesL(propName);
       
   333 	if (arrayOfGroups)
       
   334 		CleanupStack::PushL(arrayOfGroups);
       
   335 	iCurrentProperty=new(ELeave) CParserGroupedProperty(arrayOfGroups,arrayOfParams);
       
   336 	if (arrayOfGroups)
       
   337 		CleanupStack::Pop(arrayOfGroups);
       
   338 	CleanupStack::Pop(arrayOfParams);
       
   339 	// Change according to defect DEF022049. If a vCard property does not have a name,
       
   340 	// it should not create a property for this field.
       
   341 	if (propName.Length()>0)
       
   342 		{
       
   343 		MakePropertyL(propName,valueStart);
       
   344 		}
       
   345 	else
       
   346 		{
       
   347 		User::Leave(KVersitErrNoPropertyName);
       
   348 		}
       
   349 	}
       
   350 
       
   351 EXPORT_C CParserPropertyValue* CParserVCard::MakePropertyValueL(const TUid& aPropertyUid, HBufC16*& aValue)
       
   352 /** Creates a property value, by parsing the specified descriptor.
       
   353 
       
   354 This function overrides CVersitParser::MakePropertyValueL() to ensure that agent and 
       
   355 sound properties are correctly recognised and constructed.
       
   356 
       
   357 Note that aValue may be set to NULL on return from this method.
       
   358 
       
   359 @param aPropertyUid The UID type associated with the raw property string.
       
   360 @param aValue The raw property value descriptor. The function removes anything that 
       
   361 is not part of the property.
       
   362 @return A property value. */
       
   363 	{
       
   364 	if(!aValue && (aPropertyUid.iUid != KVersitPropertyBinaryUid || !iLargeDataBuf))
       
   365 		{
       
   366 		return NULL;
       
   367 		}
       
   368 		
       
   369 	switch (aPropertyUid.iUid)
       
   370 		{
       
   371 		case KVCardPropertyAgentUid:
       
   372             {
       
   373 			return MakePropertyValueAgentL(aValue->Des());
       
   374             }
       
   375 		case KVCardPropertySoundUid:
       
   376             {
       
   377 			return MakePropertyValueSoundL(aValue);
       
   378             }
       
   379 		default:
       
   380             {
       
   381 			return CVersitParser::MakePropertyValueL(aPropertyUid,aValue);
       
   382             }
       
   383 		};
       
   384 	}
       
   385 
       
   386 EXPORT_C CParserPropertyValue* CParserVCard::MakePropertyValueSoundL(HBufC16*& aValue)
       
   387 /** Creates a property value object from a SOUND property value. 
       
   388 
       
   389 SOUND property values can either contain a single string (using HBufC storage) 
       
   390 or, following the addition of Japanese pronunciation support to Symbian's 
       
   391 Versit API, an array (using CDesCArray storage). This method allocates 
       
   392 the additional storage needed to support array-based sound properties, when 
       
   393 necessary.
       
   394 
       
   395 Note that aValue will be set to NULL on return from this method.
       
   396 
       
   397 @param aValue The raw property value descriptor.
       
   398 @return A constructed sound property value. */
       
   399     {
       
   400     // Allocate additional storage if necessary
       
   401  	if(!aValue)
       
   402 		return NULL;
       
   403  	        
       
   404 	HBufC16 *buf  = HBufC16::NewLC(aValue->Length());
       
   405 	*buf = *aValue;//copy avalue into buf
       
   406 	
       
   407     TPtr16 pValue(buf->Des());
       
   408     //pass copy of avalue into AllocateAdditionalPropertyStorageL so that RemoveEscapeChars isnt applied twice to the string
       
   409     VersitUtils::AllocateAdditionalPropertyStorageL(*iStaticUtils, *iCurrentProperty, pValue, LineCharSetId());
       
   410 
       
   411     // Now we remove any escaping
       
   412 	VersitUtils::RemoveEscapeChars(*aValue, LineCharSetId());
       
   413 	
       
   414 	CleanupStack::PopAndDestroy( buf );
       
   415     
       
   416     // ... and create a property value
       
   417     CParserPropertyValueHBufC* returnedValue = new(ELeave) CParserPropertyValueHBufC(aValue);
       
   418 	aValue = NULL;
       
   419 	return returnedValue;
       
   420     }
       
   421 
       
   422 EXPORT_C TUid CParserVCard::RecognizeToken(const TDesC8& aToken) const
       
   423 // From CVersitParser - extra recognition capablities are added by overriding this
       
   424 // virtual function. These properties are specific to vCards
       
   425 /** Returns a UID that identifies a specified token's type.
       
   426 
       
   427 For example, if aToken contains the property name BDAY, the function returns 
       
   428 KVersitPropertyDateUid. If the token is not recognized as vCard-specific, the 
       
   429 function calls CVersitParser::RecognizeToken(), which recognizes generic Versit 
       
   430 tokens.
       
   431 
       
   432 @param aToken The token to be recognized.
       
   433 @return A defined UID value if the token is recognized and KVersitTokenUnknownUid 
       
   434 if not. */
       
   435 	{
       
   436 	TUid uid = KNullUid;
       
   437 	TChar firstChar(aToken.Ptr()[0]);
       
   438 	firstChar=firstChar.GetUpperCase();
       
   439 	switch (firstChar)
       
   440 		{
       
   441 	case 'A':
       
   442 		if (!aToken.CompareF(KVersitTokenADR))
       
   443 			uid.iUid=KVersitPropertyCDesCArrayUid;
       
   444 		else if (!aToken.CompareF(KVersitTokenAGENT))
       
   445 			uid.iUid=KVCardPropertyAgentUid;
       
   446 		break;
       
   447 	case 'B':
       
   448 		if (!aToken.CompareF(KVersitTokenBDAY))
       
   449 			uid.iUid=KVersitPropertyDateUid;
       
   450 		break;
       
   451 	case 'E':
       
   452 		if (!aToken.CompareF(KVersitTokenEMAIL))
       
   453 			uid.iUid=KVersitPropertyHBufCUid;
       
   454 		break;
       
   455 	case 'F':
       
   456 		if (!aToken.CompareF(KVersitTokenFN))
       
   457 			uid.iUid=KVersitPropertyHBufCUid;
       
   458 		break;
       
   459 	case 'G':
       
   460 		if (!aToken.CompareF(KVersitTokenGEO))
       
   461 			uid.iUid=KVersitPropertyHBufCUid;
       
   462 		break;
       
   463 	case 'K':
       
   464 		if (!aToken.CompareF(KVersitTokenKEY))
       
   465 			{
       
   466 			Versit::TVersitEncoding encodingValue = LineEncoding();
       
   467 			if(encodingValue == Versit::EBase64Encoding)
       
   468 				{
       
   469 				uid.iUid = KVersitPropertyBinaryUid;
       
   470 				}
       
   471 			else
       
   472 				{
       
   473  				uid.iUid=KVersitPropertyHBufCUid;
       
   474 				}
       
   475 			}
       
   476  		break;
       
   477 	case 'L':
       
   478 		if (!aToken.CompareF(KVersitTokenLABEL))
       
   479 			uid.iUid=KVersitPropertyHBufCUid;
       
   480 		else if (!aToken.CompareF(KVersitTokenLOGO))
       
   481 			uid.iUid=KVersitPropertyBinaryUid;
       
   482 		break;
       
   483 	case 'M':
       
   484 		if (!aToken.CompareF(KVersitTokenMAILER))
       
   485 			uid.iUid=KVersitPropertyHBufCUid;
       
   486 		break;
       
   487 	case 'N':
       
   488 		if (!aToken.CompareF(KVersitTokenN))
       
   489 			uid.iUid=KVersitPropertyCDesCArrayUid;
       
   490 		else if (!aToken.CompareF(KVersitTokenNOTE))
       
   491 			uid.iUid=KVersitPropertyHBufCUid;
       
   492 		break;
       
   493 	case 'O':
       
   494 		if (!aToken.CompareF(KVersitTokenORG))
       
   495 			uid.iUid=KVersitPropertyCDesCArrayUid;
       
   496 		break;
       
   497 	case 'P':
       
   498 		if (!aToken.CompareF(KVersitTokenPHOTO))
       
   499 			uid.iUid=KVersitPropertyBinaryUid;
       
   500 		break;
       
   501 	case 'R':
       
   502 		if (!aToken.CompareF(KVersitTokenREV))
       
   503 			uid.iUid=KVersitPropertyDateTimeUid;
       
   504 		else if (!aToken.CompareF(KVersitTokenROLE))
       
   505 			uid.iUid=KVersitPropertyHBufCUid;
       
   506 		break;
       
   507 	case 'S':
       
   508 		if (!aToken.CompareF(KVersitTokenSOUND))
       
   509 			uid.iUid=KVCardPropertySoundUid;
       
   510 		break;
       
   511 	case 'T':
       
   512 		if (!aToken.CompareF(KVersitTokenTZ))
       
   513 			uid.iUid=KVersitPropertyTimeZoneUid;
       
   514 		else if ((!aToken.CompareF(KVersitTokenTEL))
       
   515 			||(!aToken.CompareF(KVersitTokenTITLE)))
       
   516 			uid.iUid=KVersitPropertyHBufCUid;
       
   517 		break;
       
   518 	case 'U':
       
   519 		if ((!aToken.CompareF(KVersitTokenURL))
       
   520 			||(!aToken.CompareF(KVersitTokenUID)))
       
   521 			uid.iUid=KVersitPropertyHBufCUid;
       
   522 		break;
       
   523 	case 'V':
       
   524 		if (!aToken.CompareF(KVersitTokenVERSION))
       
   525 			uid.iUid=KVersitTokenVersionUid;
       
   526 		break;
       
   527 	case 'X':
       
   528 		if (!aToken.CompareF(KVersitTokenSECONDNAME))
       
   529 			{
       
   530 			uid.iUid=KVersitPropertyHBufCUid;
       
   531 			}
       
   532 		else if (!aToken.CompareF(KVersitTokenAssistant))
       
   533 			{
       
   534 			uid.iUid=KVersitPropertyHBufCUid;
       
   535 			}
       
   536 		else if (!aToken.CompareF(KVersitTokenAssistantTel))
       
   537 			{
       
   538 			uid.iUid=KVersitPropertyHBufCUid;
       
   539 			}
       
   540 		else if (!aToken.CompareF(KVersitTokenAnniversary))
       
   541 			{
       
   542 			uid.iUid=KVersitPropertyDateUid;
       
   543 			}
       
   544 		else if (!aToken.CompareF(KVersitTokenSpouse))
       
   545 			{
       
   546 			uid.iUid=KVersitPropertyHBufCUid;
       
   547 			}
       
   548 		else if (!aToken.CompareF(KVersitTokenChildren))
       
   549 			{
       
   550 			uid.iUid=KVersitPropertyCDesCArrayUid;
       
   551 			}
       
   552 		else if (!aToken.CompareF(KVersitTokenClass))
       
   553 			{
       
   554 			uid.iUid=KVersitPropertyHBufCUid;
       
   555 			}
       
   556 		break;
       
   557 	default:
       
   558 		break;
       
   559 		}
       
   560 	if (uid == KNullUid)		// If a vCard specific property was not recognised then get the base class to see if it recognises the token.
       
   561 		return CVersitParser::RecognizeToken(aToken);
       
   562 	return uid;
       
   563 	}
       
   564 
       
   565 EXPORT_C void CParserVCard::Reserved1()
       
   566 	{}
       
   567 
       
   568 EXPORT_C void CParserVCard::Reserved2()
       
   569 	{}
       
   570 
       
   571 //
       
   572 // CParserVCard3
       
   573 //
       
   574 EXPORT_C CParserVCard3* CParserVCard3::NewL()
       
   575 /** Allocates and constructs a vCard 3.0 parser.
       
   576 
       
   577 @return A pointer to the newly constructed vCard parser. */
       
   578 	{
       
   579 	CParserVCard3* self = new(ELeave) CParserVCard3();
       
   580 	CleanupStack::PushL(self);
       
   581 	self->ConstructL();
       
   582 	CleanupStack::Pop(self);
       
   583 	return self;	
       
   584 	}
       
   585 	
       
   586 void CParserVCard3::ConstructL()
       
   587 /** Second phase constructor.*/
       
   588 	{
       
   589 	CVersitParser::ConstructL();
       
   590 	CreateParserPlugInL();
       
   591 	}
       
   592 	
       
   593 CParserVCard3::~CParserVCard3()
       
   594 /** Frees all resources owned by the vCard parser, prior to its destruction. */
       
   595 	{
       
   596 	delete iPlugInImpl;
       
   597 	}
       
   598 
       
   599 CParserVCard3::CParserVCard3()
       
   600 	{
       
   601 	iDefaultVersion = KVersitTokenVCard3VersionNo;
       
   602 	}
       
   603 
       
   604 void CParserVCard3::CreateParserPlugInL()
       
   605 /** Create Versit plugin to enable vCard 3.0 format export as defined
       
   606 by RFC2425 and RFC2426 */
       
   607 	{
       
   608 	iPlugInImpl = new(ELeave) CVCard3ParserPlugIn;
       
   609 	SetPlugIn(iPlugInImpl);
       
   610 	}
       
   611 	
       
   612 EXPORT_C void CParserVCard3::InternalizeL(RReadStream& /*aStream*/)
       
   613 /** Internalises a vCard 3.0 entity from a read stream. 
       
   614 Always leaves with KErrNotSupported because this class should only
       
   615 be used for vCard 3.0 export
       
   616 
       
   617 @param aStream Stream from which the vCard entity should be internalised. 
       
   618 */
       
   619 	{
       
   620 	User::Leave(KErrNotSupported);
       
   621 	}
       
   622 
       
   623 
       
   624 //
       
   625 // CVCard3ParserPlugIn
       
   626 //
       
   627 TBool CVCard3ParserPlugIn::AddSpace() 
       
   628 	{
       
   629 	return EFalse;
       
   630 	}
       
   631 
       
   632 TBool CVCard3ParserPlugIn::DeleteAllSpaces()
       
   633 	{
       
   634 	return EFalse;
       
   635 	}
       
   636 
       
   637 TBool CVCard3ParserPlugIn::NeedsBlankLine()
       
   638 	{
       
   639 	return EFalse;
       
   640 	}
       
   641 
       
   642 void CVCard3ParserPlugIn::RemoveEscaping(TPtr16& /*aText*/) 
       
   643 	{
       
   644 	//import not supported so do nothing
       
   645 	}
       
   646 	
       
   647 void CVCard3ParserPlugIn::AddEscaping(HBufC16*& aText)
       
   648 /** Plugin provides escaping of comma characters and also replacement of CRLF 
       
   649 sequence with '\n' in property values. */
       
   650 	{	
       
   651 	HBufC16* targetText = NULL;
       
   652 	//allocate a buffer large enough to cope with all characters in the string being
       
   653 	//escaped. If this allocation fails no escaping is attempted which will result in
       
   654 	//the creation of an invalid vCard
       
   655 	TRAPD(error, targetText = HBufC16::NewL(2*aText->Length()));
       
   656 	if (error || !targetText)
       
   657 		{
       
   658 		return;
       
   659 		}
       
   660 
       
   661  	//escape comma characters and replace CRLF with '\n'
       
   662 	TPtr targetPtr(targetText->Des());
       
   663 	const TUint16* pSource = aText->Ptr();
       
   664 	TInt length = aText->Length();
       
   665 	for(TInt i = 0; i<length; i++, pSource++) 
       
   666 		{
       
   667 		switch (*pSource) 
       
   668 			{
       
   669 			case KVersitTokenCommaVal:
       
   670 				{
       
   671 				//replace "," with "\,"
       
   672 				targetPtr.Append(KVersitTokenBackslashVal);
       
   673 				targetPtr.Append(*pSource);
       
   674 				}
       
   675 				break;
       
   676 			case KTokenCarriageReturnVal:
       
   677 				{
       
   678 				//CR is skipped and the next LF is replaced with '\n'
       
   679 				break;
       
   680 				}
       
   681 			case KTokenLineFeedVal:
       
   682 				{
       
   683 				//replace CRLF with "\n"	
       
   684 				targetPtr.Append(KVersitTokenBackslashVal);
       
   685 				targetPtr.Append(KTokenNewLineVal);
       
   686 				}
       
   687 				break;
       
   688 			default:
       
   689 				targetPtr.Append(*pSource);
       
   690 				break;	
       
   691 			}
       
   692 		}
       
   693 	delete aText;
       
   694 	aText = targetText;				
       
   695 	}
       
   696 	
       
   697 
       
   698 TBool CVCard3ParserPlugIn::WrapLine(RWriteStream& aStream, TInt& aCurrentLineLength, const TPtr8& aText)
       
   699 /** Plugin provides line folding as defined by RFC2425 and RFC2426*/
       
   700 	{
       
   701 	//this is a non-leaving function so all writes to the stream (which can leave)
       
   702 	//must be called in a TRAP. Any leaving errors are ignored because there is no
       
   703 	//way to report them to the client. This may result in a partial property value
       
   704 	//being written to the stream  
       
   705 	TRAP_IGNORE(DoWrapLineL(aStream, aCurrentLineLength, aText));
       
   706 	return ETrue;
       
   707 	}
       
   708 
       
   709 void CVCard3ParserPlugIn::DoWrapLineL(RWriteStream& aStream, TInt& aCurrentLineLength, const TPtr8& aText)
       
   710 	{
       
   711 	TPtr8 text(aText);
       
   712 	TPtr8 line(NULL,0,0);
       
   713 	TInt lineLength = Max(KMaxVCard3LineLength-aCurrentLineLength, 0);
       
   714 	TInt remaining = text.Length();
       
   715 
       
   716 	while (remaining > lineLength)
       
   717 		{
       
   718 		line.Set(&text[0], lineLength, lineLength);
       
   719 		aStream.WriteL(line);
       
   720 		aStream.WriteL(KVCard3LineBreakAndWSP);
       
   721 		aCurrentLineLength = 1;
       
   722 		remaining -= lineLength;
       
   723 		text.Set(&text[lineLength], remaining, remaining);
       
   724 		lineLength = KMaxVCard3LineLength-1;
       
   725 		}
       
   726 	aCurrentLineLength += text.Length();
       
   727 	aStream.WriteL(text);
       
   728 	}
       
   729 	
       
   730 TBool CVCard3ParserPlugIn::EncodingType(Versit::TVersitEncoding& aEncoding,
       
   731 						TBool /*aRequiresEncoding*/,
       
   732 						Versit::TVersitEncoding /*aDefaultEncoding*/,
       
   733 						TUid aPropertyUid, TUint /*aPropertyCharsetId*/) 
       
   734 	{
       
   735 	//quoted-printable encoding is performed by the transport wrapper so all
       
   736 	//non binary property values can be set to have no encoding here
       
   737 	aEncoding = Versit::ENoEncoding;
       
   738 
       
   739 	if (aPropertyUid == TUid::Uid(KVersitPropertyBinaryUid))
       
   740 		{
       
   741 		//inline binary property values are always encoded to base64
       
   742 		aEncoding = Versit::EBase64Encoding;
       
   743 		}
       
   744 	return ETrue;
       
   745 	}
       
   746 
       
   747 const TDesC8& CVCard3ParserPlugIn::EncodingName(Versit::TVersitEncoding aEncoding) 
       
   748 	{
       
   749 	if (aEncoding == Versit::EBase64Encoding)
       
   750 		{
       
   751 		//base64 encoding parameter value changed from "BASE64" to "B" 
       
   752 		return KVCard3TokenB;
       
   753 		}
       
   754 	return VersitUtils::IANAEncodingName(aEncoding);
       
   755 	}
       
   756 
       
   757 void CVCard3ParserPlugIn::GetInterface(TUid aInterfaceUid, TAny*& aInterface)
       
   758 /** Returns interface extension. */
       
   759 	{
       
   760 	if (aInterfaceUid == KUidVersitPlugInExtension)
       
   761 		{
       
   762 		aInterface = static_cast<MVersitPlugInExtension*>(this);
       
   763 		}
       
   764 	}
       
   765 	
       
   766 TBool CVCard3ParserPlugIn::DisableCharsetParam()
       
   767 	{
       
   768 	return ETrue;
       
   769 	}
       
   770 
       
   771 TBool CVCard3ParserPlugIn::DisableBlankLineAfterBinaryValue()
       
   772 	{
       
   773 	return ETrue;
       
   774 	}
       
   775 
       
   776 TBool CVCard3ParserPlugIn::WrapBinaryLinesL(CBufBase& aBuffer, TInt& aCurrentLineLength)
       
   777 /** Plugin provides line folding as defined by RFC2425 and RFC2426*/
       
   778 	{
       
   779 	TInt lineLength = Max(KMaxVCard3LineLength-aCurrentLineLength, 0);
       
   780 	TInt remaining = aBuffer.Size();
       
   781 	TInt pos = 0;
       
   782 	while (remaining>lineLength)
       
   783 		{
       
   784 		pos += lineLength;
       
   785 		aBuffer.InsertL(pos, KVCard3LineBreakAndWSP);
       
   786 		pos += KVCard3LineBreakAndWSP().Length();
       
   787 		remaining -= lineLength;
       
   788 		lineLength = KMaxVCard3LineLength-1;
       
   789 		aCurrentLineLength = 1;
       
   790 		}
       
   791 	aCurrentLineLength += remaining;
       
   792 	return ETrue;
       
   793 	}
       
   794 	
       
   795 TBool CVCard3ParserPlugIn::FoldParam()
       
   796 	{
       
   797 	return ETrue;
       
   798 	}
       
   799 	
       
   800 	
       
   801 //
       
   802 // CParserGroupedProperty
       
   803 //
       
   804 
       
   805 CParserGroupedProperty::CParserGroupedProperty(CParserPropertyValue& aPropertyValue,CDesC8Array* aArrayOfGroups,CArrayPtr<CParserParam>* aArrayOfParams)
       
   806 	: CParserProperty(aPropertyValue, aArrayOfParams), iArrayOfGroups(aArrayOfGroups)
       
   807 	{}
       
   808 
       
   809 EXPORT_C CParserGroupedProperty::CParserGroupedProperty(CDesC8Array* aArrayOfGroups, CArrayPtr<CParserParam>* aArrayOfParams)
       
   810 	: CParserProperty(aArrayOfParams), iArrayOfGroups(aArrayOfGroups)
       
   811 /** Allocates and partially constructs a new grouped property using the array of 
       
   812 grouped property names and array of property parameters specified.
       
   813 
       
   814 @param aArrayOfGroups Pointer to an array of descriptors. Each one specifies 
       
   815 a group name. The grouped property takes ownership of this array. 
       
   816 (May be NULL).
       
   817 @param aArrayOfParams The property parameters. The grouped property 
       
   818 takes ownership of this array. (May be NULL). */
       
   819 	{}
       
   820 
       
   821 EXPORT_C CParserGroupedProperty* CParserGroupedProperty::NewL(CParserPropertyValue& aPropertyValue, const TDesC8& aName, CDesC8Array* aArrayOfGroups, CArrayPtr<CParserParam>* aArrayOfParams)
       
   822 /** Allocates and constructs a new grouped property from the value, name, property 
       
   823 parameters and groups specified.
       
   824 
       
   825 Note: the property value, name and array of property parameters are generic 
       
   826 to all properties. The array of grouped property names is specific to the CParserGroupedProperty 
       
   827 class.
       
   828 
       
   829 @param aPropertyValue The property value. The grouped property takes 
       
   830 ownership of this.
       
   831 @param aName The property name. The grouped property takes ownership 
       
   832 of this.
       
   833 @param aArrayOfGroups Pointer to an array of descriptors. Each one specifies 
       
   834 a group name. The grouped property takes ownership of this array. (May be NULL).
       
   835 @param aArrayOfParams The property parameters. The grouped property 
       
   836 takes ownership of this array. (May be NULL).
       
   837 @return Pointer to the newly created grouped property. */
       
   838 	{
       
   839 	// coverity [alloc_fn]
       
   840 	CParserGroupedProperty* self = new(ELeave) CParserGroupedProperty(aPropertyValue,aArrayOfGroups,aArrayOfParams);
       
   841 	ConstructSelfL(*self,aName);
       
   842 	return self;
       
   843 	}
       
   844 
       
   845 EXPORT_C CParserGroupedProperty::~CParserGroupedProperty()
       
   846 /** Frees all resources owned by the property, prior to its destruction. */
       
   847 	{
       
   848 	delete iArrayOfGroups;
       
   849 	}
       
   850 
       
   851 EXPORT_C TBool CParserGroupedProperty::Group(const TDesC8& aGroup) const
       
   852 /** Tests whether the property is a member of the specified property group.
       
   853 
       
   854 @param aGroup The name of the property group. 
       
   855 @return ETrue if the property is a member of the specified property group. 
       
   856 EFalse if not. */
       
   857 	{
       
   858 	if (iArrayOfGroups)
       
   859 		{
       
   860 		TInt notUsed;
       
   861 		if (iArrayOfGroups->Find(aGroup,notUsed)==0)
       
   862 			return ETrue;
       
   863 		}
       
   864 	return EFalse;
       
   865 	}
       
   866 
       
   867 EXPORT_C TBool CParserGroupedProperty::SupportsInterface(const TUid& aInterfaceUid) const
       
   868 /** Tests whether the property supports the given interface.
       
   869 
       
   870 Returns true if the given interface UID is KVersitGroupedPropertyUid.
       
   871 
       
   872 @param aInterfaceUid An interface UID.
       
   873 @return ETrue if aInterfaceUid is KVersitGroupedPropertyUid, and EFalse if not. */
       
   874 	{
       
   875 	if (aInterfaceUid==TUid::Uid(KVersitGroupedPropertyUid))
       
   876 		return ETrue;
       
   877 	return CParserProperty::SupportsInterface(aInterfaceUid);
       
   878 	}
       
   879 
       
   880 EXPORT_C void CParserGroupedProperty::ExternalizeL(RWriteStream& aStream, CVersitParser* aVersitParser)
       
   881 /** Externalises the property into aStream.
       
   882 
       
   883 Externalises the list of groups to which the property belongs, if there are 
       
   884 any, then calls CParserProperty::ExternalizeL() to write the rest of the property 
       
   885 data to the stream.
       
   886 
       
   887 @param aStream Stream to which the value should be externalised.
       
   888 @param aVersitParser Versit parser which contains the objects to be externalised. 
       
   889 This must not be NULL or a panic occurs. */
       
   890 	{
       
   891 	if (iArrayOfGroups)
       
   892 		{
       
   893 		TInt count=iArrayOfGroups->Count();
       
   894 		for (TInt ii = 0; ii < count; ii++)
       
   895 			{
       
   896 #if defined _UNICODE
       
   897 			for(TInt i = 0; i < (*iArrayOfGroups)[ii].Length(); i++)
       
   898 				aStream.WriteUint8L((*iArrayOfGroups)[ii][i]);
       
   899 #else
       
   900 			aStream.WriteL((*iArrayOfGroups)[ii]);
       
   901 #endif
       
   902 			aStream.WriteL(KVersitTokenPeriod);
       
   903 			}
       
   904 		}
       
   905 	CParserProperty::ExternalizeL(aStream, aVersitParser);
       
   906 	}
       
   907 
       
   908 EXPORT_C void CParserGroupedProperty::Reserved()
       
   909 	{}
       
   910 
       
   911 //
       
   912 // CParserPropertyValueAgent
       
   913 //
       
   914 
       
   915 EXPORT_C CParserPropertyValueAgent::CParserPropertyValueAgent(CParserVCard* aValue)
       
   916 : CParserPropertyValue(TUid::Uid(KVCardPropertyAgentUid))
       
   917 , iValue(aValue)	
       
   918 /** Constructs an agent property value, using a pointer to an agent. 
       
   919 
       
   920 Sets the property value UID to KVCardPropertyAgentUid.
       
   921 
       
   922 @param aValue A pointer to the agent object to assign to the property value. 
       
   923 The property value takes ownership of the pointer. */
       
   924 	{}
       
   925 
       
   926 EXPORT_C CParserPropertyValueAgent::~CParserPropertyValueAgent()
       
   927 /** Frees all resources owned by the property value, prior to its destruction. */
       
   928 	{
       
   929 	delete iValue;
       
   930 	}
       
   931 
       
   932 EXPORT_C void CParserPropertyValueAgent::ExternalizeL(RWriteStream& aStream,const Versit::TEncodingAndCharset& /*aEncodingCharset*/,TInt /*aLengthOutput*/)
       
   933 /** Externalises the agent property value to aStream.
       
   934 
       
   935 @param aStream Stream to which the value should be externalised.
       
   936 @param aEncodingCharset Contains character set and encoding information. Not used as it is not 
       
   937 relevant to this function.
       
   938 @param aLengthOutput The line wrapping offset. Not used as it is not relevant to this function. */
       
   939 	{
       
   940 	if (!iValue)
       
   941 		return;
       
   942 	aStream.WriteL(KVersitTokenCRLF);
       
   943 	iValue->ExternalizeL(aStream);
       
   944 	}
       
   945