genericservices/httputils/UriParser/TUriParser.cpp
changeset 0 e4d67989cc36
child 27 3a7375419266
equal deleted inserted replaced
-1:000000000000 0:e4d67989cc36
       
     1 // Copyright (c) 2001-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 //
       
    15 
       
    16 // System includes
       
    17 #include <uri8.h>
       
    18 #include <uri16.h>
       
    19 #include <uriutils.h>
       
    20 #include <uriutilscommon.h>
       
    21 
       
    22 
       
    23 //User includes
       
    24 #include "TUriParserInternal.h"
       
    25 #include "UriUtilsInternal.h"
       
    26 #include "TUriCInternal.h"
       
    27 #include "GenericUriParser.h"
       
    28 #include "SipUriParser.h"
       
    29 
       
    30 
       
    31 
       
    32 // Constants
       
    33 //
       
    34 
       
    35 _LIT8(KSIP, "Sip");
       
    36 _LIT8(KSIPS, "Sips");
       
    37 
       
    38 
       
    39 //
       
    40 //
       
    41 // Implementation of TUriParser8
       
    42 //
       
    43 //
       
    44 
       
    45 /**
       
    46 	Constructor.
       
    47 	
       
    48 	@since			6.0
       
    49  */
       
    50 EXPORT_C TUriParser8::TUriParser8()
       
    51 : TUriC8()
       
    52 	{
       
    53 	}
       
    54 	
       
    55 /**
       
    56 	Parses the descriptor aUri into uri components.
       
    57 	
       
    58 	@since			6.0
       
    59 	@param			aUri A reference to a descriptor pointer to be parsed.
       
    60 	@return			KErrNone if the descriptor has been parsed into uri components.
       
    61 	KUriUtilsParserErrInvalidUri if the descriptor is an invalid uri.
       
    62 	KErrNoMemory if out of memory
       
    63 	@post			The object references the input descriptor.
       
    64  */
       
    65 EXPORT_C TInt TUriParser8::Parse(const TDesC8& aUri)
       
    66 	{
       
    67 	// Reset the Uri information and then set the Uri
       
    68 	if( iUriDes.Length() )
       
    69 		{
       
    70 		Reset();
       
    71 		}
       
    72 	iUriDes.Set(aUri);
       
    73 
       
    74 	// Check uri is valid
       
    75 	if( iUriDes.Length() && iUriDes[0]==KSchemeDelimiter )
       
    76 		{
       
    77 		return KUriUtilsErrInvalidUri;
       
    78 		}
       
    79 	
       
    80 	TPtrC8 schemeComponent;
       
    81 	RetrieveScheme(iUriDes,schemeComponent);
       
    82 	CGenericUriParser* UriHandler = NULL;
       
    83 	TInt err=KErrNone;
       
    84 	if(schemeComponent.CompareF(KSIP()) == 0 || schemeComponent.CompareF(KSIPS()) == 0 )
       
    85 		{
       
    86 	    TRAP(err,UriHandler = CSIPUriParser::NewL());
       
    87 		}
       
    88 	else
       
    89 		{
       
    90 	    TRAP(err,UriHandler = CGenericUriParser::NewL());
       
    91  		}
       
    92 	if(UriHandler)
       
    93 		{
       
    94 		UriHandler->DoParseUri(iUriDes, iComponent);
       
    95 		delete UriHandler;
       
    96 		}
       
    97        
       
    98 		return err;      
       
    99 
       
   100 	}
       
   101 
       
   102 /**
       
   103 	Parses the descriptor aUri into uri components.
       
   104 	
       
   105 	@param			aUri A reference to a descriptor pointer of an Uri.
       
   106 	@param			aScheme A reference to a descriptor pointer for retieved 
       
   107 					scheme component.
       
   108  */
       
   109 void TUriParser8::RetrieveScheme(const TPtrC8& aUri, TPtrC8& aScheme)
       
   110 	{
       
   111 	TInt schemePos = aUri.Locate(KSchemeDelimiter);
       
   112 	if(schemePos != KErrNotFound)
       
   113 		{
       
   114 		// Got a scheme - store information
       
   115 		aScheme.Set(aUri.Left(schemePos));
       
   116 		}
       
   117 	}
       
   118 
       
   119 //
       
   120 //
       
   121 // Implementation of TUriParser16
       
   122 //
       
   123 //
       
   124 
       
   125 /**
       
   126 	Constructor.
       
   127 	
       
   128 	@since			6.0
       
   129 	@deprecated Deprecated in 9.1
       
   130  */
       
   131 EXPORT_C TUriParser16::TUriParser16()
       
   132 : TUriC16()
       
   133 	{
       
   134 	}
       
   135 
       
   136 /**
       
   137 	Parses the descriptor aUri into uri components.
       
   138 	
       
   139 	@since			6.0
       
   140 	@deprecated Deprecated in 9.1
       
   141 	@param			aUri A reference to a descriptor pointer to be parsed.
       
   142 	@return			KErrNone if the descriptor has been parsed into uri components.
       
   143 	EUriParserErrInvalidUri if the descriptor is an invalid uri.
       
   144 	@post			The object references the input descriptor.
       
   145  */
       
   146 EXPORT_C TInt TUriParser16::Parse(const TDesC16& aUri)
       
   147 	{
       
   148 	// Reset the Uri information and then set the Uri
       
   149 	if( iUriDes.Length() )
       
   150 		Reset();
       
   151 	iUriDes.Set(aUri);
       
   152 
       
   153 	// Check uri is valid
       
   154 	if( iUriDes.Length() && iUriDes[0]==KSchemeDelimiter )
       
   155 		return KUriUtilsErrInvalidUri;
       
   156 
       
   157 	// Parse the uri.
       
   158 	DoParseUri(iUriDes, iComponent);
       
   159 	return KErrNone;
       
   160 	}
       
   161 
       
   162 //
       
   163 //
       
   164 // Implementation of templated LOCAL functions
       
   165 //
       
   166 //
       
   167 
       
   168 /**
       
   169 	Templated function that parses a descriptor into the components of a uri.
       
   170 						
       
   171 	@since			6.0
       
   172 	@param			aUri		The descriptor with the data to parse.
       
   173 	@param			aComponent	The output array of descriptors of each uri component.
       
   174 	@pre 			Each descriptor pointer in aComponent has had the pointer to its
       
   175 					associated descriptor buffer set to NULL.
       
   176 	@post			The descriptor pointers in aComponent are updated to refer to the 
       
   177 					appropriate sections of aUri that represent the components of a uri.
       
   178 */
       
   179 template<class TPtrCType>
       
   180 void DoParseUri(const TPtrCType& aUri, TPtrCType aComponent[])
       
   181 	{
       
   182 	// Parse the components
       
   183 	TPtrCType uri = aUri;
       
   184 	TInt consumed = 0;
       
   185 	TPtrCType& scheme = aComponent[EUriScheme];
       
   186 	if( (consumed = ParseScheme(uri, scheme)) > 0 )
       
   187 		{
       
   188 		uri.Set(uri.Mid(consumed));
       
   189 		}
       
   190 	if( (consumed = ParseAuthority(uri, aComponent[EUriUserinfo], 
       
   191 		 aComponent[EUriHost], aComponent[EUriPort], IsNetworkScheme(scheme))) > 0 )
       
   192 		{
       
   193 		uri.Set(uri.Mid(consumed));
       
   194 		}
       
   195 	if( (consumed = ParsePath(uri, aComponent[EUriPath])) > 0 )
       
   196 		{
       
   197 		uri.Set(uri.Mid(consumed));
       
   198 		}
       
   199 	if( (consumed = ParseQuery(uri, aComponent[EUriQuery])) > 0 )
       
   200 		{
       
   201 		uri.Set(uri.Mid(consumed));
       
   202 		}
       
   203 	if( (consumed = ParseFragment(uri, aComponent[EUriFragment])) > 0 )
       
   204 		{
       
   205 		uri.Set(uri.Mid(consumed));
       
   206 		}
       
   207 	}
       
   208 
       
   209 /**
       
   210 	Templated function to parse a descriptor for a scheme component. If a scheme is found 
       
   211 	then the output argument aScheme is set to refer to it.
       
   212 						
       
   213 	@since			6.0
       
   214 	@param			aUri	The descriptor containing the uri to be parsed for 
       
   215 	a scheme.
       
   216 	@param			aScheme	The output descriptor to refer to the scheme
       
   217 	@return			The number of characters consumed in parsing the scheme.
       
   218 	@pre 			The output descriptor has been initialized so that the pointer
       
   219 					to the associated descriptor buffer is NULL. The input descriptor 
       
   220 					is set to the start of the uri.
       
   221 	@post			If a scheme component exists then the output descriptor refers
       
   222 					to it, otherwise the output descriptor is left unchanged.
       
   223 */
       
   224 template<class TPtrCType>
       
   225 TInt ParseScheme(const TPtrCType& aUri, TPtrCType& aScheme)
       
   226 	{
       
   227 	// Get the descriptor and look for scheme delimiter
       
   228 	TInt consumed =0;
       
   229 	TInt endSchemePos = FindFirstUriDelimiter(aUri, ESchemeDelimiterSearch);
       
   230 
       
   231 	if( endSchemePos != KErrNotFound )
       
   232 		{
       
   233 		// Got a scheme - store information
       
   234 		aScheme.Set(aUri.Left(endSchemePos));
       
   235 
       
   236 		// Set consumed amount move past scheme delimiter
       
   237 		consumed = endSchemePos + 1;
       
   238 		}
       
   239 	return consumed;
       
   240 	}
       
   241 	
       
   242 /**
       
   243 	Templated function to parse a descriptor for an authority component. If an authority is 
       
   244 	found then the output arguments aUserinfo, aHost and aPort are set to refer to those parts 
       
   245 	of the authority component. If an authority component exists then the host part exists. The 
       
   246 	userinfo and port parts are optional.
       
   247 						
       
   248 	@since			6.0
       
   249 	@param			aUri		The descriptor containing the uri to be parsed 
       
   250 					for an authority.
       
   251 	@param			aUserinfo	The output descriptor for the userinfo component.
       
   252 	@param			aHost		The output descriptor for the host component.
       
   253 	@param			aPort		The output descriptor for the port component.
       
   254 	@param			aUseNetworkDelimiter Whether the scheme uses the network delimeter '//'
       
   255 	@return			The number of characters consumed in parsing the authority.
       
   256 	@pre 			The output descriptors have been initialized so that the pointer
       
   257 					to the their associated descriptor buffers is NULL. The input descriptor 
       
   258 					is set to the start of the start of the authority component.
       
   259 	
       
   260 	@post			If an authority component exists then the output descriptors refer
       
   261 					to the userinfo part (if exists), the host part and the port part (if exists), 
       
   262 					otherwise the output descriptors are left unchanged.
       
   263 */
       
   264 
       
   265 template<class TPtrCType> 
       
   266 TInt ParseAuthority(const TPtrCType& aUri, TPtrCType& aUserinfo, TPtrCType& aHost, TPtrCType& aPort, TBool aUseNetworkDelimiter)
       
   267 	{
       
   268 	// Get uri descriptor and see if authority exists - if aUseNetworkDelimiter is true it has to start with '//' 
       
   269 	TInt consumed =0;
       
   270 	const TInt prefixLength = aUseNetworkDelimiter ? KUriNetworkAuthorityDelimiterLength : 0;
       
   271   	if( !aUseNetworkDelimiter || 
       
   272   		(aUri.Length() >= prefixLength && aUri[0] == KSlashDelimiter && aUri[1] == KSlashDelimiter ))
       
   273 		{
       
   274 		// There is an authority
       
   275 		TPtrCType authority = aUri.Mid(prefixLength);
       
   276 
       
   277 		// Authority delimited by '/', '?', '#' or the end of the string
       
   278 		TInt authorityEndPos = FindFirstUriDelimiter(authority, EAuthDelimiterSearch);
       
   279 
       
   280 		// Got authority - parse it for its components
       
   281 		authority.Set(authority.Left(authorityEndPos));
       
   282 
       
   283 		// Get the userinfo...
       
   284 		TInt userinfoEndPos = authority.Locate(KUserinfoDelimiter);
       
   285 		if( userinfoEndPos != KErrNotFound )
       
   286 			{
       
   287 			// Store the information 
       
   288 			aUserinfo.Set(authority.Left(userinfoEndPos));
       
   289 			  
       
   290 			// Move past the userinfo and the delimiter '@'
       
   291 			authority.Set(authority.Mid(userinfoEndPos + 1));
       
   292 			}
       
   293 
       
   294 		// Authority is also delimited by ';' but this is valid in the userinfo so can only be checked now
       
   295 		TInt semicolonPos = FindFirstUriDelimiter(authority, ESemiColonDelimiterFlag);
       
   296 		if ( semicolonPos != KErrNotFound )
       
   297 			{
       
   298 			authority.Set(authority.Left(semicolonPos));
       
   299 			authorityEndPos = semicolonPos + userinfoEndPos + 1;
       
   300 			}
       
   301 		
       
   302 		// Set consumed amount to move past authority
       
   303 		consumed += prefixLength + authorityEndPos;
       
   304 		
       
   305 		// Check if this is an IPv6 address	by looking for the opening '['
       
   306 		TInt startHostIPv6 = authority.Locate(KIPv6UriOpenBrace);
       
   307 
       
   308 		if (startHostIPv6==KErrNotFound)
       
   309 			{
       
   310 			// This isn't an IPv6 address.....
       
   311 
       
   312 			// Get host...
       
   313 			TInt hostEndPos = authority.Locate(KPortDelimiter);
       
   314 
       
   315 			// Host also delimited by the end of the authority
       
   316 			if( hostEndPos == KErrNotFound )
       
   317 				hostEndPos = authority.Length();
       
   318 
       
   319 			// There's always a host, but can be empty - store information
       
   320 			aHost.Set(authority.Left(hostEndPos));
       
   321 
       
   322 			// Move past the host
       
   323 			authority.Set(authority.Mid(hostEndPos));
       
   324 			}
       
   325 		else
       
   326 			{
       
   327 			// This is an IPv6 address, so it MUST have the closing brace too....
       
   328 			TInt endIPv6Host = authority.Locate(KIPv6UriCloseBrace);
       
   329 
       
   330 			// Return an error if the closing IPv6 delimiter isn't there.
       
   331 			if (endIPv6Host==KErrNotFound)
       
   332 				return KUriUtilsErrInvalidUri;
       
   333 
       
   334 			// It's an ipv6  address, with an opening and closing brace. So now just extract it
       
   335 			// auth = [X:X:X]?????
       
   336 
       
   337 			// First, move past the opening brace
       
   338 			authority.Set(authority.Mid(startHostIPv6 + 1));
       
   339 			// auth now = X:X:X]?????
       
   340 
       
   341 			// Set the host, and need to remove the closing brace
       
   342 			aHost.Set(authority.Left(endIPv6Host -1));
       
   343 			// host = X:X:X
       
   344 
       
   345 			// Move past the host
       
   346 			authority.Set(authority.Mid(endIPv6Host));
       
   347 			}
       
   348 		
       
   349 		// Get the port...
       
   350 		TInt portEndPos = authority.Length();
       
   351 		if( portEndPos )
       
   352 			{
       
   353 			// Store the port - remove leading ':'
       
   354 			aPort.Set(authority.Mid(1, portEndPos - 1));
       
   355 			}
       
   356 		}
       
   357 	return consumed;
       
   358 	}
       
   359 
       
   360 /**
       
   361 	Templated function to parse a descriptor for a path component.There is always a path component.
       
   362 	The ouput argument aPath is set to the path component found.
       
   363 						
       
   364 	@since			6.0
       
   365 	@param			aUri	The descriptor containing the uri to be parsed for 
       
   366 	a path.
       
   367 	@param			aComponent	The output descriptor to refer to the path.
       
   368 	@return			The number of characters consumed in parsing the path.
       
   369 	@pre 			The output descriptor has been initialized so that the pointer
       
   370 					to the associated descriptor buffer is NULL. The input descriptor 
       
   371 					is set to the start of the path.
       
   372 					
       
   373 	@post			The output descriptor refers to the path component.
       
   374 */
       
   375 template<class TPtrCType>
       
   376 TInt ParsePath(const TPtrCType& aUri, TPtrCType& aComponent)
       
   377 	{
       
   378 	// Get descriptor with the path
       
   379 	TInt consumed =0;
       
   380 
       
   381 	// Path is delimited by '?'. '#' or the end of the string
       
   382 	TInt pathEndPos = FindFirstUriDelimiter(aUri, EPathDelimiterSearch);
       
   383 
       
   384 	// Check for presence of path
       
   385 	if( pathEndPos != KErrNotFound )
       
   386 		{
       
   387 		// Got path - store information
       
   388 		aComponent.Set(aUri.Left(pathEndPos));
       
   389 	
       
   390 		// Set consumed amount to move past path
       
   391 		consumed = pathEndPos;
       
   392 		}
       
   393 	return consumed;
       
   394 	}
       
   395 
       
   396 /**
       
   397 	Templated function to parse a descriptor for a query component.If a query is found then 
       
   398 	the output argument aQuery is set to refer to it.
       
   399 						
       
   400 	@since			6.0
       
   401 	@param			aUri	The descriptor containing the uri to be parsed for 
       
   402 	a query.
       
   403 	@param			aComponent	The output descriptor to refer to the query
       
   404 	@return			The number of characters consumed in parsing the query.
       
   405 	@pre 			The output descriptor has been initialized so that the pointer
       
   406 					to the associated descriptor buffer is NULL. The input descriptor is set to
       
   407 					the start of the query.
       
   408 	@post			If a query component exists then the output descriptor refers
       
   409 					to it, otherwise the output descriptor is left unchanged.
       
   410 */
       
   411 template<class TPtrCType>
       
   412 TInt ParseQuery(const TPtrCType& aUri, TPtrCType& aComponent)
       
   413 	{
       
   414 	// Get descriptor with the query
       
   415 	TInt consumed =0;
       
   416 
       
   417 	// Query is delimited by '#' or end of the string 
       
   418 	TInt queryEndPos = FindFirstUriDelimiter(aUri, EQueryDelimiterSearch);
       
   419 
       
   420 	// Check for presence of query
       
   421 	if( queryEndPos )
       
   422 		{
       
   423 		// Got query - store information; need to excluded leading '?'
       
   424 		aComponent.Set(aUri.Mid(1, queryEndPos - 1));
       
   425 	
       
   426 		// Set consumed amount to move past query
       
   427 		consumed = queryEndPos;
       
   428 		}
       
   429 	return consumed;
       
   430 	}
       
   431 
       
   432 /**
       
   433 	Templated function to parse a descriptor for a fragment component. If a fragment is found then 
       
   434 	the output argument aFragment is set to refer to it.
       
   435 						
       
   436 	@since			6.0
       
   437 	@param			aUri		The descriptor containing the uri to be parsed for 
       
   438 					a fragment.
       
   439 	@param			aComponent	The output descriptor to refer to the fragment.
       
   440 	@return			The number of characters consumed in parsing the fragment.
       
   441 	@pre 			The output descriptor has been initialized so that the pointer
       
   442 					to the associated descriptor buffer is NULL. The input descriptor is set to
       
   443 					the start of the fragment.
       
   444 	@post			If a fragment component exists then the output descriptor refers
       
   445 					to it, otherwise the output descriptor is left unchanged.
       
   446 */
       
   447 template<class TPtrCType>
       
   448 TInt ParseFragment(const TPtrCType& aUri, TPtrCType& aComponent)
       
   449 	{
       
   450 	// Get descriptor with the fragment
       
   451 	TInt consumed =0;
       
   452 
       
   453 	// Fragment is delimited by end of the string
       
   454 	TInt fragmentEndPos = aUri.Length();
       
   455 
       
   456 	// Check for presence of fragment
       
   457 	if( fragmentEndPos )
       
   458 		{
       
   459 		// Got fragment - store information; need to excluded leading '#'
       
   460 		aComponent.Set(aUri.Mid(1, fragmentEndPos - 1));
       
   461 	
       
   462 		// Set consumed amount to move past fragment
       
   463 		consumed = fragmentEndPos;
       
   464 		}
       
   465 	return consumed;
       
   466 	}
       
   467 	
       
   468 /**
       
   469 	Templated function to find the position of the first delimiter in the descriptor specified 
       
   470 	by the delimiter flags. Note that the end of the descriptor is also a delimiter if there are 
       
   471 	no others. In the case of the scheme delimiter search, the position returned depends on the 
       
   472 	position of the colon delimiter with respect to the other delimiters for a scheme.
       
   473 						
       
   474 	@since			6.0
       
   475 	@param			aUri		The descriptor containing the section of a uri to be searched.
       
   476 	@param			aSearchFlag	The enum specifying the delimiters to search for.
       
   477 	@return			The position of nearest delimiter to start of the descriptor, where
       
   478 					zero is the start (left-most) position.
       
   479 */
       
   480 template<class TPtrCType> 
       
   481 TInt FindFirstUriDelimiter(const TPtrCType& aUri, TDelimiterSearchFlag aSearchFlag)
       
   482 	{
       
   483 	// Set ultimate delimiter - string length
       
   484 	TInt endPos = aUri.Length();
       
   485 	if( aSearchFlag & EHashDelimiterFlag )
       
   486 		{
       
   487 		TInt fragmentPos = aUri.Locate(KFragmentDelimiter);
       
   488 		if( fragmentPos != KErrNotFound && fragmentPos < endPos )
       
   489 			endPos = fragmentPos;
       
   490 		}
       
   491 	if( aSearchFlag & EQueryDelimiterFlag )
       
   492 		{
       
   493 		TInt queryPos = aUri.Locate(KQueryDelimiter);
       
   494 		if( queryPos != KErrNotFound && queryPos < endPos )
       
   495 			endPos = queryPos;
       
   496 		}
       
   497 	if( aSearchFlag & ESlashDelimiterFlag )
       
   498 		{
       
   499 		TInt slashPos = aUri.Locate(KSlashDelimiter);
       
   500 		if( slashPos != KErrNotFound && slashPos < endPos )
       
   501 			endPos = slashPos;
       
   502 		}
       
   503 	if( aSearchFlag & ESemiColonDelimiterFlag )
       
   504 		{
       
   505 		TInt semiColonPos = aUri.Locate(KParamDelimiter);
       
   506 		if( semiColonPos != KErrNotFound && semiColonPos < endPos )
       
   507 			endPos = semiColonPos;
       
   508 		}
       
   509 	if( aSearchFlag & EColonDelimiterFlag )
       
   510 		{
       
   511 		TInt schemePos = aUri.Locate(KSchemeDelimiter);
       
   512 		if( schemePos != KErrNotFound && schemePos < endPos )
       
   513 			{
       
   514 			// There is a scheme
       
   515 			endPos = schemePos;
       
   516 			}
       
   517 		else if( aSearchFlag == ESchemeDelimiterSearch )
       
   518 			{
       
   519 			// Ok different if looking for scheme delimiter - no scheme, return KErrNotFound
       
   520 			endPos = KErrNotFound;
       
   521 			}
       
   522 		}
       
   523 	return endPos;
       
   524 	}