This source file includes following definitions.
- xml_elem_free_non_recurse
- xml_elem_free
- xml_elem_new
- xml_elem_writefunc
- create_xml_escape
- xml_elem_entity_escape
- xml_element_serialize
- file_out_fptr
- simplestring_out_fptr
- xml_elem_serialize_to_string
- xml_elem_serialize_to_stream
- _xmlrpc_startElement
- _xmlrpc_endElement
- _xmlrpc_charHandler
- xml_elem_parse_buf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 static const char rcsid[] = "#(@) $Id$";
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121 #include "ext/xml/expat_compat.h"
122 #ifdef _WIN32
123 #include "xmlrpc_win32.h"
124 #endif
125 #include <stdlib.h>
126 #include <string.h>
127 #include <ctype.h>
128
129 #include "xml_element.h"
130 #include "queue.h"
131 #include "encodings.h"
132
133 #define my_free(thing) if(thing) {free(thing); thing = NULL;}
134
135 #define XML_DECL_START "<?xml"
136 #define XML_DECL_START_LEN sizeof(XML_DECL_START) - 1
137 #define XML_DECL_VERSION "version=\"1.0\""
138 #define XML_DECL_VERSION_LEN sizeof(XML_DECL_VERSION) - 1
139 #define XML_DECL_ENCODING_ATTR "encoding"
140 #define XML_DECL_ENCODING_ATTR_LEN sizeof(XML_DECL_ENCODING_ATTR) - 1
141 #define XML_DECL_ENCODING_DEFAULT "utf-8"
142 #define XML_DECL_ENCODING_DEFAULT_LEN sizeof(XML_DECL_ENCODING_DEFAULT) - 1
143 #define XML_DECL_END "?>"
144 #define XML_DECL_END_LEN sizeof(XML_DECL_END) - 1
145 #define START_TOKEN_BEGIN "<"
146 #define START_TOKEN_BEGIN_LEN sizeof(START_TOKEN_BEGIN) - 1
147 #define START_TOKEN_END ">"
148 #define START_TOKEN_END_LEN sizeof(START_TOKEN_END) - 1
149 #define EMPTY_START_TOKEN_END "/>"
150 #define EMPTY_START_TOKEN_END_LEN sizeof(EMPTY_START_TOKEN_END) - 1
151 #define END_TOKEN_BEGIN "</"
152 #define END_TOKEN_BEGIN_LEN sizeof(END_TOKEN_BEGIN) - 1
153 #define END_TOKEN_END ">"
154 #define END_TOKEN_END_LEN sizeof(END_TOKEN_END) - 1
155 #define ATTR_DELIMITER "\""
156 #define ATTR_DELIMITER_LEN sizeof(ATTR_DELIMITER) - 1
157 #define CDATA_BEGIN "<![CDATA["
158 #define CDATA_BEGIN_LEN sizeof(CDATA_BEGIN) - 1
159 #define CDATA_END "]]>"
160 #define CDATA_END_LEN sizeof(CDATA_END) - 1
161 #define EQUALS "="
162 #define EQUALS_LEN sizeof(EQUALS) - 1
163 #define WHITESPACE " "
164 #define WHITESPACE_LEN sizeof(WHITESPACE) - 1
165 #define NEWLINE "\n"
166 #define NEWLINE_LEN sizeof(NEWLINE) - 1
167 #define MAX_VAL_BUF 144
168 #define SCALAR_STR "SCALAR"
169 #define SCALAR_STR_LEN sizeof(SCALAR_STR) - 1
170 #define VECTOR_STR "VECTOR"
171 #define VECTOR_STR_LEN sizeof(VECTOR_STR) - 1
172 #define RESPONSE_STR "RESPONSE"
173 #define RESPONSE_STR_LEN sizeof(RESPONSE_STR) - 1
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197 void xml_elem_free_non_recurse(xml_element* root) {
198 if(root) {
199 xml_element_attr* attrs = Q_Head(&root->attrs);
200 while(attrs) {
201 my_free(attrs->key);
202 my_free(attrs->val);
203 my_free(attrs);
204 attrs = Q_Next(&root->attrs);
205 }
206
207 Q_Destroy(&root->children);
208 Q_Destroy(&root->attrs);
209 if(root->name) {
210 free((char *)root->name);
211 root->name = NULL;
212 }
213 simplestring_free(&root->text);
214 my_free(root);
215 }
216 }
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236 void xml_elem_free(xml_element* root) {
237 if(root) {
238 xml_element* kids = Q_Head(&root->children);
239 while(kids) {
240 xml_elem_free(kids);
241 kids = Q_Next(&root->children);
242 }
243 xml_elem_free_non_recurse(root);
244 }
245 }
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265 xml_element* xml_elem_new() {
266 xml_element* elem = calloc(1, sizeof(xml_element));
267 if(elem) {
268 Q_Init(&elem->children);
269 Q_Init(&elem->attrs);
270 simplestring_init(&elem->text);
271
272
273 simplestring_addn(&elem->text, "", 0);
274 }
275 return elem;
276 }
277
278
279 static int xml_elem_writefunc(int (*fptr)(void *data, const char *text, int size), const char *text, void *data, int len)
280 {
281 return fptr && text ? fptr(data, text, len ? len : strlen(text)) : 0;
282 }
283
284
285
286 static int create_xml_escape(char *pString, unsigned char c)
287 {
288 int counter = 0;
289
290 pString[counter++] = '&';
291 pString[counter++] = '#';
292 if(c >= 100) {
293 pString[counter++] = c / 100 + '0';
294 c = c % 100;
295 }
296 pString[counter++] = c / 10 + '0';
297 c = c % 10;
298
299 pString[counter++] = c + '0';
300 pString[counter++] = ';';
301 return counter;
302 }
303
304 #define non_ascii(c) (c > 127)
305 #define non_print(c) (!isprint(c))
306 #define markup(c) (c == '&' || c == '\"' || c == '>' || c == '<')
307 #define entity_length(c) ( (c >= 100) ? 3 : ((c >= 10) ? 2 : 1) ) + 3;
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324 static char* xml_elem_entity_escape(const char* buf, int old_len, int *newlen, XML_ELEM_ESCAPING flags) {
325 char *pRetval = 0;
326 int iNewBufLen=0;
327
328 #define should_escape(c, flag) ( ((flag & xml_elem_markup_escaping) && markup(c)) || \
329 ((flag & xml_elem_non_ascii_escaping) && non_ascii(c)) || \
330 ((flag & xml_elem_non_print_escaping) && non_print(c)) )
331
332 if(buf && *buf) {
333 const unsigned char *bufcopy;
334 char *NewBuffer;
335 int ToBeXmlEscaped=0;
336 int iLength;
337 bufcopy = buf;
338 iLength= old_len ? old_len : strlen(buf);
339 while(*bufcopy) {
340 if( should_escape(*bufcopy, flags) ) {
341
342 iLength += entity_length(*bufcopy);
343 ToBeXmlEscaped=1;
344 }
345 bufcopy++;
346 }
347
348 if(ToBeXmlEscaped) {
349
350 NewBuffer= malloc(iLength+1);
351 if(NewBuffer) {
352 bufcopy=buf;
353 while(*bufcopy) {
354 if(should_escape(*bufcopy, flags)) {
355 iNewBufLen += create_xml_escape(NewBuffer+iNewBufLen,*bufcopy);
356 }
357 else {
358 NewBuffer[iNewBufLen++]=*bufcopy;
359 }
360 bufcopy++;
361 }
362 NewBuffer[iNewBufLen] = 0;
363 pRetval = NewBuffer;
364 }
365 }
366 }
367
368 if(newlen) {
369 *newlen = iNewBufLen;
370 }
371
372 return pRetval;
373 }
374
375
376 static void xml_element_serialize(xml_element *el, int (*fptr)(void *data, const char *text, int size), void *data, XML_ELEM_OUTPUT_OPTIONS options, int depth)
377 {
378 int i;
379 static STRUCT_XML_ELEM_OUTPUT_OPTIONS default_opts = {xml_elem_pretty, xml_elem_markup_escaping | xml_elem_non_print_escaping, XML_DECL_ENCODING_DEFAULT};
380 static char whitespace[] = " "
381 " "
382 " ";
383 depth++;
384
385 if(!el) {
386
387 return;
388 }
389 if(!options) {
390 options = &default_opts;
391 }
392
393
394 if(depth == 1) {
395 xml_elem_writefunc(fptr, XML_DECL_START, data, XML_DECL_START_LEN);
396 xml_elem_writefunc(fptr, WHITESPACE, data, WHITESPACE_LEN);
397 xml_elem_writefunc(fptr, XML_DECL_VERSION, data, XML_DECL_VERSION_LEN);
398 if(options->encoding && *options->encoding) {
399 xml_elem_writefunc(fptr, WHITESPACE, data, WHITESPACE_LEN);
400 xml_elem_writefunc(fptr, XML_DECL_ENCODING_ATTR, data, XML_DECL_ENCODING_ATTR_LEN);
401 xml_elem_writefunc(fptr, EQUALS, data, EQUALS_LEN);
402 xml_elem_writefunc(fptr, ATTR_DELIMITER, data, ATTR_DELIMITER_LEN);
403 xml_elem_writefunc(fptr, options->encoding, data, 0);
404 xml_elem_writefunc(fptr, ATTR_DELIMITER, data, ATTR_DELIMITER_LEN);
405 }
406 xml_elem_writefunc(fptr, XML_DECL_END, data, XML_DECL_END_LEN);
407 if(options->verbosity != xml_elem_no_white_space) {
408 xml_elem_writefunc(fptr, NEWLINE, data, NEWLINE_LEN);
409 }
410 }
411
412 if(options->verbosity == xml_elem_pretty && depth > 2) {
413 xml_elem_writefunc(fptr, whitespace, data, depth - 2);
414 }
415
416 xml_elem_writefunc(fptr,START_TOKEN_BEGIN, data, START_TOKEN_BEGIN_LEN);
417 if(el->name) {
418 xml_elem_writefunc(fptr, el->name, data, 0);
419
420
421 if(Q_Size(&el->attrs)) {
422 xml_element_attr* iter = Q_Head(&el->attrs);
423 while( iter ) {
424 xml_elem_writefunc(fptr, WHITESPACE, data, WHITESPACE_LEN);
425 xml_elem_writefunc(fptr, iter->key, data, 0);
426 xml_elem_writefunc(fptr, EQUALS, data, EQUALS_LEN);
427 xml_elem_writefunc(fptr, ATTR_DELIMITER, data, ATTR_DELIMITER_LEN);
428 xml_elem_writefunc(fptr, iter->val, data, 0);
429 xml_elem_writefunc(fptr, ATTR_DELIMITER, data, ATTR_DELIMITER_LEN);
430
431 iter = Q_Next(&el->attrs);
432 }
433 }
434 }
435 else {
436 xml_elem_writefunc(fptr, "None", data, 0);
437 }
438
439 if(!el->text.len && !Q_Size(&el->children)) {
440 xml_elem_writefunc(fptr, EMPTY_START_TOKEN_END, data, EMPTY_START_TOKEN_END_LEN);
441 }
442
443 else {
444 xml_elem_writefunc(fptr, START_TOKEN_END, data, START_TOKEN_END_LEN);
445
446
447 if(el->text.len) {
448 char* escaped_str = el->text.str;
449 int buflen = el->text.len;
450
451 if(options->escaping && options->escaping != xml_elem_cdata_escaping) {
452 escaped_str = xml_elem_entity_escape(el->text.str, buflen, &buflen, options->escaping );
453 if(!escaped_str) {
454 escaped_str = el->text.str;
455 }
456 }
457
458 if(options->escaping & xml_elem_cdata_escaping) {
459 xml_elem_writefunc(fptr, CDATA_BEGIN, data, CDATA_BEGIN_LEN);
460 }
461
462 xml_elem_writefunc(fptr, escaped_str, data, buflen);
463
464 if(escaped_str != el->text.str) {
465 my_free(escaped_str);
466 }
467
468 if(options->escaping & xml_elem_cdata_escaping) {
469 xml_elem_writefunc(fptr, CDATA_END, data, CDATA_END_LEN);
470 }
471 }
472
473 else {
474 xml_element *kids = Q_Head(&el->children);
475 i = 0;
476 while( kids ) {
477 if(i++ == 0) {
478 if(options->verbosity != xml_elem_no_white_space) {
479 xml_elem_writefunc(fptr, NEWLINE, data, NEWLINE_LEN);
480 }
481 }
482 xml_element_serialize(kids, fptr, data, options, depth);
483 kids = Q_Next(&el->children);
484 }
485 if(i) {
486 if(options->verbosity == xml_elem_pretty && depth > 2) {
487 xml_elem_writefunc(fptr, whitespace, data, depth - 2);
488 }
489 }
490 }
491
492 xml_elem_writefunc(fptr, END_TOKEN_BEGIN, data, END_TOKEN_BEGIN_LEN);
493 xml_elem_writefunc(fptr,el->name ? el->name : "None", data, 0);
494 xml_elem_writefunc(fptr, END_TOKEN_END, data, END_TOKEN_END_LEN);
495 }
496 if(options->verbosity != xml_elem_no_white_space) {
497 xml_elem_writefunc(fptr, NEWLINE, data, NEWLINE_LEN);
498 }
499 }
500
501
502 static int file_out_fptr(void *f, const char *text, int size)
503 {
504 fputs(text, (FILE *)f);
505 return 0;
506 }
507
508
509 static int simplestring_out_fptr(void *f, const char *text, int size)
510 {
511 simplestring* buf = (simplestring*)f;
512 if(buf) {
513 simplestring_addn(buf, text, size);
514 }
515 return 0;
516 }
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537 char* xml_elem_serialize_to_string(xml_element *el, XML_ELEM_OUTPUT_OPTIONS options, int *buf_len)
538 {
539 simplestring buf;
540 simplestring_init(&buf);
541
542 xml_element_serialize(el, simplestring_out_fptr, (void *)&buf, options, 0);
543
544 if(buf_len) {
545 *buf_len = buf.len;
546 }
547
548 return buf.str;
549 }
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571 void xml_elem_serialize_to_stream(xml_element *el, FILE *output, XML_ELEM_OUTPUT_OPTIONS options)
572 {
573 xml_element_serialize(el, file_out_fptr, (void *)output, options, 0);
574 }
575
576
577
578
579
580
581
582
583
584
585
586 typedef struct _xml_elem_data {
587 xml_element* root;
588 xml_element* current;
589 XML_ELEM_INPUT_OPTIONS input_options;
590 int needs_enc_conversion;
591 } xml_elem_data;
592
593
594
595 static void _xmlrpc_startElement(void *userData, const char *name, const char **attrs)
596 {
597 xml_element *c;
598 xml_elem_data* mydata = (xml_elem_data*)userData;
599 const char** p = attrs;
600
601 if(mydata) {
602 c = mydata->current;
603
604 mydata->current = xml_elem_new();
605 mydata->current->name = (char*)strdup(name);
606 mydata->current->parent = c;
607
608
609 while(p && *p) {
610 xml_element_attr* attr = malloc(sizeof(xml_element_attr));
611 if(attr) {
612 attr->key = strdup(*p);
613 attr->val = strdup(*(p+1));
614 Q_PushTail(&mydata->current->attrs, attr);
615
616 p += 2;
617 }
618 }
619 }
620 }
621
622
623 static void _xmlrpc_endElement(void *userData, const char *name)
624 {
625 xml_elem_data* mydata = (xml_elem_data*)userData;
626
627 if(mydata && mydata->current && mydata->current->parent) {
628 Q_PushTail(&mydata->current->parent->children, mydata->current);
629
630 mydata->current = mydata->current->parent;
631 }
632 }
633
634
635 static void _xmlrpc_charHandler(void *userData,
636 const char *s,
637 int len)
638 {
639 xml_elem_data* mydata = (xml_elem_data*)userData;
640 if(mydata && mydata->current) {
641
642
643 if(mydata->needs_enc_conversion && mydata->input_options->encoding) {
644 int new_len = 0;
645 char* add_text = utf8_decode(s, len, &new_len, mydata->input_options->encoding);
646 if(add_text) {
647 len = new_len;
648 simplestring_addn(&mydata->current->text, add_text, len);
649 free(add_text);
650 return;
651 }
652 }
653 simplestring_addn(&mydata->current->text, s, len);
654 }
655 }
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687 xml_element* xml_elem_parse_buf(const char* in_buf, int len, XML_ELEM_INPUT_OPTIONS options, XML_ELEM_ERROR error)
688 {
689 xml_element* xReturn = NULL;
690 char buf[100] = "";
691 static STRUCT_XML_ELEM_INPUT_OPTIONS default_opts = {encoding_utf_8};
692
693 if(!options) {
694 options = &default_opts;
695 }
696
697 if(in_buf) {
698 XML_Parser parser;
699 xml_elem_data mydata = {0};
700
701 parser = XML_ParserCreate(NULL);
702
703 mydata.root = xml_elem_new();
704 mydata.current = mydata.root;
705 mydata.input_options = options;
706 mydata.needs_enc_conversion = options->encoding && strcmp(options->encoding, encoding_utf_8);
707
708 XML_SetElementHandler(parser, (XML_StartElementHandler)_xmlrpc_startElement, (XML_EndElementHandler)_xmlrpc_endElement);
709 XML_SetCharacterDataHandler(parser, (XML_CharacterDataHandler)_xmlrpc_charHandler);
710
711
712 XML_SetUserData(parser, (void*)&mydata);
713
714 if(!len) {
715 len = strlen(in_buf);
716 }
717
718
719 if(XML_Parse(parser, in_buf, len, 1) == 0) {
720 enum XML_Error err_code = XML_GetErrorCode(parser);
721 int line_num = XML_GetCurrentLineNumber(parser);
722 int col_num = XML_GetCurrentColumnNumber(parser);
723 long byte_idx = XML_GetCurrentByteIndex(parser);
724
725 const char * error_str = XML_ErrorString(err_code);
726 if(byte_idx >= 0) {
727 snprintf(buf,
728 sizeof(buf),
729 "\n\tdata beginning %ld before byte index: %s\n",
730 byte_idx > 10 ? 10 : byte_idx,
731 in_buf + (byte_idx > 10 ? byte_idx - 10 : byte_idx));
732 }
733
734
735
736
737
738
739
740
741
742
743
744
745 if(error) {
746 error->parser_code = (long)err_code;
747 error->line = line_num;
748 error->column = col_num;
749 error->byte_index = byte_idx;
750 error->parser_error = error_str;
751 }
752 }
753 else {
754 xReturn = (xml_element*)Q_Head(&mydata.root->children);
755 xReturn->parent = NULL;
756 }
757
758 XML_ParserFree(parser);
759
760
761 xml_elem_free_non_recurse(mydata.root);
762 }
763
764 return xReturn;
765 }
766
767