messagingfw/wappushfw/plugins/PushContentHandler/CUnknownContentHandler.cpp
changeset 62 db3f5fa34ec7
parent 0 8e480a14352b
equal deleted inserted replaced
60:9f5ae1728557 62:db3f5fa34ec7
       
     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 "CUnknownContentHandler.h"
       
    19 
       
    20 // System includes
       
    21 //
       
    22 #include <biodb.h>		// BIO Message Database and message query methods
       
    23 #include <gsmubuf.h>	// CSmsBuffer class
       
    24 #include <gsmumsg.h>	// CSmsMessage class
       
    25 #include <smuthdr.h>	// CSmsHeader class
       
    26 #include <msvuids.h>	// KUidMsvMessageEntry const
       
    27 #include <smut.h>		// TSmsUtilities class
       
    28 #include <txtrich.h>	// CRichText class
       
    29 #include <biouids.h>	// KUidBioMessageTypeMtm const
       
    30 #include <push/pushmessage.h>
       
    31 #include <wspdecoder.h>
       
    32 #include <push/cunknownpushmsgentry.h>
       
    33 #include <push/cwappushmsgutils.h>
       
    34 
       
    35 
       
    36 #if defined(_DEBUG)
       
    37 _LIT(KErrPushMsgNull,	"NULL CPushMessage");
       
    38 _LIT(KAssertFailed,     "Assertion failed");
       
    39 #endif
       
    40 
       
    41 // Constants
       
    42 _LIT(KReserved, "Reserved");
       
    43 _LIT8(KFilename8, "filename");
       
    44 
       
    45 
       
    46 void CUnknownContentHandler::CPushHandlerBase_Reserved1()
       
    47 	{
       
    48 	User::Panic(KReserved, KErrNotSupported);
       
    49 	}
       
    50 
       
    51 
       
    52 void CUnknownContentHandler::CPushHandlerBase_Reserved2()
       
    53 	{
       
    54 	User::Panic(KReserved, KErrNotSupported);
       
    55 	}
       
    56 
       
    57 
       
    58 /**
       
    59  * The Unknown Content handler private constructor
       
    60  * Index number : EUnknownContentHandlerIndex 
       
    61  */ 
       
    62 CUnknownContentHandler::CUnknownContentHandler()
       
    63 : CContentHandlerBase()
       
    64 	{
       
    65 	}
       
    66 
       
    67 
       
    68 /**
       
    69  *  This will complete initialization of the object
       
    70  */
       
    71 void CUnknownContentHandler::ConstructL()
       
    72 	{
       
    73 	iWapPushUtils = CWapPushMsgUtils::NewL();
       
    74 	// Note that CSmsGetDetDescInterface is an ECOM interface.
       
    75 	iSmsDetDesc = CSmsGetDetDescInterface::NewL();
       
    76 	CActiveScheduler::Add(this);
       
    77 	}
       
    78 
       
    79 
       
    80 /**
       
    81  * Static Factory Construction
       
    82  *
       
    83  * Version of NewL which leaves nothing
       
    84  * on the cleanup stack
       
    85  */
       
    86 CUnknownContentHandler* CUnknownContentHandler::NewL()
       
    87 	{
       
    88 	CUnknownContentHandler* self = new(ELeave) CUnknownContentHandler; 
       
    89 	CleanupStack::PushL(self);
       
    90 	self->ConstructL();
       
    91 	CleanupStack::Pop(self);
       
    92 	return self;
       
    93 	}
       
    94 
       
    95 
       
    96 /**
       
    97  * Default d'tor
       
    98  */
       
    99 CUnknownContentHandler::~CUnknownContentHandler()
       
   100 	{
       
   101 	__LOG_PTR_DEBUG("CUnknownContentHandler:: Destructor Called"); 
       
   102 	delete iWapPushUtils;
       
   103 	delete iSmsDetDesc;
       
   104 	}
       
   105 
       
   106 
       
   107 /**
       
   108  * HandleMessage Async. Version
       
   109  *	Takes ownership of Push Message and sets self active to continue
       
   110  *	processing message.
       
   111  *	@param aPushMsg
       
   112  *		CPushMessage to process
       
   113  *	@param aStatus
       
   114  *		request status variable for use in asynchronous operations
       
   115  */
       
   116 void CUnknownContentHandler::HandleMessageL(CPushMessage* aPushMsg, TRequestStatus& aStatus)
       
   117 	{
       
   118 	__LOG_PTR_DEBUG("CUnknownContentHandler:: HandleMessage Async Func. Called"); 
       
   119 	__ASSERT_DEBUG( aPushMsg != NULL , User::Panic(KErrPushMsgNull, KErrNone));
       
   120 
       
   121 	iMessage = aPushMsg;
       
   122 	iAcknowledge = ETrue;
       
   123 	SetConfirmationStatus(aStatus);
       
   124 
       
   125 	iState = EProcessing;
       
   126 	IdleComplete();
       
   127 	}
       
   128 
       
   129 
       
   130 /**
       
   131  * HandleMessage Sync. Version
       
   132  *	Takes ownership of Push Message and sets self active to continue
       
   133  *	processing message.
       
   134  *	@param aPushMsg
       
   135  *		CPushMessage to process
       
   136  */
       
   137 void CUnknownContentHandler::HandleMessageL(CPushMessage* aPushMsg)
       
   138 	{
       
   139 	__LOG_PTR_DEBUG("CUnknownContentHandler:: HandleMessage Sync Func. Called"); 
       
   140 	__ASSERT_DEBUG( aPushMsg != NULL , User::Panic(KErrPushMsgNull, KErrNone));
       
   141 	
       
   142 	iAcknowledge = EFalse;
       
   143 	iMessage = aPushMsg;
       
   144 	
       
   145 	iState = EProcessing;
       
   146 	IdleComplete();
       
   147 	}
       
   148 
       
   149 
       
   150 /**
       
   151  *	Create/Saving Push Msg Entry in the appropriate message store.
       
   152  *	First query the type of push message to check if it is a known BIO
       
   153  *	message type: 
       
   154  *	If it is then 
       
   155  *		save Push Message as appropriate BIO message
       
   156  *	else
       
   157  *		save as UnknownPushMsgEntry.
       
   158  *
       
   159  *  The supplied PushMsg is deleted in any case in the destructor.
       
   160  */
       
   161 void CUnknownContentHandler::ProcessingPushMsgEntryL()
       
   162 	{
       
   163 	__LOG_PTR_DEBUG("CUnknownContentHandler:: ProcessingPushMsgEntryL Called"); 
       
   164 	
       
   165 	TBool bioMsg = BioMessageTypeL();
       
   166 	if (bioMsg)
       
   167 		// convert to bio format & save
       
   168 		SaveBioMessageEntryL();
       
   169 	else
       
   170 		// create unknown push message entry and save
       
   171 		SaveUnknownPushMsgEntryL();
       
   172 		
       
   173 	iState = EDone;
       
   174 	IdleComplete();
       
   175 	}
       
   176 
       
   177 
       
   178 /** 
       
   179  *	Check if the given Push Message, which is now owned by the handler,
       
   180  *	is a BIO Messsage (setting the member variable iBioMsgUID if it is)
       
   181  *	and returning a boolean to indicate success (ETrue) or EFalse otherwise.
       
   182  *	@return TBool
       
   183  *		ETrue - push message is a BIO message
       
   184  *		EFalse - push message is not BIO message
       
   185  */
       
   186 TBool CUnknownContentHandler::BioMessageTypeL()
       
   187 	{
       
   188 	// need to create local RFs for BIO otherwise raises exception
       
   189 	RFs localFS;
       
   190 	CleanupClosePushL(localFS);
       
   191 	User::LeaveIfError(localFS.Connect());
       
   192 	CBIODatabase* bioDB = CBIODatabase::NewLC(localFS);
       
   193 
       
   194 	TPtrC contentTypePtr;
       
   195 	iMessage->GetContentType(contentTypePtr);
       
   196 	
       
   197 	iBioMsgUID = KNullUid;
       
   198 	TBool isBio = EFalse;
       
   199 	// IsBioMessageL returns KErrNone if found or KErrNotFound if not found 
       
   200 	if ( bioDB->IsBioMessageL(EBioMsgIdIana, contentTypePtr, NULL, iBioMsgUID) == KErrNone)
       
   201 		isBio = ETrue;
       
   202 		
       
   203 	CleanupStack::PopAndDestroy(2); // bioDB, localFS
       
   204 
       
   205 	return isBio;
       
   206 	}
       
   207 
       
   208 
       
   209 /**
       
   210  *	Save CPushMessage as the relevant BIO message type.
       
   211  *	Firstly create SMS message and use CPushMessage as
       
   212  *	source to populate SMS. Then save SMS message.
       
   213  */
       
   214 void CUnknownContentHandler::SaveBioMessageEntryL()
       
   215 	{
       
   216 	// create sms message from CPushMessage and then save message
       
   217 	__LOG_PTR_DEBUG("CUnknownContentHandler:: SaveBioMessageEntry Called"); 
       
   218 	RFs fileSession;
       
   219 	User::LeaveIfError(fileSession.Connect());
       
   220 	CleanupClosePushL(fileSession);
       
   221 	CSmsBuffer* smsBuffer = CSmsBuffer::NewL();
       
   222 
       
   223 	CSmsMessage* smsMessage = CSmsMessage::NewL(fileSession,CSmsPDU::ESmsDeliver, smsBuffer);
       
   224 	CleanupStack::PushL(smsMessage);
       
   225 
       
   226 	smsMessage->SmsPDU().SetAlphabet(TSmsDataCodingScheme::ESmsAlphabet8Bit);
       
   227 	
       
   228 	TPtrC8 fieldValue;
       
   229 
       
   230 	if (iMessage->GetBinaryHeaderField(EHttpFrom, fieldValue) ||
       
   231 		iMessage->GetBinaryHeaderField(EHttpXWapInitiatorURI, fieldValue) ||
       
   232 		iMessage->GetBinaryHeaderField(EHttpContentLocation, fieldValue) )
       
   233 		{
       
   234 		// Convert 8 bit to 16 bit
       
   235 		HBufC* tempAddr = HBufC::NewLC(fieldValue.Length());
       
   236 		tempAddr->Des().Copy(fieldValue);
       
   237 
       
   238 		smsMessage->SmsPDU().SetToFromAddressL(*tempAddr);
       
   239 		CleanupStack::PopAndDestroy(tempAddr);
       
   240 		}
       
   241 	
       
   242 	if (iMessage->GetMessageBody(fieldValue))
       
   243 		{
       
   244 		HBufC* tempBody = HBufC::NewLC(fieldValue.Length());
       
   245 		tempBody->Des().Copy(fieldValue);
       
   246 
       
   247 		smsBuffer->InsertL(0, *tempBody);
       
   248 		CleanupStack::PopAndDestroy(tempBody);
       
   249 		}
       
   250 
       
   251 	CleanupStack::Pop(); //smsMessage
       
   252 	
       
   253 	StoreMsgL(smsMessage); //destroys CSmsMessage (contains smsBuffer)
       
   254 	CleanupStack::PopAndDestroy(&fileSession);
       
   255 	}
       
   256 
       
   257 
       
   258 /** 
       
   259  *	Create CMsvEntry for sms messsage, stores the entry and 
       
   260  *	then delete entry once done.
       
   261  *	@param aSmsMsg
       
   262  *		CSmsMessage which embodies details of CPushMessage
       
   263  */
       
   264 void CUnknownContentHandler::StoreMsgL(CSmsMessage* aSmsMsg)
       
   265 	{
       
   266 	__LOG_PTR_DEBUG("CUnknownContentHandler:: StoreMsgL Called"); 
       
   267 	CleanupStack::PushL(aSmsMsg);
       
   268 
       
   269 	// Create a CSmsHeader based on this message. smsHdr takes ownership of aSmsMsg
       
   270 	CSmsHeader* smsHdr = CSmsHeader::NewL(aSmsMsg);
       
   271 	CleanupStack::Pop(aSmsMsg);
       
   272 	CleanupStack::PushL(smsHdr);
       
   273 
       
   274 	// get root entry
       
   275 	CMsvEntry* msvEntry = iWapPushUtils->Session().GetEntryL(KMsvRootIndexEntryId);
       
   276 	CleanupStack::PushL(msvEntry);
       
   277 
       
   278 	// create an invisible blank entry 
       
   279 	TMsvEntry entry;
       
   280 	entry.iType = KUidMsvMessageEntry;
       
   281 	entry.SetVisible(EFalse);
       
   282 	entry.SetInPreparation(ETrue);
       
   283 	entry.SetReadOnly(EFalse);
       
   284 	entry.SetUnread(ETrue);
       
   285 
       
   286 	TMsvId serviceId = SetBioServiceIdL();
       
   287 	TBuf<KSmsDescriptionLength> description;	
       
   288 
       
   289 	if (iBioMsgUID != KNullUid)
       
   290 		{
       
   291 		// sets entry with values passed in
       
   292 		TSmsUtilities::PopulateMsgEntry(entry, *aSmsMsg, serviceId,  KUidBIOMessageTypeMtm);
       
   293 		entry.iBioType = iBioMsgUID.iUid;
       
   294 
       
   295 		// Look up and set the description
       
   296 		TInt index;
       
   297 		CBIODatabase* bioDB = CBIODatabase::NewLC(msvEntry->Session().FileSession());
       
   298 		bioDB->GetBioIndexWithMsgIDL(iBioMsgUID, index);
       
   299 		description.Copy(bioDB->BifReader(index).Description());
       
   300 		entry.iDescription.Set(description);
       
   301 		CleanupStack::PopAndDestroy();	// bioDB
       
   302 		}
       
   303 	else
       
   304 		{
       
   305 		// sets entry with values passed in
       
   306 		TSmsUtilities::PopulateMsgEntry(entry, *aSmsMsg, serviceId);
       
   307 	
       
   308 		// Look up and set the description
       
   309 		iSmsDetDesc->GetDescription(*aSmsMsg, description);
       
   310 		entry.iDescription.Set(description);
       
   311 		}
       
   312 	
       
   313 	// Set the details
       
   314 	TBuf<KSmsDetailsLength> details;	
       
   315 	TInt err = iSmsDetDesc->GetDetails(msvEntry->Session().FileSession(), *aSmsMsg, details);
       
   316 	if (!err)
       
   317 		entry.iDetails.Set(details);
       
   318 
       
   319 	// Store entry in inbox
       
   320 	msvEntry->SetEntryL(KMsvGlobalInBoxIndexEntryId);
       
   321 	msvEntry->CreateL(entry);
       
   322 	msvEntry->Session().CleanupEntryPushL(entry.Id());
       
   323 	msvEntry->SetEntryL(entry.Id());
       
   324 
       
   325 	// Save the message
       
   326 	CMsvStore* store = msvEntry->EditStoreL();
       
   327 	CleanupStack::PushL(store);
       
   328 
       
   329 	// Save off the CSmsHdr
       
   330 	smsHdr->StoreL(*store);
       
   331 
       
   332 	// Save the body
       
   333 	
       
   334 	// Create and fill a CRichText object to save to store..
       
   335 	CParaFormatLayer* paraFormatLayer = CParaFormatLayer::NewL();
       
   336 	CleanupStack::PushL(paraFormatLayer);
       
   337 	CCharFormatLayer* charFormatLayer = CCharFormatLayer::NewL();
       
   338 	CleanupStack::PushL(charFormatLayer);
       
   339 	CRichText* richText = CRichText::NewL(paraFormatLayer,charFormatLayer);
       
   340 	CleanupStack::PushL(richText);
       
   341 	HBufC* bufBody=HBufC::NewLC(aSmsMsg->Buffer().Length());
       
   342 	TPtr bufBodyPtr = bufBody->Des();
       
   343 	aSmsMsg->Buffer().Extract(bufBodyPtr, 0, aSmsMsg->Buffer().Length());
       
   344 	richText->InsertL(0, bufBodyPtr); 
       
   345 	store->StoreBodyTextL(*richText);
       
   346 	CleanupStack::PopAndDestroy(4); //bufBody, richText, charFormatLayer, paraFormatLayer
       
   347 	
       
   348 	store->CommitL();
       
   349 	entry.SetReadOnly(ETrue);
       
   350 	entry.SetVisible(ETrue);
       
   351 	entry.SetInPreparation(EFalse);
       
   352 	msvEntry->ChangeL(entry);
       
   353 
       
   354 	CleanupStack::PopAndDestroy(); //store
       
   355 	msvEntry->Session().CleanupEntryPop(); //entry
       
   356 	CleanupStack::PopAndDestroy(2); //msvEntry, smsHdr
       
   357 	}
       
   358 
       
   359 
       
   360 /** 
       
   361  *	Set the service id for Bio messaging
       
   362  *	@return TMsvId
       
   363  *		the service id for the message store
       
   364  */
       
   365 TMsvId CUnknownContentHandler::SetBioServiceIdL()
       
   366     {
       
   367 	__LOG_PTR_DEBUG("CUnknownContentHandler:: SetBioServiceIdL Called"); 
       
   368 	CMsvEntry* msvEntry = iWapPushUtils->Session().GetEntryL(KMsvRootIndexEntryId);
       
   369 
       
   370 	CleanupStack::PushL(msvEntry);
       
   371 	
       
   372 	TMsvId serviceId = KMsvNullIndexEntryId; 
       
   373 	TRAPD(err, TSmsUtilities::ServiceIdL(*msvEntry, serviceId,  KUidBIOMessageTypeMtm));
       
   374 	if (err == KErrNotFound)
       
   375 		{
       
   376 		serviceId = KMsvLocalServiceIndexEntryId;
       
   377 		err = KErrNone;
       
   378 		}
       
   379 	
       
   380 	CleanupStack::PopAndDestroy(); //msvEntry
       
   381 	User::LeaveIfError(err);
       
   382 
       
   383 	return serviceId;
       
   384     }
       
   385 
       
   386 
       
   387 /** 
       
   388  * Save CPushMessage as a CUnknownPushMsgEntry
       
   389  */
       
   390 void CUnknownContentHandler::SaveUnknownPushMsgEntryL()
       
   391 	{
       
   392 	__LOG_PTR_DEBUG("CUnknownContentHandler:: SaveUnknownPushMsgEntryL. called");
       
   393 	
       
   394 	TBool isInt;
       
   395 	TPtrC8 appURI;
       
   396 	TInt appID=0;
       
   397 	iMessage->GetAppIdL(appURI, appID,isInt);
       
   398 
       
   399 	CUnknownPushMsgEntry* unknownPushMsgEntry =NULL;
       
   400 	if (isInt)
       
   401 		{
       
   402 		unknownPushMsgEntry = CUnknownPushMsgEntry::NewL(appID);
       
   403 		}
       
   404 	else
       
   405 		{
       
   406 		unknownPushMsgEntry = CUnknownPushMsgEntry::NewL(appURI);
       
   407 		}
       
   408 
       
   409 	CleanupStack::PushL(unknownPushMsgEntry);
       
   410 
       
   411 	SetUnknownPushMsgEntryFieldsL(*unknownPushMsgEntry);
       
   412 
       
   413 	unknownPushMsgEntry->SaveL(iWapPushUtils->Session(), KMsvGlobalInBoxIndexEntryId);
       
   414 	__LOG_PTR_DEBUG("CUnknownPushEntry: SaveL called");
       
   415 	
       
   416 	CleanupStack::PopAndDestroy(); //unknownPushMsgEntry
       
   417 	}
       
   418 
       
   419 
       
   420 /**
       
   421  *	Sets the Unknown Push Message Entry Fields from the data in
       
   422  *	the received CPushMessage:
       
   423  *	@param aUnknownPushMsgEntry
       
   424  *		CUnknownPushMsgEntry to populate with CPushMessage details
       
   425  */
       
   426 void CUnknownContentHandler::SetUnknownPushMsgEntryFieldsL(CUnknownPushMsgEntry& aUnknownPushMsgEntry)
       
   427 	{
       
   428 	// Set all the relevant fields
       
   429 	TPtrC contentTypePtr;
       
   430 	iMessage->GetContentType(contentTypePtr);
       
   431 	aUnknownPushMsgEntry.SetContentTypeL(contentTypePtr); 
       
   432 	
       
   433 	// Set content filename if it exists
       
   434 	TFileName filename;
       
   435 	if (GetContentFileNameL(filename))
       
   436 		{
       
   437 		// This could leave because the file name specified in the Content-disposition header
       
   438 		// is not a valid Symbian OS filename.
       
   439 		TRAP_IGNORE(aUnknownPushMsgEntry.SetContentFileNameL(filename));
       
   440 		}
       
   441 
       
   442 	TPtrC8 msgBodyPtr;
       
   443 	iMessage->GetMessageBody(msgBodyPtr);
       
   444 	aUnknownPushMsgEntry.SetMessageDataL(msgBodyPtr);
       
   445 
       
   446 	TTime pushMsgDate;
       
   447 	TPtrC8 pushMsgDateDes;
       
   448 	if (iMessage->GetHeaderField(EHttpDate, pushMsgDateDes))
       
   449 		{
       
   450 		pushMsgDate.UniversalTime();
       
   451 		//Modify pushMsgDateDes descriptor to Home Time
       
   452 		aUnknownPushMsgEntry.SetTimeSent(pushMsgDate);
       
   453 		}
       
   454 	}
       
   455 
       
   456 
       
   457 /**
       
   458  * Gets content filename if it exists in the Content-Disposition push message header.
       
   459  * @param aFilename Returns filename if it exists, otherwise sets to KNullDesC.
       
   460  *                  The aFilename may have invalid filename characters or path information.
       
   461  * @return ETrue if the filename exists, EFalse otherwise.
       
   462  */
       
   463 TBool CUnknownContentHandler::GetContentFileNameL(TFileName& aFilename)
       
   464 	{
       
   465 	// Look for a Content-Disposition header...
       
   466 	TPtrC8 fieldValue;
       
   467 	if (!iMessage->GetBinaryHeaderField(EHttpContentDisposition, fieldValue))
       
   468 		{
       
   469 		aFilename.Copy(KNullDesC); 
       
   470 		return EFalse;
       
   471 		}
       
   472 	
       
   473 	return DecodeWAPContentDispositionHeaderL(aFilename, fieldValue);
       
   474 	}
       
   475 
       
   476 
       
   477 /**
       
   478  *	@internalComponent
       
   479  *	@prototype
       
   480  */
       
   481 TBool CUnknownContentHandler::DecodeWAPContentDispositionHeaderL(TFileName& aFilename, const TDesC8& aFieldValue)
       
   482 	{
       
   483 	// Decode the WAP 1.1 encoded Content-disposition header field.
       
   484 	// Refer to WAP-230-WAP-20010705-a 8.4.2.53 Content-Disposition field.
       
   485 	// The BNF is quoted here for reference:
       
   486 	//
       
   487 	// Content-disposition-value = Value-length Disposition *(Parameter)
       
   488 	// Disposition = Form-data | Attachment | Inline | Token-text
       
   489 	// Form-data = <Octet 128>
       
   490 	// Attachment = <Octet 129>
       
   491 	// Inline = <Octet 130>
       
   492 	
       
   493 	TInt valueLength = aFieldValue.Length();
       
   494 	
       
   495 	// Decode Disposition...
       
   496 	TWspPrimitiveDecoder decoder(aFieldValue);
       
   497 	TInt bytesRead = 0;
       
   498 	TInt result = 0;
       
   499 	switch(decoder.VarType())
       
   500 		{
       
   501 		case TWspPrimitiveDecoder::E7BitVal:
       
   502 			{
       
   503 			TUint8 disposition;
       
   504 			result = decoder.Val7Bit(disposition);
       
   505 			}
       
   506 			break;
       
   507 		case TWspPrimitiveDecoder::EString:		
       
   508 			{
       
   509 			TPtrC8 disposition;
       
   510 			result = decoder.String(disposition);
       
   511 			}
       
   512 			break;
       
   513 		default:
       
   514 			{
       
   515 			result = -1;
       
   516 			}
       
   517 		}
       
   518 
       
   519 	if (result <= 0)
       
   520 		{
       
   521 		// Not encoded to specification.
       
   522 		aFilename.Copy(KNullDesC); 
       
   523 		return EFalse;
       
   524 		}	
       
   525 
       
   526 	bytesRead = result;
       
   527 	
       
   528 	// Check for any parameters...
       
   529 	if (bytesRead >= valueLength)
       
   530 		{
       
   531 		// There are no parameters to follow.  The filename parameter value
       
   532 		// does not exist in the encoded Content-Disposition header.
       
   533 		aFilename.Copy(KNullDesC); 
       
   534 		return EFalse;	
       
   535 		}
       
   536 	
       
   537 	// Decode parameters...
       
   538 	TInt lastBytesRead = -1;
       
   539 	while(bytesRead < valueLength)
       
   540 		{
       
   541 		if (DecodeWAPContentDispositionParameterL(decoder, aFilename, bytesRead))
       
   542 			{
       
   543 			// The filename parameter has been located and decoded. 
       
   544 			return ETrue;
       
   545 			}
       
   546 
       
   547 		if (bytesRead == lastBytesRead)
       
   548 			{
       
   549 			break;
       
   550 			}
       
   551 
       
   552 		lastBytesRead = bytesRead;  // To prevent an infinite loop if the length is corrupt.
       
   553 		}
       
   554 	
       
   555 	// There is no filename parameter. 
       
   556 	aFilename.Copy(KNullDesC); 
       
   557 	return EFalse;
       
   558 	};
       
   559 
       
   560 
       
   561 /**
       
   562  *	@internalComponent
       
   563  *	@prototype
       
   564  */
       
   565 TBool CUnknownContentHandler::DecodeWAPContentDispositionParameterL(TWspPrimitiveDecoder& aDecoder, TFileName& aFilename, TInt& aBytesRead)
       
   566 	{
       
   567 	// Decode the WAP 1.1 encoded Parameter field.
       
   568 	// Refer to WAP-230-WAP-20010705-a 8.4.2.4 Parameter.
       
   569 	// The BNF is quoted here for reference:
       
   570 	//
       
   571 	// Parameter = Typed-parameter | Untyped-parameter
       
   572 	
       
   573 	// Determine whether the Parameter is a Typed-parameter or Untyped-parameter...
       
   574 	switch(aDecoder.VarType())
       
   575 		{
       
   576 		case TWspPrimitiveDecoder::ELengthVal :
       
   577 			return DecodeWAPContentDispositionTypedParameterL(aDecoder, aFilename, aBytesRead);
       
   578 		case TWspPrimitiveDecoder::EString :
       
   579 			return DecodeWAPContentDispositionUntypedParameterL(aDecoder, aFilename, aBytesRead);
       
   580 		default :
       
   581 			{
       
   582 			// Not encoded to specification. 
       
   583 			return EFalse;
       
   584 			}
       
   585 		}
       
   586 	}
       
   587 
       
   588 
       
   589 /**
       
   590  *	@internalComponent
       
   591  *	@prototype
       
   592  */
       
   593 TBool CUnknownContentHandler::DecodeWAPContentDispositionTypedParameterL(TWspPrimitiveDecoder& aDecoder, TFileName& aFilename, TInt& aBytesRead)
       
   594 	{
       
   595 	// Decode the WAP 1.1 encoded Parameter field.
       
   596 	// Refer to WAP-230-WAP-20010705-a 8.4.2.4 Parameter.
       
   597 	// The BNF is quoted here for reference:
       
   598 	//
       
   599 	// Typed-parameter = Well-known-parameter-token Typed-value
       
   600 	// ; the actual expected type of the value is implied by the well-known parameter
       
   601 
       
   602 	__ASSERT_DEBUG((aDecoder.VarType() == TWspPrimitiveDecoder::ELengthVal), User::Panic(KAssertFailed, KErrArgument));
       
   603 	
       
   604 	// Read Well-known-parameter-token.
       
   605 	//
       
   606 	// Well-known-parameter-token = Integer-value
       
   607 	// ; the code values used for parameters are specified in the Assigned Numbers appendix
       
   608 	//
       
   609 	TInt result = 0;
       
   610 	TInt wellKnownParameterToken;
       
   611 	result = aDecoder.LengthVal(wellKnownParameterToken);
       
   612 		
       
   613 	if (result <= 0 )
       
   614 		{
       
   615 		// Not encoded to specification. 
       
   616 		return EFalse;
       
   617 		}
       
   618 	
       
   619 	aBytesRead += result;
       
   620 	
       
   621 	// Read Typed-value.
       
   622 	//
       
   623 	// Typed-value = Compact-value | Text-value
       
   624 	// ; In addition to the expected type, there may be no value.
       
   625 	// ; If the value cannot be encoded using the expected type, it shall be encoded as text.
       
   626 	//
       
   627 	// Compact-value = Integer-value | Date-value | Delta-seconds-value | Q-value | Version-value | Uri-value
       
   628 	//
       
   629 	// Date-value = Long-integer
       
   630 	// ; The encoding of dates shall be done in number of seconds from
       
   631 	// ; 1970-01-01, 00:00:00 GMT.
       
   632 	//
       
   633 	// Delta-seconds-value = Integer-value
       
   634 	//
       
   635 	// 
       
   636 	//
       
   637 	// Text-value = No-value | Token-text | Quoted-string
       
   638 	//
       
   639 	// Text-string = [Quote] *TEXT End-of-string
       
   640 	// ; If the first character in the TEXT is in the range of 128-255, a Quote character must precede it.
       
   641 	// ; Otherwise the Quote character must be omitted. The Quote is not part of the contents.
       
   642 	//
       
   643 	// Token-text = Token End-of-string
       
   644 	//
       
   645 	// No-value = <Octet 0>
       
   646 	// ; Used to indicate that the parameter actually has no value,
       
   647 	// ; eg, as the parameter "bar" in ";foo=xxx; bar; baz=xyzzy".
       
   648 	TPtrC8 typedValue;
       
   649 	switch(aDecoder.VarType())
       
   650 		{
       
   651 		case TWspPrimitiveDecoder::ELengthVal :
       
   652 			{
       
   653 			// Compact-value.
       
   654 			TUint32 value;
       
   655 			result = aDecoder.Integer(value);
       
   656 			}
       
   657 			break;
       
   658 		case TWspPrimitiveDecoder::E7BitVal :
       
   659 			{
       
   660 			// Compact-value.
       
   661 			TUint8 value;
       
   662 			result = aDecoder.Val7Bit(value);
       
   663 			}
       
   664 			break;
       
   665 		case TWspPrimitiveDecoder::EString :
       
   666 		case TWspPrimitiveDecoder::EQuotedString :
       
   667 			{
       
   668 			// Text-value.
       
   669 			result = aDecoder.String(typedValue);
       
   670 			}
       
   671 			break;
       
   672 		default:
       
   673 			{
       
   674 			result = -1;
       
   675 			}
       
   676 		}
       
   677 	
       
   678 	if (result <= 0 )
       
   679 		{
       
   680 		// Not encoded to specification. 
       
   681 		return EFalse;
       
   682 		}
       
   683 	
       
   684 	aBytesRead += result;
       
   685 	
       
   686 	// Check to see if we have a filename parameter...
       
   687 	if (wellKnownParameterToken != 0x06)
       
   688 		{
       
   689 		// The filename parameter has not been found.
       
   690 		return EFalse;
       
   691 		}
       
   692 	
       
   693 	// The filename parameter has been found.  Check its length.
       
   694 	if (typedValue.Length() > KMaxFileName)
       
   695 	{
       
   696 		return EFalse;	
       
   697 	}
       
   698 	
       
   699 	aFilename.Copy(typedValue);
       
   700 	return ETrue;
       
   701 	}
       
   702 
       
   703 
       
   704 /**
       
   705  *	@internalComponent
       
   706  *	@prototype
       
   707  */
       
   708 TBool CUnknownContentHandler::DecodeWAPContentDispositionUntypedParameterL(TWspPrimitiveDecoder& aDecoder, TFileName& aFilename, TInt& aBytesRead)
       
   709 	{
       
   710 	// Decode the WAP 1.1 encoded Untyped-parameter value.
       
   711 	// Refer to WAP-230-WAP-20010705-a 8.4.2.4 Parameter.
       
   712 	// The BNF is quoted here for reference:
       
   713 	//
       
   714 	// Untyped-parameter = Token-text Untyped-value
       
   715 	// ; the type of the value is unknown, but it shall be encoded as an integer, if that is possible.
       
   716 	
       
   717 	__ASSERT_DEBUG(aDecoder.VarType() == TWspPrimitiveDecoder::EString, User::Panic(KAssertFailed, KErrArgument));
       
   718 	
       
   719 	// Read token-text.
       
   720 	// Token-text = Token End-of-string
       
   721 	TPtrC8 tokenText;
       
   722 	TInt result = aDecoder.String(tokenText);
       
   723 	if (result <= 0 )
       
   724 		{
       
   725 		// Not encoded to specification. 
       
   726 		return EFalse;
       
   727 		}
       
   728 	
       
   729 	aBytesRead += result;
       
   730 	
       
   731 	// Read Untyped-value to get to next the parameter.
       
   732 	//
       
   733 	// Untyped-value = Integer-value | Text-value
       
   734 	//
       
   735 	// Integer-Value = Short-integer | Long-integer
       
   736 	//
       
   737 	// Short-integer = OCTET
       
   738 	// ; Integers in range 0-127 shall be encoded as a one octet value with the most significant bit set
       
   739 	// ; to one (1xxx xxxx) and with the value in the remaining least significant bits.
       
   740 	//
       
   741 	// Long-integer = Short-length Multi-octet-integer
       
   742 	// ; The Short-length indicates the length of the Multi-octet-integer
       
   743 	//
       
   744 	// Short-length = <Any octet 0-30>
       
   745 	//
       
   746 	// Text-value = No-value | Token-text | Quoted-string
       
   747 	//
       
   748 	// Text-string = [Quote] *TEXT End-of-string
       
   749 	// ; If the first character in the TEXT is in the range of 128-255, a Quote character must precede it.
       
   750 	// ; Otherwise the Quote character must be omitted. The Quote is not part of the contents.
       
   751 	//
       
   752 	// Token-text = Token End-of-string
       
   753 	//
       
   754 	// No-value = <Octet 0>
       
   755 	// ; Used to indicate that the parameter actually has no value,
       
   756 	// ; eg, as the parameter "bar" in ";foo=xxx; bar; baz=xyzzy".
       
   757 
       
   758 	// Determine ifUntyped value is an Integer-value or Text-value...
       
   759 	TPtrC8 untypedValue;
       
   760 	switch( aDecoder.VarType() )
       
   761 		{
       
   762 		case TWspPrimitiveDecoder::E7BitVal :
       
   763 			{
       
   764 			// Short-integer.
       
   765 			TUint8 value = 0;
       
   766 			result = aDecoder.Val7Bit(value);
       
   767 			}
       
   768 			break;
       
   769 		case TWspPrimitiveDecoder::ELengthVal :
       
   770 			{
       
   771 			// Long-integer or No-value.
       
   772 			TUint32 value = 0;
       
   773 			result = aDecoder.Integer(value);
       
   774 			}
       
   775 			break;
       
   776 		case TWspPrimitiveDecoder::EString :
       
   777 		case TWspPrimitiveDecoder::EQuotedString :
       
   778 			{
       
   779 			// Text-value.
       
   780 			result = aDecoder.String(untypedValue);
       
   781 			}
       
   782 			break;
       
   783 		default :
       
   784 			{
       
   785 			result = -1;
       
   786 			}
       
   787 		}
       
   788 	
       
   789 	if (result <=0 )
       
   790 		{
       
   791 		// Not encoded to specification. 
       
   792 		return EFalse;
       
   793 		}
       
   794 	
       
   795 	aBytesRead += result;
       
   796 	
       
   797 	// Check to see if we have a filename parameter...
       
   798 	if (tokenText.CompareF(KFilename8) != 0)
       
   799 		{
       
   800 		// The filename parameter has not been found.
       
   801 		return EFalse;
       
   802 		}
       
   803 	
       
   804 	// The filename parameter has been found.  Check its length.
       
   805 	if (untypedValue.Length() > KMaxFileName)
       
   806 	{
       
   807 		return EFalse;	
       
   808 	}
       
   809 	
       
   810 	aFilename.Copy(untypedValue);
       
   811 	return ETrue;
       
   812 	}
       
   813 
       
   814 
       
   815 /**
       
   816  * Same functionality as DoCancel()
       
   817  */
       
   818 void CUnknownContentHandler::CancelHandleMessage()
       
   819 	{
       
   820 	__LOG_PTR_DEBUG("CUnknownContentHandler:: CancelHandleMessage Called"); 
       
   821 	Complete(KErrCancel);
       
   822 	}
       
   823 
       
   824 
       
   825 /**
       
   826  *	Cancels the handling of the message and revokes the active status
       
   827  *	of the handler 
       
   828  */
       
   829 void CUnknownContentHandler::DoCancel()
       
   830 	{
       
   831 	__LOG_PTR_DEBUG("CUnknownContentHandler:: DoCancel Called"); 
       
   832 	Complete(KErrCancel);
       
   833 	}
       
   834 
       
   835 
       
   836 /**
       
   837  *  Handler States: 
       
   838  *	 EProcessing- convert CPushMessage to a format to save
       
   839  *					and save the message 
       
   840  *					(either as Bio msg or UnknownPushMsgEntry)
       
   841  *	 EDone		- Clean up
       
   842  */
       
   843 void CUnknownContentHandler::RunL()
       
   844 	{
       
   845 	__LOG_PTR_DEBUG("CUnknownContentHandler:: RunL Called");
       
   846 	// use active state machine routine to manage activites:
       
   847 	switch(iState)
       
   848 		{
       
   849 	case EProcessing:
       
   850 		ProcessingPushMsgEntryL();
       
   851 		break;
       
   852 	case EDone:
       
   853 		Complete(KErrNone);
       
   854 		break;
       
   855 	default:
       
   856 		break;
       
   857 		}
       
   858 	}
       
   859 
       
   860 
       
   861 /**
       
   862  *	This is invoked when RunL Leaves with an error.
       
   863  *	Cleans up and returns.
       
   864  *	@param aError Error passed into this function
       
   865  */
       
   866 TInt CUnknownContentHandler::RunError(TInt aError)
       
   867 	{
       
   868 	__LOG_PTR_DEBUG("CUnknownContentHandler:: RunError Called"); 
       
   869 	iState = EDone;
       
   870 	Complete(aError);
       
   871 	return KErrNone;
       
   872 	}