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