realtimenetprots/sipfw/ProfileAgent/IMS_Agent/Src/CSIPNotifyXmlBodyParser.cpp
changeset 0 307788aac0a8
equal deleted inserted replaced
-1:000000000000 0:307788aac0a8
       
     1 // Copyright (c) 2006-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 // Name          : CSIPNotifyXmlBodyParser.cpp
       
    15 // Part of       : ProfileAgent
       
    16 // Version       : SIP/4.0
       
    17 //
       
    18 
       
    19 
       
    20 
       
    21 #include <uri8.h>
       
    22 #include "CSIPNotifyXmlBodyParser.h"
       
    23 #include "sipreginfoelement.h"
       
    24 #include "sipregistrationelement.h"
       
    25 #include "sipcontactelement.h"
       
    26 #include <xml/documentparameters.h>
       
    27 
       
    28 _LIT8( KMimeTypeXml, "text/xml" );
       
    29 
       
    30 //Elements
       
    31 _LIT8(KTagRegInfo, "reginfo");
       
    32 _LIT8(KTagRegistration, "registration");
       
    33 _LIT8(KTagContact, "contact");
       
    34 _LIT8(KTagUri, "uri");
       
    35 //Attributes
       
    36 _LIT8(KTagVersion, "version");
       
    37 _LIT8(KTagId, "id");
       
    38 _LIT8(KTagState, "state");
       
    39 _LIT8(KTagAor, "aor");
       
    40 _LIT8(KTagEvent, "event");
       
    41 _LIT8(KTagExpires, "expires");
       
    42 //attribute values
       
    43 _LIT8(KTagFull, "full");
       
    44 _LIT8(KTagPartial, "partial");
       
    45 _LIT8(KTagActive, "active");
       
    46 _LIT8(KTagTerminated, "terminated");
       
    47 _LIT8(KTagRegistered, "registered");
       
    48 _LIT8(KTagCreated, "created");
       
    49 _LIT8(KTagRefreshed, "refreshed");
       
    50 _LIT8(KTagShortened, "shortened");
       
    51 _LIT8(KTagDeactivated, "deactivated");
       
    52 _LIT8(KTagProbation, "probation");
       
    53 _LIT8(KTagUnregistered, "unregistered");
       
    54 _LIT8(KTagRejected, "rejected");
       
    55 _LIT8(KTagExpired, "expired");
       
    56 
       
    57 const TInt KValueTwo = 2;
       
    58 const TInt KValueThree = 3;
       
    59 
       
    60 // current state, tag, enter, next state
       
    61 struct TNotifyStateTransition
       
    62 	{
       
    63 	public: // Data
       
    64 
       
    65 		const TDesC8* iTag;
       
    66 		TUint16 iState;
       
    67 		TUint8 iEnter;
       
    68 		TUint8 iNextState;
       
    69 	};
       
    70 	
       
    71 // -----------------------------------------------------------------------------
       
    72 // CSIPNotifyXmlBodyParser::NewL
       
    73 // -----------------------------------------------------------------------------
       
    74 //
       
    75 CSIPNotifyXmlBodyParser* CSIPNotifyXmlBodyParser::NewL()
       
    76 	{
       
    77 	CSIPNotifyXmlBodyParser* self = new( ELeave ) CSIPNotifyXmlBodyParser;
       
    78 	CleanupStack::PushL( self );
       
    79 	self->ConstructL();
       
    80 	CleanupStack::Pop( self );
       
    81 	return self;
       
    82 	}
       
    83 
       
    84 // -----------------------------------------------------------------------------
       
    85 // CSIPNotifyXmlBodyParser::CSIPNotifyXmlBodyParser
       
    86 // -----------------------------------------------------------------------------
       
    87 //
       
    88 CSIPNotifyXmlBodyParser::CSIPNotifyXmlBodyParser()
       
    89 	{
       
    90 	}
       
    91 
       
    92 // -----------------------------------------------------------------------------
       
    93 // CSIPNotifyXmlBodyParser::ConstructL
       
    94 // -----------------------------------------------------------------------------
       
    95 //
       
    96 void CSIPNotifyXmlBodyParser::ConstructL()
       
    97 	{
       
    98 	iParser = Xml::CParser::NewL( KMimeTypeXml, *this );
       
    99 	}
       
   100 
       
   101 // -----------------------------------------------------------------------------
       
   102 // CSIPNotifyXmlBodyParser::~CSIPNotifyXmlBodyParser
       
   103 // -----------------------------------------------------------------------------
       
   104 //
       
   105 CSIPNotifyXmlBodyParser::~CSIPNotifyXmlBodyParser()
       
   106 	{
       
   107 	delete iRegElement;
       
   108 	delete iContact;
       
   109 	delete iParser;
       
   110 	}
       
   111 
       
   112 // -----------------------------------------------------------------------------
       
   113 // CSIPNotifyXmlBodyParser::StringPool
       
   114 // -----------------------------------------------------------------------------
       
   115 //
       
   116 RStringPool& CSIPNotifyXmlBodyParser::StringPool()
       
   117     {
       
   118     return iParser->StringPool();
       
   119     }
       
   120 
       
   121 // -----------------------------------------------------------------------------
       
   122 // CSIPNotifyXmlBodyParser::ParseL
       
   123 // -----------------------------------------------------------------------------
       
   124 //
       
   125 void CSIPNotifyXmlBodyParser::ParseL( CSIPRegInfoElement* aNotifyData,
       
   126 								      const TDesC8& aXmlDocument )
       
   127 	{
       
   128 	__ASSERT_ALWAYS( aXmlDocument.Length(), User::Leave( KErrCorrupt ) );
       
   129 	//aNotifyData ownership is NOT transfered!
       
   130 	iNotifyData = aNotifyData;
       
   131 	iState = EInit;
       
   132 	iPreviousState = EInit;
       
   133 	iDepthOfUnknownElements = 0;
       
   134 	
       
   135 	// Parse the specified document into iNotifyData
       
   136 	Xml::ParseL( *iParser, aXmlDocument );
       
   137 	
       
   138 	__ASSERT_ALWAYS( iNotifyData->HasVersion(), User::Leave( KErrCorrupt ) );
       
   139     __ASSERT_ALWAYS( iNotifyData->State().DesC().Length(), 
       
   140                      User::Leave( KErrCorrupt ) );
       
   141 
       
   142 	iContact = NULL;	
       
   143 	iRegElement = NULL;
       
   144 	iNotifyData = NULL;
       
   145 	}
       
   146 
       
   147 // -----------------------------------------------------------------------------
       
   148 // CSIPNotifyXmlBodyParser::OnStartElementL
       
   149 // -----------------------------------------------------------------------------
       
   150 //
       
   151 void CSIPNotifyXmlBodyParser::OnStartElementL(
       
   152     const Xml::RTagInfo& aElement,
       
   153     const Xml::RAttributeArray& aAttributes,
       
   154     TInt aErrorCode )
       
   155 	{
       
   156 	__ASSERT_ALWAYS( !aErrorCode, User::Leave( KErrCorrupt ) );
       
   157 	// Get element name (e.g. "reginfo") and change state (Enter)
       
   158 	ChangeState( aElement.LocalName(), ETrue );
       
   159 
       
   160 	switch( iState )
       
   161 		{
       
   162 		case EParsingRegInfo:
       
   163 			{
       
   164 			HandleRegInfoL( aElement, aAttributes );
       
   165 			break;
       
   166 			}
       
   167 		case EParsingRegistration:
       
   168 			{
       
   169 			HandleRegistrationL( aAttributes );
       
   170 			break;
       
   171 			}
       
   172 		case EParsingContact:
       
   173 			{
       
   174 			HandleContactL( aAttributes );
       
   175 			break;
       
   176 			}
       
   177 		default: // do nothing
       
   178 			break;
       
   179 		}
       
   180 	}
       
   181 
       
   182 // -----------------------------------------------------------------------------
       
   183 // CSIPNotifyXmlBodyParser::OnEndElementL
       
   184 // -----------------------------------------------------------------------------
       
   185 //
       
   186 void CSIPNotifyXmlBodyParser::OnEndElementL( const Xml::RTagInfo& aElement,
       
   187 									         TInt aErrorCode )
       
   188 	{
       
   189 	__ASSERT_ALWAYS( !aErrorCode, User::Leave( KErrCorrupt ) );
       
   190 	
       
   191 	// Get element name (e.g. "reginfo") and change state (Exit)
       
   192 	if ( iState == EParsingRegistration && iRegElement )
       
   193 		{
       
   194 		CSIPRegistrationElement* regElement = iRegElement;
       
   195 		iRegElement = NULL;
       
   196 		CleanupStack::PushL( regElement );		
       
   197 		iNotifyData->RegistrationElements().AppendL( regElement );
       
   198 		CleanupStack::Pop( regElement );
       
   199 		}
       
   200 		
       
   201 	if ( iState == EParsingContact && iRegElement && iContact )
       
   202 		{
       
   203 		CSIPContactElement* contact = iContact;
       
   204 		iContact = NULL;
       
   205 		CleanupStack::PushL( contact );
       
   206 		iRegElement->ContactElements().AppendL( contact );
       
   207 		CleanupStack::Pop( contact );
       
   208 		}
       
   209 
       
   210 	if ( iState == EParsingUri && iContact )
       
   211 		{
       
   212 		//Check if there was a value
       
   213 		if ( iContact->Uri8().Uri().UriDes().Length() == 0 )
       
   214 			{
       
   215 			User::Leave( KErrCorrupt );
       
   216 			}
       
   217 		}
       
   218 
       
   219 	ChangeState( aElement.LocalName(), EFalse );
       
   220 	}
       
   221 
       
   222 // -----------------------------------------------------------------------------
       
   223 // CSIPNotifyXmlBodyParser::OnStartDocumentL
       
   224 // -----------------------------------------------------------------------------
       
   225 //
       
   226 void CSIPNotifyXmlBodyParser::OnStartDocumentL( 
       
   227     const Xml::RDocumentParameters& /*aDocParam*/,
       
   228     TInt aErrorCode )
       
   229 	{
       
   230 	__ASSERT_ALWAYS( !aErrorCode, User::Leave( KErrCorrupt ) );
       
   231 
       
   232 	iState = EParsingXmlDocument;
       
   233 	}
       
   234 
       
   235 // -----------------------------------------------------------------------------
       
   236 // CSIPNotifyXmlBodyParser::OnError
       
   237 // -----------------------------------------------------------------------------
       
   238 //
       
   239 void CSIPNotifyXmlBodyParser::OnError( TInt /*aErrorCode*/ )
       
   240 	{
       
   241 	}
       
   242 	
       
   243 // -----------------------------------------------------------------------------
       
   244 // CSIPNotifyXmlBodyParser::OnContentL
       
   245 // -----------------------------------------------------------------------------
       
   246 //
       
   247 void CSIPNotifyXmlBodyParser::OnContentL( const TDesC8& aBytes,
       
   248                                           TInt aErrorCode )
       
   249 	{
       
   250 	__ASSERT_ALWAYS( !aErrorCode, User::Leave( KErrCorrupt ) );
       
   251 	if ( iState == EParsingUri )
       
   252 		{
       
   253 		HandleUriL( aBytes );
       
   254 		}
       
   255 	}
       
   256 
       
   257 // -----------------------------------------------------------------------------
       
   258 // CSIPNotifyXmlBodyParser::ChangeState
       
   259 // -----------------------------------------------------------------------------
       
   260 //
       
   261 void CSIPNotifyXmlBodyParser::ChangeState( const RString& aElementName,
       
   262 										   TBool aEnter )
       
   263 	{
       
   264 	// Table based XML validation transitions definition
       
   265 	const TNotifyStateTransition KNotifyTransitions[] =
       
   266 	    {
       
   267 	    { &KTagRegInfo, EParsingXmlDocument, ETrue, EParsingRegInfo },
       
   268 	    { &KTagRegistration, EParsingRegInfo, ETrue, EParsingRegistration },
       
   269 	    { &KTagContact, EParsingRegistration, ETrue, EParsingContact },
       
   270 	    { &KTagUri, EParsingContact, ETrue, EParsingUri },
       
   271 	    { &KTagUri, EParsingUri, EFalse, EParsingContact },	
       
   272 	    { &KTagContact, EParsingContact, EFalse, EParsingRegistration },
       
   273 	    { &KTagRegistration, EParsingRegistration, EFalse, EParsingRegInfo },
       
   274 	    { &KTagRegInfo, EParsingRegInfo, EFalse, EInit }
       
   275 	    };
       
   276 	
       
   277 	// Try to find a matching entry from the transitions table
       
   278 	TInt count = sizeof( KNotifyTransitions ) / sizeof( TNotifyStateTransition );
       
   279 	for( TInt i = 0; i < count; i++ )
       
   280 		{
       
   281 		const TNotifyStateTransition& transition = KNotifyTransitions[ i ];
       
   282 		if( ( iState == transition.iState ) &&
       
   283 			( aElementName.DesC() == *transition.iTag ) &&
       
   284 			( aEnter == transition.iEnter ) )
       
   285 			{
       
   286 			// Match found, do transition
       
   287 			iState = (TNotifyParserState)transition.iNextState;
       
   288 			return;
       
   289 			}
       
   290 		}
       
   291 		
       
   292 	if ( aEnter )
       
   293 	    {
       
   294 	    if ( iDepthOfUnknownElements++ == 0 )
       
   295 	        {
       
   296 	        iPreviousState = iState;
       
   297 	        iState = EParsingUnknown;     
       
   298 	        }
       
   299 	    }
       
   300 	else
       
   301 	    {
       
   302 	    if ( --iDepthOfUnknownElements == 0 )
       
   303 	        {
       
   304 	        iState = iPreviousState;
       
   305 	        }
       
   306 	    }
       
   307 	}
       
   308 	
       
   309 // -----------------------------------------------------------------------------
       
   310 // CSIPNotifyXmlBodyParser::HandleRegInfoL
       
   311 // -----------------------------------------------------------------------------
       
   312 //
       
   313 void CSIPNotifyXmlBodyParser::HandleRegInfoL( 
       
   314     const Xml::RTagInfo& aElement,
       
   315     const Xml::RAttributeArray& aAttributes )
       
   316 	{
       
   317 	
       
   318 	//URI/ URN
       
   319 	_LIT8(KUriNamespace, "urn:ietf:params:xml:ns:reginfo");
       
   320 	if( aElement.Uri().DesC() != KUriNamespace )
       
   321 		{
       
   322 		User::Leave( KErrCorrupt );
       
   323 		}
       
   324 	// Verify that we have correct number of attributes
       
   325 	if( aAttributes.Count() < KValueTwo )
       
   326 		{
       
   327 		User::Leave( KErrCorrupt );
       
   328 		}
       
   329 		
       
   330 	// Verify that we have the correct attribute(s)
       
   331 	TInt versionIndex = FindAttributeIndex( KTagVersion, aAttributes );
       
   332 	if ( versionIndex < 0 )
       
   333 		{
       
   334 		User::Leave( KErrCorrupt );
       
   335 		}	
       
   336 			
       
   337 	iNotifyData->SetVersion( 
       
   338 	    ConvertToTUintL( aAttributes[ versionIndex ].Value().DesC() ) );	
       
   339 	
       
   340 	TInt stateIndex = FindAttributeIndex( KTagState, aAttributes );
       
   341 	if ( stateIndex < 0 )
       
   342 		{
       
   343 		User::Leave( KErrCorrupt );
       
   344 		}
       
   345 	
       
   346 	RString stateValue = aAttributes[ stateIndex ].Value();
       
   347 	if ( stateValue.DesC() != KTagFull && stateValue.DesC() != KTagPartial )
       
   348 		{
       
   349 		User::Leave( KErrCorrupt );
       
   350 		}
       
   351 		
       
   352 	iNotifyData->SetState( stateValue );
       
   353 	}
       
   354 
       
   355 // -----------------------------------------------------------------------------
       
   356 // CSIPNotifyXmlBodyParser::HandleRegistrationL
       
   357 // -----------------------------------------------------------------------------
       
   358 //
       
   359 void CSIPNotifyXmlBodyParser::HandleRegistrationL( 
       
   360     const Xml::RAttributeArray& aAttributes )
       
   361 	{
       
   362 	// Verify that we have correct number of attributes
       
   363 	if( aAttributes.Count() < KValueThree )
       
   364 		{
       
   365 		User::Leave( KErrCorrupt );
       
   366 		}		
       
   367 		
       
   368 	// Verify that we have the correct attribute(s)
       
   369 	TInt aorIndex = FindAttributeIndex( KTagAor, aAttributes );
       
   370 	if ( aorIndex < 0 )
       
   371 		{
       
   372 		User::Leave( KErrCorrupt );
       
   373 		}
       
   374 	
       
   375 	TInt idIndex = FindAttributeIndex( KTagId, aAttributes );
       
   376 	if ( idIndex < 0 )
       
   377 		{
       
   378 		User::Leave( KErrCorrupt );
       
   379 		}		
       
   380 	
       
   381 	TInt stateIndex = FindAttributeIndex( KTagState, aAttributes );
       
   382 	if ( stateIndex < 0 )
       
   383 		{
       
   384 		User::Leave( KErrCorrupt );
       
   385 		}	
       
   386 		
       
   387 	if ( aAttributes[ stateIndex ].Value().DesC() != KTagActive && 
       
   388 	     aAttributes[ stateIndex ].Value().DesC() != KTagTerminated)
       
   389 		{
       
   390 		User::Leave( KErrCorrupt );
       
   391 		}	
       
   392 		
       
   393 	delete iRegElement;
       
   394 	iRegElement = NULL;
       
   395 	iRegElement = CSIPRegistrationElement::NewL();
       
   396 	
       
   397 	TUriParser8 parser;
       
   398 	if ( aAttributes[ aorIndex ].Value().DesC().Length() == 0 )
       
   399 		{
       
   400 		User::Leave( KErrCorrupt );
       
   401 		}
       
   402     User::LeaveIfError( 
       
   403         parser.Parse( aAttributes[ aorIndex ].Value().DesC() ) );
       
   404     CUri8* uri8 = CUri8::NewLC( parser );
       
   405 	iRegElement->SetAORL( uri8 );
       
   406 	CleanupStack::Pop( uri8 );
       
   407 		
       
   408 	iRegElement->SetState( aAttributes[ stateIndex ].Value() );		
       
   409 	}
       
   410 
       
   411 
       
   412 // -----------------------------------------------------------------------------
       
   413 // CSIPNotifyXmlBodyParser::HandleContactL
       
   414 // -----------------------------------------------------------------------------
       
   415 //
       
   416 void CSIPNotifyXmlBodyParser::HandleContactL(
       
   417     const Xml::RAttributeArray& aAttributes )
       
   418 	{
       
   419 	__ASSERT_ALWAYS( iRegElement ,User::Leave( KErrCorrupt ));
       
   420 	// Verify that we have correct number of attributes
       
   421 	if ( aAttributes.Count() < KValueThree )
       
   422 		{
       
   423 		User::Leave( KErrCorrupt );
       
   424 		}
       
   425 				
       
   426 	// Verify that we have the correct attribute(s)
       
   427 	// id
       
   428 	TInt idIndex = FindAttributeIndex( KTagId, aAttributes );
       
   429 	if ( idIndex < 0 )
       
   430 		{
       
   431 		User::Leave( KErrCorrupt );
       
   432 		}
       
   433 
       
   434     // State
       
   435 	TInt stateIndex = FindAttributeIndex( KTagState, aAttributes );
       
   436 	if ( stateIndex < 0 )
       
   437 		{
       
   438 		User::Leave( KErrCorrupt );
       
   439 		}		
       
   440 	if ( aAttributes[ stateIndex ].Value().DesC() != KTagActive && 
       
   441 	     aAttributes[ stateIndex ].Value().DesC() != KTagTerminated)
       
   442 		{
       
   443 		User::Leave( KErrCorrupt );
       
   444 		}
       
   445 	delete iContact;
       
   446 	iContact = NULL;
       
   447 	iContact = CSIPContactElement::NewL();		
       
   448 	iContact->SetState( aAttributes[ stateIndex ].Value() );
       
   449 	
       
   450 	// event
       
   451 	TInt eventIndex = FindAttributeIndex( KTagEvent, aAttributes );
       
   452 	if ( eventIndex < 0 )
       
   453 		{
       
   454 		User::Leave( KErrCorrupt );
       
   455 		}
       
   456 	RString event = aAttributes[ eventIndex ].Value();
       
   457 	if ( event.DesC() != KTagRegistered && 
       
   458 	     event.DesC() != KTagCreated &&
       
   459 	     event.DesC() != KTagRefreshed &&
       
   460 	     event.DesC() != KTagShortened && 
       
   461 	     event.DesC() != KTagDeactivated &&
       
   462 	     event.DesC() != KTagProbation &&
       
   463 	     event.DesC() != KTagUnregistered &&
       
   464 	     event.DesC() != KTagRejected &&
       
   465 	     event.DesC() != KTagExpired )
       
   466 		{
       
   467 		User::Leave( KErrCorrupt );
       
   468 		}	
       
   469 	iContact->SetEvent( event );	
       
   470 
       
   471 	//Optional attributes
       
   472 	TInt expiresIndex = FindAttributeIndex( KTagExpires, aAttributes );
       
   473 	if ( expiresIndex >= 0 )
       
   474 		{
       
   475         iContact->SetExpires( 
       
   476             ConvertToTUintL( aAttributes[ expiresIndex ].Value().DesC() ) );		
       
   477 		}
       
   478 	}
       
   479 
       
   480 // -----------------------------------------------------------------------------
       
   481 // CSIPNotifyXmlBodyParser::HandleUriL
       
   482 // -----------------------------------------------------------------------------
       
   483 //
       
   484 void CSIPNotifyXmlBodyParser::HandleUriL( const TDesC8& aBytes )
       
   485 	{
       
   486 	__ASSERT_ALWAYS( iContact, User::Leave( KErrCorrupt ) );
       
   487 	
       
   488 	HBufC8* temp = aBytes.AllocLC();
       
   489 	temp->Des().Trim();
       
   490 	
       
   491 	if ( temp->Length() == 0 )
       
   492 		{
       
   493 		User::Leave( KErrCorrupt );
       
   494 		}
       
   495 		
       
   496 	TUriParser8 parser;
       
   497     User::LeaveIfError( parser.Parse( *temp ) );
       
   498     CUri8* uri8 = CUri8::NewLC( parser );
       
   499 	iContact->SetUri8L( uri8 );
       
   500 	CleanupStack::Pop( uri8 );
       
   501 	CleanupStack::PopAndDestroy( temp );
       
   502 	}
       
   503 	
       
   504 // -----------------------------------------------------------------------------
       
   505 // CSIPNotifyXmlBodyParser::ConvertToTUintL
       
   506 // -----------------------------------------------------------------------------
       
   507 //
       
   508 TUint CSIPNotifyXmlBodyParser::ConvertToTUintL( const TDesC8& aValue )
       
   509 	{
       
   510 	__ASSERT_ALWAYS( aValue.Length(), User::Leave( KErrCorrupt ) );
       
   511 	TLex8 lex( aValue );
       
   512 	TUint value = 0;
       
   513 	if ( lex.Val( value ) != KErrNone)
       
   514 		{
       
   515 		User::Leave( KErrCorrupt );
       
   516 		}
       
   517 	return value;
       
   518 	}
       
   519 	
       
   520 // -----------------------------------------------------------------------------
       
   521 // CSIPNotifyXmlBodyParser::FindAttributeIndex
       
   522 // -----------------------------------------------------------------------------
       
   523 //	
       
   524 TInt CSIPNotifyXmlBodyParser::FindAttributeIndex(
       
   525     const TDesC8& aName,
       
   526     const Xml::RAttributeArray& aAttributes) const
       
   527     {
       
   528     for (TInt i=0; i < aAttributes.Count(); i++)
       
   529         {
       
   530         if ( aAttributes[ i ].Attribute().LocalName().DesC() == aName )
       
   531             {
       
   532             return i;
       
   533             }
       
   534         }
       
   535     return KErrNotFound;
       
   536     }