1 /*
2 * libwbxml, the WBXML Library.
3 * Copyright (C) 2002-2008 Aymerick Jehanne <aymerick@jehanne.org>
4 * Copyright (C) 2008-2011 Michael Bell <michael.bell@opensync.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 *
20 * LGPL v2.1: http://www.gnu.org/copyleft/lesser.txt
21 *
22 * Contact: aymerick@jehanne.org
23 * Home: http://libwbxml.aymerick.com
24 */
25
26 /**
27 * @file wbxml_tree_clb_xml.c
28 * @ingroup wbxml_tree
29 *
30 * @author Aymerick Jehanne <aymerick@jehanne.org>
31 * @date 03/03/11
32 *
33 * @brief WBXML Tree Callbacks for XML Parser (Expat)
34 */
35
36 #include "wbxml_config_internals.h"
37
38 #if defined( HAVE_EXPAT )
39
40 #include "wbxml_tree_clb_xml.h"
41 #include "wbxml_tree.h"
42 #include "wbxml_log.h"
43 #include "wbxml_charset.h"
44 #include "wbxml_base64.h"
45 #include <assert.h>
46
47 /************************************
48 * Public Functions
49 */
50
wbxml_tree_clb_xml_decl(void * ctx,const XML_Char * version,const XML_Char * encoding,int standalone)51 void wbxml_tree_clb_xml_decl(void *ctx,
52 const XML_Char *version,
53 const XML_Char *encoding,
54 int standalone)
55 {
56 WBXMLTreeClbCtx *tree_ctx = (WBXMLTreeClbCtx *) ctx;
57
58 (void) standalone; /* avoid warning about unused parameter */
59
60 if (tree_ctx->expat_utf16) {
61 /** @todo Convert from UTF-16 to UTF-8 */
62 }
63
64 /* This handler is called for XML declarations and also for text declarations discovered
65 * in external entities. The way to distinguish is that the version parameter will
66 * be NULL for text declarations.
67 */
68 if (version != NULL) {
69 if (encoding != NULL) {
70 /* Get encoding */
71 if (!wbxml_charset_get_mib((const WB_TINY*)encoding, &(tree_ctx->tree->orig_charset))) {
72 WBXML_WARNING((WBXML_CONV, "Charset Encoding not supported: %s", encoding));
73 }
74 }
75 }
76 }
77
78
wbxml_tree_clb_xml_doctype_decl(void * ctx,const XML_Char * doctypeName,const XML_Char * sysid,const XML_Char * pubid,int has_internal_subset)79 void wbxml_tree_clb_xml_doctype_decl(void *ctx,
80 const XML_Char *doctypeName,
81 const XML_Char *sysid,
82 const XML_Char *pubid,
83 int has_internal_subset)
84 {
85 WBXMLTreeClbCtx *tree_ctx = (WBXMLTreeClbCtx *) ctx;
86 const WBXMLLangEntry *lang_table = NULL;
87
88 (void) doctypeName; /* avoid warning about unused parameter */
89 (void) has_internal_subset; /* avoid warning about unused parameter */
90
91 if (tree_ctx->expat_utf16) {
92 /** @todo Convert from UTF-16 to UTF-8 */
93 }
94
95 /* Search for Language Table, given the XML Public ID and System ID */
96 lang_table = wbxml_tables_search_table(wbxml_tables_get_main(),
97 (const WB_UTINY *) pubid,
98 (const WB_UTINY *) sysid,
99 NULL);
100
101 if (lang_table != NULL) {
102 /* Ho Yeah ! We got it ! */
103 tree_ctx->tree->lang = lang_table;
104 }
105 else {
106 /* We will try to find the Language Table, given the Root Element */
107 WBXML_WARNING((WBXML_CONV, "Language Table NOT found, given the XML Public ID and System ID"));
108 }
109 }
110
111
wbxml_tree_clb_xml_start_element(void * ctx,const XML_Char * localName,const XML_Char ** attrs)112 void wbxml_tree_clb_xml_start_element(void *ctx,
113 const XML_Char *localName,
114 const XML_Char **attrs)
115 {
116 WBXMLTreeClbCtx *tree_ctx = (WBXMLTreeClbCtx *) ctx;
117 const WBXMLLangEntry *lang_table = NULL;
118
119 WBXML_DEBUG((WBXML_PARSER, "Expat element start callback ('%s')", localName));
120
121 if (tree_ctx->expat_utf16) {
122 /** @todo Convert from UTF-16 to UTF-8 */
123 }
124
125 /* Check for Error */
126 if (tree_ctx->error != WBXML_OK)
127 return;
128
129 /* Are we skipping a whole node ? */
130 if (tree_ctx->skip_lvl > 0) {
131 tree_ctx->skip_lvl++;
132 return;
133 }
134
135 if (tree_ctx->current == NULL) {
136 /* This is the Root Element */
137 if (tree_ctx->tree->lang == NULL) {
138 /* Language Table not already found: Search again */
139 lang_table = wbxml_tables_search_table(wbxml_tables_get_main(),
140 NULL,
141 NULL,
142 (const WB_UTINY *) localName);
143
144 if (lang_table == NULL) {
145 /* Damn, this is an unknown language for us... */
146 tree_ctx->error = WBXML_ERROR_UNKNOWN_XML_LANGUAGE;
147 return;
148 }
149 else {
150 /* Well, we hope this was the Language we are searching for.. let's try with it :| */
151 tree_ctx->tree->lang = lang_table;
152 }
153 }
154 }
155
156 #if defined( WBXML_SUPPORT_SYNCML )
157
158 /* If this is an embedded (not root) document, skip it
159 * Actually SyncML DevInf and DM DDF are known as such
160 * potentially embedded documents.
161 */
162 if ((
163 (WBXML_STRCMP(localName, "syncml:devinf:DevInf") == 0) ||
164 (WBXML_STRCMP(localName, "syncml:dmddf1.2:MgmtTree") == 0)
165 )&&
166 (tree_ctx->current != NULL))
167 {
168 tree_ctx->skip_start = XML_GetCurrentByteIndex(tree_ctx->xml_parser);
169
170 /* Skip this node */
171 tree_ctx->skip_lvl++;
172
173 return;
174 }
175
176 #endif /* WBXML_SUPPORT_SYNCML */
177
178 /* Add Element Node */
179 tree_ctx->current = wbxml_tree_add_xml_elt_with_attrs(tree_ctx->tree,
180 tree_ctx->current,
181 (WB_UTINY *) localName,
182 (const WB_UTINY**) attrs);
183
184 if (tree_ctx->current == NULL) {
185 tree_ctx->error = WBXML_ERROR_NOT_ENOUGH_MEMORY;
186 }
187 }
188
189
wbxml_tree_clb_xml_end_element(void * ctx,const XML_Char * localName)190 void wbxml_tree_clb_xml_end_element(void *ctx,
191 const XML_Char *localName)
192 {
193 WBXMLTreeClbCtx *tree_ctx = (WBXMLTreeClbCtx *) ctx;
194 WBXMLBuffer *content = NULL;
195 WBXMLTreeNode *node = NULL;
196 WBXMLError ret = WBXML_OK;
197
198 WBXML_DEBUG((WBXML_PARSER, "Expat element end callback ('%s')", localName));
199
200 /* If the node is flagged as binary node
201 * then the data is base64 encoded in the XML document
202 * and the data must be decoded in one step.
203 * Examples: Microsoft ActiveSync tags ConversationId or MIME
204 */
205
206 node = tree_ctx->current;
207 if (node && node->type == WBXML_TREE_ELEMENT_NODE &&
208 node->name->type == WBXML_VALUE_TOKEN &&
209 node->name->u.token->options & WBXML_TAG_OPTION_BINARY)
210 {
211 if (node->content == NULL)
212 {
213 WBXML_DEBUG((WBXML_PARSER, " Binary tag: No content => no conversion!"));
214 } else {
215 WBXML_DEBUG((WBXML_PARSER, " Binary tag: Convert base64 data"));
216 ret = wbxml_buffer_decode_base64(node->content);
217 if (ret != WBXML_OK)
218 {
219 WBXML_DEBUG((WBXML_PARSER, " Binary tag: Base64 decoder failed!"));
220 tree_ctx->error = ret;
221 } else {
222 /* Add the buffer as a regular string node (since libwbxml doesn't
223 * offer a way to specify an opaque data node). The WBXML
224 * encoder is responsible for generating correct opaque data for
225 * nodes like this.
226 */
227 if (wbxml_tree_add_text(tree_ctx->tree,
228 tree_ctx->current,
229 (const WB_UTINY*)wbxml_buffer_get_cstr(node->content),
230 wbxml_buffer_len(node->content)) == NULL)
231 {
232 WBXML_DEBUG((WBXML_PARSER, " Binary tag: Cannot add base64 decoded node!"));
233 tree_ctx->error = WBXML_ERROR_INTERNAL;
234 }
235 }
236 /* safe cleanup */
237 content = node->content;
238 node->content = NULL;
239 wbxml_buffer_destroy(content);
240 }
241 }
242
243 if (tree_ctx->expat_utf16) {
244 /** @todo Convert from UTF-16 to UTF-8 */
245 }
246
247 /* Check for Error */
248 if (tree_ctx->error != WBXML_OK)
249 return;
250
251 /* Are we skipping a whole node ? */
252 if (tree_ctx->skip_lvl > 0) {
253 if (tree_ctx->skip_lvl == 1)
254 {
255 /* End of skipped node */
256
257 #if defined( WBXML_SUPPORT_SYNCML )
258 if (WBXML_STRCMP(localName, "syncml:devinf:DevInf") == 0 ||
259 WBXML_STRCMP(localName, "syncml:dmddf1.2:MgmtTree") == 0) {
260 /* definitions first ... or some compilers don't like it */
261 WBXMLBuffer *embed_doc = NULL;
262 WBXMLTree *tree = NULL;
263 const WBXMLLangEntry *lang;
264
265 /* Get embedded DevInf or DM DDF Document */
266 embed_doc = wbxml_buffer_create(tree_ctx->input_buff + tree_ctx->skip_start,
267 XML_GetCurrentByteIndex(tree_ctx->xml_parser) - tree_ctx->skip_start,
268 XML_GetCurrentByteIndex(tree_ctx->xml_parser) - tree_ctx->skip_start + 10);
269 if (embed_doc == NULL) {
270 tree_ctx->error = WBXML_ERROR_NOT_ENOUGH_MEMORY;
271 wbxml_buffer_destroy(embed_doc);
272 return;
273 }
274
275 if (tree_ctx->expat_utf16) {
276 /** @todo Convert from UTF-16 to UTF-8 */
277 }
278
279 /* Check Buffer Creation and add the closing tag */
280 if ((WBXML_STRCMP(localName, "syncml:devinf:DevInf") == 0 &&
281 (!wbxml_buffer_append_cstr(embed_doc, "</DevInf>")))
282 ||
283 (WBXML_STRCMP(localName, "syncml:dmddf1.2:MgmtTree") == 0 &&
284 (!wbxml_buffer_append_cstr(embed_doc, "</MgmtTree>"))))
285 {
286 tree_ctx->error = WBXML_ERROR_NOT_ENOUGH_MEMORY;
287 wbxml_buffer_destroy(embed_doc);
288 return;
289 }
290
291 /* Add doctype to give the XML parser a chance */
292 if (WBXML_STRCMP(localName, "syncml:dmddf1.2:MgmtTree") == 0 &&
293 tree_ctx->tree->lang->langID != WBXML_LANG_SYNCML_SYNCML12)
294 {
295 tree_ctx->error = WBXML_ERROR_UNKNOWN_XML_LANGUAGE;
296 wbxml_buffer_destroy(embed_doc);
297 return;
298 }
299 switch(tree_ctx->tree->lang->langID)
300 {
301 case WBXML_LANG_SYNCML_SYNCML10:
302 lang = wbxml_tables_get_table(WBXML_LANG_SYNCML_DEVINF10);
303 break;
304 case WBXML_LANG_SYNCML_SYNCML11:
305 lang = wbxml_tables_get_table(WBXML_LANG_SYNCML_DEVINF11);
306 break;
307 case WBXML_LANG_SYNCML_SYNCML12:
308 if (WBXML_STRCMP(localName, "syncml:dmddf1.2:MgmtTree") == 0) {
309 lang = wbxml_tables_get_table(WBXML_LANG_SYNCML_DMDDF12);
310 } else {
311 lang = wbxml_tables_get_table(WBXML_LANG_SYNCML_DEVINF12);
312 }
313 break;
314 default:
315 tree_ctx->error = WBXML_ERROR_UNKNOWN_XML_LANGUAGE;
316 wbxml_buffer_destroy(embed_doc);
317 return;
318 }
319
320 assert (lang!= NULL);
321 if (lang == NULL) {
322 tree_ctx->error = WBXML_ERROR_UNKNOWN_XML_LANGUAGE;
323 wbxml_buffer_destroy(embed_doc);
324 return;
325 }
326
327 /* DOCTYPE in reverse order */
328 if (!wbxml_buffer_insert_cstr(embed_doc,(WB_UTINY *) "\">\n", 0) || /* > */
329 !wbxml_buffer_insert_cstr(embed_doc, (WB_UTINY *) lang->publicID->xmlDTD, 0) || /* DTD */
330 !wbxml_buffer_insert_cstr(embed_doc, (WB_UTINY *) "\" \"", 0) || /* DTD */
331 !wbxml_buffer_insert_cstr(embed_doc, (WB_UTINY *) lang->publicID->xmlPublicID, 0) || /* Public ID */
332 !wbxml_buffer_insert_cstr(embed_doc, (WB_UTINY *) " PUBLIC \"", 0) || /* PUBLIC " */
333 !wbxml_buffer_insert_cstr(embed_doc, (WB_UTINY *) lang->publicID->xmlRootElt, 0) || /* Root Element */
334 !wbxml_buffer_insert_cstr(embed_doc, (WB_UTINY *) "<!DOCTYPE ", 0)) /* <!DOCTYPE */
335 {
336 tree_ctx->error = WBXML_ERROR_ENCODER_APPEND_DATA;
337 wbxml_buffer_destroy(embed_doc);
338 return;
339 }
340
341 WBXML_DEBUG((WBXML_PARSER, "\t Embedded Doc : '%s'", wbxml_buffer_get_cstr(embed_doc)));
342
343 /* Parse 'DevInf' Document */
344 if ((ret = wbxml_tree_from_xml(wbxml_buffer_get_cstr(embed_doc),
345 wbxml_buffer_len(embed_doc),
346 &tree)) != WBXML_OK)
347 {
348 tree_ctx->error = ret;
349 wbxml_buffer_destroy(embed_doc);
350 return;
351 }
352
353 /* Add Tree Node */
354 tree_ctx->current = wbxml_tree_add_tree(tree_ctx->tree,
355 tree_ctx->current,
356 tree);
357 if (tree_ctx->current == NULL)
358 {
359 tree_ctx->error = WBXML_ERROR_INTERNAL;
360 wbxml_tree_destroy(tree);
361 wbxml_buffer_destroy(embed_doc);
362 return;
363 }
364
365 /* Clean-up */
366 wbxml_buffer_destroy(embed_doc);
367 tree_ctx->skip_lvl = 0;
368 }
369 #endif /* WBXML_SUPPORT_SYNCML */
370 }
371 else {
372 tree_ctx->skip_lvl--;
373 return;
374 }
375 }
376
377 if (tree_ctx->current == NULL) {
378 tree_ctx->error = WBXML_ERROR_INTERNAL;
379 return;
380 }
381
382 if (tree_ctx->current->parent == NULL) {
383 /* This must be the Root Element */
384 if (tree_ctx->current != tree_ctx->tree->root) {
385 tree_ctx->error = WBXML_ERROR_INTERNAL;
386 }
387 }
388 else {
389 #if defined ( WBXML_SUPPORT_SYNCML )
390 /* Have we added a missing CDATA section ?
391 * If so, we assume that now that we have reached an end of Element,
392 * the CDATA section ended, and so we go back to parent.
393 */
394 if ((tree_ctx->current != NULL) && (tree_ctx->current->type == WBXML_TREE_CDATA_NODE))
395 tree_ctx->current = tree_ctx->current->parent;
396 #endif /* WBXML_SUPPORT_SYNCML */
397
398 /* Go back one step upper in the tree */
399 tree_ctx->current = tree_ctx->current->parent;
400 }
401 }
402
403
wbxml_tree_clb_xml_start_cdata(void * ctx)404 void wbxml_tree_clb_xml_start_cdata(void *ctx)
405 {
406 WBXMLTreeClbCtx *tree_ctx = (WBXMLTreeClbCtx *) ctx;
407
408 /* Check for Error */
409 if (tree_ctx->error != WBXML_OK)
410 return;
411
412 /* Are we skipping a whole node ? */
413 if (tree_ctx->skip_lvl > 0)
414 return;
415
416 /* Add CDATA Node */
417 tree_ctx->current = wbxml_tree_add_cdata(tree_ctx->tree, tree_ctx->current);
418 if (tree_ctx->current == NULL) {
419 tree_ctx->error = WBXML_ERROR_INTERNAL;
420 }
421 }
422
423
wbxml_tree_clb_xml_end_cdata(void * ctx)424 void wbxml_tree_clb_xml_end_cdata(void *ctx)
425 {
426 WBXMLTreeClbCtx *tree_ctx = (WBXMLTreeClbCtx *) ctx;
427
428 /* Check for Error */
429 if (tree_ctx->error != WBXML_OK)
430 return;
431
432 /* Are we skipping a whole node ? */
433 if (tree_ctx->skip_lvl > 0)
434 return;
435
436 if (tree_ctx->current == NULL) {
437 tree_ctx->error = WBXML_ERROR_INTERNAL;
438 return;
439 }
440
441 if (tree_ctx->current->parent == NULL) {
442 /* This must be the Root Element */
443 if (tree_ctx->current != tree_ctx->tree->root) {
444 tree_ctx->error = WBXML_ERROR_INTERNAL;
445 }
446 }
447 else {
448 /* Go back one step upper in the tree */
449 tree_ctx->current = tree_ctx->current->parent;
450 }
451 }
452
453
wbxml_tree_clb_xml_characters(void * ctx,const XML_Char * ch,int len)454 void wbxml_tree_clb_xml_characters(void *ctx,
455 const XML_Char *ch,
456 int len)
457 {
458 WBXMLTreeNode *node;
459 WBXMLTreeClbCtx *tree_ctx = (WBXMLTreeClbCtx *) ctx;
460
461 WBXML_DEBUG((WBXML_PARSER, "Expat text callback"));
462
463 if (tree_ctx->expat_utf16) {
464 /** @todo Convert from UTF-16 to UTF-8 */
465 }
466
467 /* Check for Error */
468 if (tree_ctx->error != WBXML_OK)
469 return;
470
471 /* Are we skipping a whole node ? */
472 if (tree_ctx->skip_lvl > 0)
473 return;
474
475 #if defined ( WBXML_SUPPORT_SYNCML )
476 /* Specific treatment for SyncML */
477 switch (wbxml_tree_node_get_syncml_data_type(tree_ctx->current)) {
478 case WBXML_SYNCML_DATA_TYPE_DIRECTORY_VCARD:
479 case WBXML_SYNCML_DATA_TYPE_VCALENDAR:
480 case WBXML_SYNCML_DATA_TYPE_VCARD:
481 case WBXML_SYNCML_DATA_TYPE_VOBJECT:
482 /* SyncML has some real design bugs
483 * because the authors of the specification did not understand XML.
484 *
485 * There must be a hack to preserve the CRLFs of vFormat objects.
486 * The only chance to do this is the detection of the vFormat itself
487 * and the conversion of every LF to a CRLF.
488 *
489 * The line breaks are always in a single text node.
490 * So a CR is appended to get a CRLF at the end.
491 */
492
493 if (len == 1 && ch[0] == '\n') /* line break - LF */
494 {
495 ch = "\r\n";
496 len = 2;
497 }
498
499 /* Do not break here.
500 * The CDATA handling is required for vFormat objects too.
501 */
502 case WBXML_SYNCML_DATA_TYPE_CLEAR:
503 /*
504 * Add a missing CDATA section node
505 *
506 * Example:
507 * <Add>
508 * <CmdID>6</CmdID>
509 * <Meta><Type xmlns='syncml:metinf'>text/x-vcard</Type></Meta>
510 * <Item>
511 * <Source>
512 * <LocURI>pas-id-3F4B790300000000</LocURI>
513 * </Source>
514 * <Data>BEGIN:VCARD
515 * VERSION:2.1
516 * X-EVOLUTION-FILE-AS:Ximian, Inc.
517 * N:
518 * LABEL;WORK;ENCODING=QUOTED-PRINTABLE:401 Park Drive 3 West=0ABoston, MA
519 * 02215=0AUSA
520 * TEL;WORK;VOICE:(617) 236-0442
521 * TEL;WORK;FAX:(617) 236-8630
522 * EMAIL;INTERNET:[EMAIL PROTECTED]
523 * URL:www.ximian.com/
524 * ORG:Ximian, Inc.
525 * NOTE:Welcome to the Ximian Addressbook.
526 * UID:pas-id-3F4B790300000000
527 * END:VCARD</Data>
528 * </Item>
529 * </Add>
530 *
531 * The end of CDATA section is assumed to be reached when parsing the end
532 * of </Data> element.
533 *
534 * This kind of document is erroneous, but we must handle it.
535 * Normally, this should be:
536 *
537 * ...
538 * <Data><!CDATA[[BEGIN:VCARD
539 * VERSION:2.1
540 * X-EVOLUTION-FILE-AS:Ximian, Inc.
541 * ...
542 * UID:pas-id-3F4B790300000000
543 * END:VCARD
544 * ]]></Data>
545 * ...
546 */
547
548 /*
549 * We add a missing CDATA section if we are not already in a CDATA section.
550 *
551 * We don't add a CDATA section if we have already added a CDATA section. This
552 * permits to correctly handle good XML documents like this:
553 *
554 * ...
555 * <Data><!CDATA[[BEGIN:VCARD
556 * VERSION:2.1
557 * X-EVOLUTION-FILE-AS:Ximian, Inc.
558 * ...
559 * UID:pas-id-3F4B790300000000
560 * END:VCARD
561 * ]]>
562 * </Data>
563 * ...
564 *
565 * In this example, the spaces beetwen "]]>" and "</Data>" must not be added
566 * to a CDATA section.
567 */
568 if ((tree_ctx->current != NULL) &&
569 (tree_ctx->current->type != WBXML_TREE_CDATA_NODE) &&
570 !((tree_ctx->current->children != NULL) &&
571 (tree_ctx->current->children->type == WBXML_TREE_CDATA_NODE)))
572 {
573 /* Add CDATA Node */
574 tree_ctx->current = wbxml_tree_add_cdata(tree_ctx->tree, tree_ctx->current);
575 if (tree_ctx->current == NULL) {
576 tree_ctx->error = WBXML_ERROR_INTERNAL;
577 return;
578 }
579 }
580
581 /* Now we can add the Text Node */
582 break;
583
584 default:
585 /* NOP */
586 break;
587 } /* switch */
588 #endif /* WBXML_SUPPORT_SYNCML */
589
590 /* We expect that "byte array" or BLOB types are
591 * encoded in Base 64 in the XML code, since they may contain binary data.
592 */
593
594 node = tree_ctx->current;
595 if (node && node->type == WBXML_TREE_ELEMENT_NODE &&
596 node->name->type == WBXML_VALUE_TOKEN &&
597 node->name->u.token->options & WBXML_TAG_OPTION_BINARY)
598 {
599 WBXML_DEBUG((WBXML_PARSER, " Binary tag: Caching base64 encoded data for later conversion."));
600 if (node->content == NULL)
601 {
602 node->content = wbxml_buffer_create(ch, len, 1);
603 if (node->content == NULL)
604 tree_ctx->error = WBXML_ERROR_NOT_ENOUGH_MEMORY;
605 } else {
606 if (!wbxml_buffer_append_data(node->content, ch, len))
607 tree_ctx->error = WBXML_ERROR_NOT_ENOUGH_MEMORY;
608 }
609 return;
610 }
611
612 /* Add Text Node */
613 if (wbxml_tree_add_text(tree_ctx->tree,
614 tree_ctx->current,
615 (const WB_UTINY*) ch,
616 len) == NULL)
617 {
618 tree_ctx->error = WBXML_ERROR_INTERNAL;
619 }
620 }
621
622
wbxml_tree_clb_xml_pi(void * ctx,const XML_Char * target,const XML_Char * data)623 void wbxml_tree_clb_xml_pi(void *ctx,
624 const XML_Char *target,
625 const XML_Char *data)
626 {
627 WBXMLTreeClbCtx *tree_ctx = (WBXMLTreeClbCtx *) ctx;
628
629 if (tree_ctx->expat_utf16) {
630 /** @todo Convert from UTF-16 to UTF-8 */
631 }
632
633 /* Check for Error */
634 if (tree_ctx->error != WBXML_OK)
635 return;
636
637 /* Are we skipping a whole node ? */
638 if (tree_ctx->skip_lvl > 0)
639 return;
640
641 /** @todo wbxml2xml_clb_pi() */
642 }
643
644 #endif /* HAVE_EXPAT */
645