genericservices/httputils/EscapeUtils/EscapeUtils.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 <escapeutils.h>
       
    17 
       
    18 #include <utf.h>
       
    19 
       
    20 #include "EscapeUtilsInternal.h"
       
    21 
       
    22 // Constants
       
    23 //
       
    24 _LIT(KHexDigit, "0123456789ABCDEF");
       
    25 _LIT(KExcludedData, "{}|\\^`<>#%\"");
       
    26 _LIT8(KQueryData8, ";/?:@&=+$,[]");
       
    27 _LIT8(KPathData8, "/;=?[]");
       
    28 _LIT8(KAuthData8, ";:@?/[]");
       
    29 _LIT8(KUrlEncoded8, ";/?:@&=+$[]!\'()~*");
       
    30 _LIT16(KQueryData16, ";/?:@&=+$,[]");
       
    31 _LIT16(KPathData16, "/;=?[]");
       
    32 _LIT16(KAuthData16, ";:@?/[]");
       
    33 _LIT16(KUrlEncoded16, ";/?:@&=+$[]!\'()~");
       
    34 const TInt KEscapeUtilsConversionBufferSize	= 50;
       
    35 const TInt KEscapeIndicator					= '%';
       
    36 const TInt KEscapeTripleLength				= 3;
       
    37 const TInt KEscDelimiterPos					= 0;
       
    38 const TInt KMostSignificantNibblePos		= 1;
       
    39 const TInt KLeastSignificantNibblePos		= 2;
       
    40 
       
    41 // Panic category
       
    42 //
       
    43 #ifdef _DEBUG
       
    44 	_LIT(KEscapeUtilsPanicCategory, "ESC-UTILS"); 
       
    45 #endif
       
    46 
       
    47 //
       
    48 //
       
    49 // Implementation of EscapeUtils
       
    50 //
       
    51 //
       
    52 
       
    53 /**
       
    54 	Escape encodes excluded and reserved characters in the data as escape triples. 
       
    55 	The reserved characters are defined by the escape mode. These characters and the 
       
    56 	set of excluded characters specified by RFC2396 form the entire set of excluded data.
       
    57 						
       
    58 	@since			6.0
       
    59 	@leave		    KUriUtilsErr16BitChar. A 16-Bit character was found in the data to be escape encoded.
       
    60 	@param			aData	A descriptor with the data to encode.
       
    61 	@param			aEscapeMode	An enum specifying the escape mode.
       
    62 	@return			A pointer to a descriptor buffer which contains the escape encoded data.
       
    63 */
       
    64 EXPORT_C HBufC8* EscapeUtils::EscapeEncodeL(const TDesC8& aData, TEscapeMode aEscapeMode)
       
    65 	{
       
    66 	// Need descriptor pointer to reserved characters...
       
    67 	TPtrC8 reserved;
       
    68 
       
    69 	switch (aEscapeMode)
       
    70 		{
       
    71 	case EEscapeNormal:
       
    72 		{
       
    73 		// This is normal operation - no reserved chars
       
    74 		reserved.Set(KNullDesC8);
       
    75 		} break;
       
    76 	case EEscapeQuery:
       
    77 		{
       
    78 		// Reserved data in a URI query - ; / ? : @ & = + $ ,
       
    79 		reserved.Set(KQueryData8());
       
    80 		} break;
       
    81 	case EEscapePath:
       
    82 		{
       
    83 		// Reserved data in a URI path segment - / ; = ?
       
    84 		reserved.Set(KPathData8());
       
    85 		} break;
       
    86 	case EEscapeAuth:
       
    87 		{
       
    88 		// Reserved data in a URI authority - ; : @ ? /
       
    89 		reserved.Set(KAuthData8());
       
    90 		} break;
       
    91 	case EEscapeUrlEncoded:
       
    92 		{
       
    93 		// Reserved data in  Url Encoded data - ; / ? : @ & = + $ [ ] ! ' ( ) ~ *
       
    94 		reserved.Set(KUrlEncoded8());
       
    95 		} break;
       
    96 	default:
       
    97 		// Not supported return NULL
       
    98 		__ASSERT_DEBUG(EFalse, User::Panic(KEscapeUtilsPanicCategory, KUriUtilsErrBadEscapeMode));
       
    99 		return NULL;
       
   100 		}
       
   101 	return EscapeEncodeL(aData, reserved);
       
   102 	}
       
   103 
       
   104 /**
       
   105 	Escape encodes excluded and reserved characters in the data as escape triples. The 
       
   106 	reserved characters are defined by the escape mode. These characters and the set of 
       
   107 	excluded characters specified by RFC2396 form the entire set of excluded data.
       
   108 						
       
   109 	@since			6.0
       
   110 	@leave			KUriUtilsErr16BitChar. A 16-Bit character was found in the data to be escape encoded.
       
   111 	@param			aData	A descriptor with the data to encode.
       
   112 	@param			aEscapeMode	An enum specifying the escape mode.
       
   113 	@return			A pointer to a descriptor buffer which contains the escape encoded data.
       
   114 */
       
   115 EXPORT_C HBufC16* EscapeUtils::EscapeEncodeL(const TDesC16& aData, TEscapeMode aEscapeMode)
       
   116 	{
       
   117 	// Need to descriptor pointer to reserved chars
       
   118 	TPtrC16 reserved;
       
   119 
       
   120 	switch (aEscapeMode)
       
   121 		{
       
   122 	case EEscapeNormal:
       
   123 		{
       
   124 		// This is normal operation - no reserved chars
       
   125 		reserved.Set(KNullDesC16);
       
   126 		} break;
       
   127 	case EEscapeQuery:
       
   128 		{
       
   129 		// Reserved data in a URI query - ; / ? : @ & = + $ [],
       
   130 		reserved.Set(KQueryData16());
       
   131 		} break;
       
   132 	case EEscapePath:
       
   133 		{
       
   134 		// Reserved data in a URI path segment - / ; = ? []
       
   135 		reserved.Set(KPathData16());
       
   136 		} break;
       
   137 	case EEscapeAuth:
       
   138 		{
       
   139 		// Reserved data in a URI authority - ; : @ ? / []
       
   140 		reserved.Set(KAuthData16());
       
   141 		} break;
       
   142 	case EEscapeUrlEncoded:
       
   143 		{
       
   144 		// Reserved data in  Url Encoded data - ; / ? : @ & = + $ [ ] ! ' ( ) ~
       
   145 		reserved.Set(KUrlEncoded16());
       
   146 		} break;
       
   147 	default:
       
   148 		// Not supported return NULL
       
   149 		__ASSERT_DEBUG(EFalse, User::Panic(KEscapeUtilsPanicCategory, KUriUtilsErrBadEscapeMode));
       
   150 		return NULL;
       
   151 		}
       
   152 	return EscapeEncodeL(aData, reserved);
       
   153 	}
       
   154 
       
   155 /**
       
   156 	Escape encodes excluded and reserved characters in the data as escape triples. These 
       
   157 	characters and the set of excluded characters specified by RFC2396 form the entire set
       
   158 	of excluded data.
       
   159 						
       
   160 	@since			6.0
       
   161 	@leave			KUriUtilsErr16BitChar. A 16-Bit character was found in the data to be escape encoded.
       
   162 	@param			aData			A descriptor with the data to encode.
       
   163 	@param			aReservedChars	A descriptor with the reserved characters.
       
   164 	@return			A pointer to a descriptor buffer which contains the escape encoded data.
       
   165 */
       
   166 EXPORT_C HBufC8* EscapeUtils::EscapeEncodeL(const TDesC8& aData, const TDesC8& aReservedChars)
       
   167 	{
       
   168 	// Allocate space to build escaped url - consider worse case; all characters are excluded => length x 3
       
   169 	HBufC8* buf = HBufC8::NewLC(aData.Length()*3);
       
   170 	TPtr8 escaped = buf->Des();
       
   171 
       
   172 	User::LeaveIfError(EscapeEncodeData(aData, aReservedChars, escaped));
       
   173 	HBufC8* encoded = escaped.AllocL();
       
   174 
       
   175 	CleanupStack::PopAndDestroy(buf);
       
   176 	return encoded;
       
   177 	}
       
   178 
       
   179 /**
       
   180 	Escape encodes excluded and reserved characters in the data as escape triples. These characters 
       
   181 	and the set of excluded characters specified by RFC2396 form the entire set of excluded data.
       
   182 						
       
   183 	@since			6.0
       
   184 	@leave			KUriUtilsErr16BitChar. A 16-Bit character was found in the data to be escape encoded.
       
   185 	@param			aData			A descriptor with the data to encode.
       
   186 	@param			aReservedChars	A descriptor with the reserved characters.
       
   187 	@return			A pointer to a descriptor buffer which contains the escape encoded data.
       
   188 */
       
   189 EXPORT_C HBufC16* EscapeUtils::EscapeEncodeL(const TDesC16& aData, const TDesC16& aReservedChars)
       
   190 	{
       
   191 	// Allocate space to build escaped url - consider worse case; all characters are excluded => length x 3
       
   192 	HBufC16* buf = HBufC16::NewLC(aData.Length()*3);
       
   193 	TPtr16 escaped = buf->Des();
       
   194 
       
   195 	User::LeaveIfError(EscapeEncodeData(aData, aReservedChars, escaped));
       
   196 	HBufC16* encoded = escaped.AllocL();
       
   197 
       
   198 	CleanupStack::PopAndDestroy(buf);
       
   199 	return encoded;
       
   200 	}
       
   201 
       
   202 /**
       
   203 	Escape decodes the data.
       
   204 	
       
   205 	@since			6.0
       
   206 	@param			aData	A descriptor with the data to decode.
       
   207 	@return			A pointer to a descriptor buffer which contains the escape decoded data.
       
   208 */
       
   209 EXPORT_C HBufC8* EscapeUtils::EscapeDecodeL(const TDesC8& aData)
       
   210 	{
       
   211 	// Allocate space to build unescaped data
       
   212 	HBufC8* buf = HBufC8::NewLC(aData.Length());
       
   213 	TPtr8 unescaped = buf->Des();
       
   214 
       
   215 	User::LeaveIfError(EscapeDecodeData(aData, unescaped));
       
   216 	HBufC8* decoded = unescaped.AllocL();
       
   217 
       
   218 	CleanupStack::PopAndDestroy(buf);
       
   219 	return decoded;
       
   220 	}
       
   221 
       
   222 /**
       
   223 	Escape decodes the data.
       
   224 	
       
   225 	@since			6.0
       
   226 	@param			aData	A descriptor with the data to decode.
       
   227 	@return			A pointer to a descriptor buffer which contains the escape decoded data.
       
   228 */
       
   229 EXPORT_C HBufC16* EscapeUtils::EscapeDecodeL(const TDesC16& aData)
       
   230 	{
       
   231 	// Allocate space to build unescaped data
       
   232 	HBufC16* buf = HBufC16::NewLC(aData.Length());
       
   233 	TPtr16 unescaped = buf->Des();
       
   234 
       
   235 	User::LeaveIfError(EscapeDecodeData(aData, unescaped));
       
   236 	HBufC16* decoded = unescaped.AllocL();
       
   237 
       
   238 	CleanupStack::PopAndDestroy(buf);
       
   239 	return decoded;
       
   240 	}
       
   241 
       
   242 /**
       
   243 	@internalComponent
       
   244 	
       
   245 	escape encode only those characters that cannot be in a URI. assume all %hh are %encoded already.
       
   246 	
       
   247 	@param		aData	The descriptor buffer to be escape encoded.
       
   248 	@return		A pointer to a descriptor buffer which contains the escape encoded data.
       
   249 */
       
   250 HBufC8* EscapeUtils::ReEscapeEncodeL(const TDesC8& aData)
       
   251 	{
       
   252 	// Descriptor to hex digits and excluded chars
       
   253 	const TDesC& KHexChars = KHexDigit;
       
   254 
       
   255 	const TInt length = aData.Length();
       
   256 	
       
   257 	// find out how many characters need escape encoding
       
   258 	TInt count = 0;
       
   259 	for( TInt i=0; i<length; ++i )
       
   260 		{
       
   261 		TChar current( aData[i] );
       
   262 		if( EscapeUtils::IsExcludedChar(current) && current != KFragmentDelimiter && 
       
   263 			!(current == KEscapeIndicator &&  i+2<length && TChar(aData[i+1]).IsHexDigit() && TChar(aData[i+2]).IsHexDigit() ) )
       
   264 			{
       
   265 			count++;
       
   266 			}
       
   267 		}
       
   268 	if( count == 0)	// no encoding needed, just allocate and return the whole string
       
   269 		{
       
   270 		return aData.AllocL();
       
   271 		}
       
   272 	// pre-allocate space for the descriptor
       
   273 	HBufC8* buf = HBufC8::NewLC( aData.Length() + count*2 ); // two extra chars for each escaped
       
   274 	TPtr8 escaped = buf->Des();
       
   275 
       
   276 	for( TInt i=0; i<length; ++i )
       
   277 		{
       
   278 		// Check if current character must be escaped
       
   279 		TChar current ( aData[i] );
       
   280 		// Check if current character is excluded, but not  if it appears to be escape encoded
       
   281 		TBool excluded = EscapeUtils::IsExcludedChar(current) && current != KFragmentDelimiter &&
       
   282 			!(current == KEscapeIndicator &&  i+2<length && TChar(aData[i+1]).IsHexDigit() && TChar(aData[i+2]).IsHexDigit() );
       
   283 
       
   284 		if( excluded )
       
   285 			{
       
   286 			// Excluded char - escape encode
       
   287 			escaped.Append(KEscapeIndicator);
       
   288 			const TInt mostSignificantNibble = (current & 0xf0) >> 4;	// Get msNibble by masking against 11110000 and dividing by 16 (>>4)
       
   289 			escaped.Append(KHexChars[mostSignificantNibble]);
       
   290 			const TInt leastSignificantNibble = (current & 0x0f);		// Get lsNibble by masking against 00001111
       
   291 			escaped.Append(KHexChars[leastSignificantNibble]);
       
   292 			}
       
   293 		else
       
   294 			{
       
   295 			// Not an excluded char - just append			  
       
   296 			escaped.Append(current);
       
   297 			}
       
   298 		}
       
   299 	CleanupStack::Pop(buf);
       
   300 	return buf;
       
   301 	}
       
   302 
       
   303 
       
   304 /**
       
   305 
       
   306 	Converts UNICODE data into UTF8 format.
       
   307 	
       
   308 	@since			6.0
       
   309 	@leave			KUriUtilsCannotConvert. When the input data cannot be converted.
       
   310 	@param			aString			A descriptor with the data to convert.
       
   311 	@return			A pointer to an 8-bit descriptor buffer which contains UTF8 data.
       
   312 */
       
   313 EXPORT_C HBufC8* EscapeUtils::ConvertFromUnicodeToUtf8L(const TDesC& aString)
       
   314 	{
       
   315 	// Return an empty buffer straight-away
       
   316 	if( aString.Compare(KNullDesC) == 0 )
       
   317 		return KNullDesC8().AllocL();
       
   318 
       
   319 	// Convert from Unicode to UTF8
       
   320 	TPtrC unicode = aString;
       
   321 	TBuf8<KEscapeUtilsConversionBufferSize> buf;
       
   322 	HBufC8* utf8Buffer = HBufC8::NewLC(unicode.Length());
       
   323 	TPtr8 utf8 = utf8Buffer->Des();
       
   324 
       
   325 	// Loop until all of the filename is converted
       
   326 	FOREVER
       
   327 		{
       
   328 		const TInt returnValue = CnvUtfConverter::ConvertFromUnicodeToUtf8(buf, unicode);
       
   329 		if( returnValue == CnvUtfConverter::EErrorIllFormedInput || returnValue < 0)
       
   330 			User::Leave(KUriUtilsCannotConvert);
       
   331 
       
   332 		// Is escapedFullPath too small?
       
   333 		if( utf8.Length() + buf.Length() > utf8.MaxLength() )
       
   334 			{
       
   335 			utf8Buffer = utf8Buffer->ReAllocL(utf8.Length() + buf.Length());
       
   336 			CleanupStack::Pop();	// utf8Buffer (old version)
       
   337 			CleanupStack::PushL(utf8Buffer);	// new version
       
   338 			utf8.Set(utf8Buffer->Des());
       
   339 			}
       
   340 		// Copy converted characters
       
   341 		utf8.Append(buf);
       
   342 
       
   343 		if( returnValue == KErrNone )
       
   344 			break; // All of aUnicodeText has been converted and handled
       
   345 
       
   346 		// Set input descriptor to remaining characters
       
   347 		unicode.Set(unicode.Right(returnValue));
       
   348 		}
       
   349 	CleanupStack::Pop(utf8Buffer);
       
   350 	return utf8Buffer;		// Ownership transfered to caller
       
   351 	}
       
   352 
       
   353 /**
       
   354 	Converts UTF8 format into UNICODE data.
       
   355 	
       
   356 	@since			6.0
       
   357 	@leave			KUriUtilsCannotConvert. When the input data cannot be converted.
       
   358 	@param			aString			A descriptor with the data to convert.
       
   359 	@return			A pointer to a 16-bit descriptor buffer which contains UNICODE data.
       
   360 */
       
   361 EXPORT_C HBufC* EscapeUtils::ConvertToUnicodeFromUtf8L(const TDesC8& aString)
       
   362 	{
       
   363 	// Return an empty buffer straight-away
       
   364 	if( aString.Compare(KNullDesC8) == 0 )
       
   365 		return KNullDesC().AllocL();
       
   366 
       
   367 	// Convert from Unicode to UTF8
       
   368 	TPtrC8 utf8 = aString;
       
   369 	TBuf<KEscapeUtilsConversionBufferSize> buf;
       
   370 	HBufC* unicodeBuffer = HBufC::NewLC(utf8.Length());
       
   371 	TPtr unicode = unicodeBuffer->Des();
       
   372 
       
   373 	// Loop until all of the filename is converted
       
   374 	FOREVER
       
   375 		{
       
   376 		const TInt returnValue = CnvUtfConverter::ConvertToUnicodeFromUtf8(buf, utf8);
       
   377 		if( returnValue == CnvUtfConverter::EErrorIllFormedInput || returnValue < 0)
       
   378 			User::Leave(KUriUtilsCannotConvert);
       
   379 
       
   380 		// Is escapedFullPath too small?
       
   381 		if( unicode.Length() + buf.Length() > unicode.MaxLength() )
       
   382 			{
       
   383 			unicodeBuffer = unicodeBuffer->ReAllocL(unicode.Length() + buf.Length());
       
   384 			CleanupStack::Pop();	// unicodeBuffer (old version)
       
   385 			CleanupStack::PushL(unicodeBuffer);	// new version
       
   386 			unicode.Set(unicodeBuffer->Des());
       
   387 			}
       
   388 		// Copy converted characters
       
   389 		unicode.Append(buf);
       
   390 
       
   391 		if( returnValue==0 )
       
   392 			break; // All of utf8 has been converted and handled
       
   393 
       
   394 		// Set input descriptor to remaining characters
       
   395 		utf8.Set(utf8.Right(returnValue));
       
   396 		}
       
   397 	CleanupStack::Pop(unicodeBuffer);
       
   398 	return unicodeBuffer;	// Ownership transfered to caller
       
   399 	}
       
   400 
       
   401 /**
       
   402 	Checks to see if the input argument is excluded.
       
   403 	
       
   404 	@since			6.0
       
   405 	@param			aChar	The character to be checked.
       
   406 	@return			A boolean value of ETrue if the character is an excluded one, or
       
   407 					EFalse if it is not.
       
   408  */
       
   409 EXPORT_C TBool EscapeUtils::IsExcludedChar(TChar aChar)
       
   410 	{
       
   411 	const TDesC& KExcludedChars = KExcludedData;
       
   412 	TBool excluded = KExcludedChars.Locate(aChar) != KErrNotFound || aChar <= 0x1F || aChar == ' ' || aChar > 0x7E;
       
   413 	return excluded;
       
   414 	}
       
   415 
       
   416 /**
       
   417 	Checks for an escape triple at the start of the input descriptor. If there is a triple 
       
   418 	its value is calculated and returned through the output argument aHexValue. If there is 
       
   419 	no escape triple then this argument is left unchanged.
       
   420 						
       
   421 	@since			6.0
       
   422 	@param			aData		The descriptor to be checked for an escape triple.
       
   423 	@param			aHexValue	The output argument with the value of the escape triple 
       
   424 	if it exists.
       
   425 	@return			A boolean value of ETrue if there is an escape triple at the start of 
       
   426 	the input descriptor, EFalse otherwise.
       
   427 */
       
   428 EXPORT_C TBool EscapeUtils::IsEscapeTriple(const TDesC8& aData, TInt& aHexValue)
       
   429 	{
       
   430 	return CheckAndConvertEscapeTriple(aData, aHexValue);
       
   431 	}
       
   432 
       
   433 /**
       
   434 	Checks for an escape triple at the start of the input descriptor. If there is a triple 
       
   435 	its value is calculated and returned through the output argument aHexValue. If there is 
       
   436 	no escape triple then this argument is left unchanged.
       
   437 						
       
   438 	@since			6.0
       
   439 	@param			aData		The descriptor to be checked for an escape triple.
       
   440 	@param			aHexValue	The output argument with the value of the escape triple 
       
   441 	if it exists.
       
   442 	@return			A boolean value of ETrue if there is an escape triple at the start of 
       
   443 	the input descriptor, EFalse otherwise.
       
   444 */
       
   445 EXPORT_C TBool EscapeUtils::IsEscapeTriple(const TDesC16& aData, TInt& aHexValue)
       
   446 	{
       
   447 	return CheckAndConvertEscapeTriple(aData, aHexValue);
       
   448 	}
       
   449 
       
   450 /**
       
   451 	returns the escape encoded descriptor output. This checks the every character of aData 
       
   452 	against aCharsToEscape and if it exist then it escape encodes that character.
       
   453 
       
   454 	@param			aData	The descriptor to be checked against escaping set of characters.
       
   455 	@param			aCharsToEscape	The set of escape characters.
       
   456 	@return			A pointer to the escape encoded descriptor.
       
   457 */
       
   458 EXPORT_C HBufC8* EscapeUtils::SpecificEscapeEncodeL ( const TDesC8& aData, const TDesC8& aCharsToEscape )
       
   459 	{
       
   460 	// Descriptor to hex digits and excluded chars
       
   461 	const TDesC& KHexChars = KHexDigit;
       
   462 
       
   463 	const TInt length = aData.Length();
       
   464 	
       
   465 	// find out how many characters need escape encoding
       
   466 	TInt count = 0;
       
   467 	for( TInt i=0; i<length; ++i )
       
   468 		{
       
   469 		TChar current( aData[i] );
       
   470 		if ( current <= 0x1F || aCharsToEscape.Locate ( current ) != KErrNotFound || current > 0x7E )
       
   471 			{
       
   472 			count++;
       
   473 			}
       
   474 		}
       
   475 	if( count == 0)	// no encoding needed, just allocate and return the whole string
       
   476 		{
       
   477 		return aData.AllocL();
       
   478 		}
       
   479 
       
   480 	// pre-allocate space for the descriptor
       
   481 	HBufC8* buf = HBufC8::NewLC( length + count*2 ); // two extra chars for each escaped
       
   482 	TPtr8 escaped = buf->Des();
       
   483 
       
   484 	for( TInt i=0; i<length; ++i )
       
   485 		{
       
   486 		// Check if current character must be escaped
       
   487 		TChar current ( aData[i] );
       
   488 		// Check if current character is excluded ( control characters and the character specified for escaping )
       
   489 		TBool excluded = current <= 0x1F || ( aCharsToEscape.Locate ( current ) != KErrNotFound ) || current > 0x7E;
       
   490 
       
   491 		if( excluded )
       
   492 			{
       
   493 			// Excluded char - escape encode
       
   494 			escaped.Append(KEscapeIndicator);
       
   495 			const TInt mostSignificantNibble = (current & 0xf0) >> 4;	// Get msNibble by masking against 11110000 and dividing by 16 (>>4)
       
   496 			escaped.Append(KHexChars[mostSignificantNibble]);
       
   497 			const TInt leastSignificantNibble = (current & 0x0f);		// Get lsNibble by masking against 00001111
       
   498 			escaped.Append(KHexChars[leastSignificantNibble]);
       
   499 			}
       
   500 		else
       
   501 			{
       
   502 			// Not an excluded char - just append			  
       
   503 			escaped.Append(current);
       
   504 			}
       
   505 		}
       
   506 	CleanupStack::Pop(buf);
       
   507 	return buf;		
       
   508 	}
       
   509 
       
   510 /** 
       
   511     The Dummy API is used to redirect to SpecificEscapeEncodeL() API in order to preserve BC and is made private                                                                                                       
       
   512 	to ensure no-one else starts using it.
       
   513 */
       
   514 EXPORT_C HBufC8* EscapeUtils::DummyForwardingFunctionForCompatibility( const TDesC8& aData, const TDesC8& aCharsToEscape )
       
   515 	{
       
   516 	return EscapeUtils::SpecificEscapeEncodeL ( aData, aCharsToEscape );
       
   517 	}
       
   518 
       
   519 
       
   520 //
       
   521 //
       
   522 // Implementation of LOCAL functions
       
   523 //
       
   524 //
       
   525 /**
       
   526 	Escape encodes the data, converting the reserved characters and excluded characters defined by 
       
   527 	RFC2396 as escape triples.
       
   528 						
       
   529 	@since			6.0
       
   530 	@warning		This function will panic if the output descriptor aEncodedData is
       
   531 	not big enough to append all the data.
       
   532 	@param			aData			A descriptor with the data to encode.
       
   533 	@param			aReservedChars  Reserved characters set.
       
   534 	@param			aEncodedData	The output descriptor pointer where the escaped encoded 
       
   535 	data is placed.
       
   536 	@return			An error code of KUriUtilsErr16BitChar if the data contains a 16-bit 
       
   537 	character. KErrNone if the data was successfully encoded.
       
   538  */				
       
   539 template<class TDesCType, class TPtrType>
       
   540 TInt EscapeEncodeData(const TDesCType& aData, const TDesCType& aReservedChars, TPtrType& aEncodedData)
       
   541 	{
       
   542 	// Descriptor to hex digits and excluded chars
       
   543 	const TDesC& KHexChars = KHexDigit;
       
   544 
       
   545 	const TInt length = aData.Length();
       
   546 	for( TInt i=0; i<length; ++i )
       
   547 		{
       
   548 		// Check if current character must be escaped, will return error if not 8-bit character
       
   549 		TChar current = aData[i];
       
   550 		if( current > 0xff )
       
   551 			{
       
   552 			__ASSERT_DEBUG(EFalse, User::Panic(KEscapeUtilsPanicCategory, KUriUtilsErr16BitChar));
       
   553 			return (KUriUtilsErr16BitChar);
       
   554 			}
       
   555 		// Check if current character is excluded, a control character or a space
       
   556 		TBool excluded = EscapeUtils::IsExcludedChar(current) || aReservedChars.Locate(current) != KErrNotFound;
       
   557 	  if ( excluded )
       
   558 		   {
       
   559        		// Excluded char - escape encode
       
   560 			aEncodedData.Append(KEscapeIndicator);
       
   561 			const TInt mostSignificantNibble = (current & 0xf0) >> 4;	// Get msNibble by masking against 11110000 and dividing by 16 (>>4)
       
   562 			aEncodedData.Append(KHexChars[mostSignificantNibble]);
       
   563 			const TInt leastSignificantNibble = (current & 0x0f);		// Get lsNibble by masking against 00001111
       
   564 			aEncodedData.Append(KHexChars[leastSignificantNibble]);
       
   565 			}
       
   566 		else
       
   567 			{
       
   568 			// Not an excluded char or It's already Escape encode - just append			  
       
   569 			aEncodedData.Append(current);
       
   570 		    }
       
   571 		}
       
   572 	return KErrNone;
       
   573 	}
       
   574 
       
   575 /**
       
   576 	Escape decodes the data, converting escape triples back to their single character value.
       
   577 	
       
   578 	@since			6.0
       
   579 	@warning		This function will panic if the output descriptor aDecodedData is not big 
       
   580 	enough to append all the data.
       
   581 	@param			aData			A descriptor with the data to decode.
       
   582 	@param			aDecodedData	The output descriptor pointer where the escaped decoded data 
       
   583 	is placed.
       
   584 	@return			An error code of KUriUtilsErr16BitChar if the data contains a 16-bit character. 
       
   585 	KErrNone if the data was successfully encoded.
       
   586  */
       
   587 template<class TDesCType, class TPtrType>
       
   588 TInt EscapeDecodeData(const TDesCType& aData, TPtrType& aDecodedData)
       
   589 	{
       
   590 	// Go through the descriptor
       
   591 	const TInt length = aData.Length();
       
   592 	for( TInt i=0; i<length; ++i )
       
   593 		{
       
   594 		// See if at start of an escape triple
       
   595 		TChar current = aData[i];
       
   596 		if( current == KEscapeIndicator )
       
   597 			{
       
   598 			TInt hex;
       
   599 			if( !CheckAndConvertEscapeTriple(aData.Mid(i), hex) )
       
   600 				{
       
   601 				// Either of the nibbles were not a valid hex character
       
   602 				return KUriUtilsErrBadEscapeTriple;
       
   603 				}
       
   604 			// Append hex value
       
   605 			aDecodedData.Append(hex);
       
   606 
       
   607 			// Move index to get next character - add 2 to index
       
   608 			i += 2;
       
   609 			}
       
   610 		else
       
   611 			{
       
   612 			// Not an escaped triple - just append
       
   613 			aDecodedData.Append(current);
       
   614 			}
       
   615 		}
       
   616 	return KErrNone;
       
   617 	}
       
   618 
       
   619 /**
       
   620 	Checks for an escape triple at the start of the input descriptor. If there is a triple its 
       
   621 	value is calculated and returned through the output argument aHexValue. If there is no escape 
       
   622 	then triple this argument is left unchanged.
       
   623 						
       
   624 	@since			6.0
       
   625 	@param			aData		The descriptor to be checked for an escape triple.
       
   626 	@param			aHexValue	The output argument with the value of the escape triple 
       
   627 	if it exists.
       
   628 	@return			A boolean value of ETrue if there is an escape triple at the start 
       
   629 	of the input descriptor, EFalse otherwise.
       
   630  */
       
   631 template<class TDesCType>
       
   632 TBool CheckAndConvertEscapeTriple(const TDesCType& aData, TInt& aHexValue)
       
   633 	{
       
   634 	// See if the descriptor is actually long enough
       
   635 	if( aData.Length() < KEscapeTripleLength )
       
   636 		{
       
   637 		return EFalse;
       
   638 		}
       
   639 	// Check that the three characters form an escape triple - first char is '%'
       
   640 	if( aData[KEscDelimiterPos] != KEscapeIndicator )
       
   641 		{
       
   642 		return EFalse;
       
   643 		}
       
   644 	// Descriptor to hex digits and excluded chars
       
   645 	const TDesC& KHexChars = KHexDigit;
       
   646 
       
   647 	// Check that next two characters are valid
       
   648 	TChar mostSignificantNibble = aData[KMostSignificantNibblePos];
       
   649 	TChar leastSignificantNibble = aData[KLeastSignificantNibblePos];
       
   650 
       
   651 	TInt mostSignificantNibbleValue = KHexChars.LocateF(mostSignificantNibble);
       
   652 	TInt leastSignificantNibbleValue = KHexChars.LocateF(leastSignificantNibble);
       
   653 
       
   654 	if( mostSignificantNibbleValue == KErrNotFound || leastSignificantNibbleValue == KErrNotFound )
       
   655 		{
       
   656 		// Either of the nibbles were not a valid hex character
       
   657 		return EFalse;
       
   658 		}
       
   659 	// Convert characters into hex value and return
       
   660 	aHexValue = 0x10*mostSignificantNibbleValue + 0x01*leastSignificantNibbleValue;
       
   661 	return ETrue;
       
   662 	}