messagingfw/wappushfw/SISLContentHandlers/src/CSIContentHandler.cpp
changeset 0 8e480a14352b
equal deleted inserted replaced
-1:000000000000 0:8e480a14352b
       
     1 // Copyright (c) 2001-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 // Local includes
       
    17 //
       
    18 #include "CSIContentHandler.h"
       
    19 
       
    20 // System includes
       
    21 //
       
    22 #include  <push/sislpushmsgutils.h>
       
    23 #include <push/csipushmsgentry.h>
       
    24 #include <escapeutils.h>
       
    25 #include <msvids.h>
       
    26 #include <inetprottextutils.h>
       
    27 
       
    28 // SI string tables.
       
    29 #include "sitagstable.h"
       
    30 #include "siattributetable.h"
       
    31 #include "siattributevaluetable.h"
       
    32 
       
    33 
       
    34 const TInt KValidUTCLength = 20;
       
    35 
       
    36 
       
    37 #if defined(_DEBUG)
       
    38 _LIT(KErrPushMsgNull,	"NULL CPushMessage");
       
    39 #endif
       
    40 
       
    41 // Constants
       
    42 _LIT(KReserved, "Reserved");
       
    43 
       
    44 void CSIContentHandler::CPushHandlerBase_Reserved1()
       
    45 	{
       
    46 	User::Panic(KReserved, KErrNotSupported);
       
    47 	}
       
    48 
       
    49 void CSIContentHandler::CPushHandlerBase_Reserved2()
       
    50 	{
       
    51 	User::Panic(KReserved, KErrNotSupported);
       
    52 	}
       
    53 
       
    54 /**
       
    55  * The SL Content handler private constructor.
       
    56  * Index number : ESIContentHandlerIndex 
       
    57  */ 
       
    58 CSIContentHandler::CSIContentHandler()
       
    59 : CContentHandlerBase(), iPushMsgAction(KErrNotFound), iExpiresTime(Time::NullTTime()), iCreatedTime(Time::NullTTime()), iValidDate(ETrue)
       
    60 	{
       
    61 	}
       
    62 
       
    63 /**
       
    64  *  This will complete initialization of the object
       
    65  */
       
    66 void CSIContentHandler::ConstructL()
       
    67 	{
       
    68 	iWapPushUtils = CSISLPushMsgUtils::NewL();
       
    69 	CActiveScheduler::Add(this);
       
    70 	}
       
    71 
       
    72 /**
       
    73  * Static Factory Construction
       
    74  *
       
    75  * Version of NewL which leaves nothing
       
    76  * on the cleanup stack
       
    77  */
       
    78 CSIContentHandler* CSIContentHandler::NewL()
       
    79 	{
       
    80 	CSIContentHandler* self = new(ELeave) CSIContentHandler;
       
    81 	CleanupStack::PushL(self);
       
    82 	self->ConstructL();
       
    83 	CleanupStack::Pop(self);
       
    84 	return self;
       
    85 	}
       
    86 
       
    87 /**
       
    88  * Default d'tor
       
    89  */
       
    90 CSIContentHandler::~CSIContentHandler()
       
    91 	{
       
    92 	__LOG_PTR_DEBUG("CSIContentHandler:: Destructor Called"); 
       
    93 	delete iHrefBuf;
       
    94 	delete iSiIdBuf;
       
    95 	delete iData;
       
    96 	delete iWapPushUtils;
       
    97 	}
       
    98 
       
    99 /**
       
   100  * HandleMessage Async. Version
       
   101  *	Takes ownership of Push Message and sets self active to continue
       
   102  *	processing message.
       
   103  *	@param aPushMsg
       
   104  *		CPushMessage to process
       
   105  *	@param aStatus
       
   106  *		request status variable for use in asynchronous operations
       
   107  */
       
   108 void CSIContentHandler::HandleMessageL(CPushMessage* aPushMsg, TRequestStatus& aStatus)
       
   109 	{
       
   110 	__LOG_PTR_DEBUG("CSIContentHandler:: HandleMessage Async Func. Called"); 
       
   111 	__ASSERT_DEBUG( aPushMsg != NULL, User::Panic(KErrPushMsgNull, KErrNone));
       
   112 
       
   113 	iMessage = aPushMsg;
       
   114 	iAcknowledge = ETrue;
       
   115 	SetConfirmationStatus(aStatus);
       
   116 
       
   117 	iState= EParsing;
       
   118 	IdleComplete();
       
   119 	}
       
   120 
       
   121 /**
       
   122  * HandleMessage Sync. Version
       
   123  *	Takes ownership of Push Message and sets self active to continue
       
   124  *	processing message.
       
   125  *
       
   126  *	Initial State: Set data members then go to the next state 
       
   127  *	@param aPushMsg
       
   128  *		CPushMessage to process
       
   129  */
       
   130 void CSIContentHandler::HandleMessageL(CPushMessage* aPushMsg)
       
   131 	{
       
   132 	__LOG_PTR_DEBUG("CSIContentHandler:: HandleMessage Sync Func. Called");
       
   133 	__ASSERT_DEBUG( aPushMsg != NULL, User::Panic(KErrPushMsgNull, KErrNone));
       
   134 	
       
   135 	iAcknowledge = EFalse;
       
   136 	iMessage = aPushMsg;
       
   137 
       
   138 	iState =EParsing;
       
   139 	IdleComplete();
       
   140 	}
       
   141 
       
   142 /** 
       
   143  *	Parse the SI message from XML to its component parts which are held
       
   144  *	in the document tree. This tree is then examined and the attributes
       
   145  *	read and recorded for later reference. Once parsed the parser and tree
       
   146  *	are deleted as no longer required.
       
   147  *	@leave KErrNotFound
       
   148  *		indicates general processing error and to abandon processing
       
   149  *	@leave KErrCorrupt
       
   150  *		there is no body in the message
       
   151  *	@leave TDesC::AllocL
       
   152  
       
   153  */
       
   154 void CSIContentHandler::ParsePushMsgL()
       
   155 	{
       
   156 	__LOG_PTR_DEBUG("CSIContentHandler:: ParsePushMsgL. Called"); 
       
   157 
       
   158 	CMessageParser* myParser = CMessageParser::NewL ( *iMessage, 
       
   159 													*this, 
       
   160 													&sitagstable::Table,
       
   161 													&siattributetable::Table,
       
   162 													&siattributevaluetable::Table );
       
   163 	CleanupStack::PushL ( myParser );
       
   164 	
       
   165 	myParser->ParseMessageL ();
       
   166 
       
   167 	User::LeaveIfError ( myParser->LastError() );
       
   168 
       
   169 	CleanupStack::PopAndDestroy ( myParser );
       
   170 
       
   171 	if (iData)
       
   172 	{
       
   173 	( iData->Des() ).TrimLeft ();
       
   174 	( iData->Des() ).TrimRight ();		
       
   175 	}
       
   176 	iState = EProcessing;
       
   177 	IdleComplete();
       
   178 	}
       
   179 
       
   180 	// Return value NULL indicates failed conversion!
       
   181 	// Ownership of the resulting string is passed up to caller.
       
   182 	HBufC16* CSIContentHandler::FormatDateStringL(const TDesC& aData)
       
   183 	{
       
   184 	const TInt KDateTimePart = 7;
       
   185 	enum TDateTimeParts {EYearTop, EYearBot, EMon, EDay, EHour, EMin, ESec};
       
   186 	TInt dateData[KDateTimePart];	
       
   187 	
       
   188 	for (TInt i = 0; i < KDateTimePart; i++)
       
   189 		dateData[i] = 0;
       
   190 	
       
   191 	TInt offSet = 0;
       
   192 	TInt dataLen = aData.Length();
       
   193 	
       
   194 
       
   195 	while (offSet < KDateTimePart && dataLen > 0)
       
   196 		{
       
   197 		dateData[offSet] = aData[offSet];
       
   198 		offSet++;
       
   199 		dataLen--;
       
   200 		}
       
   201 
       
   202 		_LIT(KDateFormat,"%2x%02x-%02x-%02xT%02x:%02x:%02xZ");
       
   203 		const TInt KDateFormatLen = 20;
       
   204 		
       
   205 		TBuf16<KDateFormatLen> dateBuf;
       
   206 		dateBuf.Format(KDateFormat, dateData[EYearTop], 
       
   207 								dateData[EYearBot], 
       
   208 								dateData[EMon], 
       
   209 								dateData[EDay], 
       
   210 								dateData[EHour], 
       
   211 								dateData[EMin], 
       
   212 								dateData[ESec]);
       
   213 	return( dateBuf.AllocL() );	
       
   214 }
       
   215 		
       
   216 
       
   217 /** 
       
   218  *	Convert UTC date time into native TTime format. Method can not leave
       
   219  *	and traps any leaves from ValidateUTCTimeL.
       
   220  *	@param aDateTime
       
   221  *			the UTC string representing the date and time
       
   222  *	@param aConvertedDate
       
   223  *			member date variable passed in to accept converted UTC date as TTime varaible
       
   224  *	@return TBool
       
   225  *			indicates if conversion successful (ETrue) or conversion failed (EFalse)
       
   226  */
       
   227 TBool CSIContentHandler::ConvertDateTimeL(const TDesC& aDateTime, TTime &aConvertedDate)
       
   228 	{
       
   229 	TTime convertedTime = Time::NullTTime();
       
   230 	TBool convertedOK = EFalse;
       
   231 
       
   232 	HBufC* dateTime = NULL;
       
   233 	if (aDateTime.Length() == KValidUTCLength) //check supplied descriptor is the correct length
       
   234 		{		
       
   235 		dateTime = aDateTime.AllocLC ();
       
   236 		}
       
   237 	else
       
   238 		{
       
   239 		// Convert to UTC string
       
   240 		dateTime = FormatDateStringL ( aDateTime );
       
   241 		CleanupStack::PushL ( dateTime );		
       
   242 		}
       
   243 		
       
   244 	TBuf<20> str = dateTime->Des();
       
   245 	if (IsValidUTCTime(str))
       
   246 		{
       
   247 		// adjust UTC time to zero offset TTime
       
   248 		const TInt KFirstMonthChar = 4;
       
   249 		const TInt KSecondMonthChar = KFirstMonthChar + 1;
       
   250 		const TInt KFirstDayChar = 6;
       
   251 		const TInt KSecondDayChar = KFirstDayChar + 1;
       
   252 		// check for special case of month = 10 which becomes 09
       
   253 		if (str[KFirstMonthChar]=='1' && str[KSecondMonthChar] == '0')
       
   254 			{
       
   255 			str[KFirstMonthChar]='0';
       
   256 			str[KSecondMonthChar]='9';
       
   257 			}
       
   258 		else
       
   259 			// month value is either 11, 12 or less than 10, ie 1 - 9.
       
   260 			// reduce day by one, eg 11 becomes 10, 12 becomes 11, 09 becomes 08
       
   261 			str[KSecondMonthChar]-- ; 
       
   262 		
       
   263 		// check for special cases 10, 20, 30
       
   264 		if (str[KSecondDayChar] == '0')
       
   265 			{
       
   266 			// reduce day by 1, ie 10 becomes 09, 20 becomes 19 ...
       
   267 			str[KSecondDayChar] = '9';
       
   268 			str[KFirstDayChar]--;
       
   269 			}
       
   270 		else
       
   271 			// day value is between 1 and 9 so reduce day by one
       
   272 			// eg 29 becomes 28, 11 bcomes 10, 31 becomes 30
       
   273 			str[KSecondDayChar]--;
       
   274 		
       
   275 		// string is now syntaxically correct and year will be not be negative
       
   276 		// so no errors will occur here and will now have a valid TTime
       
   277 		convertedTime.Set(str);
       
   278 		convertedOK = ETrue;
       
   279 		}	
       
   280 	
       
   281 	aConvertedDate = convertedTime;
       
   282 	CleanupStack::PopAndDestroy ( dateTime );
       
   283 	if(!convertedOK)
       
   284 	   {
       
   285 	   iValidDate = EFalse;
       
   286 	   }
       
   287 	return convertedOK;
       
   288 	}
       
   289 
       
   290 /**
       
   291  *	Check given UTC time string conforms to expected format:
       
   292  *	YYYY-MM-DDTHH:MM:SSZ and strip out formatting characters
       
   293  *	then validate the remaining characters are all digits.
       
   294  *	If validated then add TTime formating character so final
       
   295  *	string returned will be of the format YYYYMMDD:HHMMSS.
       
   296  *	@param aDateTime
       
   297  *		UTC string which is validated and returned
       
   298  *	@return boolean 
       
   299  *		indicates if given date is valid (ETrue)
       
   300  *		or not (EFalse)
       
   301  */
       
   302 TBool CSIContentHandler::IsValidUTCTime(TDes& aDateTime)
       
   303 	{
       
   304 	// strip out formatting characters
       
   305 	TInt formatCharPos = 4;
       
   306 	aDateTime.Delete(formatCharPos, 1); 
       
   307 	// now move through two characters at a time and remove other chars 
       
   308 	// to just leave digits
       
   309 	TInt KRemainingFormatChars = 5;
       
   310 	for (TInt i = 0 ; i < KRemainingFormatChars; i++)
       
   311 		{
       
   312 		formatCharPos += 2;
       
   313 		aDateTime.Delete(formatCharPos, 1);
       
   314 		}
       
   315 	
       
   316 	// check string now the right TTime length
       
   317 	const TInt KValidTTimeLength = 14;
       
   318 	if (aDateTime.Length() != KValidTTimeLength)
       
   319 		return EFalse;
       
   320 
       
   321 	// now have UTC string stripped of format characters - check remaining characters are
       
   322 	// all digits - YYYYMMDDHHMMSS
       
   323 	TChar ch;
       
   324 	for (TInt x = 0; x < KValidTTimeLength; x++)
       
   325 		{
       
   326 		ch = aDateTime[x];
       
   327 		if (ch.IsDigit() == EFalse)
       
   328 			return EFalse;
       
   329 		}
       
   330 	
       
   331 	TInt err = ValidateDateTime( aDateTime );
       
   332 	if(!err)   
       
   333 	return EFalse;
       
   334 
       
   335 	// insert colon seperating date from time
       
   336 	_LIT(colon, ":");
       
   337 	const TInt KColonPosition = 8;
       
   338 	aDateTime.Insert(KColonPosition, colon);
       
   339 	return ETrue;
       
   340 	}
       
   341 
       
   342 /**
       
   343  * Validate date and time to check whether date and time values lie 
       
   344  * within the valid range
       
   345  *	@param aDateTime
       
   346  *		UTC string which is validated 
       
   347  *	@return boolean 
       
   348  *		indicates if given date and time is valid (ETrue)
       
   349  *		or not (EFalse)
       
   350  */
       
   351 TBool CSIContentHandler::ValidateDateTime(TDes& aDateTime)
       
   352     {
       
   353 	TPtrC ptr(aDateTime);
       
   354 	TPtrC yr;
       
   355 	yr.Set(ptr.Left(4));	   
       
   356 	TInt yearInt;
       
   357 	InetProtTextUtils::ConvertDescriptorToInt(yr,yearInt);
       
   358 	   
       
   359 	TPtrC month;
       
   360 	month.Set(ptr.Mid(4));
       
   361 	TPtrC mon;
       
   362 	mon.Set(month.Left(2));
       
   363 	TInt monthInt;
       
   364 	InetProtTextUtils::ConvertDescriptorToInt(mon,monthInt);
       
   365 	   
       
   366 	TPtrC day;
       
   367 	day.Set(month.Mid(2));
       
   368     TPtrC dy;
       
   369 	dy.Set(day.Left(2));
       
   370 	TInt dayInt;
       
   371 	InetProtTextUtils::ConvertDescriptorToInt(dy,dayInt);
       
   372 	   
       
   373 	TPtrC hour;
       
   374     hour.Set(day.Mid(2));
       
   375     TPtrC hr;
       
   376     hr.Set(hour.Left(2));
       
   377 	TInt hourInt;
       
   378     InetProtTextUtils::ConvertDescriptorToInt(hr,hourInt);
       
   379 	   
       
   380 	TPtrC minute;
       
   381 	minute.Set(hour.Mid(2));
       
   382 	TPtrC min;
       
   383 	min.Set(minute.Left(2));
       
   384 	TInt minInt;
       
   385     InetProtTextUtils::ConvertDescriptorToInt(min,minInt);
       
   386 	   
       
   387     TPtrC second;
       
   388 	second.Set(minute.Mid(2));
       
   389 	TPtrC sec;
       
   390 	sec.Set(second.Left(2));
       
   391 	TInt secInt;
       
   392 	InetProtTextUtils::ConvertDescriptorToInt(sec,secInt);
       
   393 	    
       
   394 		
       
   395 	if ( monthInt == 1 ||  monthInt == 3 || monthInt == 5 || monthInt == 7
       
   396 		 || monthInt == 8 || monthInt == 10 || monthInt == 12)
       
   397          {
       
   398          if (!(dayInt <= 31))
       
   399 	         return EFalse;	
       
   400          }	 
       
   401     else if (monthInt == 04 ||  monthInt == 06 || monthInt == 9 || monthInt == 11)
       
   402              {
       
   403              if (!(dayInt <= 30))
       
   404 	             return EFalse;
       
   405 	         }
       
   406     else if (monthInt == 02)
       
   407              {
       
   408              if (Time::IsLeapYear(yearInt))
       
   409                  {
       
   410                  if (!(dayInt <= 29))
       
   411 	                 return EFalse;		                  
       
   412 	             }
       
   413 	         else if (!(dayInt <= 28))	                  
       
   414 	                  return EFalse;
       
   415 	         }	                 
       
   416     else 
       
   417        {
       
   418        return EFalse;
       
   419        }
       
   420   
       
   421     if ( !(hourInt <= 23 && minInt <= 59 && secInt <= 59))
       
   422         return EFalse;
       
   423     
       
   424     return ETrue;
       
   425     }
       
   426 
       
   427 /** 
       
   428  *	Convert the action string to a representative numeric value to facilitate 
       
   429  *	storing the message in the wap push utils.
       
   430  *	@param aActionString
       
   431  *		the attribute value indicating the action level eg 'signal-high'
       
   432  *	@return TUint
       
   433  *		a value representing the action type (as defined in PushEntry.h)
       
   434  */
       
   435 TUint CSIContentHandler::ConvertActionString(const RString& aActionString)
       
   436 	{
       
   437 	// set to default signal value (to rid ourselves of build warning)
       
   438 	TUint actionValue = CSIPushMsgEntry::ESIPushMsgSignalMedium;	
       
   439 	switch ( aActionString.Index ( siattributevaluetable::Table ) )
       
   440 		{
       
   441 		case siattributevaluetable::EAction1:
       
   442 		actionValue = CSIPushMsgEntry::ESIPushMsgSignalNone;
       
   443 		break;
       
   444 		case siattributevaluetable::EAction2:
       
   445 		actionValue = CSIPushMsgEntry::ESIPushMsgSignalLow;
       
   446 		break;
       
   447 		case siattributevaluetable::EAction3:
       
   448  		actionValue = CSIPushMsgEntry::ESIPushMsgSignalMedium;
       
   449 		break;
       
   450 		case siattributevaluetable::EAction4:
       
   451  		actionValue = CSIPushMsgEntry::ESIPushMsgSignalHigh;
       
   452 		break;		
       
   453 		case siattributevaluetable::EAction5:
       
   454 		actionValue = CSIPushMsgEntry::ESIPushMsgDelete;
       
   455 		break;						
       
   456 		default:
       
   457 		User::Invariant ();
       
   458 		}
       
   459 	return actionValue;
       
   460 	}
       
   461 
       
   462 /** 
       
   463  *	Handles message reception and processes the received message following 
       
   464  *	the flow of actions detailed in 7.2 Reception 
       
   465  *	[WAP Service Indication 08-Nov-1999]
       
   466  *		1. check if received message is expired 
       
   467  *		2. if received message is an older version of stored SI,
       
   468  *			or is the same age - discard received message 
       
   469  *		3. if message is more recent version than stored SI - delete stored SI
       
   470  *		4. if message actioned to delete, and has Si Id set, then delete it 
       
   471  *			and any stored messages with same id
       
   472  *	finally if received message not set to deleted or discarded - store it
       
   473  */
       
   474 void CSIContentHandler::ProcessingPushMsgEntryL()
       
   475 	{
       
   476 	__LOG_PTR_DEBUG("CSIContentHandler:: ProcessingPushMsgEntryL. called");
       
   477 	TBool deletePushMsg = EFalse;
       
   478 	
       
   479 	// 1. Expiration
       
   480 	TTime today;
       
   481 	today.UniversalTime();
       
   482 	// check if message has expiry date before today's date
       
   483 	if (ExpiresFlag() && iExpiresTime < today)
       
   484 		{
       
   485 		deletePushMsg = ETrue;
       
   486 		__LOG_PTR_DEBUG("CSIContentHandler: ProcessingPushMsgEntryL: Expired msg (1)");
       
   487 		}
       
   488 	
       
   489 	// 2. handling out of order delivery & 
       
   490 	// 3. replacement
       
   491 	else if (SiIdFlag() || HrefFlag())
       
   492 		deletePushMsg = HandleMsgOrderReceptionL();
       
   493 
       
   494 	// 4. deletion
       
   495 	if (!deletePushMsg && ActionFlag())
       
   496 		{
       
   497 		// check if action = delete and SiId value is set before can delete
       
   498 		if ((iPushMsgAction == CSIPushMsgEntry::ESIPushMsgDelete) && (SiIdFlag())) 
       
   499 			{
       
   500 			__LOG_PTR_DEBUG("CSIContentHandler: ProcessingPushMsgEntryL: delete msg (4)");
       
   501 			
       
   502 			// delete msg and any matching messages (with same si-id)
       
   503 			__LOG_PTR_DEBUG("CWapPushMsgUtils: FindSiIdLC  called");
       
   504 			CMsvEntrySelection* matchingIdList = iWapPushUtils->FindSiIdLC(*iSiIdBuf);
       
   505 			TInt matchingListCount = matchingIdList->Count();
       
   506 			for (TInt count = 0; count < matchingListCount; count++)
       
   507 				{
       
   508 				TMsvId matchingSiMsgEntryId = matchingIdList->At(count);
       
   509 				if (matchingSiMsgEntryId)
       
   510 					{
       
   511 					__LOG_PTR_DEBUG("CWapPushMsgUtils: DeleteEntryNowL called");
       
   512 					iWapPushUtils->DeleteEntryNowL(matchingSiMsgEntryId);
       
   513 					}
       
   514 				}
       
   515 			CleanupStack::PopAndDestroy(); // matchingIdList
       
   516 			deletePushMsg = ETrue;
       
   517 			}
       
   518 		}
       
   519 
       
   520 	// store message if not marked for deletion and date/time is valid
       
   521 	if (!deletePushMsg && iValidDate)
       
   522 		StoreSIMessageL();
       
   523 	// Reset the flag to ETrue for next message
       
   524 	iValidDate = ETrue;
       
   525 
       
   526 	iState = EDone;
       
   527 	IdleComplete();
       
   528 	}
       
   529 
       
   530 /**
       
   531  *	Check received SI message against existing stored messages
       
   532  *	with the same si-id and update the message(s) according to
       
   533  *	the creation date (if specified).
       
   534  *	@return TBool
       
   535  *		ETrue - Received SI message older than stored match(es)
       
   536  *				and should be marked for deletion
       
   537  *		EFalse - Receieved SI message to be retained as newer
       
   538  *				therefore do not delete it
       
   539  */
       
   540 TBool CSIContentHandler::HandleMsgOrderReceptionL()
       
   541 	{
       
   542 	CMsvEntrySelection* matchingIdList;
       
   543 	TBool discardPushMsg = EFalse;
       
   544 
       
   545 	__LOG_PTR_DEBUG("CSISLPushMsgUtils: FindSiIdLC called");
       
   546 	// get list of matching stored SI messages 
       
   547 	if (SiIdFlag())
       
   548 		matchingIdList = iWapPushUtils->FindSiIdLC(*iSiIdBuf);
       
   549 	else
       
   550 		matchingIdList = iWapPushUtils->FindSiIdLC(*iHrefBuf);
       
   551 
       
   552 	// check we have a creation date specified before checking against list of matches
       
   553 	if (matchingIdList->Count() && CreatedFlag())
       
   554 		{
       
   555 		CSIPushMsgEntry* siEntry=GetSiEntryL();	
       
   556 		CleanupStack::PushL(siEntry);
       
   557 			
       
   558 		// delete older stored messages and/or mark current message for deletion
       
   559 		// if same date or older than stored messages
       
   560 		TInt matchingListCount = matchingIdList->Count();
       
   561 		for (TInt count = 0; count < matchingListCount; count++)
       
   562 			{
       
   563 			TMsvId matchingSiMsgEntryId = matchingIdList->At(count);
       
   564 						
       
   565 			__LOG_PTR_DEBUG("CSIPushMsgEntry: RetrieveL called");
       
   566 			siEntry->RetrieveL(iWapPushUtils->Session(), matchingSiMsgEntryId);
       
   567 		
       
   568 			// skip date comparisons if creation date not valid
       
   569 			TTime existingSiCreatedTime = siEntry->Created();
       
   570 			if (existingSiCreatedTime == Time::NullTTime())
       
   571 				continue;
       
   572 			//check if received SI is newer than existing stored Si (out of order)
       
   573 			if (iCreatedTime > existingSiCreatedTime) 
       
   574 				{
       
   575 				__LOG_PTR_DEBUG("CWapPushMsgUtils: DeleteEntryNowL called");
       
   576 				iWapPushUtils->DeleteEntryNowL(matchingSiMsgEntryId);
       
   577 				__LOG_PTR_DEBUG("CSIContentHandler: ProcessingPushMsgEntryL: delete stored msg (3)");
       
   578 				}
       
   579 			else if (iCreatedTime <= existingSiCreatedTime)
       
   580 				// received SI older than existing stored Si (replacement)
       
   581 				discardPushMsg = ETrue;
       
   582 			}
       
   583 		CleanupStack::PopAndDestroy(siEntry);
       
   584 		}
       
   585 		
       
   586 	CleanupStack::PopAndDestroy(matchingIdList);
       
   587 		
       
   588 	if (discardPushMsg)
       
   589 		{
       
   590 		__LOG_PTR_DEBUG("CSIContentHandler: ProcessingPushMsgEntryL: discard msg (2)");
       
   591 		}
       
   592 	return discardPushMsg;
       
   593 	}
       
   594 
       
   595 
       
   596 /** 
       
   597  *	Save push message in message store.
       
   598  * 	Creates link to message service provided by wap push utils
       
   599  *	and uses this and the associated push entry class to save
       
   600  *	the push message.
       
   601  */
       
   602 void CSIContentHandler::StoreSIMessageL() 
       
   603 	{
       
   604 	__LOG_PTR_DEBUG("CSIContentHandler:: StoreSiMessageL. called");
       
   605 
       
   606 	CSIPushMsgEntry* siEntry=GetSiEntryL();
       
   607 	CleanupStack::PushL(siEntry);
       
   608 	SetSIPushMsgEntryFieldsL(*siEntry);
       
   609 	
       
   610 	TMsvId folderId;
       
   611 	iWapPushUtils->GetPushMsgFolderIdL(folderId);
       
   612 
       
   613 	__LOG_PTR_DEBUG("CSIPushMsgEntry::SaveL called");
       
   614 	siEntry->SaveL(iWapPushUtils->Session(), folderId);
       
   615 	
       
   616 	CleanupStack::PopAndDestroy(siEntry);
       
   617 	}
       
   618 
       
   619 
       
   620 CSIPushMsgEntry* CSIContentHandler::GetSiEntryL()
       
   621 	{
       
   622 	TBool isInt;
       
   623 	TPtrC8 appURI;
       
   624 	TInt appID=0;
       
   625 	iMessage->GetAppIdL(appURI, appID, isInt);
       
   626 	CSIPushMsgEntry* siEntry=NULL;
       
   627 	if (isInt)
       
   628 		{
       
   629 		siEntry = CSIPushMsgEntry::NewL(appID);
       
   630 		}
       
   631 	else
       
   632 		{
       
   633 		siEntry = CSIPushMsgEntry::NewL(appURI);
       
   634 		}
       
   635 	return siEntry;
       
   636 	}
       
   637 
       
   638 /** 
       
   639  *	Create SI entry fields prior to storing message. The saving of
       
   640  * 	certain push message attributes will be set to defaults if 
       
   641  *	information missing to facilitate message searching, storing 
       
   642  *	and retrieval.
       
   643  *	@param siEntry 
       
   644  *		entry represents message format to use when storing it
       
   645  */
       
   646 void CSIContentHandler::SetSIPushMsgEntryFieldsL(CSIPushMsgEntry& aSIPushMsgEntry)
       
   647 	{
       
   648 	// if message has no si-id but does have a href - use href as si-id and
       
   649 	// if message has a si-id but no href use si-id for href
       
   650 	
       
   651 	if (SiIdFlag() || HrefFlag())
       
   652 		{
       
   653 		if (SiIdFlag() && (HrefFlag() == EFalse))
       
   654 			{
       
   655 			aSIPushMsgEntry.SetIdL(*iSiIdBuf);
       
   656 			aSIPushMsgEntry.SetUrlL(*iSiIdBuf);
       
   657 			}
       
   658 		else if (HrefFlag() && (SiIdFlag() == EFalse))
       
   659 			{
       
   660 			aSIPushMsgEntry.SetIdL(*iHrefBuf);
       
   661 			aSIPushMsgEntry.SetUrlL(*iHrefBuf);
       
   662 			}
       
   663 		else
       
   664 			{
       
   665 			aSIPushMsgEntry.SetIdL(*iSiIdBuf);
       
   666 			aSIPushMsgEntry.SetUrlL(*iHrefBuf);
       
   667 			}
       
   668 		}
       
   669 	
       
   670 	if (ActionFlag())
       
   671 		aSIPushMsgEntry.SetAction(iPushMsgAction);
       
   672 	else // default if no action explicitly stated
       
   673 		aSIPushMsgEntry.SetAction(CSIPushMsgEntry::ESIPushMsgSignalMedium);
       
   674 	
       
   675 	// uses default null time value if no explicit date set in message
       
   676 	aSIPushMsgEntry.SetCreated(iCreatedTime);
       
   677 	aSIPushMsgEntry.SetExpires(iExpiresTime);
       
   678 	
       
   679 	// PCDATA (text) from message
       
   680 	if (DataFlag())
       
   681 		aSIPushMsgEntry.SetTextL(*iData);
       
   682 	
       
   683 	TPtrC8 msgHeaderPtr;
       
   684 	iMessage->GetHeader(msgHeaderPtr);	
       
   685 	aSIPushMsgEntry.SetHeaderL(msgHeaderPtr);
       
   686 	
       
   687 	TPtrC8 from;
       
   688 	if (!iMessage->GetBinaryHeaderField(EHttpFrom, from) &&
       
   689 		!iMessage->GetBinaryHeaderField(EHttpXWapInitiatorURI, from) &&
       
   690 		!iMessage->GetBinaryHeaderField(EHttpContentLocation, from) )
       
   691 		{
       
   692 		from.Set(KNullDesC8);
       
   693 		}
       
   694 		aSIPushMsgEntry.SetFromL(from);
       
   695 	
       
   696 	if(iMessage->MessageAllowed())
       
   697 		{
       
   698 		aSIPushMsgEntry.SetTrusted(ETrue);
       
   699 		}
       
   700 	else
       
   701 		{
       
   702 		aSIPushMsgEntry.SetTrusted(EFalse);	
       
   703 		}
       
   704 		
       
   705 	TPtrC8 serverAddress8;
       
   706 	iMessage->GetServerAddress(serverAddress8);
       
   707 	aSIPushMsgEntry.SetMsgOriginUriL(serverAddress8);
       
   708 	}
       
   709 
       
   710 /** 
       
   711  *	Same functionality as DoCancel()
       
   712  */
       
   713 void CSIContentHandler::CancelHandleMessage()
       
   714 	{
       
   715 	__LOG_PTR_DEBUG("CSIContentHandler:: CancelHandleMessage called");
       
   716 	Complete(KErrCancel);
       
   717 	}
       
   718 
       
   719 /** 
       
   720  *	Cancels the handling of the message and revokes the active status
       
   721  *	of the handler 
       
   722  */
       
   723 void CSIContentHandler::DoCancel()
       
   724 	{
       
   725 	__LOG_PTR_DEBUG("CSIContentHandler:: DoCancel Called");
       
   726 	Complete(KErrCancel);	
       
   727 	}
       
   728 
       
   729 /** 
       
   730  *	Step through the various representative states for handling a message 
       
   731  *	1. validate the message by parsing it against the relevant DTD
       
   732  *	2. process the message in accordance with the Reception rules
       
   733  *	3. finish up 
       
   734  */
       
   735 void CSIContentHandler::RunL()
       
   736 	{
       
   737 	__LOG_PTR_DEBUG("CSIContentHandler:: RunL Called");
       
   738 	// use active state machine routine to manage activites:
       
   739 	switch (iState)
       
   740 		{
       
   741 	case EParsing : 
       
   742 		ParsePushMsgL();
       
   743 		break;
       
   744 	case EProcessing:
       
   745 		ProcessingPushMsgEntryL();
       
   746 		break;
       
   747 	case EDone:
       
   748 		Complete(KErrNone);
       
   749 		break;
       
   750 	default:
       
   751 		break;
       
   752 		}
       
   753 	}
       
   754 
       
   755 /** 
       
   756  * CPluginActiveBase methods
       
   757  */
       
   758 TInt CSIContentHandler::RunError(TInt aError)
       
   759 	{
       
   760 	__LOG_PTR_DEBUG("CSIContentHandler:: RunError Called"); 
       
   761 	iState=EDone;
       
   762 	Complete(aError);
       
   763 	return KErrNone;
       
   764 	}
       
   765 
       
   766 void CSIContentHandler::HandleElementL ( const RString& aTag, const RString& aAttributeName, const RString& aAttributeValue )
       
   767 	{
       
   768 	__LOG_PTR_DEBUG( "CSIContentHandler:: HandleElementL Called" );
       
   769 	
       
   770 	const TDesC8& tag = aTag.DesC();
       
   771 	iIndicationTagFound = EFalse;
       
   772 	
       
   773 	if ( aTag.Index ( sitagstable::Table ) == sitagstable::EIndication )
       
   774 		{
       
   775 		iIndicationTagFound = ETrue;
       
   776 		}
       
   777 	
       
   778 	TBool gotDate = EFalse;	
       
   779 	HBufC* des16 = EscapeUtils::ConvertToUnicodeFromUtf8L ( aAttributeValue.DesC() );	
       
   780 	CleanupStack::PushL ( des16 );
       
   781 
       
   782 	switch ( aAttributeName.Index ( siattributetable::Table ) )
       
   783 		{
       
   784 		case siattributetable::EAction1:
       
   785 		case siattributetable::EAction2:
       
   786 		case siattributetable::EAction3:		
       
   787 		case siattributetable::EAction4:
       
   788 		case siattributetable::EAction5:
       
   789 		iPushMsgAction = ConvertActionString( aAttributeValue );
       
   790 		SetActionFlag(ETrue);		
       
   791 		break;
       
   792 			
       
   793 		case siattributetable::ECreated:
       
   794 		gotDate = ConvertDateTimeL ( *des16, iCreatedTime );
       
   795 		SetCreatedFlag(gotDate);
       
   796 		break;
       
   797 		
       
   798 		case siattributetable::EHref:
       
   799 		delete iHrefBuf;
       
   800 		iHrefBuf = NULL;
       
   801 		
       
   802 		iHrefBuf = ( des16->Des() ).AllocL ();
       
   803 		SetHrefFlag(ETrue);		
       
   804 		break;
       
   805 
       
   806 		case siattributetable::ESiExpires:
       
   807 		gotDate  = ConvertDateTimeL ( *des16, iExpiresTime );
       
   808 		SetExpiresFlag(gotDate);
       
   809 		break;
       
   810 		
       
   811 		case siattributetable::ESiId:
       
   812 		delete iSiIdBuf;
       
   813 		iSiIdBuf = NULL;
       
   814 		
       
   815 		iSiIdBuf = ( des16->Des() ).AllocL (); 
       
   816 		SetSiIdFlag(ETrue);
       
   817 		break;
       
   818 		
       
   819 		case siattributetable::EClass:
       
   820 		break;
       
   821 
       
   822 		default:
       
   823 		// Shouldn't come here.
       
   824 		User::Invariant ();
       
   825 		}
       
   826 
       
   827 	CleanupStack::PopAndDestroy ( des16 );
       
   828 	}
       
   829 
       
   830 void CSIContentHandler::HandleContentL ( const TDesC8& aBytes )
       
   831 	{	
       
   832 	// We do handle content only if it is in indication tag.
       
   833 	// else we reject the content.
       
   834 	if ( !iIndicationTagFound )
       
   835 		{
       
   836 		return;
       
   837 		}
       
   838 	if ( iData )
       
   839 		{
       
   840 		HBufC* des16 = EscapeUtils::ConvertToUnicodeFromUtf8L ( aBytes );
       
   841 		CleanupStack::PushL ( des16 );		
       
   842 		
       
   843 		TInt newDataLength = des16->Length ();
       
   844 		TInt existingDataLength = iData->Length ();
       
   845 				
       
   846 		if ( ( newDataLength + existingDataLength ) > existingDataLength )
       
   847 			{
       
   848 			iData = iData->ReAllocL ( newDataLength + existingDataLength );
       
   849 			}
       
   850 			
       
   851 		(iData->Des()).Append( *des16 );			
       
   852 		
       
   853 		CleanupStack::PopAndDestroy ( des16 );		
       
   854 		}
       
   855 	else
       
   856 		{
       
   857 		iData = EscapeUtils::ConvertToUnicodeFromUtf8L ( aBytes );
       
   858 		}	
       
   859 	SetDataFlag ( ETrue );
       
   860 	}
       
   861