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