genericservices/httputils/UriUtils/UriUtils.cpp
changeset 0 e4d67989cc36
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 #include <uriutils.h>
       
    17 #include <uriutilscommon.h>
       
    18 #include "UriUtilsInternal.h"
       
    19 #include <escapeutils.h>
       
    20 
       
    21 _LIT8(KDot, ".");
       
    22 _LIT8(KDotDot, "..");
       
    23 _LIT8(KDotSlash, "./");
       
    24 _LIT8(KDotDotSlash, "../");
       
    25 _LIT8(KSlash, "/");	
       
    26 _LIT8(KSlashDot, "/.");
       
    27 _LIT8(KSlashDotDot, "/..");
       
    28 _LIT8(KSlashDotSlash, "/./");
       
    29 _LIT8(KSlashDotDotSlash, "/../");
       
    30 
       
    31 _LIT(KHexDigit, "0123456789ABCDEF");
       
    32 _LIT(KUnreserved, "-.~_");
       
    33 #ifdef _DEBUG
       
    34 _LIT(KNormalisationUriPanicCategory, "URI-NORMALIZATION");
       
    35 #endif
       
    36 const TInt KEscapeIndicator					= '%';
       
    37 const TInt KEscapeTripleLength				= 3;
       
    38 const TInt KEscDelimiterPos					= 0;
       
    39 const TInt KMostSignificantNibblePos		= 1;
       
    40 const TInt KLeastSignificantNibblePos		= 2;
       
    41 const TInt KSubstringLength					= 3;
       
    42 const TInt KUpdateLength					= 2;
       
    43 const TInt KAttachLength					= 1;
       
    44 
       
    45 const TInt KDotLength						= 1;
       
    46 const TInt KDotDotLength					= 2;
       
    47 const TInt KDotDotSlashLength				= 3;
       
    48 const TInt KSlashDotDotSlashLength			= 4;
       
    49 
       
    50 //
       
    51 //
       
    52 // Implementation of UriUtils
       
    53 //
       
    54 //
       
    55 
       
    56 /**
       
    57 	Converts a 16-bit format uri into its internet form. Any Unicode characters 
       
    58 	are converted into Utf8 representation and then any excluded characters are 
       
    59 	escape encoded.  Reserved characters specified in RFC2396 will not be escape 
       
    60 	encoded however, these include ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | ",". 
       
    61 	For example http://localhost will not be encoded to http%3A%2F%2Flocalhost.
       
    62 	
       
    63 	@since			6.0
       
    64 	@deprecated	 Deprecated in 9.1
       
    65 	@leave			KUriUtilsCannotConvert. When the input data cannot be converted.
       
    66 	@leave			KUriUtilsErr16BitChar. When the input data has a 16-Bit character to be escape encoded.
       
    67 	@param			aUri	The 16-bit format uri.
       
    68 	@return			A pointer to a newly created 8-bit uri.
       
    69  */
       
    70 EXPORT_C CUri8* UriUtils::ConvertToInternetFormL(const TUriC16& aUri)
       
    71 	{
       
    72 	// Need to convert to utf8
       
    73 	HBufC8* utf8Buf = EscapeUtils::ConvertFromUnicodeToUtf8L(aUri.UriDes());
       
    74 	CleanupStack::PushL(utf8Buf);
       
    75 
       
    76 	// Ok need to parse for the uri without the fragment
       
    77 	TUriParser8 parser;
       
    78 	parser.Parse(*utf8Buf);
       
    79 	TPtrC8 uriNoFragment;
       
    80 	parser.UriWithoutFragment(uriNoFragment);
       
    81 
       
    82 	// Now escape encode the uri without the fragment
       
    83 	HBufC8* escapedBuf = EscapeUtils::EscapeEncodeL(uriNoFragment, EscapeUtils::EEscapeNormal);
       
    84 	CleanupStack::PushL(escapedBuf);
       
    85 
       
    86 	// Now escape encode the fragment if there is one...
       
    87 	HBufC8* escapedFragmentBuf = NULL;
       
    88 	if( parser.IsPresent(EUriFragment) )
       
    89 		{
       
    90 		escapedFragmentBuf = EscapeUtils::EscapeEncodeL(parser.Extract(EUriFragment), EscapeUtils::EEscapeNormal);
       
    91 		CleanupStack::PushL(escapedFragmentBuf);
       
    92 		}
       
    93 
       
    94 	// Parse and then create the CUri8 object
       
    95 	parser.Parse(*escapedBuf);
       
    96 	CUri8* netForm = CUri8::NewL(parser);
       
    97 
       
    98 	// Set the fragment if there was one...
       
    99 	if( escapedFragmentBuf != NULL )
       
   100 		{
       
   101 		CleanupStack::PushL(netForm);
       
   102 		netForm->SetComponentL(*escapedFragmentBuf, EUriFragment);
       
   103 		CleanupStack::Pop(netForm);
       
   104 		CleanupStack::PopAndDestroy(escapedFragmentBuf);
       
   105 		}
       
   106 
       
   107 	// Cleanup and return
       
   108 	CleanupStack::PopAndDestroy(2, utf8Buf);	// utf8Buf, escapedBuf
       
   109 	return netForm;
       
   110 	}
       
   111 
       
   112 /**
       
   113 	Converts an 8-bit format uri its into display form. Any escape tripes are decoded and 
       
   114 	sets of Utf8 format characters are converted into Unicode.
       
   115 	
       
   116 	@since			6.0
       
   117 	@deprecated	 Deprecated in 9.1	
       
   118 	@leave			KUriUtilsCannotConvert. When the input data cannot be converted.
       
   119 	@param			aUri	The 8-bit format uri.
       
   120 	@return			A pointer to a newly created 16-bit uri.
       
   121  */
       
   122 EXPORT_C CUri16* UriUtils::ConvertToDisplayFormL(const TUriC8& aUri)
       
   123 	{
       
   124 	// Need decode escape triples
       
   125 	HBufC8* unescapedBuf = EscapeUtils::EscapeDecodeL(aUri.UriDes());
       
   126 	CleanupStack::PushL(unescapedBuf);
       
   127 
       
   128 	// Now need to convert utf8 to unicode
       
   129 	HBufC16* utf8Buf = EscapeUtils::ConvertToUnicodeFromUtf8L(*unescapedBuf);
       
   130 	CleanupStack::PushL(utf8Buf);
       
   131 
       
   132 	// Parse and then create the CUri16 object
       
   133 	TUriParser16 parser;
       
   134 	parser.Parse(*utf8Buf);
       
   135 	CUri16* displayForm = CUri16::NewL(parser);
       
   136 
       
   137 	// Cleanup and return
       
   138 	CleanupStack::PopAndDestroy(2, unescapedBuf);	// unescapedBuf, utf8Buf
       
   139 	return displayForm;
       
   140 	}
       
   141 	
       
   142 /** 
       
   143 	Create a new CUri8 object from a Unicode descriptor.
       
   144 	
       
   145 	@param aUri a Unicode string containing the URI to parse.
       
   146 	@return the new CUri8 object
       
   147 	@leave EUriUtilsParserErrInvalidUri  if the descriptor is an invalid URI.
       
   148  */
       
   149 EXPORT_C CUri8* UriUtils::CreateUriL(const TDesC& aUri) 
       
   150 	{
       
   151 	// convert to UTF8
       
   152 	HBufC8* unsafe8 = EscapeUtils::ConvertFromUnicodeToUtf8L(aUri);
       
   153      	CleanupStack::PushL(unsafe8);
       
   154 	// escape encode only those characters that cannot be in a URI. assume all %hh are %encoded already
       
   155 	HBufC8* uri8desc = EscapeUtils::ReEscapeEncodeL(*unsafe8);
       
   156 	CleanupStack::PopAndDestroy(unsafe8);
       
   157      	CleanupStack::PushL(uri8desc);
       
   158 	TUriParser8 parser;
       
   159 	// parse the descriptor into a URI, Leave if it cannot be parsed
       
   160 	User::LeaveIfError( parser.Parse(*uri8desc) );
       
   161 
       
   162 	CUri8* uri8 = CUri8::NewL(parser);
       
   163 	CleanupStack::PopAndDestroy(uri8desc);
       
   164 	return uri8;
       
   165 	}
       
   166 
       
   167 /** 
       
   168 	Create a new CAuthority8 object from a Unicode descriptor.
       
   169 	
       
   170 	@param aAuthority a Unicode string containing the Authority to parse.
       
   171 	@return the new CAuthority8 object
       
   172 	@leave EUriUtilsParserErrInvalidUri  if the descriptor is an invalid Authority.
       
   173  */
       
   174 EXPORT_C CAuthority8* UriUtils::CreateAuthorityL(const TDesC& aAuthority) 
       
   175 	{
       
   176 	// convert to UTF8
       
   177 	HBufC8* unsafe8 = EscapeUtils::ConvertFromUnicodeToUtf8L(aAuthority);
       
   178      	CleanupStack::PushL(unsafe8);
       
   179 	// escape encode only those characters that cannot be in the authority. assume all %s are %encoded already
       
   180 	HBufC8* authority8desc = EscapeUtils::ReEscapeEncodeL(*unsafe8);
       
   181 	CleanupStack::PopAndDestroy(unsafe8);
       
   182      	CleanupStack::PushL(authority8desc);
       
   183 	TAuthorityParser8 parser;
       
   184 	// parse the descriptor into the authority, Leave if it cannot be parsed
       
   185 	User::LeaveIfError( parser.Parse(*authority8desc) );
       
   186 
       
   187 	CAuthority8* authority8 = CAuthority8::NewL(parser);
       
   188 	CleanupStack::PopAndDestroy(authority8desc);
       
   189 	return authority8;
       
   190 	}
       
   191 
       
   192 /**
       
   193 	Checks a descriptor for excluded (invalid) characters. Excluded characters include all 
       
   194 	control characters (values 0x00 to 0x1F and greater than 0x7F), space (0x20), delimiter 
       
   195 	characters ('<', '>', '#', '%',	'"') and unwise characters ('{', '}', '|', '\', '^', '[', ']', '`').
       
   196 	
       
   197 	@since			6.0
       
   198 	@param			aData	The descriptor to be checked.
       
   199 	@return			A boolean value of ETrue if the descriptor contains invalid
       
   200 	characters, otherwise EFalse.
       
   201  */
       
   202 EXPORT_C TBool UriUtils::HasInvalidChars(const TDesC8& aData)
       
   203 	{
       
   204 	return CheckForExcludedChars(aData);
       
   205 	}
       
   206 	
       
   207 /**
       
   208 	Checks a descriptor for excluded (invalid) characters. Excluded characters include all 
       
   209 	control characters (values 0x00 to 0x1F and	greater than 0x7F), space (0x20), delimiter 
       
   210 	characters ('<', '>', '#', '%','"') and unwise characters ('{', '}', '|', '\', '^', '[', ']', '`').
       
   211 	
       
   212 	@since			6.0
       
   213 	@param			aData	The descriptor to be checked.
       
   214 	@return			A boolean value of ETrue if the descriptor contains invalid
       
   215 	characters, otherwise EFalse.
       
   216  */
       
   217 EXPORT_C TBool UriUtils::HasInvalidChars(const TDesC16& aData)
       
   218 	{
       
   219 	return CheckForExcludedChars(aData);
       
   220 	}
       
   221 
       
   222 /**
       
   223 	Checks the supplied host for an IPv4, IPv6 or text format host
       
   224 	
       
   225 	@since			7.0
       
   226 	@param			aHost	The descriptor containing the host to check
       
   227 	@return			A TUriHostType enum of either EIPv6, EIPv4, EText or EUnknown
       
   228  */
       
   229 EXPORT_C UriUtils::TUriHostType UriUtils::HostType(const TDesC8& aHost)
       
   230 	{
       
   231 	return CheckHostType(aHost);
       
   232 	}
       
   233 
       
   234 /**
       
   235 	Checks the supplied host for an IPv4, IPv6 or text format host
       
   236 	
       
   237 	@since			7.0
       
   238 	@param			aHost	The descriptor containing the host to check
       
   239 	@return			A TUriHostType enum of either EIPv6, EIPv4, EText or EUnknown
       
   240  */
       
   241 EXPORT_C UriUtils::TUriHostType UriUtils::HostType(const TDesC16& aHost)
       
   242 	{
       
   243 	return CheckHostType(aHost);
       
   244 	}
       
   245 
       
   246 
       
   247 
       
   248 //
       
   249 //
       
   250 // Implementation of component internal functions
       
   251 //
       
   252 //
       
   253 
       
   254 /**
       
   255 	@internalComponent
       
   256 
       
   257 	Checks whether the given scheme is a network scheme or not
       
   258 	
       
   259 	@param aScheme The descriptor with the scheme.
       
   260 	@return A boolean value of EFalse if the scheme is SIP.	For all other schemes returns ETrue.
       
   261  */
       
   262 TBool IsNetworkScheme(const TDesC8& aScheme)
       
   263 	{
       
   264 	TUriSchemeType scheme = SchemeType(aScheme);
       
   265 	if (scheme == ESchemeTypeSip)
       
   266 		{
       
   267 		return EFalse;
       
   268 		}
       
   269 	return ETrue;
       
   270 	}
       
   271 
       
   272 /**
       
   273 	@internalComponent
       
   274 
       
   275 	Checks whether the given scheme is a network scheme or not
       
   276 	
       
   277 	@param aScheme The descriptor with the scheme.
       
   278 	@return A boolean value of EFalse if the scheme is SIP.	For all other schemes returns ETrue.
       
   279  */
       
   280 TBool IsNetworkScheme(const TDesC16& aScheme)
       
   281 	{
       
   282 	TUriSchemeType scheme = SchemeType(aScheme);
       
   283 	if (scheme == ESchemeTypeSip)
       
   284 		{
       
   285 		return EFalse;
       
   286 		}
       
   287 	return ETrue;
       
   288 	}
       
   289 
       
   290 /**
       
   291 	@internalComponent
       
   292 
       
   293 	Returns the type of the URIs scheme
       
   294 	
       
   295 	@param			aScheme	The descriptor with the scheme.
       
   296 	@return			The scheme type
       
   297  */
       
   298 TUriSchemeType SchemeType(const TDesC8& aScheme)
       
   299 	{
       
   300 	// Compares the scheme with both sip and sips
       
   301 	if (aScheme.CompareF(KSipScheme8()) == 0 || aScheme.CompareF(KSipsScheme8()) == 0)
       
   302 		{
       
   303 		// there's a match so this is a sip scheme
       
   304 		return ESchemeTypeSip;
       
   305 		}
       
   306 	//Compares the scheme with tel 
       
   307 	else if (aScheme.CompareF(KTelScheme8()) == 0) 
       
   308 		{
       
   309 		return ESchemeTypeTel;
       
   310 		} 
       
   311 
       
   312 	return ESchemeTypeUnknown;
       
   313 	}
       
   314 
       
   315 /**
       
   316 	@internalComponent
       
   317 
       
   318 	Returns the type of the URIs scheme
       
   319 	
       
   320 	@param			aScheme	The descriptor with the scheme.
       
   321 	@return			The scheme type
       
   322  */
       
   323 TUriSchemeType SchemeType(const TDesC16& aScheme)
       
   324 	{
       
   325 	// Compares the scheme with both sip and sips
       
   326 	if (aScheme.CompareF(KSipScheme()) == 0 || aScheme.CompareF(KSipsScheme()) == 0)
       
   327 		{
       
   328 		// there's a match so this is a sip scheme
       
   329 		return ESchemeTypeSip;
       
   330 		}
       
   331 
       
   332 	return ESchemeTypeUnknown;
       
   333 	}
       
   334 
       
   335 /**
       
   336 	@internalComponent
       
   337 
       
   338 	Checks that a text host is in a valid form
       
   339 	
       
   340 	@param			aHost	The descriptor containing the host to check
       
   341 	@return			ETrue if the host is valid otherwise EFalse
       
   342  */
       
   343 TBool IsTextHostValid(const TDesC8& aHost)
       
   344 	{
       
   345 	return CheckValidTextHost(aHost);
       
   346 	}
       
   347 
       
   348 /**
       
   349 	@internalComponent
       
   350 
       
   351 	Checks that a text host is in a valid form
       
   352 	
       
   353 	@param			aHost	The descriptor containing the host to check
       
   354 	@return			ETrue if the host is valid otherwise EFalse
       
   355  */
       
   356 TBool IsTextHostValid(const TDesC16& aHost)
       
   357 	{
       
   358 	return CheckValidTextHost(aHost);
       
   359 	}
       
   360 
       
   361 
       
   362 /**
       
   363 	@internalComponent
       
   364 
       
   365 	Parses a segment of the form name=value and returns the name and value parts
       
   366 	
       
   367 	@param			aSegment	the name-value segemnt to parse
       
   368 	@param			aName		the name part that is returned
       
   369 	@param			aValue		the value part that is returned
       
   370  */
       
   371 void GetNameValuePair(const TDesC8& aSegment, TPtrC8& aName, TPtrC8& aValue)
       
   372 	{
       
   373 	TPtrC8 value;
       
   374 	TInt sepPos = aSegment.Locate(KEqualsSeparator);
       
   375 	if (sepPos != KErrNotFound)
       
   376 		{
       
   377 		aName.Set(aSegment.Left(sepPos));
       
   378 		value.Set(aSegment.Mid(sepPos+1));
       
   379 		}
       
   380 	else
       
   381 		{
       
   382 		aName.Set(aSegment);
       
   383 		}
       
   384 
       
   385 	aValue.Set(value);
       
   386 	}
       
   387 
       
   388 
       
   389 //
       
   390 //
       
   391 // Implementation of LOCAL functions
       
   392 //
       
   393 //
       
   394 
       
   395 /**
       
   396 	Checks the descriptor for any excluded characters. These are characters that 
       
   397 	should have been escaped encoded or ocnverted to Utf8 from Unicode.
       
   398 						
       
   399 	@since			6.0
       
   400 	@param			aData	The descriptor to be checked.
       
   401 	@return		A boolean value of ETrue if the descriptor contains excluded
       
   402 				characters, EFalse if it does not.
       
   403  */
       
   404 template<class TDesCType>
       
   405 LOCAL_C TBool CheckForExcludedChars(const TDesCType& aData)
       
   406 	{
       
   407 	// Run through the descriptor
       
   408 	TBool valid = ETrue;
       
   409 	const TInt length = aData.Length();
       
   410 	TInt i=0;
       
   411 	while( valid && i<length )
       
   412 		{
       
   413 		TInt notUsed;
       
   414 		// See if the character is an excluded one, or is part of an escape triple...
       
   415 		if( EscapeUtils::IsExcludedChar(aData[i]) && !EscapeUtils::IsEscapeTriple(aData.Mid(i), notUsed) )
       
   416 			{
       
   417 			valid = EFalse;
       
   418 			}
       
   419 		else
       
   420 			{
       
   421 			++i;
       
   422 			}
       
   423 		}
       
   424 	return !valid;
       
   425 	}
       
   426 
       
   427 /**
       
   428 	Checks the supplied host for an IPv4, IPv6 or text format host
       
   429 	
       
   430 	@since			7.0
       
   431 	@param			aHost	The descriptor containing the host to check
       
   432 	@return			A TUriHostType enum of either EIPv6, EIPv4, EText or EUnknown
       
   433  */
       
   434 template<class TDesCType>
       
   435 LOCAL_C UriUtils::TUriHostType CheckHostType(const TDesCType& aHost)
       
   436 	{
       
   437 	UriUtils::TUriHostType hostType;
       
   438 
       
   439 	TInt dotCount=0;
       
   440 	TBool colonPresent=EFalse;
       
   441 	TBool numeric=ETrue;
       
   442 
       
   443 	TInt len = aHost.Length();
       
   444 	for (TInt ii=0; ii < len && !colonPresent; ++ii)
       
   445 		{
       
   446 		TChar ch(aHost[ii]);
       
   447 
       
   448 		// host contains a character that is not '0'..'9' or '.'
       
   449 		if ((ch < 48 || ch > 57) && ch != 46)
       
   450 			numeric=EFalse;
       
   451 
       
   452 		// need to check that IPv4 address has the 3 dots
       
   453 		if (ch == 46)
       
   454 			++dotCount;
       
   455 		else
       
   456 			if (ch == 58)
       
   457 				colonPresent=ETrue;
       
   458 		}
       
   459 
       
   460 	if (colonPresent) // if theres a colon, it has to be an IPv6 address
       
   461 		hostType = UriUtils::EIPv6Host;
       
   462 	else
       
   463 		if (numeric  && (dotCount==3)) // if its numeric only, and has three seperators...
       
   464 			hostType = UriUtils::EIPv4Host;
       
   465 		else
       
   466 			hostType = UriUtils::ETextHost;
       
   467 
       
   468 	return hostType;
       
   469 	}
       
   470 
       
   471 /**
       
   472 	@internalComponent
       
   473 
       
   474 	Checks that a text host is in a valid form
       
   475 	
       
   476 	@param			aHost	The descriptor containing the host to check
       
   477 	@return			ETrue if the host is valid otherwise EFalse
       
   478  */
       
   479 template<class TDesCType>
       
   480 LOCAL_C TBool CheckValidTextHost(const TDesCType& aHost)
       
   481 	{
       
   482 	TInt len = aHost.Length();
       
   483 	if (len == 0)
       
   484 		return EFalse;
       
   485 
       
   486 	// host name can't start with a dot or dash
       
   487 	TChar firstChar(aHost[0]);
       
   488 	if (firstChar == '-' || firstChar == '.')
       
   489 		return EFalse;
       
   490 
       
   491 	TChar prev = '\0';
       
   492 	TInt ii;
       
   493 	for (ii=0; ii < len; ii++)
       
   494 		{
       
   495 		TChar ch(aHost[ii]);
       
   496 
       
   497 		// Valid characters are a-z, 0-9, '-' and '.'
       
   498 		if ((ch < 'A' || ch > 'Z') && (ch < 'a' || ch > 'z') && (ch < '0' || ch > '9') && ch != '-' && ch != '.')
       
   499 			{
       
   500 			return EFalse;
       
   501 			}
       
   502 
       
   503 		// dot is the section separator. Check the previous section is not empty
       
   504 		if (ch == '.' && prev == '.')
       
   505 			{
       
   506 			// can't have an empty section
       
   507 			return EFalse;
       
   508 			}
       
   509 			prev = ch;
       
   510 		}
       
   511 
       
   512 	// host name can't end with a dot or dash
       
   513 	if (prev == '-' || prev == '.')
       
   514 		return EFalse;
       
   515 
       
   516 	return ETrue;
       
   517 	}
       
   518 
       
   519 /**
       
   520 	Supports Syntax-Based Normalization as specifed in section 6.2.2 of RFC3986.
       
   521 	returns a new CUri8 object containing a normalised URI from a parsed URI object.
       
   522 	
       
   523 	@param aUri	A reference to a parsed uri object.
       
   524 	@return A pointer to a CUri8 object containing normalised URI.
       
   525 	@leave KErrNoMemory
       
   526 	@internalAll
       
   527  */
       
   528 EXPORT_C CUri8* UriUtils:: NormaliseUriL(const TUriC8& aUri)	
       
   529 	{
       
   530 	CUri8* normalisedUri = CUri8::NewLC(aUri);
       
   531 	PercentEncodeL(normalisedUri); 
       
   532 	CaseNormaliseL(normalisedUri);
       
   533 	RemoveDotSegmentsL(normalisedUri);
       
   534 	CleanupStack::Pop(normalisedUri);
       
   535 	return normalisedUri;
       
   536 	}
       
   537 	
       
   538 /**
       
   539 	Performs Case Normalization for CUri8 object as specified 
       
   540 	in section 6.2.2.1 of RFC3986.
       
   541 	
       
   542 	@param aNormalisedUri It is an in-out parameter. aNormalisedUri is a pointer 
       
   543 	to CUri8 object with an uri needs to be case normalised and returns with 
       
   544 	case normalised.
       
   545 	@leave KErrNoMemory
       
   546  */
       
   547 void CaseNormaliseL(CUri8* aNormalisedUri )	
       
   548 	{
       
   549 	//Case normalise the scheme
       
   550 	DoCaseNormaliseL(aNormalisedUri, EUriScheme);	
       
   551 	//Case normalise the Userinfo
       
   552 	DoCaseNormaliseL(aNormalisedUri, EUriUserinfo);	
       
   553 	//Case normalise the Host
       
   554 	DoCaseNormaliseL(aNormalisedUri, EUriHost);	
       
   555 	//Case normalise the Port
       
   556 	DoCaseNormaliseL(aNormalisedUri, EUriPort);	
       
   557 	//Case normalise the Path
       
   558 	DoCaseNormaliseL(aNormalisedUri, EUriPath);	
       
   559 	//Case normalise the Query
       
   560 	DoCaseNormaliseL(aNormalisedUri, EUriQuery);	
       
   561 	//Case normalise the Fragment
       
   562 	DoCaseNormaliseL(aNormalisedUri, EUriFragment);	
       
   563 	}
       
   564 
       
   565 /**
       
   566 	Performs Case Normalization for specified sub component of URI.
       
   567 	
       
   568 	@param aNormalisedUri It is an in-out parameter. aNormalisedUri is a pointer 
       
   569 	to CUri8 object with an uri needs to be case normalised and returns with 
       
   570 	case normalised for specified sub component.
       
   571 	@param aComponent Enumeration of TUriComponent.
       
   572 	@leave KErrNoMemory
       
   573 */
       
   574 void DoCaseNormaliseL(CUri8* aNormalisedUri, TUriComponent aComponent)
       
   575 	{
       
   576 	const TUriC8& uri(aNormalisedUri->Uri());
       
   577 	if(!uri.IsPresent(aComponent) )
       
   578 		{
       
   579 		return;
       
   580 		}
       
   581 	//extracts subcomponent of uri which needs to be case-normalised
       
   582 	HBufC8* heapBuf = uri.Extract(aComponent).AllocLC(); 	
       
   583 	TPtr8 normalisedComponent(heapBuf->Des());
       
   584 	TBool normalised = EFalse;
       
   585 	if(aComponent == EUriScheme || aComponent == EUriHost )
       
   586 		{
       
   587 		//change this component to lower case
       
   588 		normalisedComponent.LowerCase();
       
   589 		normalised = ETrue;
       
   590 		}
       
   591 	
       
   592 	TInt len =  normalisedComponent.Length();
       
   593 	TBuf8<KSubstringLength> subString;
       
   594 	//case normalise the component
       
   595 	for (TInt pos = 0; pos < len; pos++)
       
   596 		{
       
   597 		if (normalisedComponent[pos] == KEscapeIndicator )
       
   598 			{
       
   599 			__ASSERT_DEBUG( ((len-pos) >= KSubstringLength), User::Panic(KNormalisationUriPanicCategory, KUriUtilsErrBadEscapeTriple) );
       
   600 			TPtrC8 componentBuf(normalisedComponent.Mid(pos,KSubstringLength));
       
   601 			if (ValidateAndConvertPercentEncodedTriple(componentBuf,subString))
       
   602 				{
       
   603 				normalisedComponent.Replace(pos,KSubstringLength,subString);
       
   604 				pos += KUpdateLength;
       
   605 				normalised = ETrue;
       
   606 				subString.Zero();
       
   607 				}
       
   608 			}
       
   609 		}
       
   610 
       
   611 	//updating the uri with normalised string
       
   612 	if( normalised )
       
   613 		{
       
   614 		if(aComponent<EUriMaxComponents && aComponent >=EUriScheme)
       
   615 		   {
       
   616 		   aNormalisedUri->SetComponentL(normalisedComponent, aComponent);
       
   617 		   }
       
   618 		else
       
   619 		   {
       
   620 			User::Leave(KErrArgument);	
       
   621 		   }
       
   622 
       
   623 		}
       
   624 	CleanupStack::PopAndDestroy(heapBuf);
       
   625 	}
       
   626 
       
   627 /**
       
   628 	Validates and Converts the valid Percent encoded triplets to Uppercase for specified 
       
   629 	sub component of URI. For eg: Converts %3a to %3A
       
   630 	
       
   631 	@param aData A reference to a string to be validated and converted to upper case.
       
   632 	@param aCaseNormalizedData A reference to a descriptor that is converted to 
       
   633 	uppercase that is to be returned.
       
   634 	@return returns a bool whether it is a valid Percent encoded triplet
       
   635 */
       
   636 TBool ValidateAndConvertPercentEncodedTriple(TDesC8& aData , TDes8& aCaseNormalizedData )	
       
   637 	{
       
   638 	// See if the descriptor is actually long enough and
       
   639 	// Check that the three characters form an escape triple - first char is '%'
       
   640 	if( aData.Length() < KEscapeTripleLength || aData[KEscDelimiterPos] != KEscapeIndicator )
       
   641 		{
       
   642 		return EFalse;//do nothing
       
   643 		}
       
   644 	
       
   645 	// Check that next two characters are valid
       
   646 	TInt mostSignificantDigitValue = KHexDigit().LocateF(aData[KMostSignificantNibblePos] );
       
   647 	TInt leastSignificantDigitValue = KHexDigit().LocateF(aData[KLeastSignificantNibblePos] );
       
   648 
       
   649 	if( mostSignificantDigitValue== KErrNotFound || leastSignificantDigitValue == KErrNotFound )
       
   650 		{
       
   651 		// Either of the characters were not a valid hex character
       
   652 		return EFalse;
       
   653 		}
       
   654 	aCaseNormalizedData.Zero();
       
   655 	aCaseNormalizedData.Append(KEscapeIndicator); 
       
   656 	
       
   657 	//Coverts most significant hex character to uppercase
       
   658 	(mostSignificantDigitValue >= 0 && mostSignificantDigitValue <= 0xF) ? 
       
   659 		aCaseNormalizedData.Append(KHexDigit().Mid(mostSignificantDigitValue,1)) :
       
   660 		aCaseNormalizedData.Append(KHexDigit().Mid(mostSignificantDigitValue,1));
       
   661 	
       
   662 	//Coverts least significant hex character to uppercase
       
   663 	(leastSignificantDigitValue >= 0 && leastSignificantDigitValue <= 0xF) ? 
       
   664 		aCaseNormalizedData.Append(KHexDigit().Mid(leastSignificantDigitValue,1)) :
       
   665 		aCaseNormalizedData.Append(aData[KLeastSignificantNibblePos]);
       
   666 	
       
   667 	return ETrue;
       
   668 	}
       
   669 
       
   670 /**
       
   671 	Performs Percent-Encoding Normalization for CUri8 object as specifed in 
       
   672 	section 6.2.2.2 of RFC3986.
       
   673 	
       
   674 	@param aNormalisedUri It is an in-out parameter. aNormalisedUri is a pointer to 
       
   675 	CUri8 object with an uri needs to be Percent-Encoded and returns with Percent-Encode 
       
   676 	normalised form.
       
   677 	@leave KErrNoMemory
       
   678  */
       
   679 void  PercentEncodeL(CUri8* aNormalisedUri)
       
   680 	{
       
   681 	//PercentEncode the scheme
       
   682 	DoPercentEncodeL(aNormalisedUri, EUriScheme);	
       
   683 	//PercentEncode the Userinfo
       
   684 	DoPercentEncodeL(aNormalisedUri, EUriUserinfo);	
       
   685 	//PercentEncode the Host
       
   686 	DoPercentEncodeL(aNormalisedUri, EUriHost);	
       
   687 	//PercentEncode the Port
       
   688 	DoPercentEncodeL(aNormalisedUri, EUriPort);	
       
   689 	//PercentEncode the Path
       
   690 	DoPercentEncodeL(aNormalisedUri, EUriPath);	
       
   691 	//PercentEncode the Query
       
   692 	DoPercentEncodeL(aNormalisedUri, EUriQuery);	
       
   693 	//PercentEncode the Fragment
       
   694 	DoPercentEncodeL(aNormalisedUri, EUriFragment);	
       
   695 	}
       
   696 
       
   697 /**
       
   698 	Performs Percent-Encoding for specified sub component of URI.
       
   699 	
       
   700 	@param aNormalisedUri It is an in-out parameter. aNormalisedUri is a pointer to 
       
   701 	CUri8 object with an uri needs to be Percent-Encoded and returns with Percent-Encoded 
       
   702 	for specified sub component.
       
   703 	@param aComponent Enumeration of TUriComponent.
       
   704 	@leave KErrNoMemory
       
   705 */
       
   706 void DoPercentEncodeL(CUri8* aNormalisedUri, TUriComponent aComponent)
       
   707 	{
       
   708 	const TUriC8& uri(aNormalisedUri->Uri());
       
   709 	if(!uri.IsPresent(aComponent))
       
   710 		{
       
   711 		return;
       
   712 		}
       
   713 	
       
   714 	HBufC8* heapBuf = uri.Extract(aComponent).AllocLC();
       
   715 	TPtr8 percentNormalisedComponent(heapBuf->Des());
       
   716 	TBool normalised = EFalse;
       
   717 	TInt len = percentNormalisedComponent.Length();	
       
   718 	for (TInt pos = 0; pos < len; pos++)
       
   719 		{
       
   720 		TInt hex;
       
   721 		// check for and decode '%' encoded characters
       
   722 		if (percentNormalisedComponent[pos] == KEscapeIndicator && EscapeUtils::IsEscapeTriple(percentNormalisedComponent.Mid(pos, KSubstringLength), hex))
       
   723 			{
       
   724 			TChar replacedChar(hex);
       
   725 			if( KUnreserved().LocateF(hex) != KErrNotFound || replacedChar.IsAlphaDigit() )
       
   726 				{
       
   727 				TBuf8<KAttachLength> subString;
       
   728 				subString.Append(replacedChar);
       
   729 				percentNormalisedComponent.Replace(pos, KSubstringLength, subString);
       
   730 				normalised = ETrue;
       
   731 				len = percentNormalisedComponent.Length();
       
   732 				}
       
   733 			}
       
   734 		}
       
   735 	if( normalised )
       
   736 		{
       
   737 		if(aComponent<EUriMaxComponents && aComponent >=EUriScheme)
       
   738 		   {
       
   739 		    aNormalisedUri->SetComponentL(percentNormalisedComponent, aComponent);
       
   740 		   }
       
   741 		else
       
   742 		   {
       
   743 			User::Leave(KErrArgument);	
       
   744 		   }
       
   745 
       
   746 		}
       
   747 	CleanupStack::PopAndDestroy(heapBuf); 	
       
   748 	}
       
   749 
       
   750 /**
       
   751 	Performs Path Segment Normalization for CUri8 object as specifed in 
       
   752 	section 6.2.2.3 of RFC3986.
       
   753 	
       
   754 	@param aNormalisedUri It is an in-out parameter. aNormalisedUri is a pointer to 
       
   755 	CUri8 object with uri needs to be Path Segment normalised and returns with 
       
   756 	Path Segment normalised form.
       
   757 	@leave KErrNoMemory
       
   758  */
       
   759 void  RemoveDotSegmentsL(CUri8* aNormalisedUri)
       
   760 	{
       
   761 	const TUriC8& uri( aNormalisedUri->Uri() );
       
   762 	if(uri.IsPresent(EUriPath))
       
   763 		{
       
   764 		HBufC8* dotSegmentsPath = uri.Extract(EUriPath).AllocLC();
       
   765 		RemoveExtraneousDotSegmentsL(dotSegmentsPath);
       
   766 		aNormalisedUri->SetComponentL(*dotSegmentsPath, EUriPath);	
       
   767 		CleanupStack::PopAndDestroy(dotSegmentsPath);	
       
   768 		}
       
   769 	}
       
   770 
       
   771 /**
       
   772 	Performs Remove_dot_segments algorithm as specifed in section 5.2.4 of RFC3986.
       
   773 	
       
   774 	@param aUriInputPath It is an in-out parameter. aUriInputPath is a pointer to the 
       
   775 	path descriptor to be normalised for extraneous dot_segments and returns with 
       
   776 	normalised dot_segments.
       
   777 	@leave KErrNoMemory
       
   778 */
       
   779 void RemoveExtraneousDotSegmentsL(HBufC8* aUriInputPath)
       
   780 	{
       
   781 	TPtr8 uriPathBuf(aUriInputPath->Des());
       
   782 	TInt length = uriPathBuf.Length();	
       
   783 	HBufC8* path = HBufC8::NewLC(length);
       
   784 	TPtr8 transitionalBuf(path->Des());
       
   785 
       
   786 	while(length > 0)	
       
   787 		{
       
   788 		//step a of section 5.2.4 of RFC 3986
       
   789 		if(length >= KDotDotSlashLength && 
       
   790 			KDotDotSlash().Compare(uriPathBuf.Mid(0, KDotDotSlashLength)) == 0 )
       
   791 			{
       
   792 			uriPathBuf.Delete(0,KDotDotSlashLength);
       
   793 			}
       
   794 		//step a of section 5.2.4 of RFC 3986
       
   795 		else if(length >= KDotDotLength && 
       
   796 				KDotSlash().Compare(uriPathBuf.Mid(0, KDotDotLength)) == 0)
       
   797 			{
       
   798 			uriPathBuf.Delete(0,KDotDotLength);	
       
   799 			}
       
   800 		//step b of section 5.2.4 of RFC 3986
       
   801 		else if(length >= KDotDotSlashLength && 
       
   802 				KSlashDotSlash().Compare(uriPathBuf.Mid(0, KDotDotSlashLength)) == 0)
       
   803 			{
       
   804 			uriPathBuf.Replace(0, KDotDotSlashLength, KSlash);
       
   805 			}
       
   806 		//step c of section 5.2.4 of RFC 3986
       
   807 		else if(length >= KSlashDotDotSlashLength && 
       
   808 				KSlashDotDotSlash().Compare(uriPathBuf.Mid(0, KSlashDotDotSlashLength)) == 0)
       
   809 			{
       
   810 			updateStrings(uriPathBuf, transitionalBuf, KSlashDotDotSlashLength);
       
   811 			}
       
   812 		//step c of section 5.2.4 of RFC 3986 --complete path segment
       
   813 		else if(length == KDotDotSlashLength && 
       
   814 				KSlashDotDot().Compare(uriPathBuf.Mid(0, KDotDotSlashLength)) == 0)
       
   815 			{
       
   816 			updateStrings(uriPathBuf, transitionalBuf, KDotDotSlashLength);
       
   817 			}
       
   818 		//step b of section 5.2.4 of RFC 3986--complete path segment
       
   819 		else if(length == KDotDotLength && 
       
   820 				KSlashDot().Compare(uriPathBuf.Mid(0, KDotDotLength)) == 0)
       
   821 			{
       
   822 			uriPathBuf.Replace(0, KDotDotLength, KSlash);
       
   823 			}
       
   824 		//step d of section 5.2.4 of RFC 3986
       
   825 		else if(length == KDotDotLength && 
       
   826 				KDotDot().Compare(uriPathBuf.Mid(0)) == 0)
       
   827 			{
       
   828 			uriPathBuf.Delete(0,KDotDotLength);	
       
   829 			}
       
   830 		//step d of section 5.2.4 of RFC 3986
       
   831 		else if(length == KDotLength && 
       
   832 				KDot().Compare(uriPathBuf.Mid(0)) == 0)
       
   833 			{
       
   834 			uriPathBuf.Delete(0,KDotLength);	
       
   835 			}
       
   836 		//step e of section 5.2.4 of RFC 3986
       
   837 		else 
       
   838 			{
       
   839 			//get the first path segment including initial / (if any)from uriPathBuf
       
   840 			// till next slash (but not including next slash)..append it to the output Buf	
       
   841 			TInt substrLength;
       
   842 			TInt nextSlashPos = uriPathBuf.Find(KSlash);
       
   843 			if(nextSlashPos == 0 && length > KDotLength)
       
   844 				//replace with locate next
       
   845 				{
       
   846 				nextSlashPos = uriPathBuf.Mid(1).Find(KSlash);
       
   847 				if(nextSlashPos != KErrNotFound)
       
   848 					{
       
   849 					++nextSlashPos;
       
   850 					}
       
   851 				}
       
   852 			if(length == KDotLength)
       
   853 				//only '/' is exist
       
   854 				{
       
   855 				substrLength = length;	
       
   856 				}
       
   857 			else
       
   858 				{
       
   859 				substrLength = nextSlashPos == KErrNotFound ? length : nextSlashPos ;	
       
   860 				}
       
   861 			transitionalBuf.Append(uriPathBuf.Mid(0,substrLength));
       
   862 			uriPathBuf.Delete(0,substrLength);	
       
   863 			}
       
   864 		length = uriPathBuf.Length();
       
   865 		}
       
   866 	uriPathBuf.Copy(transitionalBuf);
       
   867 	CleanupStack::PopAndDestroy(path);
       
   868 	}
       
   869 
       
   870 /**
       
   871 	Updates the strings specified in step c of section 5.2.4 of RFC 3986
       
   872 	
       
   873 	@param aInputBuf A reference to the inputBuf needs to be modified 
       
   874 	@param aOutPutBuf A reference to the outPutBuf needs to be modified
       
   875 	@param aLength length of the string to be replaced.
       
   876  */
       
   877 void  updateStrings(TPtr8& aInputBuf, TPtr8& aOutPutBuf, TInt aLength)
       
   878 	{
       
   879 	aInputBuf.Replace(0,aLength,KSlash);
       
   880 
       
   881 	//In outPutBuf to remove the last segment starting with / (if exist)
       
   882 	//eg: /abc/def/fgh --> /abc/def
       
   883 	TInt outputBufLength = aOutPutBuf.Length();
       
   884 	TInt pos = aOutPutBuf.LocateReverse('/');	
       
   885 	//remove the last segment including '/'
       
   886 	pos != KErrNotFound ? aOutPutBuf.Delete( pos, outputBufLength - pos ) : aOutPutBuf.Delete( 0,outputBufLength );
       
   887 	}
       
   888