pimappsupport/vcardandvcal/src/VCAL.CPP
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Tue, 14 Sep 2010 21:17:03 +0300
branchRCL_3
changeset 31 97232defd20e
parent 30 bd7edf625bdd
permissions -rw-r--r--
Revision: 201033 Kit: 201035

// Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
// All rights reserved.
// This component and the accompanying materials are made available
// under the terms of "Eclipse Public License v1.0"
// which accompanies this distribution, and is available
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
//
// Initial Contributors:
// Nokia Corporation - initial contribution.
//
// Contributors:
//
// Description:
//
 
#include <vcal.h>
#include <vutil.h>
#include <utf.h>
#include <charconv.h>
#include "verror.h"
#include <vstaticutils.h>
#include <vobserv.h>

#include <s32mem.h>


//
// CParserVCal
//

EXPORT_C CParserVCal* CParserVCal::NewL()
/** Allocates and constructs a vCalendar parser.

@return Pointer to the newly created vCalendar parser. */
	{
	CParserVCal* self=new(ELeave) CParserVCal();
	CleanupStack::PushL(self);
	self->ConstructL();
	CleanupStack::Pop();
	return self;	
	}

CParserVCal::CParserVCal() :CVersitParser(ESupportsVersion)
	{
	iDefaultVersion = KVersitTokenVCalVersionNo;
	}

EXPORT_C void CParserVCal::InternalizeL(RReadStream& aStream)
/** Internalises a vCalendar entity from a read stream.

The presence of this function means that the standard templated operator>>() 
(defined in s32strm.h) is available to internalise objects of this class.

@param aStream Stream from which the vCalendar should be internalised. 
@see CVersitParser::InternalizeL() */
	{
	CVersitParser::InternalizeL(aStream);
	}


EXPORT_C void CParserVCal::ExternalizeL(RWriteStream& aStream)
/** Externalises a vCalendar entity (and all sub-entities) to a write stream. 

Sets the entity name to KVersitVarTokenVCALENDAR if it hasn't already been 
set.

Adds a version property to the start of the current entity's array of properties 
if the entity supports this. (If there isn't an array of properties then one 
is made).

The presence of this function means that the standard templated operator<<() 
(defined in s32strm.h) is available to externalise objects of this class.

@param aStream Stream to which the vCalendar should be externalised. 
@see CVersitParser::ExternalizeL() */
	{
	if (!iEntityName)
		SetEntityNameL(KVersitVarTokenVCALENDAR);
	CVersitParser::ExternalizeL(aStream);
	}

EXPORT_C CVersitParser* CParserVCal::MakeEntityL(TInt aEntityUid,HBufC* aEntityName)
// From CVersitParser
	{
	CVersitParser* newEntity = NULL;

	switch (aEntityUid)
		{
		case KVCalEntityUidVEvent:
		case KVCalEntityUidVTodo:
			newEntity=CParserVCalEntity::NewL();
			CleanupStack::PushL(newEntity);
			break;
		default: //Allows it to read (and ignore) additional iCalendar entities
			newEntity = new(ELeave) CVersitParser(ENoVersionProperty);
			CleanupStack::PushL(newEntity);
			newEntity->ConstructL();
			break;
		}
	if (iObserver)
		iObserver->NewParser(newEntity);
	newEntity->SetAutoDetect(iFlags&EUseAutoDetection,iAutoDetectCharSets);
	if (iFlags&EImportSyncML)
		newEntity->SetFlags(EImportSyncML);

	// make child entries aware of default char set
    if (iFlags&EUseDefaultCharSetForAllProperties)
		newEntity->SetFlags(EUseDefaultCharSetForAllProperties);
	newEntity->SetDefaultCharSet(DefaultCharSet());
	
	if (iPlugIn)
		{
		newEntity->SetPlugIn(iPlugIn);
		}

	newEntity->InternalizeL(aEntityName, iLineReader);
	
	CleanupStack::Pop(newEntity);
	return newEntity;
	}

EXPORT_C TUid CParserVCal::RecognizeToken(const TDesC8& aToken) const
// From CVersitParser
/** Returns a UID that identifies a specified token's type.

For example, if aToken contains the property name DAYLIGHT the function returns 
KVersitPropertyDaylightUid. If the token is not recognized as vCalendar-specific, 
the function calls CVersitParser::RecognizeToken(), which recognizes generic Versit 
tokens.

@param aToken The token to be recognized.
@return A defined UID value if the token has been recognized, KVersitTokenUnknownUid 
otherwise. */
	{
	TUid uid = KNullUid;
	TChar firstChar(aToken.Ptr()[0]);
	firstChar=firstChar.GetUpperCase();
	switch (firstChar)
		{
	case 'D':
		if (!aToken.CompareF(KVersitTokenDAYLIGHT))
			uid.iUid = KVersitPropertyDaylightUid;
		break;
	case 'P':
		if (!aToken.CompareF(KVersitTokenPRODID))
			uid.iUid = KVersitPropertyHBufCUid;
		break;
	case 'T':
		if (!aToken.CompareF(KVersitTokenTZ))
			uid.iUid = KVersitPropertyTimeZoneUid;
		break;
	case 'V':
		if (!aToken.CompareF(KVersitTokenVERSION))
			uid.iUid = KVersitTokenVersionUid;
		break;
	default:
		break;
		}
	if (uid == KNullUid)
		return CVersitParser::RecognizeToken(aToken);
	return uid;
	}

