pimappservices/calendarvcalplugin/src/agmvcalx.cpp
changeset 0 f979ecb2b13e
child 29 12af337248b1
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 <s32mem.h>
       
    17 #include <vtzrules.h>
       
    18 #include <utf.h>
       
    19 #include <tz.h>
       
    20 
       
    21 #include <calentry.h>
       
    22 #include <calcontent.h>
       
    23 #include <calrrule.h>
       
    24 #include <caluser.h>
       
    25 #include <calalarm.h>
       
    26 #include <calattachment.h>
       
    27 
       
    28 #include "agmvcal.h"
       
    29 #ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
       
    30 #include <vpropbinaryfile.h>
       
    31 #endif
       
    32 
       
    33 
       
    34 /** Specifies number of years backward from current year for which DAYLIGHT properties are exported.*/
       
    35 const TInt KDaylightPropertyYearsBackwards(2);
       
    36 
       
    37 /** Specifies number of years forward from current year, or the repeat start year, for which DAYLIGHT properties are exported.*/
       
    38 const TInt KDaylightPropertyYearsForwards(5);
       
    39 
       
    40 
       
    41 // Utility method to ensure proper cleanup in OOM 
       
    42 //
       
    43 void CAgendaEntryToVCalConverter::ResetAndDestroyArrayOfParams(TAny* aObject)
       
    44 	{
       
    45 	CArrayPtr<CParserParam>* array=reinterpret_cast<CArrayPtr<CParserParam>*>(aObject);
       
    46 	if (array)
       
    47 		{
       
    48 		array->ResetAndDestroy();
       
    49 		}
       
    50 	delete array;
       
    51 	}
       
    52 
       
    53 void CAgendaEntryToVCalConverter::ResetAndDestroyArrayOfVersitDateTime(TAny* aObject)
       
    54 	{
       
    55 	CArrayPtr<TVersitDateTime>* array=reinterpret_cast<CArrayPtr<TVersitDateTime>*>(aObject);
       
    56 	if (array)
       
    57 		{
       
    58 		array->ResetAndDestroy();
       
    59 		}
       
    60 	delete array;
       
    61 	}
       
    62 
       
    63 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
       
    64  *	Public
       
    65  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
       
    66 
       
    67 // Export agenda entry aEntry to the given parser
       
    68 //
       
    69 void CAgendaEntryToVCalConverter::ExportEntryL(CCalEntry* aEntry, CVersitParser& aParser)
       
    70 	{
       
    71 	CParserVCalEntity* entity = CParserVCalEntity::NewL();
       
    72 	CleanupStack::PushL(entity);
       
    73 
       
    74 	if (aEntry->EntryTypeL() == CCalEntry::ETodo)
       
    75 		{
       
    76 		entity->SetEntityNameL(KVersitVarTokenVTODO);
       
    77 		}
       
    78 	else
       
    79 		{
       
    80 		entity->SetEntityNameL(KVersitVarTokenVEVENT);
       
    81 		}
       
    82 
       
    83 	if ((aEntry->StartTimeL()).TimeMode() == TCalTime::EFloating)
       
    84 		{
       
    85 		iTimeType = TVersitDateTime::EIsMachineLocal;
       
    86 		iTimeFlag = TVersitDateTime::EExportLeaveAsLocalTime;
       
    87 		}
       
    88 	else 
       
    89 		{
       
    90 		iTimeType=TVersitDateTime::EIsUTC;
       
    91 		iTimeFlag=TVersitDateTime::EExportTimeZoneDesignator;
       
    92 		}
       
    93 
       
    94 	AddEntryPropertiesL(aEntry, *entity);
       
    95 	CleanupStack::Pop(); // entity
       
    96 	aParser.AddEntityL(entity); // takes ownership
       
    97 	}
       
    98 
       
    99 CAgendaEntryToVCalConverter::~CAgendaEntryToVCalConverter()
       
   100 	{
       
   101 	}
       
   102 	
       
   103 
       
   104 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
       
   105  *	Private
       
   106  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
       
   107 	
       
   108 /** AddTzPropertyL()
       
   109  *
       
   110  *	Adds TZ property to aParser.
       
   111  *
       
   112  *	@param aParser		- a vCal entity or sub-entity (VEVENT or VTODO);
       
   113  *	@param aStdOffset	- standard time zone offset from UTC in seconds.
       
   114  */
       
   115 void CAgendaEntryToVCalConverter::AddTzPropertyL(CVersitParser& aParser, 
       
   116 												 TTimeIntervalSeconds aStdOffsetInSeconds)
       
   117 	{
       
   118 	if (!iAddedTzProperty)
       
   119 		{
       
   120 		CParserPropertyValue* vValue = new (ELeave) CParserPropertyValueTimeZone(aStdOffsetInSeconds);
       
   121 		CleanupStack::PushL(vValue);
       
   122 
       
   123 		CParserProperty* vProp = CParserProperty::NewL(*vValue, KVersitTokenTZ, NULL); 
       
   124 		CleanupStack::Pop(vValue);
       
   125 
       
   126 		aParser.AddPropertyL(vProp);
       
   127 		}
       
   128 	iAddedTzProperty = ETrue;
       
   129 	}
       
   130 
       
   131 
       
   132 /** MapToRelativeTime()
       
   133  *
       
   134  *	Provides mapping between iTimeReference of TVTzActualisedRule and iRelativeTime of TVersitDateTime. 
       
   135  *
       
   136  *	CTzRules::AddActualisedRulesL() guarantees that TVTzActualisedRule is always UTC or 
       
   137  *	local(ETzWallTimeReference), and is never STD. The func maps everything to 
       
   138  *	TVersitDateTime::EIsMachineLocal, unless iTimeReference is ETzUtcTimeReference, which is mapped
       
   139  *  to TVersitDateTime::EIsUTC.
       
   140  *
       
   141  *	This is local helper function.
       
   142  *	Used exclusively by CAgendaEntryToVCalConverter::AddTimeZonePropertiesL() to export DAYLIGHT properties.
       
   143  */
       
   144 static inline TVersitDateTime::TRelativeTime MapToRelativeTime(TTzTimeReference& aTzTimeRef)
       
   145 	{
       
   146 	return (aTzTimeRef==ETzUtcTimeReference) ? (TVersitDateTime::EIsUTC) : (TVersitDateTime::EIsMachineLocal);
       
   147 	}
       
   148 
       
   149 /*	AddDaylightPropertyL()
       
   150  *
       
   151  *	Export a DAYLIGHT property to describe the daylight saving period and its offset.
       
   152  *	There can be more than one DAYLIGHT property for a year (depenging on number of DST rules for the year).  
       
   153  *	Time designators (i.e EST, EDT) are not exported.
       
   154  *
       
   155  *	@param aParser		- a vCal entity or sub-entity (VEVENT or VTODO);
       
   156  *	@param aOffsetInSeconds	 - offset in seconds from UTC (i.e. STD + DST) for the period when the 
       
   157  					 	  daylight saving rule is in effect, 
       
   158  						  for instance, for time zone "Vancouver/America (PST)" aOffsetInSeconds is
       
   159  						  -480*60=-28800 secs in winter time, and -420*60=-25200 secs when DST is observed; 
       
   160  *	@param aStartTime	- exact time when a rule starts (usually 02:00:00 local time);
       
   161  *	@param aEndTime		- time when rule ends (usually 03:00:00 local time).
       
   162  */
       
   163 void CAgendaEntryToVCalConverter::AddDaylightPropertyL(CVersitParser& aParser, 
       
   164 													   TTimeIntervalSeconds aOffsetInSeconds,
       
   165 													   TTimeWithReference aStartTime,
       
   166 													   TTimeWithReference aEndTime)
       
   167 	{
       
   168 	TVersitDateTime* vStartTime = new(ELeave) TVersitDateTime(aStartTime.iTime.DateTime(),
       
   169 															  MapToRelativeTime(aStartTime.iTimeReference));
       
   170 	CleanupStack::PushL(vStartTime);
       
   171 
       
   172 	TVersitDateTime* vEndTime = new (ELeave) TVersitDateTime(aEndTime.iTime.DateTime(),
       
   173 															  MapToRelativeTime(aEndTime.iTimeReference));
       
   174 	CleanupStack::PushL(vEndTime);
       
   175 
       
   176 	CVersitDaylight* vDaylight = CVersitDaylight::NewL(ETrue, 
       
   177 													  aOffsetInSeconds, 
       
   178 													  vStartTime, 
       
   179 													  vEndTime, 
       
   180 													  KNullDesC(), 
       
   181 													  KNullDesC());
       
   182 	
       
   183 	CleanupStack::Pop(vEndTime);   // CVersitDaylight takes ownership.
       
   184 	CleanupStack::Pop(vStartTime); // CVersitDaylight takes ownership.
       
   185 
       
   186 	CleanupStack::PushL(vDaylight);
       
   187 	CParserPropertyValue* vValue = new (ELeave) CParserPropertyValueDaylight(vDaylight);
       
   188 	CleanupStack::Pop(vDaylight);
       
   189 
       
   190 	CleanupStack::PushL(vValue);
       
   191 	CParserProperty* vProp = CParserProperty::NewL(*vValue, KVersitTokenDAYLIGHT, NULL); 
       
   192 	CleanupStack::Pop(vValue);
       
   193 
       
   194 	aParser.AddPropertyL(vProp);
       
   195 	}
       
   196 
       
   197 
       
   198 /**	Adds DAYLIGHT properties for a range of years from aStartYear to aEndYear inclusive to 
       
   199  *	a vCalendar entity (aParser).
       
   200  *	
       
   201  *	@param aParser		- a vCalendar object where properties added
       
   202  *	@param aRules		- time zone rules used to retrieve DST information
       
   203  *	@param aRepeatStartTime		- start of entry range, including the repeat rule
       
   204  *	@param aRepeatEndTime		- end of entry range, including the repeat rule
       
   205  *
       
   206  */
       
   207 void CAgendaEntryToVCalConverter::AddDaylightPropertiesL(CVersitParser& aParser, const CTzRules* aRules, TInt aStdOffset, TTime aRepeatStartTime, TTime aRepeatEndTime)
       
   208 	{
       
   209 	const TInt KRepeatStartYear = aRepeatStartTime.DateTime().Year();
       
   210 	const TInt KRepeatEndYear = aRepeatEndTime.DateTime().Year();
       
   211 	
       
   212  	// actualise the rules starting a year before our period of interest
       
   213 	CVTzActualisedRules* actRules = CVTzActualisedRules::NewL(KRepeatStartYear - 1, KRepeatEndYear + 1);
       
   214 	
       
   215 	if (actRules)
       
   216 		{
       
   217 		CleanupStack::PushL(actRules);
       
   218 		aRules->GetActualisedRulesL(*actRules);
       
   219 		
       
   220 		TTime now;
       
   221 		now.HomeTime();
       
   222 		const TInt KThisYear = now.DateTime().Year();
       
   223 		
       
   224 		// Set up the time range for exported DAYLIGHT properties
       
   225 		const TInt KRangeBeginYear(Max(KThisYear - KDaylightPropertyYearsBackwards, KRepeatStartYear));
       
   226 		const TInt KRangeEndYear(Min(Max(KThisYear + KDaylightPropertyYearsForwards, KRepeatStartYear + KDaylightPropertyYearsForwards), KRepeatEndYear + 1));
       
   227 		const TTime KRangeBeginTime(TDateTime(KRangeBeginYear, EJanuary, 0, 0, 0, 0, 0));
       
   228 		const TTime KRangeEndTime(TDateTime(KRangeEndYear, EJanuary, 0, 0, 0, 0, 0));
       
   229 		
       
   230 		const TInt KRulesCount(actRules->Count());
       
   231 		for (TInt i(0) ; i < KRulesCount - 1 ; ++i)
       
   232 			{
       
   233 			TVTzActualisedRule& actRule = (*actRules)[i];
       
   234 			
       
   235 			if (aStdOffset < actRule.iNewOffset)		// work with DST rules only
       
   236 				{
       
   237 				// End time of a rule is start time of the next rule
       
   238 				TVTzActualisedRule& actRuleNext = (*actRules)[i+1];
       
   239 				
       
   240 				TTimeWithReference ruleStart(TTimeWithReference(actRule.iTimeOfChange, actRule.iTimeReference));
       
   241 				TTimeWithReference ruleEnd(TTimeWithReference(actRuleNext.iTimeOfChange, actRuleNext.iTimeReference));
       
   242 				
       
   243 				TTime ruleStartTime = ruleStart.iTime;
       
   244 				TTime ruleEndTime = ruleEnd.iTime;
       
   245 				
       
   246 				if (actRule.iTimeReference == ETzStdTimeReference)
       
   247 					{
       
   248 					ruleStartTime -= TTimeIntervalMinutes(aRules->InitialStdTimeOffset());
       
   249 					}
       
   250 				else if (actRule.iTimeReference == ETzWallTimeReference)
       
   251 					{
       
   252 					ruleStartTime -= TTimeIntervalMinutes(actRule.iNewOffset);
       
   253 					}						
       
   254 
       
   255 				if (actRule.iTimeReference == ETzStdTimeReference)
       
   256 					{
       
   257 					ruleEndTime -= TTimeIntervalMinutes(aRules->InitialStdTimeOffset());
       
   258 					}
       
   259 				else if (actRule.iTimeReference == ETzWallTimeReference)
       
   260 					{
       
   261 					ruleEndTime -= TTimeIntervalMinutes(actRule.iNewOffset);
       
   262 					}	
       
   263 				
       
   264 				// Export rule if the first instance occours when dst is on
       
   265 				// or if the rule covers the range defined above
       
   266 				if ( (aRepeatStartTime >= ruleStartTime) && (aRepeatStartTime <= ruleEndTime) || (ruleEndTime >= KRangeBeginTime) && (ruleStartTime <= KRangeEndTime) )
       
   267 					{
       
   268 					// Export DAYLIGHT property for concrete DST rule
       
   269 					AddDaylightPropertyL(aParser, actRule.iNewOffset * 60, ruleStart, ruleEnd);
       
   270 					}
       
   271 				}
       
   272 			}
       
   273 		CleanupStack::PopAndDestroy(actRules);
       
   274 		}
       
   275 	}
       
   276 
       
   277 void CAgendaEntryToVCalConverter::NextVCalendarL()
       
   278 	{
       
   279 	iAddedTzProperty = EFalse;
       
   280 	}
       
   281 
       
   282 /**	CAgendaEntryToVCalConverter::AddTimeZonePropertiesL()
       
   283  *	 	
       
   284  *	Adds TZ and DAYLIGHT properties to a vCalendar entity. 
       
   285  *
       
   286  *	@param aEntry 	- an agenda entry which supplies timezone and tz rules information 
       
   287  *						(has to have a repeat definition, otherwise function will do nothing);
       
   288  *	@param aParser	- a vCalendar object to which the properties are added. 
       
   289  *	
       
   290  *	aParser can be 1) a vCalendar object (also referrred to as "vCalendar entity"), 
       
   291  *		as well as 2) a vEvent or vTodo objects (also referred to as "vCalendar sub-entities").
       
   292  *	
       
   293  *	TZ and DAYLIGHT properties (as per vCalendar v1.0 spec) apply to the vCalendar object as a whole; UNLESS 
       
   294  *	overriden by a property within the scope of an event or todo entity.
       
   295  *	
       
   296  *	@internalComponent
       
   297  */
       
   298 void CAgendaEntryToVCalConverter::AddTimeZonePropertiesL(CVersitParser& aParser, CCalEntry* aEntry)
       
   299 	{
       
   300 	TCalRRule rrule;
       
   301 	
       
   302   	if (aEntry->GetRRuleL(rrule) && aEntry->StartTimeL().TimeMode() != TCalTime::EFloating)
       
   303 		{
       
   304 		// Only export the TZ property when the entry is repeating.
       
   305 		// Do not export TZ rules for floating entry.
       
   306 		CTzRules* rules = aEntry->TzRulesL();
       
   307 		
       
   308 		if (rules)
       
   309 			{
       
   310     		CleanupStack::PushL( rules );
       
   311 
       
   312             // find the standard offset for this time zone
       
   313             // which is the lowest offset from the rules for the entry's repeat range
       
   314             CVTzActualisedRules* actRules = CVTzActualisedRules::NewL(rrule.DtStart().TimeUtcL().DateTime().Year() - 1, rrule.Until().TimeUtcL().DateTime().Year() + 1);
       
   315         	CleanupStack::PushL(actRules);
       
   316         	rules->GetActualisedRulesL(*actRules);
       
   317         	
       
   318         	TInt stdOffset(KMaxTInt);
       
   319         	
       
   320         	const TInt KRulesCount = actRules->Count();
       
   321         	for (TInt i(0) ; i < KRulesCount ; ++i)
       
   322         		{
       
   323         		if ((*actRules)[i].iNewOffset < stdOffset)
       
   324         			{
       
   325         			stdOffset = (*actRules)[i].iNewOffset;
       
   326         			}
       
   327         		}
       
   328         	
       
   329         	if (stdOffset == KMaxTInt)
       
   330         		{
       
   331         		// there were no offsets found so use the current system utc offset
       
   332         		stdOffset = (User::UTCOffset().Int() / 60);
       
   333         		}
       
   334         	
       
   335         	CleanupStack::PopAndDestroy(actRules);
       
   336 			AddTzPropertyL(aParser, stdOffset * 60);
       
   337 			AddDaylightPropertiesL(aParser, rules, stdOffset, rrule.DtStart().TimeUtcL(), rrule.Until().TimeUtcL());
       
   338             
       
   339 			CleanupStack::PopAndDestroy(rules);	
       
   340 			}
       
   341 		}
       
   342 	}
       
   343 
       
   344 // This function specifies the ordering of the vCalendar properties as exported by Versit.
       
   345 //
       
   346 // The UID property should be the first property. 
       
   347 //
       
   348 // The following three properties of a vCalendar should be DESCRIPTION, DTSTART and DTEND for appointments, 
       
   349 // anniversaries & events. To-do entries should have DESCRIPTION and DUE as the following two properties.
       
   350 // This is to assist processing by Connectivity (as requested by Time Technology)
       
   351 //
       
   352 void CAgendaEntryToVCalConverter::AddEntryPropertiesL(CCalEntry* aEntry, CVersitParser& aParser)
       
   353 	{
       
   354 	// UID 
       
   355 
       
   356 	HBufC* guid16 = HBufC::NewLC(aEntry->UidL().Length());
       
   357 	TPtr ptr16 = guid16->Des();
       
   358 	CnvUtfConverter::ConvertToUnicodeFromUtf8(ptr16, aEntry->UidL());
       
   359 	AddDesPropertyL(aParser, KVersitTokenUID, guid16->Des());
       
   360 	CleanupStack::PopAndDestroy(guid16);
       
   361 		
       
   362 	// CAgnEntry::RichTextL()	=> SUMMARY 
       
   363 	// CAgnEntry::NotesTextL()	=> DESCRIPTION 
       
   364 
       
   365 	if (aEntry->DescriptionL().Length() > 0)
       
   366 		{
       
   367 		AddDesPropertyL(aParser, KVersitTokenDESCRIPTION, aEntry->DescriptionL());					
       
   368 		}
       
   369 		
       
   370 	if (aEntry->SummaryL().Length() > 0)
       
   371 		{
       
   372 		AddDesPropertyL(aParser, KVersitTokenSUMMARY, aEntry->SummaryL());
       
   373 		}
       
   374 
       
   375 	// Add DTSTART and DTEND (or DUE, PRIORITY and todo list information for to-do items), then add X-EPOCAGENDAENTRYTYPE
       
   376 	switch (aEntry->EntryTypeL())
       
   377 		{
       
   378 		case CCalEntry::EAppt:
       
   379 			{
       
   380 			AddEventPropertiesL(aParser, aEntry);
       
   381 			AddDesPropertyL(aParser, KVCalToken8ENTRYTYPE, KVCalTokenTypeAPPT);	
       
   382 			break;
       
   383 			}
       
   384 		case CCalEntry::EReminder:
       
   385 			{
       
   386 			AddEventPropertiesL(aParser, aEntry);
       
   387 			AddDesPropertyL(aParser, KVCalToken8ENTRYTYPE, KVCalTokenTypeREMINDER);	
       
   388 			break;
       
   389 			}
       
   390 		case CCalEntry::EAnniv:
       
   391 			{
       
   392 			AddEventPropertiesL(aParser, aEntry);
       
   393 			AddDesPropertyL(aParser, KVCalToken8ENTRYTYPE, KVCalTokenTypeANNIV);
       
   394 			break;
       
   395 			}
       
   396 		case CCalEntry::EEvent:
       
   397 			{
       
   398 			AddEventPropertiesL(aParser, aEntry);
       
   399 			AddDesPropertyL(aParser, KVCalToken8ENTRYTYPE, KVCalTokenTypeEVENT);
       
   400 			break;
       
   401 			}
       
   402 		case CCalEntry::ETodo:
       
   403 			{
       
   404 			AddTodoPropertiesL(aParser, aEntry);
       
   405 			AddDesPropertyL(aParser, KVCalToken8ENTRYTYPE, KVCalTokenTypeTODO);
       
   406 			break;
       
   407 			}
       
   408 		default: break;
       
   409 		}
       
   410 
       
   411 	// Class
       
   412 	CCalEntry::TReplicationStatus status = aEntry->ReplicationStatusL();
       
   413 	switch(status)
       
   414 		{
       
   415 		case CCalEntry::EOpen:
       
   416 			AddDesPropertyL(aParser, KVersitTokenCLASS, KVCalTokenPUBLIC);
       
   417 			break;
       
   418 		case CCalEntry::EPrivate:
       
   419 			AddDesPropertyL(aParser, KVersitTokenCLASS, KVCalTokenPRIVATE);
       
   420 			break;
       
   421 		case CCalEntry::ERestricted:
       
   422 			AddDesPropertyL(aParser, KVersitTokenCLASS, KVCalTokenCONFIDENTIAL);
       
   423 			break;
       
   424 		}
       
   425 
       
   426 	// Location
       
   427 	const TDesC& location = aEntry->LocationL();
       
   428 	if (location.Length() != 0)
       
   429 		{
       
   430 		AddDesPropertyL(aParser, KVersitTokenLOCATION, location);
       
   431 		}
       
   432 
       
   433 	// DTSTAMP
       
   434 	TCalTime dTStamp = aEntry->DTStampL();
       
   435 		
       
   436    	if ( dTStamp.TimeUtcL() != Time::NullTTime() )
       
   437       	{	
       
   438 		AddDateTimePropertyL(aParser, KVersitTokenXDTSTAMP, dTStamp.TimeUtcL(), TVersitDateTime::EIsUTC, iTimeFlag);
       
   439       	}
       
   440 	
       
   441 	// Sequence Number
       
   442 	AddIntegerPropertyL(aParser, KVersitTokenSEQUENCE, aEntry->SequenceNumberL());
       
   443 
       
   444 	//X-Method property
       
   445 	CCalEntry::TMethod methodStatus = aEntry->MethodL();
       
   446 	TPtrC methodStr;
       
   447 	switch(methodStatus)
       
   448 		{
       
   449 		case  CCalEntry::EMethodNone:
       
   450 			methodStr.Set(KVCalTokenMethodStatusENone);
       
   451 			break;
       
   452 		case CCalEntry::EMethodPublish:
       
   453 			methodStr.Set(KVCalTokenMethodStatusEPublish);
       
   454 			break;
       
   455 		case CCalEntry::EMethodRequest:
       
   456 			methodStr.Set(KVCalTokenMethodStatusERequest);
       
   457 			break;
       
   458 		case CCalEntry::EMethodReply:
       
   459 			methodStr.Set(KVCalTokenMethodStatusEReply);
       
   460 			break;
       
   461 		case CCalEntry::EMethodAdd:
       
   462 			methodStr.Set(KVCalTokenMethodStatusEAdd);
       
   463 			break;
       
   464 		case CCalEntry::EMethodCancel:
       
   465 			methodStr.Set(KVCalTokenMethodStatusECancel);
       
   466 			break;
       
   467 		case CCalEntry::EMethodRefresh:
       
   468 			methodStr.Set(KVCalTokenMethodStatusERefresh);
       
   469 			break;
       
   470 		case CCalEntry::EMethodCounter:
       
   471 			methodStr.Set(KVCalTokenMethodStatusECounter);
       
   472 			break;
       
   473 		case CCalEntry::EMethodDeclineCounter:
       
   474 			methodStr.Set(KVCalTokenMethodStatusEDeclineCounter);
       
   475 			break;	
       
   476 		default:
       
   477 			User::Leave(KErrArgument);	
       
   478 		}
       
   479 
       
   480 	AddDesPropertyL(aParser, KVersitTokenXMETHOD, methodStr);
       
   481 	// X-Recurrence-ID
       
   482 	TCalTime recurrenceDate = aEntry->RecurrenceIdL();
       
   483 	
       
   484 	if (recurrenceDate.TimeUtcL() != Time::NullTTime())
       
   485 		{
       
   486 		TTime recId;
       
   487 		if(iTimeType==TVersitDateTime::EIsUTC)
       
   488 			{
       
   489 			recId = recurrenceDate.TimeUtcL();
       
   490 			}
       
   491 		else
       
   492 			{
       
   493 			recId = recurrenceDate.TimeLocalL();
       
   494 			}
       
   495 		AddDateTimePropertyL(aParser, KVersitTokenXRECURRENCEID, recId, iTimeType, iTimeFlag);	
       
   496 		}
       
   497 		
       
   498 	// Attendees
       
   499 	RPointerArray<CCalAttendee> attendees = aEntry->AttendeesL();
       
   500 
       
   501 	TInt count=attendees.Count();
       
   502 	CCalUser* phoneowner=aEntry->PhoneOwnerL();
       
   503 	for (TInt ii=0; ii<count; ii++)
       
   504 		{
       
   505 		if(phoneowner==attendees[ii])
       
   506 			{
       
   507 			AddAttendeePropertyL(aParser, attendees[ii],ETrue, EFalse);
       
   508 			}
       
   509 		else
       
   510 			{
       
   511 			AddAttendeePropertyL(aParser, attendees[ii],EFalse, EFalse);
       
   512 			}
       
   513 		
       
   514 		}
       
   515 
       
   516 	CCalUser* organizer=aEntry->OrganizerL();
       
   517 	if(organizer)
       
   518 		{
       
   519 		if(phoneowner==organizer)
       
   520 			{
       
   521 			AddAttendeePropertyL(aParser, organizer,ETrue, ETrue);
       
   522 			}
       
   523 		else
       
   524 			{
       
   525 			AddAttendeePropertyL(aParser, organizer,EFalse, ETrue);
       
   526 			}
       
   527 		}
       
   528 
       
   529 	// Recurrence details
       
   530 	TCalRRule rule;
       
   531 	TBool isrepeat = aEntry->GetRRuleL(rule);
       
   532 	if (isrepeat)
       
   533 		{
       
   534 		CTzRules* repeatRule = aEntry->TzRulesL();
       
   535 		CleanupStack::PushL(repeatRule);
       
   536 		AddRepeatPropertiesL(aParser, rule, repeatRule);
       
   537 		CleanupStack::PopAndDestroy(repeatRule);
       
   538 		}
       
   539 		
       
   540 	// RDates
       
   541 	RArray<TCalTime>rdates;
       
   542 	CleanupClosePushL(rdates);
       
   543 	aEntry->GetRDatesL(rdates);
       
   544 
       
   545 	if (rdates.Count()>0)
       
   546 		{
       
   547 		AddRDatePropertyL(aParser, rdates);
       
   548 		isrepeat = ETrue;
       
   549 		}
       
   550 		
       
   551 	CleanupStack::PopAndDestroy(&rdates);
       
   552 
       
   553 	if (isrepeat)
       
   554 		{
       
   555 		// Recurrence Exception details
       
   556 		RArray<TCalTime> exceptions;
       
   557 		CleanupClosePushL(exceptions);
       
   558 		aEntry->GetExceptionDatesL(exceptions);
       
   559 
       
   560 		if (exceptions.Count()>0)
       
   561 			{
       
   562 			AddRepeatExceptionPropertiesL(aParser, exceptions);
       
   563 			}
       
   564 		CleanupStack::PopAndDestroy(&exceptions);
       
   565 		}
       
   566 		
       
   567 	// Alarm
       
   568 	CCalAlarm* alarm = aEntry->AlarmL();
       
   569 	if (alarm)
       
   570 		{
       
   571 		TCalTime alarmOrigin;
       
   572 		CleanupStack::PushL(alarm);
       
   573 		if(aEntry->EntryTypeL()==CCalEntry::ETodo && (aEntry->EndTimeL()).TimeUtcL()!=Time::NullTTime())
       
   574 			{
       
   575 			alarmOrigin = aEntry->EndTimeL();
       
   576 			}
       
   577 		else
       
   578 			{
       
   579 			alarmOrigin = aEntry->StartTimeL();
       
   580 			}
       
   581 		
       
   582 		TTime alarmtime;
       
   583 		if (aEntry->StartTimeL().TimeMode() != TCalTime::EFloating)
       
   584 			{
       
   585 			alarmtime = alarmOrigin.TimeUtcL() - TTimeIntervalMinutes(alarm->TimeOffset());
       
   586 			}
       
   587 		else
       
   588 			{
       
   589 			alarmtime = alarmOrigin.TimeLocalL() - TTimeIntervalMinutes(alarm->TimeOffset());
       
   590 			}
       
   591 		AddAlarmPropertyL(aParser, KVersitTokenAALARM, alarmtime, alarm->AlarmSoundNameL());
       
   592 		
       
   593 
       
   594 		CCalContent* alarmAction = alarm->AlarmAction();
       
   595 		if (alarmAction != NULL)
       
   596 			{
       
   597 			AddExtendedAlarmPropertyL(aParser, KVersitTokenXALARM, *alarmAction);
       
   598 			}
       
   599 		CleanupStack::PopAndDestroy(alarm);
       
   600 		}
       
   601 
       
   602 	// Add Last Changed Date
       
   603 	AddDateTimePropertyL(aParser, KVersitTokenLASTMODIFIED, (aEntry->LastModifiedDateL()).TimeUtcL(), TVersitDateTime::EIsUTC, iTimeFlag);
       
   604 
       
   605 	// Category Support
       
   606 	const RPointerArray<CCalCategory>& categories = aEntry->CategoryListL();
       
   607 
       
   608 	if (categories.Count()>0)
       
   609 		{
       
   610 		AddCategoryPropertyL(aParser, categories);
       
   611 		}
       
   612 
       
   613 	// ADDITION FOR VERSIT COMPLIANCE 
       
   614 	// Merged priorities into one place - ToDo priority was previously in AddTodoPropertiesL()
       
   615 	TInt priority = aEntry->PriorityL();
       
   616 	AddIntegerPropertyL(aParser, KVersitTokenPRIORITY, priority);
       
   617 	if (aEntry->EntryTypeL() != CCalEntry::ETodo)
       
   618 		{
       
   619 		AddStatusPropertyL(aParser, aEntry);
       
   620 		}
       
   621 	AddIntegerPropertyL(aParser, KVersitTokenXLOCALUID, aEntry->LocalUidL());
       
   622 	AddIntegerPropertyL(aParser, KVersitTokenTRANSP, aEntry->TimeTransparencyL());
       
   623 	
       
   624 	// Add GEO
       
   625 	CCalGeoValue* geoValue = aEntry->GeoValueL();
       
   626 	
       
   627 	// Check that the GEO values are not NULL
       
   628 	if(geoValue)
       
   629 		{
       
   630 		CleanupStack::PushL(geoValue);
       
   631 		
       
   632 		TReal geoLatitude;
       
   633 		TReal geoLongitude;
       
   634 		
       
   635 		// Extract latitude and longitude values
       
   636 		// Check if it returns EFalse
       
   637 		geoValue->GetLatLong(geoLatitude,geoLongitude);
       
   638 		
       
   639 		// Convert the geo values from numbers to string
       
   640 		// Create GEO string buffer to be constructed from a latitude, delimiter and a longitude value
       
   641 		TBuf<KGEOMaxWidthOfGeoValue*2+1> geoString;
       
   642 		TBuf<KGEOMaxWidthOfGeoValue> geoLatString;
       
   643 		TBuf<KGEOMaxWidthOfGeoValue> geoLongString;
       
   644 		
       
   645 		// Maximum width of a GEO value and max number of decimal places
       
   646 		TRealFormat geoFormat(KGEOMaxWidthOfGeoValue,KCalGEOMaxDecimalPlaces);
       
   647 		
       
   648 		_LIT(KGeoStringFormat,"%S%c%S");
       
   649 		
       
   650 		// Ensure correct conversion from stored numeric values to descriptors
       
   651 		if((geoLatString.Num(geoLatitude,geoFormat)>0) && (geoLongString.Num(geoLongitude,geoFormat)>0))
       
   652 			{
       
   653 			geoString.AppendFormat(KGeoStringFormat,&geoLatString,KVersitTokenCommaVal,&geoLongString);
       
   654 			
       
   655 			// Add the GEO property
       
   656 			AddDesPropertyL(aParser,KVersitTokenGEO,geoString);
       
   657 			}
       
   658 		
       
   659 		CleanupStack::PopAndDestroy(geoValue);
       
   660 		}
       
   661 		
       
   662 	TUint attachCount = aEntry->AttachmentCountL();
       
   663 	for(TInt ii = 0; ii<attachCount; ++ii)
       
   664 		{
       
   665 		CCalAttachment* attach = aEntry->AttachmentL(ii);
       
   666 		AddAttachmentPropertyL(aParser, *attach);
       
   667 		}
       
   668 	}
       
   669 
       
   670 
       
   671 // Add appointment properties to parser
       
   672 //
       
   673 void CAgendaEntryToVCalConverter::AddEventPropertiesL(CVersitParser& aParser, CCalEntry* aEntry)
       
   674 	{
       
   675 	//If this is an untimed appt the start time will be the default start time
       
   676  	//If the alarm time is *after* this time we need to move the start time to the alarm time
       
   677 	TTime startTime; 
       
   678 	TTime endTime; 
       
   679 	if((aEntry->StartTimeL()).TimeMode() == TCalTime::EFloating )
       
   680 		{
       
   681 		startTime = (aEntry->StartTimeL()).TimeLocalL();
       
   682 		if(aEntry->EntryTypeL()==CCalEntry::EReminder)
       
   683 			{
       
   684 			endTime = startTime;
       
   685 			}
       
   686 		else
       
   687 			{
       
   688 			endTime =(aEntry->EndTimeL()).TimeLocalL();
       
   689 			}
       
   690 
       
   691 		}
       
   692 	else 	
       
   693 		{
       
   694 		startTime = (aEntry->StartTimeL()).TimeUtcL();
       
   695 		if(aEntry->EntryTypeL()==CCalEntry::EReminder)
       
   696 			{
       
   697 			endTime = startTime;
       
   698 			}
       
   699 		else
       
   700 			{
       
   701 			endTime = (aEntry->EndTimeL()).TimeUtcL();
       
   702 			}
       
   703 
       
   704 		}
       
   705 	
       
   706 	iStartTime=startTime.DateTime();
       
   707 
       
   708 
       
   709 	AddDateTimePropertyL(aParser, KVersitTokenDTSTART, startTime, iTimeType, iTimeFlag);
       
   710 	AddDateTimePropertyL(aParser, KVersitTokenDTEND, endTime, iTimeType, iTimeFlag);
       
   711 	}
       
   712 
       
   713 // Add todo properties
       
   714 //
       
   715 void CAgendaEntryToVCalConverter::AddTodoPropertiesL(CVersitParser& aParser, CCalEntry* aEntry)
       
   716 	{
       
   717 	TBool isUtc = ETrue;
       
   718 	if ((aEntry->EndTimeL()).TimeUtcL() != Time::NullTTime())
       
   719 		{
       
   720 		if ((aEntry->StartTimeL()).TimeMode() == TCalTime::EFloating)
       
   721 			{
       
   722 			isUtc = EFalse;
       
   723 			AddDateTimePropertyL(aParser, KVersitTokenDUE, (aEntry->EndTimeL()).TimeLocalL(), iTimeType, iTimeFlag);
       
   724 			}
       
   725 		else
       
   726 			{
       
   727 			AddDateTimePropertyL(aParser, KVersitTokenDUE, (aEntry->EndTimeL()).TimeUtcL(), iTimeType, iTimeFlag);
       
   728 			}
       
   729 		}
       
   730 
       
   731 	// Add todo name list is now done with rest of category implementation	
       
   732 	TTime startDate; 
       
   733 	
       
   734 	if (isUtc)
       
   735 		{
       
   736 		startDate = aEntry->StartTimeL().TimeUtcL();
       
   737 		}
       
   738 	else
       
   739 		{
       
   740 		startDate = aEntry->StartTimeL().TimeLocalL();
       
   741 		}
       
   742 	iStartTime=startDate.DateTime();
       
   743 	
       
   744 	// We have already checked the start and end times so we do not need 
       
   745 	// further checks here. After discussion with MV.
       
   746 	if (startDate != Time::NullTTime())
       
   747 		{
       
   748 		AddDateTimePropertyL(aParser, KVersitTokenDTSTART, startDate, iTimeType, iTimeFlag);
       
   749 		}
       
   750 
       
   751 	// Is the entry completed - if so export completed date/time and COMPLETED status
       
   752 	if ((aEntry->CompletedTimeL()).TimeUtcL() != Time::NullTTime())
       
   753 		{
       
   754 		AddDateTimePropertyL(aParser,KVCalTokenCOMPLETED, (aEntry->CompletedTimeL()).TimeUtcL(), TVersitDateTime::EIsUTC, iTimeFlag);
       
   755 		AddDesPropertyL(aParser, KVCalTokenSTATUS, KVCalStatusCOMPLETED);
       
   756 		}
       
   757 	else
       
   758 		{
       
   759 		if (aEntry->StatusL()==CCalEntry::ETodoCompleted)
       
   760 			{
       
   761 			// If entry status is COMPLETED, ensure COMPLETED date is exported too
       
   762 			if ((aEntry->EndTimeL()).TimeUtcL()!= Time::NullTTime())
       
   763 				{
       
   764 				aEntry->SetCompletedL(ETrue,aEntry->EndTimeL());
       
   765 				}
       
   766 			else
       
   767 				{
       
   768 				//No valid due date, set the completed date to the today's date
       
   769 				TTime today;
       
   770 				today.UniversalTime();
       
   771 				TCalTime caltime;
       
   772 				caltime.SetTimeUtcL(today);
       
   773 				aEntry->SetCompletedL(ETrue, caltime);
       
   774 				}
       
   775 			AddDateTimePropertyL(aParser,KVCalTokenCOMPLETED, (aEntry->CompletedTimeL()).TimeUtcL(), TVersitDateTime::EIsUTC, iTimeFlag);
       
   776 			AddDesPropertyL(aParser, KVCalTokenSTATUS, KVCalStatusCOMPLETED);
       
   777 			}
       
   778 		else
       
   779 			{
       
   780 			// Entry is not completed and doesn't have status==Completed
       
   781 			// So, add status property as normal
       
   782 			AddStatusPropertyL(aParser,aEntry);
       
   783 			}
       
   784 
       
   785 		}
       
   786 		
       
   787 	}
       
   788 
       
   789 // Construct an integer property
       
   790 //
       
   791 void CAgendaEntryToVCalConverter::AddIntegerPropertyL(CVersitParser& aParser, const TDesC8& aToken, TCalLocalUid aInt)
       
   792 	{
       
   793 	CParserPropertyValue* value = new(ELeave)CParserPropertyValueInt(aInt);
       
   794 	CleanupStack::PushL(value);
       
   795 	CParserProperty* prop = CParserProperty::NewL(*value, aToken, NULL); 
       
   796 	CleanupStack::Pop(value);	
       
   797 	// Add to the parser
       
   798 	aParser.AddPropertyL(prop);
       
   799 	}
       
   800 
       
   801 void CAgendaEntryToVCalConverter::AddDateTimePropertyL(CVersitParser& aParser, const TDesC8& aToken, const TTime& aTime, const TVersitDateTime::TRelativeTime aRelativeTime, TVersitDateTime::TVersitDateTimeFlags aTimeFlag)
       
   802 	{
       
   803 	// Construct a date-time property
       
   804 	TVersitDateTime* versitDateTime = new(ELeave)TVersitDateTime(aTime.DateTime(), aRelativeTime);
       
   805 	CleanupStack::PushL(versitDateTime);
       
   806 	CParserPropertyValue* value = new(ELeave)CParserPropertyValueDateTime(versitDateTime);
       
   807 	CleanupStack::Pop(versitDateTime);
       
   808 	versitDateTime->SetFlag(aTimeFlag);
       
   809 	
       
   810 	CleanupStack::PushL(value);
       
   811 	CParserProperty* prop = CParserProperty::NewL(*value, aToken, NULL);
       
   812 	CleanupStack::Pop(value);
       
   813 	// Add to the parser
       
   814 	aParser.AddPropertyL(prop);
       
   815 
       
   816 	}
       
   817 
       
   818 void CAgendaEntryToVCalConverter::AddDesPropertyL(CVersitParser& aParser, const TDesC8& aToken, const TDesC& aDes)
       
   819 	{
       
   820 	HBufC* buf=AgnConvertUtil::EncodeL(aDes,KUidEtextToText);
       
   821 	CleanupStack::PushL(buf);
       
   822 	CParserPropertyValue* value = CParserPropertyValueHBufC::NewL(buf->Des());
       
   823 	CleanupStack::PopAndDestroy(buf);
       
   824 	CleanupStack::PushL(value);
       
   825 	CParserProperty* prop = CParserProperty::NewL(*value, aToken, NULL);
       
   826 	CleanupStack::Pop(value);
       
   827 	// Add to the parser
       
   828 	aParser.AddPropertyL(prop);
       
   829 	}
       
   830 
       
   831 void CAgendaEntryToVCalConverter::AddAlarmPropertyL(CVersitParser& aParser, const TDesC8& aToken, const TTime& aAlarmTime, const TDesC& aAlarmName)
       
   832 	{
       
   833 	// Create an array of paramaters for this property
       
   834 	CArrayPtr<CParserParam>* arrayOfParams = new(ELeave)CArrayPtrFlat<CParserParam>(4);
       
   835 	CleanupStack::PushL(TCleanupItem(ResetAndDestroyArrayOfParams,arrayOfParams));
       
   836 
       
   837 	CParserParam* typeParam = CParserParam::NewL(KVCalToken8TYPE, KNullDesC8);
       
   838 	CleanupStack::PushL(typeParam);
       
   839 	typeParam->SetValueL(KVCalValue8EPOCSOUND);
       
   840 	arrayOfParams->AppendL(typeParam); // takes ownership
       
   841 	CleanupStack::Pop(typeParam);
       
   842 
       
   843 	// Construct a date-time property
       
   844 	
       
   845 	TVersitDateTime* versitDateTime = new(ELeave)TVersitDateTime(aAlarmTime.DateTime(), iTimeType);
       
   846 	CleanupStack::PushL(versitDateTime);
       
   847 
       
   848 	CVersitAlarm* alarm = CVersitAlarm::NewL(versitDateTime, NULL, 0, aAlarmName, TPtrC());
       
   849 	CleanupStack::Pop(versitDateTime);
       
   850 	versitDateTime->SetFlag(iTimeFlag);
       
   851 	CleanupStack::PushL(alarm);
       
   852 	CParserPropertyValue* value = new(ELeave)CParserPropertyValueAlarm(alarm);
       
   853 	CleanupStack::Pop(alarm);
       
   854 	CleanupStack::PushL(value);
       
   855 
       
   856 	CParserProperty* prop = CParserProperty::NewL(*value, aToken, arrayOfParams);
       
   857 	CleanupStack::Pop(2,arrayOfParams); // value, arrayOfParams
       
   858 
       
   859 	// Add to the parser
       
   860 	aParser.AddPropertyL(prop);
       
   861 	}
       
   862 
       
   863 void CAgendaEntryToVCalConverter::AddExtendedAlarmPropertyL(CVersitParser& aParser, const TDesC8& aToken, const CCalContent& aAlarmAction)
       
   864 	{
       
   865 	// Create an array of parameters for this property
       
   866 	CArrayPtr<CParserParam>* arrayOfParams = new(ELeave)CArrayPtrFlat<CParserParam>(4);
       
   867 	CleanupStack::PushL(TCleanupItem(ResetAndDestroyArrayOfParams,arrayOfParams));
       
   868 	
       
   869 	// Create content disposition parameter
       
   870 	CParserParam* dispositionParam = CParserParam::NewL(KVersitTokenVALUE, KNullDesC8);
       
   871 	CleanupStack::PushL(dispositionParam);
       
   872 	CCalContent::TDisposition disposition = aAlarmAction.Disposition();
       
   873 	switch (disposition)
       
   874 		{
       
   875 		case CCalContent::EDispositionUrl:
       
   876 			{
       
   877 			dispositionParam->SetValueL(KVCalContentValueUrl);
       
   878 			break;
       
   879 			}
       
   880 		case CCalContent::EDispositionInline:
       
   881 			{
       
   882 			dispositionParam->SetValueL(KVCalContentValueInline);
       
   883 			break;
       
   884 			}
       
   885 		default:
       
   886 			{
       
   887 			// In the default case, the property is unsupported. So we'll clean up
       
   888 			// and then return
       
   889 			CleanupStack::PopAndDestroy(2); //arrayOfParams, dispositionParam
       
   890 			return;
       
   891 			}
       
   892 		}
       
   893 	arrayOfParams->AppendL(dispositionParam); // takes ownership
       
   894 	CleanupStack::Pop(dispositionParam);
       
   895 
       
   896 	// Create content MIME type parameter
       
   897 	CParserParam* mimeTypeParam = CParserParam::NewL(KVersitTokenCONTENTTYPE, KNullDesC8);
       
   898 	CleanupStack::PushL(mimeTypeParam);
       
   899 	TPtrC8 mimeType(aAlarmAction.MimeType());
       
   900 	mimeTypeParam->SetValueL(mimeType);
       
   901   	arrayOfParams->AppendL(mimeTypeParam);
       
   902   	CleanupStack::Pop(mimeTypeParam);
       
   903   	
       
   904   	
       
   905 	// Construct X-EPOC-ALARM property and initialise with parameters and content
       
   906 	CVersitExtendedAlarm* alarm = CVersitExtendedAlarm::NewL(aAlarmAction.Content(), aAlarmAction.MimeType(), static_cast<CVersitExtendedAlarm::TDisposition>(aAlarmAction.Disposition()));
       
   907 	CleanupStack::PushL(alarm);
       
   908 	CParserPropertyValue* value = new(ELeave)CParserPropertyValueExtendedAlarm(alarm);
       
   909 	CleanupStack::Pop(alarm);
       
   910 	CleanupStack::PushL(value);
       
   911 	CParserProperty* prop = CParserProperty::NewL(*value, aToken, arrayOfParams);
       
   912 	CleanupStack::Pop(2,arrayOfParams); // value, arrayOfParams
       
   913 
       
   914 	// Add to the parser
       
   915 	aParser.AddPropertyL(prop); // takes ownership of prop
       
   916 	}
       
   917 
       
   918 void CAgendaEntryToVCalConverter::AddAttachmentPropertyL(CVersitParser& aParser, CCalAttachment& aAttachment)
       
   919 	{
       
   920 	// Create an array of parameters for this property
       
   921 	CArrayPtr<CParserParam>* arrayOfParams = new(ELeave)CArrayPtrFlat<CParserParam>(4);
       
   922 	CleanupStack::PushL(TCleanupItem(ResetAndDestroyArrayOfParams,arrayOfParams));
       
   923 	
       
   924 	// Create value parameter
       
   925 	CParserParam* valueType = CParserParam::NewL(KVersitTokenVALUE, KNullDesC8);
       
   926 	CleanupStack::PushL(valueType);
       
   927 	CCalAttachment::TType type = aAttachment.Type();
       
   928 	TBool exportBinaryData = EFalse;
       
   929 	switch (type)
       
   930 		{
       
   931 		case CCalAttachment::EUri:
       
   932 			{
       
   933 			valueType->SetValueL(KVCalContentValueUrl);
       
   934 			break;
       
   935 			}
       
   936 		case CCalAttachment::EFile:
       
   937 			{
       
   938 			if (aAttachment.FileAttachment()->ContentId().Length() > 0)
       
   939 				{
       
   940 				valueType->SetValueL(KVCalContentValueContentId);
       
   941 				}
       
   942 			else if (aAttachment.IsAttributeSet(CCalAttachment::EExportInline))
       
   943 				{
       
   944 				valueType->SetValueL(KVCalContentValueInline);
       
   945 				exportBinaryData = ETrue;
       
   946 				}
       
   947 			break;
       
   948 			}
       
   949 		default:
       
   950 			// Do nothing. In this case the value will not be set
       
   951 			break;
       
   952 		}
       
   953 	if (valueType->Value().Length() == 0)
       
   954 		{
       
   955 		// The property is unsupported. So we'll clean up and then return
       
   956 		CleanupStack::PopAndDestroy(2, arrayOfParams); //arrayOfParams, valueType
       
   957 		return;
       
   958 		}
       
   959 	arrayOfParams->AppendL(valueType); // takes ownership
       
   960 	CleanupStack::Pop(valueType);
       
   961 
       
   962 	// Create content MIME type parameter
       
   963 	TPtrC8 mimeType(aAttachment.MimeType());
       
   964 	if(mimeType != KNullDesC8)
       
   965 		{
       
   966 		CParserParam* mimeTypeParam = CParserParam::NewL(KVersitAttachMimeType, mimeType);
       
   967 		CleanupStack::PushL(mimeTypeParam);
       
   968 	  	arrayOfParams->AppendL(mimeTypeParam);
       
   969 	  	CleanupStack::Pop(mimeTypeParam);
       
   970 		}
       
   971   
       
   972   	const TPtrC fileName(aAttachment.Label());
       
   973   	if(fileName != KNullDesC)
       
   974   		{
       
   975 		HBufC8* filenameUtf8 = HBufC8::NewLC(2 * fileName.Length()); // need room to convert from 16 bit to 8 bit (x2)
       
   976 		TPtr8 pfileName(filenameUtf8->Des());
       
   977 		User::LeaveIfError(CnvUtfConverter::ConvertFromUnicodeToUtf8(pfileName, fileName));					 
       
   978 		CParserParam* fileNameParameter = CParserParam::NewL(KVersitAttachLabel, pfileName);
       
   979 		CleanupStack::PopAndDestroy(filenameUtf8);  
       
   980 		CleanupStack::PushL(fileNameParameter);
       
   981 	  	arrayOfParams->AppendL(fileNameParameter);
       
   982 	  	CleanupStack::Pop(fileNameParameter);
       
   983   		}
       
   984 	 	// Create File Date parameter
       
   985 	TTime lastModifiedFileTime = Time::NullTTime();
       
   986 	if (aAttachment.FileAttachment())
       
   987 		{
       
   988 		lastModifiedFileTime = aAttachment.FileAttachment()->LastModifiedTimeUtc();
       
   989 		}
       
   990 	if(lastModifiedFileTime != Time::NullTTime())
       
   991 		{
       
   992 		_LIT(KStringFormat, "%F%Y%M%DT%H%T%SZ"); // locale-independent formatting YYMMDD"T"HHMMSS"Z" (day,month,year,hour,minute,second)
       
   993 		TBuf<KMaxTimeStringSize> dateString;
       
   994 		lastModifiedFileTime.FormatL(dateString,KStringFormat);
       
   995 		TBuf8<KMaxTimeStringSize> dateString8;
       
   996 		dateString8.Copy(dateString);
       
   997 		CParserParam* fileDate = CParserParam::NewL(KVCalAttachFileDate, dateString8);
       
   998 		CleanupStack::PushL(fileDate);
       
   999 	  	arrayOfParams->AppendL(fileDate);
       
  1000 	  	CleanupStack::Pop(fileDate);
       
  1001 		}
       
  1002 	  	
       
  1003   	CParserPropertyValue* propertyValue = NULL;
       
  1004 
       
  1005  	if (exportBinaryData)
       
  1006  		{
       
  1007  		RFile file;
       
  1008 	 	TRAPD(err,aAttachment.FileAttachment()->FetchFileHandleL(file));
       
  1009 		if(err == KErrNone)
       
  1010 			{
       
  1011 			CleanupClosePushL(file);
       
  1012 			propertyValue = CParserPropertyValueBinaryFile::NewL(file);
       
  1013 			CleanupStack::PopAndDestroy(&file);
       
  1014 			}
       
  1015 		else if(err == KErrArgument)
       
  1016 			{//FetchFileHandleL leaves with KErrArgument if there is no file handle has been set, eg. the entry hasn't been saved to Calendar file which isn't common user case
       
  1017 			TRAP(err, aAttachment.FileAttachment()->LoadBinaryDataL());
       
  1018 
       
  1019 			if(err != KErrNone)
       
  1020 				{//The user can keep synching if, e.g. it is out of memory, or the attachment file is on a drive where the media has been removed, or the attachment has been deleted from the calendar store by other clients.
       
  1021 				CleanupStack::PopAndDestroy(arrayOfParams);	
       
  1022 				return;
       
  1023 				}
       
  1024 
       
  1025 			propertyValue = CParserPropertyValueBinary::NewL(aAttachment.Value());
       
  1026 			}
       
  1027 		else
       
  1028 			{
       
  1029 			User::Leave(err);
       
  1030 			}
       
  1031 		}
       
  1032  	else 
       
  1033  		{
       
  1034  		TPtrC8 attach8;
       
  1035  		if (type == CCalAttachment::EFile)
       
  1036  			{
       
  1037  			attach8.Set(aAttachment.FileAttachment()->ContentId());	
       
  1038  			}
       
  1039  		else
       
  1040  			{
       
  1041  			attach8.Set(aAttachment.Value());	
       
  1042  			}
       
  1043  		
       
  1044  		HBufC* attach16 = HBufC::NewLC(attach8.Length());
       
  1045 		attach16->Des().Copy(attach8);
       
  1046  		propertyValue = CParserPropertyValueHBufC::NewL(attach16->Des());
       
  1047 		CleanupStack::PopAndDestroy(attach16);		
       
  1048   		}
       
  1049 	CleanupStack::PushL(propertyValue);
       
  1050 	CParserProperty* property = CParserProperty::NewL(*propertyValue, KVersitTokenATTACH, arrayOfParams);
       
  1051 	aParser.AddPropertyL(property);
       
  1052 	CleanupStack::Pop(2,arrayOfParams);		// propertyValue, arrayOfParams
       
  1053 	}
       
  1054 
       
  1055 void CAgendaEntryToVCalConverter::AddAttendeeParameterL(CArrayPtr<CParserParam>* aArrayOfParams, CCalAttendee* aAttendee)
       
  1056 	{
       
  1057 	// Create an array of paramaters for this property
       
  1058 	CParserParam* expectParam = CParserParam::NewL(KVCalAttendee8EXPECT, KNullDesC8);
       
  1059 	CleanupStack::PushL(expectParam);
       
  1060 	switch (aAttendee->VCalExpect())
       
  1061 		{
       
  1062 		case CCalAttendee::EVCalFyi:
       
  1063 			expectParam->SetValueL(KVCalAttendeeExpect8FYI);
       
  1064 			break;
       
  1065 		case CCalAttendee::EVCalRequire:
       
  1066 			expectParam->SetValueL(KVCalAttendeeExpect8REQUIRE);
       
  1067 			break;
       
  1068 		case CCalAttendee::EVCalRequest:
       
  1069 			expectParam->SetValueL(KVCalAttendeeExpect8REQUEST);
       
  1070 			break;
       
  1071 		case CCalAttendee::EVCalImmediate:
       
  1072 			expectParam->SetValueL(KVCalAttendeeExpect8IMMEDIATE);
       
  1073 			break;
       
  1074 		default:
       
  1075 			break;
       
  1076 		}
       
  1077 	aArrayOfParams->AppendL(expectParam); // takes ownership
       
  1078 	CleanupStack::Pop(expectParam); 
       
  1079 	
       
  1080 	CParserParam* rsvpParam = CParserParam::NewL(KVCalAttendee8RSVP, KNullDesC8);
       
  1081 	CleanupStack::PushL(rsvpParam);
       
  1082 	switch (aAttendee->ResponseRequested())
       
  1083 		{
       
  1084 		case ETrue:
       
  1085 			rsvpParam->SetValueL(KVCalAttendeeRsvp8YES);
       
  1086 			break;
       
  1087 		case EFalse:
       
  1088 			rsvpParam->SetValueL(KVCalAttendeeRsvp8NO);
       
  1089 			break;
       
  1090 		default:
       
  1091 			break;
       
  1092 		}
       
  1093 	aArrayOfParams->AppendL(rsvpParam); // takes ownership
       
  1094 	CleanupStack::Pop(rsvpParam); 
       
  1095 	
       
  1096 	CParserParam* calroleParam = CParserParam::NewL(KICalAttendeeCalRole8, KNullDesC8);
       
  1097 	CleanupStack::PushL(calroleParam);
       
  1098 	
       
  1099 	CParserParam* vcalroleParam = CParserParam::NewL(KICalAttendeeCalRole8, KNullDesC8);
       
  1100 	CleanupStack::PushL(vcalroleParam);
       
  1101 	
       
  1102 	switch (aAttendee->RoleL())
       
  1103 		{
       
  1104 		case CCalAttendee::EChair:
       
  1105 			calroleParam->SetValueL(KICalAttendeeCalRole8CHAIR);
       
  1106 			break;
       
  1107 		case CCalAttendee::EReqParticipant:
       
  1108 			calroleParam->SetValueL(KICalAttendeeCalRole8REQUIRED);
       
  1109 			break;
       
  1110 		case CCalAttendee::EOptParticipant: 
       
  1111 			calroleParam->SetValueL(KICalAttendeeCalRole8OPTIONAL);
       
  1112 			break;
       
  1113 		case CCalAttendee::ENonParticipant:
       
  1114 			calroleParam->SetValueL(KICalAttendeeCalRole8NONPARTICIPANT);
       
  1115 			break;
       
  1116 			
       
  1117 		case CCalAttendee::EVCalAttendee:
       
  1118 			vcalroleParam->SetValueL(KVCalAttendeeRole8ATTENDEE);
       
  1119 			break;
       
  1120 		case CCalAttendee::EVCalDelegate:
       
  1121 			vcalroleParam->SetValueL(KVCalAttendeeRole8DELEGATE);
       
  1122 			break;
       
  1123 		case CCalAttendee::EVCalOwner:
       
  1124 			vcalroleParam->SetValueL(KVCalAttendeeRole8OWNER);
       
  1125 			break;
       
  1126 		default:
       
  1127 			break;
       
  1128 		}
       
  1129 	if (calroleParam->Value().Length() > 0)
       
  1130 		{
       
  1131 		aArrayOfParams->AppendL(calroleParam); // takes ownership
       
  1132 		CleanupStack::PopAndDestroy(vcalroleParam); // delete the vCal role as it is not used
       
  1133 		CleanupStack::Pop(calroleParam);
       
  1134 		}
       
  1135 	else
       
  1136 		{
       
  1137 		aArrayOfParams->AppendL(vcalroleParam); // takes ownership
       
  1138 		CleanupStack::Pop(vcalroleParam);
       
  1139 		CleanupStack::PopAndDestroy(calroleParam); // delete the iCal role as it is not used
       
  1140 		}
       
  1141 	
       
  1142 	CParserParam* calStatusParam = CParserParam::NewL(KICalAttendeeCalStatus8, KNullDesC8);
       
  1143 	CleanupStack::PushL(calStatusParam);
       
  1144 	
       
  1145 	CParserParam* vcalStatusParam = CParserParam::NewL(KVCalAttendee8STATUS, KNullDesC8);
       
  1146 	CleanupStack::PushL(vcalStatusParam);
       
  1147 	
       
  1148 	switch (aAttendee->StatusL())
       
  1149 		{
       
  1150 		case CCalAttendee::EAccepted:
       
  1151 			calStatusParam->SetValueL(KVCalAttendeeStatus8ACCEPTED);
       
  1152 			vcalStatusParam->SetValueL(KVCalAttendeeStatus8ACCEPTED);
       
  1153 			break;
       
  1154 		case CCalAttendee::ENeedsAction:
       
  1155 			calStatusParam->SetValueL(KICalAttendeeCalStatus8NEEDSACTION);
       
  1156 			vcalStatusParam->SetValueL(KVCalAttendeeStatus8NEEDSACTION);
       
  1157 			break;
       
  1158 		case CCalAttendee::ETentative:
       
  1159 			calStatusParam->SetValueL(KVCalAttendeeStatus8TENTATIVE);
       
  1160 			vcalStatusParam->SetValueL(KVCalAttendeeStatus8TENTATIVE);
       
  1161 			break;
       
  1162 		case CCalAttendee::EConfirmed:
       
  1163 			calStatusParam->SetValueL(KVCalAttendeeStatus8CONFIRMED);
       
  1164 			vcalStatusParam->SetValueL(KVCalAttendeeStatus8CONFIRMED);
       
  1165 			break;
       
  1166 		case CCalAttendee::EDeclined:
       
  1167 			calStatusParam->SetValueL(KVCalAttendeeStatus8DECLINED);
       
  1168 			vcalStatusParam->SetValueL(KVCalAttendeeStatus8DECLINED);
       
  1169 			break;
       
  1170 		case CCalAttendee::ECompleted:
       
  1171 			calStatusParam->SetValueL(KVCalAttendeeStatus8COMPLETED);
       
  1172 			vcalStatusParam->SetValueL(KVCalAttendeeStatus8COMPLETED);
       
  1173 			break;
       
  1174 		case CCalAttendee::EDelegated:
       
  1175 			calStatusParam->SetValueL(KVCalAttendeeStatus8DELEGATED);
       
  1176 			vcalStatusParam->SetValueL(KVCalAttendeeStatus8DELEGATED);
       
  1177 			break;
       
  1178 		case CCalAttendee::EInProcess:
       
  1179 			calStatusParam->SetValueL(KICalAttendeeCalStatus8INPROCESS);
       
  1180 			break;
       
  1181 		case CCalAttendee::EVCalSent:
       
  1182 			vcalStatusParam->SetValueL(KVCalAttendeeStatus8SENT);
       
  1183 			break;
       
  1184 		case CCalAttendee::EVCalXReceived:
       
  1185 			vcalStatusParam->SetValueL(KVCalAttendeeStatus8XDASHRECEIVED);
       
  1186 			break;
       
  1187 		default:
       
  1188 			break;
       
  1189 		}
       
  1190 	
       
  1191 	if (vcalStatusParam->Value().Length() > 0)
       
  1192 		{
       
  1193 		aArrayOfParams->AppendL(vcalStatusParam); // takes ownership
       
  1194 		CleanupStack::Pop(vcalStatusParam);
       
  1195 		}
       
  1196 	else
       
  1197 		{
       
  1198 		CleanupStack::PopAndDestroy(vcalStatusParam); 
       
  1199 		}
       
  1200 		
       
  1201 	if (calStatusParam->Value().Length() > 0)
       
  1202 		{
       
  1203 		aArrayOfParams->AppendL(calStatusParam); // takes ownership
       
  1204 		CleanupStack::Pop(calStatusParam); 
       
  1205 		}
       
  1206 	else
       
  1207 		{
       
  1208 		CleanupStack::PopAndDestroy(calStatusParam); 
       
  1209 		}
       
  1210 	}
       
  1211 
       
  1212 void CAgendaEntryToVCalConverter::AddAttendeePropertyL(CVersitParser& aParser, CCalUser* aAttendee, TBool isPhoneOwner, TBool isOrganizer)
       
  1213 	{
       
  1214 	CArrayPtr<CParserParam>* arrayOfParams = new(ELeave)CArrayPtrFlat<CParserParam>(9);
       
  1215 	CleanupStack::PushL(TCleanupItem(ResetAndDestroyArrayOfParams,arrayOfParams));
       
  1216 
       
  1217 	if( aAttendee->SentBy() != KNullDesC)
       
  1218 		{
       
  1219 		CParserParam* sentByParam = CParserParam::NewL(KICalAttendeeSentBy8, aAttendee->SentBy());
       
  1220 		CleanupStack::PushL(sentByParam);
       
  1221 		arrayOfParams->AppendL(sentByParam);
       
  1222 		CleanupStack::Pop(sentByParam);	
       
  1223 		}	
       
  1224 
       
  1225 	if( aAttendee->CommonName() != KNullDesC)
       
  1226 		{
       
  1227 		CParserParam* commonNameParam = CParserParam::NewL(KICalAttendeeCommonName8, aAttendee->CommonName());
       
  1228 		CleanupStack::PushL(commonNameParam);
       
  1229 		arrayOfParams->AppendL(commonNameParam);	// takes ownership
       
  1230 		CleanupStack::Pop(commonNameParam);	
       
  1231 		}
       
  1232 	
       
  1233 	if(isPhoneOwner)
       
  1234 		{
       
  1235 		CParserParam* phoneOwnerParam = CParserParam::NewL(KICalAttendee8XDASHPHONEOWNER, KNullDesC8);
       
  1236 		CleanupStack::PushL(phoneOwnerParam);
       
  1237 		arrayOfParams->AppendL(phoneOwnerParam);	// takes ownership
       
  1238 		CleanupStack::Pop(phoneOwnerParam);			
       
  1239 		}
       
  1240 		
       
  1241 	if (isOrganizer)
       
  1242 		{
       
  1243 		CParserParam* organizerParam = CParserParam::NewL(KVCalAttendee8ROLE, KVCalAttendeeRole8ORGANIZER);
       
  1244 		CleanupStack::PushL(organizerParam);
       
  1245 		arrayOfParams->AppendL(organizerParam);	// takes ownership
       
  1246 		CleanupStack::Pop(organizerParam);
       
  1247 		}
       
  1248 	else
       
  1249 		{
       
  1250 		// these properties are not supported in CCalUser so don't need to be exported for an organizer
       
  1251 		AddAttendeeParameterL(arrayOfParams,static_cast<CCalAttendee*>(aAttendee));
       
  1252 		}
       
  1253 				
       
  1254 	CParserPropertyValue* value = CParserPropertyValueHBufC::NewL(aAttendee->Address());
       
  1255 	CleanupStack::PushL(value);
       
  1256 	CParserProperty* prop = CParserProperty::NewL(*value, KVersitTokenATTENDEE, arrayOfParams);
       
  1257 	// Add to the parser
       
  1258 	aParser.AddPropertyL(prop);
       
  1259 	CleanupStack::Pop(2,arrayOfParams);		// value, arrayOfParams
       
  1260 	}
       
  1261 
       
  1262 
       
  1263 
       
  1264 void CAgendaEntryToVCalConverter::AddRepeatPropertiesL(CVersitParser& aParser, TCalRRule& aRpt, CTzRules* aEntryTzRule)
       
  1265 	{
       
  1266 	CVersitRecurrence* recurrence = NULL;
       
  1267 	TCalRRule::TType rType = aRpt.Type();
       
  1268 
       
  1269 	TVersitDateTime* endTime = NULL;
       
  1270 	TUint duration = 0;
       
  1271 	if (aRpt.Count() != 0)
       
  1272 		{
       
  1273 		TTime untilTime;
       
  1274 		if(aEntryTzRule)
       
  1275 			{
       
  1276 			untilTime = aRpt.Until().TimeUtcL();
       
  1277 			//convert utc to repeat local
       
  1278 			aEntryTzRule->ConvertToLocalL(untilTime);
       
  1279 			}
       
  1280 		else
       
  1281 			{//use system local
       
  1282 			untilTime = aRpt.Until().TimeLocalL();
       
  1283 			}
       
  1284 		TDateTime end=untilTime.DateTime();
       
  1285 		endTime = new(ELeave) TVersitDateTime(end, TVersitDateTime::EIsVCardLocal);
       
  1286 		endTime->SetFlag(TVersitDateTime::EExportLeaveAsLocalTime);
       
  1287  		duration = aRpt.Count();
       
  1288 		}
       
  1289 	CleanupStack::PushL(endTime);
       
  1290 
       
  1291 	switch (aRpt.Type())
       
  1292 		{
       
  1293 		// Daily Repeat
       
  1294 		case TCalRRule::EDaily:
       
  1295 			recurrence = new(ELeave)CVersitRecurrenceDaily(aRpt.Interval(), duration, endTime);
       
  1296 			break;
       
  1297 		// Weekly Repeat
       
  1298 		case TCalRRule::EWeekly:
       
  1299 			recurrence = CreateWeeklyRepeatL(aRpt, duration, endTime);
       
  1300 			break;
       
  1301 		// Monthly By Days Repeat
       
  1302 		case TCalRRule::EMonthly:
       
  1303 			recurrence = CreateMonthlyRepeatL(aRpt, duration, endTime);
       
  1304 			break;
       
  1305 		// Yearly By Day Repeat
       
  1306 		case TCalRRule::EYearly:
       
  1307 			recurrence = CreateYearlyRepeatL(aRpt, duration, endTime);
       
  1308 			break;
       
  1309 		default:
       
  1310 			delete endTime;
       
  1311 			break;
       
  1312 		}
       
  1313 	CleanupStack::Pop();	// endTime (owned by recurrence)
       
  1314 
       
  1315 	if (recurrence)
       
  1316 		{
       
  1317 		CleanupStack::PushL(recurrence);
       
  1318 		CParserPropertyValue* value = new(ELeave)CParserPropertyValueRecurrence(recurrence);	// takes ownership
       
  1319 		CleanupStack::Pop();		// recurrence
       
  1320 		CleanupStack::PushL(value);
       
  1321 		CParserProperty* prop = CParserProperty::NewL(*value, KVersitTokenRRULE, NULL);
       
  1322 		CleanupStack::Pop(value);
       
  1323 
       
  1324 		// Add to the parser
       
  1325 		aParser.AddPropertyL(prop);
       
  1326 		}
       
  1327 	}
       
  1328 
       
  1329 CVersitRecurrence* CAgendaEntryToVCalConverter::CreateWeeklyRepeatL(TCalRRule& aRpt,TInt aDuration, TVersitDateTime* aEndTime)
       
  1330 	{
       
  1331 	// Convert the agenda weekly repeat to a versit recurrence
       
  1332 
       
  1333 	CWeekDayArray* dayArray = new(ELeave)CWeekDayArray();
       
  1334 	CleanupStack::PushL(dayArray);
       
  1335 	dayArray->iArray = new(ELeave)CArrayFixFlat<TDay>(1);
       
  1336 
       
  1337 	// Iterate through the days to check which days are set
       
  1338 	RArray<TDay> daysinweek;
       
  1339 	CleanupClosePushL(daysinweek);
       
  1340 	aRpt.GetByDayL(daysinweek);
       
  1341 	TInt count=daysinweek.Count();
       
  1342 	for (TInt ii=0; ii<count; ++ii)
       
  1343 		{
       
  1344 		dayArray->iArray->AppendL(daysinweek[ii]);
       
  1345 		}
       
  1346 	CleanupStack::PopAndDestroy(&daysinweek);
       
  1347 	CVersitRecurrence* recurrence = new(ELeave)CVersitRecurrenceWeekly(aRpt.Interval(), aDuration, aEndTime, dayArray); // takes ownership
       
  1348 	CleanupStack::Pop(dayArray);
       
  1349 
       
  1350 	return recurrence;
       
  1351 	}
       
  1352 	
       
  1353 CVersitRecurrence* CAgendaEntryToVCalConverter::CreateMonthlyRepeatL(TCalRRule& aRpt, TInt aDuration, TVersitDateTime* aEndTime)
       
  1354 	{
       
  1355 	// Convert Agenda Monthly By Days repeat to a versit recurrence
       
  1356 	RArray<TCalRRule::TDayOfMonth> days;
       
  1357 	aRpt.GetByDayL(days);
       
  1358 	TInt count=days.Count();
       
  1359 	if(count>0)	
       
  1360 		{//e.g. every Monday of first week and every Friday of the third week.
       
  1361 		CleanupClosePushL(days);
       
  1362 		CArrayPtrFlat<CVersitRecurrenceMonthlyByPos::CMonthPosition>* monthPositions = new(ELeave)CArrayPtrFlat<CVersitRecurrenceMonthlyByPos::CMonthPosition>(1);
       
  1363 		CleanupStack::PushL(monthPositions);
       
  1364 
       
  1365 		// Iterate through the five weeks for the month
       
  1366 		// (First,Second,Third,Fourth,Last)
       
  1367 				
       
  1368 		for (TInt ii=0; ii<count; ++ii)
       
  1369 			{
       
  1370 			CVersitRecurrenceMonthlyByPos::CMonthPosition* monthPos = new(ELeave)CVersitRecurrenceMonthlyByPos::CMonthPosition();
       
  1371 			CleanupStack::PushL(monthPos);
       
  1372 			
       
  1373 			TInt8 weekNo = days[ii].WeekInMonth();
       
  1374 			if(weekNo>0)
       
  1375 				{
       
  1376 				monthPos->iSign = CVersitRecurrenceMonthlyByPos::CMonthPosition::EWeeksFromStartOfMonth;
       
  1377 				monthPos->iWeekNo = weekNo;	
       
  1378 				}
       
  1379 			else
       
  1380 				{
       
  1381 				monthPos->iSign = CVersitRecurrenceMonthlyByPos::CMonthPosition::EWeeksFromEndOfMonth;
       
  1382 				monthPos->iWeekNo = Abs(weekNo);
       
  1383 				}
       
  1384 			monthPos->iArrayOfWeekDays = new(ELeave)CWeekDayArray();
       
  1385 			monthPos->iArrayOfWeekDays->iArray = new(ELeave)CArrayFixFlat<TDay>(1);
       
  1386 			monthPos->iArrayOfWeekDays->iArray->AppendL(days[ii].Day());
       
  1387 			monthPositions->AppendL(monthPos);
       
  1388 			CleanupStack::Pop();		// monthPos;
       
  1389 			}
       
  1390 
       
  1391 		CVersitRecurrence* recurrence = new(ELeave)CVersitRecurrenceMonthlyByPos(aRpt.Interval(), aDuration, aEndTime, monthPositions);
       
  1392 		CleanupStack::Pop();	// monthPositions (owned by recurrence)
       
  1393 		CleanupStack::PopAndDestroy(&days);
       
  1394 		return recurrence;
       
  1395 		}
       
  1396 	else
       
  1397 		{
       
  1398 		RArray<TInt> dayofmonth;
       
  1399 		aRpt.GetByMonthDayL(dayofmonth);
       
  1400 		TInt count=dayofmonth.Count();
       
  1401 		if(count>0)
       
  1402 			{
       
  1403 			CleanupClosePushL(dayofmonth);
       
  1404 			CArrayFixFlat<TInt>* dayList = new(ELeave)CArrayFixFlat<TInt>(1);
       
  1405 			CleanupStack::PushL(dayList);
       
  1406 
       
  1407 			// Iterate through each day in the month
       
  1408 
       
  1409 			for (TInt ii=0; ii<count; ++ii)
       
  1410 				{
       
  1411 				dayList->AppendL(dayofmonth[ii]+1);  // add 1, since 0 means 1st
       
  1412 				}
       
  1413 
       
  1414 			CVersitRecurrence* recurrence = new(ELeave)CVersitRecurrenceMonthlyByDay(aRpt.Interval(), aDuration, aEndTime, dayList, NULL, EFalse);
       
  1415 
       
  1416 			CleanupStack::Pop();		// dayList;
       
  1417 			
       
  1418 			CleanupStack::PopAndDestroy(&dayofmonth);
       
  1419 			return recurrence;
       
  1420 			}
       
  1421 		}
       
  1422 	return NULL;
       
  1423 	}
       
  1424 
       
  1425 CVersitRecurrence* CAgendaEntryToVCalConverter::CreateYearlyRepeatL(TCalRRule& aRpt, TInt aDuration, TVersitDateTime* aEndTime)
       
  1426 	{
       
  1427 	// Convert Agenda Yearly By Days repeat to a versit recurrence
       
  1428 
       
  1429 	// There is no vCal equivalent of a yearly 'by day' repeat,
       
  1430 	// e.g. repeat on the first monday of october,
       
  1431 	// so a monthly repeat with an interval of 12* the yearly repeat
       
  1432 	// is used instead
       
  1433 	RArray<TCalRRule::TDayOfMonth> days;
       
  1434 	aRpt.GetByDayL(days);
       
  1435 	TInt count=days.Count();
       
  1436 	if(count>0)
       
  1437 		{
       
  1438 		CleanupClosePushL(days);
       
  1439 		CArrayPtrFlat<CVersitRecurrenceMonthlyByPos::CMonthPosition>* monthPositions = new(ELeave)CArrayPtrFlat<CVersitRecurrenceMonthlyByPos::CMonthPosition>(1);
       
  1440 		CleanupStack::PushL(monthPositions);
       
  1441 
       
  1442 		// Iterate through the five weeks for the month
       
  1443 		// (First,Second,Third,Fourth,Last)
       
  1444 				
       
  1445 		for (TInt ii=0; ii<count; ++ii)
       
  1446 			{
       
  1447 			CVersitRecurrenceMonthlyByPos::CMonthPosition* monthPos = new(ELeave)CVersitRecurrenceMonthlyByPos::CMonthPosition();
       
  1448 			CleanupStack::PushL(monthPos);
       
  1449 			monthPos->iSign = CVersitRecurrenceMonthlyByPos::CMonthPosition::EWeeksFromStartOfMonth;
       
  1450 			monthPos->iWeekNo = days[ii].WeekInMonth(); // iWeekNo goes from 1-5
       
  1451 		
       
  1452 			monthPos->iArrayOfWeekDays = new(ELeave)CWeekDayArray();
       
  1453 			monthPos->iArrayOfWeekDays->iArray = new(ELeave)CArrayFixFlat<TDay>(1);
       
  1454 			monthPos->iArrayOfWeekDays->iArray->AppendL(days[ii].Day());
       
  1455 			monthPositions->AppendL(monthPos);
       
  1456 			CleanupStack::Pop();		// monthPos;
       
  1457 			}
       
  1458 		// Interval * 12, since we really want is to repeat yearly
       
  1459 		CVersitRecurrence* recurrence = new(ELeave)CVersitRecurrenceMonthlyByPos(aRpt.Interval() * 12, aDuration, aEndTime, monthPositions);
       
  1460 		CleanupStack::Pop();	// monthPositions (owned by recurrence)
       
  1461 		CleanupStack::PopAndDestroy(&days);//close the array
       
  1462 
       
  1463 		return recurrence;
       
  1464 		}
       
  1465 	else
       
  1466 		{
       
  1467 		CArrayFixFlat<TMonth>* monthList = new(ELeave)CArrayFixFlat<TMonth>(1);
       
  1468 		CleanupStack::PushL(monthList);
       
  1469 		monthList->AppendL(aRpt.DtStart().TimeLocalL().DateTime().Month());
       
  1470 		CVersitRecurrence* recurrence = new(ELeave)CVersitRecurrenceYearlyByMonth(aRpt.Interval(), aDuration, aEndTime, monthList);
       
  1471 		CleanupStack::Pop();	// monthList
       
  1472 		return recurrence;
       
  1473 		}
       
  1474 	}
       
  1475 
       
  1476 void CAgendaEntryToVCalConverter::AddRDatePropertyL(CVersitParser& aParser, RArray<TCalTime>& aRdates)
       
  1477 	{
       
  1478 	CArrayPtrFlat<TVersitDateTime>* dateList = new (ELeave) CArrayPtrFlat<TVersitDateTime>(4);
       
  1479 	CleanupStack::PushL(TCleanupItem(ResetAndDestroyArrayOfVersitDateTime,dateList));
       
  1480 	
       
  1481 	const TInt KCount(aRdates.Count());
       
  1482 
       
  1483 	for (TInt i = 0; i < KCount; ++i)
       
  1484 		{
       
  1485 		TCalTime sporadicDate = aRdates[i];
       
  1486 		TDateTime rDate;
       
  1487 		if (iTimeType == TVersitDateTime::EIsUTC)
       
  1488 			{
       
  1489 			rDate=sporadicDate.TimeUtcL().DateTime();
       
  1490 			}
       
  1491 		else
       
  1492 			{
       
  1493 			rDate=sporadicDate.TimeLocalL().DateTime();
       
  1494 			}
       
  1495 		
       
  1496 		// Construct a versit date-time property	
       
  1497 		TVersitDateTime* versitDateTime = new(ELeave) TVersitDateTime(rDate, iTimeType);
       
  1498 		CleanupStack::PushL(versitDateTime);
       
  1499 		versitDateTime->SetFlag(iTimeFlag);	
       
  1500 		dateList->AppendL(versitDateTime);
       
  1501 		CleanupStack::Pop(); // versitDateTime
       
  1502 		}
       
  1503 	
       
  1504 	CParserPropertyValue* value = new(ELeave)CParserPropertyValueMultiDateTime(dateList);
       
  1505 	CleanupStack::Pop(dateList);
       
  1506 	CleanupStack::PushL(value);
       
  1507 	
       
  1508 	CParserProperty* property = CParserProperty::NewL(*value, KVersitTokenRDATE, NULL);
       
  1509 	CleanupStack::Pop(value);
       
  1510 	
       
  1511 	// Add to the parser
       
  1512 	aParser.AddPropertyL(property);//aParser takes the ownership
       
  1513 	}
       
  1514 
       
  1515 // Exception property
       
  1516 //
       
  1517 void CAgendaEntryToVCalConverter::AddRepeatExceptionPropertiesL(CVersitParser& aParser, RArray<TCalTime>& aExceptions)
       
  1518 	{
       
  1519 	CArrayPtrFlat<TVersitDateTime>* dateList = new(ELeave)CArrayPtrFlat<TVersitDateTime>(1);
       
  1520 	CleanupStack::PushL(TCleanupItem(ResetAndDestroyArrayOfVersitDateTime, dateList));
       
  1521 	
       
  1522 	TInt size = aExceptions.Count();
       
  1523 
       
  1524 	for (TInt count=0; count<size; count++)
       
  1525 		{
       
  1526 		TCalTime exception = aExceptions[count];
       
  1527 		
       
  1528 		TDateTime date;
       
  1529 		if (iTimeType == TVersitDateTime::EIsUTC)
       
  1530 			{
       
  1531 			date = exception.TimeUtcL().DateTime();
       
  1532 			}
       
  1533 		else
       
  1534 			{
       
  1535 			date = exception.TimeLocalL().DateTime();
       
  1536 			}
       
  1537 
       
  1538 		// Construct a date-time property
       
  1539 
       
  1540 		TVersitDateTime* versitDateTime = new(ELeave) TVersitDateTime(date, iTimeType);
       
  1541  		versitDateTime->SetFlag(iTimeFlag);
       
  1542  		CleanupStack::PushL(versitDateTime);
       
  1543 		dateList->AppendL(versitDateTime);
       
  1544 		CleanupStack::Pop(); // versitDateTime 
       
  1545 		}
       
  1546 
       
  1547 	CParserPropertyValue* value = new(ELeave)CParserPropertyValueMultiDateTime(dateList);
       
  1548 	CleanupStack::Pop();		// dateList
       
  1549 
       
  1550 	CleanupStack::PushL(value);
       
  1551 	CParserProperty* prop = CParserProperty::NewL(*value, KVersitTokenEXDATE, NULL);
       
  1552 	CleanupStack::Pop(value);
       
  1553 	// Add to the parser
       
  1554 	aParser.AddPropertyL(prop);
       
  1555 	}
       
  1556 
       
  1557 // Creates a stream dictionary, from an embedded store and a stream ID 
       
  1558 //
       
  1559 CStreamDictionary* CAgendaEntryToVCalConverter::CreateDictionaryLC(CEmbeddedStore& aEmbeddedStore, TStreamId& aId)
       
  1560 	{
       
  1561 	CStreamDictionary* dictionary = CStreamDictionary::NewLC();
       
  1562 	RStoreReadStream dicStream;
       
  1563 	dicStream.OpenLC(aEmbeddedStore, aId);
       
  1564 	dicStream >> *dictionary;
       
  1565 	CleanupStack::PopAndDestroy(); //dicStream
       
  1566 	return dictionary;
       
  1567 	}
       
  1568 
       
  1569 
       
  1570 // The vCalendar CATEGORIES property has multiple property values so the property values
       
  1571 // are stored in an array.
       
  1572 //
       
  1573 // The categories of the entry are iterated through, and each category is added as a 
       
  1574 // property value to the array. 
       
  1575 //
       
  1576 void CAgendaEntryToVCalConverter::AddCategoryPropertyL(CVersitParser& aParser, const RPointerArray<CCalCategory>& aCategories)
       
  1577 	{
       
  1578 	CDesCArrayFlat* desArray = new(ELeave) CDesCArrayFlat(4);
       
  1579 	CleanupStack::PushL(desArray);
       
  1580 
       
  1581 	TInt categories = aCategories.Count();
       
  1582 	for (TInt count=0; count<categories; count++)
       
  1583 		{
       
  1584 		CCalCategory* category = aCategories[count];
       
  1585 		switch (category->Category())
       
  1586 			{
       
  1587 		case CCalCategory::ECalAppointment:
       
  1588 				desArray->AppendL(KVCalCategoriesAPPOINTMENT);
       
  1589 				break;
       
  1590 		case CCalCategory::ECalBusiness:
       
  1591 				desArray->AppendL(KVCalCategoriesBUSINESS);
       
  1592 				break;
       
  1593 		case CCalCategory::ECalEducation:
       
  1594 				desArray->AppendL(KVCalCategoriesEDUCATION);
       
  1595 				break;
       
  1596 		case CCalCategory::ECalHoliday:
       
  1597 				desArray->AppendL(KVCalCategoriesHOLIDAY);
       
  1598 				break;
       
  1599 		case CCalCategory::ECalMeeting:
       
  1600 				desArray->AppendL(KVCalCategoriesMEETING);
       
  1601 				break;
       
  1602 		case CCalCategory::ECalMiscellaneous:
       
  1603 				desArray->AppendL(KVCalCategoriesMISCELLANEOUS);
       
  1604 				break;
       
  1605 		case CCalCategory::ECalPersonal:
       
  1606 				desArray->AppendL(KVCalCategoriesPERSONAL);
       
  1607 				break;
       
  1608 		case CCalCategory::ECalPhoneCall:
       
  1609 				desArray->AppendL(KVCalCategoriesPHONECALL);
       
  1610 				break;
       
  1611 		case CCalCategory::ECalSickDay:
       
  1612 				desArray->AppendL(KVCalCategoriesSICKDAY);
       
  1613 				break;
       
  1614 		case CCalCategory::ECalSpecialOccasion:
       
  1615 				desArray->AppendL(KVCalCategoriesSPECIALOCCASION);
       
  1616 				break;
       
  1617 		case CCalCategory::ECalTravel:
       
  1618 				desArray->AppendL(KVCalCategoriesTRAVEL);
       
  1619 				break;
       
  1620 		case CCalCategory::ECalVacation:
       
  1621 				desArray->AppendL(KVCalCategoriesVACATION);
       
  1622 				break;
       
  1623 		case CCalCategory::ECalExtended:
       
  1624 				desArray->AppendL(category->ExtendedCategoryName());
       
  1625 				break;
       
  1626 		default:
       
  1627 				break;
       
  1628 			}
       
  1629 		}
       
  1630 
       
  1631     CParserPropertyValue* value = new (ELeave) CParserPropertyValueCDesCArray(desArray);
       
  1632 	CleanupStack::Pop(); //desArray
       
  1633 	
       
  1634 	CleanupStack::PushL(value); 
       
  1635 	CParserProperty* prop = CParserProperty::NewL(*value, KVersitTokenCATEGORIES, NULL);
       
  1636 	CleanupStack::Pop(value); 
       
  1637 	// Add to the parser
       
  1638 	aParser.AddPropertyL(prop);
       
  1639 	}
       
  1640 
       
  1641 /**
       
  1642  * Checks the status value and adds the appropriate status value to the export list 
       
  1643  * held by the versit parser. 
       
  1644  */
       
  1645 void CAgendaEntryToVCalConverter::AddStatusPropertyL(CVersitParser& aParser, CCalEntry* aEntry)
       
  1646 	{
       
  1647 	switch(aEntry->StatusL())
       
  1648 		{
       
  1649 		case CCalEntry::ETodoInProcess:
       
  1650 		case CCalEntry::EVCalAccepted:
       
  1651 			AddDesPropertyL(aParser, KVCalTokenSTATUS, KVCalStatusACCEPTED);			
       
  1652 			break;
       
  1653 		case CCalEntry::ETodoNeedsAction:
       
  1654 		case CCalEntry::EVCalNeedsAction:
       
  1655 			AddDesPropertyL(aParser, KVCalTokenSTATUS, KVCalStatusNEEDSACTION);			
       
  1656 			break;
       
  1657 		case CCalEntry::ETodoCompleted:
       
  1658 			AddDesPropertyL(aParser, KVCalTokenSTATUS, KVCalStatusCOMPLETED);			
       
  1659 			break;
       
  1660 			
       
  1661 		case CCalEntry::EConfirmed:
       
  1662 			AddDesPropertyL(aParser, KVCalTokenSTATUS, KVCalStatusCONFIRMED);			
       
  1663 			break;
       
  1664 		case CCalEntry::ECancelled:
       
  1665 		case CCalEntry::EVCalDeclined:
       
  1666 			AddDesPropertyL(aParser, KVCalTokenSTATUS, KVCalStatusDECLINED);			
       
  1667 			break;
       
  1668 		case CCalEntry::ETentative:
       
  1669 			AddDesPropertyL(aParser, KVCalTokenSTATUS, KVCalStatusTENTATIVE);			
       
  1670 			break;
       
  1671 		case CCalEntry::EVCalSent:
       
  1672 			AddDesPropertyL(aParser, KVCalTokenSTATUS, KVCalStatusSENT);			
       
  1673 			break;
       
  1674 		case CCalEntry::EVCalDelegated:
       
  1675 			AddDesPropertyL(aParser, KVCalTokenSTATUS, KVCalStatusDELEGATED);			
       
  1676 			break;
       
  1677 		}
       
  1678 
       
  1679 	}
       
  1680 
       
  1681 
       
  1682