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.c
28  * @ingroup wbxml_tree
29  *
30  * @author Aymerick Jehanne <aymerick@jehanne.org>
31  * @date 03/02/18
32  *
33  * @brief WBXML Tree
34  */
35 
36 #include "wbxml_config_internals.h"
37 #include "wbxml_tree.h"
38 #include "wbxml_log.h"
39 #include "wbxml_parser.h"
40 #include "wbxml_encoder.h"
41 #include "wbxml_tree_clb_xml.h"
42 #include "wbxml_tree_clb_wbxml.h"
43 #include "wbxml_internals.h"
44 
45 /***************************************************
46  *    Public Functions
47  */
48 
wbxml_tree_from_wbxml(WB_UTINY * wbxml,WB_ULONG wbxml_len,WBXMLLanguage lang,WBXMLCharsetMIBEnum charset,WBXMLTree ** tree)49 WBXML_DECLARE(WBXMLError) wbxml_tree_from_wbxml(WB_UTINY *wbxml,
50                                                 WB_ULONG wbxml_len,
51                                                 WBXMLLanguage lang,
52                                                 WBXMLCharsetMIBEnum charset,
53                                                 WBXMLTree **tree)
54 {
55     WBXMLParser *wbxml_parser = NULL;
56     WB_LONG error_index = 0;
57     WBXMLTreeClbCtx wbxml_tree_clb_ctx;
58     WBXMLError ret = WBXML_OK;
59     WBXMLContentHandler wbxml_tree_content_handler =
60         {
61             wbxml_tree_clb_wbxml_start_document,
62             wbxml_tree_clb_wbxml_end_document,
63             wbxml_tree_clb_wbxml_start_element,
64             wbxml_tree_clb_wbxml_end_element,
65             wbxml_tree_clb_wbxml_characters,
66             wbxml_tree_clb_wbxml_pi
67         };
68 
69     if (tree != NULL)
70         *tree = NULL;
71 
72     /* Create WBXML Parser */
73     if((wbxml_parser = wbxml_parser_create()) == NULL) {
74         WBXML_ERROR((WBXML_PARSER, "Can't create WBXML Parser"));
75         return WBXML_ERROR_NOT_ENOUGH_MEMORY;
76     }
77 
78     /* Init context */
79     wbxml_tree_clb_ctx.error = WBXML_OK;
80     wbxml_tree_clb_ctx.current = NULL;
81     if ((wbxml_tree_clb_ctx.tree = wbxml_tree_create(WBXML_LANG_UNKNOWN, WBXML_CHARSET_UNKNOWN)) == NULL) {
82         wbxml_parser_destroy(wbxml_parser);
83         WBXML_ERROR((WBXML_PARSER, "Can't create WBXML Tree"));
84         return WBXML_ERROR_NOT_ENOUGH_MEMORY;
85     }
86 
87     /* Set Handlers Callbacks */
88     wbxml_parser_set_user_data(wbxml_parser, &wbxml_tree_clb_ctx);
89     wbxml_parser_set_content_handler(wbxml_parser, &wbxml_tree_content_handler);
90 
91     /* Give the user the possibility to force Document Language */
92     if (lang != WBXML_LANG_UNKNOWN)
93         wbxml_parser_set_language(wbxml_parser, lang);
94 
95     /* Give the user the possibility to force the document character set */
96     if (charset != WBXML_CHARSET_UNKNOWN)
97         wbxml_parser_set_meta_charset(wbxml_parser, charset);
98 
99     /* Parse the WBXML document to WBXML Tree */
100     ret = wbxml_parser_parse(wbxml_parser, wbxml, wbxml_len);
101     if ((ret != WBXML_OK) || (wbxml_tree_clb_ctx.error != WBXML_OK))
102     {
103         error_index = wbxml_parser_get_current_byte_index(wbxml_parser);
104         WBXML_ERROR((WBXML_PARSER, "WBXML Parser failed at %ld - token: %x (%s)",
105                                    error_index,
106                                    wbxml[error_index],
107                                    ret != WBXML_OK ? wbxml_errors_string(ret) : wbxml_errors_string(wbxml_tree_clb_ctx.error)));
108 
109         wbxml_tree_destroy(wbxml_tree_clb_ctx.tree);
110     }
111     else {
112         *tree = wbxml_tree_clb_ctx.tree;
113     }
114 
115     /* Clean-up */
116     wbxml_parser_destroy(wbxml_parser);
117 
118     if (ret != WBXML_OK)
119         return ret;
120     else
121         return wbxml_tree_clb_ctx.error;
122 }
123 
124 
wbxml_tree_to_wbxml(WBXMLTree * tree,WB_UTINY ** wbxml,WB_ULONG * wbxml_len,WBXMLGenWBXMLParams * params)125 WBXML_DECLARE(WBXMLError) wbxml_tree_to_wbxml(WBXMLTree *tree,
126                                               WB_UTINY **wbxml,
127                                               WB_ULONG  *wbxml_len,
128                                               WBXMLGenWBXMLParams *params)
129 {
130     WBXMLEncoder *wbxml_encoder = NULL;
131     WBXMLError ret = WBXML_OK;
132 
133     /* Encode WBXML Tree to WBXML Document */
134     if ((wbxml_encoder = wbxml_encoder_create()) == NULL) {
135         return WBXML_ERROR_NOT_ENOUGH_MEMORY;
136     }
137 
138     /* Set the WBXML Tree to encode */
139     wbxml_encoder_set_tree(wbxml_encoder, tree);
140 
141     /* Set encoder parameters */
142     if (params == NULL) {
143         /* Default Parameters */
144 
145         /* Ignores "Empty Text" Nodes */
146         wbxml_encoder_set_ignore_empty_text(wbxml_encoder, TRUE);
147 
148         /* Remove leading and trailing whitespaces in "Text Nodes" */
149         wbxml_encoder_set_remove_text_blanks(wbxml_encoder, TRUE);
150 
151         /* Use String Table */
152         wbxml_encoder_set_use_strtbl(wbxml_encoder, TRUE);
153 
154         /* Don't produce an anonymous document by default */
155         wbxml_encoder_set_produce_anonymous(wbxml_encoder, FALSE);
156     }
157     else {
158         /* WBXML Version */
159         wbxml_encoder_set_wbxml_version(wbxml_encoder, params->wbxml_version);
160 
161         /* Keep Ignorable Whitespaces ? */
162         if (!params->keep_ignorable_ws) {
163             /* Ignores "Empty Text" Nodes */
164             wbxml_encoder_set_ignore_empty_text(wbxml_encoder, TRUE);
165 
166             /* Remove leading and trailing whitespaces in "Text Nodes" */
167             wbxml_encoder_set_remove_text_blanks(wbxml_encoder, TRUE);
168         }
169 
170         /* String Table */
171         wbxml_encoder_set_use_strtbl(wbxml_encoder, params->use_strtbl);
172 
173         /* Produce an anonymous document? */
174         wbxml_encoder_set_produce_anonymous(wbxml_encoder,
175             params->produce_anonymous);
176 
177         /** @todo Add parameter to call : wbxml_encoder_set_output_charset() */
178     }
179 
180     /* Encode WBXML */
181     ret = wbxml_encoder_encode_to_wbxml(wbxml_encoder, wbxml, wbxml_len);
182 
183     /* Clean-up */
184     wbxml_encoder_destroy(wbxml_encoder);
185 
186     return ret;
187 }
188 
189 
wbxml_tree_from_xml(WB_UTINY * xml,WB_ULONG xml_len,WBXMLTree ** tree)190 WBXML_DECLARE(WBXMLError) wbxml_tree_from_xml(WB_UTINY *xml, WB_ULONG xml_len, WBXMLTree **tree)
191 {
192 #if defined( HAVE_EXPAT )
193 
194     const XML_Feature *feature_list = NULL;
195     XML_Parser         xml_parser   = NULL;
196     WBXMLError         ret          = WBXML_OK;
197     WB_BOOL            expat_utf16  = FALSE;
198     WBXMLTreeClbCtx    wbxml_tree_clb_ctx;
199 
200     if ((xml == NULL) || (xml_len == 0) || (tree == NULL))
201         return WBXML_ERROR_BAD_PARAMETER;
202 
203     /* Clean up pointer */
204     *tree = NULL;
205 
206     /* First Check if Expat is outputing UTF-16 strings */
207     feature_list = (const XML_Feature *)XML_GetFeatureList();
208 
209     if ((feature_list != NULL) && (feature_list[0].value != sizeof(WB_TINY))) {
210 #if !defined( HAVE_ICONV )
211         /* Ouch, can't convert from UTF-16 to UTF-8 */
212         return WBXML_ERROR_XMLPARSER_OUTPUT_UTF16;
213 #else
214         /* Expat returns UTF-16 encoded strings in its callbacks */
215         expat_utf16 = TRUE;
216 #endif /* !HAVE_ICONV */
217     }
218 
219     /* Create Expat XML Parser */
220     if ((xml_parser = XML_ParserCreateNS(NULL, WBXML_NAMESPACE_SEPARATOR)) == NULL)
221         return WBXML_ERROR_NOT_ENOUGH_MEMORY;
222 
223     /* Init context */
224     wbxml_tree_clb_ctx.current = NULL;
225     wbxml_tree_clb_ctx.error = WBXML_OK;
226     wbxml_tree_clb_ctx.skip_lvl = 0;
227     wbxml_tree_clb_ctx.skip_start = 0;
228     wbxml_tree_clb_ctx.xml_parser = xml_parser;
229     wbxml_tree_clb_ctx.input_buff = xml;
230     wbxml_tree_clb_ctx.expat_utf16 = expat_utf16;
231 
232     /* Create WBXML Tree */
233     if ((wbxml_tree_clb_ctx.tree = wbxml_tree_create(WBXML_LANG_UNKNOWN, WBXML_CHARSET_UNKNOWN)) == NULL) {
234         XML_ParserFree(xml_parser);
235         WBXML_ERROR((WBXML_PARSER, "Can't create WBXML Tree"));
236         return WBXML_ERROR_NOT_ENOUGH_MEMORY;
237     }
238 
239     /* Set Handlers Callbacks */
240     XML_SetXmlDeclHandler(xml_parser, wbxml_tree_clb_xml_decl);
241     XML_SetStartDoctypeDeclHandler(xml_parser, wbxml_tree_clb_xml_doctype_decl);
242     XML_SetElementHandler(xml_parser, wbxml_tree_clb_xml_start_element, wbxml_tree_clb_xml_end_element);
243     XML_SetCdataSectionHandler(xml_parser, wbxml_tree_clb_xml_start_cdata, wbxml_tree_clb_xml_end_cdata);
244     XML_SetProcessingInstructionHandler(xml_parser , wbxml_tree_clb_xml_pi);
245     XML_SetCharacterDataHandler(xml_parser, wbxml_tree_clb_xml_characters);
246     XML_SetUserData(xml_parser, (void*)&wbxml_tree_clb_ctx);
247 
248     /* Parse the XML Document to WBXML Tree */
249     if (XML_Parse(xml_parser, (WB_TINY*) xml, xml_len, TRUE) == 0)
250     {
251         WBXML_ERROR((WBXML_CONV, "xml2wbxml conversion failed - expat error %i\n"
252             "\tdescription: %s\n"
253             "\tline: %i\n"
254             "\tcolumn: %i\n"
255             "\tbyte index: %i\n"
256             "\ttotal bytes: %i\n%s",
257             XML_GetErrorCode(xml_parser),
258             XML_ErrorString(XML_GetErrorCode(xml_parser)),
259             XML_GetCurrentLineNumber(xml_parser),
260             XML_GetCurrentColumnNumber(xml_parser),
261             XML_GetCurrentByteIndex(xml_parser),
262             XML_GetCurrentByteCount(xml_parser), xml));
263 
264         wbxml_tree_destroy(wbxml_tree_clb_ctx.tree);
265 
266         ret = WBXML_ERROR_XML_PARSING_FAILED;
267     }
268     else {
269         if ((ret = wbxml_tree_clb_ctx.error) != WBXML_OK)
270         {
271             WBXML_ERROR((WBXML_CONV, "xml2wbxml conversion failed - context error %i", ret));
272             wbxml_tree_destroy(wbxml_tree_clb_ctx.tree);
273         }
274         else
275             *tree = wbxml_tree_clb_ctx.tree;
276     }
277 
278     /* Clean-up */
279     XML_ParserFree(xml_parser);
280 
281     return ret;
282 
283 #else /* HAVE_EXPAT */
284 
285 #if defined( HAVE_LIBXML )
286 
287     /** @todo Use LibXML2 SAX interface ! */
288     return WBXML_ERROR_NO_XMLPARSER;
289 
290 #else /* HAVE_LIBXML */
291 
292     /** @note You can add here another XML Parser support */
293     return WBXML_ERROR_NO_XMLPARSER;
294 
295 #endif /* HAVE_LIBXML */
296 
297 #endif /* HAVE_EXPAT */
298 }
299 
300 
wbxml_tree_to_xml(WBXMLTree * tree,WB_UTINY ** xml,WB_ULONG * xml_len,WBXMLGenXMLParams * params)301 WBXML_DECLARE(WBXMLError) wbxml_tree_to_xml(WBXMLTree *tree,
302                                             WB_UTINY **xml,
303                                             WB_ULONG  *xml_len,
304                                             WBXMLGenXMLParams *params)
305 {
306     WBXMLEncoder *wbxml_encoder = NULL;
307     WBXMLError ret = WBXML_OK;
308 
309     /* Create WBXML Encoder */
310     if ((wbxml_encoder = wbxml_encoder_create()) == NULL) {
311         return WBXML_ERROR_NOT_ENOUGH_MEMORY;
312     }
313 
314     /* Set the WBXML Tree to encode */
315     wbxml_encoder_set_tree(wbxml_encoder, tree);
316 
317     /* Set encoder parameters */
318     if (params == NULL) {
319         /* Default Values */
320 
321         /* Set XML Generation Type */
322         wbxml_encoder_set_xml_gen_type(wbxml_encoder, WBXML_GEN_XML_INDENT);
323 
324         /* Set Indent */
325         wbxml_encoder_set_indent(wbxml_encoder, 0);
326 
327         /* Skip Ignorable Whitespaces */
328         wbxml_encoder_set_ignore_empty_text(wbxml_encoder, TRUE);
329         wbxml_encoder_set_remove_text_blanks(wbxml_encoder, TRUE);
330     }
331     else {
332         /* Set XML Generation Type */
333         wbxml_encoder_set_xml_gen_type(wbxml_encoder, params->gen_type);
334 
335         /* Set Indent */
336         if (params->gen_type == WBXML_GEN_XML_INDENT)
337             wbxml_encoder_set_indent(wbxml_encoder, params->indent);
338 
339         /* Ignorable Whitespaces */
340         if (params->keep_ignorable_ws) {
341             wbxml_encoder_set_ignore_empty_text(wbxml_encoder, FALSE);
342             wbxml_encoder_set_remove_text_blanks(wbxml_encoder, FALSE);
343         }
344         else {
345             wbxml_encoder_set_ignore_empty_text(wbxml_encoder, TRUE);
346             wbxml_encoder_set_remove_text_blanks(wbxml_encoder, TRUE);
347         }
348 
349         /** @todo Add parameter to call : wbxml_encoder_set_output_charset() */
350     }
351 
352     /* Encode WBXML Tree to XML */
353     ret = wbxml_encoder_encode_tree_to_xml(wbxml_encoder, xml, xml_len);
354 
355     /* Clean-up */
356     wbxml_encoder_destroy(wbxml_encoder);
357 
358     return ret;
359 }
360 
361 
362 #if defined( HAVE_LIBXML )
363 
wbxml_tree_from_libxml_doc(xmlDocPtr libxml_doc,WBXMLTree ** tree)364 WBXML_DECLARE(WBXMLError) wbxml_tree_from_libxml_doc(xmlDocPtr libxml_doc,
365                                                      WBXMLTree **tree)
366 {
367     /** @todo wbxml_tree_from_libxml_doc() */
368     return WBXML_ERROR_NOT_IMPLEMENTED;
369 }
370 
371 
wbxml_tree_to_libxml_doc(WBXMLTree * tree,xmlDocPtr * libxml_doc)372 WBXML_DECLARE(WBXMLError) wbxml_tree_to_libxml_doc(WBXMLTree *tree,
373                                                    xmlDocPtr *libxml_doc)
374 {
375     /** @todo wbxml_tree_to_libxml_doc() */
376     return WBXML_ERROR_NOT_IMPLEMENTED;
377 }
378 
379 #endif /* HAVE_LIBXML */
380 
381 
wbxml_tree_node_create(WBXMLTreeNodeType type)382 WBXML_DECLARE(WBXMLTreeNode *) wbxml_tree_node_create(WBXMLTreeNodeType type)
383 {
384     WBXMLTreeNode *result = NULL;
385 
386     if ((result = wbxml_malloc(sizeof(WBXMLTreeNode))) == NULL)
387         return NULL;
388 
389     result->type = type;
390     result->name = NULL;
391     result->attrs = NULL;
392     result->content = NULL;
393     result->tree = NULL;
394 
395     result->parent = NULL;
396     result->children = NULL;
397     result->next = NULL;
398     result->prev = NULL;
399 
400     return result;
401 }
402 
403 
wbxml_tree_node_destroy(WBXMLTreeNode * node)404 WBXML_DECLARE(void) wbxml_tree_node_destroy(WBXMLTreeNode *node)
405 {
406     if (node == NULL)
407         return;
408 
409     wbxml_tag_destroy(node->name);
410     wbxml_list_destroy(node->attrs, wbxml_attribute_destroy_item);
411     wbxml_buffer_destroy(node->content);
412     wbxml_tree_destroy(node->tree);
413 
414     wbxml_free(node);
415 }
416 
417 
wbxml_tree_node_destroy_item(void * node)418 WBXML_DECLARE(void) wbxml_tree_node_destroy_item(void *node)
419 {
420     wbxml_tree_node_destroy((WBXMLTreeNode *)node);
421 }
422 
423 
wbxml_tree_node_destroy_all(WBXMLTreeNode * node)424 WBXML_DECLARE(void) wbxml_tree_node_destroy_all(WBXMLTreeNode *node)
425 {
426     WBXMLTreeNode *parent_node   = NULL;
427     WBXMLTreeNode *current_node  = NULL;
428     WBXMLTreeNode *previous_node = NULL;
429     WBXMLTreeNode *tmp_node      = NULL;
430     WB_BOOL        end_of_walk   = FALSE;
431 
432     if (node == NULL)
433         return;
434 
435     /* Let's go through the sub-tree (iteratively) to free all the nodes */
436     current_node = node;
437     parent_node  = node->parent;
438 
439     while (!end_of_walk)
440     {
441         if (current_node == NULL) {
442             /* Leaf reached */
443             if (previous_node == NULL) {
444                 end_of_walk = TRUE;
445                 break;
446             }
447             else {
448                 if (previous_node->parent == parent_node) {
449                     /* End of parsing, we have parsed the last child of node */
450                     end_of_walk = TRUE;
451                     break;
452                 }
453                 else {
454                     /* Let's parse next child of parent node */
455                     current_node = previous_node->next;
456                     tmp_node = previous_node->parent;
457 
458                     /* Destroy this node (leaf) */
459                     wbxml_tree_node_destroy(previous_node);
460 
461                     previous_node = tmp_node;
462                 }
463             }
464         }
465         else {
466             /* Go deeper in sub-tree */
467             previous_node = current_node;
468             current_node = current_node->children;
469         }
470     }
471 
472     wbxml_tree_node_destroy(node);
473 }
474 
475 
wbxml_tree_node_create_xml_elt(const WBXMLLangEntry * lang_table,const WB_UTINY * name)476 WBXML_DECLARE(WBXMLTreeNode *) wbxml_tree_node_create_xml_elt(const WBXMLLangEntry *lang_table,
477                                                               const WB_UTINY *name)
478 {
479     const WBXMLTagEntry *tag_entry = NULL;
480     WBXMLTreeNode *node = NULL;
481     WBXMLTag *tag = NULL;
482 
483     /* Search for XML Tag Name in Table */
484     if ((tag_entry = wbxml_tables_get_tag_from_xml(lang_table, -1, name)) != NULL) {
485         /* Found : token tag */
486         tag = wbxml_tag_create_token(tag_entry);
487     }
488     else {
489         /* Not found : literal tag */
490         tag = wbxml_tag_create_literal((WB_UTINY *)name);
491     }
492 
493     if (tag == NULL)
494         return NULL;
495 
496     /* Create a new Node */
497     if ((node = wbxml_tree_node_create(WBXML_TREE_ELEMENT_NODE)) == NULL) {
498         wbxml_tag_destroy(tag);
499         return NULL;
500     }
501 
502     /* Set Node Tag */
503     node->name = tag;
504 
505     return node;
506 }
507 
508 
wbxml_tree_node_create_xml_elt_with_text(const WBXMLLangEntry * lang_table,const WB_UTINY * name,const WB_UTINY * text,WB_ULONG len)509 WBXML_DECLARE(WBXMLTreeNode *) wbxml_tree_node_create_xml_elt_with_text(const WBXMLLangEntry *lang_table,
510                                                                         const WB_UTINY *name,
511                                                                         const WB_UTINY *text,
512                                                                         WB_ULONG len)
513 {
514     WBXMLTreeNode *node = NULL;
515     WBXMLTreeNode *text_node = NULL;
516 
517     /* Create element node */
518     if ((node = wbxml_tree_node_create_xml_elt(lang_table, name)) == NULL)
519         return NULL;
520 
521     /* Create text node */
522     if ((text_node = wbxml_tree_node_create_text(text, len)) == NULL) {
523         wbxml_tree_node_destroy(node);
524         return NULL;
525     }
526 
527     /* Add text node to element node */
528     if (!wbxml_tree_node_add_child(node, text_node)) {
529         wbxml_tree_node_destroy(node);
530         wbxml_tree_node_destroy(text_node);
531         return NULL;
532     }
533 
534     return node;
535 }
536 
537 
wbxml_tree_node_create_text(const WB_UTINY * text,WB_ULONG len)538 WBXML_DECLARE(WBXMLTreeNode *) wbxml_tree_node_create_text(const WB_UTINY *text,
539                                                            WB_ULONG len)
540 {
541     WBXMLTreeNode *node = NULL;
542 
543     /* Create a new Node */
544     if ((node = wbxml_tree_node_create(WBXML_TREE_TEXT_NODE)) == NULL) {
545         return NULL;
546     }
547 
548     /* Set Content */
549     if ((node->content = wbxml_buffer_create(text, len, len)) == NULL) {
550         wbxml_tree_node_destroy(node);
551         return NULL;
552     }
553 
554     return node;
555 }
556 
557 
wbxml_tree_node_create_cdata(const WB_UTINY * text,WB_ULONG len)558 WBXML_DECLARE(WBXMLTreeNode *) wbxml_tree_node_create_cdata(const WB_UTINY *text,
559                                                             WB_ULONG len)
560 {
561     WBXMLTreeNode *node = NULL;
562     WBXMLTreeNode *text_node = NULL;
563 
564     /* Create a new node */
565     if ((node = wbxml_tree_node_create(WBXML_TREE_CDATA_NODE)) == NULL) {
566         return NULL;
567     }
568 
569     /* Create a text node */
570     if ((text_node = wbxml_tree_node_create_text(text, len)) == NULL) {
571         wbxml_tree_node_destroy(node);
572         return NULL;
573     }
574 
575     /* Add text node to cdata */
576     if (!wbxml_tree_node_add_child(node, text_node)) {
577         wbxml_tree_node_destroy_all(node);
578         node = NULL;
579     }
580 
581     return node;
582 }
583 
584 
wbxml_tree_node_create_tree(WBXMLTreeNode * root,WBXMLLanguage lang,WBXMLCharsetMIBEnum orig_charset)585 WBXML_DECLARE(WBXMLTreeNode *) wbxml_tree_node_create_tree(WBXMLTreeNode *root,
586                                                            WBXMLLanguage lang,
587                                                            WBXMLCharsetMIBEnum orig_charset)
588 {
589     WBXMLTreeNode* result = NULL;
590     WBXMLTree*     tree   = NULL;
591 
592     if ((root == NULL) || (lang == WBXML_LANG_UNKNOWN))
593         return NULL;
594 
595     /* Create Tree */
596     if ((tree = wbxml_tree_create(lang, orig_charset)) == NULL)
597         return NULL;
598 
599     /* Fill Tree */
600     tree->root = root;
601 
602     /* Create Tree Node */
603     if ((result = wbxml_tree_node_create(WBXML_TREE_TREE_NODE)) == NULL) {
604         wbxml_tree_destroy(tree);
605         return NULL;
606     }
607 
608     /* Fill Tree Node */
609     result->tree = tree;
610 
611     return result;
612 }
613 
614 
wbxml_tree_node_add_child(WBXMLTreeNode * parent,WBXMLTreeNode * node)615 WBXML_DECLARE(WB_BOOL) wbxml_tree_node_add_child(WBXMLTreeNode *parent,
616                                                  WBXMLTreeNode *node)
617 {
618     WBXMLTreeNode *tmp = NULL;
619 
620     if ((parent == NULL) || (node == NULL))
621         return FALSE;
622 
623     /* Set parent to new node */
624     node->parent = parent;
625 
626     /* Search for previous sibbling element */
627     if (parent->children != NULL) {
628         /* Add this Node to end of Sibbling Node list of Parent */
629         tmp = parent->children;
630 
631         while (tmp->next != NULL)
632             tmp = tmp->next;
633 
634         node->prev = tmp;
635         tmp->next = node;
636     }
637     else {
638         /* No previous sibbling element */
639         parent->children = node;
640     }
641 
642     return TRUE;
643 }
644 
645 
wbxml_tree_node_add_attr(WBXMLTreeNode * node,WBXMLAttribute * attr)646 WBXML_DECLARE(WBXMLError) wbxml_tree_node_add_attr(WBXMLTreeNode *node,
647                                                    WBXMLAttribute *attr)
648 {
649     WBXMLAttribute *new_attr = NULL;
650 
651     if ((node == NULL) || (attr == NULL)) {
652         return WBXML_ERROR_BAD_PARAMETER;
653     }
654 
655     /* Create list if needed */
656     if (node->attrs == NULL) {
657         if ((node->attrs = wbxml_list_create()) == NULL) {
658             return WBXML_ERROR_NOT_ENOUGH_MEMORY;
659         }
660     }
661 
662     /* Duplicate Attribute */
663     if ((new_attr = wbxml_attribute_duplicate(attr)) == NULL)
664         return WBXML_ERROR_NOT_ENOUGH_MEMORY;
665 
666     /* Add attribute to list */
667     if (!wbxml_list_append(node->attrs, new_attr)) {
668         wbxml_attribute_destroy(attr);
669         return WBXML_ERROR_NOT_ENOUGH_MEMORY;
670     }
671 
672     return WBXML_OK;
673 }
674 
675 
wbxml_tree_node_add_attrs(WBXMLTreeNode * node,WBXMLAttribute ** attrs)676 WBXML_DECLARE(WBXMLError) wbxml_tree_node_add_attrs(WBXMLTreeNode *node,
677                                                     WBXMLAttribute **attrs)
678 {
679     WB_ULONG i = 0;
680 
681     if ((node == NULL) || (attrs == NULL)) {
682         return WBXML_ERROR_BAD_PARAMETER;
683     }
684 
685     while (attrs[i] != NULL) {
686         /* Add attribute */
687         if (wbxml_tree_node_add_attr(node, attrs[i]) != WBXML_OK)
688             return WBXML_ERROR_NOT_ENOUGH_MEMORY;
689 
690         i++;
691     }
692 
693     return WBXML_OK;
694 }
695 
696 
wbxml_tree_node_add_xml_attr(const WBXMLLangEntry * lang_table,WBXMLTreeNode * node,const WB_UTINY * name,const WB_UTINY * value)697 WBXML_DECLARE(WBXMLError) wbxml_tree_node_add_xml_attr(const WBXMLLangEntry *lang_table,
698                                                        WBXMLTreeNode *node,
699                                                        const WB_UTINY *name,
700                                                        const WB_UTINY *value)
701 {
702     WBXMLAttribute *attr = NULL;
703     const WBXMLAttrEntry *attr_entry = NULL;
704 
705     /* Create list if needed */
706     if (node->attrs == NULL) {
707         if ((node->attrs = wbxml_list_create()) == NULL) {
708             return WBXML_ERROR_NOT_ENOUGH_MEMORY;
709         }
710     }
711 
712     /* Create Attribute */
713     if ((attr = wbxml_attribute_create()) == NULL)
714         return WBXML_ERROR_NOT_ENOUGH_MEMORY;
715 
716     /* Set Attribute Name */
717     if ((attr_entry = wbxml_tables_get_attr_from_xml(lang_table, (WB_UTINY *)name, (WB_UTINY *)value, NULL)) != NULL)
718         attr->name = wbxml_attribute_name_create_token(attr_entry);
719     else
720         attr->name = wbxml_attribute_name_create_literal((WB_UTINY *)name);
721 
722     if (attr->name == NULL) {
723         wbxml_attribute_destroy(attr);
724         return WBXML_ERROR_NOT_ENOUGH_MEMORY;
725     }
726 
727     /* Set Attribute Value */
728     attr->value = wbxml_buffer_create_real(value, WBXML_STRLEN(value), WBXML_STRLEN(value));
729     if (attr->value == NULL) {
730         wbxml_attribute_destroy(attr);
731         return WBXML_ERROR_NOT_ENOUGH_MEMORY;
732     }
733 
734     /* Add attribute to list */
735     if (!wbxml_list_append(node->attrs, attr)) {
736         wbxml_attribute_destroy(attr);
737         return WBXML_ERROR_NOT_ENOUGH_MEMORY;
738     }
739 
740     return WBXML_OK;
741 }
742 
743 
wbxml_tree_node_add_xml_attrs(const WBXMLLangEntry * lang_table,WBXMLTreeNode * node,const WB_UTINY ** attrs)744 WBXML_DECLARE(WBXMLError) wbxml_tree_node_add_xml_attrs(const WBXMLLangEntry *lang_table,
745                                                         WBXMLTreeNode *node,
746                                                         const WB_UTINY **attrs)
747 {
748     const WB_UTINY **p = attrs;
749 
750     if ((lang_table == NULL) || (node == NULL) || (attrs == NULL))
751         return WBXML_ERROR_BAD_PARAMETER;
752 
753     while (p && *p) {
754         /* Add attribute */
755         if (wbxml_tree_node_add_xml_attr(lang_table, node, *p, *(p+1)) != WBXML_OK)
756             return WBXML_ERROR_NOT_ENOUGH_MEMORY;
757 
758         p += 2;
759     }
760 
761     return WBXML_OK;
762 }
763 
764 
wbxml_tree_node_elt_get_from_name(WBXMLTreeNode * node,const char * name,WB_BOOL recurs)765 WBXML_DECLARE(WBXMLTreeNode *) wbxml_tree_node_elt_get_from_name(WBXMLTreeNode *node, const char *name, WB_BOOL recurs)
766 {
767     WBXMLTreeNode *current_node = NULL;
768     WBXMLTreeNode *recurs_node = NULL;
769 
770     if ((node == NULL) || (name == NULL))
771         return NULL;
772 
773     /* Let's go through the tree */
774     current_node = node;
775 
776     while (current_node != NULL)
777     {
778         /* Is this a normal node? */
779         if (current_node->type == WBXML_TREE_ELEMENT_NODE)
780         {
781             /* Is this the Node we searched ? */
782             if (WBXML_STRCMP(wbxml_tag_get_xml_name(current_node->name), name) == 0)
783             {
784                 return current_node;
785             }
786 
787             /* Sould we start a recursive search? */
788             if (recurs && current_node->children)
789             {
790                 recurs_node = wbxml_tree_node_elt_get_from_name(current_node->children, name, TRUE);
791                 /* Is this the Node we searched ? */
792                 if (recurs_node)
793                 {
794                     return recurs_node;
795                 }
796             }
797         }
798 
799         /* Go to next Sibbling Node */
800         current_node = current_node->next;
801     }
802 
803     /* A node with the specified name could not be found. */
804     return NULL;
805 }
806 
807 
808 #if defined ( WBXML_SUPPORT_SYNCML )
809 
wbxml_tree_node_get_syncml_data_type(WBXMLTreeNode * node)810 WBXML_DECLARE(WBXMLSyncMLDataType) wbxml_tree_node_get_syncml_data_type(WBXMLTreeNode *node)
811 {
812     WBXMLTreeNode *tmp_node = NULL;
813 
814     if (node == NULL)
815         return WBXML_SYNCML_DATA_TYPE_NORMAL;
816 
817     /* If we are in a CDATA node then we must look into the parent node. */
818     if (node->type == WBXML_TREE_CDATA_NODE)
819         node = node->parent;
820 
821     /* Are we in a <Data> ? */
822     if ((node->type == WBXML_TREE_ELEMENT_NODE) &&
823         (node->name != NULL) &&
824         (WBXML_STRCMP(wbxml_tag_get_xml_name(node->name), "Data") == 0))
825     {
826         /* Go to Parent element (or Parent of Parent) and search for <Meta> then <Type> */
827         if (((node->parent != NULL) &&
828              (node->parent->children != NULL) &&
829              ((tmp_node = wbxml_tree_node_elt_get_from_name(node->parent->children, "Meta", FALSE)) != NULL) &&
830              ((tmp_node = wbxml_tree_node_elt_get_from_name(tmp_node->children, "Type", FALSE)) != NULL)) ||
831             (((node->parent != NULL) &&
832               (node->parent->parent != NULL) &&
833               (node->parent->parent->children != NULL) &&
834               ((tmp_node = wbxml_tree_node_elt_get_from_name(node->parent->parent->children, "Meta", FALSE)) != NULL)) &&
835               ((tmp_node = wbxml_tree_node_elt_get_from_name(tmp_node->children, "Type", FALSE)) != NULL)))
836         {
837             /* Check <Type> value */
838             if ((tmp_node->children != NULL) && (tmp_node->children->type == WBXML_TREE_TEXT_NODE)) {
839                 /* This function is used by wbxml and xml callbacks.
840                  * So content types must be handled for both situations.
841                  */
842 
843                 /* application/vnd.syncml-devinf+wbxml */
844                 if (wbxml_buffer_compare_cstr(tmp_node->children->content, "application/vnd.syncml-devinf+wbxml") == 0) {
845                     return WBXML_SYNCML_DATA_TYPE_WBXML;
846                 }
847 
848                 /* application/vnd.syncml-devinf+xml */
849                 if (wbxml_buffer_compare_cstr(tmp_node->children->content, "application/vnd.syncml-devinf+xml") == 0) {
850                     return WBXML_SYNCML_DATA_TYPE_NORMAL;
851                 }
852 
853                 /* application/vnd.syncml.dmtnds+wbxml */
854                 if (wbxml_buffer_compare_cstr(tmp_node->children->content, "application/vnd.syncml.dmtnds+wbxml") == 0) {
855                     return WBXML_SYNCML_DATA_TYPE_WBXML;
856                 }
857 
858                 /* application/vnd.syncml.dmtnds+xml */
859                 if (wbxml_buffer_compare_cstr(tmp_node->children->content, "application/vnd.syncml.dmtnds+xml") == 0) {
860                     return WBXML_SYNCML_DATA_TYPE_NORMAL;
861                 }
862 
863                 /* text/clear */
864                 if (wbxml_buffer_compare_cstr(tmp_node->children->content, "text/clear") == 0) {
865                     return WBXML_SYNCML_DATA_TYPE_CLEAR;
866                 }
867 
868                 /* text/directory;profile=vCard */
869                 if (wbxml_buffer_compare_cstr(tmp_node->children->content, "text/directory;profile=vCard") == 0) {
870                     return WBXML_SYNCML_DATA_TYPE_DIRECTORY_VCARD;
871                 }
872 
873                 /* text/x-vcard */
874                 if (wbxml_buffer_compare_cstr(tmp_node->children->content, "text/x-vcard") == 0) {
875                     return WBXML_SYNCML_DATA_TYPE_VCARD;
876                 }
877 
878                 /* text/x-vcalendar */
879                 if (wbxml_buffer_compare_cstr(tmp_node->children->content, "text/x-vcalendar") == 0) {
880                     return WBXML_SYNCML_DATA_TYPE_VCALENDAR;
881                 }
882             }
883         }
884 
885         /**
886          * Hack: we assume that any <Data> inside a <Replace> or <Add> Item is a vObject (vCard / vCal / ...).
887          *
888          * This is because when parsing a <Data> content we really need to put a CDATA, event if we don't really
889          * know the content-type. For example when receiving the end of a splitted vObject with Samsung D600, we receive this:
890          *
891          * 	      <Replace>
892          * 	        <CmdID>162</CmdID>
893          * 	        <Item>
894          * 	          <Source>
895          * 	            <LocURI>./690</LocURI>
896          * 	          </Source>
897          * 	          <Data>EF;CELL:0661809055
898          * 	TEL;HOME:0299783886
899          * 	X-IRMC-LUID:690
900          * 	END:VCARD</Data>
901          * 	        </Item>
902          * 	      </Replace>
903          *
904          * There is no <Meta> info to find the content-type of the <Data>.
905          */
906         if ( (node->parent != NULL) &&
907              (node->parent->parent != NULL) &&
908              (node->parent->parent->name != NULL) &&
909              ((WBXML_STRCMP(wbxml_tag_get_xml_name(node->parent->parent->name), "Add") == 0) ||
910               (WBXML_STRCMP(wbxml_tag_get_xml_name(node->parent->parent->name), "Replace") == 0)) )
911         {
912             return WBXML_SYNCML_DATA_TYPE_VOBJECT;
913         }
914     }
915 
916     return WBXML_SYNCML_DATA_TYPE_NORMAL;
917 }
918 
919 #endif /* WBXML_SUPPORT_SYNCML */
920 
921 
wbxml_tree_node_have_child_elt(WBXMLTreeNode * node)922 WBXML_DECLARE(WB_BOOL) wbxml_tree_node_have_child_elt(WBXMLTreeNode *node)
923 {
924     WBXMLTreeNode *current = NULL;
925 
926     if (node != NULL) {
927         /* Get first child */
928         current = node->children;
929 
930         while (current != NULL) {
931             if (current->type == WBXML_TREE_ELEMENT_NODE) {
932                 /* Element Node found ! */
933                 return TRUE;
934             }
935 
936             /* Check next child */
937             current = current->next;
938         }
939     }
940 
941     return FALSE;
942 }
943 
944 
wbxml_tree_node_get_all_children(WBXMLTreeNode * node)945 WBXML_DECLARE(WBXMLList*) wbxml_tree_node_get_all_children(WBXMLTreeNode *node)
946 {
947     WBXMLList* result = NULL;
948 
949     if ( node == NULL )
950         return NULL;
951 
952     node = node->children;
953 
954     while ( node != NULL ) {
955         /* Create result list if not already done */
956         if ( result == NULL )
957             result = wbxml_list_create();
958 
959         /* Append node to result */
960         wbxml_list_append(result, node);
961 
962         /* Go to next node */
963         node = node->next;
964     }
965 
966     return result;
967 }
968 
969 
wbxml_tree_create(WBXMLLanguage lang,WBXMLCharsetMIBEnum orig_charset)970 WBXML_DECLARE(WBXMLTree *) wbxml_tree_create(WBXMLLanguage lang,
971                                              WBXMLCharsetMIBEnum orig_charset)
972 {
973     WBXMLTree *result = NULL;
974 
975     if ((result = wbxml_malloc(sizeof(WBXMLTree))) == NULL)
976         return NULL;
977 
978     result->lang = wbxml_tables_get_table(lang);
979     result->root = NULL;
980     result->orig_charset = orig_charset;
981     result->cur_code_page = 0;
982 
983     return result;
984 }
985 
986 
wbxml_tree_destroy(WBXMLTree * tree)987 WBXML_DECLARE(void) wbxml_tree_destroy(WBXMLTree *tree)
988 {
989     if (tree != NULL) {
990         /* Destroy root node and all its children */
991         wbxml_tree_node_destroy_all(tree->root);
992 
993         /* Free tree */
994         wbxml_free(tree);
995     }
996 }
997 
998 
999 /** @todo Rewrite this function (use wbxml_tree_node_* functions) */
wbxml_tree_add_node(WBXMLTree * tree,WBXMLTreeNode * parent,WBXMLTreeNode * node)1000 WBXML_DECLARE(WB_BOOL) wbxml_tree_add_node(WBXMLTree *tree, WBXMLTreeNode *parent, WBXMLTreeNode *node)
1001 {
1002     WBXMLTreeNode *tmp = NULL;
1003 
1004     if ((tree == NULL) || (node == NULL))
1005         return FALSE;
1006 
1007     /* Set parent to new node */
1008     node->parent = parent;
1009 
1010     /* Check if this is the Root Element */
1011     if (parent != NULL) {
1012         /* This is not the Root Element... search for previous sibbling element */
1013         if (parent->children != NULL) {
1014             /* Add this Node to end of Sibbling Node list of Parent */
1015             tmp = parent->children;
1016 
1017             /* !!! WARNING !!!
1018              * EXPAT splits &lt;html&gt; into three separate text nodes.
1019              * Therefore it is necessary to scan for splitted text nodes and
1020              * join them to get consistent text nodes.
1021              */
1022 
1023             /* If the handled node is a text node and the last node is a text node
1024              * then the last node must be replace.
1025              * Otherwise the node will be appended.
1026              */
1027             while (tmp->next != NULL)
1028                 tmp = tmp->next;
1029 
1030 	    if (node->type == WBXML_TREE_TEXT_NODE &&
1031                 tmp->type == WBXML_TREE_TEXT_NODE) {
1032 
1033                 /* join the two text nodes and replace the present text node */
1034                 if (!wbxml_buffer_append(tmp->content, node->content))
1035                     return FALSE;
1036 
1037 		if (tmp->prev == NULL) {
1038                     /* tmp is first child */
1039                     parent->children = node;
1040                 } else {
1041                     /* tmp is not first child */
1042                     tmp->prev->next = node;
1043                     node->prev = tmp->prev;
1044                 }
1045 
1046                 wbxml_buffer_destroy(node->content);
1047                 node->content = tmp->content;
1048                 tmp->content = NULL;
1049                 wbxml_tree_node_destroy(tmp);
1050             } else {
1051                 /* normal situation => append node */
1052                 node->prev = tmp;
1053                 tmp->next = node;
1054             }
1055         }
1056         else {
1057             /* No previous sibbling element */
1058             parent->children = node;
1059         }
1060     }
1061     else {
1062         /* We do NOT allow replacement of an existing Tree Node */
1063         if (tree->root != NULL)
1064             return FALSE;
1065 
1066         /* This is the Root Element */
1067         tree->root = node;
1068     }
1069 
1070     return TRUE;
1071 }
1072 
1073 
1074 /** @todo Rewrite this function (use wbxml_tree_node_* functions) */
wbxml_tree_extract_node(WBXMLTree * tree,WBXMLTreeNode * node)1075 WBXML_DECLARE(WBXMLError) wbxml_tree_extract_node(WBXMLTree *tree,
1076                                                   WBXMLTreeNode *node)
1077 {
1078     if ((tree == NULL) || (node == NULL))
1079         return WBXML_ERROR_BAD_PARAMETER;
1080 
1081     /* Parent link */
1082     if (node->parent != NULL) {
1083         if (node->parent->children == node) {
1084             /* Update parent children */
1085 		    node->parent->children = node->next;
1086         }
1087 
1088         /* No more parent */
1089         node->parent = NULL;
1090     }
1091     else {
1092         /* Root removed ! */
1093         tree->root = node->next;
1094     }
1095 
1096     /* Link next node to previous node */
1097     if (node->next != NULL)
1098         node->next->prev = node->prev;
1099 
1100     /* Link previous node to next node */
1101     if (node->prev != NULL)
1102         node->prev->next = node->next;
1103 
1104     /* Cleanup pointers */
1105     node->next = node->prev = NULL;
1106 
1107     return WBXML_OK;
1108 }
1109 
1110 
1111 /** @todo Rewrite this function (use wbxml_tree_node_* functions) */
wbxml_tree_add_elt(WBXMLTree * tree,WBXMLTreeNode * parent,WBXMLTag * tag)1112 WBXML_DECLARE(WBXMLTreeNode *) wbxml_tree_add_elt(WBXMLTree *tree,
1113                                                   WBXMLTreeNode *parent,
1114                                                   WBXMLTag *tag)
1115 {
1116     WBXMLTreeNode *node = NULL;
1117 
1118     /* Create a new Node */
1119     if ((node = wbxml_tree_node_create(WBXML_TREE_ELEMENT_NODE)) == NULL) {
1120         return NULL;
1121     }
1122 
1123     /* Set Element */
1124     if ((node->name = wbxml_tag_duplicate(tag)) == NULL) {
1125         wbxml_tree_node_destroy(node);
1126         return NULL;
1127     }
1128 
1129     /* Add this Node to Tree  */
1130     if (!wbxml_tree_add_node(tree, parent, node)) {
1131         wbxml_tree_node_destroy(node);
1132         return NULL;
1133     }
1134 
1135     return node;
1136 }
1137 
1138 
1139 /** @todo Rewrite this function (use wbxml_tree_node_* functions) */
wbxml_tree_add_elt_with_attrs(WBXMLTree * tree,WBXMLTreeNode * parent,WBXMLTag * tag,WBXMLAttribute ** attrs)1140 WBXML_DECLARE(WBXMLTreeNode *) wbxml_tree_add_elt_with_attrs(WBXMLTree *tree,
1141                                                              WBXMLTreeNode *parent,
1142                                                              WBXMLTag *tag,
1143                                                              WBXMLAttribute **attrs)
1144 {
1145     WBXMLTreeNode *node = NULL;
1146 
1147     /* Add element */
1148     if ((node = wbxml_tree_add_elt(tree, parent, tag)) == NULL) {
1149         return NULL;
1150     }
1151 
1152     /* Add attributes to element */
1153     if ((attrs != NULL) && (*attrs != NULL)) {
1154         if (wbxml_tree_node_add_attrs(node, attrs) != WBXML_OK) {
1155             /* Remove node from Tree */
1156             wbxml_tree_extract_node(tree, node);
1157             wbxml_tree_node_destroy(node);
1158             return NULL;
1159         }
1160     }
1161 
1162     return node;
1163 }
1164 
1165 
1166 /** @todo Rewrite this function (use wbxml_tree_node_* functions) */
wbxml_tree_add_xml_elt(WBXMLTree * tree,WBXMLTreeNode * parent,WB_UTINY * name)1167 WBXML_DECLARE(WBXMLTreeNode *) wbxml_tree_add_xml_elt(WBXMLTree *tree,
1168                                                       WBXMLTreeNode *parent,
1169                                                       WB_UTINY *name)
1170 {
1171     const WBXMLTagEntry *tag_entry = NULL;
1172     WBXMLTreeNode *node = NULL;
1173     WBXMLTag *tag = NULL;
1174     WB_UTINY *sep = NULL;
1175     const WB_UTINY *namespace_name = NULL;
1176     WB_UTINY *element_name = NULL;
1177 
1178     /* Separate the namespace from the element name */
1179     sep = (WB_UTINY *)strrchr((const WB_TINY *) name, WBXML_NAMESPACE_SEPARATOR);
1180     if (sep != NULL) {
1181         /* Temporarily split the string by changing the separater to a null-terminator */
1182         *sep = '\0';
1183 
1184         namespace_name = name;
1185         element_name = sep+1;
1186     }
1187     else {
1188         /* No namespace, so just set it to an empty string (specifically, the null-terminator at the end of the elemet name */
1189         namespace_name = name + strlen((const WB_TINY *) name);
1190         element_name = name;
1191     }
1192 
1193     WBXML_DEBUG((WBXML_CONV, "Parsed element name: Namespace='%s', Element='%s'", namespace_name, element_name));
1194 
1195     /* Update the current code page to match the one specified by the namespace */
1196     tree->cur_code_page = wbxml_tables_get_code_page(tree->lang->nsTable, (const WB_TINY *) namespace_name);
1197 
1198     /* Search for XML Tag Name in Table */
1199     if ((tag_entry = wbxml_tables_get_tag_from_xml(tree->lang, tree->cur_code_page, element_name)) != NULL) {
1200         tree->cur_code_page = tag_entry->wbxmlCodePage;
1201 
1202         /* Found : token tag */
1203         tag = wbxml_tag_create_token(tag_entry);
1204     }
1205     else {
1206         /* Not found : literal tag */
1207         tag = wbxml_tag_create_literal(element_name);
1208     }
1209 
1210     if (sep != NULL) {
1211         /* We are done with the element and namespace names, so put the separator character back */
1212         *sep = WBXML_NAMESPACE_SEPARATOR;
1213     }
1214 
1215     if (tag == NULL)
1216         return NULL;
1217 
1218     /* Create a new Node */
1219     if ((node = wbxml_tree_node_create(WBXML_TREE_ELEMENT_NODE)) == NULL) {
1220         wbxml_tag_destroy(tag);
1221         return NULL;
1222     }
1223 
1224     /* Set Node Tag */
1225     node->name = tag;
1226 
1227     /* Add this Node to Tree  */
1228     if (!wbxml_tree_add_node(tree, parent, node)) {
1229         wbxml_tree_node_destroy(node);
1230         return NULL;
1231     }
1232 
1233     return node;
1234 }
1235 
1236 
1237 /** @todo Rewrite this function (use wbxml_tree_node_* functions) */
wbxml_tree_add_xml_elt_with_attrs(WBXMLTree * tree,WBXMLTreeNode * parent,WB_UTINY * name,const WB_UTINY ** attrs)1238 WBXML_DECLARE(WBXMLTreeNode *) wbxml_tree_add_xml_elt_with_attrs(WBXMLTree *tree,
1239                                                                  WBXMLTreeNode *parent,
1240                                                                  WB_UTINY *name,
1241                                                                  const WB_UTINY **attrs)
1242 {
1243     WBXMLTreeNode *node = NULL;
1244 
1245     /* Add element */
1246     if ((node = wbxml_tree_add_xml_elt(tree, parent, name)) == NULL) {
1247         return NULL;
1248     }
1249 
1250     /* Add attributes to element */
1251     if ((attrs != NULL) && (*attrs != NULL)) {
1252         if (wbxml_tree_node_add_xml_attrs(tree->lang, node, attrs) != WBXML_OK) {
1253             /* Remove node from Tree */
1254             wbxml_tree_extract_node(tree, node);
1255             wbxml_tree_node_destroy(node);
1256             return NULL;
1257         }
1258     }
1259 
1260     return node;
1261 }
1262 
1263 
1264 /** @todo Rewrite this function (use wbxml_tree_node_* functions) */
wbxml_tree_add_text(WBXMLTree * tree,WBXMLTreeNode * parent,const WB_UTINY * text,WB_ULONG len)1265 WBXML_DECLARE(WBXMLTreeNode *) wbxml_tree_add_text(WBXMLTree *tree,
1266                                                    WBXMLTreeNode *parent,
1267                                                    const WB_UTINY *text,
1268                                                    WB_ULONG len)
1269 {
1270     WBXMLTreeNode *node = NULL;
1271 
1272     /* Create a new Node */
1273     if ((node = wbxml_tree_node_create(WBXML_TREE_TEXT_NODE)) == NULL) {
1274         return NULL;
1275     }
1276 
1277     /* Set Content */
1278     if ((node->content = wbxml_buffer_create(text, len, len)) == NULL) {
1279         wbxml_tree_node_destroy(node);
1280         return NULL;
1281     }
1282 
1283     /* Add this Node to Tree  */
1284     if (!wbxml_tree_add_node(tree, parent, node)) {
1285         wbxml_tree_node_destroy(node);
1286         return NULL;
1287     }
1288 
1289     return node;
1290 }
1291 
1292 
1293 /** @todo Rewrite this function (use wbxml_tree_node_* functions) */
wbxml_tree_add_cdata(WBXMLTree * tree,WBXMLTreeNode * parent)1294 WBXML_DECLARE(WBXMLTreeNode *) wbxml_tree_add_cdata(WBXMLTree *tree,
1295                                                     WBXMLTreeNode *parent)
1296 {
1297     WBXMLTreeNode *node = NULL;
1298 
1299     /* Create a new Node */
1300     if ((node = wbxml_tree_node_create(WBXML_TREE_CDATA_NODE)) == NULL) {
1301         return NULL;
1302     }
1303 
1304     /* Add this Node to Tree  */
1305     if (!wbxml_tree_add_node(tree, parent, node)) {
1306         wbxml_tree_node_destroy(node);
1307         return NULL;
1308     }
1309 
1310     return node;
1311 }
1312 
1313 
1314 /** @todo wbxml_tree_add_cdata_with_text() */
1315 
1316 
1317 /** @todo Rewrite this function (use wbxml_tree_node_* functions) */
wbxml_tree_add_tree(WBXMLTree * tree,WBXMLTreeNode * parent,WBXMLTree * new_tree)1318 WBXML_DECLARE(WBXMLTreeNode *) wbxml_tree_add_tree(WBXMLTree *tree,
1319                                                    WBXMLTreeNode *parent,
1320                                                    WBXMLTree *new_tree)
1321 {
1322     WBXMLTreeNode *node = NULL;
1323 
1324     /* Create a new Node */
1325     if ((node = wbxml_tree_node_create(WBXML_TREE_TREE_NODE)) == NULL) {
1326         return NULL;
1327     }
1328 
1329     /* Add this Node to Tree  */
1330     if (!wbxml_tree_add_node(tree, parent, node)) {
1331         wbxml_tree_node_destroy(node);
1332         return NULL;
1333     }
1334 
1335     /* Set Tree */
1336     node->tree = new_tree;
1337 
1338     return node;
1339 }
1340 
1341 
1342 /** @todo Rewrite this function (use wbxml_tree_node_* functions) */
wbxml_tree_add_xml_elt_with_attrs_and_text(WBXMLTree * tree,WBXMLTreeNode * parent,WB_UTINY * name,const WB_UTINY ** attrs,const WB_UTINY * text,WB_ULONG len)1343 WBXML_DECLARE(WBXMLTreeNode *) wbxml_tree_add_xml_elt_with_attrs_and_text(WBXMLTree *tree,
1344                                                                           WBXMLTreeNode *parent,
1345                                                                           WB_UTINY *name,
1346                                                                           const WB_UTINY **attrs,
1347                                                                           const WB_UTINY *text,
1348                                                                           WB_ULONG len)
1349 {
1350     WBXMLTreeNode *new_node = NULL;
1351 
1352     /* Add XML node */
1353     if ((new_node = wbxml_tree_add_xml_elt_with_attrs(tree, parent, name, attrs)) == NULL)
1354         return NULL;
1355 
1356     /* Add text node */
1357     if ((text != NULL) && (len > 0)) {
1358         if (wbxml_tree_add_text(tree, new_node, text, len) == NULL) {
1359             wbxml_tree_node_destroy(new_node);
1360             return NULL;
1361         }
1362     }
1363 
1364     return new_node;
1365 }
1366