EXPORT_C TInt CParserVCal::RecognizeEntityName() const
// From CVersitParser
/** Tests the current value to see if it a vEvent or vTodo entity.

@return KVCalEntityUidVEvent if it is a vEvent entity; KVersitVarTokenVTODO 
if it is a vTodo entity; zero if there is no current property or it has no value. */
	{
	if (iCurrentProperty && iCurrentProperty->Value())
		{
		TPtrC entityName=STATIC_CAST(CParserPropertyValueHBufC*,iCurrentProperty->Value())->Value();
		if (entityName==KVersitVarTokenVEVENT)
			return KVCalEntityUidVEvent;
		else if (entityName==KVersitVarTokenVTODO)
			return KVCalEntityUidVTodo;
		}
	return 0;
	}

EXPORT_C void CParserVCal::Reserved1()
	{}

EXPORT_C void CParserVCal::Reserved2()
	{}

//
// CParserVCalEntity
//

EXPORT_C CParserVCalEntity* CParserVCalEntity::NewL()
/** Allocates and constructs a vCalendar sub-entity parser.

@return A pointer to the new vCalendar sub-entity parser. */
	{
	CParserVCalEntity* self=new(ELeave) CParserVCalEntity();
	CleanupStack::PushL(self);
	self->ConstructL();
	CleanupStack::Pop(self);
	return self;	
	}

CParserVCalEntity::CParserVCalEntity()
	: CRecurrenceParser(EFalse)
/** Constructs a vCalendar sub-entity parser. */
	{}

EXPORT_C CParserVCalEntity::~CParserVCalEntity()
/** The destructor is empty. */
	{
	}

EXPORT_C void CParserVCalEntity::ExternalizeL(RWriteStream& aStream)
/** Externalises a vTodo or vEvent to a write stream.

Sets the entity's name to KVersitVarTokenVEVENT if it hasn't already been 
set.

Converts all date/time values from machine-local into universal time. 

The presence of this function means that the standard templated operator<<() 
(defined in s32strm.h) is available to externalise objects of this class. 

@param aStream Stream to which the vTodo or vEvent should be externalised. */
	{
	if (!iEntityName)
		SetEntityNameL(KVersitVarTokenVEVENT);
	CVersitParser::ExternalizeL(aStream);
	}

EXPORT_C CParserPropertyValue* CParserVCalEntity::MakePropertyValueL(const TUid& aPropertyUid,HBufC16*& aValue)
// From CVersitParser
	{
	if(!aValue && !iLargeDataBuf)
		return NULL;

	switch (aPropertyUid.iUid)
		{
		case KVCalPropertyAlarmUid: // won't be recognized except by subclass
			{
			CVersitAlarm* alarm = MakePropertyValueAlarmL(aValue->Des());
			CleanupStack::PushL(alarm);
			CParserPropertyValue* value = new(ELeave) CParserPropertyValueAlarm(alarm);
			CleanupStack::Pop(alarm);
			return value;
			}
		case KVCalPropertyExtendedAlarmUid: // won't be recognized except by subclass
			{
			CVersitExtendedAlarm* richAlarm = NULL;
			if (aValue)
				{
				richAlarm = MakePropertyValueExtendedAlarmL(aValue->Des());
				}
			else
				{
				richAlarm = MakePropertyValueExtendedAlarmL(*iLargeDataBuf);
				}
			CleanupStack::PushL(richAlarm);
			CParserPropertyValue* value = new(ELeave) CParserPropertyValueExtendedAlarm(richAlarm);
			CleanupStack::Pop(richAlarm);
			return value;
			}
		case KVCalPropertyRecurrenceUid:
			{
			TPtr val=aValue->Des();
			return MakePropertyValueRecurrenceL(val);
			}
		default:
			break;
		};
	return CVersitParser::MakePropertyValueL(aPropertyUid,aValue);
	}

