omaprovisioning/provisioning/ProvisioningParser/Src/CWPWbxmlParser.cpp
changeset 0 b497e44ab2fc
child 2 5594fba90824
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/omaprovisioning/provisioning/ProvisioningParser/Src/CWPWbxmlParser.cpp	Thu Dec 17 09:07:52 2009 +0200
@@ -0,0 +1,551 @@
+/*
+* Copyright (c) 2002 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:  CWPWbxmlParser parses WBXML data using builder design pattern
+*
+*/
+
+
+// INCLUDE FILES
+#include <stdlib.h>  // included for free()
+#include "MWPBuilder.h"
+#include "CWPWbxmlParser.h"
+#include "OMAProvisioningDictionary.h"
+#include "ProvisioningDebug.h"
+#include <nw_cXML_Parser.h>
+
+// EXTERNAL DATA STRUCTURES
+extern "C" NW_WBXML_Dictionary_t NW_omawapprovisioning_WBXMLDictionary;
+
+// CONSTANTS
+const NW_Uint16 KParseError = 0xffff;
+const NW_Uint16 KParseStatusOk = 0;
+const TUint KWapProvisioningDocToken = 0x05;
+const TUint KCharacteristicToken = 0x06;
+const NW_Uint16 KTokenValueMask = 0xff;
+//const TUint16 KTokenPageMask = 0xff00; // Commented to remove warning in armv5
+const TUint KAttribValMin = 128;
+const TUint KParmNameToken = 0x05;
+const TUint KCharTypeToken = 0x50;
+const TUint KParmStartValueToken = 0x06;
+const TUint KParmToken = 0x07;
+const TUint KFromTag = 0x0201;
+//const TUint KMaxBandwidthTag = 0x0202; // Commented to remove warning in armv5
+//const TUint KMaxUdpPortTag = 0x0203; // Commented to remove warning in armv5
+//const TUint KMinUdpPortTag = 0x0204; // Commented to remove warning in armv5
+//const NW_Int32 publicID = 0x0b; // Commented to remove warning in armv5
+const TUint KDictionaryCount = 1;
+const TInt KHeaderLength = 4;
+// binary values of the clashing names in different code pages
+//const TInt KDuplicateTagTable[]={ 0x06,0x07 };
+const TInt KDuplicateCharacteristicTable[]={ 0x53,0x58 };
+const TInt KDuplicateParmAttributeStartTable[]={ 0x07, 0x14, 0x1C,
+												 0x22, 0x23, 0x24 };
+//const TInt KDuplicateAddrtypeValueTable[]={ 0x86, 0x87, 0x88 }; // Commented to remove warning in armv5
+
+_LIT(KFromStr,"FROM");
+//_LIT(KMaxBandwidthStr,"MAX-BANDWIDTH"); // Commented to remove warning in armv5
+//_LIT(KMaxUdpPortStr,"MAX-UDP-PORT"); // Commented to remove warning in armv5
+//_LIT(KMinUdpPortStr,"MIN-UDP-PORT"); // Commented to remove warning in armv5
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+
+// -----------------------------------------------------------------------------
+// CWPNameValuePair::CWPNameValuePair
+// C++ default constructor.
+// -----------------------------------------------------------------------------
+//
+CWPNameValuePair::CWPNameValuePair()
+	{
+	}
+
+// -----------------------------------------------------------------------------
+// CWPNameValuePair::~CWPNameValuePair
+// Destructor
+// -----------------------------------------------------------------------------
+//
+CWPNameValuePair::~CWPNameValuePair()
+	{
+	delete iValue;
+	}
+
+// ---------------------------------------------------------
+// CWPStringPair::SetValue
+// ---------------------------------------------------------
+//
+void CWPNameValuePair::SetValue( HBufC* aValue )
+	{
+	delete iValue;
+	iValue = aValue;
+	}
+
+const TDesC& CWPNameValuePair::Value() const
+	{
+	if ( iValue )
+		{
+		return *iValue;
+		}
+	else
+		{
+		return KNullDesC;
+		}
+	}
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CWPWbxmlParser::CWPWbxmlParser
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+//
+CWPWbxmlParser::CWPWbxmlParser()
+	{
+	}
+
+// -----------------------------------------------------------------------------
+// CWPWbxmlParser::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CWPWbxmlParser::ConstructL()
+	{
+
+	iDocNode = NULL;	
+	// A dictionary containing OMA provisioning WBXML tokens:
+	iDictionary[0] = &NW_omawapprovisioning_WBXMLDictionary;
+	TInt err = NW_WBXML_Dictionary_initialize ( KDictionaryCount, iDictionary );
+	switch( err )
+		{
+		case NW_STAT_OUT_OF_MEMORY:
+			{
+			User::Leave( KErrNoMemory ); 
+			break;
+			}		
+		case NW_STAT_FAILURE:
+			{
+			User::Leave( KErrGeneral ); 
+			break;
+			}
+		default:
+		break;
+		}
+
+	}
+
+// -----------------------------------------------------------------------------
+// CWPWbxmlParser::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C CWPWbxmlParser* CWPWbxmlParser::NewL()
+	{
+	CWPWbxmlParser* self = new( ELeave ) CWPWbxmlParser; 
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+// Destructor
+CWPWbxmlParser::~CWPWbxmlParser()
+	{ 
+	delete iParameterName;
+	NW_WBXML_Dictionary_destroy(); // deletes iDictionary
+	}
+
+void CWPWbxmlParser::Cleanup( TAny *aPtr )
+	{
+	NW_TinyDom_ParserDelete( STATIC_CAST( Parser_t* , aPtr ) );
+	}
+
+
+// -----------------------------------------------------------------------------
+// CWPWbxmlParser::ParseL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CWPWbxmlParser::ParseL( const TDesC8& aDocument,
+									 MWPBuilder& aRoot )
+	{	
+	NW_TinyDom_Handle_t handle; 
+	FLOG( _L( "[ProvisioningParser] CWPWbxmlParser::ParseL begin" ) );
+
+	NW_Int32 bufferLength( aDocument.Size() );
+	if( bufferLength <= KHeaderLength )
+		{
+		FLOG( _L( "[ProvisioningParser] CWPWbxmlParser::ParseL leaving" ) );
+		User::Leave( KErrCorrupt );
+		}
+	NW_Byte* buffer = CONST_CAST( NW_Byte*, aDocument.Ptr() ); 	
+	// create a tree from a wbxml buffer
+    iDocNode = NW_DOM_DocumentNode_BuildWBXMLTree(&handle, 
+                                           buffer,
+                                           bufferLength,
+                                           NW_FALSE,
+                                           NW_FALSE);
+
+	if( !iDocNode )
+		{
+		User::Leave( KErrCorrupt );
+		FLOG( _L( "[ProvisioningParser] CWPWbxmlParser::ParseL error branch" ) );
+		}
+	else
+		{ 
+		FLOG( _L( "[ProvisioningParser] CWPWbxmlParser::ParseL okey branch" ) ); 
+
+       	CleanupStack::PushL( TCleanupItem( Cleanup, &handle ) ) ;
+		// traverse tree and build data into engine	
+		ParseDocumentL( iDocNode, aRoot ) ; 
+    	CleanupStack::PopAndDestroy(); // via handle
+		}
+	FLOG( _L( "[ProvisioningParser] CWPWbxmlParser::ParseL end" ) );
+	}
+
+
+// -----------------------------------------------------------------------------
+// CWPWbxmlParser::ParseDocumentL
+// Parses DOM document
+// -----------------------------------------------------------------------------
+//
+NW_Uint16 CWPWbxmlParser::ParseDocumentL( NW_DOM_DocumentNode_t *aDocument,
+									MWPBuilder& aRoot )
+	{
+	FLOG( _L( "[ProvisioningParser] CWPWbxmlParser::ParseDocumentL begin" ) );
+	NW_Uint32 encoding( NW_DOM_DocumentNode_getCharacterEncoding( aDocument ) );
+	NW_DOM_ElementNode_t* elem = 
+							NW_DOM_DocumentNode_getDocumentElement( aDocument );
+	FLOG( _L( "[ProvisioningParser] CWPWbxmlParser::ParseDocumentL end" ) );
+	return ParseNodeL( elem, encoding, aRoot );
+	}
+
+// -----------------------------------------------------------------------------
+// CWPWbxmlParser::ParseNode
+// Parses DOM tree Node recursively
+// -----------------------------------------------------------------------------
+//
+NW_Uint16 CWPWbxmlParser::ParseNodeL( NW_DOM_Node_t* aNode, NW_Uint32 aEncoding,
+										MWPBuilder& aRoot)
+	{
+	FLOG( _L( "[ProvisioningParser] CWPWbxmlParser::ParesNodeL begin" ) );
+	NW_DOM_Node_t* node = aNode;
+	if( !node )
+		{
+		User::Leave( KErrGeneral );
+		}
+	else
+		{
+		NW_Uint32 type = NW_DOM_Node_getNodeType( aNode );
+		if ( type != NW_DOM_ELEMENT_NODE )
+			{
+			User::Leave( KErrGeneral );
+			}
+		}
+	NW_Uint16 errCode( KParseStatusOk );
+	// traverse tree by simulating a stack
+	while( node )
+		{
+		ParseElementL( node, aEncoding, aRoot );
+		if( NW_DOM_Node_hasChildNodes( node ) )
+			{
+			node = NW_DOM_Node_getFirstChild( node );
+			}
+		else // leaf reached, find parent level
+			{
+			while( NW_DOM_Node_getNextSibling( node ) == NULL && node != aNode )
+				{
+				NW_Uint32 tagToken = NW_DOM_ElementNode_getTagToken( node ); 
+				if( tagToken == KCharacteristicToken )
+					{
+					aRoot.EndCharacteristicL(); 
+					}
+			
+				if(tagToken==0)
+				User::Leave(KErrCorrupt);
+				node =  NW_DOM_Node_getParentNode( node );
+				}
+			// always end leaf characteristic
+			NW_Uint32 tagToken = NW_DOM_ElementNode_getTagToken( node ); 
+			if( tagToken == KCharacteristicToken )
+				{
+				aRoot.EndCharacteristicL(); 
+				}
+			node = NW_DOM_Node_getNextSibling( node );
+			} // end leaf
+		} // end outer while
+	FLOG( _L( "[ProvisioningParser] CWPWbxmlParser::ParseNodeL end" ) );
+	return errCode; 
+	}
+
+// -----------------------------------------------------------------------------
+// CWPWbxmlParser::ParseElement
+// Parses DOM tree element into Engine data model using builder pattern.
+// -----------------------------------------------------------------------------
+//
+void CWPWbxmlParser::ParseElementL( NW_DOM_ElementNode_t* aElement,
+								  NW_Uint32 aEncoding, MWPBuilder& aRoot )
+	{
+	FLOG( _L( "[ProvisioningParser] CWPWbxmlParser::ParseElementL begin" ) );
+	NW_Uint32 token = NW_DOM_ElementNode_getTagToken( aElement );			
+	NW_Uint16 parmNameToken( 0 );
+	NW_TinyTree_t* tiny_tree =  NW_TinyTree_Node_findTree( aElement ) ;
+	NW_TinyDom_getParser( tiny_tree );
+	if ( NW_DOM_ElementNode_hasAttributes( aElement ) )
+		{
+		NW_DOM_AttributeListIterator_t listIter;
+		NW_Status_t status = 
+			NW_DOM_ElementNode_getAttributeListIterator( aElement, &listIter );
+		if( status != NW_STAT_SUCCESS )
+			{
+			User::Leave( KErrCorrupt );
+			}
+		TBool isFirstPart( ETrue ); // only one iteration
+		TBool isLastPartProcessed( EFalse );
+		TBool unknownNameFound( EFalse );
+		NW_DOM_AttributeHandle_t attrHandle;
+		while ( NW_DOM_AttributeListIterator_getNextAttribute( &listIter,
+															   &attrHandle )
+												== NW_STAT_WBXML_ITERATE_MORE )
+			{
+			CWPNameValuePair* pair = new( ELeave ) CWPNameValuePair();
+			CleanupStack::PushL( pair );
+			NW_Uint16 attribToken( KParseError );	
+			attribToken = ParseAttributeL( &attrHandle,
+													aEncoding,
+													 *pair );
+
+			if(  attribToken == KParseError  )
+				{
+				// syntactically invalid attribute
+				User::Leave( KErrCorrupt );
+				}
+
+			// extract code page from token
+			NW_Uint16 codePage(
+				STATIC_CAST( NW_Uint16, ( ( attribToken >> 8 ) & KTokenValueMask 
+									   ) ) );
+			NW_Uint16 extractedValue (
+				STATIC_CAST( NW_Uint16, ( attribToken & KTokenValueMask )
+										) );
+			// process attributes based on current element token
+			switch( token )
+				{
+				case KWapProvisioningDocToken:
+					{
+					FLOG( _L( "[ProvisioningParser] ParseElementL: prov doc found" ) );
+					break; // start of document
+					}
+				case KCharacteristicToken: 
+					{
+					FLOG( _L( "[ProvisioningParser] characteristic token found" ) );
+					// check if the name clashes with a name in code page zero
+					if ( attribToken == KCharTypeToken && pair )
+						{
+						aRoot.StartCharacteristicL( pair->Value() );
+						}
+					else {
+						if(  codePage != 0  )
+							{
+							TInt numElements(	STATIC_CAST( TInt, (
+								sizeof ( KDuplicateCharacteristicTable ) /
+								sizeof ( KDuplicateCharacteristicTable[0] )	) ) );
+							for( TInt i( 0 ); i < numElements; i++ ) 
+								{
+								if ( extractedValue ==
+										KDuplicateCharacteristicTable[i] )
+									{
+									attribToken = extractedValue;
+									FTRACE(RDebug::Print(_L("[ProvisioningParser] characteristic: id %d"), extractedValue));        
+									break; // end for
+									}
+								}
+							} // end codepage not 0
+						aRoot.StartCharacteristicL( attribToken ); 
+					}
+					break;
+					}
+				// Note: parameters are constructed in two phases:
+				// 1. the attribute value prefix token of the parm is stored
+				// 2. the value of the attribute is read and stored
+				//		with the prefix.
+				case KParmToken:
+					{
+					FLOG( _L( "[ProvisioningParser] parameter token found" ) );
+					// process the first part of the parameter attribute
+					if( isFirstPart && attribToken > 0 &&
+						 extractedValue  < KAttribValMin ) 
+						{						
+						if( extractedValue == KParmNameToken && pair )
+							{
+							if( pair->Value().Compare( KFromStr ) ==0 )
+								{							
+								parmNameToken = KFromTag;
+								}
+
+							// unknown parameter name.
+							else
+								{
+								unknownNameFound = ETrue;
+								delete iParameterName;
+								iParameterName = NULL;
+								iParameterName = (pair->Value()).AllocL();
+								}
+						}
+						// set parameter name token for storing it in step 2.
+						else
+							{
+							parmNameToken = attribToken; 
+							}
+						FTRACE(RDebug::Print(_L("[ProvisioningParser] parameter id %d"), parmNameToken));        
+
+						// check if the name clashes with a name in code page 0
+						if(  codePage != 0  )
+							{
+							TInt numElements( STATIC_CAST( TInt, (
+								sizeof ( KDuplicateParmAttributeStartTable ) /
+								sizeof ( KDuplicateParmAttributeStartTable[0] ))
+								));
+							for( TInt i(0); i < numElements ; i++ ) 
+								{
+								if ( extractedValue ==
+										KDuplicateParmAttributeStartTable[i] )
+									{
+									parmNameToken = extractedValue;
+									break; // end for
+									}
+								}
+							} // end codepage not 0	
+						isFirstPart = EFalse;
+						break;
+						}
+					// process the second part of the attribute (value)
+					else if(!isFirstPart && (extractedValue == KParmStartValueToken
+								|| extractedValue >= KAttribValMin ) )
+						{
+						if( !unknownNameFound )							
+							{
+							aRoot.ParameterL( parmNameToken, pair->Value() );
+							}
+						else if ( unknownNameFound ) 							 
+							{
+							aRoot.ParameterL( *iParameterName , pair->Value() );
+							delete iParameterName;
+							iParameterName = NULL;
+							}
+						isLastPartProcessed=ETrue;
+						}
+					break;
+					}
+				default: // error no corresponding element exists
+					{
+					break;
+					}
+				} // end switch
+			CleanupStack::PopAndDestroy(); // pair
+			} // end while 	
+			// if this parameter consisted of only one attribute, then
+			// store it
+			if( parmNameToken && !isLastPartProcessed )
+				{
+				aRoot.ParameterL( parmNameToken, KNullDesC ); 
+				}
+			else if( iParameterName && !isLastPartProcessed )
+				{
+				aRoot.ParameterL( *iParameterName, KNullDesC );
+				delete iParameterName;
+				iParameterName = NULL;
+				}
+
+		} 
+		
+		FLOG( _L( "[ProvisioningParser] CWPWbxmlParser::ParseElementL end" ) );
+		// end if has attributes.
+	}
+
+// -----------------------------------------------------------------------------
+// CWPWbxmlParser::ParseAttribute
+// Constructs HBufCs containing attribute name and value
+// -----------------------------------------------------------------------------
+//
+NW_Uint16 CWPWbxmlParser::ParseAttributeL( NW_DOM_AttributeHandle_t* aAttrHandle,
+											NW_Uint32 aEncoding,
+											 CWPNameValuePair& aPair )
+	{	
+	FLOG( _L( "[ProvisioningParser] CWPWbxmlParser::ParseAttributeL begin" ) );	
+	NW_Uint16 getStatus( KParseError );
+	// All tokenised attributes must begin with a single attribute start token 
+	// and may be followed by zero or more attribute value, string, entity, 
+	// opaque, or extension tokens.
+	// 1. process attribute name
+	TUint16 token( NW_DOM_AttributeHandle_getToken( aAttrHandle ) ); 
+	// 2. process attribute value (only one allowed)
+	NW_String_t strValue;
+	NW_Status_t status = NW_DOM_AttributeHandle_getValue( aAttrHandle, &strValue );
+	if( status == NW_STAT_SUCCESS )
+		{
+		getStatus = KParseStatusOk;
+		}
+	aPair.SetValue( ProcessAttributePartL( &strValue, aEncoding, getStatus ) );
+	
+	FLOG( _L( "[ProvisioningParser] CWPWbxmlParser::ParseAttributeL end" ) ); 
+	return token;
+	}
+// -----------------------------------------------------------------------------
+// CWPWbxmlParser::ProcessAttributePartL
+// Constructs HBufCs containing attribute name and value
+// -----------------------------------------------------------------------------
+//
+HBufC* CWPWbxmlParser::ProcessAttributePartL( NW_String_t* aString,
+											  NW_Uint32 aEncoding,
+											  NW_Uint16 aStatus )
+	{
+	FLOG( _L( "[ProvisioningParser] CWPWbxmlParser::ProcessAttributePartL begin" ) );
+	
+	NW_Ucs2 *ucs2Value = NULL;
+	HBufC* attribute = NULL;
+	if ( aStatus == KParseStatusOk ) 
+		{
+		NW_String_stringToUCS2Char( aString, aEncoding, &ucs2Value ); 
+		if ( !ucs2Value )
+			{
+			NW_String_deleteStorage( aString );
+			//User::Leave( KErrCorrupt );
+			attribute = HBufC::NewL(1);
+			TPtr aptr(attribute->Des());
+			aptr.Append(_L(""));
+			return attribute;
+			}
+		TPtrC attribValuePtr( ucs2Value );
+		attribute = attribValuePtr.Alloc();		
+		if( !attribute ) // mem alloc failed
+			{
+			free( ucs2Value ); 
+			NW_String_deleteStorage( aString );
+			User::Leave( KErrNoMemory );
+			}
+		}
+	else
+		{
+		NW_String_deleteStorage( aString );
+		User::Leave( KErrCorrupt );
+		}
+	// clean attribute value
+	free( ucs2Value ); 
+	NW_String_deleteStorage( aString );
+
+	FLOG( _L( "[ProvisioningParser] CWPWbxmlParser::ProcessAttributePartL end" ) );
+	return attribute;
+	}
+
+//  End of File