messagingfw/wappushfw/SISLContentHandlers/src/CMsgParser.cpp
changeset 0 8e480a14352b
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/messagingfw/wappushfw/SISLContentHandlers/src/CMsgParser.cpp	Mon Jan 18 20:36:02 2010 +0200
@@ -0,0 +1,408 @@
+// Copyright (c) 2000-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+#include <f32file.h>
+#include <xml/documentparameters.h>
+#include <xml/taginfo.h>
+#include <xml/attribute.h>
+
+using namespace Xml;
+ 
+#include <xml/xmlparsererrors.h>
+#include <xml/xmlframeworkerrors.h>
+
+// User Include
+#include "CMsgParser.h"
+#include "errorcodes.h"
+//text SL MIME type
+_LIT(KSLTextContentType, "text/vnd.wap.sl");
+_LIT(KSITextContentType, "text/vnd.wap.si");
+
+_LIT8(KXmlParserDataType, "text/xml");
+_LIT8(KWbxmlParserDataType, "text/wbxml");
+
+/** 
+ * Constructor
+ * Copy CPushMessage pointer for reference during parse operations
+ */
+CMessageParser::CMessageParser ( CPushMessage& aPushMessage, 
+								MWAPElementHandler& aElementHandler,
+								const TStringTable* aTagsTable,
+								const TStringTable* aAttributeTable,
+								const TStringTable* aAttributeValueTable ) 
+	: iPushMessage ( aPushMessage ),
+	iElementHandler ( aElementHandler ),
+	iTagsTable ( aTagsTable ),
+	iAttributeTable ( aAttributeTable ),
+	iAttributeValueTable ( aAttributeValueTable )
+	{
+	}
+
+/** 
+*/
+CMessageParser::~CMessageParser()
+	{
+	delete iParser;
+	}
+
+/** 
+
+*/
+CMessageParser* CMessageParser::NewL( CPushMessage& aPushMessage, 
+									MWAPElementHandler& aElementHandler,
+									const TStringTable* aTagsTable,
+									const TStringTable* aAttributeTable,
+									const TStringTable* aAttributeValueTable )
+	{
+	CMessageParser* self = new ( ELeave ) CMessageParser ( aPushMessage, aElementHandler, aTagsTable, aAttributeTable, aAttributeValueTable );
+	CleanupStack::PushL ( self );
+	self->ConstructL ();
+	CleanupStack::Pop ( self );
+	return ( self );
+	}
+
+/** 
+
+*/
+void CMessageParser::ConstructL()
+	{
+	LoadPluginL ();
+	RStringPool& pool = StringPool ();
+	pool.OpenL ( *iTagsTable );
+	pool.OpenL ( *iAttributeTable );
+	pool.OpenL ( *iAttributeValueTable );
+	}
+
+void CMessageParser::LoadPluginL ()
+	{
+	TPtrC contentType;
+	iPushMessage.GetContentType ( contentType );
+	TBool xml = ETrue;
+	if ( contentType.CompareF ( KSLTextContentType ) && contentType.CompareF ( KSITextContentType ) )
+		{
+		xml = EFalse;
+		}
+		
+	iParser = CParser::NewL ( ( xml ) ? KXmlParserDataType() : KWbxmlParserDataType(), *this );
+	}
+/**
+
+*/
+TInt CMessageParser::ParseMessageL ()
+	{	
+	// Begin parsing
+	iParser->ParseBeginL ();
+	
+	// Get the message body and do parsing.
+	TPtrC8 msgBody;
+	iPushMessage.GetMessageBody ( msgBody );
+	
+	iParser->ParseL ( msgBody );
+	
+	// End parsing
+	iParser->ParseEndL ();
+	
+	return KErrNone;
+	}
+
+RStringPool& CMessageParser::StringPool ()
+	{
+	return iParser->StringPool ();
+	}
+
+void CMessageParser::OnStartDocumentL ( const Xml::RDocumentParameters& /* aDocParam */, TInt aErrorCode )
+	{
+	User::LeaveIfError ( MapToWapXMLError ( aErrorCode ) );
+	}
+
+void CMessageParser::OnEndDocumentL ( TInt aErrorCode )
+	{
+	User::LeaveIfError ( MapToWapXMLError ( aErrorCode ) );
+	}
+
+void CMessageParser::OnStartElementL ( const Xml::RTagInfo& aElement, const Xml::RAttributeArray& aAttributes, TInt aErrorCode )
+	{	
+	User::LeaveIfError( MapToWapXMLError ( aErrorCode ) );
+
+	TInt nAttributes = aAttributes.Count();
+	RString tag = aElement.LocalName();
+	CheckTagInTableL ( tag );
+ 
+	for ( TInt i = 0; i < nAttributes; ++i )
+		{
+		const RAttribute& attribute = aAttributes[i];
+		const RTagInfo& nameInfo = attribute.Attribute();
+		
+		RString attr = nameInfo.LocalName();
+		RString attributeValue = attribute.Value();
+		CheckAttributeValuePairL ( attr, attributeValue );
+		iElementHandler.HandleElementL ( tag, attr, attributeValue );
+		}
+	}
+ 
+void CMessageParser::OnEndElementL ( const Xml::RTagInfo& /* aElement */, TInt aErrorCode )
+	{
+	User::LeaveIfError ( MapToWapXMLError ( aErrorCode ) );	
+	}
+
+void CMessageParser::OnContentL ( const TDesC8& aBytes, TInt aErrorCode )
+	{
+	User::LeaveIfError ( MapToWapXMLError ( aErrorCode ) );
+	iElementHandler.HandleContentL ( aBytes );
+	}
+
+void CMessageParser::OnStartPrefixMappingL ( const RString& /* aPrefix */, const RString& /* aUri */, TInt aErrorCode )
+	{
+	User::LeaveIfError ( MapToWapXMLError ( aErrorCode ) );
+	}
+
+void CMessageParser::OnEndPrefixMappingL ( const RString& /* aPrefix */, TInt aErrorCode )
+	{
+	User::LeaveIfError ( MapToWapXMLError ( aErrorCode ) );
+	}
+
+void CMessageParser::OnIgnorableWhiteSpaceL ( const TDesC8& /* aBytes */, TInt aErrorCode )
+	{
+	User::LeaveIfError ( MapToWapXMLError ( aErrorCode ) );
+	}
+
+void CMessageParser::OnSkippedEntityL ( const RString& /* aName */, TInt aErrorCode )
+	{
+	User::LeaveIfError ( MapToWapXMLError ( aErrorCode ) );
+	}
+
+void CMessageParser::OnProcessingInstructionL ( const TDesC8& /* aTarget */, const TDesC8& /* aData */, TInt aErrorCode )
+	{
+	User::LeaveIfError ( MapToWapXMLError ( aErrorCode ) );
+	}
+ 
+void CMessageParser::OnError ( TInt aErrorCode )
+	{
+	iLastError = MapToWapXMLError ( aErrorCode );
+	}
+
+TAny* CMessageParser::GetExtendedInterface ( const TInt32 /* aUid */ )
+	{
+	return NULL;
+	}
+
+void CMessageParser::CheckTagInTableL ( const RString& aTag )
+	{
+	// Check the tag is appearing in the tags table
+	TInt index = aTag.Index ( *iTagsTable );
+	
+	if ( ( index == KErrNotFound ) || ( iTagPosition != index  ) )
+		{
+		// This tag name does not appear in tags table or tag is not in the right position as in DTD. 
+		// Tag is illegal or shouldn't appear or not in the expected position in XML content .
+		User::Leave ( EWapErrXmlLibIllegalTagName );
+		}
+		++iTagPosition; // Increment the tag position.
+	}
+
+void CMessageParser::CheckAttributeValuePairL ( const RString& aAttribute, const RString& aAttributeValue )
+{
+	// Check the attribute is appearing in attribute table.
+	TInt attributeIndex = aAttribute.Index ( *iAttributeTable );
+	
+	if ( attributeIndex == KErrNotFound )
+		{
+		User::Leave ( EWapErrXmlLibMissingRequiredAttribute );
+		}
+	RStringPool& pool = iParser->StringPool();
+	// Loop it around the attribute & value table. Value can be pre-defined and specific
+	for ( TInt i = attributeIndex; i < iAttributeTable->iCount; ++i  )
+		{
+		// Check the attribute matches
+		RString attribute = pool.String ( i, *iAttributeTable );
+		if ( attribute != aAttribute )
+			{
+			break;
+			}		
+		
+		RString attributeVal = pool.String ( i, *iAttributeValueTable );		
+		if ( ( attributeVal.DesC().Length() == 0 ) || ( attributeVal == aAttributeValue ) )
+			{
+			// Attribute takes any attribute value or attribute value mataches with the table values.
+			// Attribute value is valid.
+			return;	
+			}								
+ 		}
+	
+	User::Leave ( EWapErrXmlLibIllegalAttributeValue );	
+	}
+
+TInt CMessageParser::LastError ()
+	{
+	return iLastError;
+	}
+
+// Map the generic XML parser code to WAP XML errors. Description of the error code
+// has taken from expat.
+TInt CMessageParser::MapToWapXMLError ( TInt aXmlErrorCode )
+	{
+	
+	TInt errorCode = aXmlErrorCode;
+	
+	switch ( aXmlErrorCode )
+		{
+		case EXmlParserError:	
+		case EXmlSyntax:			
+		errorCode = EWapErrGeneral;
+		break;
+		// The document contains no elements 
+		// (XML requires all documents to contain exactly one top-level element)..
+		case EXmlNoElements:
+		errorCode = EWapErrXmlLibMissingDocumentRootNode;
+		break;
+		
+		// Raised when an input byte could not properly be assigned to a character; 
+		// for example, a NUL byte (value 0) in a UTF-8 input stream.
+		case EXmlInvalidToken:
+		errorCode = EWapErrXmlLibIllegalTagName;
+		break;
+		
+		// Some token (such as a start tag) was not closed before the end of the stream or 
+		// the next token was encountered.
+		case EXmlUnclosedToken:
+		// An end tag did not match the innermost open start tag.
+		case EXmlTagMismatch:
+		errorCode = EWapErrXmlLibEndTagMismatch;
+		break;
+		
+		// An incomplete character was found in the input.
+		case EXmlPartialChar:
+		// A character reference referred to a character which is illegal in XML 
+		// (for example, character 0, or `&#0;').
+		case EXmlBadCharRef:
+		errorCode = EWapErrXmlLibInvalidCharacterReference;
+		break;		
+		
+		// An attribute was used more than once in a start tag.
+		case EXmlDuplicateAttribute:
+		errorCode = EWapErrXmlLibInvalidAttributeDeclaration;
+		break;
+		
+		// Something other than whitespace occurred after the document element.
+		case EXmlJunkAfterDocElement:		
+		// A parameter entity reference was found where it was not allowed.
+		case EXmlPeRef:
+		errorCode = EWapErrDocumentCorrupted;
+		break;
+		
+		// A reference was made to a entity which was not defined.
+		case EXmlUndefinedEntity:
+		// An entity reference contained another reference to the same entity; possibly via a 
+		// different name, and possibly indirectly.
+		case EXmlRecursiveEntity:		
+		case EXmlAsyncEntity:
+		// An entity reference in an attribute value referred to an external entity instead of an internal entity.
+		case EXmlAttributeExternalEntityRef:
+		case EXmlExternalEntityHandling:
+		errorCode = EWapErrXmlLibUnknownEntityReference;
+		break;
+
+		// An entity reference referred to an entity which was declared with a notation, 
+		// so cannot be parsed.
+		case EXmlBinaryEntityRef:
+		errorCode = EWapErrDocumentCorrupted;
+		break;
+		
+		// An XML declaration was found somewhere other than the start of the input data.				
+		case EXmlMisplacedPi:
+		case EXmlIncorrectEncoding:
+		errorCode = EWapErrXmlLibInvalidDocument;
+		break;
+		// The document encoding is not supported by Expat.				
+		case EXmlUnknownEncoding:
+		errorCode = EWapErrUnknownDocument; 
+		break;		
+		
+		// A CDATA marked section was not closed.
+		case EXmlUnclosedCdata:
+		errorCode = EWapErrXmlLibMissingCDATASectionEndTag;
+		break;
+
+// The parser determined that the document was not ``standalone'' 
+		// though it declared itself to be in the XML declaration, and the NotStandaloneHandler 
+		// was set and returned 0.
+		case EXmlNotStandalone:
+		case EXmlUnexpectedState:
+		case EXmlEntityDeclInPe:
+		errorCode = EWapErrUnknownDocument;
+		break;
+		
+		case EXmlDtdRequired:
+		errorCode = EWapErrDTDUnavailable;
+		break;
+		
+		// A behavioral change was requested after parsing started that can only be changed 
+		// before parsing has started. This is (currently) only raised by UseForeignDTD().
+		case EXmlFeatureLockedWhileParsing:
+		errorCode = EWapErrGeneral;
+		break;
+		
+		// Xml framework errors
+		case KErrXmlStringDictionaryPluginNotFound:
+		case KErrXmlParserPluginNotFound:
+		case KErrXmlGeneratorPluginNotFound:
+		case KErrXmlPluginNotFound:
+		errorCode = EWapErrPluginNotFound;
+		break;
+
+		case KErrXmlBadCharacterConversion:
+		case KErrXmlUnsupportedCharacterSet:
+		case KErrXmlUnavailableCharacterSet:
+		errorCode = EWapErrXmlLibInvalidCharacterReference;
+		break;
+		
+		// MStringDictionary errors ( mainly wbxml errors )
+		case KErrXmlUnsupportedElement:
+		errorCode = EWapErrXmlLibIllegalTagName;
+		break;
+		
+		case KErrXmlUnsupportedAttribute:
+		errorCode = EWapErrXmlLibMissingRequiredAttribute;
+		break;
+		
+		case KErrXmlUnsupportedAttributeValue:
+		errorCode = EWapErrXmlLibIllegalAttributeValue;
+		break;
+
+		case KErrXmlMissingStringDictionary:
+		errorCode = EWapErrXmlLibMissingDocument;
+		break;
+
+		case KErrXmlUnsupportedDocumentVersion:
+		errorCode = EWapErrXmlLibInvalidDocumentStructure;
+		break;
+		
+		case KErrXmlDocumentCorrupt:
+		errorCode = EWapErrDocumentCorrupted;
+		break;
+		
+		case KErrXmlStringPoolTableNotFound:
+		case KErrXmlBadIndex:
+		case KErrXmlUnsupportedExtInterface:
+		case KErrXmlLast:
+		errorCode = EWapErrGeneral;
+		break;
+		
+		default:
+		// Do nothing. any other kind of error.
+		break;
+		}
+	return errorCode;
+	}