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