diff -r 000000000000 -r f979ecb2b13e pimappservices/calendarvcalplugin/src/agmvcali.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pimappservices/calendarvcalplugin/src/agmvcali.cpp Tue Feb 02 10:12:19 2010 +0200 @@ -0,0 +1,1993 @@ +// Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// + + +#include +#include +#include +#include +#include +#include "agnversit.h" +#include +#include //Conversion between local and UTC times +#include +#include +#include +#include +#include + +#include "agmvcal.h" + +const TInt KCountDigits = 8; +_LIT(KDateStringFormat, "%F%D%M%Y%H%T%S%C"); // locale-independent formatting DDMMYYHHMMSSUUUUUU (day,month,year,hour,minute,second,usec +_LIT(KVersitTokenMailTo,"MAILTO:"); + +HBufC* AgnConvertUtil::EncodeL(const TDesC& aText,TUid aConversion) + { + HBufC8* text=HBufC8::NewLC(aText.Length()*2); + TPtr8 ptr = text->Des(); + TInt i; + for (i=0; i < aText.Length(); i++) + { + ptr.Append(aText[i] & 0x00FF); + ptr.Append((aText[i] >> 8) & 0x00FF); + } + CCnaConverterList* convList=CCnaConverterList::NewLC(); + CConverterBase* conv = convList->NewConverterL(aConversion); + if (!conv) + { + CleanupStack::PopAndDestroy(); // convList + User::Leave(KErrNotSupported); + } + CleanupStack::PushL(conv); + CBufFlat* decodeBuffer = CBufFlat::NewL(256); + CleanupStack::PushL(decodeBuffer); + CBufFlat* encodedBuffer = CBufFlat::NewL(256); + CleanupStack::PushL(encodedBuffer); + decodeBuffer->InsertL(0,ptr); + RBufReadStream readStream; + RBufWriteStream writeStream; + readStream.Open(*decodeBuffer); + writeStream.Open(*encodedBuffer); + conv->ConvertObjectL(readStream, writeStream); + readStream.Close(); + TInt size=encodedBuffer->Size(); + HBufC* writeBuf=HBufC::NewLC(size); + TPtr resulttext = writeBuf->Des(); + for(i = 0; i < (size - 1); i += 2) + { + resulttext.Append((encodedBuffer->Ptr(0)[i + 1] << 8) | + encodedBuffer->Ptr(0)[i]); + } + + writeStream.CommitL(); + writeStream.Close(); + CleanupStack::Pop(writeBuf); // writebuf + CleanupStack::PopAndDestroy(2,decodeBuffer); // buffers + CleanupStack::PopAndDestroy(2,convList); //conv+convList + CleanupStack::PopAndDestroy(text); //text + return (writeBuf); + } + +// This method imports a vCalendar entity from aParser and returns a pointer to a CAgnEntry +// if successful or NULL if it wasn't possible to import the vCalendar. It reads the +// relevant properties from aParser entity and builds up a corresponding agenda entry. +// It allows to import vCal file without Summary and Description fields +void CVCalToAgendaEntryConverter::ImportVCalL(CVersitParser& aParser, RPointerArray& aEntryArray) + { + CCalEntry::TType entryType = GetEntryTypeL(aParser); + + // Group Scheduling Data + + //Import UID + HBufC* guid16 = ImportDesPropertyL(aParser, KVersitTokenUID); + + if (!guid16) // non cal entry + { + // create our a UID based on the current time (UTC, microsecond precision) + TTime now; + now.UniversalTime(); + TBuf dateString; + now.FormatL(dateString,KDateStringFormat); + + TInt threeDidgit=Math::Random() % 1000; + dateString.Append(threeDidgit); + + guid16 = dateString.AllocL(); + } + + CleanupStack::PushL(guid16); + + // the UID is stored as an 8-bit descriptor, so convert from 16-bit to 8-bit + HBufC8* guid8= CnvUtfConverter::ConvertFromUnicodeToUtf8L(guid16->Des()); + CleanupStack::PopAndDestroy(guid16); + CleanupStack::PushL(guid8); + + // Import Sequence Number + TInt seqNumber; + + // if no sequence number + if (!ImportIntegerPropertyL(aParser, KVersitTokenSEQUENCE, seqNumber)) + { + seqNumber = 0; + } + + // Import Method + CCalEntry::TMethod methodStatus(CCalEntry::EMethodNone); + HBufC* method = ImportDesPropertyL(aParser, KVersitTokenXMETHOD); + + if (method) + { + CleanupStack::PushL(method); + if (*method == KVCalTokenMethodStatusENone) + { + methodStatus = CCalEntry::EMethodNone; + } + else if (*method == KVCalTokenMethodStatusEPublish) + { + methodStatus = CCalEntry::EMethodPublish; + } + else if (*method == KVCalTokenMethodStatusERequest) + { + methodStatus = CCalEntry::EMethodRequest; + } + else if (*method == KVCalTokenMethodStatusEReply) + { + methodStatus = CCalEntry::EMethodReply; + } + else if (*method == KVCalTokenMethodStatusEAdd) + { + methodStatus = CCalEntry::EMethodAdd; + } + else if (*method == KVCalTokenMethodStatusECancel) + { + methodStatus = CCalEntry::EMethodCancel; + } + else if (*method == KVCalTokenMethodStatusERefresh) + { + methodStatus = CCalEntry::EMethodRefresh; + } + else if (*method == KVCalTokenMethodStatusECounter) + { + methodStatus = CCalEntry::EMethodCounter; + } + else if (*method == KVCalTokenMethodStatusEDeclineCounter) + { + methodStatus = CCalEntry::EMethodDeclineCounter; + } + else + { + // do nothing if method is invalid - it will be None by default + } + + + CleanupStack::PopAndDestroy(method); + } + + // Import X-Recurrence-Id + TVersitDateTime::TRelativeTime relativeTime = TVersitDateTime::EIsUTC; + TTime recurrenceId; + TBool isRecurrenceIdPresent = ImportDateTimePropertyL(aParser, KVersitTokenXRECURRENCEID, recurrenceId, relativeTime); + if (!isRecurrenceIdPresent) + { + iEntry = CCalEntry::NewL(entryType,guid8, methodStatus, seqNumber); + } + else + { + TCalTime caltime; + if(GetTimeModeL(aParser) == TCalTime::EFloating) + { + caltime.SetTimeLocalFloatingL(recurrenceId); + } + else + { + caltime.SetTimeUtcL(recurrenceId); + } + + iEntry = CCalEntry::NewL(entryType,guid8, methodStatus, seqNumber, caltime, CalCommon::EThisOnly); + } + + CleanupStack::Pop(guid8); // ownership was passed to calGSData + // Fill in the entry description from the SUMMARY property + // If this doesn't exist, use the DESCRIPTION property, and if this + // doesn't exist, return a NULL entry + + // get properties but don't take ownership of the elements of the array + CArrayPtr* properties = aParser.PropertyL(KVersitTokenSUMMARY, TUid::Uid(KVersitPropertyHBufCUid), EFalse); + + if (!properties) + { + // get properties but don't take ownership of the elements of the array + properties = aParser.PropertyL(KVersitTokenDESCRIPTION, TUid::Uid(KVersitPropertyHBufCUid), EFalse); + } + CleanupStack::PushL(properties); + + // Use the value found from the Summary/Description + // Both Summary and Description are not found in imported vCal file + //then insert empty enties for summary and description + // these empty entries will be descarded while exporting vCal file + TPtrC summary; + if (properties) + { + summary.Set(static_cast((*properties)[0]->Value())->Value()); + } + + HBufC* summaryBuf = AgnConvertUtil::EncodeL(summary,KUidTextToEtextNoTrim); + CleanupStack::PushL(summaryBuf); + if (summaryBuf) + { + iEntry->SetSummaryL(*summaryBuf); + } + CleanupStack::PopAndDestroy(summaryBuf); + + HBufC* description =ImportDesPropertyL(aParser,KVersitTokenDESCRIPTION); + CleanupStack::PushL(description); + if (description != NULL) + { + iEntry->SetDescriptionL(*description); // Takes ownership + } + CleanupStack::PopAndDestroy(description); + + TBool validEntry = EFalse; + if (entryType == CCalEntry::ETodo) + { + validEntry = ImportTodoPropertiesL(aParser); + } + else + { + validEntry = ImportEventPropertiesL(aParser); + } + + if (!validEntry) + { + CleanupStack::PopAndDestroy(properties); + delete iEntry; + iEntry = NULL; + return; + } + + // Import CLASS property + HBufC* property=ImportDesPropertyL(aParser, KVersitTokenCLASS); + if (property) + { + CleanupStack::PushL(property); + if (*property == KVCalTokenPUBLIC) + iEntry->SetReplicationStatusL(CCalEntry::EOpen); + else if (*property == KVCalTokenPRIVATE) + iEntry->SetReplicationStatusL(CCalEntry::EPrivate); + else if (*property == KVCalTokenCONFIDENTIAL) + iEntry->SetReplicationStatusL(CCalEntry::ERestricted); + CleanupStack::PopAndDestroy(property); + } + // Import LOCATION property + property=ImportDesPropertyL(aParser, KVersitTokenLOCATION); + if (property) + { + CleanupStack::PushL(property); + iEntry->SetLocationL(*property); + CleanupStack::PopAndDestroy(property); + } + // Import DTSTAMP + TTime timeProperty; + if (ImportDateTimePropertyL(aParser, KVersitTokenXDTSTAMP, timeProperty, relativeTime)) + { + TCalTime caltimeProperty; + caltimeProperty.SetTimeUtcL(timeProperty); + iEntry->SetDTStampL(caltimeProperty); + } + + // Attendee property + ImportAttendeePropertiesL(aParser, KVersitTokenATTENDEE); + + // Categories property + ImportCategoriesPropertyL(aParser, KVersitTokenCATEGORIES); + + + + TInt localId; + if (ImportIntegerPropertyL(aParser, KVersitTokenXLOCALUID, localId)) + { + iEntry->SetLocalUidL(localId); + } + + // Additional stuff to comply with Versit Specs 1.0 + // All entries have a priority not just ToDo's + // Todo Functionality merged into this code block + TInt priority; + if (ImportIntegerPropertyL(aParser, KVersitTokenPRIORITY, priority)) + { + iEntry->SetPriorityL(priority); + } + + // All entries have a status - will default to Needs Action if cannot be read + CCalEntry::TStatus entryStatus=CCalEntry::ENullStatus; + ImportStatusPropertyL(aParser, entryStatus); + //Now sync completed and ECompleted status to keep entry consistenty + if(entryType==CCalEntry::ETodo && (iEntry->CompletedTimeL().TimeUtcL()) != Time::NullTTime()) + { + iEntry->SetCompletedL(ETrue, iEntry->CompletedTimeL()); + } + iEntry->SetStatusL(entryStatus); + + //Get last changed date from vcal + if (ImportDateTimePropertyL(aParser, KVersitTokenLASTMODIFIED, timeProperty, relativeTime)) + { + if (iTzZone && (relativeTime == TVersitDateTime::EIsVCardLocal)) + { + iTzZone->ConvertToUtcL(timeProperty); + } + TCalTime lastModifiedDate; + lastModifiedDate.SetTimeUtcL(timeProperty); + iEntry->SetLastModifiedDateL(lastModifiedDate); + } + else + { + iEntry->SetLastModifiedDateL(); //set changed date to now + } + + TInt transp; + if (ImportIntegerPropertyL(aParser, KVersitTokenTRANSP, transp)) + { + iEntry->SetTimeTransparencyL(static_cast(transp)); + } + + ImportAttachmentPropertyL(aParser); + + // Import GEO + HBufC* geoString=ImportDesPropertyL(aParser,KVersitTokenGEO); + + if (geoString != NULL) + { + CleanupStack::PushL(geoString); + // Determine the position of the delimiter for extraction of the geo latitude and longitude values + TInt delimiterPos = geoString->Locate(KVersitTokenCommaVal); + + if(delimiterPos!=KErrNotFound) + { + // Extract the latitude + TLex geoLatitudeLex(geoString->Left(delimiterPos)); + // Extract the latitude by excluding the delimiter + TLex geoLongitudeLex(geoString->Right(geoString->Length()-(delimiterPos+1))); + + TReal geoLatitude; + TReal geoLongitude; + + if((geoLatitudeLex.Val(geoLatitude)==KErrNone) && (geoLongitudeLex.Val(geoLongitude)==KErrNone)) + { + CCalGeoValue* importedGeoValue=CCalGeoValue::NewL(); + CleanupStack::PushL(importedGeoValue); + TRAPD(err, importedGeoValue->SetLatLongL(geoLatitude,geoLongitude)); + if(err==KErrNone) + { + iEntry->SetGeoValueL(*importedGeoValue); + } + CleanupStack::PopAndDestroy(importedGeoValue); + } + } + CleanupStack::PopAndDestroy(geoString); + } + + CleanupStack::PopAndDestroy(properties); + aEntryArray.AppendL(iEntry); // takes ownership of entry + iEntry = NULL; + } + +CVCalToAgendaEntryConverter::~CVCalToAgendaEntryConverter() + { + delete iEntry; + delete iTzZone; + } + +void CVCalToAgendaEntryConverter::SetTzConverter(RTz* aTzConverter) + { + iTzConverter = aTzConverter; + } + +void CVCalToAgendaEntryConverter::SetTzRules(CTzRules* aTzZone) + { + // this function should only ever be called once so this shouldn't be needed + if (iTzZone) + { + delete iTzZone; + iTzZone = NULL; + } + iTzZone = aTzZone; + } + +TCalTime::TTimeMode CVCalToAgendaEntryConverter::GetTimeModeL(CVersitParser& aParser) + { + TTime dummyTime; + TVersitDateTime::TRelativeTime relativeTime; + + if ( ! ImportDateTimePropertyL(aParser, KVersitTokenDTSTART, dummyTime, relativeTime)) + { + if ( ! ImportDateTimePropertyL(aParser, KVersitTokenDTEND, dummyTime, relativeTime)) + { + if ( ! ImportDateTimePropertyL(aParser, KVersitTokenDUE, dummyTime, relativeTime)) + { + // no time + relativeTime = TVersitDateTime::EIsUTC; + } + } + } + + if (iTzZone || relativeTime == TVersitDateTime::EIsUTC) + { + return TCalTime::EFixedUtc; + } + return TCalTime::EFloating; + } + +// Try and find out which Epoc Agenda entry type this belongs to. +// At the moment, relies on having an 'X-EPOCAGENDAENTRYTYPE' field, and defaults to a appointment +// type if this isn't present. +// Maybe some heuristics should be used to try and ascertain which entry type is most appropriate +// e.g. if the entry has a yearly repeat, then maybe it should be an anniversary type. +// +// A call to this function resets iVcalTokenTypeReminder flag (unless the vCal entry is actually a Reminder). +// +CCalEntry::TType CVCalToAgendaEntryConverter::GetEntryTypeL(CVersitParser& aParser) + { + // If the entry type is a Todo, return immediately + if (aParser.EntityName()==KVersitVarTokenVTODO) + { + return CCalEntry::ETodo; + } + + // get properties but don't take ownership of the elements of the array + CArrayPtr* properties = aParser.PropertyL(KVCalToken8XDASHENTRYTYPE, TUid::Uid(KVersitPropertyHBufCUid), EFalse); + if (properties) + { + TPtrC type = static_cast((*properties)[0]->Value())->Value(); + delete properties; + + if (type == KVCalTokenTypeAPPT) + { + return CCalEntry::EAppt; + } + + if (type == KVCalTokenTypeEVENT) + { + return CCalEntry::EEvent; + } + + if (type == KVCalTokenTypeANNIV) + { + return CCalEntry::EAnniv; + } + + if (type == KVCalTokenTypeTODO) + { + return CCalEntry::ETodo; + } + + if (type == KVCalTokenTypeREMINDER) + { + return CCalEntry::EReminder; + } + + } + + // return an appointment as default type + return (CCalEntry::EAppt); + } + +TBool CVCalToAgendaEntryConverter::IsValidTime(const TTime& aTime) + { + if (aTime < TCalTime::MinTime() || aTime > TCalTime::MaxTime()) + { + return EFalse; + } + return ETrue; + } + +// Import Recurrence Dates property +// +void CVCalToAgendaEntryConverter::ImportRDatePropertyL(CVersitParser& aParser, const TDesC8& aToken) + { + // get properties but don't take ownership of the elements of the array + CArrayPtr* properties = aParser.PropertyL(aToken, TUid::Uid(KVersitPropertyMultiDateTimeUid), EFalse); + + if (properties) + { + CleanupStack::PushL(properties); + CArrayPtr* rDates = static_cast((*properties)[0]->Value())->Value(); + + if (rDates) + { + RArraycalrdates; + CleanupClosePushL(calrdates); + const TInt KSize = rDates->Count(); + for (TInt count = 0; count < KSize; ++count) + { + TVersitDateTime* time = (*rDates)[count]; + TTime timeProperty(time->iDateTime); + + if (IsValidTime(timeProperty)) + { + TVersitDateTime::TRelativeTime relativeTime = time->iRelativeTime; + if (iTzZone && (relativeTime == TVersitDateTime::EIsVCardLocal)) + { + //Convert to utc time using imported TZ rules + iTzZone->ConvertToUtcL(timeProperty); + relativeTime = TVersitDateTime::EIsUTC; + } + + TCalTime calrdate; + if (relativeTime == TVersitDateTime::EIsVCardLocal) + { + calrdate.SetTimeLocalFloatingL(timeProperty); + } + else + { + __ASSERT_DEBUG(relativeTime == TVersitDateTime::EIsUTC, Panic(EAgnVersitPanicWrongTimeType)); + calrdate.SetTimeUtcL(timeProperty); //assume time as UTC for release build + } + calrdates.Append(calrdate); + } + } + iEntry->SetRDatesL(calrdates); + CleanupStack::PopAndDestroy();//close RArray + } + CleanupStack::PopAndDestroy(properties); + } + + } + +// Import the start and end dates of the vCalendar +// This method returns EFalse if there is no start date or end date, or if the start date +// is after the end date. If the start date is missing but an end date is present, the +// start date is set to the end date. If the end date is missing but there is a start +// date, the end date is set to the start date. +// +TBool CVCalToAgendaEntryConverter::GetStartAndEndDatesL(CVersitParser& aParser, TTime& aStartDate, TTime& aEndDate, TVersitDateTime::TRelativeTime& aRelativeTime) + { + TBool startValid = ETrue; + TBool endValid = ETrue; + + if (!ImportDateTimePropertyL(aParser, KVersitTokenDTSTART, aStartDate,aRelativeTime)) + { + startValid = EFalse; + } + + TVersitDateTime::TRelativeTime relativeTime; + + if (!ImportDateTimePropertyL(aParser, KVersitTokenDTEND, aEndDate, relativeTime)) + { + endValid = EFalse; + } + + if (!startValid && !endValid) + { + // Neither times exist, so return Invalid Entry + return EFalse; + } + + if (startValid && !endValid) + { + // Start time but no end time + aEndDate = aStartDate; + } + else if (!startValid && endValid) + { + // End time but no start time + aStartDate = aEndDate; + aRelativeTime = relativeTime; + } + + if (aStartDate>aEndDate) + return EFalse; + + return ETrue; + } + +// Import appointment properties +// +TBool CVCalToAgendaEntryConverter::ImportEventPropertiesL(CVersitParser& aParser) + { + TTime startDate; + TTime endDate; + TVersitDateTime::TRelativeTime relativeTime; + if (!GetStartAndEndDatesL(aParser, startDate, endDate, relativeTime)) + { + return EFalse; + } + + if(iEntry->EntryTypeL()==CCalEntry::EReminder) + { + endDate = startDate; + } + + TCalTime caltimeStart; + TCalTime caltimeEnd; + if (relativeTime == TVersitDateTime::EIsVCardLocal) + { + caltimeStart.SetTimeLocalFloatingL(startDate); + caltimeEnd.SetTimeLocalFloatingL(endDate); + } + else + { + __ASSERT_DEBUG(relativeTime==TVersitDateTime::EIsUTC, Panic(EAgnVersitPanicWrongTimeType)); + caltimeStart.SetTimeUtcL(startDate); //assume time as UTC for release build + caltimeEnd.SetTimeUtcL(endDate); //assume time as UTC for release build + } + + if (startDate > endDate && endDate != Time::NullTTime()) + { + return EFalse; + } + iEntry->SetStartAndEndTimeL(caltimeStart,caltimeEnd); + + // Attempt to import alarm/repeat properties + ImportRepeatPropertyL(aParser, KVersitTokenRRULE, startDate, relativeTime); + ImportAlarmPropertyL(aParser, startDate, relativeTime); + return ETrue; + } + +// +TBool CVCalToAgendaEntryConverter::ImportTodoPropertiesL(CVersitParser& aParser) + { + TVersitDateTime::TRelativeTime relativeTime;//EIsUTC is the default + TTime startDate = Time::NullTTime(); + TTime endDate = Time::NullTTime(); + + if (!ImportDateTimePropertyL(aParser, KVersitTokenDUE, endDate, relativeTime)) + { + if (!ImportDateTimePropertyL(aParser, KVersitTokenDTEND, endDate, relativeTime)) + { + endDate = Time::NullTTime(); + } + } + + if ( ! ImportDateTimePropertyL(aParser, KVersitTokenDTSTART, startDate, relativeTime)) + { + startDate = endDate; + } + + if (startDate > endDate && endDate != Time::NullTTime()) + { + return EFalse; + } + + + + if (endDate == Time::NullTTime()) + { + endDate = startDate; + } + else if (startDate == Time::NullTTime() || startDate > endDate) + { + startDate = endDate; + } + + TTime completedDate; + if (ImportDateTimePropertyL(aParser, KVCalTokenCOMPLETED,completedDate, relativeTime)) + { + TCalTime calcompletedDate; + calcompletedDate.SetTimeUtcL(completedDate); + iEntry->SetCompletedL(ETrue, calcompletedDate); + } + + TCalTime caltimeStart; + TCalTime caltimeEnd; + + if (relativeTime == TVersitDateTime::EIsUTC) + { + caltimeStart.SetTimeUtcL(startDate); + caltimeEnd.SetTimeUtcL(endDate); + } + else + { + caltimeStart.SetTimeLocalFloatingL(startDate); + caltimeEnd.SetTimeLocalFloatingL(endDate); + } + iEntry->SetStartAndEndTimeL(caltimeStart,caltimeEnd); + +// Attempt to import alarm properties + ImportAlarmPropertyL(aParser, endDate, relativeTime); + +// Attempt to import repeat properties + ImportRepeatPropertyL(aParser, KVersitTokenRRULE, endDate, relativeTime); + + return ETrue; + } + +// Import a date/time +// This method returns true if a date/time exists and is within the standard agenda date range +// If it doesn't exist or the date isn't valid this method returns EFalse. +// +TBool CVCalToAgendaEntryConverter::ImportDateTimePropertyL(CVersitParser& aParser, const TDesC8& aToken, TTime& aValue, TVersitDateTime::TRelativeTime& aRelativeTime) + { + // get properties but don't take ownership of the elements of the array + CArrayPtr* properties = aParser.PropertyL(aToken, TUid::Uid(KVersitPropertyDateTimeUid), EFalse); + + if (properties) + { + CleanupStack::PushL(properties); + TVersitDateTime* time = static_cast((*properties)[0]->Value())->Value(); + aValue = TTime(time->iDateTime); + TCalTime calTime; + if (IsValidTime(aValue)) + { + aRelativeTime = time->iRelativeTime; + if (iTzZone && ( aRelativeTime== TVersitDateTime::EIsVCardLocal)) + { + //Convert to utc time using imported TZ rules + iTzZone->ConvertToUtcL(aValue); + aRelativeTime = TVersitDateTime::EIsUTC; + } + CleanupStack::PopAndDestroy(properties); + return ETrue; + } + + CleanupStack::PopAndDestroy(properties); + } + + return EFalse; + } + +// Import an integer property +// +TBool CVCalToAgendaEntryConverter::ImportIntegerPropertyL(CVersitParser& aParser, const TDesC8& aToken, TInt& aValue) + { + // get properties but don't take ownership of the elements of the array + CArrayPtr* properties = aParser.PropertyL(aToken, TUid::Uid(KVersitPropertyIntUid), EFalse); + + if (properties) + { + aValue = static_cast((*properties)[0]->Value())->Value(); + delete properties; + return ETrue; + } + else + { + // If there is no property available, return EFalse to signal that this property doesn't exist + return EFalse; + } + } + +// Import a descriptor property +// +HBufC* CVCalToAgendaEntryConverter::ImportDesPropertyL(CVersitParser& aParser, const TDesC8& aToken) + { + // get properties but don't take ownership of the elements of the array + CArrayPtr* properties = aParser.PropertyL(aToken, TUid::Uid(KVersitPropertyHBufCUid), EFalse); + // If there is no property available, return NULL to signal that this property doesn't exist + HBufC* aHBufC = NULL; + + if (properties) + { + CleanupStack::PushL(properties); + CParserPropertyValueHBufC* propertyValue = static_cast((*properties)[0]->Value()); + aHBufC=propertyValue->TakeValueOwnership(); + CleanupStack::PopAndDestroy(properties); + if (aHBufC) + { + CleanupStack::PushL(aHBufC); + HBufC* temp=AgnConvertUtil::EncodeL(aHBufC->Des(),KUidTextToEtextNoTrim); + CleanupStack::PopAndDestroy(aHBufC); + aHBufC=temp; + } + } + return aHBufC; + } + +// Import an alarm property +// +TBool CVCalToAgendaEntryConverter::ImportAlarmPropertyL(CVersitParser& aParser, TTime& aEntryTime, TVersitDateTime::TRelativeTime& aRelativeTime) + { + // Get properties but don't take ownership of the elements of the array. + // Check if there is an AALARM first. + CArrayPtr* properties = aParser.PropertyL(KVersitTokenAALARM, + TUid::Uid(KVCalPropertyAlarmUid), EFalse); + + // If there is no AALARM then try with a DALARM. They are treated the same. + if (!properties) + { + properties = aParser.PropertyL(KVersitTokenDALARM, + TUid::Uid(KVCalPropertyAlarmUid), EFalse); + } + + if (properties) + { + CleanupStack::PushL(properties); + CParserPropertyValueAlarm* alarmProperty = static_cast((*properties)[0]->Value()); + CVersitAlarm* alarm = alarmProperty->Value(); + if (!alarm->iRunTime) + { + CleanupStack::PopAndDestroy(properties); + return EFalse; + } + TTime alarmTime = TTime(alarm->iRunTime->iDateTime); + TVersitDateTime::TRelativeTime relativeTime = alarm->iRunTime->iRelativeTime; + if (iTzZone && (alarm->iRunTime->iRelativeTime == TVersitDateTime::EIsVCardLocal)) + { + //Convert to utc time using imported TZ rules + iTzZone->ConvertToUtcL(alarmTime); + relativeTime = TVersitDateTime::EIsUTC; + } + + if(aEntryTime==Time::NullTTime()) + {//It is only possible if it is a undated doto entry, in which, the due time should be set before the alarm time is set + __ASSERT_DEBUG(iEntry->EntryTypeL()==CCalEntry::ETodo, Panic(EAgnVersitWrongAttribute)); + + aEntryTime = alarmTime; + aRelativeTime = relativeTime; + + TCalTime endTime; + if (relativeTime==TVersitDateTime::EIsVCardLocal || relativeTime==TVersitDateTime::EIsMachineLocal) + { + endTime.SetTimeLocalFloatingL(aEntryTime); + } + else + { + __ASSERT_DEBUG(relativeTime==TVersitDateTime::EIsUTC, Panic(EAgnVersitPanicWrongTimeType)); + endTime.SetTimeUtcL(aEntryTime); + } + iEntry->SetStartAndEndTimeL(iEntry->StartTimeL(), endTime); + } + + + TTimeIntervalMinutes minutes; + aEntryTime.MinutesFrom(alarmTime, minutes); + + CCalAlarm* calalarm = CCalAlarm::NewL(); + CleanupStack::PushL(calalarm); + + const TInt KMinValidAlarmTime = -1440; // can have an alarm up to one day after an event + if(minutes.Int() >= KMinValidAlarmTime) + { + calalarm->SetTimeOffset(minutes); + } + else + { + // Alarm run-time is not valid - return EFalse since there is no valid alarm property + CleanupStack::PopAndDestroy(2,properties); + return EFalse; + } + + HBufC* soundName=NULL; + // Check if the sound type is an Epoc Sound + CParserParam* param = ((*properties)[0])->Param(KVCalToken8TYPE); + if (param) + { + if (param->Value() == KVCalValue8EPOCSOUND) + { + soundName = alarm->iAudioContent; + if (soundName) + { + calalarm->SetAlarmSoundNameL(*soundName); + } + } + } + + TBool hasExtenedAlarm = ImportExtendedAlarmPropertyL(calalarm, aParser, KVersitTokenXALARM); + + if (!soundName && !hasExtenedAlarm) + { + TBaSystemSoundType type(KSystemSoundAlarmUID); + TBaSystemSoundInfo info; + RFs s; + User::LeaveIfError(s.Connect()); + BaSystemSound::GetSound(s,type,info); //don't check err as info will always be filled in + s.Close(); + calalarm->SetAlarmSoundNameL(info.FileName()); + } + + iEntry->SetAlarmL(calalarm); + + CleanupStack::PopAndDestroy(2,properties); + return ETrue; + } + else + { + // If there is no property available, return EFalse to signal that this property doesn't exist + return EFalse; + } + } + +// Import an extended alarm property (X-EPOCALARM) - containing the rich alarm data; it does not import the +// timing control parameters because the AALARM property would have been imported and written to the agenda +// model entry; no need to re-populate the timing controls since both audio sound and extended alarm share the +// same timing controls. The audio alarm timing controls override the rich alarm's timing controls (not used). +TBool CVCalToAgendaEntryConverter::ImportExtendedAlarmPropertyL(CCalAlarm* aAlarm, CVersitParser& aParser, const TDesC8& aToken ) + { + // get properties but don't take ownership of the elements of the array + CArrayPtr* properties = aParser.PropertyL(aToken, TUid::Uid(KVCalPropertyExtendedAlarmUid), EFalse); + + if (properties) + { + CleanupStack::PushL(properties); + CParserPropertyValueExtendedAlarm* extendedAlarmProperty = static_cast((*properties)[0]->Value()); + CVersitExtendedAlarm* extendedAlarm = extendedAlarmProperty->Value(); + // get properties but don't take ownership of the elements of the array + CArrayPtr* audioAlarmProperties = aParser.PropertyL(KVersitTokenAALARM, TUid::Uid(KVCalPropertyAlarmUid), EFalse); + + if (extendedAlarm && audioAlarmProperties) + { + CleanupStack::PushL(audioAlarmProperties); + + // Convert X-EPOC-ALARM to alarm content and add to entry + CCalContent* alarmAction = CCalContent::NewL(); + CleanupStack::PushL(alarmAction); + HBufC8* content = NULL; + if (extendedAlarm->iContent != NULL) + { + content = extendedAlarm->iContent->AllocL(); + CleanupStack::PushL(content); + } + HBufC8* mimeType = NULL; + if (extendedAlarm->iMimeType != NULL) + { + mimeType = extendedAlarm->iMimeType->AllocL(); + CleanupStack::PushL(mimeType); + } + alarmAction->SetContentL(content, mimeType, static_cast(extendedAlarm->iDisposition)); //Takes ownership of content & mimeType + + if (mimeType != NULL) + { + CleanupStack::Pop(mimeType); + } + if (content != NULL) + { + CleanupStack::Pop(content); + } + aAlarm->SetAlarmAction(alarmAction); // takes ownership of alarmAction + CleanupStack::Pop(alarmAction); + + CleanupStack::PopAndDestroy(audioAlarmProperties); + CleanupStack::PopAndDestroy(properties); + return ETrue; + } + else + { + // If there is no rich alarm available, return EFalse to signal that this property doesn't exist + CleanupStack::PopAndDestroy(properties); + return EFalse; + } + } + else + { + // If there is no property available, return EFalse to signal that this property doesn't exist + return EFalse; + } + } + +void CVCalToAgendaEntryConverter::ImportAttachmentPropertyL(CVersitParser& aParser) + { + // get properties but don't take ownership of the elements of the array + CArrayPtr* properties = aParser.PropertyL(KVersitTokenATTACH, KNullUid, EFalse);//We past KNullUid since we don't know whether it is a binary or URI - versit will have the informantion. + + if (!properties) + { + return; + } + + CleanupStack::PushL(properties); + const TInt KCount = properties->Count(); // no. of attachments + for (TInt i = 0; i < KCount; ++i) + { + CParserParam* attachValueType = (*properties)[i]->Param(KVersitTokenVALUE); + TPtrC8 valueType; + if(attachValueType && attachValueType->Value().Length() > 0) + { + valueType.Set(attachValueType->Value()); + } + + CCalAttachment* attachment = NULL; + if(!attachValueType || valueType == KVersitTokenINLINE || valueType == KVersitTokenBINARY) + { + CParserPropertyValueBinary* attachValueBinary = static_cast((*properties)[i]->Value()); + if (attachValueBinary) + { + CBufSeg* binary=(CBufSeg*)(attachValueBinary->Value()); + const TInt KBinaryLength = binary->Size(); + if(KBinaryLength>0) + { + HBufC8* bufValue = HBufC8::NewLC(KBinaryLength); + TPtr8 pBufValue = bufValue->Des(); + binary->Read(0, pBufValue, KBinaryLength); + attachment = CCalAttachment::NewFileL(bufValue); + CleanupStack::Pop(bufValue); + } + } + } + else + { + CParserPropertyValueHBufC* attachValueDes = static_cast((*properties)[i]->Value()); + if (attachValueDes && attachValueDes->Value().Length() > 0) + { + TPtrC des16Value = attachValueDes->Value(); + HBufC8* buf8Value = HBufC8::NewLC(des16Value.Length()); + buf8Value->Des().Copy(des16Value); + if ( ! valueType.Compare(KVCalContentValueContentId) || ! valueType.Compare(KVCalContentValueContentIdShort)) + { + attachment = CCalAttachment::NewFileByContentIdL(*buf8Value); + } + else + { + attachment = CCalAttachment::NewUriL(*buf8Value); + } + CleanupStack::PopAndDestroy(buf8Value); + } + } + if (attachment) + { + CleanupStack::PushL(attachment); + //Set paramenters + CParserParam* mimeTypeParam = (*properties)[i]->Param(KVersitAttachMimeType); + if(mimeTypeParam && mimeTypeParam->Value().Length() > 0) + { + attachment->SetMimeTypeL(mimeTypeParam->Value()); + } + + CParserParam* attachName = (*properties)[i]->Param(KVersitAttachLabel); + if(attachName && attachName->Value().Length() > 0) + { + TPtrC8 attachnameNarror = attachName->Value(); + HBufC* attachname16 = HBufC::NewLC(attachnameNarror.Length()); + TPtr pattachname16 = attachname16->Des(); + User::LeaveIfError(CnvUtfConverter::ConvertToUnicodeFromUtf8(pattachname16, attachnameNarror)); + attachment->SetLabelL(*attachname16); + CleanupStack::PopAndDestroy(attachname16); + } + + CParserParam* attachDate = (*properties)[i]->Param(KVCalAttachFileDate); + if(attachDate && attachment->FileAttachment() && attachDate->Value().Length() > 0) + { + TPtrC8 pAttachDate = attachDate->Value(); + TBufdate16; + date16.Copy(pAttachDate); + TVersitDateTime* datetime = aParser.DecodeDateTimeL(date16); + CleanupStack::PushL(datetime); + TTime fileTtime(datetime->iDateTime); + if(iTzZone && datetime->iRelativeTime != TVersitDateTime::EIsUTC) + { + iTzZone->ConvertToUtcL(fileTtime); + } + attachment->FileAttachment()->SetLastModifiedTimeUtc(fileTtime); + CleanupStack::PopAndDestroy(datetime); + } + iEntry->AddAttachmentL(*attachment); + CleanupStack::Pop(attachment); + } + }// for loop + + CleanupStack::PopAndDestroy(properties); + } + +// Import repeat property +// +void CVCalToAgendaEntryConverter::ImportRepeatPropertyL(CVersitParser& aParser, const TDesC8& aToken, const TTime& aRepeatTime, TVersitDateTime::TRelativeTime aRelativeTime) + { + if (aRepeatTime != Time::NullTTime()) + { + ImportRepeatRuleL(aParser, aToken, aRepeatTime, aRelativeTime); + + //check for RDates - this operation must be carried out after any rule has been imported + ImportRDatePropertyL(aParser, KVersitTokenRDATE); + + ImportRepeatExceptionPropertiesL(aParser, KVersitTokenEXDATE); + } + } + +// Repeat end date behaviour +// - If the repeat end date is within the agenda range it is set +// - If the repeat end date is greater than the maximum agenda date then the entry is set to repeat forever +// - If the repeat end date is less than the minimum agenda date then the entry is made non-repeating +// +// Current implementation follows these policies: +// 1) time mode of repeat always matches time mode of the entry: +// if entry's time mode is EFloating, then repeat's time mode is EFloating; +// if entry's time mode is EFixedUTC, then repeat's time mode is EFixedTimeZone. +// 2) time format of DTSTART determines time mode of the entry. +// if DTSTART is not valid, then time format of DTEND/DUE is used. +// +void CVCalToAgendaEntryConverter::ImportRepeatRuleL(CVersitParser& aParser, const TDesC8& aToken, const TTime& aStartDate, TVersitDateTime::TRelativeTime aRelativeTime) + { + // get properties but don't take ownership of the elements of the array + CArrayPtr* properties = aParser.PropertyL(aToken, TUid::Uid(KVCalPropertyRecurrenceUid), EFalse); + if (properties) + { + CleanupStack::PushL(properties); + CVersitRecurrence* recurrence = static_cast((*properties)[0]->Value())->Value(); + if (!recurrence) + { + CleanupStack::PopAndDestroy(properties); + return; + } + + //Importing the start time of the repeating + //startTimeLoc & startTimeUtc will be same if it is floating entry or when iTzZone is not specified. + TTime startTimeLoc = aStartDate; + TTime startTimeUtc = aStartDate; + TBool isFloatingEntry = (!iTzZone && aRelativeTime != TVersitDateTime::EIsUTC); + + if (iTzZone) + { + if (aRelativeTime == TVersitDateTime::EIsUTC) + { + iTzZone->ConvertToLocalL(startTimeLoc); + } + else + { + iTzZone->ConvertToUtcL(startTimeUtc); + } + } + + TCalRRule repeat; + TCalTime calstart; + + if (isFloatingEntry) + { + calstart.SetTimeLocalFloatingL(startTimeLoc); + } + else + { + calstart.SetTimeUtcL(startTimeUtc); + } + + repeat.SetDtStart(calstart); + + //Importing the recurrence of the repeating + switch(recurrence->iRepeatType) + { + case CVersitRecurrence::EDaily: + repeat.SetType(TCalRRule::EDaily); + break; + case CVersitRecurrence::EYearlyByMonth: + repeat.SetType(TCalRRule::EYearly); + break; + case CVersitRecurrence::EWeekly: + ImportWeeklyRepeatPropertiesL(static_cast(recurrence), repeat, startTimeLoc.DayNoInWeek()); + break; + case CVersitRecurrence::EMonthlyByPos: + ImportMonthlyByPosRepeatPropertiesL(static_cast(recurrence), repeat, startTimeLoc); + break; + case CVersitRecurrence::EMonthlyByDay: + ImportMonthlyByDayRepeatPropertiesL(static_cast(recurrence), repeat, startTimeLoc.DayNoInMonth()); + break; + case CVersitRecurrence::EYearlyByDay: + // Not supported, since an event cannot repeat on the 100th day of a year, etc + // -- intentional drop through to default case -- + default: + // Don't understand the repeat type, + // so cleanup and exit + CleanupStack::PopAndDestroy(properties); + return; + } + + // We allow only TVersitDateTime::EIsUTC and EIsVCardLocal, because + // EIsMachineLocal is never returned by parser,and EIsCorrect is not used + __ASSERT_DEBUG(aRelativeTime == TVersitDateTime::EIsUTC || + aRelativeTime == TVersitDateTime::EIsVCardLocal, Panic(EAgnVersitPanicWrongTimeType)); + + //Importing the until time of the repeating + TVersitDateTime* rptEndDate = recurrence->iEndDate; + TCalTime calUntil; + TBool isUntilTimeValid = EFalse; + + if(!rptEndDate && recurrence->iDuration == 0) + {//If no until time has been set and the count is 0, the repeating is forever + calUntil.SetTimeUtcL(TCalTime::MaxTime()); + repeat.SetCount(0); + isUntilTimeValid = ETrue; + } + else if(rptEndDate) + {//Set the until time + TDateTime untilDateTimeLoc = rptEndDate->iDateTime; + //Adjust the local repeating until time according to the local start time + if (!isFloatingEntry && iTzZone && rptEndDate->iRelativeTime == TVersitDateTime::EIsUTC) + { + TTime time(untilDateTimeLoc);//create a temp object of TTime + iTzZone->ConvertToLocalL(time);//convert the UTC until to local + untilDateTimeLoc = time.DateTime();// set the local until + } + + untilDateTimeLoc.SetHour(startTimeLoc.DateTime().Hour()); + untilDateTimeLoc.SetMinute(startTimeLoc.DateTime().Minute()); + untilDateTimeLoc.SetSecond(startTimeLoc.DateTime().Second()); + untilDateTimeLoc.SetMicroSecond(0); + isUntilTimeValid = ETrue; + + if (isFloatingEntry) + { + if (TTime(untilDateTimeLoc) < TCalTime::MinTime()) + { + isUntilTimeValid = EFalse; + } + else + { + if (TTime(untilDateTimeLoc) > TCalTime::MaxTime()) + { + untilDateTimeLoc = TCalTime::MaxTime().DateTime(); + } + calUntil.SetTimeLocalFloatingL(untilDateTimeLoc); + } + } + else + { + TTime untilUtc(untilDateTimeLoc); + if (iTzZone) + { + iTzZone->ConvertToUtcL(untilUtc); + } + + if (untilUtc < TCalTime::MinTime()) + { + isUntilTimeValid = EFalse; + } + + else + { + if (untilUtc > TCalTime::MaxTime()) + { + untilUtc = TCalTime::MaxTime().DateTime(); + } + calUntil.SetTimeUtcL(untilUtc); + } + } + + } + + if (isUntilTimeValid) + { + repeat.SetUntil(calUntil); + } + + if (recurrence->iDuration>0) + { + TInt instancesPerRepeat = CalculateInstancesPerRepeatL(repeat); + + TInt count = recurrence->iDuration * instancesPerRepeat; + + // it is possible to have both count and untiltime in an imported vcal + // we will import the shortest repeat of the two dates + if(repeat.Until().TimeLocalL() != Time::NullTTime()) + { + TCalTime countUntilTime = iEntry->FindRptUntilTimeL(count); + + if(countUntilTime.TimeLocalL() < repeat.Until().TimeLocalL()) + { + // if until time is already set, it will be replaced + repeat.SetUntil(countUntilTime); + } + } + else + { + repeat.SetCount(count); + } + + isUntilTimeValid = ETrue; + } + + if (isUntilTimeValid) + { + //Importing the interval + repeat.SetInterval(recurrence->iInterval); + + //Importing the repeating count + + TRAPD(err, iEntry->SetRRuleL(repeat)); + if (err != KErrArgument && err != KErrNotSupported) + { + User::LeaveIfError(err); + } + + TCalRRule ruleGot; + if(iEntry->GetRRuleL(ruleGot)) + { + if(iTzZone) + { + // If there are DAYLIGHT and TZ properties, use these rules when converting + // repeating dates to UTC for storage, otherwise the time zone device will be used + // instead. + iEntry->SetTzRulesL(*iTzZone); + } + } + } + + CleanupStack::PopAndDestroy(properties); + } + } + +TInt CVCalToAgendaEntryConverter::CalculateInstancesPerRepeatL(const TCalRRule& aRRule) const + { + TInt instancesPerRepeat = 1; + switch (aRRule.Type()) + { + case TCalRRule::EWeekly: + { + RArray wkdays; + CleanupClosePushL(wkdays); + aRRule.GetByDayL(wkdays); + instancesPerRepeat = wkdays.Count(); + CleanupStack::PopAndDestroy(&wkdays); + } + break; + case TCalRRule::EMonthly: + { + RArray monthdays; + CleanupClosePushL(monthdays); + aRRule.GetByDayL(monthdays); + instancesPerRepeat = monthdays.Count(); + CleanupStack::PopAndDestroy(&monthdays); + if (instancesPerRepeat == 0) + { + RArray monthdates; + CleanupClosePushL(monthdates); + aRRule.GetByMonthDayL(monthdates); + instancesPerRepeat = monthdates.Count(); + CleanupStack::PopAndDestroy(&monthdates); + } + } + break; + case TCalRRule::EYearly: + { + RArray yrdays; + CleanupClosePushL(yrdays); + aRRule.GetByDayL(yrdays); + instancesPerRepeat = yrdays.Count(); + CleanupStack::PopAndDestroy(&yrdays); + if (instancesPerRepeat == 0) + { + RArray yrmonths; + CleanupClosePushL(yrmonths); + aRRule.GetByMonthL(yrmonths); + instancesPerRepeat = yrmonths.Count(); + CleanupStack::PopAndDestroy(&yrmonths); + } + } + break; + case TCalRRule::EDaily: + default: + // do nothing + break; + } + if (instancesPerRepeat == 0) + { + instancesPerRepeat = 1; + } + return instancesPerRepeat; + } + +void CVCalToAgendaEntryConverter::ImportWeeklyRepeatPropertiesL(CVersitRecurrenceWeekly* aRepeat, TCalRRule& aRpt, TDay aDefaultDayOfWeek) + { + aRpt.SetType(TCalRRule::EWeekly); + CWeekDayArray* weekdayArray = aRepeat->iArrayOfWeekDayOccurrences; + RArray daysinweek; + CleanupClosePushL(daysinweek); + + if (weekdayArray) + { + CArrayFix* dayList = weekdayArray->iArray; + + TInt size = dayList->Count(); + for (TInt count=0; count* dayList = aRepeat->iArrayOfOccurrencesInDaysFromStartOfMonth; + CArrayFix* endDayList = aRepeat->iArrayOfOccurrencesInDaysFromEndOfMonth; + RArray monthdays; + CleanupClosePushL(monthdays); + if (dayList) + { + TInt size = dayList->Count(); + for (TInt count=0; count= 0 && day <= 30) + { + monthdays.AppendL(day); + } + } + } + else if(endDayList) + { + TInt size = endDayList->Count(); + for (TInt count=0;countiMonthPositions->Count(); + RArray dayofmonthArray; + CleanupClosePushL(dayofmonthArray); + + if (size > 0) + { + for (TInt count=0; count* dayList = (*(aRepeat->iMonthPositions))[count]->iArrayOfWeekDays->iArray; + TInt weekNo = (*(aRepeat->iMonthPositions))[count]->iWeekNo; + TInt sign = (*(aRepeat->iMonthPositions))[count]->iSign; + + if (weekNo == 1 && sign == CVersitRecurrenceMonthlyByPos::CMonthPosition::EWeeksFromEndOfMonth) + { + // If the poisiton is in the last week of the month + weekNo = -1; + } + else if (weekNo > 5 || sign == CVersitRecurrenceMonthlyByPos::CMonthPosition::EWeeksFromEndOfMonth) + { + // We can't model this setting, so ignore it + continue; + } + + // Now set the days for the week setting + TInt dayCount = dayList->Count(); + for (TInt ii=0; ii* properties = aParser.PropertyL(aToken, TUid::Uid(KVersitPropertyMultiDateTimeUid), EFalse); + + if (properties) + { + CleanupStack::PushL(properties); + CArrayPtr* exDates = static_cast((*properties)[0]->Value())->Value(); + if (exDates) + { + TInt size = exDates->Count(); + RArray exceptionlist; + CleanupClosePushL(exceptionlist); + + for (TInt count=0; countiDateTime); + if (IsValidTime(timeProperty)) + { + TVersitDateTime::TRelativeTime relativeTime = time->iRelativeTime; + + if (iTzZone && (relativeTime == TVersitDateTime::EIsVCardLocal)) + { + //Convert to utc time + iTzZone->ConvertToUtcL(timeProperty); + relativeTime = TVersitDateTime::EIsUTC; + } + + if (iEntry->StartTimeL().TimeMode() == TCalTime::EFloating) + { + exception.SetTimeLocalFloatingL(timeProperty); + } + else + { + // the EXDATE is floating but the entry is UTC + exception.SetTimeUtcL(timeProperty); + } + + exceptionlist.AppendL(exception); + } + } + iEntry->SetExceptionDatesL(exceptionlist); + CleanupStack::PopAndDestroy();//close the RArray + } + CleanupStack::PopAndDestroy(properties); + } + } + +void CVCalToAgendaEntryConverter::ImportAttendeePropertiesL(CVersitParser& aParser, const TDesC8& aToken) + { + TBool mailto; + TInt propLen; + // get properties but don't take ownership of the elements of the array + CArrayPtr* properties = aParser.PropertyL(aToken, TUid::Uid(KVersitPropertyHBufCUid), EFalse); + CleanupStack::PushL(properties); + + if (properties) + { + TInt size = properties->Count(); // no. of attendees + for (TInt count=0; count((*properties)[count]->Value()); + + mailto = EFalse; + propLen = 0; + if (attendeeProperty->Value().FindF(KVersitTokenMailTo) == 0) + { + mailto = ETrue; + propLen = attendeeProperty->Value().Length() - KVersitTokenMailTo().Length(); + } + + CParserParam* sentBy = (*properties)[count]->Param(KICalAttendeeSentBy8); + + CCalAttendee* attendee = NULL; + CCalUser* user = NULL; + CParserParam* role = (*properties)[count]->Param(KVCalAttendee8ROLE); + + const TDesC& KAttendeeProperty = mailto ? attendeeProperty->Value().Right(propLen) : attendeeProperty->Value(); + if (sentBy) + { + HBufC* sentByDesc = sentBy->ValueL(); + CleanupStack::PushL(sentByDesc); + if (role && role->Value() == KVCalAttendeeRole8ORGANIZER) + { + user = CCalUser::NewL(KAttendeeProperty, *sentByDesc); + iEntry->SetOrganizerL(user); + } + else + { + attendee = CCalAttendee::NewL(KAttendeeProperty, *sentByDesc); + iEntry->AddAttendeeL(attendee); + } + CleanupStack::PopAndDestroy(sentByDesc); + } + else + { + if (role && role->Value() == KVCalAttendeeRole8ORGANIZER) + { + user = CCalUser::NewL(KAttendeeProperty); + iEntry->SetOrganizerL(user); + } + else + { + attendee = CCalAttendee::NewL(KAttendeeProperty); + iEntry->AddAttendeeL(attendee); + } + } + + if (attendee) + { + CParserParam* calrole = (*properties)[count]->Param(KICalAttendeeCalRole8); + TBool roleSet = EFalse; + // Check for iCal roles values + if (calrole) + { + if(calrole->Value() == KICalAttendeeCalRole8CHAIR) + { + attendee->SetRoleL(CCalAttendee::EChair); + roleSet = ETrue; + } + else if(calrole->Value() == KICalAttendeeCalRole8REQUIRED) + { + attendee->SetRoleL(CCalAttendee::EReqParticipant); + roleSet = ETrue; + } + else if(calrole->Value() == KICalAttendeeCalRole8OPTIONAL) + { + attendee->SetRoleL(CCalAttendee::EOptParticipant); + roleSet = ETrue; + } + else if(calrole->Value() == KICalAttendeeCalRole8NONPARTICIPANT) + { + attendee->SetRoleL(CCalAttendee::ENonParticipant); + roleSet = ETrue; + } + } + if ( ! roleSet && role) + { + if (role->Value() == KVCalAttendeeRole8OWNER) + { + attendee->SetRoleL(CCalAttendee::EVCalOwner); + roleSet = ETrue; + } + else if (role->Value() == KVCalAttendeeRole8DELEGATE) + { + attendee->SetRoleL(CCalAttendee::EVCalDelegate); + roleSet = ETrue; + } + else if (role->Value() == KVCalAttendeeRole8ATTENDEE) + { + attendee->SetRoleL(CCalAttendee::EVCalAttendee); + roleSet = ETrue; + } + } + if ( ! roleSet) + { + attendee->SetRoleL(CCalAttendee::EReqParticipant); + } + + // Check for vCal status values + CParserParam* calStatus = (*properties)[count]->Param(KICalAttendeeCalStatus8); + CParserParam* status = (*properties)[count]->Param(KVCalAttendee8STATUS); + if (calStatus) + { + if (calStatus->Value() == KVCalAttendeeStatus8ACCEPTED) + attendee->SetStatusL(CCalAttendee::EAccepted); + else if (calStatus->Value() == KVCalAttendeeStatus8NEEDSACTION) + attendee->SetStatusL(CCalAttendee::ENeedsAction); + else if (calStatus->Value() == KVCalAttendeeStatus8TENTATIVE) + attendee->SetStatusL(CCalAttendee::ETentative); + else if (calStatus->Value() == KVCalAttendeeStatus8CONFIRMED) + attendee->SetStatusL(CCalAttendee::EConfirmed); + else if (calStatus->Value() == KVCalAttendeeStatus8DECLINED) + attendee->SetStatusL(CCalAttendee::EDeclined); + else if (calStatus->Value() == KVCalAttendeeStatus8COMPLETED) + attendee->SetStatusL(CCalAttendee::ECompleted); + else if (calStatus->Value() == KVCalAttendeeStatus8DELEGATED) + attendee->SetStatusL(CCalAttendee::EDelegated); + else if (calStatus->Value() == KICalAttendeeCalStatus8INPROCESS) + attendee->SetStatusL(CCalAttendee::EInProcess); + } + else if (status) + { + if (status->Value() == KVCalAttendeeStatus8ACCEPTED) + attendee->SetStatusL(CCalAttendee::EAccepted); + else if (status->Value() == KVCalAttendeeStatus8NEEDSACTION) + attendee->SetStatusL(CCalAttendee::ENeedsAction); + else if (status->Value() == KVCalAttendeeStatus8SENT) + attendee->SetStatusL(CCalAttendee::EVCalSent); + else if (status->Value() == KVCalAttendeeStatus8XDASHRECEIVED) + attendee->SetStatusL(CCalAttendee::EVCalXReceived); + else if (status->Value() == KVCalAttendeeStatus8TENTATIVE) + attendee->SetStatusL(CCalAttendee::ETentative); + else if (status->Value() == KVCalAttendeeStatus8CONFIRMED) + attendee->SetStatusL(CCalAttendee::EConfirmed); + else if (status->Value() == KVCalAttendeeStatus8DECLINED) + attendee->SetStatusL(CCalAttendee::EDeclined); + else if (status->Value() == KVCalAttendeeStatus8COMPLETED) + attendee->SetStatusL(CCalAttendee::ECompleted); + else if (status->Value() == KVCalAttendeeStatus8DELEGATED) + attendee->SetStatusL(CCalAttendee::EDelegated); + } + + // Check for RSVP parameter + CParserParam* rsvp = (*properties)[count]->Param(KVCalAttendee8RSVP); + if (rsvp) + { + if (rsvp->Value() == KVCalAttendeeRsvp8YES) + attendee->SetResponseRequested(ETrue); + else + attendee->SetResponseRequested(EFalse); + } + + // Check for EXPECT parameter + CParserParam* expect = (*properties)[count]->Param(KVCalAttendee8EXPECT); + if (expect) + { + if (expect->Value() == KVCalAttendeeExpect8FYI) + attendee->SetVCalExpect(CCalAttendee::EVCalFyi); + else if (expect->Value() == KVCalAttendeeExpect8REQUIRE) + attendee->SetVCalExpect(CCalAttendee::EVCalRequire); + else if (expect->Value() == KVCalAttendeeExpect8REQUEST) + attendee->SetVCalExpect(CCalAttendee::EVCalRequest); + else if (expect->Value() == KVCalAttendeeExpect8IMMEDIATE) + attendee->SetVCalExpect(CCalAttendee::EVCalImmediate); + } + } + + // Check for a common name + CParserParam* commonname = (*properties)[count]->Param(KICalAttendeeCommonName8); + if (commonname) + { + HBufC* commonNameDesC = commonname->ValueL(); + CleanupStack::PushL(commonNameDesC); + if(user) + { + user->SetCommonNameL(*commonNameDesC); + } + else if (attendee) + { + attendee->SetCommonNameL(*commonNameDesC); + } + CleanupStack::PopAndDestroy(commonNameDesC); + } + //Set phone owner + CParserParam* phoneowner = (*properties)[count]->Param(KICalAttendee8XDASHPHONEOWNER); + if(phoneowner) + { + if(user) + { + iEntry->SetPhoneOwnerL(user); + } + else if (attendee) + { + iEntry->SetPhoneOwnerL(attendee); + } + } + }//for + }//if property + + CleanupStack::PopAndDestroy(properties); + } + +// Import the categories property +// For each category, try and match the name of the category with the standard category types. +// If this fails, the category is assumed to be an extended category type and the "X-" prefix +// is removed +// +void CVCalToAgendaEntryConverter::ImportCategoriesPropertyL(CVersitParser& aParser, const TDesC8& aToken) + { + // get properties but don't take ownership of the elements of the array + CArrayPtr* properties = aParser.PropertyL(aToken, TUid::Uid(KVersitPropertyCDesCArrayUid), EFalse); + if (properties) + { + CleanupStack::PushL(properties); + CDesCArray* categories = static_cast((*properties)[0]->Value())->Value(); + for (TInt count=0; count < categories->Count(); count++) + { + TPtrC categoryName=categories->MdcaPoint(count); + CCalCategory* category = NULL; + //match category name to standard ones + CCalCategory::TCalCategoryType type = (CCalCategory::TCalCategoryType)(-1); + if (categoryName.CompareF(KVCalCategoriesAPPOINTMENT)==0) + { + type = CCalCategory::ECalAppointment; + } + else if(categoryName.CompareF(KVCalCategoriesBUSINESS)==0) + { + type = CCalCategory::ECalBusiness; + } + else if(categoryName.CompareF(KVCalCategoriesEDUCATION)==0) + { + type = CCalCategory::ECalEducation; + } + else if(categoryName.CompareF(KVCalCategoriesHOLIDAY)==0) + { + type = CCalCategory::ECalHoliday; + } + else if(categoryName.CompareF(KVCalCategoriesMEETING)==0) + { + type = CCalCategory::ECalMeeting; + } + else if(categoryName.CompareF(KVCalCategoriesMISCELLANEOUS)==0) + { + type = CCalCategory::ECalMiscellaneous; + } + else if(categoryName.CompareF(KVCalCategoriesPERSONAL)==0) + { + type = CCalCategory::ECalPersonal; + } + else if(categoryName.CompareF(KVCalCategoriesPHONECALL)==0) + { + type = CCalCategory::ECalPhoneCall; + } + else if(categoryName.CompareF(KVCalCategoriesSICKDAY)==0) + { + type = CCalCategory::ECalSickDay; + } + else if(categoryName.CompareF(KVCalCategoriesSPECIALOCCASION)==0) + { + type = CCalCategory::ECalSpecialOccasion; + } + else if(categoryName.CompareF(KVCalCategoriesTRAVEL)==0) + { + type = CCalCategory::ECalTravel; + } + else if(categoryName.CompareF(KVCalCategoriesVACATION)==0) + { + type = CCalCategory::ECalVacation; + } + if(type>-1) + { + category = CCalCategory::NewL(type); + } + else if(categoryName.Length() > 0) + { + if (categoryName.Find(KVCalTokenXDash) == 0) + { + categoryName.Set(categoryName.Right(categoryName.Length() - 2)); + } + + if(categoryName.Length() > 0) + { + category = CCalCategory::NewL(categoryName); + } + } + + if(category) + { + // AddCategoryL() takes ownership at the end of the function call (after calling leaving functions) + iEntry->AddCategoryL(category); + } + } + CleanupStack::PopAndDestroy(properties); + } + } + + + + +// Utility method to ensure proper cleanup in OOM +// +void ResetAndDestroyArrayOfEntries(TAny* aObject) + { + CArrayPtrFlat* array=reinterpret_cast*>(aObject); + if (array) + array->ResetAndDestroy(); + delete array; + } + + +void CVCalToAgendaEntryConverter::SetImportVCalendarValues(TBool aImportVCalendar) + { + iImportVCalendarValues = aImportVCalendar; + } + +void CVCalToAgendaEntryConverter::ImportStatusPropertyL(CVersitParser& aParser, CCalEntry::TStatus& aStatus) + { + if (iImportVCalendarValues) + { + ImportVCalStatusPropertyL(aParser, aStatus); + } + else + { + ImportICalStatusPropertyL(aParser, aStatus); + } + } + +void CVCalToAgendaEntryConverter::ImportICalStatusPropertyL(CVersitParser& aParser, CCalEntry::TStatus& aStatus) + { + HBufC* property=ImportDesPropertyL(aParser, KVCalTokenSTATUS); + if (!property) + { + aStatus = CCalEntry::ENullStatus; + return; + } +// BB mapped according to CCalEntryImpl::StatusL() which should be reconsidered + if (property->Length() ==0) // Property value not found - use default setting + { + aStatus = CCalEntry::ENullStatus; + } + else if (property->CompareF(KVCalStatusNEEDSACTION) == 0) + { + if (iEntry->EntryTypeL()==CCalEntry::ETodo) + { + aStatus = CCalEntry::ETodoNeedsAction; + } + else + { + aStatus = CCalEntry::EConfirmed; + } + } + else if (property->CompareF(KVCalStatusSENT) ==0 || property->CompareF(KVCalStatusDELEGATED)==0 || property->CompareF(KVCalStatusCONFIRMED) ==0 || property->CompareF(KVCalStatusACCEPTED) == 0) + { + if (iEntry->EntryTypeL()==CCalEntry::ETodo) + { + aStatus = CCalEntry::ETodoInProcess; + } + else + { + aStatus = CCalEntry::EConfirmed; + } + + } + else if (property->CompareF(KVCalStatusTENTATIVE)==0) + { + if (iEntry->EntryTypeL()==CCalEntry::ETodo) + { + aStatus = CCalEntry::ETodoNeedsAction; + } + else + { + aStatus = CCalEntry::ETentative; + } + + } + else if (property->CompareF(KVCalStatusDECLINED)==0) + { + aStatus = CCalEntry::ECancelled; + } + else if (property->CompareF(KVCalStatusCOMPLETED)==0) + { + if(iEntry->EntryTypeL()==CCalEntry::ETodo) + { + aStatus = CCalEntry::ETodoCompleted; + } + else + { + aStatus = CCalEntry::EConfirmed; + } + + } + else // No Match found so use the default + aStatus = CCalEntry::ENullStatus; + delete property; + } + +void CVCalToAgendaEntryConverter::ImportVCalStatusPropertyL(CVersitParser& aParser, CCalEntry::TStatus& aStatus) + { + HBufC* property=ImportDesPropertyL(aParser, KVCalTokenSTATUS); + if (!property || property->Length() == 0) + { + aStatus = CCalEntry::ENullStatus; + } + else if (property->CompareF(KVCalStatusNEEDSACTION) == 0) + { + aStatus = CCalEntry::EVCalNeedsAction; + } + else if (property->CompareF(KVCalStatusSENT) == 0) + { + aStatus = CCalEntry::EVCalSent; + } + else if (property->CompareF(KVCalStatusDELEGATED)== 0) + { + aStatus = CCalEntry::EVCalDelegated; + } + else if (property->CompareF(KVCalStatusCONFIRMED) == 0 && iEntry->EntryTypeL() != CCalEntry::ETodo) + { + aStatus = CCalEntry::EConfirmed; + } + else if (property->CompareF(KVCalStatusACCEPTED) == 0) + { + aStatus = CCalEntry::EVCalAccepted; + } + else if (property->CompareF(KVCalStatusTENTATIVE)==0 && iEntry->EntryTypeL() != CCalEntry::ETodo) + { + aStatus = CCalEntry::ETentative; + } + else if (property->CompareF(KVCalStatusDECLINED)==0) + { + aStatus = CCalEntry::EVCalDeclined; + } + else if (property->CompareF(KVCalStatusCOMPLETED)==0 && iEntry->EntryTypeL() == CCalEntry::ETodo) + { + aStatus = CCalEntry::ETodoCompleted; + } + delete property; + } +