EXPORT_C CVersitAlarm* CParserVCalEntity::MakePropertyValueAlarmL(TPtr16 aAlarmValue)
//Make an Alarm property from stream
	{
	TPtrC8 propName=iCurrentProperty->Name();
	TPtr16 field(NULL,0);

	FindFirstField(field,aAlarmValue);
	TVersitDateTime* runTime=NULL;
	if(field.Length()>0)
		runTime = DecodeDateTimeL(field);
	CleanupStack::PushL(runTime);
	
	FindFirstField(field,aAlarmValue);
	TTime* snoozeTime = NULL;
	if(field.Length()>0)
		snoozeTime = DecodeTimePeriodL(field);
	CleanupStack::PushL(snoozeTime);

	FindFirstField(field,aAlarmValue);
	TInt repeatCount=0;
	if(field.Length()>0)
		Val(field, repeatCount);

	if (propName==KVersitTokenAALARM || propName==KVersitTokenMALARM)
		FindFirstField(field,aAlarmValue);
	else
		field.Zero();
	
	TPtr16 note(NULL,0);
	if (propName!=KVersitTokenAALARM)
		FindFirstField(note,aAlarmValue);

	CVersitAlarm* alarm = CVersitAlarm::NewL(runTime, snoozeTime, repeatCount, field, note);

	CleanupStack::Pop(2,runTime);
	return alarm; //alarm takes ownership of runTime and snoozeTime
	}

/** Create a new extended alarm from a stream.
The MIME type is set to the creating object's MIME type.
The disposition is set to the creating object's disposition.  
@param aAlarmValue a pointer to a buffer containing the assocaited data for the alarm. Should not point to an empty 
descriptor.
@return The newly created extended alarm. */
EXPORT_C CVersitExtendedAlarm* CParserVCalEntity::MakePropertyValueExtendedAlarmL(TPtr16 aAlarmValue)
	{
	TPtrC8 propName=iCurrentProperty->Name();
	TPtr16 field(NULL,0);


	// Note: the presence of this property means that
	// the parameters VALUE and X-CONTENTTYPE should be present; if not
	// present, then INLINE rich data shall be assumed

	TPtrC8 mimeType(NULL,0);
	TPtrC8 dispositionField(NULL,0);

	// content-value-type assumes default is INLINE if parameter not present
	CVersitExtendedAlarm::TDisposition disposition = CVersitExtendedAlarm::EDispositionInline;

	// read in data content-type
	CParserParam* alarmParameter = iCurrentProperty->Param(KVersitTokenCONTENTTYPE);

	if (alarmParameter)
		{
		mimeType.Set(alarmParameter->Value());
		}

	// read in data content-value-type
	alarmParameter = iCurrentProperty->Param(KVersitTokenVALUE);
		
	if (alarmParameter)
		{
		dispositionField.Set(alarmParameter->Value());
		
		// if there is a value, convert from text to enum
		if (dispositionField.Length())
			{
			disposition = DecodeDisposition(dispositionField);
			}
		}
		
	FindRemainingField(field,aAlarmValue);
	CVersitExtendedAlarm* alarm = CVersitExtendedAlarm::NewL(field.Collapse(), mimeType, disposition);

	return alarm; 
	}
	
/** Create a new extended alarm from a buffer.
The MIME type is set to the creating object's MIME type.
The disposition is set to the creating object's disposition. 
@param aAlarmValue a reference to a buffer containing the assocaited data for the alarm. Should not be an empty 
buffer.
@return The newly created extended alarm. */	
EXPORT_C CVersitExtendedAlarm* CParserVCalEntity::MakePropertyValueExtendedAlarmL(CBufSeg& aAlarmValue)
	{
	TPtrC8 propName=iCurrentProperty->Name();
	TPtr16 field(NULL,0);


	// Note: the presence of this property means that
	// the parameters VALUE and CONTENTTYPE should be present; if not
	// present, then MIME rich data shall be assumed

	TPtrC8 mimeType(NULL,0);
	TPtrC8 dispositionField(NULL,0);

	// content-value-type assumes INLINE if parameter not present
	CVersitExtendedAlarm::TDisposition disposition = CVersitExtendedAlarm::EDispositionInline;

	// read in data content-type
	CParserParam* alarmParameter = iCurrentProperty->Param(KVersitTokenCONTENTTYPE);

	if (alarmParameter)
		{
		mimeType.Set(alarmParameter->Value());
		}

	// read in disposition
	alarmParameter = iCurrentProperty->Param(KVersitTokenVALUE);
		
	if (alarmParameter)
		{
		dispositionField.Set(alarmParameter->Value());
		
		// if there is a value, convert from text to enum
		if (dispositionField.Length())
			{
			disposition = DecodeDisposition(dispositionField);
			}
		}
		
	// read in rich data content
	// For this version of MakePropertyValueExtendedAlarmL, we have the 
	// data in a CBufSeg that should already have been decoded from BASE64
	// (assuming everything else works properly). So we need to get it into 
	// a TBufC8
	TInt segSize = aAlarmValue.Size();
	HBufC8* content = HBufC8::NewLC(segSize);
	TPtr8 ptrContent(content->Des());
	aAlarmValue.Read(0, ptrContent, segSize);
	
	CVersitExtendedAlarm* alarm = CVersitExtendedAlarm::NewL(ptrContent, mimeType, disposition);
	CleanupStack::PopAndDestroy(content);
	
	return alarm; 
	}

