diff -r 000000000000 -r 8e480a14352b messagingfw/wappushfw/SISLContentHandlers/src/CSIContentHandler.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/messagingfw/wappushfw/SISLContentHandlers/src/CSIContentHandler.cpp Mon Jan 18 20:36:02 2010 +0200 @@ -0,0 +1,861 @@ +// Copyright (c) 2001-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: +// + +// Local includes +// +#include "CSIContentHandler.h" + +// System includes +// +#include +#include +#include +#include +#include + +// SI string tables. +#include "sitagstable.h" +#include "siattributetable.h" +#include "siattributevaluetable.h" + + +const TInt KValidUTCLength = 20; + + +#if defined(_DEBUG) +_LIT(KErrPushMsgNull, "NULL CPushMessage"); +#endif + +// Constants +_LIT(KReserved, "Reserved"); + +void CSIContentHandler::CPushHandlerBase_Reserved1() + { + User::Panic(KReserved, KErrNotSupported); + } + +void CSIContentHandler::CPushHandlerBase_Reserved2() + { + User::Panic(KReserved, KErrNotSupported); + } + +/** + * The SL Content handler private constructor. + * Index number : ESIContentHandlerIndex + */ +CSIContentHandler::CSIContentHandler() +: CContentHandlerBase(), iPushMsgAction(KErrNotFound), iExpiresTime(Time::NullTTime()), iCreatedTime(Time::NullTTime()), iValidDate(ETrue) + { + } + +/** + * This will complete initialization of the object + */ +void CSIContentHandler::ConstructL() + { + iWapPushUtils = CSISLPushMsgUtils::NewL(); + CActiveScheduler::Add(this); + } + +/** + * Static Factory Construction + * + * Version of NewL which leaves nothing + * on the cleanup stack + */ +CSIContentHandler* CSIContentHandler::NewL() + { + CSIContentHandler* self = new(ELeave) CSIContentHandler; + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return self; + } + +/** + * Default d'tor + */ +CSIContentHandler::~CSIContentHandler() + { + __LOG_PTR_DEBUG("CSIContentHandler:: Destructor Called"); + delete iHrefBuf; + delete iSiIdBuf; + delete iData; + delete iWapPushUtils; + } + +/** + * HandleMessage Async. Version + * Takes ownership of Push Message and sets self active to continue + * processing message. + * @param aPushMsg + * CPushMessage to process + * @param aStatus + * request status variable for use in asynchronous operations + */ +void CSIContentHandler::HandleMessageL(CPushMessage* aPushMsg, TRequestStatus& aStatus) + { + __LOG_PTR_DEBUG("CSIContentHandler:: HandleMessage Async Func. Called"); + __ASSERT_DEBUG( aPushMsg != NULL, User::Panic(KErrPushMsgNull, KErrNone)); + + iMessage = aPushMsg; + iAcknowledge = ETrue; + SetConfirmationStatus(aStatus); + + iState= EParsing; + IdleComplete(); + } + +/** + * HandleMessage Sync. Version + * Takes ownership of Push Message and sets self active to continue + * processing message. + * + * Initial State: Set data members then go to the next state + * @param aPushMsg + * CPushMessage to process + */ +void CSIContentHandler::HandleMessageL(CPushMessage* aPushMsg) + { + __LOG_PTR_DEBUG("CSIContentHandler:: HandleMessage Sync Func. Called"); + __ASSERT_DEBUG( aPushMsg != NULL, User::Panic(KErrPushMsgNull, KErrNone)); + + iAcknowledge = EFalse; + iMessage = aPushMsg; + + iState =EParsing; + IdleComplete(); + } + +/** + * Parse the SI message from XML to its component parts which are held + * in the document tree. This tree is then examined and the attributes + * read and recorded for later reference. Once parsed the parser and tree + * are deleted as no longer required. + * @leave KErrNotFound + * indicates general processing error and to abandon processing + * @leave KErrCorrupt + * there is no body in the message + * @leave TDesC::AllocL + + */ +void CSIContentHandler::ParsePushMsgL() + { + __LOG_PTR_DEBUG("CSIContentHandler:: ParsePushMsgL. Called"); + + CMessageParser* myParser = CMessageParser::NewL ( *iMessage, + *this, + &sitagstable::Table, + &siattributetable::Table, + &siattributevaluetable::Table ); + CleanupStack::PushL ( myParser ); + + myParser->ParseMessageL (); + + User::LeaveIfError ( myParser->LastError() ); + + CleanupStack::PopAndDestroy ( myParser ); + + if (iData) + { + ( iData->Des() ).TrimLeft (); + ( iData->Des() ).TrimRight (); + } + iState = EProcessing; + IdleComplete(); + } + + // Return value NULL indicates failed conversion! + // Ownership of the resulting string is passed up to caller. + HBufC16* CSIContentHandler::FormatDateStringL(const TDesC& aData) + { + const TInt KDateTimePart = 7; + enum TDateTimeParts {EYearTop, EYearBot, EMon, EDay, EHour, EMin, ESec}; + TInt dateData[KDateTimePart]; + + for (TInt i = 0; i < KDateTimePart; i++) + dateData[i] = 0; + + TInt offSet = 0; + TInt dataLen = aData.Length(); + + + while (offSet < KDateTimePart && dataLen > 0) + { + dateData[offSet] = aData[offSet]; + offSet++; + dataLen--; + } + + _LIT(KDateFormat,"%2x%02x-%02x-%02xT%02x:%02x:%02xZ"); + const TInt KDateFormatLen = 20; + + TBuf16 dateBuf; + dateBuf.Format(KDateFormat, dateData[EYearTop], + dateData[EYearBot], + dateData[EMon], + dateData[EDay], + dateData[EHour], + dateData[EMin], + dateData[ESec]); + return( dateBuf.AllocL() ); +} + + +/** + * Convert UTC date time into native TTime format. Method can not leave + * and traps any leaves from ValidateUTCTimeL. + * @param aDateTime + * the UTC string representing the date and time + * @param aConvertedDate + * member date variable passed in to accept converted UTC date as TTime varaible + * @return TBool + * indicates if conversion successful (ETrue) or conversion failed (EFalse) + */ +TBool CSIContentHandler::ConvertDateTimeL(const TDesC& aDateTime, TTime &aConvertedDate) + { + TTime convertedTime = Time::NullTTime(); + TBool convertedOK = EFalse; + + HBufC* dateTime = NULL; + if (aDateTime.Length() == KValidUTCLength) //check supplied descriptor is the correct length + { + dateTime = aDateTime.AllocLC (); + } + else + { + // Convert to UTC string + dateTime = FormatDateStringL ( aDateTime ); + CleanupStack::PushL ( dateTime ); + } + + TBuf<20> str = dateTime->Des(); + if (IsValidUTCTime(str)) + { + // adjust UTC time to zero offset TTime + const TInt KFirstMonthChar = 4; + const TInt KSecondMonthChar = KFirstMonthChar + 1; + const TInt KFirstDayChar = 6; + const TInt KSecondDayChar = KFirstDayChar + 1; + // check for special case of month = 10 which becomes 09 + if (str[KFirstMonthChar]=='1' && str[KSecondMonthChar] == '0') + { + str[KFirstMonthChar]='0'; + str[KSecondMonthChar]='9'; + } + else + // month value is either 11, 12 or less than 10, ie 1 - 9. + // reduce day by one, eg 11 becomes 10, 12 becomes 11, 09 becomes 08 + str[KSecondMonthChar]-- ; + + // check for special cases 10, 20, 30 + if (str[KSecondDayChar] == '0') + { + // reduce day by 1, ie 10 becomes 09, 20 becomes 19 ... + str[KSecondDayChar] = '9'; + str[KFirstDayChar]--; + } + else + // day value is between 1 and 9 so reduce day by one + // eg 29 becomes 28, 11 bcomes 10, 31 becomes 30 + str[KSecondDayChar]--; + + // string is now syntaxically correct and year will be not be negative + // so no errors will occur here and will now have a valid TTime + convertedTime.Set(str); + convertedOK = ETrue; + } + + aConvertedDate = convertedTime; + CleanupStack::PopAndDestroy ( dateTime ); + if(!convertedOK) + { + iValidDate = EFalse; + } + return convertedOK; + } + +/** + * Check given UTC time string conforms to expected format: + * YYYY-MM-DDTHH:MM:SSZ and strip out formatting characters + * then validate the remaining characters are all digits. + * If validated then add TTime formating character so final + * string returned will be of the format YYYYMMDD:HHMMSS. + * @param aDateTime + * UTC string which is validated and returned + * @return boolean + * indicates if given date is valid (ETrue) + * or not (EFalse) + */ +TBool CSIContentHandler::IsValidUTCTime(TDes& aDateTime) + { + // strip out formatting characters + TInt formatCharPos = 4; + aDateTime.Delete(formatCharPos, 1); + // now move through two characters at a time and remove other chars + // to just leave digits + TInt KRemainingFormatChars = 5; + for (TInt i = 0 ; i < KRemainingFormatChars; i++) + { + formatCharPos += 2; + aDateTime.Delete(formatCharPos, 1); + } + + // check string now the right TTime length + const TInt KValidTTimeLength = 14; + if (aDateTime.Length() != KValidTTimeLength) + return EFalse; + + // now have UTC string stripped of format characters - check remaining characters are + // all digits - YYYYMMDDHHMMSS + TChar ch; + for (TInt x = 0; x < KValidTTimeLength; x++) + { + ch = aDateTime[x]; + if (ch.IsDigit() == EFalse) + return EFalse; + } + + TInt err = ValidateDateTime( aDateTime ); + if(!err) + return EFalse; + + // insert colon seperating date from time + _LIT(colon, ":"); + const TInt KColonPosition = 8; + aDateTime.Insert(KColonPosition, colon); + return ETrue; + } + +/** + * Validate date and time to check whether date and time values lie + * within the valid range + * @param aDateTime + * UTC string which is validated + * @return boolean + * indicates if given date and time is valid (ETrue) + * or not (EFalse) + */ +TBool CSIContentHandler::ValidateDateTime(TDes& aDateTime) + { + TPtrC ptr(aDateTime); + TPtrC yr; + yr.Set(ptr.Left(4)); + TInt yearInt; + InetProtTextUtils::ConvertDescriptorToInt(yr,yearInt); + + TPtrC month; + month.Set(ptr.Mid(4)); + TPtrC mon; + mon.Set(month.Left(2)); + TInt monthInt; + InetProtTextUtils::ConvertDescriptorToInt(mon,monthInt); + + TPtrC day; + day.Set(month.Mid(2)); + TPtrC dy; + dy.Set(day.Left(2)); + TInt dayInt; + InetProtTextUtils::ConvertDescriptorToInt(dy,dayInt); + + TPtrC hour; + hour.Set(day.Mid(2)); + TPtrC hr; + hr.Set(hour.Left(2)); + TInt hourInt; + InetProtTextUtils::ConvertDescriptorToInt(hr,hourInt); + + TPtrC minute; + minute.Set(hour.Mid(2)); + TPtrC min; + min.Set(minute.Left(2)); + TInt minInt; + InetProtTextUtils::ConvertDescriptorToInt(min,minInt); + + TPtrC second; + second.Set(minute.Mid(2)); + TPtrC sec; + sec.Set(second.Left(2)); + TInt secInt; + InetProtTextUtils::ConvertDescriptorToInt(sec,secInt); + + + if ( monthInt == 1 || monthInt == 3 || monthInt == 5 || monthInt == 7 + || monthInt == 8 || monthInt == 10 || monthInt == 12) + { + if (!(dayInt <= 31)) + return EFalse; + } + else if (monthInt == 04 || monthInt == 06 || monthInt == 9 || monthInt == 11) + { + if (!(dayInt <= 30)) + return EFalse; + } + else if (monthInt == 02) + { + if (Time::IsLeapYear(yearInt)) + { + if (!(dayInt <= 29)) + return EFalse; + } + else if (!(dayInt <= 28)) + return EFalse; + } + else + { + return EFalse; + } + + if ( !(hourInt <= 23 && minInt <= 59 && secInt <= 59)) + return EFalse; + + return ETrue; + } + +/** + * Convert the action string to a representative numeric value to facilitate + * storing the message in the wap push utils. + * @param aActionString + * the attribute value indicating the action level eg 'signal-high' + * @return TUint + * a value representing the action type (as defined in PushEntry.h) + */ +TUint CSIContentHandler::ConvertActionString(const RString& aActionString) + { + // set to default signal value (to rid ourselves of build warning) + TUint actionValue = CSIPushMsgEntry::ESIPushMsgSignalMedium; + switch ( aActionString.Index ( siattributevaluetable::Table ) ) + { + case siattributevaluetable::EAction1: + actionValue = CSIPushMsgEntry::ESIPushMsgSignalNone; + break; + case siattributevaluetable::EAction2: + actionValue = CSIPushMsgEntry::ESIPushMsgSignalLow; + break; + case siattributevaluetable::EAction3: + actionValue = CSIPushMsgEntry::ESIPushMsgSignalMedium; + break; + case siattributevaluetable::EAction4: + actionValue = CSIPushMsgEntry::ESIPushMsgSignalHigh; + break; + case siattributevaluetable::EAction5: + actionValue = CSIPushMsgEntry::ESIPushMsgDelete; + break; + default: + User::Invariant (); + } + return actionValue; + } + +/** + * Handles message reception and processes the received message following + * the flow of actions detailed in 7.2 Reception + * [WAP Service Indication 08-Nov-1999] + * 1. check if received message is expired + * 2. if received message is an older version of stored SI, + * or is the same age - discard received message + * 3. if message is more recent version than stored SI - delete stored SI + * 4. if message actioned to delete, and has Si Id set, then delete it + * and any stored messages with same id + * finally if received message not set to deleted or discarded - store it + */ +void CSIContentHandler::ProcessingPushMsgEntryL() + { + __LOG_PTR_DEBUG("CSIContentHandler:: ProcessingPushMsgEntryL. called"); + TBool deletePushMsg = EFalse; + + // 1. Expiration + TTime today; + today.UniversalTime(); + // check if message has expiry date before today's date + if (ExpiresFlag() && iExpiresTime < today) + { + deletePushMsg = ETrue; + __LOG_PTR_DEBUG("CSIContentHandler: ProcessingPushMsgEntryL: Expired msg (1)"); + } + + // 2. handling out of order delivery & + // 3. replacement + else if (SiIdFlag() || HrefFlag()) + deletePushMsg = HandleMsgOrderReceptionL(); + + // 4. deletion + if (!deletePushMsg && ActionFlag()) + { + // check if action = delete and SiId value is set before can delete + if ((iPushMsgAction == CSIPushMsgEntry::ESIPushMsgDelete) && (SiIdFlag())) + { + __LOG_PTR_DEBUG("CSIContentHandler: ProcessingPushMsgEntryL: delete msg (4)"); + + // delete msg and any matching messages (with same si-id) + __LOG_PTR_DEBUG("CWapPushMsgUtils: FindSiIdLC called"); + CMsvEntrySelection* matchingIdList = iWapPushUtils->FindSiIdLC(*iSiIdBuf); + TInt matchingListCount = matchingIdList->Count(); + for (TInt count = 0; count < matchingListCount; count++) + { + TMsvId matchingSiMsgEntryId = matchingIdList->At(count); + if (matchingSiMsgEntryId) + { + __LOG_PTR_DEBUG("CWapPushMsgUtils: DeleteEntryNowL called"); + iWapPushUtils->DeleteEntryNowL(matchingSiMsgEntryId); + } + } + CleanupStack::PopAndDestroy(); // matchingIdList + deletePushMsg = ETrue; + } + } + + // store message if not marked for deletion and date/time is valid + if (!deletePushMsg && iValidDate) + StoreSIMessageL(); + // Reset the flag to ETrue for next message + iValidDate = ETrue; + + iState = EDone; + IdleComplete(); + } + +/** + * Check received SI message against existing stored messages + * with the same si-id and update the message(s) according to + * the creation date (if specified). + * @return TBool + * ETrue - Received SI message older than stored match(es) + * and should be marked for deletion + * EFalse - Receieved SI message to be retained as newer + * therefore do not delete it + */ +TBool CSIContentHandler::HandleMsgOrderReceptionL() + { + CMsvEntrySelection* matchingIdList; + TBool discardPushMsg = EFalse; + + __LOG_PTR_DEBUG("CSISLPushMsgUtils: FindSiIdLC called"); + // get list of matching stored SI messages + if (SiIdFlag()) + matchingIdList = iWapPushUtils->FindSiIdLC(*iSiIdBuf); + else + matchingIdList = iWapPushUtils->FindSiIdLC(*iHrefBuf); + + // check we have a creation date specified before checking against list of matches + if (matchingIdList->Count() && CreatedFlag()) + { + CSIPushMsgEntry* siEntry=GetSiEntryL(); + CleanupStack::PushL(siEntry); + + // delete older stored messages and/or mark current message for deletion + // if same date or older than stored messages + TInt matchingListCount = matchingIdList->Count(); + for (TInt count = 0; count < matchingListCount; count++) + { + TMsvId matchingSiMsgEntryId = matchingIdList->At(count); + + __LOG_PTR_DEBUG("CSIPushMsgEntry: RetrieveL called"); + siEntry->RetrieveL(iWapPushUtils->Session(), matchingSiMsgEntryId); + + // skip date comparisons if creation date not valid + TTime existingSiCreatedTime = siEntry->Created(); + if (existingSiCreatedTime == Time::NullTTime()) + continue; + //check if received SI is newer than existing stored Si (out of order) + if (iCreatedTime > existingSiCreatedTime) + { + __LOG_PTR_DEBUG("CWapPushMsgUtils: DeleteEntryNowL called"); + iWapPushUtils->DeleteEntryNowL(matchingSiMsgEntryId); + __LOG_PTR_DEBUG("CSIContentHandler: ProcessingPushMsgEntryL: delete stored msg (3)"); + } + else if (iCreatedTime <= existingSiCreatedTime) + // received SI older than existing stored Si (replacement) + discardPushMsg = ETrue; + } + CleanupStack::PopAndDestroy(siEntry); + } + + CleanupStack::PopAndDestroy(matchingIdList); + + if (discardPushMsg) + { + __LOG_PTR_DEBUG("CSIContentHandler: ProcessingPushMsgEntryL: discard msg (2)"); + } + return discardPushMsg; + } + + +/** + * Save push message in message store. + * Creates link to message service provided by wap push utils + * and uses this and the associated push entry class to save + * the push message. + */ +void CSIContentHandler::StoreSIMessageL() + { + __LOG_PTR_DEBUG("CSIContentHandler:: StoreSiMessageL. called"); + + CSIPushMsgEntry* siEntry=GetSiEntryL(); + CleanupStack::PushL(siEntry); + SetSIPushMsgEntryFieldsL(*siEntry); + + TMsvId folderId; + iWapPushUtils->GetPushMsgFolderIdL(folderId); + + __LOG_PTR_DEBUG("CSIPushMsgEntry::SaveL called"); + siEntry->SaveL(iWapPushUtils->Session(), folderId); + + CleanupStack::PopAndDestroy(siEntry); + } + + +CSIPushMsgEntry* CSIContentHandler::GetSiEntryL() + { + TBool isInt; + TPtrC8 appURI; + TInt appID=0; + iMessage->GetAppIdL(appURI, appID, isInt); + CSIPushMsgEntry* siEntry=NULL; + if (isInt) + { + siEntry = CSIPushMsgEntry::NewL(appID); + } + else + { + siEntry = CSIPushMsgEntry::NewL(appURI); + } + return siEntry; + } + +/** + * Create SI entry fields prior to storing message. The saving of + * certain push message attributes will be set to defaults if + * information missing to facilitate message searching, storing + * and retrieval. + * @param siEntry + * entry represents message format to use when storing it + */ +void CSIContentHandler::SetSIPushMsgEntryFieldsL(CSIPushMsgEntry& aSIPushMsgEntry) + { + // if message has no si-id but does have a href - use href as si-id and + // if message has a si-id but no href use si-id for href + + if (SiIdFlag() || HrefFlag()) + { + if (SiIdFlag() && (HrefFlag() == EFalse)) + { + aSIPushMsgEntry.SetIdL(*iSiIdBuf); + aSIPushMsgEntry.SetUrlL(*iSiIdBuf); + } + else if (HrefFlag() && (SiIdFlag() == EFalse)) + { + aSIPushMsgEntry.SetIdL(*iHrefBuf); + aSIPushMsgEntry.SetUrlL(*iHrefBuf); + } + else + { + aSIPushMsgEntry.SetIdL(*iSiIdBuf); + aSIPushMsgEntry.SetUrlL(*iHrefBuf); + } + } + + if (ActionFlag()) + aSIPushMsgEntry.SetAction(iPushMsgAction); + else // default if no action explicitly stated + aSIPushMsgEntry.SetAction(CSIPushMsgEntry::ESIPushMsgSignalMedium); + + // uses default null time value if no explicit date set in message + aSIPushMsgEntry.SetCreated(iCreatedTime); + aSIPushMsgEntry.SetExpires(iExpiresTime); + + // PCDATA (text) from message + if (DataFlag()) + aSIPushMsgEntry.SetTextL(*iData); + + TPtrC8 msgHeaderPtr; + iMessage->GetHeader(msgHeaderPtr); + aSIPushMsgEntry.SetHeaderL(msgHeaderPtr); + + TPtrC8 from; + if (!iMessage->GetBinaryHeaderField(EHttpFrom, from) && + !iMessage->GetBinaryHeaderField(EHttpXWapInitiatorURI, from) && + !iMessage->GetBinaryHeaderField(EHttpContentLocation, from) ) + { + from.Set(KNullDesC8); + } + aSIPushMsgEntry.SetFromL(from); + + if(iMessage->MessageAllowed()) + { + aSIPushMsgEntry.SetTrusted(ETrue); + } + else + { + aSIPushMsgEntry.SetTrusted(EFalse); + } + + TPtrC8 serverAddress8; + iMessage->GetServerAddress(serverAddress8); + aSIPushMsgEntry.SetMsgOriginUriL(serverAddress8); + } + +/** + * Same functionality as DoCancel() + */ +void CSIContentHandler::CancelHandleMessage() + { + __LOG_PTR_DEBUG("CSIContentHandler:: CancelHandleMessage called"); + Complete(KErrCancel); + } + +/** + * Cancels the handling of the message and revokes the active status + * of the handler + */ +void CSIContentHandler::DoCancel() + { + __LOG_PTR_DEBUG("CSIContentHandler:: DoCancel Called"); + Complete(KErrCancel); + } + +/** + * Step through the various representative states for handling a message + * 1. validate the message by parsing it against the relevant DTD + * 2. process the message in accordance with the Reception rules + * 3. finish up + */ +void CSIContentHandler::RunL() + { + __LOG_PTR_DEBUG("CSIContentHandler:: RunL Called"); + // use active state machine routine to manage activites: + switch (iState) + { + case EParsing : + ParsePushMsgL(); + break; + case EProcessing: + ProcessingPushMsgEntryL(); + break; + case EDone: + Complete(KErrNone); + break; + default: + break; + } + } + +/** + * CPluginActiveBase methods + */ +TInt CSIContentHandler::RunError(TInt aError) + { + __LOG_PTR_DEBUG("CSIContentHandler:: RunError Called"); + iState=EDone; + Complete(aError); + return KErrNone; + } + +void CSIContentHandler::HandleElementL ( const RString& aTag, const RString& aAttributeName, const RString& aAttributeValue ) + { + __LOG_PTR_DEBUG( "CSIContentHandler:: HandleElementL Called" ); + + const TDesC8& tag = aTag.DesC(); + iIndicationTagFound = EFalse; + + if ( aTag.Index ( sitagstable::Table ) == sitagstable::EIndication ) + { + iIndicationTagFound = ETrue; + } + + TBool gotDate = EFalse; + HBufC* des16 = EscapeUtils::ConvertToUnicodeFromUtf8L ( aAttributeValue.DesC() ); + CleanupStack::PushL ( des16 ); + + switch ( aAttributeName.Index ( siattributetable::Table ) ) + { + case siattributetable::EAction1: + case siattributetable::EAction2: + case siattributetable::EAction3: + case siattributetable::EAction4: + case siattributetable::EAction5: + iPushMsgAction = ConvertActionString( aAttributeValue ); + SetActionFlag(ETrue); + break; + + case siattributetable::ECreated: + gotDate = ConvertDateTimeL ( *des16, iCreatedTime ); + SetCreatedFlag(gotDate); + break; + + case siattributetable::EHref: + delete iHrefBuf; + iHrefBuf = NULL; + + iHrefBuf = ( des16->Des() ).AllocL (); + SetHrefFlag(ETrue); + break; + + case siattributetable::ESiExpires: + gotDate = ConvertDateTimeL ( *des16, iExpiresTime ); + SetExpiresFlag(gotDate); + break; + + case siattributetable::ESiId: + delete iSiIdBuf; + iSiIdBuf = NULL; + + iSiIdBuf = ( des16->Des() ).AllocL (); + SetSiIdFlag(ETrue); + break; + + case siattributetable::EClass: + break; + + default: + // Shouldn't come here. + User::Invariant (); + } + + CleanupStack::PopAndDestroy ( des16 ); + } + +void CSIContentHandler::HandleContentL ( const TDesC8& aBytes ) + { + // We do handle content only if it is in indication tag. + // else we reject the content. + if ( !iIndicationTagFound ) + { + return; + } + if ( iData ) + { + HBufC* des16 = EscapeUtils::ConvertToUnicodeFromUtf8L ( aBytes ); + CleanupStack::PushL ( des16 ); + + TInt newDataLength = des16->Length (); + TInt existingDataLength = iData->Length (); + + if ( ( newDataLength + existingDataLength ) > existingDataLength ) + { + iData = iData->ReAllocL ( newDataLength + existingDataLength ); + } + + (iData->Des()).Append( *des16 ); + + CleanupStack::PopAndDestroy ( des16 ); + } + else + { + iData = EscapeUtils::ConvertToUnicodeFromUtf8L ( aBytes ); + } + SetDataFlag ( ETrue ); + } +