os/ossrv/genericservices/httputils/UriParser/SipUriParser.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     1 // Copyright (c) 2007-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 #include "SipUriParser.h"
    17 
    18 /** 
    19  * CSIPUriParser Constructor.
    20  */ 
    21 CSIPUriParser::CSIPUriParser()
    22 : CGenericUriParser()
    23 	{
    24 	}
    25 
    26 /** 
    27  * CSIPUriParser Static Factory Construction.
    28  */
    29 CSIPUriParser* CSIPUriParser::NewL()
    30 	{
    31 	CSIPUriParser* self = new (ELeave) CSIPUriParser;
    32 	CleanupStack::PushL(self);
    33 	self->ConstructL();
    34 	CleanupStack::Pop(self);
    35 	return self;
    36 	}
    37 
    38 /**	
    39 	Second phase of two-phase construction method. 
    40 	
    41 	@pre 			First phase of construction is complete.
    42 	@post			The object is fully constructed and initialized.
    43  */
    44 void CSIPUriParser::ConstructL()
    45 	{
    46 	// Does nothing.
    47 	}
    48 
    49 /**
    50  * Default Destructor.
    51  */
    52 CSIPUriParser::~CSIPUriParser()
    53 	{
    54 	}
    55 
    56 /**
    57 	Function to parse a descriptor for a scheme component. If a scheme is found 
    58 	then the output argument aScheme is set to refer to it.
    59 						
    60 	@param			aUri	The descriptor containing the uri to be parsed for a scheme.
    61 	@param			aScheme	The output descriptor to refer to the scheme
    62 	@return			The number of characters consumed in parsing the scheme.
    63 	@pre 			The output descriptor has been initialized so that the pointer
    64 					to the associated descriptor buffer is NULL. The input descriptor 
    65 					is set to the start of the uri.
    66 	@post			If a scheme component exists then the output descriptor refers
    67 					to it, otherwise the output descriptor is left unchanged.
    68 */
    69 TInt CSIPUriParser::ParseScheme(const TPtrC8& aUri, TPtrC8& aScheme)
    70 	{
    71 	// Get the descriptor and look for scheme delimiter
    72 	TInt consumed =0;
    73 	TInt endSchemePos = FindFirstUriDelimiter(aUri, ESipSchemeDelimiterSearch);
    74 
    75 	if( endSchemePos != KErrNotFound )
    76 		{
    77 		// Got a scheme - store information
    78 		aScheme.Set(aUri.Left(endSchemePos));
    79 
    80 		// Set consumed amount move past scheme delimiter
    81 		consumed = endSchemePos + 1;
    82 		}
    83 	return consumed;
    84 	}
    85 	
    86 /**
    87 	Function to parse a descriptor for an authority component. If an authority is 
    88 	found then the output arguments aUserinfo, aHost and aPort are set to refer to those parts 
    89 	of the authority component. If an authority component exists then the host part exists. The 
    90 	userinfo and port parts are optional.
    91 						
    92 	@param			aUri		The descriptor containing the uri to be parsed 
    93 					for an authority.
    94 	@param			aUserinfo	The output descriptor for the userinfo component.
    95 	@param			aHost		The output descriptor for the host component.
    96 	@param			aPort		The output descriptor for the port component.
    97 	@param			aUseNetworkDelimiter is not used as we know the Sip scheme 
    98 					not uses the network delimeter '//'
    99 	@return			The number of characters consumed in parsing the authority.
   100 	@pre 			The output descriptors have been initialized so that the pointer
   101 					to the their associated descriptor buffers is NULL. The input descriptor 
   102 					is set to the start of the start of the authority component.
   103 	
   104 	@post			If an authority component exists then the output descriptors refer
   105 					to the userinfo part (if exists), the host part and the port part (if exists), 
   106 					otherwise the output descriptors are left unchanged.
   107 */
   108 TInt CSIPUriParser::ParseAuthority(const TPtrC8& aUri, TPtrC8& aUserinfo, TPtrC8& aHost, TPtrC8& aPort, TBool aUseNetworkDelimiter)
   109 	{
   110 	// Get uri descriptor and see if authority exists - if aUseNetworkDelimiter is true it has to start with '//' 
   111 	TInt consumed =0;
   112 	const TInt prefixLength = aUseNetworkDelimiter ? KUriNetworkAuthorityDelimiterLength : 0;
   113   	if( !aUseNetworkDelimiter || 
   114   		(aUri.Length() >= prefixLength && aUri[0] == KSlashDelimiter && aUri[1] == KSlashDelimiter ))
   115 		{
   116 		// There is an authority
   117 		TPtrC8 authority( aUri.Mid(prefixLength) );
   118 
   119 		// Authority delimited by ';', '?' or the end of the string
   120 		TInt authorityEndPos = FindFirstUriDelimiter(authority, ESipAuthDelimiterSearch);
   121 
   122 		// Got authority - parse it for its components
   123 		authority.Set(authority.Left(authorityEndPos));
   124 
   125 		// Get the userinfo...
   126 		TInt userinfoEndPos = authority.Locate(KUserinfoDelimiter);
   127 		if( userinfoEndPos != KErrNotFound )
   128 			{
   129 			// Store the information 
   130 			aUserinfo.Set(authority.Left(userinfoEndPos));
   131 			  
   132 			// Move past the userinfo and the delimiter '@'
   133 			authority.Set(authority.Mid(userinfoEndPos + 1));
   134 			}
   135 
   136 		// Authority is also delimited by ';' but this is valid in the userinfo so can only be checked now
   137 		TInt semicolonPos = FindFirstUriDelimiter(authority, ESipSemiColonDelimiterFlag);
   138 		if ( semicolonPos != KErrNotFound )
   139 			{
   140 			authority.Set(authority.Left(semicolonPos));
   141 			authorityEndPos = semicolonPos + userinfoEndPos + 1;
   142 			}
   143 		
   144 		// Set consumed amount to move past authority
   145 		consumed += prefixLength + authorityEndPos;
   146 		
   147 		// Check if this is an IPv6 address	by looking for the opening '['
   148 		TInt startHostIPv6 = authority.Locate(KIPv6UriOpenBrace);
   149 
   150 		if (startHostIPv6 == KErrNotFound)
   151 			{
   152 			// This isn't an IPv6 address.....
   153 
   154 			// Get host...
   155 			TInt hostEndPos = authority.Locate(KPortDelimiter);
   156 
   157 			// Host also delimited by the end of the authority
   158 			if( hostEndPos == KErrNotFound )
   159 				{
   160 				hostEndPos = authority.Length();	
   161 				}
   162 
   163 			// There's always a host, but can be empty - store information
   164 			aHost.Set(authority.Left(hostEndPos));
   165 
   166 			// Move past the host
   167 			authority.Set(authority.Mid(hostEndPos));
   168 			}
   169 		else
   170 			{
   171 		// First, move past the opening brace
   172 		    authority.Set(authority.Mid(startHostIPv6 + 1));
   173 		    // auth now = X:X:X]?????
   174 
   175 			// This is an IPv6 address, so it MUST have the closing brace too....
   176 			TInt endIPv6Host = authority.Locate(KIPv6UriCloseBrace);
   177 
   178 			// Return an error if the closing IPv6 delimiter isn't there.
   179 			// or Host is empty
   180 			if (endIPv6Host == KErrNotFound || endIPv6Host == startHostIPv6 + 1)
   181 				{
   182 				return KUriUtilsErrInvalidUri;	
   183 				}
   184 
   185 			// It's an ipv6  address, with an opening and closing brace. So now just extract it
   186 			// auth = [X:X:X]?????
   187 
   188 
   189 			// Set the host, and need to remove the closing brace
   190 			aHost.Set(authority.Left(endIPv6Host));
   191 			// host = X:X:X
   192 
   193 			// Move past the host
   194 			authority.Set(authority.Mid(endIPv6Host + 1 ));
   195 			}
   196 		
   197 		// Get the port...
   198 		TInt portEndPos = authority.Length();
   199 		if( portEndPos )
   200 			{
   201 			// Store the port - remove leading ':'
   202 			aPort.Set(authority.Mid(1, portEndPos - 1));
   203 			}
   204 		}
   205 	return consumed;
   206 	}
   207 
   208 /**
   209 	Function to parse a descriptor for a path/parameter component.There is always a path component.
   210 	The ouput argument aPath is set to the path/parameter component found.
   211 						
   212 	@param			aUri	The descriptor containing the uri to be parsed for a path/parameter.
   213 	@param			aComponent	The output descriptor to refer to the path.
   214 	@return			The number of characters consumed in parsing the path.
   215 	@pre 			The output descriptor has been initialized so that the pointer
   216 					to the associated descriptor buffer is NULL. The input descriptor 
   217 					is set to the start of the path.
   218 					
   219 	@post			The output descriptor refers to the path component.
   220 */	
   221 TInt CSIPUriParser::ParsePath(const TPtrC8& aUri, TPtrC8& aComponent)
   222 	{
   223 	// Get descriptor with the path
   224 	TInt consumed =0;
   225 
   226 	// Path is delimited by '?' or the end of the string
   227 	TInt pathEndPos = FindFirstUriDelimiter(aUri, ESipPathDelimiterSearch);
   228 
   229 	// Check for presence of path
   230 	if( pathEndPos != KErrNotFound )
   231 		{
   232 		// Got path - store information
   233 		aComponent.Set(aUri.Left(pathEndPos));
   234 	
   235 		// Set consumed amount to move past path
   236 		consumed = pathEndPos;
   237 		}
   238 	return consumed;
   239 	}
   240 
   241 /**
   242 	Function to parse a descriptor for a query/header component.If a query is found then 
   243 	the output argument aQuery is set to refer to it.
   244 						
   245 	@param			aUri	The descriptor containing the uri to be parsed for a query/Header.
   246 	@param			aComponent	The output descriptor to refer to the query
   247 	@return			The number of characters consumed in parsing the query.
   248 	@pre 			The output descriptor has been initialized so that the pointer
   249 					to the associated descriptor buffer is NULL. The input descriptor is set to
   250 					the start of the query.
   251 	@post			If a query component exists then the output descriptor refers
   252 					to it, otherwise the output descriptor is left unchanged.
   253 */
   254 TInt CSIPUriParser::ParseQuery(const TPtrC8& aUri, TPtrC8& aComponent)
   255 	{
   256 	// Get descriptor with the query
   257 	TInt consumed =0;
   258 
   259 	// Query/Header is delimited by end of the string 
   260 	TInt queryEndPos = aUri.Length();
   261 
   262 	// Check for presence of query
   263 	if( queryEndPos )
   264 		{
   265 		// Got query - store information; need to excluded leading '?'
   266 		aComponent.Set(aUri.Mid(1, queryEndPos - 1));
   267 	
   268 		// Set consumed amount to move past query
   269 		consumed = queryEndPos;
   270 		}
   271 	return consumed;
   272 	}
   273 	
   274 /**
   275 	Function to parse a descriptor for a fragment component. 
   276 	In Sip Uris no Fragment Component it contains. This is an dummy implementation.
   277 						
   278 	@param			aUri not used.
   279 	@param			aComponent	not used.
   280 	@return			returns zero.
   281 */
   282 TInt CSIPUriParser::ParseFragment(const TPtrC8& /*aUri*/, TPtrC8& /* aComponent*/)
   283 	{
   284 	// Sip Uri Does not conatin Fragment
   285 	return 0;
   286 	}
   287 	
   288 /**
   289 	Function to find the position of the first delimiter in the descriptor specified 
   290 	by the delimiter flags. Note that the end of the descriptor is also a delimiter if there are 
   291 	no others. In the case of the scheme delimiter search, the position returned depends on the 
   292 	position of the colon delimiter with respect to the other delimiters for a scheme.
   293 						
   294 	@param			aUri The descriptor containing the section of a uri to be searched.
   295 	@param			aSearchFlag	The enum specifying the delimiters to search for.
   296 	@return			The position of nearest delimiter to start of the descriptor, where
   297 					zero is the start (left-most) position.
   298 */
   299 TInt CSIPUriParser::FindFirstUriDelimiter(const TPtrC8& aUri, TSipDelimiterSearchFlag aSearchFlag)
   300 	{
   301 	// Set ultimate delimiter - string length
   302 	TInt endPos = aUri.Length();
   303 
   304 	if( aSearchFlag & ESipQueryDelimiterFlag )
   305 		{
   306 		TInt queryPos = aUri.Locate(KQueryDelimiter);
   307 		if( queryPos != KErrNotFound && queryPos < endPos )
   308 			{
   309 			TInt userinfoPos = aUri.Locate(KUserinfoDelimiter);
   310 			//QueryDelimiter may be in Userinfo
   311 			if(userinfoPos != KErrNotFound && userinfoPos < endPos && userinfoPos > queryPos ) 
   312 				{
   313 				//Find QueryDelimiter after Userinfo
   314 				queryPos = aUri.Mid(userinfoPos).Locate(KQueryDelimiter);
   315 				if (queryPos != KErrNotFound  && queryPos < endPos )
   316 					{
   317 					queryPos += userinfoPos;	
   318 					}
   319 				}
   320 			if(queryPos != KErrNotFound)
   321 				{
   322 				endPos = queryPos;		
   323 				}
   324 			}
   325 		}
   326 
   327 	if( aSearchFlag & ESipSemiColonDelimiterFlag )
   328 		{
   329 		TInt semiColonPos = aUri.Locate(KParamDelimiter);
   330 		if( semiColonPos != KErrNotFound && semiColonPos < endPos )
   331 			{
   332 			TInt userinfoPos = aUri.Locate(KUserinfoDelimiter);
   333 			//ParamDelimiter may be in Userinfo
   334 			if(userinfoPos != KErrNotFound && userinfoPos < endPos && userinfoPos > semiColonPos ) 
   335 				{
   336 				//Find ParamDelimiter after Userinfo
   337 				semiColonPos = aUri.Mid(userinfoPos).Locate(KParamDelimiter);
   338 				if (semiColonPos != KErrNotFound  && semiColonPos < endPos )
   339 					{
   340 					semiColonPos += userinfoPos;	
   341 					}
   342 				}
   343 			if(semiColonPos != KErrNotFound)
   344 				{
   345 				endPos = semiColonPos;		
   346 				}
   347 			}
   348 		}
   349 	if( aSearchFlag & ESipColonDelimiterFlag )
   350 		{
   351 		TInt schemePos = aUri.Locate(KSchemeDelimiter);
   352 		if( schemePos != KErrNotFound && schemePos < endPos )
   353 			{
   354 			// There is a scheme
   355 			endPos = schemePos;
   356 			}
   357 		else if( aSearchFlag == ESipSchemeDelimiterSearch )
   358 			{
   359 			// Ok different if looking for scheme delimiter - no scheme, return KErrNotFound
   360 			endPos = KErrNotFound;
   361 			}
   362 		}
   363 	return endPos;
   364 	}
   365