|
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 } |