1 kumpf 1.1 //%2006////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
4 // Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
5 // Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;
6 // IBM Corp.; EMC Corporation, The Open Group.
7 // Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
8 // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
9 // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
10 // EMC Corporation; VERITAS Software Corporation; The Open Group.
11 // Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
12 // EMC Corporation; Symantec Corporation; The Open Group.
13 //
14 // Permission is hereby granted, free of charge, to any person obtaining a copy
15 // of this software and associated documentation files (the "Software"), to
16 // deal in the Software without restriction, including without limitation the
17 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
18 // sell copies of the Software, and to permit persons to whom the Software is
19 // furnished to do so, subject to the following conditions:
20 //
21 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
22 kumpf 1.1 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
23 // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
24 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
25 // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
26 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
27 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 //
30 //==============================================================================
31 //
32 //%/////////////////////////////////////////////////////////////////////////////
33
34 #include <cstdlib>
35 #include <cstdio>
36
37 #include <Pegasus/Common/Config.h>
38 #include "XmlGenerator.h"
39 #include "Constants.h"
40 #include "StrLit.h"
41 #include "CommonUTF.h"
42 #include "StringConversion.h"
43 kumpf 1.1 #include "LanguageParser.h"
44 #include "AutoPtr.h"
45
46 PEGASUS_NAMESPACE_BEGIN
47
48 ////////////////////////////////////////////////////////////////////////////////
49 //
50 // SpecialChar and table.
51 //
52 ////////////////////////////////////////////////////////////////////////////////
53
54 // Note: we cannot use StrLit here since it has a constructor (forbids
55 // structure initialization).
56
57 struct SpecialChar
58 {
59 const char* str;
60 Uint32 size;
61 };
62
63 // Defines encodings of special characters. Just use a 7-bit ASCII character
64 kumpf 1.1 // as an index into this array to retrieve its string encoding and encoding
65 // length in bytes.
66 static const SpecialChar _specialChars[] =
67 {
68 {STRLIT_ARGS("�")},
69 {STRLIT_ARGS("")},
70 {STRLIT_ARGS("")},
71 {STRLIT_ARGS("")},
72 {STRLIT_ARGS("")},
73 {STRLIT_ARGS("")},
74 {STRLIT_ARGS("")},
75 {STRLIT_ARGS("")},
76 {STRLIT_ARGS("")},
77 {STRLIT_ARGS("	")},
78 {STRLIT_ARGS(" ")},
79 {STRLIT_ARGS("")},
80 {STRLIT_ARGS("")},
81 {STRLIT_ARGS(" ")},
82 {STRLIT_ARGS("")},
83 {STRLIT_ARGS("")},
84 {STRLIT_ARGS("")},
85 kumpf 1.1 {STRLIT_ARGS("")},
86 {STRLIT_ARGS("")},
87 {STRLIT_ARGS("")},
88 {STRLIT_ARGS("")},
89 {STRLIT_ARGS("")},
90 {STRLIT_ARGS("")},
91 {STRLIT_ARGS("")},
92 {STRLIT_ARGS("")},
93 {STRLIT_ARGS("")},
94 {STRLIT_ARGS("")},
95 {STRLIT_ARGS("")},
96 {STRLIT_ARGS("")},
97 {STRLIT_ARGS("")},
98 {STRLIT_ARGS("")},
99 {STRLIT_ARGS("")},
100 {STRLIT_ARGS(" ")},
101 {STRLIT_ARGS("!")},
102 {STRLIT_ARGS(""")},
103 {STRLIT_ARGS("#")},
104 {STRLIT_ARGS("$")},
105 {STRLIT_ARGS("%")},
106 kumpf 1.1 {STRLIT_ARGS("&")},
107 {STRLIT_ARGS("'")},
108 {STRLIT_ARGS("(")},
109 {STRLIT_ARGS(")")},
110 {STRLIT_ARGS("*")},
111 {STRLIT_ARGS("+")},
112 {STRLIT_ARGS(",")},
113 {STRLIT_ARGS("-")},
114 {STRLIT_ARGS(".")},
115 {STRLIT_ARGS("/")},
116 {STRLIT_ARGS("0")},
117 {STRLIT_ARGS("1")},
118 {STRLIT_ARGS("2")},
119 {STRLIT_ARGS("3")},
120 {STRLIT_ARGS("4")},
121 {STRLIT_ARGS("5")},
122 {STRLIT_ARGS("6")},
123 {STRLIT_ARGS("7")},
124 {STRLIT_ARGS("8")},
125 {STRLIT_ARGS("9")},
126 {STRLIT_ARGS(":")},
127 kumpf 1.1 {STRLIT_ARGS(";")},
128 {STRLIT_ARGS("<")},
129 {STRLIT_ARGS("=")},
130 {STRLIT_ARGS(">")},
131 {STRLIT_ARGS("?")},
132 {STRLIT_ARGS("@")},
133 {STRLIT_ARGS("A")},
134 {STRLIT_ARGS("B")},
135 {STRLIT_ARGS("C")},
136 {STRLIT_ARGS("D")},
137 {STRLIT_ARGS("E")},
138 {STRLIT_ARGS("F")},
139 {STRLIT_ARGS("G")},
140 {STRLIT_ARGS("H")},
141 {STRLIT_ARGS("I")},
142 {STRLIT_ARGS("J")},
143 {STRLIT_ARGS("K")},
144 {STRLIT_ARGS("L")},
145 {STRLIT_ARGS("M")},
146 {STRLIT_ARGS("N")},
147 {STRLIT_ARGS("O")},
148 kumpf 1.1 {STRLIT_ARGS("P")},
149 {STRLIT_ARGS("Q")},
150 {STRLIT_ARGS("R")},
151 {STRLIT_ARGS("S")},
152 {STRLIT_ARGS("T")},
153 {STRLIT_ARGS("U")},
154 {STRLIT_ARGS("V")},
155 {STRLIT_ARGS("W")},
156 {STRLIT_ARGS("X")},
157 {STRLIT_ARGS("Y")},
158 {STRLIT_ARGS("Z")},
159 {STRLIT_ARGS("[")},
160 {STRLIT_ARGS("\\")},
161 {STRLIT_ARGS("]")},
162 {STRLIT_ARGS("^")},
163 {STRLIT_ARGS("_")},
164 {STRLIT_ARGS("`")},
165 {STRLIT_ARGS("a")},
166 {STRLIT_ARGS("b")},
167 {STRLIT_ARGS("c")},
168 {STRLIT_ARGS("d")},
169 kumpf 1.1 {STRLIT_ARGS("e")},
170 {STRLIT_ARGS("f")},
171 {STRLIT_ARGS("g")},
172 {STRLIT_ARGS("h")},
173 {STRLIT_ARGS("i")},
174 {STRLIT_ARGS("j")},
175 {STRLIT_ARGS("k")},
176 {STRLIT_ARGS("l")},
177 {STRLIT_ARGS("m")},
178 {STRLIT_ARGS("n")},
179 {STRLIT_ARGS("o")},
180 {STRLIT_ARGS("p")},
181 {STRLIT_ARGS("q")},
182 {STRLIT_ARGS("r")},
183 {STRLIT_ARGS("s")},
184 {STRLIT_ARGS("t")},
185 {STRLIT_ARGS("u")},
186 {STRLIT_ARGS("v")},
187 {STRLIT_ARGS("w")},
188 {STRLIT_ARGS("x")},
189 {STRLIT_ARGS("y")},
190 kumpf 1.1 {STRLIT_ARGS("z")},
191 {STRLIT_ARGS("{")},
192 {STRLIT_ARGS("|")},
193 {STRLIT_ARGS("}")},
194 {STRLIT_ARGS("~")},
195 {STRLIT_ARGS("")},
196 };
197
198 // If _isSpecialChar7[ch] is true, then ch is a special character, which must
199 // have a special encoding in XML. But only use 7-bit ASCII characters to
200 // index this array.
201 static const int _isSpecialChar7[] =
202 {
203 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,1,0,0,
204 0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,
205 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
206 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
207 };
208
209 ////////////////////////////////////////////////////////////////////////////////
210
211 kumpf 1.1 Buffer& operator<<(Buffer& out, const Char16& x)
212 {
213 XmlGenerator::append(out, x);
214 return out;
215 }
216
217 Buffer& operator<<(Buffer& out, const String& x)
218 {
219 XmlGenerator::append(out, x);
220 return out;
221 }
222
223 Buffer& operator<<(Buffer& out, const Buffer& x)
224 {
225 out.append(x.getData(), x.size());
226 return out;
227 }
228
229 Buffer& operator<<(Buffer& out, Uint32 x)
230 {
231 XmlGenerator::append(out, x);
232 kumpf 1.1 return out;
233 }
234
235 Buffer& operator<<(Buffer& out, const CIMName& name)
236 {
237 XmlGenerator::append(out, name.getString ());
238 return out;
239 }
240
241 Buffer& operator<<(Buffer& out, const AcceptLanguageList& al)
242 {
243 XmlGenerator::append(out, LanguageParser::buildAcceptLanguageHeader(al));
244 return out;
245 }
246
247 Buffer& operator<<(Buffer& out, const ContentLanguageList& cl)
248 {
249 XmlGenerator::append(out, LanguageParser::buildContentLanguageHeader(cl));
250 return out;
251 }
252
253 kumpf 1.1 void XmlGenerator::_appendChar(Buffer& out, const Char16& c)
254 {
255 // We need to convert the Char16 to UTF8 then append the UTF8
256 // character into the array.
257 // NOTE: The UTF8 character could be several bytes long.
258 // WARNING: This function will put in replacement character for
259 // all characters that have surogate pairs.
260 char str[6];
261 memset(str,0x00,sizeof(str));
262 Uint8* charIN = (Uint8 *)&c;
263
264 const Uint16 *strsrc = (Uint16 *)charIN;
265 Uint16 *endsrc = (Uint16 *)&charIN[1];
266
267 Uint8 *strtgt = (Uint8 *)str;
268 Uint8 *endtgt = (Uint8 *)&str[5];
269
270 UTF16toUTF8(
271 &strsrc,
272 endsrc,
273 &strtgt,
274 kumpf 1.1 endtgt);
275
276 out.append(str, UTF_8_COUNT_TRAIL_BYTES(str[0]) + 1);
277 }
278
279 void XmlGenerator::_appendSpecialChar7(Buffer& out, char c)
280 {
281 if (_isSpecialChar7[int(c)])
282 out.append(_specialChars[int(c)].str, _specialChars[int(c)].size);
283 else
284 out.append(c);
285 }
286
287 void XmlGenerator::_appendSpecialChar(Buffer& out, const Char16& c)
288 {
289 if (c < 128)
290 _appendSpecialChar7(out, char(c));
291 else
292 _appendChar(out, c);
293 }
294
295 kumpf 1.1 void XmlGenerator::_appendSpecialChar(PEGASUS_STD(ostream)& os, char c)
296 {
297 if ( ((c < 0x20) && (c >= 0)) || (c == 0x7f) )
298 {
299 char scratchBuffer[22];
300 Uint32 outputLength;
301 const char * output = Uint8ToString(scratchBuffer,
302 static_cast<Uint8>(c),
303 outputLength);
304 os << "&#" << output << ";";
305 }
306 else
307 {
308 switch (c)
309 {
310 case '&':
311 os << "&";
312 break;
313
314 case '<':
315 os << "<";
316 kumpf 1.1 break;
317
318 case '>':
319 os << ">";
320 break;
321
322 case '"':
323 os << """;
324 break;
325
326 case '\'':
327 os << "'";
328 break;
329
330 default:
331 os << c;
332 }
333 }
334 }
335
336 void XmlGenerator::_appendSurrogatePair(Buffer& out, Uint16 high, Uint16 low)
337 kumpf 1.1 {
338 char str[6];
339 Uint8 charIN[5];
340 memset(str,0x00,sizeof(str));
341 memcpy(&charIN,&high,2);
342 memcpy(&charIN[2],&low,2);
343 const Uint16 *strsrc = (Uint16 *)charIN;
344 Uint16 *endsrc = (Uint16 *)&charIN[3];
345
346 Uint8 *strtgt = (Uint8 *)str;
347 Uint8 *endtgt = (Uint8 *)&str[5];
348
349 UTF16toUTF8(
350 &strsrc,
351 endsrc,
352 &strtgt,
353 endtgt);
354
355 Uint32 number1 = UTF_8_COUNT_TRAIL_BYTES(str[0]) + 1;
356 out.append(str,number1);
357 }
358 kumpf 1.1
359 void XmlGenerator::_appendSpecial(PEGASUS_STD(ostream)& os, const char* str)
360 {
361 while (*str)
362 _appendSpecialChar(os, *str++);
363 }
364
365 // On windows sprintf outputs 3 digit precision exponent prepending
366 // zeros. Make it 2 digit precision if first digit is zero in the exponent.
367 #ifdef PEGASUS_OS_TYPE_WINDOWS
|
369 kumpf 1.1 {
370 // skip initial sign value...
371 if (*str == '-' || *str == '+')
372 {
373 ++str;
374 }
375 while (*str && *str != '+' && *str != '-')
376 {
377 ++str;
378 }
379 if (*str && * ++str == '0')
380 {
381 *str = *(str+1);
382 *(str+1) = *(str+2);
383 *(str+2) = 0;
384 }
385 }
386 #endif
387
388 void XmlGenerator::append(Buffer& out, const Char16& x)
389 {
390 kumpf 1.1 _appendChar(out, x);
391 }
392
393 void XmlGenerator::append(Buffer& out, Boolean x)
394 {
395 if (x)
396 out.append(STRLIT_ARGS("TRUE"));
397 else
398 out.append(STRLIT_ARGS("FALSE"));
399 }
400
401 void XmlGenerator::append(Buffer& out, Uint32 x)
402 {
403 Uint32 outputLength=0;
404 char buffer[22];
405 const char * output = Uint32ToString(buffer, x, outputLength);
406 out.append(output, outputLength);
407 }
408
409 void XmlGenerator::append(Buffer& out, Sint32 x)
410 {
411 kumpf 1.1 Uint32 outputLength=0;
412 char buffer[22];
413 const char * output = Sint32ToString(buffer, x, outputLength);
414 out.append(output, outputLength);
415 }
416
417 void XmlGenerator::append(Buffer& out, Uint64 x)
418 {
419 Uint32 outputLength=0;
420 char buffer[22];
421 const char * output = Uint64ToString(buffer, x, outputLength);
422 out.append(output, outputLength);
423 }
424
425 void XmlGenerator::append(Buffer& out, Sint64 x)
426 {
427 Uint32 outputLength=0;
428 char buffer[22];
429 const char * output = Sint64ToString(buffer, x, outputLength);
430 out.append(output, outputLength);
431 }
432 kumpf 1.1
433 void XmlGenerator::append(Buffer& out, Real32 x)
434 {
435 char buffer[128];
436 // %.7e gives '[-]m.ddddddde+/-xx', which seems compatible with the format
437 // given in the CIM/XML spec, and the precision required by the CIM 2.2 spec
438 // (4 byte IEEE floating point)
439 sprintf(buffer, "%.7e", x);
440 #ifdef PEGASUS_OS_TYPE_WINDOWS
441 _normalizeRealValueString(buffer);
442 #endif
443 append(out, buffer);
444 }
445
446 void XmlGenerator::append(Buffer& out, Real64 x)
447 {
448 char buffer[128];
449 // %.16e gives '[-]m.dddddddddddddddde+/-xx', which seems compatible
450 // with the format given in the CIM/XML spec, and the precision required
451 // by the CIM 2.2 spec (8 byte IEEE floating point)
452 sprintf(buffer, "%.16e", x);
453 kumpf 1.1 #ifdef PEGASUS_OS_TYPE_WINDOWS
454 _normalizeRealValueString(buffer);
455 #endif
456 append(out, buffer);
457 }
458
459 void XmlGenerator::append(Buffer& out, const char* str)
460 {
461 size_t n = strlen(str);
462 out.append(str, n);
463 }
464
465 void XmlGenerator::append(Buffer& out, const String& str)
466 {
467 const Uint16* p = (const Uint16*)str.getChar16Data();
468 size_t n = str.size();
469
470 // Handle leading ASCII 7 characers in these next two loops (use unrolling).
471
472 while (n >= 8 && ((p[0]|p[1]|p[2]|p[3]|p[4]|p[5]|p[6]|p[7]) & 0xFF80) == 0)
473 {
474 kumpf 1.1 out.append(p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
475 p += 8;
476 n -= 8;
477 }
478
479 while (n >= 4 && ((p[0]|p[1]|p[2]|p[3]) & 0xFF80) == 0)
480 {
481 out.append(p[0], p[1], p[2], p[3]);
482 p += 4;
483 n -= 4;
484 }
485
486 while (n--)
487 {
488 Uint16 c = *p++;
489
490 // Special processing for UTF8 case:
491
492 if (c < 128)
493 {
494 out.append(c);
495 kumpf 1.1 continue;
496 }
497
498 // Handle UTF8 case (if reached).
499
500 if (((c >= FIRST_HIGH_SURROGATE) && (c <= LAST_HIGH_SURROGATE)) ||
501 ((c >= FIRST_LOW_SURROGATE) && (c <= LAST_LOW_SURROGATE)))
502 {
503 Char16 highSurrogate = p[-1];
504 Char16 lowSurrogate = p[0];
505 p++;
506 n--;
507
508 _appendSurrogatePair(
509 out, Uint16(highSurrogate),Uint16(lowSurrogate));
510 }
511 else
512 {
513 _appendChar(out, c);
514 }
515 }
516 kumpf 1.1 }
517
518 void XmlGenerator::appendSpecial(Buffer& out, const Char16& x)
519 {
520 _appendSpecialChar(out, x);
521 }
522
523 void XmlGenerator::appendSpecial(Buffer& out, char x)
524 {
525 _appendSpecialChar7(out, x);
526 }
527
528 void XmlGenerator::appendSpecial(Buffer& out, const char* str)
529 {
530 while (*str)
531 _appendSpecialChar7(out, *str++);
532 }
533
534 void XmlGenerator::appendSpecial(Buffer& out, const String& str)
535 {
536 const Uint16* p = (const Uint16*)str.getChar16Data();
537 kumpf 1.1 // prevCharIsSpace is true when the last character written to the Buffer
538 // is a space character (not a character reference).
539 Boolean prevCharIsSpace = false;
540
541 // If the first character is a space, use a character reference to avoid
542 // space compression.
543 if (*p == ' ')
544 {
545 out.append(STRLIT_ARGS(" "));
546 p++;
547 }
548
549 Uint16 c;
550 while ((c = *p++) != 0)
551 {
552 if (c < 128)
553 {
554 if (_isSpecialChar7[c])
555 {
556 // Write the character reference for the special character
557 out.append(
558 kumpf 1.1 _specialChars[int(c)].str, _specialChars[int(c)].size);
559 prevCharIsSpace = false;
560 }
561 else if (prevCharIsSpace && (c == ' '))
562 {
563 // Write the character reference for the space character, to
564 // avoid compression
565 out.append(STRLIT_ARGS(" "));
566 prevCharIsSpace = false;
567 }
568 else
569 {
570 out.append(c);
571 prevCharIsSpace = (c == ' ');
572 }
573 }
574 else
575 {
576 // Handle UTF8 case
577
578 if ((((c >= FIRST_HIGH_SURROGATE) && (c <= LAST_HIGH_SURROGATE)) ||
579 kumpf 1.1 ((c >= FIRST_LOW_SURROGATE) && (c <= LAST_LOW_SURROGATE))) &&
580 *p)
581 {
582 _appendSurrogatePair(out, c, *p++);
583 }
584 else
585 {
586 _appendChar(out, c);
587 }
588
589 prevCharIsSpace = false;
590 }
591 }
592
593 // If the last character is a space, use a character reference to avoid
594 // space compression.
595 if (prevCharIsSpace)
596 {
597 out.remove(out.size() - 1);
598 out.append(STRLIT_ARGS(" "));
599 }
600 kumpf 1.1 }
601
602 // See http://www.ietf.org/rfc/rfc2396.txt section 2
603 // Reserved characters = ';' '/' '?' ':' '@' '&' '=' '+' '$' ','
604 // Excluded characters:
605 // Control characters = 0x00-0x1f, 0x7f
606 // Space character = 0x20
607 // Delimiters = '<' '>' '#' '%' '"'
608 // Unwise = '{' '}' '|' '\\' '^' '[' ']' '`'
609 //
610
611 static const char _is_uri[128] =
612 {
613 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,
614 1,1,0,0,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,
615 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
616 0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,1,
617 };
618
619 // Perform the necessary URI encoding of characters in HTTP header values.
620 // This is required by the HTTP/1.1 specification and the CIM/HTTP
621 kumpf 1.1 // Specification (section 3.3.2).
622 void XmlGenerator::_encodeURIChar(String& outString, Sint8 char8)
623 {
624 Uint8 c = (Uint8)char8;
625
626 #ifndef PEGASUS_DO_NOT_IMPLEMENT_URI_ENCODING
627 if (c > 127 || _is_uri[int(c)])
628 {
629 char hexencoding[4];
630 int n = sprintf(hexencoding, "%%%X%X", c/16, c%16);
631 #ifdef PEGASUS_USE_STRING_EXTENSIONS
632 outString.append(hexencoding, n);
633 #else /* PEGASUS_USE_STRING_EXTENSIONS */
634 outString.append(hexencoding);
635 #endif /* PEGASUS_USE_STRING_EXTENSIONS */
636 }
637 else
638 #endif
639 {
640 outString.append((Uint16)c);
641 }
642 kumpf 1.1 }
643
644 String XmlGenerator::encodeURICharacters(const Buffer& uriString)
645 {
646 String encodedString;
647
648 for (Uint32 i=0; i<uriString.size(); i++)
649 {
650 _encodeURIChar(encodedString, uriString[i]);
651 }
652
653 return encodedString;
654 }
655
656 String XmlGenerator::encodeURICharacters(const String& uriString)
657 {
658 String encodedString;
659
660 // See the "CIM Operations over HTTP" spec, section 3.3.2 and
661 // 3.3.3, for the treatment of non US-ASCII (UTF-8) chars
662
663 kumpf 1.1 // First, convert to UTF-8 (include handling of surrogate pairs)
664 Buffer utf8;
665 for (Uint32 i = 0; i < uriString.size(); i++)
666 {
667 Uint16 c = uriString[i];
668
669 if (((c >= FIRST_HIGH_SURROGATE) && (c <= LAST_HIGH_SURROGATE)) ||
670 ((c >= FIRST_LOW_SURROGATE) && (c <= LAST_LOW_SURROGATE)))
671 {
672 Char16 highSurrogate = uriString[i];
673 Char16 lowSurrogate = uriString[++i];
674
675 _appendSurrogatePair(
676 utf8, Uint16(highSurrogate),Uint16(lowSurrogate));
677 }
678 else
679 {
680 _appendChar(utf8, uriString[i]);
681 }
682 }
683
684 kumpf 1.1 // Second, escape the non HTTP-safe chars
685 for (Uint32 i=0; i<utf8.size(); i++)
686 {
687 _encodeURIChar(encodedString, utf8[i]);
688 }
689
690 return encodedString;
691 }
692
693 //------------------------------------------------------------------------------
694 //
695 // _printAttributes()
696 //
697 //------------------------------------------------------------------------------
698
699 void XmlGenerator::_printAttributes(
700 PEGASUS_STD(ostream)& os,
701 const XmlAttribute* attributes,
702 Uint32 attributeCount)
703 {
704 for (Uint32 i = 0; i < attributeCount; i++)
705 kumpf 1.1 {
706 os << attributes[i].name << "=";
707
708 os << '"';
709 _appendSpecial(os, attributes[i].value);
710 os << '"';
711
712 if (i + 1 != attributeCount)
713 os << ' ';
714 }
715 }
716
717 //------------------------------------------------------------------------------
718 //
719 // _indent()
720 //
721 //------------------------------------------------------------------------------
722
723 void XmlGenerator::_indent(
724 PEGASUS_STD(ostream)& os,
725 Uint32 level,
726 kumpf 1.1 Uint32 indentChars)
727 {
728 Uint32 n = level * indentChars;
729
730 for (Uint32 i = 0; i < n; i++)
731 os << ' ';
732 }
733
734 //------------------------------------------------------------------------------
735 //
736 // indentedPrint()
737 //
738 //------------------------------------------------------------------------------
739
740 void XmlGenerator::indentedPrint(
741 PEGASUS_STD(ostream)& os,
742 const char* text,
743 Uint32 indentChars)
744 {
745 AutoArrayPtr<char> tmp(strcpy(new char[strlen(text) + 1], text));
746
747 kumpf 1.1 XmlParser parser(tmp.get());
748 XmlEntry entry;
749 Stack<const char*> stack;
750
751 while (parser.next(entry))
752 {
753 switch (entry.type)
754 {
755 case XmlEntry::XML_DECLARATION:
756 {
757 _indent(os, stack.size(), indentChars);
758
759 os << "<?" << entry.text << " ";
760 _printAttributes(
|