/** Used to find the type of the content disposition: inline, URL, or unknown.
Converts content-value-type token field to content-value-type enum.
@param aContentDisposition The disposition of the data for the alarm action.
@return decoded disposition type */
EXPORT_C CVersitExtendedAlarm::TDisposition CParserVCalEntity::DecodeDisposition(const TDesC8& aContentDisposition) const
	{
	if (!aContentDisposition.CompareF(KVersitTokenINLINE))
		{
		return CVersitExtendedAlarm::EDispositionInline;
		};
		
	if (!aContentDisposition.CompareF(KVersitTokenURL))
		{
		return CVersitExtendedAlarm::EDispositionUrl;
		};
	
	return CVersitExtendedAlarm::EDispositionUnknown;
	}


/*
 * Try to recognize aToken and return a UID for it. 
 * Call <code>CVersitParser::RecognizeToken()</code>
 * which recognizes generic Versit tokens if the token has not been 
 * recognized in this function 
 *
 * @param     " const TDesC8& aToken "
 *            The token to be recognized
 * @return    " TUid "
 *            a defined UID value if the token has been recognized, 
 *				<code>KVersitTokenUnknownUid</code>, otherwise
 */

EXPORT_C TUid CParserVCalEntity::RecognizeToken(const TDesC8& aToken) const
// From CVersitParser
	{
	TUid uid = KNullUid;
	TChar firstChar(aToken.Ptr()[0]);
	firstChar=firstChar.GetUpperCase();
	switch (firstChar)
		{
	case 'A':	
		if (!aToken.CompareF(KVersitTokenAALARM))
			uid.iUid = KVCalPropertyAlarmUid;
		else if (!aToken.CompareF(KVersitTokenATTENDEE))
			uid.iUid = KVersitPropertyHBufCUid;
		else if (!aToken.CompareF(KVersitTokenATTACH))
			{
			if(iCurrentProperty)
				{//If it is internalising, iCurrentProperty is set
				uid.iUid = KVersitPropertyBinaryUid;//In vCal standard, default value is binary
				CParserParam* valueParam = iCurrentProperty->Param(KVersitTokenVALUE);
				if (valueParam)
					{
					TPtrC8 pParameterValue(valueParam->Value());
					
					if (pParameterValue.CompareF(KVersitTokenINLINE) && pParameterValue.CompareF(KVersitTokenBINARY))
						{//If VALUE isn't specified as INLINE or BINARY, value is text type.
						uid.iUid = KVersitPropertyHBufCUid;			
						}
					}
				}
			}
		break;
	case 'C':
		if (!aToken.CompareF(KVersitTokenCATEGORIES))
			uid.iUid = KVersitPropertyCDesCArrayUid;
		else if (!aToken.CompareF(KVersitTokenCLASS))
			uid.iUid = KVersitPropertyHBufCUid;
		else if (!aToken.CompareF(KVersitTokenCOMPLETED))
			uid.iUid = KVersitPropertyDateTimeUid;
		break;
	case 'D':
		if (!aToken.CompareF(KVersitTokenDALARM))
			uid.iUid = KVCalPropertyAlarmUid;
		else if (!aToken.CompareF(KVersitTokenDCREATED) ||
				!aToken.CompareF(KVersitTokenDTEND) ||
				!aToken.CompareF(KVersitTokenDTSTART) ||
				!aToken.CompareF(KVersitTokenDUE))
			uid.iUid = KVersitPropertyDateTimeUid;
		else if(!aToken.CompareF(KVersitTokenDESCRIPTION))
			uid.iUid = KVersitPropertyHBufCUid;
		break;
	case 'E':
		if (!aToken.CompareF(KVersitTokenEXDATE))
			uid.iUid = KVersitPropertyMultiDateTimeUid;
		else if (!aToken.CompareF(KVersitTokenEXRULE))
			uid.iUid = KVCalPropertyRecurrenceUid;
		break;
	case 'G':
		if (!aToken.CompareF(KVersitTokenGEO))
			uid.iUid = KVersitPropertyHBufCUid;
		break;	
	case 'L':
		if (!aToken.CompareF(KVersitTokenLASTMODIFIED))
			uid.iUid = KVersitPropertyDateTimeUid;
		else if(!aToken.CompareF(KVersitTokenLOCATION))
			uid.iUid = KVersitPropertyHBufCUid;
		break;
	case 'M':
		if (!aToken.CompareF(KVersitTokenMALARM))
			uid.iUid = KVCalPropertyAlarmUid;
		break;
	case 'P':
		if (!aToken.CompareF(KVersitTokenPALARM))
			uid.iUid = KVCalPropertyAlarmUid;
		else if (!aToken.CompareF(KVersitTokenPRIORITY))
			uid.iUid = KVersitPropertyIntUid;
		break;
	case 'R':
		if(!aToken.CompareF(KVersitTokenRDATE))
			uid.iUid = KVersitPropertyMultiDateTimeUid;
		else if (!aToken.CompareF(KVersitTokenRELATEDTO))
			uid.iUid = KVersitPropertyHBufCUid;
		else if (!aToken.CompareF(KVersitTokenRESOURCES))
			uid.iUid = KVersitPropertyCDesCArrayUid;
		else if (!aToken.CompareF(KVersitTokenRNUM))
			uid.iUid = KVersitPropertyIntUid;
		else if (!aToken.CompareF(KVersitTokenRRULE))
			uid.iUid = KVCalPropertyRecurrenceUid;
		break;
	case 'S':
		if (!aToken.CompareF(KVersitTokenSEQUENCE))
			uid.iUid = KVersitPropertyIntUid;
		else if (!aToken.CompareF(KVersitTokenSTATUS) ||
				!aToken.CompareF(KVersitTokenSUMMARY))
			uid.iUid = KVersitPropertyHBufCUid;
		break;
	case 'T':
		if(!aToken.CompareF(KVersitTokenTRANSP))
			uid.iUid = KVersitPropertyIntUid;
		break;
	case 'U':
		if (!aToken.CompareF(KVersitTokenURL) ||
			!aToken.CompareF(KVersitTokenUID))
		uid.iUid = KVersitPropertyHBufCUid;
		break;
	case 'X':
		if (!aToken.CompareF(KVersitTokenXRECURRENCEID) ||
			!aToken.CompareF(KVersitTokenXDTSTAMP))
			{
			uid.iUid = KVersitPropertyDateTimeUid;
			}
		else if (!aToken.CompareF(KVersitTokenXALARM))
			{
			uid.iUid = KVCalPropertyExtendedAlarmUid;
			}
		else if ( !aToken.CompareF( KVersitTokenXLOCALUID ) ||
                  !aToken.CompareF( KVersitExtUserInt ) )       
		    {
			uid.iUid = KVersitPropertyIntUid;
		    }
		break;
		}
	if (uid == KNullUid)
		return CVersitParser::RecognizeToken(aToken);
	return uid;
	}

