diff -r 000000000000 -r 307788aac0a8 realtimenetprots/sipfw/ProfileAgent/IMS_Agent/Src/CSIPNotifyXmlBodyParser.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/realtimenetprots/sipfw/ProfileAgent/IMS_Agent/Src/CSIPNotifyXmlBodyParser.cpp Tue Feb 02 01:03:15 2010 +0200 @@ -0,0 +1,536 @@ +// Copyright (c) 2006-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: +// Name : CSIPNotifyXmlBodyParser.cpp +// Part of : ProfileAgent +// Version : SIP/4.0 +// + + + +#include +#include "CSIPNotifyXmlBodyParser.h" +#include "sipreginfoelement.h" +#include "sipregistrationelement.h" +#include "sipcontactelement.h" +#include + +_LIT8( KMimeTypeXml, "text/xml" ); + +//Elements +_LIT8(KTagRegInfo, "reginfo"); +_LIT8(KTagRegistration, "registration"); +_LIT8(KTagContact, "contact"); +_LIT8(KTagUri, "uri"); +//Attributes +_LIT8(KTagVersion, "version"); +_LIT8(KTagId, "id"); +_LIT8(KTagState, "state"); +_LIT8(KTagAor, "aor"); +_LIT8(KTagEvent, "event"); +_LIT8(KTagExpires, "expires"); +//attribute values +_LIT8(KTagFull, "full"); +_LIT8(KTagPartial, "partial"); +_LIT8(KTagActive, "active"); +_LIT8(KTagTerminated, "terminated"); +_LIT8(KTagRegistered, "registered"); +_LIT8(KTagCreated, "created"); +_LIT8(KTagRefreshed, "refreshed"); +_LIT8(KTagShortened, "shortened"); +_LIT8(KTagDeactivated, "deactivated"); +_LIT8(KTagProbation, "probation"); +_LIT8(KTagUnregistered, "unregistered"); +_LIT8(KTagRejected, "rejected"); +_LIT8(KTagExpired, "expired"); + +const TInt KValueTwo = 2; +const TInt KValueThree = 3; + +// current state, tag, enter, next state +struct TNotifyStateTransition + { + public: // Data + + const TDesC8* iTag; + TUint16 iState; + TUint8 iEnter; + TUint8 iNextState; + }; + +// ----------------------------------------------------------------------------- +// CSIPNotifyXmlBodyParser::NewL +// ----------------------------------------------------------------------------- +// +CSIPNotifyXmlBodyParser* CSIPNotifyXmlBodyParser::NewL() + { + CSIPNotifyXmlBodyParser* self = new( ELeave ) CSIPNotifyXmlBodyParser; + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop( self ); + return self; + } + +// ----------------------------------------------------------------------------- +// CSIPNotifyXmlBodyParser::CSIPNotifyXmlBodyParser +// ----------------------------------------------------------------------------- +// +CSIPNotifyXmlBodyParser::CSIPNotifyXmlBodyParser() + { + } + +// ----------------------------------------------------------------------------- +// CSIPNotifyXmlBodyParser::ConstructL +// ----------------------------------------------------------------------------- +// +void CSIPNotifyXmlBodyParser::ConstructL() + { + iParser = Xml::CParser::NewL( KMimeTypeXml, *this ); + } + +// ----------------------------------------------------------------------------- +// CSIPNotifyXmlBodyParser::~CSIPNotifyXmlBodyParser +// ----------------------------------------------------------------------------- +// +CSIPNotifyXmlBodyParser::~CSIPNotifyXmlBodyParser() + { + delete iRegElement; + delete iContact; + delete iParser; + } + +// ----------------------------------------------------------------------------- +// CSIPNotifyXmlBodyParser::StringPool +// ----------------------------------------------------------------------------- +// +RStringPool& CSIPNotifyXmlBodyParser::StringPool() + { + return iParser->StringPool(); + } + +// ----------------------------------------------------------------------------- +// CSIPNotifyXmlBodyParser::ParseL +// ----------------------------------------------------------------------------- +// +void CSIPNotifyXmlBodyParser::ParseL( CSIPRegInfoElement* aNotifyData, + const TDesC8& aXmlDocument ) + { + __ASSERT_ALWAYS( aXmlDocument.Length(), User::Leave( KErrCorrupt ) ); + //aNotifyData ownership is NOT transfered! + iNotifyData = aNotifyData; + iState = EInit; + iPreviousState = EInit; + iDepthOfUnknownElements = 0; + + // Parse the specified document into iNotifyData + Xml::ParseL( *iParser, aXmlDocument ); + + __ASSERT_ALWAYS( iNotifyData->HasVersion(), User::Leave( KErrCorrupt ) ); + __ASSERT_ALWAYS( iNotifyData->State().DesC().Length(), + User::Leave( KErrCorrupt ) ); + + iContact = NULL; + iRegElement = NULL; + iNotifyData = NULL; + } + +// ----------------------------------------------------------------------------- +// CSIPNotifyXmlBodyParser::OnStartElementL +// ----------------------------------------------------------------------------- +// +void CSIPNotifyXmlBodyParser::OnStartElementL( + const Xml::RTagInfo& aElement, + const Xml::RAttributeArray& aAttributes, + TInt aErrorCode ) + { + __ASSERT_ALWAYS( !aErrorCode, User::Leave( KErrCorrupt ) ); + // Get element name (e.g. "reginfo") and change state (Enter) + ChangeState( aElement.LocalName(), ETrue ); + + switch( iState ) + { + case EParsingRegInfo: + { + HandleRegInfoL( aElement, aAttributes ); + break; + } + case EParsingRegistration: + { + HandleRegistrationL( aAttributes ); + break; + } + case EParsingContact: + { + HandleContactL( aAttributes ); + break; + } + default: // do nothing + break; + } + } + +// ----------------------------------------------------------------------------- +// CSIPNotifyXmlBodyParser::OnEndElementL +// ----------------------------------------------------------------------------- +// +void CSIPNotifyXmlBodyParser::OnEndElementL( const Xml::RTagInfo& aElement, + TInt aErrorCode ) + { + __ASSERT_ALWAYS( !aErrorCode, User::Leave( KErrCorrupt ) ); + + // Get element name (e.g. "reginfo") and change state (Exit) + if ( iState == EParsingRegistration && iRegElement ) + { + CSIPRegistrationElement* regElement = iRegElement; + iRegElement = NULL; + CleanupStack::PushL( regElement ); + iNotifyData->RegistrationElements().AppendL( regElement ); + CleanupStack::Pop( regElement ); + } + + if ( iState == EParsingContact && iRegElement && iContact ) + { + CSIPContactElement* contact = iContact; + iContact = NULL; + CleanupStack::PushL( contact ); + iRegElement->ContactElements().AppendL( contact ); + CleanupStack::Pop( contact ); + } + + if ( iState == EParsingUri && iContact ) + { + //Check if there was a value + if ( iContact->Uri8().Uri().UriDes().Length() == 0 ) + { + User::Leave( KErrCorrupt ); + } + } + + ChangeState( aElement.LocalName(), EFalse ); + } + +// ----------------------------------------------------------------------------- +// CSIPNotifyXmlBodyParser::OnStartDocumentL +// ----------------------------------------------------------------------------- +// +void CSIPNotifyXmlBodyParser::OnStartDocumentL( + const Xml::RDocumentParameters& /*aDocParam*/, + TInt aErrorCode ) + { + __ASSERT_ALWAYS( !aErrorCode, User::Leave( KErrCorrupt ) ); + + iState = EParsingXmlDocument; + } + +// ----------------------------------------------------------------------------- +// CSIPNotifyXmlBodyParser::OnError +// ----------------------------------------------------------------------------- +// +void CSIPNotifyXmlBodyParser::OnError( TInt /*aErrorCode*/ ) + { + } + +// ----------------------------------------------------------------------------- +// CSIPNotifyXmlBodyParser::OnContentL +// ----------------------------------------------------------------------------- +// +void CSIPNotifyXmlBodyParser::OnContentL( const TDesC8& aBytes, + TInt aErrorCode ) + { + __ASSERT_ALWAYS( !aErrorCode, User::Leave( KErrCorrupt ) ); + if ( iState == EParsingUri ) + { + HandleUriL( aBytes ); + } + } + +// ----------------------------------------------------------------------------- +// CSIPNotifyXmlBodyParser::ChangeState +// ----------------------------------------------------------------------------- +// +void CSIPNotifyXmlBodyParser::ChangeState( const RString& aElementName, + TBool aEnter ) + { + // Table based XML validation transitions definition + const TNotifyStateTransition KNotifyTransitions[] = + { + { &KTagRegInfo, EParsingXmlDocument, ETrue, EParsingRegInfo }, + { &KTagRegistration, EParsingRegInfo, ETrue, EParsingRegistration }, + { &KTagContact, EParsingRegistration, ETrue, EParsingContact }, + { &KTagUri, EParsingContact, ETrue, EParsingUri }, + { &KTagUri, EParsingUri, EFalse, EParsingContact }, + { &KTagContact, EParsingContact, EFalse, EParsingRegistration }, + { &KTagRegistration, EParsingRegistration, EFalse, EParsingRegInfo }, + { &KTagRegInfo, EParsingRegInfo, EFalse, EInit } + }; + + // Try to find a matching entry from the transitions table + TInt count = sizeof( KNotifyTransitions ) / sizeof( TNotifyStateTransition ); + for( TInt i = 0; i < count; i++ ) + { + const TNotifyStateTransition& transition = KNotifyTransitions[ i ]; + if( ( iState == transition.iState ) && + ( aElementName.DesC() == *transition.iTag ) && + ( aEnter == transition.iEnter ) ) + { + // Match found, do transition + iState = (TNotifyParserState)transition.iNextState; + return; + } + } + + if ( aEnter ) + { + if ( iDepthOfUnknownElements++ == 0 ) + { + iPreviousState = iState; + iState = EParsingUnknown; + } + } + else + { + if ( --iDepthOfUnknownElements == 0 ) + { + iState = iPreviousState; + } + } + } + +// ----------------------------------------------------------------------------- +// CSIPNotifyXmlBodyParser::HandleRegInfoL +// ----------------------------------------------------------------------------- +// +void CSIPNotifyXmlBodyParser::HandleRegInfoL( + const Xml::RTagInfo& aElement, + const Xml::RAttributeArray& aAttributes ) + { + + //URI/ URN + _LIT8(KUriNamespace, "urn:ietf:params:xml:ns:reginfo"); + if( aElement.Uri().DesC() != KUriNamespace ) + { + User::Leave( KErrCorrupt ); + } + // Verify that we have correct number of attributes + if( aAttributes.Count() < KValueTwo ) + { + User::Leave( KErrCorrupt ); + } + + // Verify that we have the correct attribute(s) + TInt versionIndex = FindAttributeIndex( KTagVersion, aAttributes ); + if ( versionIndex < 0 ) + { + User::Leave( KErrCorrupt ); + } + + iNotifyData->SetVersion( + ConvertToTUintL( aAttributes[ versionIndex ].Value().DesC() ) ); + + TInt stateIndex = FindAttributeIndex( KTagState, aAttributes ); + if ( stateIndex < 0 ) + { + User::Leave( KErrCorrupt ); + } + + RString stateValue = aAttributes[ stateIndex ].Value(); + if ( stateValue.DesC() != KTagFull && stateValue.DesC() != KTagPartial ) + { + User::Leave( KErrCorrupt ); + } + + iNotifyData->SetState( stateValue ); + } + +// ----------------------------------------------------------------------------- +// CSIPNotifyXmlBodyParser::HandleRegistrationL +// ----------------------------------------------------------------------------- +// +void CSIPNotifyXmlBodyParser::HandleRegistrationL( + const Xml::RAttributeArray& aAttributes ) + { + // Verify that we have correct number of attributes + if( aAttributes.Count() < KValueThree ) + { + User::Leave( KErrCorrupt ); + } + + // Verify that we have the correct attribute(s) + TInt aorIndex = FindAttributeIndex( KTagAor, aAttributes ); + if ( aorIndex < 0 ) + { + User::Leave( KErrCorrupt ); + } + + TInt idIndex = FindAttributeIndex( KTagId, aAttributes ); + if ( idIndex < 0 ) + { + User::Leave( KErrCorrupt ); + } + + TInt stateIndex = FindAttributeIndex( KTagState, aAttributes ); + if ( stateIndex < 0 ) + { + User::Leave( KErrCorrupt ); + } + + if ( aAttributes[ stateIndex ].Value().DesC() != KTagActive && + aAttributes[ stateIndex ].Value().DesC() != KTagTerminated) + { + User::Leave( KErrCorrupt ); + } + + delete iRegElement; + iRegElement = NULL; + iRegElement = CSIPRegistrationElement::NewL(); + + TUriParser8 parser; + if ( aAttributes[ aorIndex ].Value().DesC().Length() == 0 ) + { + User::Leave( KErrCorrupt ); + } + User::LeaveIfError( + parser.Parse( aAttributes[ aorIndex ].Value().DesC() ) ); + CUri8* uri8 = CUri8::NewLC( parser ); + iRegElement->SetAORL( uri8 ); + CleanupStack::Pop( uri8 ); + + iRegElement->SetState( aAttributes[ stateIndex ].Value() ); + } + + +// ----------------------------------------------------------------------------- +// CSIPNotifyXmlBodyParser::HandleContactL +// ----------------------------------------------------------------------------- +// +void CSIPNotifyXmlBodyParser::HandleContactL( + const Xml::RAttributeArray& aAttributes ) + { + __ASSERT_ALWAYS( iRegElement ,User::Leave( KErrCorrupt )); + // Verify that we have correct number of attributes + if ( aAttributes.Count() < KValueThree ) + { + User::Leave( KErrCorrupt ); + } + + // Verify that we have the correct attribute(s) + // id + TInt idIndex = FindAttributeIndex( KTagId, aAttributes ); + if ( idIndex < 0 ) + { + User::Leave( KErrCorrupt ); + } + + // State + TInt stateIndex = FindAttributeIndex( KTagState, aAttributes ); + if ( stateIndex < 0 ) + { + User::Leave( KErrCorrupt ); + } + if ( aAttributes[ stateIndex ].Value().DesC() != KTagActive && + aAttributes[ stateIndex ].Value().DesC() != KTagTerminated) + { + User::Leave( KErrCorrupt ); + } + delete iContact; + iContact = NULL; + iContact = CSIPContactElement::NewL(); + iContact->SetState( aAttributes[ stateIndex ].Value() ); + + // event + TInt eventIndex = FindAttributeIndex( KTagEvent, aAttributes ); + if ( eventIndex < 0 ) + { + User::Leave( KErrCorrupt ); + } + RString event = aAttributes[ eventIndex ].Value(); + if ( event.DesC() != KTagRegistered && + event.DesC() != KTagCreated && + event.DesC() != KTagRefreshed && + event.DesC() != KTagShortened && + event.DesC() != KTagDeactivated && + event.DesC() != KTagProbation && + event.DesC() != KTagUnregistered && + event.DesC() != KTagRejected && + event.DesC() != KTagExpired ) + { + User::Leave( KErrCorrupt ); + } + iContact->SetEvent( event ); + + //Optional attributes + TInt expiresIndex = FindAttributeIndex( KTagExpires, aAttributes ); + if ( expiresIndex >= 0 ) + { + iContact->SetExpires( + ConvertToTUintL( aAttributes[ expiresIndex ].Value().DesC() ) ); + } + } + +// ----------------------------------------------------------------------------- +// CSIPNotifyXmlBodyParser::HandleUriL +// ----------------------------------------------------------------------------- +// +void CSIPNotifyXmlBodyParser::HandleUriL( const TDesC8& aBytes ) + { + __ASSERT_ALWAYS( iContact, User::Leave( KErrCorrupt ) ); + + HBufC8* temp = aBytes.AllocLC(); + temp->Des().Trim(); + + if ( temp->Length() == 0 ) + { + User::Leave( KErrCorrupt ); + } + + TUriParser8 parser; + User::LeaveIfError( parser.Parse( *temp ) ); + CUri8* uri8 = CUri8::NewLC( parser ); + iContact->SetUri8L( uri8 ); + CleanupStack::Pop( uri8 ); + CleanupStack::PopAndDestroy( temp ); + } + +// ----------------------------------------------------------------------------- +// CSIPNotifyXmlBodyParser::ConvertToTUintL +// ----------------------------------------------------------------------------- +// +TUint CSIPNotifyXmlBodyParser::ConvertToTUintL( const TDesC8& aValue ) + { + __ASSERT_ALWAYS( aValue.Length(), User::Leave( KErrCorrupt ) ); + TLex8 lex( aValue ); + TUint value = 0; + if ( lex.Val( value ) != KErrNone) + { + User::Leave( KErrCorrupt ); + } + return value; + } + +// ----------------------------------------------------------------------------- +// CSIPNotifyXmlBodyParser::FindAttributeIndex +// ----------------------------------------------------------------------------- +// +TInt CSIPNotifyXmlBodyParser::FindAttributeIndex( + const TDesC8& aName, + const Xml::RAttributeArray& aAttributes) const + { + for (TInt i=0; i < aAttributes.Count(); i++) + { + if ( aAttributes[ i ].Attribute().LocalName().DesC() == aName ) + { + return i; + } + } + return KErrNotFound; + }