genericservices/httputils/UriParser/GenericUriParser.cpp
changeset 31 ce057bb09d0b
parent 0 e4d67989cc36
child 27 3a7375419266
equal deleted inserted replaced
30:e20de85af2ee 31:ce057bb09d0b
       
     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 			// This is an IPv6 address, so it MUST have the closing brace too....
       
   173 			TInt endIPv6Host = authority.Locate(KIPv6UriCloseBrace);
       
   174 
       
   175 			// Return an error if the closing IPv6 delimiter isn't there.
       
   176 			// or Host is empty
       
   177 			if (endIPv6Host == KErrNotFound || endIPv6Host == startHostIPv6 + 1)
       
   178 				{
       
   179 				return KUriUtilsErrInvalidUri;	
       
   180 				}
       
   181 
       
   182 			// It's an ipv6  address, with an opening and closing brace. So now just extract it
       
   183 			// auth = [X:X:X]?????
       
   184 
       
   185 			// First, move past the opening brace
       
   186 			authority.Set(authority.Mid(startHostIPv6 + 1));
       
   187 			// auth now = X:X:X]?????
       
   188 
       
   189 			// Set the host, and need to remove the closing brace
       
   190 			aHost.Set(authority.Left(endIPv6Host - 1));
       
   191 			// host = X:X:X
       
   192 
       
   193 			// Move past the host
       
   194 			authority.Set(authority.Mid(endIPv6Host));
       
   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.
       
   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 CGenericUriParser::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, EPathDelimiterSearch);
       
   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 
       
   246 					a query.
       
   247 	@param			aComponent	The output descriptor to refer to the query
       
   248 	@return			The number of characters consumed in parsing the query.
       
   249 	@pre 			The output descriptor has been initialized so that the pointer
       
   250 					to the associated descriptor buffer is NULL. The input descriptor is set to
       
   251 					the start of the query.
       
   252 	@post			If a query component exists then the output descriptor refers
       
   253 					to it, otherwise the output descriptor is left unchanged.
       
   254 */
       
   255 TInt CGenericUriParser::ParseQuery(const TPtrC8& aUri, TPtrC8& aComponent)
       
   256 	{
       
   257 	// Get descriptor with the query
       
   258 	TInt consumed =0;
       
   259 
       
   260 	// Query is delimited by '#' or end of the string 
       
   261 	TInt queryEndPos = FindFirstUriDelimiter(aUri, EQueryDelimiterSearch);
       
   262 
       
   263 	// Check for presence of query
       
   264 	if( queryEndPos )
       
   265 		{
       
   266 		// Got query - store information; need to excluded leading '?'
       
   267 		aComponent.Set(aUri.Mid(1, queryEndPos - 1));
       
   268 	
       
   269 		// Set consumed amount to move past query
       
   270 		consumed = queryEndPos;
       
   271 		}
       
   272 	return consumed;
       
   273 	}
       
   274 	
       
   275 /**
       
   276 	Function to parse a descriptor for a fragment component. If a fragment is found then 
       
   277 	the output argument aFragment is set to refer to it.
       
   278 						
       
   279 	@param			aUri	The descriptor containing the uri to be parsed for a fragment.
       
   280 	@param			aComponent	The output descriptor to refer to the fragment.
       
   281 	@return			The number of characters consumed in parsing the fragment.
       
   282 	@pre 			The output descriptor has been initialized so that the pointer
       
   283 					to the associated descriptor buffer is NULL. The input descriptor is set to
       
   284 					the start of the fragment.
       
   285 	@post			If a fragment component exists then the output descriptor refers
       
   286 					to it, otherwise the output descriptor is left unchanged.
       
   287 */
       
   288 TInt CGenericUriParser::ParseFragment(const TPtrC8& aUri, TPtrC8& aComponent)
       
   289 	{
       
   290 	// Get descriptor with the fragment
       
   291 	TInt consumed =0;
       
   292 
       
   293 	// Fragment is delimited by end of the string
       
   294 	TInt fragmentEndPos = aUri.Length();
       
   295 
       
   296 	// Check for presence of fragment
       
   297 	if( fragmentEndPos )
       
   298 		{
       
   299 		// Got fragment - store information; need to excluded leading '#'
       
   300 		aComponent.Set(aUri.Mid(1, fragmentEndPos - 1));
       
   301 	
       
   302 		// Set consumed amount to move past fragment
       
   303 		consumed = fragmentEndPos;
       
   304 		}
       
   305 	return consumed;
       
   306 	}
       
   307 	
       
   308 /**
       
   309 	Function to find the position of the first delimiter in the descriptor specified 
       
   310 	by the delimiter flags. Note that the end of the descriptor is also a delimiter if there are 
       
   311 	no others. In the case of the scheme delimiter search, the position returned depends on the 
       
   312 	position of the colon delimiter with respect to the other delimiters for a scheme.
       
   313 						
       
   314 	@param			aUri The descriptor containing the section of a uri to be searched.
       
   315 	@param			aSearchFlag	The enum specifying the delimiters to search for.
       
   316 	@return			The position of nearest delimiter to start of the descriptor, where
       
   317 					zero is the start (left-most) position.
       
   318 */
       
   319 TInt CGenericUriParser::FindFirstUriDelimiter(const TPtrC8& aUri, TDelimiterSearchFlag aSearchFlag)
       
   320 	{
       
   321 	// Set ultimate delimiter - string length
       
   322 	TInt endPos = aUri.Length();
       
   323 	if( aSearchFlag & EHashDelimiterFlag )
       
   324 		{
       
   325 		TInt fragmentPos = aUri.Locate(KFragmentDelimiter);
       
   326 		if( fragmentPos != KErrNotFound && fragmentPos < endPos )
       
   327 			{
       
   328 			endPos = fragmentPos;	
       
   329 			}
       
   330 		}
       
   331 	if( aSearchFlag & EQueryDelimiterFlag )
       
   332 		{
       
   333 		TInt queryPos = aUri.Locate(KQueryDelimiter);
       
   334 		if( queryPos != KErrNotFound && queryPos < endPos )
       
   335 			{
       
   336 			endPos = queryPos;				
       
   337 			}
       
   338 		}
       
   339 	if( aSearchFlag & ESlashDelimiterFlag )
       
   340 		{
       
   341 		TInt slashPos = aUri.Locate(KSlashDelimiter);
       
   342 		if( slashPos != KErrNotFound && slashPos < endPos )
       
   343 			{
       
   344 			endPos = slashPos;	
       
   345 			}
       
   346 		}
       
   347 	if( aSearchFlag & ESemiColonDelimiterFlag )
       
   348 		{
       
   349 		TInt semiColonPos = aUri.Locate(KParamDelimiter);
       
   350 		if( semiColonPos != KErrNotFound && semiColonPos < endPos )
       
   351 			{
       
   352 			endPos = semiColonPos;	
       
   353 			}
       
   354 		}
       
   355 	if( aSearchFlag & EColonDelimiterFlag )
       
   356 		{
       
   357 		TInt schemePos = aUri.Locate(KSchemeDelimiter);
       
   358 		if( schemePos != KErrNotFound && schemePos < endPos )
       
   359 			{
       
   360 			// There is a scheme
       
   361 			endPos = schemePos;
       
   362 			}
       
   363 		else if( aSearchFlag == ESchemeDelimiterSearch )
       
   364 			{
       
   365 			// Ok different if looking for scheme delimiter - no scheme, return KErrNotFound
       
   366 			endPos = KErrNotFound;
       
   367 			}
       
   368 		}
       
   369 	return endPos;
       
   370 	}
       
   371 
       
   372 
       
   373 
       
   374 
       
   375