EXPORT_C void CParserVCalEntity::Reserved1()
	{}

EXPORT_C void CParserVCalEntity::Reserved2()
	{}


//
// CVersitAlarm
//

CVersitAlarm::CVersitAlarm(TInt aRepeatCount)
	: iRepeatCount(aRepeatCount)
	{
	}

void CVersitAlarm::ConstructL(const TDesC& aAudioContent, const TDesC& aNote, TVersitDateTime* aRunTime, TTime* aSnoozeTime)
	{
	if (aAudioContent.Size())
		{
		iAudioContent = aAudioContent.AllocL();
		}
	if (aNote.Size())
		{
		iNote = aNote.AllocL();
		}
	iRunTime = aRunTime;
	iSnoozeTime = aSnoozeTime;
	}

EXPORT_C CVersitAlarm* CVersitAlarm::NewL(TVersitDateTime* aRunTime, TTime* aSnoozeTime, TInt aRepeatCount, const TDesC& aAudioContent, const TDesC& aNote)
/** Allocates and constructs a new alarm.

Ownership of aRunTime and aSnoozeTime is taken in the end.

@param aRunTime Pointer to the alarm time. 
@param aSnoozeTime Pointer to the snooze time (may be NULL). 
@param aRepeatCount The repeat count. 
@param aAudioContent A binary buffer containing the sound data. May be an empty 
descriptor. 
@param aNote A descriptor containing text to display when the alarm is executing. 
May be an empty descriptor. 
@return Pointer to the newly created alarm. */
	{
	CVersitAlarm* self = new(ELeave) CVersitAlarm(aRepeatCount);
	CleanupStack::PushL(self);
	self->ConstructL(aAudioContent, aNote, aRunTime, aSnoozeTime);
	CleanupStack::Pop(self);
	return self;	
	}

