diff -r 08008ce8a6df -r bde600d88860 messagingfw/wappushfw/SISLContentHandlers/src/CMsgParser.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/messagingfw/wappushfw/SISLContentHandlers/src/CMsgParser.cpp Fri Jun 04 10:32:16 2010 +0100 @@ -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 +#include +#include +#include + +using namespace Xml; + +#include +#include + +// 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 `�'). + 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; + }