messagingfw/wappushfw/SISLContentHandlers/src/CSIContentHandler.cpp
changeset 0 8e480a14352b
--- /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  <push/sislpushmsgutils.h>
+#include <push/csipushmsgentry.h>
+#include <escapeutils.h>
+#include <msvids.h>
+#include <inetprottextutils.h>
+
+// 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<KDateFormatLen> 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 );
+	}
+