EXPORT_C CVersitAlarm::~CVersitAlarm()
/** Frees all resources owned by the alarm, prior to its destruction. */
	{
	delete iRunTime;
	delete iSnoozeTime;
	delete iAudioContent;
	delete iNote;
	}

CVersitExtendedAlarm::CVersitExtendedAlarm()
	{
	}

void CVersitExtendedAlarm::ConstructL(const TDesC8& aContent, const TDesC8& aContentMimeType, CVersitExtendedAlarm::TDisposition aContentDisposition) 
	{
	if (aContent.Size())
		{
		iContent = aContent.AllocL();		
		}
	else
		{
		iContent = NULL;
		}
		
	if (aContentMimeType.Size())
		{
		iMimeType = aContentMimeType.AllocL();
		}
	else
		{
		iMimeType = NULL;
		}
	iDisposition = aContentDisposition;
	}

/** Allocates and constructs a new extended alarm (X-EPOCALARM).
@param aContent A binary buffer containing the assocaited data for the alarm. Should not be empty 
descriptor.
@param aContentMimeType The MIME type of the data describing the action for the alarm.  
@param aContentDisposition The disposition of the data for the alarm action.
@return Pointer to the newly created extended alarm. */
EXPORT_C CVersitExtendedAlarm* CVersitExtendedAlarm::NewL(const TDesC8& aContent, const TDesC8& aContentMimeType,
						   			CVersitExtendedAlarm::TDisposition aContentDisposition)
	{
	CVersitExtendedAlarm * self = new(ELeave) CVersitExtendedAlarm();
	CleanupStack::PushL(self);
	self->ConstructL(aContent, aContentMimeType, aContentDisposition);
	CleanupStack::Pop(self);
	return self;	
	}

EXPORT_C CVersitExtendedAlarm::~CVersitExtendedAlarm()
/** Frees all resources owned by the alarm, prior to its destruction. */
	{
	delete iContent;
	delete iMimeType;
	}

//
// CParserPropertyValueAlarm
//
EXPORT_C CParserPropertyValueAlarm::CParserPropertyValueAlarm(CVersitAlarm* aValue)
: CParserTimePropertyValue(TUid::Uid(KVCalPropertyAlarmUid))
	,iValue(aValue)
/** Constructs a new alarm property value with a pointer to a CVersitAlarm.

@param aValue Pointer to the alarm. The property value takes ownership of 
the pointer. */
	{}


EXPORT_C CParserPropertyValueAlarm::~CParserPropertyValueAlarm()
/** Frees all resources owned by the property value, prior to its destruction. */
	{
	delete iValue;
	}

EXPORT_C void CParserPropertyValueAlarm::ConvertAllDateTimesToUTCL(const TTimeIntervalSeconds& aIncrement, const CVersitDaylight* aDaylight)
/** Converts the alarm time into universal time.

The date/time of the alarm is checked against the daylight saving information 
provided in aDaylight. If it falls inside the daylight saving period then 
the daylight saving offset is subtracted from the time to convert it to universal 
time. Otherwise aIncrement is added to the date/time of the alarm to convert 
it to universal time.

Note that the daylight savings offset will adjust the time both for the daylight 
saving and for the time zone.

The function has no effect if the value is already stored as universal time.

If aDaylight is a NULL pointer then aIncrement is used.

@param aIncrement A time interval in seconds which represents the negative 
of the time zone of the originating machine. For instance, if the time zone 
is +04:30, aIncrement should be set to -04:30.
@param aDaylight Pointer to the specification for daylight saving. If the alarm's 
time value is within the period for daylight saving, the value is modified 
by the daylight saving offset (which accounts for both the time zone and daylight 
saving rule). 
@deprecated since 9.1
*/
	{
	if (iValue && iValue->iRunTime && (iValue->iRunTime->iRelativeTime != TVersitDateTime::EIsUTC) && !iValue->iRunTime->IsFlagSet(TVersitDateTime::EExportLeaveAsLocalTime))
		{
		ConvertDateTime(&iValue->iRunTime->iDateTime,aIncrement, aDaylight);
		iValue->iRunTime->iRelativeTime = TVersitDateTime::EIsUTC;		
		}
	}	

EXPORT_C void CParserPropertyValueAlarm::ConvertAllUTCDateTimesToMachineLocalL(const TTimeIntervalSeconds& aIncrement)
/** Converts the alarm time to machine-local time. 

This involves adjusting the alarm's date/time by the offset in aIncrement.

The function has no effect if the value is already stored as machine-local 
time.

@param aIncrement A time interval which represents the number of seconds which 
is to be added to the date/time value. This should normally be the universal 
time offset for the machine's locale. 
@deprecated since 9.1
*/
	{
	if (iValue && iValue->iRunTime && (iValue->iRunTime->iRelativeTime == TVersitDateTime::EIsUTC))
		{
		ConvertDateTime(&iValue->iRunTime->iDateTime, aIncrement,NULL);
		iValue->iRunTime->iRelativeTime = TVersitDateTime::EIsMachineLocal;
		}
	}

