1 /*-
2 * Copyright (c) 2004 - 2011 CTPP Team
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 4. Neither the name of the CTPP Team nor the names of its contributors
13 * may be used to endorse or promote products derived from this software
14 * without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 *
28 * CTPP2Util.cpp
29 *
30 * $CTPP$
31 */
32 #include "CTPP2Util.hpp"
33 #include "CTPP2Exception.hpp"
34
35 #include "CDT.hpp"
36
37 #include <stdio.h>
38
39 namespace CTPP // C++ Template Engine
40 {
41
42 static const UINT_32 aCRC32[] =
43 {
44 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
45 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
46 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
47 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
48 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
49 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
50 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
51 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
52 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
53 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
54 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
55 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
56 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
57 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
58 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
59 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
60 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
61 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
62 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
63 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
64 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
65 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
66 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
67 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
68 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
69 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
70 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
71 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
72 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
73 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
74 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
75 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
76
77 };
78
79 //
80 // Calculate crc32 checksum
81 //
crc32(UCCHAR_P sBuffer,const UINT_32 & iSize)82 UINT_32 crc32(UCCHAR_P sBuffer, const UINT_32 & iSize)
83 {
84 UINT_32 iCRC = 0;
85
86 for (UINT_32 iI = 0; iI < iSize; ++iI)
87 {
88 iCRC = aCRC32[(iCRC ^ sBuffer[iI]) & 0xFF] ^ (iCRC >> 8);
89 }
90
91 return iCRC;
92 }
93
94 //
95 // Swap bytes for UINT_32 value
96 //
Swap32(const UINT_32 & iValue)97 UINT_32 Swap32(const UINT_32 & iValue)
98 {
99 return ((iValue << 24) & 0xff000000 ) |
100 ((iValue << 8) & 0x00ff0000 ) |
101 ((iValue >> 8) & 0x0000ff00 ) |
102 ((iValue >> 24) & 0x000000ff );
103 }
104
105 //
106 // Swap bytes for UINT_64 value
107 //
Swap64(const UINT_64 & iValue)108 UINT_64 Swap64(const UINT_64 & iValue)
109 {
110 union
111 {
112 UINT_64 ul;
113 UINT_32 ui[2];
114 } u;
115
116 UINT_32 * pTMP = (UINT_32*)&iValue;
117
118 u.ui[0] = Swap32(pTMP[1]);
119 u.ui[1] = Swap32(pTMP[0]);
120
121 return u.ul;
122 }
123
124 //
125 // Escape value
126 //
URLEscape(const STLW::string & sData)127 STLW::string URLEscape(const STLW::string & sData)
128 {
129 static const CHAR_8 * szEscape = "0123456789ABCDEF";
130
131 CHAR_8 sBuffer[CTPP_ESCAPE_BUFFER_LEN + 1];
132
133 STLW::string sRetVal = "";
134
135 UINT_32 iBufferPointer = 0;
136
137 // Get string to escape
138 STLW::string::const_iterator itsData = sData.begin();
139 while (itsData != sData.end())
140 {
141 UCHAR_8 chTMP = (UCHAR_8)(*itsData);
142
143 if ((chTMP >= 'a' && chTMP <= 'z') ||
144 (chTMP >= 'A' && chTMP <= 'Z') ||
145 (chTMP >= '0' && chTMP <= '9') ||
146 chTMP == '/' || chTMP == '.' || chTMP == '-' || chTMP == '_')
147 {
148 sBuffer[iBufferPointer++] = *itsData;
149 }
150 else if (chTMP == ' ') { sBuffer[iBufferPointer++] = '+'; }
151 else
152 {
153 if (iBufferPointer >= (CTPP_ESCAPE_BUFFER_LEN - 3))
154 {
155 sRetVal.append(sBuffer, iBufferPointer);
156 iBufferPointer = 0;
157 }
158 sBuffer[iBufferPointer++] = '%';
159 sBuffer[iBufferPointer++] = szEscape[((chTMP >> 4) & 0x0F)];
160 sBuffer[iBufferPointer++] = szEscape[(chTMP & 0x0F)];
161 }
162
163 if (iBufferPointer == CTPP_ESCAPE_BUFFER_LEN)
164 {
165 sRetVal.append(sBuffer, iBufferPointer);
166 iBufferPointer = 0;
167 }
168 ++itsData;
169 }
170
171 if (iBufferPointer != 0) { sRetVal.append(sBuffer, iBufferPointer); }
172
173 return sRetVal;
174 }
175
176 //
177 // Escape value
178 //
URIEscape(const STLW::string & sData)179 STLW::string URIEscape(const STLW::string & sData)
180 {
181 static const CHAR_8 * szEscape = "0123456789ABCDEF";
182
183 CHAR_8 sBuffer[CTPP_ESCAPE_BUFFER_LEN + 1];
184
185 STLW::string sRetVal = "";
186
187 UINT_32 iBufferPointer = 0;
188
189 // Get string to escape
190 STLW::string::const_iterator itsData = sData.begin();
191 while (itsData != sData.end())
192 {
193 UCHAR_8 chTMP = (UCHAR_8)(*itsData);
194
195 if ((chTMP >= 'a' && chTMP <= 'z') ||
196 (chTMP >= 'A' && chTMP <= 'Z') ||
197 (chTMP >= '0' && chTMP <= '9') ||
198 chTMP == '/' || chTMP == '.' || chTMP == '-' || chTMP == '_')
199 {
200 sBuffer[iBufferPointer++] = *itsData;
201 }
202 else
203 {
204 if (iBufferPointer >= (CTPP_ESCAPE_BUFFER_LEN - 3))
205 {
206 sRetVal.append(sBuffer, iBufferPointer);
207 iBufferPointer = 0;
208 }
209 sBuffer[iBufferPointer++] = '%';
210 sBuffer[iBufferPointer++] = szEscape[((chTMP >> 4) & 0x0F)];
211 sBuffer[iBufferPointer++] = szEscape[(chTMP & 0x0F)];
212 }
213
214 if (iBufferPointer == CTPP_ESCAPE_BUFFER_LEN)
215 {
216 sRetVal.append(sBuffer, iBufferPointer);
217 iBufferPointer = 0;
218 }
219 ++itsData;
220 }
221
222 if (iBufferPointer != 0) { sRetVal.append(sBuffer, iBufferPointer); }
223
224 return sRetVal;
225 }
226
227 //
228 // Escape value
229 //
HTMLEscape(const STLW::string & sData)230 STLW::string HTMLEscape(const STLW::string & sData)
231 {
232 CHAR_8 sBuffer[CTPP_ESCAPE_BUFFER_LEN + 1];
233
234 STLW::string sRetVal = "";
235
236 UINT_32 iBufferPointer = 0;
237
238 // Get string to escape
239 STLW::string::const_iterator itsData = sData.begin();
240 while (itsData != sData.end())
241 {
242 UCHAR_8 chTMP = (UCHAR_8)(*itsData);
243
244 if (chTMP == '"')
245 {
246 if (iBufferPointer >= (CTPP_ESCAPE_BUFFER_LEN - 6))
247 {
248 sRetVal.append(sBuffer, iBufferPointer);
249 iBufferPointer = 0;
250 }
251
252 sBuffer[iBufferPointer++] = '&';
253 sBuffer[iBufferPointer++] = 'q';
254 sBuffer[iBufferPointer++] = 'u';
255 sBuffer[iBufferPointer++] = 'o';
256 sBuffer[iBufferPointer++] = 't';
257 sBuffer[iBufferPointer++] = ';';
258 }
259 else if (chTMP == '\'')
260 {
261 if (iBufferPointer >= (CTPP_ESCAPE_BUFFER_LEN - 5))
262 {
263 sRetVal.append(sBuffer, iBufferPointer);
264 iBufferPointer = 0;
265 }
266
267 sBuffer[iBufferPointer++] = '&';
268 sBuffer[iBufferPointer++] = '#';
269 sBuffer[iBufferPointer++] = '3';
270 sBuffer[iBufferPointer++] = '9';
271 sBuffer[iBufferPointer++] = ';';
272 }
273 else if (chTMP == '<')
274 {
275 if (iBufferPointer >= (CTPP_ESCAPE_BUFFER_LEN - 4))
276 {
277 sRetVal.append(sBuffer, iBufferPointer);
278 iBufferPointer = 0;
279 }
280
281 sBuffer[iBufferPointer++] = '&';
282 sBuffer[iBufferPointer++] = 'l';
283 sBuffer[iBufferPointer++] = 't';
284 sBuffer[iBufferPointer++] = ';';
285 }
286 else if (chTMP == '>')
287 {
288 if (iBufferPointer >= CTPP_ESCAPE_BUFFER_LEN - 4)
289 {
290 sRetVal.append(sBuffer, iBufferPointer);
291 iBufferPointer = 0;
292 }
293
294 sBuffer[iBufferPointer++] = '&';
295 sBuffer[iBufferPointer++] = 'g';
296 sBuffer[iBufferPointer++] = 't';
297 sBuffer[iBufferPointer++] = ';';
298 }
299 else if (chTMP == '&')
300 {
301 if (iBufferPointer >= (CTPP_ESCAPE_BUFFER_LEN - 5))
302 {
303 sRetVal.append(sBuffer, iBufferPointer);
304 iBufferPointer = 0;
305 }
306
307 sBuffer[iBufferPointer++] = '&';
308 sBuffer[iBufferPointer++] = 'a';
309 sBuffer[iBufferPointer++] = 'm';
310 sBuffer[iBufferPointer++] = 'p';
311 sBuffer[iBufferPointer++] = ';';
312 }
313 else
314 {
315 sBuffer[iBufferPointer++] = *itsData;
316 }
317
318 if (iBufferPointer == CTPP_ESCAPE_BUFFER_LEN)
319 {
320 sRetVal.append(sBuffer, iBufferPointer);
321 iBufferPointer = 0;
322 }
323 ++itsData;
324 }
325
326 if (iBufferPointer != 0) { sRetVal.append(sBuffer, iBufferPointer); }
327
328 return sRetVal;
329 }
330
331 //
332 // Escape value
333 //
XMLEscape(const STLW::string & sData)334 STLW::string XMLEscape(const STLW::string & sData)
335 {
336 CHAR_8 sBuffer[CTPP_ESCAPE_BUFFER_LEN + 1];
337
338 STLW::string sRetVal = "";
339
340 UINT_32 iBufferPointer = 0;
341
342 // Get string to escape
343 STLW::string::const_iterator itsData = sData.begin();
344 while (itsData != sData.end())
345 {
346 UCHAR_8 chTMP = (UCHAR_8)(*itsData);
347
348 if (chTMP == '"')
349 {
350 if (iBufferPointer >= (CTPP_ESCAPE_BUFFER_LEN - 6))
351 {
352 sRetVal.append(sBuffer, iBufferPointer);
353 iBufferPointer = 0;
354 }
355
356 sBuffer[iBufferPointer++] = '&';
357 sBuffer[iBufferPointer++] = 'q';
358 sBuffer[iBufferPointer++] = 'u';
359 sBuffer[iBufferPointer++] = 'o';
360 sBuffer[iBufferPointer++] = 't';
361 sBuffer[iBufferPointer++] = ';';
362 }
363 else if (chTMP == '\'')
364 {
365 if (iBufferPointer >= (CTPP_ESCAPE_BUFFER_LEN - 6))
366 {
367 sRetVal.append(sBuffer, iBufferPointer);
368 iBufferPointer = 0;
369 }
370
371 sBuffer[iBufferPointer++] = '&';
372 sBuffer[iBufferPointer++] = 'a';
373 sBuffer[iBufferPointer++] = 'p';
374 sBuffer[iBufferPointer++] = 'o';
375 sBuffer[iBufferPointer++] = 's';
376 sBuffer[iBufferPointer++] = ';';
377 }
378 else if (chTMP == '<')
379 {
380 if (iBufferPointer >= (CTPP_ESCAPE_BUFFER_LEN - 4))
381 {
382 sRetVal.append(sBuffer, iBufferPointer);
383 iBufferPointer = 0;
384 }
385
386 sBuffer[iBufferPointer++] = '&';
387 sBuffer[iBufferPointer++] = 'l';
388 sBuffer[iBufferPointer++] = 't';
389 sBuffer[iBufferPointer++] = ';';
390 }
391 else if (chTMP == '>')
392 {
393 if (iBufferPointer >= CTPP_ESCAPE_BUFFER_LEN - 4)
394 {
395 sRetVal.append(sBuffer, iBufferPointer);
396 iBufferPointer = 0;
397 }
398
399 sBuffer[iBufferPointer++] = '&';
400 sBuffer[iBufferPointer++] = 'g';
401 sBuffer[iBufferPointer++] = 't';
402 sBuffer[iBufferPointer++] = ';';
403 }
404 else if (chTMP == '&')
405 {
406 if (iBufferPointer >= (CTPP_ESCAPE_BUFFER_LEN - 5))
407 {
408 sRetVal.append(sBuffer, iBufferPointer);
409 iBufferPointer = 0;
410 }
411
412 sBuffer[iBufferPointer++] = '&';
413 sBuffer[iBufferPointer++] = 'a';
414 sBuffer[iBufferPointer++] = 'm';
415 sBuffer[iBufferPointer++] = 'p';
416 sBuffer[iBufferPointer++] = ';';
417 }
418 else
419 {
420 sBuffer[iBufferPointer++] = *itsData;
421 }
422
423 if (iBufferPointer == CTPP_ESCAPE_BUFFER_LEN)
424 {
425 sRetVal.append(sBuffer, iBufferPointer);
426 iBufferPointer = 0;
427 }
428 ++itsData;
429 }
430
431 if (iBufferPointer != 0) { sRetVal.append(sBuffer, iBufferPointer); }
432
433 return sRetVal;
434 }
435
436 //
437 // Escape value
438 //
WMLEscape(const STLW::string & sData)439 STLW::string WMLEscape(const STLW::string & sData)
440 {
441 CHAR_8 sBuffer[CTPP_ESCAPE_BUFFER_LEN + 1];
442
443 STLW::string sRetVal = "";
444
445 UINT_32 iBufferPointer = 0;
446
447 // Get string to escape
448 STLW::string::const_iterator itsData = sData.begin();
449 while (itsData != sData.end())
450 {
451 UCHAR_8 chTMP = (UCHAR_8)(*itsData);
452
453 if (chTMP < ' ')
454 {
455 if (iBufferPointer >= (CTPP_ESCAPE_BUFFER_LEN - 6))
456 {
457 sRetVal.append(sBuffer, iBufferPointer);
458 iBufferPointer = 0;
459 }
460 snprintf(sBuffer + iBufferPointer, 6, "\\u%04d", chTMP);
461 }
462 else if (chTMP == '"')
463 {
464 if (iBufferPointer >= (CTPP_ESCAPE_BUFFER_LEN - 6))
465 {
466 sRetVal.append(sBuffer, iBufferPointer);
467 iBufferPointer = 0;
468 }
469
470 sBuffer[iBufferPointer++] = '&';
471 sBuffer[iBufferPointer++] = 'q';
472 sBuffer[iBufferPointer++] = 'u';
473 sBuffer[iBufferPointer++] = 'o';
474 sBuffer[iBufferPointer++] = 't';
475 sBuffer[iBufferPointer++] = ';';
476 }
477 else if (chTMP == '\'')
478 {
479 if (iBufferPointer >= (CTPP_ESCAPE_BUFFER_LEN - 6))
480 {
481 sRetVal.append(sBuffer, iBufferPointer);
482 iBufferPointer = 0;
483 }
484
485 sBuffer[iBufferPointer++] = '&';
486 sBuffer[iBufferPointer++] = 'a';
487 sBuffer[iBufferPointer++] = 'p';
488 sBuffer[iBufferPointer++] = 'o';
489 sBuffer[iBufferPointer++] = 's';
490 sBuffer[iBufferPointer++] = ';';
491 }
492 else if (chTMP == '<')
493 {
494 if (iBufferPointer >= (CTPP_ESCAPE_BUFFER_LEN - 4))
495 {
496 sRetVal.append(sBuffer, iBufferPointer);
497 iBufferPointer = 0;
498 }
499
500 sBuffer[iBufferPointer++] = '&';
501 sBuffer[iBufferPointer++] = 'l';
502 sBuffer[iBufferPointer++] = 't';
503 sBuffer[iBufferPointer++] = ';';
504 }
505 else if (chTMP == '>')
506 {
507 if (iBufferPointer >= CTPP_ESCAPE_BUFFER_LEN - 4)
508 {
509 sRetVal.append(sBuffer, iBufferPointer);
510 iBufferPointer = 0;
511 }
512
513 sBuffer[iBufferPointer++] = '&';
514 sBuffer[iBufferPointer++] = 'g';
515 sBuffer[iBufferPointer++] = 't';
516 sBuffer[iBufferPointer++] = ';';
517 }
518 else if (chTMP == '&')
519 {
520 if (iBufferPointer >= (CTPP_ESCAPE_BUFFER_LEN - 5))
521 {
522 sRetVal.append(sBuffer, iBufferPointer);
523 iBufferPointer = 0;
524 }
525
526 sBuffer[iBufferPointer++] = '&';
527 sBuffer[iBufferPointer++] = 'a';
528 sBuffer[iBufferPointer++] = 'm';
529 sBuffer[iBufferPointer++] = 'p';
530 sBuffer[iBufferPointer++] = ';';
531 }
532 else if (chTMP == '$')
533 {
534 if (iBufferPointer >= (CTPP_ESCAPE_BUFFER_LEN - 4))
535 {
536 sRetVal.append(sBuffer, iBufferPointer);
537 iBufferPointer = 0;
538 }
539
540 sBuffer[iBufferPointer++] = '$';
541 sBuffer[iBufferPointer++] = '$';
542 }
543 else
544 {
545 sBuffer[iBufferPointer++] = *itsData;
546 }
547
548 if (iBufferPointer == CTPP_ESCAPE_BUFFER_LEN)
549 {
550 sRetVal.append(sBuffer, iBufferPointer);
551 iBufferPointer = 0;
552 }
553 ++itsData;
554 }
555
556 if (iBufferPointer != 0) { sRetVal.append(sBuffer, iBufferPointer); }
557
558 return sRetVal;
559 }
560
561
562 //
563 // Escape string, if need
564 //
EscapeJSONString(const STLW::string & sSource,const bool & bECMAConventions,const bool & bHTMLSafe)565 STLW::string EscapeJSONString(const STLW::string & sSource, const bool & bECMAConventions, const bool & bHTMLSafe)
566 {
567 DumpBuffer oBuff;
568 DumpJSONString(oBuff, sSource, bECMAConventions, bHTMLSafe);
569 return STLW::string(oBuff.Data(), oBuff.Size());
570 }
571
572
573 //
574 // Escape and dump string to buffer
575 //
DumpJSONString(DumpBuffer & sResult,const STLW::string & sSource,const bool & bECMAConventions,const bool & bHTMLSafe)576 DumpBuffer & DumpJSONString(DumpBuffer & sResult, const STLW::string & sSource, const bool & bECMAConventions, const bool & bHTMLSafe)
577 {
578 INT_32 iPos = 0;
579 INT_32 iSize = sSource.size();
580 INT_32 iOffset = 0;
581
582 while (iSize--)
583 {
584 const UCHAR_8 uCH = sSource[iPos];
585 const CHAR_8 * sEscaped = NULL;
586 bool bFound = false;
587
588 switch (uCH)
589 {
590 case '"':
591 sEscaped = "\\\"";
592 bFound = true;
593 break;
594 case '\\':
595 sEscaped = "\\\\";
596 bFound = true;
597 break;
598 case '/':
599 sEscaped = "\\/";
600 bFound = true;
601 break;
602 case '\b':
603 sEscaped = "\\b";
604 bFound = true;
605 break;
606 case '\f':
607 sEscaped = "\\f";
608 bFound = true;
609 break;
610 case '\n':
611 sEscaped = "\\n";
612 bFound = true;
613 break;
614 case '\r':
615 sEscaped = "\\r";
616 bFound = true;
617 break;
618 case '\t':
619 sEscaped = "\\t";
620 bFound = true;
621 break;
622 case '\'':
623 sEscaped = "\\'";
624 if (bECMAConventions) { bFound = true; }
625 break;
626 case '\v':
627 sEscaped = "\\v";
628 if (bECMAConventions) { bFound = true; }
629 break;
630 case '\0':
631 sEscaped = "\\0";
632 if (bECMAConventions) { bFound = true; }
633 break;
634 default:
635 break;
636 }
637
638 if (bFound)
639 {
640 if (iPos - iOffset > 0) { sResult.Write(sSource.c_str() + iOffset, iPos - iOffset); }
641 sResult.Write(sEscaped, strlen(sEscaped));
642 iOffset = iPos + 1;
643 }
644 else if (uCH < ' ' || (bHTMLSafe && (uCH == '<' || uCH == '>')))
645 {
646 if (iPos - iOffset > 0) { sResult.Write(sSource.c_str() + iOffset, iPos - iOffset); }
647 CHAR_8 szBuffer[7] = { '\0' };
648 const CHAR_8 *szHexChars = "0123456789abcdef";
649 snprintf(szBuffer, 7, "\\u00%c%c", szHexChars[uCH >> 4], szHexChars[uCH & 0xF]);
650 sResult.Write(szBuffer, 6);
651 iOffset = iPos + 1;
652 }
653 ++iPos;
654 }
655
656 if (iPos - iOffset > 0) { sResult.Write(sSource.c_str() + iOffset, iPos - iOffset); }
657
658 return sResult;
659 }
660
661 //
662 // Dump CDT to JSON
663 //
CDT2JSON(const CTPP::CDT & oCDT,STLW::string & sData)664 void CDT2JSON(const CTPP::CDT & oCDT, STLW::string & sData)
665 {
666 DumpBuffer oBuff;
667 DumpCDT2JSON(oCDT, oBuff);
668 sData.append(oBuff.Data(), oBuff.Size());
669 }
670
~DumpBuffer()671 DumpBuffer::~DumpBuffer()
672 {
673 free(pBuffer);
674 }
675
DumpBuffer()676 DumpBuffer::DumpBuffer()
677 {
678 pBuffer = 0;
679 iCapacity = 0;
680 pPos = 0;
681 }
682
Data() const683 CCHAR_P DumpBuffer::Data() const { return pBuffer; }
684
Size() const685 DumpBuffer::StreamSize DumpBuffer::Size() const { return pPos - pBuffer; }
686
Reserve(DumpBuffer::StreamSize iN)687 void DumpBuffer::Reserve(DumpBuffer::StreamSize iN)
688 {
689 if (iN <= iCapacity) { return; }
690
691 StreamSize iOffset = pPos - pBuffer;
692 CHAR_P pTmp = (CHAR_P) realloc(pBuffer, iN);
693 if(!pTmp) { throw CTPPNoMemoryError(); }
694 pBuffer = pTmp;
695
696 pPos = pBuffer + iOffset;
697 iCapacity = iN;
698 }
699
Write(CCHAR_P pStr,DumpBuffer::StreamSize iN)700 void DumpBuffer::Write(CCHAR_P pStr, DumpBuffer::StreamSize iN) {
701 if(pPos + iN > pBuffer + iCapacity) {
702 Reserve(2 * (iCapacity + iN));
703 }
704 memcpy(pPos, pStr, iN);
705 pPos += iN;
706 }
707
708 //
709 // Escape and dump string to buffer
710 //
DumpCDT2JSON(const CTPP::CDT & oCDT,DumpBuffer & oResult)711 DumpBuffer & DumpCDT2JSON(const CTPP::CDT & oCDT, DumpBuffer & oResult)
712 {
713 using namespace CTPP;
714 switch (oCDT.GetType())
715 {
716 case CDT::UNDEF:
717 oResult.Write("null", 4);
718 break;
719
720 case CDT::INT_VAL:
721 case CDT::REAL_VAL:
722 case CDT::POINTER_VAL:
723 case CDT::STRING_INT_VAL:
724 case CDT::STRING_REAL_VAL:
725 {
726 STLW::string tmp = oCDT.GetString();
727 oResult.Write(tmp.data(), tmp.size());
728 }
729 break;
730
731 case CDT::STRING_VAL:
732 oResult.Write("\"", 1);
733 DumpJSONString(oResult, oCDT.GetString(), false);
734 oResult.Write("\"", 1);
735 break;
736
737 case CDT::ARRAY_VAL:
738 {
739 oResult.Write("[", 1);
740 UINT_32 iJ = 0;
741 while (iJ < oCDT.Size())
742 {
743 DumpCDT2JSON(oCDT.GetCDT(iJ), oResult);
744 ++iJ;
745 if (iJ != oCDT.Size()) { oResult.Write(",", 1); }
746 }
747 oResult.Write("]", 1);
748 }
749 break;
750
751 case CDT::HASH_VAL:
752 {
753 oResult.Write("{", 1);
754 CDTConstIterator itCDTCArray = oCDT.Begin();
755 while (itCDTCArray != oCDT.End())
756 {
757 oResult.Write("\"", 1);
758 DumpJSONString(oResult, itCDTCArray -> first, false);
759 oResult.Write("\":", 2);
760
761 DumpCDT2JSON(itCDTCArray -> second, oResult);
762
763 ++itCDTCArray;
764 if (itCDTCArray != oCDT.End()) { oResult.Write(",", 1); }
765 }
766 oResult.Write("}", 1);
767 }
768 break;
769 }
770
771 return oResult;
772 }
773
774 //
775 // Encode value
776 //
Base64Encode(const STLW::string & sData)777 STLW::string Base64Encode(const STLW::string & sData)
778 {
779 // RFC 3548 - The Base16, Base32, and Base64 Data Encodings
780 static CHAR_8 aBase64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
781
782 UINT_32 aDst[4];
783
784 // Data
785 UCCHAR_P szData = (UCCHAR_P)sData.c_str();
786 // Data length
787 const UINT_32 iDataLength = sData.size();
788 const UINT_32 iDataLengthFixed = 3 * (iDataLength / 3);
789
790 // Temp buffer
791 CHAR_P szBuffer = new CHAR_8[iDataLength * 4 / 3 + 4];
792 CHAR_P szDst = szBuffer;
793
794 UINT_32 iDstLength = 0;
795 UINT_32 iI = 0;
796 for (; iI < iDataLengthFixed;)
797 {
798 iI += 3;
799
800 aDst[0] = szData[0] >> 2;
801 aDst[1] = ((szData[0] & 0x03) << 4) + (szData[1] >> 4);
802 aDst[2] = ((szData[1] & 0x0f) << 2) + (szData[2] >> 6);
803 aDst[3] = szData[2] & 0x3f;
804
805 *szDst++ = aBase64[ aDst[0] ];
806 *szDst++ = aBase64[ aDst[1] ];
807 *szDst++ = aBase64[ aDst[2] ];
808 *szDst++ = aBase64[ aDst[3] ];
809
810 szData += 3;
811 iDstLength += 4;
812 }
813
814 const UINT_32 iDelta = iDataLength - iDataLengthFixed;
815 if (iDelta != 0)
816 {
817 UINT_32 aSrc[3];
818 aSrc[0] = aSrc[1] = aSrc[2] = 0;
819
820 for(iI = 0; iI < iDelta; ++iI) { aSrc[iI] = *szData++; }
821
822 aDst[0] = aSrc[0] >> 2;
823 aDst[1] = ((aSrc[0] & 0x03) << 4) + (aSrc[1] >> 4);
824 aDst[2] = ((aSrc[1] & 0x0f) << 2) + (aSrc[2] >> 6);
825
826 *szDst++ = aBase64[ aDst[0] ];
827 *szDst++ = aBase64[ aDst[1] ];
828
829 if (iDelta == 1) { *szDst++ = '='; }
830 else { *szDst++ = aBase64[ aDst[2] ]; }
831 *szDst++ = '=';
832
833 iDstLength += 4;
834 }
835
836 // Okay
837 STLW::string sRetVal(szBuffer, iDstLength);
838
839 delete [] szBuffer;
840
841 return sRetVal;
842 }
843
844 static UCHAR_8 aBase64Rev[256] =
845 {
846 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
847 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
848 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63,
849 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64,
850 64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
851 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64,
852 64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
853 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64,
854 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
855 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
856 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
857 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
858 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
859 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
860 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
861 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64
862 };
863
864 //
865 // Decode value
866 //
Base64Decode(const STLW::string & sData)867 STLW::string Base64Decode(const STLW::string & sData)
868 {
869 // Data
870 UCCHAR_P szData = (UCCHAR_P)sData.c_str();
871 // Data length
872 UINT_32 iDataLength = sData.size();
873
874 // Temp buffer
875 UCHAR_P szBuffer = new UCHAR_8[ ( (iDataLength + 3) / 4) * 3];
876 UCHAR_P szDst = szBuffer;
877
878 UINT_32 iDstLength = 0;
879 while (iDataLength > 4)
880 {
881 *szDst++ = (aBase64Rev[ szData[0] ] << 2 | aBase64Rev[ szData[1] ] >> 4);
882 *szDst++ = (aBase64Rev[ szData[1] ] << 4 | aBase64Rev[ szData[2] ] >> 2);
883 *szDst++ = (aBase64Rev[ szData[2] ] << 6 | aBase64Rev[ szData[3] ]);
884 szData += 4;
885 iDataLength -= 4;
886 iDstLength += 3;
887 }
888
889 *szDst++ = (aBase64Rev[ szData[0] ] << 2 | aBase64Rev[ szData[1] ] >> 4);
890 ++iDstLength;
891
892 if (szData[2] != '=') { *szDst++ = (aBase64Rev[ szData[1] ] << 4 | aBase64Rev[ szData[2] ] >> 2); ++iDstLength; }
893
894 if (szData[3] != '=') { *szDst++ = (aBase64Rev[ szData[2] ] << 6 | aBase64Rev[ szData[3] ]); ++iDstLength; }
895
896 // Okay
897 STLW::string sRetVal((CHAR_P)szBuffer, iDstLength);
898
899 delete [] szBuffer;
900
901 return sRetVal;
902 }
903
904 //
905 // Length of UTF character
906 //
utf_charlen(CCHAR_P szString,CCHAR_P szStringEnd)907 INT_32 utf_charlen(CCHAR_P szString, CCHAR_P szStringEnd)
908 {
909 /*
910 * 0x00000000 � 0x0000007F 0x xxx xxx
911 * 0x00000080 � 0x000007FF 110xxxxx 10xxxxxx
912 * 0x00000800 � 0x0000FFFF 1110xxxx 10xxxxxx 10xxxxxx
913 * 0x00010000 � 0x001FFFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
914 */
915
916 // End of string
917 if (szString == szStringEnd) { return -3; }
918
919 // UTF8-1 0xxxxxxx
920 if ((UCCHAR_8(*szString) & 0x80) == 0) { return 1; }
921
922 // UTF8-2 110xxxxx 10xxxxxx
923 if ((UCCHAR_8(*szString) & 0xE0) == 0xC0)
924 {
925 // Check next byte
926 ++szString;
927 if (szString == szStringEnd) { return -3; }
928 if ((UCCHAR_8(*szString) & 0xC0) != 0x80) { return -1; }
929
930 // Ok
931 return 2;
932 }
933
934 // UTF8-3 1110xxxx 10xxxxxx 10xxxxxx
935 if ((UCCHAR_8(*szString) & 0xF0) == 0xE0)
936 {
937 // Check next byte
938 ++szString;
939 if (szString == szStringEnd) { return -3; }
940 if ((UCCHAR_8(*szString) & 0xC0) != 0x80) { return -1; }
941
942 ++szString;
943 if (szString == szStringEnd) { return -3; }
944 if ((UCCHAR_8(*szString) & 0xC0) != 0x80) { return -1; }
945
946 // Ok
947 return 3;
948 }
949
950 // UTF8-4 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
951 if ((UCCHAR_8(*szString) & 0xF8) == 0xF0)
952 {
953 // Check next byte
954 ++szString;
955 if (szString == szStringEnd) { return -3; }
956 if ((UCCHAR_8(*szString) & 0xC0) != 0x80) { return -1; }
957
958 ++szString;
959 if (szString == szStringEnd) { return -3; }
960 if ((UCCHAR_8(*szString) & 0xC0) != 0x80) { return -1; }
961
962 ++szString;
963 if (szString == szStringEnd) { return -3; }
964 if ((UCCHAR_8(*szString) & 0xC0) != 0x80) { return -1; }
965
966 // Ok
967 return 4;
968 }
969
970 // This is not an UTF8 character
971 return -2;
972 }
973
974 /*
975 * Convert Unicode character to UTF8
976 */
UnicodeToUTF8(UINT_32 iUCS,UCHAR_P sUTF8)977 INT_32 UnicodeToUTF8(UINT_32 iUCS, UCHAR_P sUTF8)
978 {
979 INT_32 iPos = 0;
980 INT_32 iCharLength = 0;
981 UCHAR_8 sUTF8Prefix = 0;
982
983 /* ASCII characters. */
984 if ((iUCS & ~0x0000007F) == 0)
985 {
986 /* Modified UTF-8, special case */
987 if (iUCS == 0)
988 {
989 sUTF8[0] = 0xC0;
990 sUTF8[1] = 0x80;
991 return 2;
992 }
993
994 sUTF8[0] = (char)iUCS;
995 return 1;
996 }
997 /*
998 * Does not need here, but let it be
999 if ((iUCS & ~0x0000007F) == 0)
1000 {
1001 sUTF8Prefix = 0x00; // 11000000b
1002 iCharLength = 1;
1003 } else
1004 */
1005
1006 if ((iUCS & ~0x000007FF) == 0)
1007 {
1008 sUTF8Prefix = 0xC0; // 11000000b
1009 iCharLength = 2;
1010 }
1011 else if ((iUCS & ~0x0000FFFF) == 0)
1012 {
1013 sUTF8Prefix = 0xE0; // 11100000b
1014 iCharLength = 3;
1015 }
1016 else if ((iUCS & ~0x001FFFFF) == 0)
1017 {
1018 sUTF8Prefix = 0xF0; // 11110000b
1019 iCharLength = 4;
1020 }
1021 else if ((iUCS & ~0x03FFFFFF) == 0)
1022 {
1023 sUTF8Prefix = 0xF8; // 11111000b
1024 iCharLength = 5;
1025 }
1026 else if ((iUCS & ~0x7FFFFFFF) == 0)
1027 {
1028 sUTF8Prefix = 0xFC; // 11111100b
1029 iCharLength = 6;
1030 }
1031 /* Incorrect multibyte character */
1032 else { return -1; }
1033
1034 /*
1035 * Convert UCS character to UTF8. Split value in 6-bit chunks and
1036 * move to UTF8 string
1037 */
1038 for (iPos = iCharLength - 1; iPos > 0; --iPos)
1039 {
1040 sUTF8[iPos] = (iUCS & 0x0000003F) | 0x80;
1041 iUCS >>= 6;
1042 }
1043
1044 /* UTF8 prefix, special case */
1045 sUTF8[0] = (iUCS & 0x000000FF) | sUTF8Prefix;
1046
1047 /* Return size of UTF8 character */
1048 return iCharLength;
1049 }
1050
1051 } // namespace CTPP
1052 // End.
1053