EXPORT_C void CParserPropertyValueAlarm::ExternalizeL(RWriteStream& aStream,const Versit::TEncodingAndCharset& aEncodingCharset,TInt aLengthOutput)
	// From CParserProperty
/** Externalises the alarm property value into aStream.

@param aStream Stream to which the value should be externalised.
@param aEncodingCharset Contains the character set and encoding into which the 
property value should be converted.
@param aLengthOutput The amount of text that has been outputted on the line 
so far, which needs to be taken into account when calculating if and where 
any line break should occur. */
	{
	if (!iValue)
		return;

	TInt bufLen=64;		//This should cover the Date/Time, Duration, Repeat Count and semi colons
	if (iValue->iAudioContent)
		bufLen+=iValue->iAudioContent->Length();
	if (iValue->iNote)
		bufLen+=iValue->iNote->Length();
	HBufC* outputStringBuf=HBufC::NewLC(bufLen);
	TPtr outputString=outputStringBuf->Des();
	TBuf8<KVersitDefaultBufferSize> buf;
	if (iValue->iRunTime)
		{
		EncodeVersitDateTimeL(buf,*iValue->iRunTime);
		Append(outputString,buf);
		}
	outputString.Append(KVersitTokenSemiColonUnicode);
	if (iValue->iSnoozeTime)
		{
		EncodeTimePeriodL(buf,*iValue->iSnoozeTime);
		Append(outputString,buf);
		}
	outputString.Append(KVersitTokenSemiColonUnicode);
	__ASSERT_DEBUG(iValue->iRepeatCount < 100000, User::Invariant());
	if(iValue->iRepeatCount>0)
		{
		outputString.AppendNum(iValue->iRepeatCount);
		}
	outputString.Append(KVersitTokenSemiColonUnicode);

	if (iValue->iAudioContent)
		{
		outputString.Append(*iValue->iAudioContent);
		if (iValue->iNote)
			outputString.Append(KVersitTokenSemiColonUnicode);
		}
	if (iValue->iNote)
		outputString.Append(*iValue->iNote);
	FoldAndWriteValueToStreamL(aStream,outputString,aEncodingCharset,aLengthOutput);
	CleanupStack::PopAndDestroy(outputStringBuf);
	}

EXPORT_C TBool CParserPropertyValueAlarm::IsAsciiCharacterSetSufficient()
/** Tests whether the property value can be represented using the ASCII character 
set.

@return ETrue if the property value can be represented using the ASCII character 
set. If not, EFalse. */
	{
	if	(!iValue)
		return ETrue;
	if (iValue->iAudioContent && !VersitUtils::DescriptorContainsOnlySevenBitCharacters(*iValue->iAudioContent))
		return EFalse;
	if (iValue->iNote && !VersitUtils::DescriptorContainsOnlySevenBitCharacters(*iValue->iNote))
		return EFalse;
	return ETrue;
	}

//
// CParserPropertyValueExtendedAlarm. 
//
EXPORT_C CParserPropertyValueExtendedAlarm::CParserPropertyValueExtendedAlarm(CVersitExtendedAlarm* aValue)
: CParserTimePropertyValue(TUid::Uid(KVCalPropertyExtendedAlarmUid))
	,iValue(aValue)
/** Constructs a new extended alarm property value with a pointer to a CVersitExtendedAlarm.

@param aValue Pointer to the alarm. The property value takes ownership of 
the pointer. */
	{}

EXPORT_C CParserPropertyValueExtendedAlarm::~CParserPropertyValueExtendedAlarm()
/** Frees all resources owned by the property value, prior to its destruction. */
	{
	delete iValue;
	}

EXPORT_C void CParserPropertyValueExtendedAlarm::ConvertAllDateTimesToUTCL(const TTimeIntervalSeconds& /* aIncrement */, const CVersitDaylight* /* aDaylight */)
/** Converts the extended alarm time into universal time.

@param aIncrement A time interval in seconds which represents the negative 
of the time zone of the originating machine. For instance, if the time zone 
is +04:30, aIncrement should be set to -04:30.
@param aDaylight Pointer to the specification for daylight saving. If the alarm's 
time value is within the period for daylight saving, the value is modified 
by the daylight saving offset (which accounts for both the time zone and daylight 
saving rule). 
@deprecated since 9.1
*/
	{
	}	

EXPORT_C void CParserPropertyValueExtendedAlarm::ConvertAllUTCDateTimesToMachineLocalL(const TTimeIntervalSeconds& /*aIncrement */)
/** Converts the extended alarm time to machine-local time.

@param aIncrement A time interval which represents the number of seconds which 
is to be added to the date/time value. This should normally be the universal 
time offset for the machine's locale. 
@deprecated since 9.1
*/
	{
	}

EXPORT_C void CParserPropertyValueExtendedAlarm::ExternalizeL(RWriteStream& aStream,const Versit::TEncodingAndCharset& aEncodingCharset,TInt aLengthOutput)
// From CParserProperty
/** Externalises the extended alarm property value into aStream.

@param aStream Stream to which the value should be externalised.
@param aEncodingCharset Contains the character set and encoding into which the 
property value should be converted.
@param aLengthOutput The amount of text that has been outputted on the line 
so far, which needs to be taken into account when calculating if and where 
any line break should occur. */
	{
	if (!iValue)
		{
		return;
		}
	// There are two encoding possibilities for this value. If it is a URL, then we expand the 8 bit string,
	// which we know is US ASCII into Unicode and append it. If it is INLINE data, then we must encode it as 
	// 64 bit data
	switch (iValue->iDisposition)
		{
		case CVersitExtendedAlarm::EDispositionUrl:
			ExternalizeUrlL(aStream, aEncodingCharset, aLengthOutput);
			break;
		case CVersitExtendedAlarm::EDispositionInline:
		default:  //intentional fall through, we'll treat any unknown as INLINE data
			ExternalizeInlineL(aStream, aEncodingCharset, aLengthOutput);
			break;
		}
	
	}

void CParserPropertyValueExtendedAlarm::ExternalizeUrlL(RWriteStream& aStream,const Versit::TEncodingAndCharset& aEncodingCharset,TInt aLengthOutput)
	{
	TInt bufLen = 0;
	if (iValue->iContent)
		{
		bufLen+=iValue->iContent->Size();		
		}
	
	HBufC* outputStringBuf=HBufC::NewLC(bufLen);

	TPtr outputString=outputStringBuf->Des();
		
	HBufC* bufferUrl = NULL;

	CVersitUnicodeUtils* vUtils = new(ELeave)CVersitUnicodeUtils();
	vUtils->CreateConverterL();

	bufferUrl = vUtils->WidenL(*(iValue->iContent));

	TPtrC desUrl(bufferUrl->Des());
	CleanupStack::PushL(bufferUrl);

	outputString.Append(desUrl);

	FoldAndWriteValueToStreamL(aStream,outputString,aEncodingCharset,aLengthOutput);
	
	CleanupStack::PopAndDestroy(2,outputStringBuf);
	
	}

const TInt KBase64MaxLineLength = 64; // chars

void CParserPropertyValueExtendedAlarm::ExternalizeInlineL(RWriteStream& aStream,const Versit::TEncodingAndCharset& /*aEncodingCharset*/,TInt /*aLengthOutput*/)
	{
	if (iValue->iContent)
		{
		const TInt length = iValue->iContent->Size();
		if (length >0)
			{
			CBufSeg* target = CBufSeg::NewL(length);
			CleanupStack::PushL(target);

			//get the Data Content into a usable buffer
			CBufSeg* source = CBufSeg::NewL(length+1);
			source->Reset();
			source->InsertL(0, *(iValue->iContent));
			source->Compress();
			CleanupStack::PushL(source);

			
			//Do the BASE64 Encoding
			RBufReadStream readStream;
			readStream.Open(*source);
			VersitUtils::ConArcEncodeL(readStream, *target, 
						VersitUtils::ConArcEncodingUid(Versit::EBase64Encoding));
			readStream.Close();

			// make sure the  line lengths are appropriate
			VersitUtils::WrapLinesL(*target, KBase64MaxLineLength);

			// write to output stream
			TInt pos=0;
			TInt len=target->Size();
			while (pos < len)
				{
				TPtr8 ptr = target->Ptr(pos);
				aStream.WriteL(ptr);
				pos+=ptr.Length();
				}
			CleanupStack::PopAndDestroy(2, target);
			}
		}
	aStream.WriteL(KVersitTokenCRLF);
	}

	
EXPORT_C TBool CParserPropertyValueExtendedAlarm::IsAsciiCharacterSetSufficient()
/** Tests whether the property value can be represented using the ASCII character 
set.

@return ETrue if the property value can be represented using the ASCII character 
set. If not, EFalse. */
	{
	if (!iValue)
		{
		return ETrue;
		}
	
	if (!iValue->iContent)
		{
		return ETrue;
		}
	
	if (iValue->iDisposition == CVersitExtendedAlarm::EDispositionUrl)
		{
		return ETrue;
		}
		
	return EFalse;
	}