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_encoder.c
28 * @ingroup wbxml_encoder
29 *
30 * @author Aymerick Jehanne <aymerick@jehanne.org>
31 * @date 11/11/02
32 *
33 * @brief WBXML Encoder - Encodes a WBXML Tree to WBXML or to XML
34 *
35 * @note Inspired from kannel WML Encoder (http://www.kannel.org)
36 *
37 * @note [OMA WV 1.1] : OMA-WV-CSP_WBXML-V1_1-20021001-A.pdf
38 *
39 * @todo Parse CDDATA
40 * @todo Parse PI
41 * @todo Handle Charsets Encoding
42 * @todo Really generate ENTITY tokens
43 * @todo Handle Namespaces !
44 * @todo For canonical XML output: Sort the Attributes
45 * @todo When adding string to String Table, check that this is not a Content Text that will be tokenized
46 * @todo For Wireless-Village CSP :
47 * - Encode "Date and Time" in OPAQUE (OMA-WV-CSP_WBXML-V1_1-20021001-A.pdf - 6.6)
48 *
49 * @todo Review the canonical XML generation:
50 * - http://www.jclark.com/xml/canonxml.html
51 * - http://www.w3.org/TR/2004/REC-xml-20040204/
52 */
53
54 #include <ctype.h> /* For isdigit() */
55
56 #include "wbxml_encoder.h"
57 #include "wbxml_log.h"
58 #include "wbxml_internals.h"
59 #include "wbxml_base64.h"
60
61
62 /**
63 * Compilation Flag: WBXML_ENCODER_USE_STRTBL
64 * -----------------
65 * Do We Use String Table when Encoding to WBXML ?
66 * (NOTE: We still use String Table for Unknown Public ID, even if this flag is not set)
67 */
68
69 /* WBXML Header: version publicid charset length
70 * u_int8 mb_u_int32 mb_u_int32 mb_u_int32
71 * 1 octet 5 octets 5 octets 5 octets : 16 octets
72 * mb_u_int32: 5 octets (to handle continuation bits)
73 */
74 #define WBXML_HEADER_MAX_LEN 16
75
76 /* Memory management related defines */
77 #define WBXML_ENCODER_XML_DOC_MALLOC_BLOCK 5000
78 #define WBXML_ENCODER_WBXML_DOC_MALLOC_BLOCK 1000
79
80 #define WBXML_ENCODER_XML_HEADER_MALLOC_BLOCK 250
81 #define WBXML_ENCODER_WBXML_HEADER_MALLOC_BLOCK WBXML_HEADER_MAX_LEN
82
83 /* WBXML Default Charset: UTF-8 (106) */
84 #define WBXML_ENCODER_DEFAULT_CHARSET 0x6a
85
86 /* String Terminating NULL Char */
87 #define WBXML_STR_END '\0'
88
89 /* Minimum String Size needed for String Table - @note Set to '3' for Prov 1.0 */
90 #define WBXML_ENCODER_STRING_TABLE_MIN 3
91
92 /**
93 * Default charset of the outputed WBXML document. Used only in this case :
94 * - No charset was indicated thanks to the function 'wbxml_encoder_set_output_charset()'
95 * - and the WBXML Tree field 'orig_charset' is set to WBXML_CHARSET_UNKNOWN (ie. charset
96 * information not found in original document)
97 */
98 #define WBXML_ENCODER_WBXML_DEFAULT_CHARSET WBXML_CHARSET_UTF_8
99
100 /**
101 * Default charset of the outputed XML document. Used only in this case :
102 * - No charset was indicated thanks to the function 'wbxml_encoder_set_output_charset()'
103 * - and the WBXML Tree field 'orig_charset' is set to WBXML_CHARSET_UNKNOWN (ie. charset
104 * information not found in original document)
105 */
106 #define WBXML_ENCODER_XML_DEFAULT_CHARSET WBXML_CHARSET_UTF_8
107
108 /**
109 * If defined, generate empty XML elements (eg: <foo />), else generate
110 * full "end element" (eg: <foo></foo>)
111 *
112 * @todo This must be a 'WBXMLGenXMLParams' parameter
113 */
114 #define WBXML_ENCODER_XML_GEN_EMPTY_ELT
115
116 /**
117 * If defined, do not indent elements that have no element child (eg: <foo>bar</foo>),
118 * else indent anyway (eg: <foo>
119 * bar
120 * </foo>)
121 *
122 * @todo This must be a 'WBXMLGenXMLParams' parameter
123 */
124 #define WBXML_ENCODER_XML_NO_EMPTY_ELT_INDENT
125
126
127 /**
128 * @warning For now 'current_tag' field is only used for WV Content Encoding. And for this use, it works.
129 * But this field is reset after End Tag, and as there is no Linked List mecanism, this is bad for
130 * cascading elements: we don't fill this field with parent Tag when parsing End Tag.
131 *
132 * @warning For now 'current_text_parent' field is only used for DRM REL Content Encoding. It should not be
133 * used for another purpose.
134 *
135 * @warning For now 'current_node' field is a hack. It is reset after End Tag, and as there is no Linked List
136 * mecanism, this is bad for cascading elements: we don't fill this field with parent Tag
137 * when parsing End Tag.
138 */
139 struct WBXMLEncoder_s {
140 WBXMLTree *tree; /**< WBXML Tree to Encode */
141 const WBXMLLangEntry *lang; /**< Language table to use */
142 WBXMLBuffer *output; /**< The output (wbxml or xml) we are producing */
143 WBXMLBuffer *output_header; /**< The output header (used if Flow Mode encoding is activated) */
144 const WBXMLTagEntry *current_tag; /**< Current Tag (See The Warning For This Field !) */
145 const WBXMLTreeNode *current_text_parent; /**< Text parent of current Node (See The Warning For This Field !) */
146 const WBXMLAttrEntry *current_attr; /**< Current Attribute */
147 WBXMLTreeNode *current_node; /**< Current Node (See The Warning For This Field !) */
148 WB_UTINY tagCodePage; /**< Current Tag Code Page */
149 WB_UTINY attrCodePage; /**< Current Attribute Code Page */
150 WB_BOOL ignore_empty_text; /**< Do we ignore empty text nodes (ie: ignorable whitespaces)? */
151 WB_BOOL remove_text_blanks; /**< Do we remove leading and trailing blanks in text nodes ? */
152 WBXMLEncoderOutputType output_type; /**< Output Type */
153 WBXMLGenXMLType xml_gen_type; /**< XML Generation Type */
154 WB_UTINY indent_delta; /**< Indent Delta (number of spaces) */
155 WB_UTINY indent; /**< Current Indent */
156 WB_BOOL in_content; /**< We are in Content Text (used for indentation when generating XML output) */
157 WB_BOOL in_cdata; /**< We are in a CDATA section (and so, content must be generaed "as is") */
158 WBXMLBuffer *cdata; /**< Current CDATA Buffer */
159 #if defined( WBXML_ENCODER_USE_STRTBL )
160 WBXMLList *strstbl; /**< String Table we are creating */
161 WB_ULONG strstbl_len; /**< String Table Length */
162 WB_BOOL use_strtbl; /**< Do we use String Table when generating WBXML output ? (default: YES) */
163 #endif /* WBXML_ENCODER_USE_STRTBL */
164 WB_BOOL xml_encode_header; /**< Do we generate XML Header ? */
165 WB_BOOL produce_anonymous; /**< Do we produce anonymous documents? (default: NO) */
166 WBXMLVersion wbxml_version; /**< WBXML Version to use (when generating WBXML output) */
167 WBXMLCharsetMIBEnum output_charset; /**< Output charset encoding */
168 WB_BOOL flow_mode; /**< Is Flow Mode encoding activated ? */
169 WB_ULONG pre_last_node_len; /**< Output buffer length before last node encoding */
170 WB_BOOL textual_publicid; /**< Generate textual Public ID instead of token (when generating WBXML output) */
171 };
172
173 #if defined( WBXML_ENCODER_USE_STRTBL )
174 /**
175 * @brief The WBXML String Table Element
176 */
177 typedef struct WBXMLStringTableElement_t {
178 WBXMLBuffer *string; /**< String */
179 WB_ULONG offset; /**< Offset of String in String Table */
180 WB_ULONG count; /**< Number of times this String is referenced in the XML Document */
181 WB_BOOL stat; /**< If set to TRUE, this is a static String that we must not destroy in wbxml_strtbl_element_destroy() function */
182 } WBXMLStringTableElement;
183 #endif /* WBXML_ENCODER_USE_STRTBL */
184
185 /**
186 * @brief WBXML Value Element Context: In Content or in Attribute Value
187 */
188 typedef enum WBXMLValueElementCtx_e {
189 WBXML_VALUE_ELEMENT_CTX_CONTENT = 0, /**< Text Content */
190 WBXML_VALUE_ELEMENT_CTX_ATTR /**< Attribute Value */
191 } WBXMLValueElementCtx;
192
193 /**
194 * @brief WBXML Value Element Type: string / tableref / extension / opaque
195 */
196 typedef enum WBXMLValueElementType_e {
197 WBXML_VALUE_ELEMENT_STRING = 0, /**< Inline String */
198 WBXML_VALUE_ELEMENT_EXTENSION, /**< Extension Token */
199 WBXML_VALUE_ELEMENT_OPAQUE, /**< Opaque Buffer */
200 WBXML_VALUE_ELEMENT_ATTR_TOKEN /**< Attribute Value Token */
201 #if defined( WBXML_ENCODER_USE_STRTBL )
202 , WBXML_VALUE_ELEMENT_TABLEREF /**< String Table Reference */
203 #endif /* WBXML_ENCODER_USE_STRTBL */
204 } WBXMLValueElementType;
205
206 /**
207 * @brief WBXML Value Element Structure
208 */
209 typedef struct WBXMLValueElement_t {
210 WBXMLValueElementType type; /**< Cf WBXMLValueElementType enum */
211 union {
212 WBXMLBuffer *str; /**< WBXML_VALUE_ELEMENT_STRING */
213 const WBXMLExtValueEntry *ext; /**< WBXML_VALUE_ELEMENT_EXTENSION */
214 WBXMLBuffer *buff; /**< WBXML_VALUE_ELEMENT_OPAQUE */
215 const WBXMLAttrValueEntry *attr; /**< WBXML_VALUE_ELEMENT_ATTR_TOKEN */
216 #if defined( WBXML_ENCODER_USE_STRTBL )
217 WB_ULONG index; /**< WBXML_VALUE_ELEMENT_TABLEREF */
218 #endif /* WBXML_ENCODER_USE_STRTBL */
219 } u;
220 } WBXMLValueElement;
221
222
223 /***************************************************
224 * Private Functions prototypes
225 */
226
227 /*******************************
228 * Common Functions
229 */
230
231 #if 0
232 static WB_BOOL convert_char_to_ucs4(WB_UTINY ch, WB_ULONG *result);
233 #endif /* 0 */
234
235 static WBXMLEncoder *encoder_duplicate(WBXMLEncoder *encoder);
236 static WBXMLError encoder_encode_tree(WBXMLEncoder *encoder);
237 static WB_BOOL encoder_init_output(WBXMLEncoder *encoder);
238
239
240 /*******************************
241 * WBXML Tree Parsing Functions
242 */
243
244 static WBXMLError parse_node(WBXMLEncoder *encoder, WBXMLTreeNode *node, WB_BOOL enc_end);
245 static WBXMLError parse_element(WBXMLEncoder *encoder, WBXMLTreeNode *node, WB_BOOL has_content);
246 static WBXMLError parse_element_end(WBXMLEncoder *encoder, WBXMLTreeNode *node, WB_BOOL has_content);
247 static WBXMLError parse_attribute(WBXMLEncoder *encoder, WBXMLAttribute *attribute);
248 static WBXMLError parse_text(WBXMLEncoder *encoder, WBXMLTreeNode *node);
249 static WBXMLError parse_cdata(WBXMLEncoder *encoder);
250 static WBXMLError parse_pi(WBXMLEncoder *encoder, WBXMLTreeNode *node);
251 static WBXMLError parse_tree(WBXMLEncoder *encoder, WBXMLTreeNode *node);
252
253
254 /*******************************
255 * WBXML Output Functions
256 */
257
258 /* Build WBXML Result */
259 static WBXMLError wbxml_build_result(WBXMLEncoder *encoder, WB_UTINY **wbxml, WB_ULONG *wbxml_len);
260 static WBXMLError wbxml_fill_header(WBXMLEncoder *encoder, WBXMLBuffer *header);
261
262 /* WBXML Encoding Functions */
263 static WBXMLError wbxml_encode_end(WBXMLEncoder *encoder);
264
265 static WBXMLError wbxml_encode_tag(WBXMLEncoder *encoder, WBXMLTreeNode *node, WB_BOOL has_content);
266 static WBXMLError wbxml_encode_tag_literal(WBXMLEncoder *encoder, const WB_UTINY *tag, WB_UTINY mask);
267 static WBXMLError wbxml_encode_tag_token(WBXMLEncoder *encoder, WB_UTINY token, WB_UTINY page);
268
269 static WBXMLError wbxml_encode_attr(WBXMLEncoder *encoder, WBXMLAttribute *attribute);
270 static WBXMLError wbxml_encode_attr_start(WBXMLEncoder *encoder, WBXMLAttribute *attribute, WB_UTINY **value);
271 static WBXMLError wbxml_encode_value_element_buffer(WBXMLEncoder *encoder, WB_UTINY *value, WBXMLValueElementCtx ctx);
272 static WBXMLError wbxml_encode_value_element_list(WBXMLEncoder *encoder, WBXMLList *list);
273 static WBXMLError wbxml_encode_attr_start_literal(WBXMLEncoder *encoder, const WB_UTINY *attr);
274 static WBXMLError wbxml_encode_attr_token(WBXMLEncoder *encoder, WB_UTINY token, WB_UTINY page);
275
276 static WBXMLError wbxml_encode_inline_string(WBXMLEncoder *encoder, WBXMLBuffer *str);
277 static WBXMLError wbxml_encode_inline_integer_extension_token(WBXMLEncoder *encoder, WB_UTINY ext, WB_UTINY value);
278 #if 0
279 static WBXMLError wbxml_encode_entity(WBXMLEncoder *encoder, WB_ULONG value);
280 #endif /* 0 */
281 static WBXMLError wbxml_encode_opaque(WBXMLEncoder *encoder, WBXMLBuffer *buff);
282 static WBXMLError wbxml_encode_opaque_data(WBXMLEncoder *encoder, WB_UTINY *data, WB_ULONG data_len);
283 #if defined( WBXML_ENCODER_USE_STRTBL )
284 static WBXMLError wbxml_encode_tableref(WBXMLEncoder *encoder, WB_ULONG offset);
285 #endif /* WBXML_ENCODER_USE_STRTBL */
286
287 static WBXMLValueElement *wbxml_value_element_create(void);
288 static void wbxml_value_element_destroy(WBXMLValueElement *elt);
289 static void wbxml_value_element_destroy_item(void *elt);
290
291 static WBXMLError wbxml_encode_tree(WBXMLEncoder *encoder, WBXMLTree *tree);
292
293 #if ( defined( WBXML_SUPPORT_SI ) || defined( WBXML_SUPPORT_EMN ) )
294 static WBXMLError wbxml_encode_datetime(WBXMLEncoder *encoder, WB_UTINY *buffer);
295 #endif /* WBXML_SUPPORT_SI || WBXML_SUPPORT_EMN */
296
297 #if defined( WBXML_SUPPORT_WV )
298 static WBXMLError wbxml_encode_wv_content(WBXMLEncoder *encoder, WB_UTINY *buffer);
299 static WBXMLError wbxml_encode_wv_integer(WBXMLEncoder *encoder, WB_UTINY *buffer);
300 static WBXMLError wbxml_encode_wv_datetime(WBXMLEncoder *encoder, WB_UTINY *buffer);
301 #endif /* WBXML_SUPPORT_WV */
302
303 #if defined( WBXML_SUPPORT_DRMREL )
304 static WBXMLError wbxml_encode_drmrel_content(WBXMLEncoder *encoder, WB_UTINY *buffer);
305 #endif /* WBXML_SUPPORT_DRMREL */
306
307 #if defined( WBXML_SUPPORT_OTA_SETTINGS )
308 static WBXMLError wbxml_encode_ota_nokia_icon(WBXMLEncoder *encoder, WB_UTINY *buffer);
309 #endif /* WBXML_SUPPORT_OTA_SETTINGS */
310
311 #if defined( WBXML_ENCODER_USE_STRTBL )
312 /* WBXML String Table Functions */
313 static WBXMLStringTableElement *wbxml_strtbl_element_create(WBXMLBuffer *string, WB_BOOL is_stat);
314 static void wbxml_strtbl_element_destroy(WBXMLStringTableElement *element);
315 static void wbxml_strtbl_element_destroy_item(void *element);
316
317 static WBXMLError wbxml_strtbl_initialize(WBXMLEncoder *encoder, WBXMLTreeNode *root);
318 static void wbxml_strtbl_collect_strings(WBXMLEncoder *encoder, WBXMLTreeNode *node, WBXMLList *strings);
319 static WBXMLError wbxml_strtbl_collect_words(WBXMLList *elements, WBXMLList **result);
320 static WBXMLError wbxml_strtbl_construct(WBXMLBuffer *buff, WBXMLList *strstbl);
321 static WBXMLError wbxml_strtbl_check_references(WBXMLEncoder *encoder, WBXMLList **strings, WBXMLList **one_ref, WB_BOOL stat_buff);
322 static WB_BOOL wbxml_strtbl_add_element(WBXMLEncoder *encoder, WBXMLStringTableElement *elt, WB_ULONG *index, WB_BOOL *added);
323 #endif /* WBXML_ENCODER_USE_STRTBL */
324
325
326 /*******************************
327 * XML Output Functions
328 */
329
330 /** New Line */
331 #define WBXML_ENCODER_XML_NEW_LINE ((WB_UTINY *)"\n")
332
333 /* XML Header Macros */
334 #define WBXML_ENCODER_XML_HEADER "<?xml version=\"1.0\"?>"
335 #define WBXML_ENCODER_XML_DOCTYPE "<!DOCTYPE "
336 #define WBXML_ENCODER_XML_PUBLIC_START " PUBLIC \""
337 #define WBXML_ENCODER_XML_PUBLIC_END "\""
338 #define WBXML_ENCODER_XML_SYSTEM " SYSTEM"
339 #define WBXML_ENCODER_XML_DTD " \""
340 #define WBXML_ENCODER_XML_END_DTD "\">"
341
342 /* Global vars for XML Normalization */
343 const WB_UTINY xml_lt[5] = "<"; /**< < */
344 const WB_UTINY xml_gt[5] = ">"; /**< > */
345 const WB_UTINY xml_amp[6] = "&"; /**< & */
346 const WB_UTINY xml_quot[7] = """; /**< " */
347 const WB_UTINY xml_apos[7] = "'"; /**< ' */
348 const WB_UTINY xml_slashr[6] = " "; /**< */
349 const WB_UTINY xml_slashn[6] = " "; /**< */
350 const WB_UTINY xml_tab[5] = "	"; /**< 	 */
351
352 /* Build XML Result */
353 static WBXMLError xml_build_result(WBXMLEncoder *encoder, WB_UTINY **xml, WB_ULONG *xml_len);
354 static WBXMLError xml_fill_header(WBXMLEncoder *encoder, WBXMLBuffer *header);
355
356 /* XML Encoding Functions */
357 static WBXMLError xml_encode_tag(WBXMLEncoder *encoer, WBXMLTreeNode *node);
358 static WBXMLError xml_encode_end_tag(WBXMLEncoder *encoder, WBXMLTreeNode *node);
359
360 static WBXMLError xml_encode_attr(WBXMLEncoder *encoder, WBXMLAttribute *attribute);
361 static WBXMLError xml_encode_end_attrs(WBXMLEncoder *encoder, WBXMLTreeNode *node);
362
363 static WBXMLError xml_encode_text(WBXMLEncoder *encoder, WBXMLTreeNode *node);
364 static WBXMLError xml_encode_text_entities(WBXMLEncoder *encoder, WBXMLBuffer *buff);
365 static WB_BOOL xml_encode_new_line(WBXMLBuffer *buff);
366
367 static WBXMLError xml_encode_cdata(WBXMLEncoder *encoder);
368 static WBXMLError xml_encode_end_cdata(WBXMLEncoder *encoder);
369
370 static WBXMLError xml_encode_tree(WBXMLEncoder *encoder, WBXMLTree *tree);
371
372
373 /***************************************************
374 * Public Functions
375 */
376
wbxml_encoder_create_real(void)377 WBXML_DECLARE(WBXMLEncoder *) wbxml_encoder_create_real(void)
378 {
379 WBXMLEncoder *encoder = NULL;
380
381 encoder = wbxml_malloc(sizeof(WBXMLEncoder));
382 if (encoder == NULL) {
383 return NULL;
384 }
385
386 #if defined( WBXML_ENCODER_USE_STRTBL )
387 if ((encoder->strstbl = wbxml_list_create()) == NULL) {
388 wbxml_free(encoder);
389 return NULL;
390 }
391 encoder->use_strtbl = TRUE;
392 encoder->strstbl_len = 0;
393 #endif /* WBXML_ENCODER_USE_STRTBL */
394
395 encoder->tree = NULL;
396 encoder->lang = NULL;
397 encoder->output = NULL;
398 encoder->output_header = NULL;
399
400 encoder->current_tag = NULL;
401 encoder->current_text_parent = NULL;
402 encoder->current_attr = NULL;
403 encoder->current_node = NULL;
404
405 encoder->tagCodePage = 0;
406 encoder->attrCodePage = 0;
407
408 encoder->ignore_empty_text = FALSE;
409 encoder->remove_text_blanks = FALSE;
410
411 encoder->output_type = WBXML_ENCODER_OUTPUT_WBXML;
412 encoder->xml_gen_type = WBXML_GEN_XML_COMPACT;
413
414 encoder->indent_delta = 1;
415 encoder->indent = 0;
416 encoder->in_content = FALSE;
417 encoder->in_cdata = FALSE;
418 encoder->cdata = NULL;
419
420 encoder->xml_encode_header = TRUE;
421 encoder->produce_anonymous = FALSE;
422
423 /* Default Version: WBXML 1.3 */
424 encoder->wbxml_version = WBXML_VERSION_13;
425
426 /**
427 * Default Output Charset Encoding is the one found in WBXML Tree,
428 * so set it as 'unknown' for now.
429 */
430 encoder->output_charset = WBXML_CHARSET_UNKNOWN;
431
432 encoder->flow_mode = FALSE;
433 encoder->pre_last_node_len = 0;
434 encoder->textual_publicid = FALSE;
435
436 return encoder;
437 }
438
439
wbxml_encoder_destroy(WBXMLEncoder * encoder)440 WBXML_DECLARE(void) wbxml_encoder_destroy(WBXMLEncoder *encoder)
441 {
442 if (encoder == NULL)
443 return;
444
445 wbxml_buffer_destroy(encoder->output);
446 wbxml_buffer_destroy(encoder->output_header);
447 wbxml_buffer_destroy(encoder->cdata);
448
449 #if defined( WBXML_ENCODER_USE_STRTBL )
450 wbxml_list_destroy(encoder->strstbl, wbxml_strtbl_element_destroy_item);
451 #endif /* WBXML_ENCODER_USE_STRTBL */
452
453 wbxml_free(encoder);
454 }
455
456
wbxml_encoder_reset(WBXMLEncoder * encoder)457 WBXML_DECLARE(void) wbxml_encoder_reset(WBXMLEncoder *encoder)
458 {
459 if (encoder == NULL)
460 return;
461
462 encoder->tree = NULL;
463
464 wbxml_buffer_destroy(encoder->output);
465 encoder->output = NULL;
466
467 wbxml_buffer_destroy(encoder->output_header);
468 encoder->output_header = NULL;
469
470 encoder->current_tag = NULL;
471 encoder->current_attr = NULL;
472 encoder->current_node = NULL;
473
474 encoder->tagCodePage = 0;
475 encoder->attrCodePage = 0;
476
477 encoder->in_content = FALSE;
478 encoder->in_cdata = FALSE;
479
480 wbxml_buffer_destroy(encoder->cdata);
481 encoder->cdata = NULL;
482
483 encoder->pre_last_node_len = 0;
484
485 #if defined( WBXML_ENCODER_USE_STRTBL )
486 wbxml_list_destroy(encoder->strstbl, wbxml_strtbl_element_destroy_item);
487 encoder->strstbl = NULL;
488 encoder->strstbl_len = 0;
489 #endif /* WBXML_ENCODER_USE_STRTBL */
490 }
491
492
wbxml_encoder_set_ignore_empty_text(WBXMLEncoder * encoder,WB_BOOL set_ignore)493 WBXML_DECLARE(void) wbxml_encoder_set_ignore_empty_text(WBXMLEncoder *encoder, WB_BOOL set_ignore)
494 {
495 if (encoder == NULL)
496 return;
497
498 encoder->ignore_empty_text = set_ignore;
499 }
500
501
wbxml_encoder_set_remove_text_blanks(WBXMLEncoder * encoder,WB_BOOL set_remove)502 WBXML_DECLARE(void) wbxml_encoder_set_remove_text_blanks(WBXMLEncoder *encoder, WB_BOOL set_remove)
503 {
504 if (encoder == NULL)
505 return;
506
507 encoder->remove_text_blanks = set_remove;
508 }
509
510
wbxml_encoder_set_output_charset(WBXMLEncoder * encoder,WBXMLCharsetMIBEnum charset)511 WBXML_DECLARE(void) wbxml_encoder_set_output_charset(WBXMLEncoder *encoder, WBXMLCharsetMIBEnum charset)
512 {
513 if (encoder == NULL)
514 return;
515
516 /* Tell which Output Charset Encoding to use (this overides the Charset Encoding found in WBXML Tree) */
517 encoder->output_charset = charset;
518 }
519
520
wbxml_encoder_set_use_strtbl(WBXMLEncoder * encoder,WB_BOOL use_strtbl)521 WBXML_DECLARE(void) wbxml_encoder_set_use_strtbl(WBXMLEncoder *encoder, WB_BOOL use_strtbl)
522 {
523 #if defined( WBXML_ENCODER_USE_STRTBL )
524 if (encoder == NULL)
525 return;
526
527 encoder->use_strtbl = use_strtbl;
528 #endif /* WBXML_ENCODER_USE_STRTBL */
529 }
530
531
wbxml_encoder_set_produce_anonymous(WBXMLEncoder * encoder,WB_BOOL set_anonymous)532 WBXML_DECLARE(void) wbxml_encoder_set_produce_anonymous(WBXMLEncoder *encoder, WB_BOOL set_anonymous)
533 {
534 if (encoder == NULL)
535 return;
536
537 encoder->produce_anonymous = set_anonymous;
538 }
539
540
wbxml_encoder_set_wbxml_version(WBXMLEncoder * encoder,WBXMLVersion version)541 WBXML_DECLARE(void) wbxml_encoder_set_wbxml_version(WBXMLEncoder *encoder, WBXMLVersion version)
542 {
543 if (encoder == NULL)
544 return;
545
546 if (version != WBXML_VERSION_UNKNOWN)
547 encoder->wbxml_version = version;
548 }
549
550
wbxml_encoder_set_xml_gen_type(WBXMLEncoder * encoder,WBXMLGenXMLType gen_type)551 WBXML_DECLARE(void) wbxml_encoder_set_xml_gen_type(WBXMLEncoder *encoder, WBXMLGenXMLType gen_type)
552 {
553 if (encoder == NULL)
554 return;
555
556 encoder->xml_gen_type = gen_type;
557 }
558
559
wbxml_encoder_set_indent(WBXMLEncoder * encoder,WB_UTINY indent)560 WBXML_DECLARE(void) wbxml_encoder_set_indent(WBXMLEncoder *encoder, WB_UTINY indent)
561 {
562 if (encoder == NULL)
563 return;
564
565 encoder->indent_delta = indent;
566 }
567
568
wbxml_encoder_set_tree(WBXMLEncoder * encoder,WBXMLTree * tree)569 WBXML_DECLARE(void) wbxml_encoder_set_tree(WBXMLEncoder *encoder, WBXMLTree *tree)
570 {
571 if (encoder == NULL)
572 return;
573
574 encoder->tree = tree;
575 }
576
577
wbxml_encoder_encode_tree_to_wbxml(WBXMLEncoder * encoder,WB_UTINY ** wbxml,WB_ULONG * wbxml_len)578 WBXML_DECLARE(WBXMLError) wbxml_encoder_encode_tree_to_wbxml(WBXMLEncoder *encoder, WB_UTINY **wbxml, WB_ULONG *wbxml_len)
579 {
580 WBXMLError ret = WBXML_OK;
581
582 /* Check Parameters */
583 if (encoder == NULL)
584 return WBXML_ERROR_BAD_PARAMETER;
585
586 /* Init ret values */
587 *wbxml = NULL;
588 *wbxml_len = 0;
589
590 /* We output WBXML */
591 wbxml_encoder_set_output_type(encoder, WBXML_ENCODER_OUTPUT_WBXML);
592
593 /* Encode */
594 if ((ret = encoder_encode_tree(encoder)) != WBXML_OK)
595 return ret;
596
597 /* Get result */
598 return wbxml_encoder_get_output(encoder, wbxml, wbxml_len);
599 }
600
601
wbxml_encoder_encode_tree_to_xml(WBXMLEncoder * encoder,WB_UTINY ** xml,WB_ULONG * xml_len)602 WBXML_DECLARE(WBXMLError) wbxml_encoder_encode_tree_to_xml(WBXMLEncoder *encoder, WB_UTINY **xml, WB_ULONG *xml_len)
603 {
604 WBXMLError ret = WBXML_OK;
605
606 /* Check Parameters */
607 if (encoder == NULL)
608 return WBXML_ERROR_BAD_PARAMETER;
609
610 /* Init ret values */
611 *xml = NULL;
612 *xml_len = 0;
613
614 /* We output WBXML */
615 wbxml_encoder_set_output_type(encoder, WBXML_ENCODER_OUTPUT_XML);
616
617 /* Encode */
618 if ((ret = encoder_encode_tree(encoder)) != WBXML_OK)
619 return ret;
620
621 /* Get result */
622 return wbxml_encoder_get_output(encoder, xml, xml_len);
623 }
624
625
wbxml_encoder_set_flow_mode(WBXMLEncoder * encoder,WB_BOOL flow_mode)626 WBXML_DECLARE(WBXMLError) wbxml_encoder_set_flow_mode(WBXMLEncoder *encoder, WB_BOOL flow_mode)
627 {
628 if (encoder == NULL)
629 return WBXML_ERROR_BAD_PARAMETER;
630
631 encoder->flow_mode = flow_mode;
632
633 /* The string tables must only be disabled during flow mode. */
634 if (flow_mode)
635 {
636 /* Don't use String Tables */
637 wbxml_encoder_set_use_strtbl(encoder, FALSE);
638 }
639
640 return WBXML_OK;
641 }
642
643
wbxml_encoder_set_output_type(WBXMLEncoder * encoder,WBXMLEncoderOutputType output_type)644 WBXML_DECLARE(void) wbxml_encoder_set_output_type(WBXMLEncoder *encoder, WBXMLEncoderOutputType output_type)
645 {
646 if (encoder == NULL)
647 return;
648
649 encoder->output_type = output_type;
650 }
651
652
wbxml_encoder_set_lang(WBXMLEncoder * encoder,WBXMLLanguage lang)653 WBXML_DECLARE(void) wbxml_encoder_set_lang(WBXMLEncoder *encoder, WBXMLLanguage lang)
654 {
655 if (encoder == NULL)
656 return;
657
658 encoder->lang = wbxml_tables_get_table(lang);
659 }
660
661
wbxml_encoder_set_text_public_id(WBXMLEncoder * encoder,WB_BOOL gen_text)662 WBXML_DECLARE(void) wbxml_encoder_set_text_public_id(WBXMLEncoder *encoder, WB_BOOL gen_text)
663 {
664 if (encoder == NULL)
665 return;
666
667 encoder->textual_publicid = gen_text;
668 }
669
670
wbxml_encoder_encode_node(WBXMLEncoder * encoder,WBXMLTreeNode * node)671 WBXML_DECLARE(WBXMLError) wbxml_encoder_encode_node(WBXMLEncoder *encoder, WBXMLTreeNode *node)
672 {
673 if (encoder->flow_mode == FALSE) {
674 WBXML_WARNING((WBXML_ENCODER, "You should NOT call wbxml_encoder_encode_node() if you are not in Flow Mode encoding ! (use wbxml_encoder_set_flow_mode(encoder, TRUE))"));
675 }
676
677 return wbxml_encoder_encode_node_with_elt_end(encoder, node, TRUE);
678 }
679
680
wbxml_encoder_encode_node_with_elt_end(WBXMLEncoder * encoder,WBXMLTreeNode * node,WB_BOOL enc_end)681 WBXML_DECLARE(WBXMLError) wbxml_encoder_encode_node_with_elt_end(WBXMLEncoder *encoder, WBXMLTreeNode *node, WB_BOOL enc_end)
682 {
683 WB_ULONG prev_len = 0;
684 WBXMLError ret = WBXML_OK;
685
686 if ((encoder == NULL) || (node == NULL))
687 return WBXML_ERROR_BAD_PARAMETER;
688
689 /* Check that language table has been set */
690 if (encoder->lang == NULL)
691 return WBXML_ERROR_BAD_PARAMETER;
692
693 /* Init Output Buffer if needed */
694 if (!encoder_init_output(encoder))
695 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
696
697 /* Backup length */
698 prev_len = wbxml_buffer_len(encoder->output);
699
700 /* Check if result header is not already built */
701 if ((encoder->flow_mode == TRUE) && (encoder->output_header == NULL) &&
702 !((encoder->xml_encode_header == FALSE) && (encoder->output_type == WBXML_ENCODER_OUTPUT_XML)))
703 {
704 /* Build result header */
705 switch (encoder->output_type) {
706 case WBXML_ENCODER_OUTPUT_XML:
707 if ((encoder->output_header = wbxml_buffer_create("", 0, WBXML_ENCODER_XML_HEADER_MALLOC_BLOCK)) == NULL)
708 ret = WBXML_ERROR_NOT_ENOUGH_MEMORY;
709 else
710 ret = xml_fill_header(encoder, encoder->output_header);
711 break;
712
713 case WBXML_ENCODER_OUTPUT_WBXML:
714 if ((encoder->output_header = wbxml_buffer_create("", 0, WBXML_ENCODER_WBXML_HEADER_MALLOC_BLOCK)) == NULL)
715 ret = WBXML_ERROR_NOT_ENOUGH_MEMORY;
716 else
717 ret = wbxml_fill_header(encoder, encoder->output_header);
718 break;
719
720 default:
721 ret = WBXML_ERROR_BAD_PARAMETER;
722 break;
723 }
724 }
725
726 if (ret != WBXML_OK)
727 return ret;
728
729 if ((ret = parse_node(encoder, node, enc_end)) == WBXML_OK)
730 encoder->pre_last_node_len = prev_len;
731
732 return ret;
733 }
734
735
wbxml_encoder_encode_tree(WBXMLEncoder * encoder,WBXMLTree * tree)736 WBXML_DECLARE(WBXMLError) wbxml_encoder_encode_tree(WBXMLEncoder *encoder, WBXMLTree *tree)
737 {
738 const WBXMLLangEntry *lang = NULL;
739 WBXMLError ret = WBXML_OK;
740
741 if ((encoder == NULL) || (tree == NULL))
742 return WBXML_ERROR_BAD_PARAMETER;
743
744 /* Backup encoder lang */
745 lang = encoder->lang;
746
747 /* Set Tree lang to encoder */
748 encoder->lang = tree->lang;
749
750 /* Encode root node */
751 ret = wbxml_encoder_encode_node(encoder, tree->root);
752
753 /* Revert encoder lang */
754 encoder->lang = lang;
755
756 return ret;
757 }
758
759
wbxml_encoder_encode_raw_elt_start(WBXMLEncoder * encoder,WBXMLTreeNode * node,WB_BOOL has_content)760 WBXML_DECLARE(WBXMLError) wbxml_encoder_encode_raw_elt_start(WBXMLEncoder *encoder, WBXMLTreeNode *node, WB_BOOL has_content)
761 {
762 /* Init Output Buffer if needed */
763 if (!encoder_init_output(encoder))
764 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
765
766 return parse_element(encoder, node, has_content);
767 }
768
769
wbxml_encoder_encode_raw_elt_end(WBXMLEncoder * encoder,WBXMLTreeNode * node,WB_BOOL has_content)770 WBXML_DECLARE(WBXMLError) wbxml_encoder_encode_raw_elt_end(WBXMLEncoder *encoder, WBXMLTreeNode *node, WB_BOOL has_content)
771 {
772 /* Init Output Buffer if needed */
773 if (!encoder_init_output(encoder))
774 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
775
776 return parse_element_end(encoder, node, has_content);
777 }
778
779
wbxml_encoder_get_output(WBXMLEncoder * encoder,WB_UTINY ** result,WB_ULONG * result_len)780 WBXML_DECLARE(WBXMLError) wbxml_encoder_get_output(WBXMLEncoder *encoder, WB_UTINY **result, WB_ULONG *result_len)
781 {
782 if ((encoder == NULL) || (result == NULL) || (result_len == NULL))
783 return WBXML_ERROR_BAD_PARAMETER;
784
785 switch (encoder->output_type) {
786 case WBXML_ENCODER_OUTPUT_XML:
787 return xml_build_result(encoder, result, result_len);
788
789 case WBXML_ENCODER_OUTPUT_WBXML:
790 return wbxml_build_result(encoder, result, result_len);
791
792 default:
793 return WBXML_ERROR_BAD_PARAMETER;
794 }
795 }
796
797
wbxml_encoder_get_output_len(WBXMLEncoder * encoder)798 WBXML_DECLARE(WB_ULONG) wbxml_encoder_get_output_len(WBXMLEncoder *encoder)
799 {
800 if (encoder == NULL)
801 return 0;
802
803 return wbxml_buffer_len(encoder->output_header) + wbxml_buffer_len(encoder->output);
804 }
805
806
wbxml_encoder_delete_output_bytes(WBXMLEncoder * encoder,WB_ULONG nb)807 WBXML_DECLARE(void) wbxml_encoder_delete_output_bytes(WBXMLEncoder *encoder, WB_ULONG nb)
808 {
809 if (encoder == NULL)
810 return;
811
812 wbxml_buffer_delete(encoder->output, wbxml_buffer_len(encoder->output) - nb, nb);
813 }
814
815
wbxml_encoder_delete_last_node(WBXMLEncoder * encoder)816 WBXML_DECLARE(void) wbxml_encoder_delete_last_node(WBXMLEncoder *encoder)
817 {
818 if (encoder == NULL)
819 return;
820
821 wbxml_encoder_delete_output_bytes(encoder, wbxml_buffer_len(encoder->output) - encoder->pre_last_node_len);
822 }
823
824
825 /***************************************************
826 * Private Functions
827 */
828
829 /****************************
830 * Common Functions
831 */
832
833 #if 0
834 /**
835 * @brief Convert a char to UCS-4
836 * @param ch [in] The character to convert
837 * @param result [out] The UCS-4 code
838 * @return TRUE if convertion succeeded, FALSE otherwise
839 */
840 static WB_BOOL convert_char_to_ucs4(WB_UTINY ch, WB_ULONG *result)
841 {
842 /** @todo convert_char_to_ucs4() */
843
844 return FALSE;
845 }
846 #endif /* 0 */
847
848 /**
849 * @brief Duplicate a WBXML Encoder
850 * @param encoder [in] The WBXML Encoder to Duplicate
851 * @return The duplicated WBXML Encoder, or NULL if error
852 * @note Only options (parameters) fields are duplicated, others are reset
853 */
encoder_duplicate(WBXMLEncoder * encoder)854 static WBXMLEncoder *encoder_duplicate(WBXMLEncoder *encoder)
855 {
856 WBXMLEncoder *result = NULL;
857
858 if ((result = wbxml_encoder_create()) == NULL)
859 return NULL;
860
861 result->ignore_empty_text = encoder->ignore_empty_text;
862 result->remove_text_blanks = encoder->remove_text_blanks;
863
864 result->output_type = encoder->output_type;
865 result->xml_gen_type = encoder->xml_gen_type;
866
867 result->indent_delta = encoder->indent_delta;
868 result->indent = encoder->indent;
869
870 #if defined( WBXML_ENCODER_USE_STRTBL )
871 result->use_strtbl = encoder->use_strtbl;
872 #endif /* WBXML_ENCODER_USE_STRTBL */
873
874 /* Do NOT generate XML Header */
875 result->xml_encode_header = FALSE;
876
877 result->wbxml_version = encoder->wbxml_version;
878
879 return result;
880 }
881
882
encoder_encode_tree(WBXMLEncoder * encoder)883 static WBXMLError encoder_encode_tree(WBXMLEncoder *encoder)
884 {
885 WBXMLError ret = WBXML_OK;
886
887 /* Check Parameters */
888 if ((encoder == NULL) || (encoder->tree == NULL) || ((encoder->lang == NULL) && (encoder->tree->lang == NULL)) ||
889 ((encoder->output_type != WBXML_ENCODER_OUTPUT_XML) && (encoder->output_type != WBXML_ENCODER_OUTPUT_WBXML)))
890 {
891 return WBXML_ERROR_BAD_PARAMETER;
892 }
893
894 if (encoder->lang == NULL)
895 encoder->lang = encoder->tree->lang;
896
897 /* Choose Output Charset */
898 if (encoder->output_charset == WBXML_CHARSET_UNKNOWN) {
899 /* User has not choosen the Output Charset Encoding */
900 if (encoder->tree->orig_charset != WBXML_CHARSET_UNKNOWN) {
901 /* Use the original Charset Encoding found when we have parsed the original document */
902 encoder->output_charset = encoder->tree->orig_charset;
903 }
904 else {
905 /* Use default charset */
906 encoder->output_charset = WBXML_ENCODER_XML_DEFAULT_CHARSET;
907 }
908 }
909
910 /* Init Output Buffer */
911 if (!encoder_init_output(encoder)) {
912 wbxml_encoder_destroy(encoder);
913 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
914 }
915
916 #if defined( WBXML_ENCODER_USE_STRTBL )
917
918 if (encoder->output_type == WBXML_ENCODER_OUTPUT_WBXML) {
919 /* Choose if we will use String Table */
920 switch (encoder->lang->langID)
921 {
922 #if defined( WBXML_SUPPORT_WV )
923 /* Wireless-Village CSP 1.1 / 1.2: content can be tokenized, so we mustn't interfere with String Table stuff */
924 case WBXML_LANG_WV_CSP11:
925 case WBXML_LANG_WV_CSP12:
926 encoder->use_strtbl = FALSE;
927 break;
928 #endif /* WBXML_SUPPORT_WV */
929
930 #if defined( WBXML_SUPPORT_OTA_SETTINGS )
931 /* Nokia Ericsson OTA Settings : string tables are not supported */
932 case WBXML_LANG_OTA_SETTINGS:
933 encoder->use_strtbl = FALSE;
934 break;
935 #endif /* WBXML_SUPPORT_OTA_SETTINGS */
936
937 default:
938 /* Use Default Value */
939 break;
940 }
941
942 /* Init String Table */
943 if (encoder->use_strtbl) {
944 /**
945 * @bug If 'output_charset' is different from UTF-8, the string table initialization
946 * also is erroneous !!!
947 */
948 if ((ret = wbxml_strtbl_initialize(encoder, encoder->tree->root)) != WBXML_OK)
949 return ret;
950 }
951 }
952
953 #endif /* WBXML_ENCODER_USE_STRTBL */
954
955 /* Let's begin WBXML Tree Parsing */
956 return parse_node(encoder, encoder->tree->root, TRUE);
957 }
958
959
encoder_init_output(WBXMLEncoder * encoder)960 static WB_BOOL encoder_init_output(WBXMLEncoder *encoder)
961 {
962 WB_ULONG malloc_block = 0;
963
964 if (encoder == NULL)
965 return FALSE;
966
967 /* Check if output already inited */
968 if (encoder->output != NULL)
969 return TRUE;
970
971 /* Get malloc block */
972 if (encoder->output_type == WBXML_ENCODER_OUTPUT_WBXML)
973 malloc_block = WBXML_ENCODER_WBXML_DOC_MALLOC_BLOCK;
974 else
975 malloc_block = WBXML_ENCODER_XML_DOC_MALLOC_BLOCK;
976
977 /* Init Output Buffer */
978 encoder->output = wbxml_buffer_create("", 0, malloc_block);
979 if (encoder->output == NULL)
980 return FALSE;
981
982 return TRUE;
983 }
984
985
986 /*********************************
987 * WBXML Tree Parsing Functions
988 */
989
990 /**
991 * @brief Parse an XML Node
992 * @param encoder The WBXML Encoder
993 * @param node The node to parse
994 * @param enc_end If node is an element, do we encoded its end ?
995 * @return WBXML_OK if parsing is OK, an error code otherwise
996 * @note We have recurrency in this function
997 */
parse_node(WBXMLEncoder * encoder,WBXMLTreeNode * node,WB_BOOL enc_end)998 static WBXMLError parse_node(WBXMLEncoder *encoder, WBXMLTreeNode *node, WB_BOOL enc_end)
999 {
1000 WBXMLError ret = WBXML_OK;
1001
1002 /* Set current node */
1003 encoder->current_node = node;
1004
1005 /* Parse this node */
1006 switch (node->type) {
1007 case WBXML_TREE_ELEMENT_NODE:
1008 ret = parse_element(encoder, node, node->children != NULL);
1009 break;
1010 case WBXML_TREE_TEXT_NODE:
1011 ret = parse_text(encoder, node);
1012 break;
1013 case WBXML_TREE_CDATA_NODE:
1014 ret = parse_cdata(encoder);
1015 break;
1016 case WBXML_TREE_PI_NODE:
1017 ret = parse_pi(encoder, node);
1018 break;
1019 case WBXML_TREE_TREE_NODE:
1020 ret = parse_tree(encoder, node);
1021 break;
1022 default:
1023 return WBXML_ERROR_XML_NODE_NOT_ALLOWED;
1024 }
1025
1026 if (ret != WBXML_OK)
1027 return ret;
1028
1029 /* Check if node has children */
1030 if (node->children != NULL) {
1031 /* Parse Child */
1032 if ((ret = parse_node(encoder, node->children, TRUE)) != WBXML_OK)
1033 return ret;
1034 }
1035
1036 /* Handle end of Element or CDATA section */
1037 switch (node->type) {
1038 case WBXML_TREE_ELEMENT_NODE:
1039 if (enc_end) {
1040 switch(encoder->output_type) {
1041 case WBXML_ENCODER_OUTPUT_XML:
1042 #if defined( WBXML_ENCODER_XML_GEN_EMPTY_ELT )
1043 if (node->children != NULL) {
1044 #endif /* WBXML_ENCODER_XML_GEN_EMPTY_ELT */
1045
1046 /* Encode end tag */
1047 if ((ret = xml_encode_end_tag(encoder, node)) != WBXML_OK)
1048 return ret;
1049
1050 WBXML_DEBUG((WBXML_ENCODER, "End Element"));
1051
1052 #if defined( WBXML_ENCODER_XML_GEN_EMPTY_ELT )
1053 }
1054 #endif /* WBXML_ENCODER_XML_GEN_EMPTY_ELT */
1055 break;
1056
1057 case WBXML_ENCODER_OUTPUT_WBXML:
1058 if (node->children != NULL) {
1059 /* Add a WBXML End tag */
1060 if ((ret = wbxml_encode_end(encoder)) != WBXML_OK)
1061 return ret;
1062
1063 WBXML_DEBUG((WBXML_ENCODER, "End Element"));
1064 }
1065 break;
1066
1067 default:
1068 /* hu ? */
1069 break;
1070 } /* switch */
1071 } /* if */
1072 break;
1073
1074 case WBXML_TREE_CDATA_NODE:
1075 /* End of CDATA section */
1076 encoder->in_cdata = FALSE;
1077
1078 WBXML_DEBUG((WBXML_ENCODER, "End CDATA"));
1079
1080 switch(encoder->output_type) {
1081 case WBXML_ENCODER_OUTPUT_XML:
1082 /* Encode XML "End of CDATA section" */
1083 if ((ret = xml_encode_end_cdata(encoder)) != WBXML_OK)
1084 return ret;
1085 break;
1086
1087 case WBXML_ENCODER_OUTPUT_WBXML:
1088 if (encoder->cdata == NULL) {
1089 /* Must never happen */
1090 return WBXML_ERROR_INTERNAL;
1091 }
1092
1093 /* Encode CDATA Buffer into Opaque */
1094 /* NOTE: A CDATA section is not necessarily opaque data.
1095 * NOTE: CDATA is only character data which can be NULL terminated.
1096 * NOTE: Nevertheless it is not wrong to handle it like opaque data.
1097 */
1098 if (wbxml_buffer_len(encoder->cdata) > 0) {
1099 if ((ret = wbxml_encode_opaque(encoder, encoder->cdata)) != WBXML_OK)
1100 return ret;
1101 }
1102
1103 /* Reset CDATA Buffer */
1104 wbxml_buffer_destroy(encoder->cdata);
1105 encoder->cdata = NULL;
1106 break;
1107
1108 default:
1109 /* hu ? */
1110 break;
1111 } /* switch */
1112 break;
1113
1114 default:
1115 /* NOP */
1116 break;
1117 }
1118
1119 /* Reset Current Tag and Current Node */
1120 encoder->current_tag = NULL;
1121 encoder->current_node = NULL;
1122
1123 /* Parse next node */
1124 if (node->next != NULL)
1125 return parse_node(encoder, node->next, TRUE);
1126 else
1127 return WBXML_OK;
1128 }
1129
1130
1131 /**
1132 * @brief Parse an XML Element
1133 * @param encoder The WBXML Encoder
1134 * @param node The element to parse
1135 * @param has_content Does the element has content ?
1136 * @return WBXML_OK if parsing is OK, an error code otherwise
1137 */
parse_element(WBXMLEncoder * encoder,WBXMLTreeNode * node,WB_BOOL has_content)1138 static WBXMLError parse_element(WBXMLEncoder *encoder, WBXMLTreeNode *node, WB_BOOL has_content)
1139 {
1140 WB_ULONG i = 0;
1141 WBXMLError ret = WBXML_OK;
1142 WBXMLAttribute *attr = NULL;
1143
1144 WBXML_DEBUG((WBXML_ENCODER, "Element: <%s>", wbxml_tag_get_xml_name(node->name)));
1145
1146 /* Encode: Element Name */
1147 switch (encoder->output_type) {
1148 case WBXML_ENCODER_OUTPUT_WBXML:
1149 if ((ret = wbxml_encode_tag(encoder, node, has_content)) != WBXML_OK)
1150 return ret;
1151 break;
1152
1153 case WBXML_ENCODER_OUTPUT_XML:
1154 if ((ret = xml_encode_tag(encoder, node)) != WBXML_OK)
1155 return ret;
1156 break;
1157
1158 default:
1159 return WBXML_ERROR_INTERNAL;
1160 }
1161
1162 /** @todo Check handling of Namespaces */
1163
1164 /** @todo For Canonical XML Output: Attributes MUST be sorted */
1165
1166 /* Parse: Attributes List */
1167 if (node->attrs != NULL)
1168 {
1169 for (i = 0; i < wbxml_list_len(node->attrs); i++) {
1170 /* Parse: Attribute */
1171 attr = wbxml_list_get(node->attrs, i);
1172 if (attr == NULL)
1173 return WBXML_ERROR_INTERNAL;
1174 if ((ret = parse_attribute(encoder, attr)) != WBXML_OK)
1175 return ret;
1176 }
1177 }
1178
1179 /* Encode: End of attributes */
1180 switch (encoder->output_type) {
1181 case WBXML_ENCODER_OUTPUT_WBXML:
1182 /** @todo Check if the attributes will really be tokenized. There can be ignored attributes, and so NO attribute
1183 * tokenized at all.
1184 */
1185 if ((node->attrs != NULL) && (encoder->lang->attrTable != NULL) /** @todo Fast patch for SyncML (change this) */) {
1186 if ((ret = wbxml_encode_end(encoder)) != WBXML_OK)
1187 return ret;
1188
1189 WBXML_DEBUG((WBXML_ENCODER, "End Attributes"));
1190 }
1191 break;
1192
1193 case WBXML_ENCODER_OUTPUT_XML:
1194 /* Encode end of attributes */
1195 if ((ret = xml_encode_end_attrs(encoder, node)) != WBXML_OK)
1196 return ret;
1197
1198 WBXML_DEBUG((WBXML_ENCODER, "End Attributes"));
1199 break;
1200
1201 default:
1202 return WBXML_ERROR_INTERNAL;
1203 }
1204
1205 return WBXML_OK;
1206 }
1207
1208
1209 /**
1210 * @brief Parse an Element End
1211 * @param encoder The WBXML Encoder
1212 * @param node The element to parse
1213 * @param has_content Does the element has content ?
1214 * @return WBXML_OK if parsing is OK, an error code otherwise
1215 */
parse_element_end(WBXMLEncoder * encoder,WBXMLTreeNode * node,WB_BOOL has_content)1216 static WBXMLError parse_element_end(WBXMLEncoder *encoder, WBXMLTreeNode *node, WB_BOOL has_content)
1217 {
1218 WBXMLError ret = WBXML_OK;
1219
1220 if (encoder->output_type == WBXML_ENCODER_OUTPUT_XML) {
1221 #if defined( WBXML_ENCODER_XML_GEN_EMPTY_ELT )
1222 if (has_content) {
1223 #endif /* WBXML_ENCODER_XML_GEN_EMPTY_ELT */
1224
1225 /* Encode end tag */
1226 ret = xml_encode_end_tag(encoder, node);
1227
1228 WBXML_DEBUG((WBXML_ENCODER, "End Element"));
1229
1230 #if defined( WBXML_ENCODER_XML_GEN_EMPTY_ELT )
1231 }
1232 #endif /* WBXML_ENCODER_XML_GEN_EMPTY_ELT */
1233 }
1234 else if (encoder->output_type == WBXML_ENCODER_OUTPUT_WBXML) {
1235 if (has_content) {
1236 /* Add a WBXML End tag */
1237 ret = wbxml_encode_end(encoder);
1238
1239 WBXML_DEBUG((WBXML_ENCODER, "End Element"));
1240 }
1241 }
1242
1243 return ret;
1244 }
1245
1246
1247 /**
1248 * @brief Parse an XML Attribute
1249 * @param encoder The WBXML Encoder
1250 * @param attribute The XML Attribute to parse
1251 * @return WBXML_OK if parsing is OK, an error code otherwise
1252 */
parse_attribute(WBXMLEncoder * encoder,WBXMLAttribute * attribute)1253 static WBXMLError parse_attribute(WBXMLEncoder *encoder, WBXMLAttribute *attribute)
1254 {
1255 if (encoder->lang == NULL)
1256 return WBXML_ERROR_LANG_TABLE_UNDEFINED;
1257
1258 if (encoder->lang->attrTable == NULL)
1259 return WBXML_OK;
1260
1261 /* Check that this attribute has a name */
1262 if (attribute->name == NULL)
1263 return WBXML_ERROR_XML_NULL_ATTR_NAME;
1264
1265 WBXML_DEBUG((WBXML_ENCODER, "Attribute: %s = %s", wbxml_attribute_get_xml_name(attribute), wbxml_attribute_get_xml_value(attribute)));
1266
1267 /* Encode: Attribute */
1268 switch (encoder->output_type) {
1269 case WBXML_ENCODER_OUTPUT_WBXML:
1270 return wbxml_encode_attr(encoder, attribute);
1271
1272 case WBXML_ENCODER_OUTPUT_XML:
1273 return xml_encode_attr(encoder, attribute);
1274
1275 default:
1276 return WBXML_ERROR_INTERNAL;
1277 }
1278 }
1279
1280
1281 /**
1282 * @brief Parse an XML Text
1283 * @param encoder The WBXML Encoder
1284 * @param node The text to parse
1285 * @return WBXML_OK if parsing is OK, an error code otherwise
1286 */
parse_text(WBXMLEncoder * encoder,WBXMLTreeNode * node)1287 static WBXMLError parse_text(WBXMLEncoder *encoder, WBXMLTreeNode *node)
1288 {
1289 WBXMLError ret = WBXML_OK;
1290
1291 /* Some elements should be transferred as opaque data */
1292 if (encoder->output_type == WBXML_ENCODER_OUTPUT_WBXML &&
1293 encoder->current_tag != NULL &&
1294 encoder->current_tag->options & WBXML_TAG_OPTION_BINARY)
1295 {
1296 return wbxml_encode_opaque(encoder, node->content);
1297 }
1298
1299 /* Do not modify text inside a CDATA section */
1300 /* Do not modify text inside a BINARY section */
1301 if (!encoder->in_cdata &&
1302 ! (encoder->current_tag != NULL && encoder->current_tag->options & WBXML_TAG_OPTION_BINARY)) {
1303 /* If Canonical Form: "Ignorable white space is considered significant and is treated equivalently to data" */
1304 if ((encoder->output_type != WBXML_ENCODER_OUTPUT_XML) || (encoder->xml_gen_type != WBXML_GEN_XML_CANONICAL)) {
1305 /* Ignore blank nodes */
1306 if ((encoder->ignore_empty_text) && (wbxml_buffer_contains_only_whitespaces(node->content)))
1307 return WBXML_OK;
1308
1309 /* Strip Blanks */
1310 if (encoder->remove_text_blanks)
1311 wbxml_buffer_strip_blanks(node->content);
1312 }
1313 }
1314
1315 WBXML_DEBUG((WBXML_ENCODER, "Text: <%s>", wbxml_buffer_get_cstr(node->content)));
1316
1317 /* Encode Text */
1318 switch (encoder->output_type) {
1319 case WBXML_ENCODER_OUTPUT_WBXML:
1320 if (encoder->in_cdata) {
1321 if (encoder->cdata == NULL) {
1322 /* Must never happen */
1323 return WBXML_ERROR_INTERNAL;
1324 }
1325
1326 #if defined( WBXML_SUPPORT_SYNCML )
1327
1328 if ((encoder->lang->langID == WBXML_LANG_SYNCML_SYNCML10) ||
1329 (encoder->lang->langID == WBXML_LANG_SYNCML_SYNCML11) ||
1330 (encoder->lang->langID == WBXML_LANG_SYNCML_SYNCML12))
1331 {
1332 /** @todo We suppose that Opaque Data in SyncML messages can only be vCard or vCal documents. CHANGE THAT ! */
1333 if (node->content != NULL) {
1334 if (wbxml_buffer_get_cstr(node->content)[0] == 0x0a && wbxml_buffer_len(node->content) == 1) {
1335 wbxml_buffer_insert_cstr(node->content, (WB_UTINY*) "\r", 0);
1336 }
1337 }
1338 }
1339
1340 #endif /* WBXML_SUPPORT_SYNCML */
1341
1342 /* Add text into CDATA Buffer */
1343 if (!wbxml_buffer_append(encoder->cdata, node->content))
1344 return WBXML_ERROR_ENCODER_APPEND_DATA;
1345
1346 return WBXML_OK;
1347 }
1348 else {
1349 /* Encode text */
1350 encoder->current_text_parent = node->parent;
1351 ret = wbxml_encode_value_element_buffer(encoder, wbxml_buffer_get_cstr(node->content), WBXML_VALUE_ELEMENT_CTX_CONTENT);
1352 encoder->current_text_parent = NULL;
1353 return ret;
1354 }
1355
1356 case WBXML_ENCODER_OUTPUT_XML:
1357 return xml_encode_text(encoder, node);
1358
1359 default:
1360 return WBXML_ERROR_INTERNAL;
1361 }
1362 }
1363
1364
1365 /**
1366 * @brief Parse an XML CDATA
1367 * @param encoder The WBXML Encoder
1368 * @return WBXML_OK if parsing is OK, an error code otherwise
1369 * @note There is no node parameter because the content is not
1370 * handled by this function and CDATA has no "attributes".
1371 */
parse_cdata(WBXMLEncoder * encoder)1372 static WBXMLError parse_cdata(WBXMLEncoder *encoder)
1373 {
1374 WBXML_DEBUG((WBXML_ENCODER, "CDATA Begin"));
1375
1376 /* Keep in mind that we are in a CDATA section */
1377 encoder->in_cdata = TRUE;
1378
1379 /* Encode CDATA */
1380 switch (encoder->output_type) {
1381 case WBXML_ENCODER_OUTPUT_WBXML:
1382 if (encoder->cdata != NULL) {
1383 /* Must never happend */
1384 return WBXML_ERROR_INTERNAL;
1385 }
1386
1387 /* Create a new CDATA Buffer */
1388 if ((encoder->cdata = wbxml_buffer_create("", 0, 0)) == NULL) {
1389 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
1390 }
1391
1392 return WBXML_OK;
1393 case WBXML_ENCODER_OUTPUT_XML:
1394 return xml_encode_cdata(encoder);
1395 default:
1396 return WBXML_ERROR_INTERNAL;
1397 }
1398 }
1399
1400
1401 /**
1402 * @brief Parse an XML PI
1403 * @param encoder The WBXML Encoder
1404 * @param node The PI to parse
1405 * @return WBXML_OK if parsing is OK, an error code otherwise
1406 */
parse_pi(WBXMLEncoder * encoder,WBXMLTreeNode * node)1407 static WBXMLError parse_pi(WBXMLEncoder *encoder, WBXMLTreeNode *node)
1408 {
1409 /** @todo parse_pi() */
1410
1411 return WBXML_ERROR_NOT_IMPLEMENTED;
1412 }
1413
1414
1415 /**
1416 * @brief Parse a WBXML Tree
1417 * @param encoder The WBXML Encoder
1418 * @param node The WBXML Tree to parse
1419 * @return WBXML_OK if parsing is OK, an error code otherwise
1420 */
parse_tree(WBXMLEncoder * encoder,WBXMLTreeNode * node)1421 static WBXMLError parse_tree(WBXMLEncoder *encoder, WBXMLTreeNode *node)
1422 {
1423 switch (encoder->output_type) {
1424 case WBXML_ENCODER_OUTPUT_WBXML:
1425 return wbxml_encode_tree(encoder, node->tree);
1426 case WBXML_ENCODER_OUTPUT_XML:
1427 return xml_encode_tree(encoder, node->tree);
1428 default:
1429 return WBXML_ERROR_INTERNAL;
1430 }
1431 }
1432
1433
1434 /*****************************************
1435 * WBXML Output Functions
1436 */
1437
1438 /****************************
1439 * Build WBXML Result
1440 */
1441
1442 /**
1443 * @brief Build WBXML Result
1444 * @param encoder [in] The WBXML Encoder
1445 * @param wbxml [out] Resulting WBXML document
1446 * @param wbxml_len [out] The resulting WBXML document length
1447 * @return WBXML_OK if built is OK, an error code otherwise
1448 * @note WBXML Header = version publicid charset length
1449 */
wbxml_build_result(WBXMLEncoder * encoder,WB_UTINY ** wbxml,WB_ULONG * wbxml_len)1450 static WBXMLError wbxml_build_result(WBXMLEncoder *encoder, WB_UTINY **wbxml, WB_ULONG *wbxml_len)
1451 {
1452 WBXMLBuffer *header = NULL;
1453 WBXMLError ret = WBXML_OK;
1454
1455 if (encoder->flow_mode == TRUE) {
1456 /* Header already built */
1457 header = encoder->output_header;
1458 }
1459 else {
1460 /* Create WBXML Header buffer */
1461 if ((header = wbxml_buffer_create("", 0, WBXML_ENCODER_WBXML_HEADER_MALLOC_BLOCK)) == NULL)
1462 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
1463
1464 /* Fill Header Buffer */
1465 if ((ret = wbxml_fill_header(encoder, header)) != WBXML_OK) {
1466 wbxml_buffer_destroy(header);
1467 return ret;
1468 }
1469 }
1470
1471 /* Result Buffer Length */
1472 *wbxml_len = wbxml_buffer_len(header) + wbxml_buffer_len(encoder->output);
1473
1474 /* Create Result Buffer */
1475 *wbxml = wbxml_malloc(*wbxml_len * sizeof(WB_UTINY));
1476 if (*wbxml == NULL) {
1477 if (encoder->flow_mode == FALSE)
1478 wbxml_buffer_destroy(header);
1479
1480 *wbxml_len = 0;
1481 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
1482 }
1483
1484 /* Copy WBXML Header */
1485 memcpy(*wbxml, wbxml_buffer_get_cstr(header), wbxml_buffer_len(header));
1486
1487 /* Copy WBXML Buffer */
1488 memcpy(*wbxml + wbxml_buffer_len(header), wbxml_buffer_get_cstr(encoder->output), wbxml_buffer_len(encoder->output));
1489
1490 if (encoder->flow_mode == FALSE)
1491 wbxml_buffer_destroy(header);
1492
1493 return WBXML_OK;
1494 }
1495
1496
wbxml_fill_header(WBXMLEncoder * encoder,WBXMLBuffer * header)1497 static WBXMLError wbxml_fill_header(WBXMLEncoder *encoder, WBXMLBuffer *header)
1498 {
1499 WBXMLBuffer *pid = NULL;
1500 WB_ULONG public_id = 0, public_id_index = 0, strstbl_len = 0;
1501 WB_BOOL pi_in_strtbl = FALSE;
1502 WBXMLError ret = WBXML_OK;
1503
1504 #if defined( WBXML_ENCODER_USE_STRTBL )
1505 WBXMLStringTableElement *elt = NULL;
1506 WB_BOOL added = FALSE;
1507 #endif /* WBXML_ENCODER_USE_STRTBL */
1508
1509 if ((encoder == NULL) || (encoder->lang == NULL) || (encoder->lang->publicID == NULL) || (header == NULL))
1510 return WBXML_ERROR_BAD_PARAMETER;
1511
1512 #if defined( WBXML_ENCODER_USE_STRTBL )
1513 strstbl_len = encoder->strstbl_len;
1514 #endif /* WBXML_ENCODER_USE_STRTBL */
1515
1516 /* WBXML Public ID */
1517 public_id = encoder->lang->publicID->wbxmlPublicID;
1518
1519 /* Encode WBXML Version */
1520 if (!wbxml_buffer_append_char(header, (WB_UTINY) encoder->wbxml_version))
1521 return WBXML_ERROR_ENCODER_APPEND_DATA;
1522
1523 /* Prepare string table - adding Public ID */
1524 /* If WBXML Public Id is '0x01' (unknown), or we forced it, add the XML Public ID in the String Table */
1525 if ((encoder->textual_publicid || (public_id == WBXML_PUBLIC_ID_UNKNOWN)) &&
1526 !encoder->produce_anonymous)
1527 {
1528 if (encoder->lang->publicID->xmlPublicID != NULL)
1529 {
1530 if ((pid = wbxml_buffer_create(encoder->lang->publicID->xmlPublicID,
1531 WBXML_STRLEN(encoder->lang->publicID->xmlPublicID),
1532 WBXML_STRLEN(encoder->lang->publicID->xmlPublicID))) == NULL)
1533 {
1534 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
1535 }
1536
1537 #if defined( WBXML_ENCODER_USE_STRTBL )
1538 if (encoder->use_strtbl) {
1539 if ((elt = wbxml_strtbl_element_create(pid, FALSE)) == NULL)
1540 {
1541 wbxml_buffer_destroy(pid);
1542 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
1543 }
1544
1545 if (!wbxml_strtbl_add_element(encoder,
1546 elt,
1547 &public_id_index,
1548 &added))
1549 {
1550 wbxml_strtbl_element_destroy(elt);
1551 if (pid) wbxml_buffer_destroy(pid);
1552 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
1553 }
1554
1555 /* "added" means that pid was consumed by encoder.
1556 * So never free pid if added is TRUE.
1557 */
1558 if (!added)
1559 wbxml_strtbl_element_destroy(elt);
1560
1561 strstbl_len = encoder->strstbl_len;
1562 }
1563 else {
1564 #endif /* WBXML_ENCODER_USE_STRTBL */
1565 /* Length of String Table is length of XML Public ID (plus the NULL char) */
1566 strstbl_len = wbxml_buffer_len(pid) + 1;
1567
1568 /* There is only the XML Public ID in String Table */
1569 public_id_index = 0;
1570 #if defined( WBXML_ENCODER_USE_STRTBL )
1571 }
1572 #endif /* WBXML_ENCODER_USE_STRTBL */
1573
1574 pi_in_strtbl = TRUE;
1575 }
1576 }
1577
1578 /* Encode Public ID */
1579 /* publicid = mb_u_int32 | ( zero index ) */
1580 if (pi_in_strtbl) {
1581 /* Encode XML Public ID String Table index */
1582 if (!wbxml_buffer_append_char(header, 0x00) ||
1583 !wbxml_buffer_append_mb_uint_32(header, public_id_index))
1584 {
1585 if (pid && !added) wbxml_buffer_destroy(pid);
1586 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
1587 }
1588 }
1589 else {
1590 /* Encode WBXML Public ID */
1591 if (!wbxml_buffer_append_mb_uint_32(header, public_id))
1592 {
1593 return WBXML_ERROR_ENCODER_APPEND_DATA;
1594 }
1595 }
1596
1597 /* Encode Charset (default: UTF-8) and String Table Length */
1598 /** @todo Handle correctly the charset */
1599 if (!wbxml_buffer_append_mb_uint_32(header, WBXML_ENCODER_DEFAULT_CHARSET) ||
1600 !wbxml_buffer_append_mb_uint_32(header, strstbl_len))
1601 {
1602 if (pid && !added) wbxml_buffer_destroy(pid);
1603 return WBXML_ERROR_ENCODER_APPEND_DATA;
1604 }
1605
1606 /* Encode WBXML String Table */
1607 #if defined( WBXML_ENCODER_USE_STRTBL )
1608 if (encoder->use_strtbl) {
1609 if ((ret = wbxml_strtbl_construct(header,(WBXMLList *) encoder->strstbl)) != WBXML_OK)
1610 {
1611 if (pid && !added) wbxml_buffer_destroy(pid);
1612 return ret;
1613 }
1614 }
1615 else {
1616 #endif /* WBXML_ENCODER_USE_STRTBL */
1617
1618 if (pid != NULL) {
1619 if (!wbxml_buffer_append(header, pid))
1620 {
1621 wbxml_buffer_destroy(pid);
1622 return WBXML_ERROR_ENCODER_APPEND_DATA;
1623 }
1624
1625 if (!wbxml_buffer_append_char(header, WBXML_STR_END))
1626 {
1627 wbxml_buffer_destroy(pid);
1628 return WBXML_ERROR_ENCODER_APPEND_DATA;
1629 }
1630
1631 /* Clean up */
1632 wbxml_buffer_destroy(pid);
1633 pid = NULL;
1634 }
1635
1636 #if defined( WBXML_ENCODER_USE_STRTBL )
1637 }
1638 if (pid && !added) wbxml_buffer_destroy(pid);
1639 #endif /* WBXML_ENCODER_USE_STRTBL */
1640
1641 return WBXML_OK;
1642 }
1643
1644
1645 /****************************
1646 * WBXML Encoding Functions
1647 */
1648
1649 /**
1650 * @brief Encode a WBXML End Token
1651 * @param encoder The WBXML Encoder
1652 * @return WBXML_OK if encoding is OK, an error code otherwise
1653 */
wbxml_encode_end(WBXMLEncoder * encoder)1654 static WBXMLError wbxml_encode_end(WBXMLEncoder *encoder)
1655 {
1656 /* Append END */
1657 if (!wbxml_buffer_append_char(encoder->output, WBXML_END))
1658 return WBXML_ERROR_ENCODER_APPEND_DATA;
1659
1660 return WBXML_OK;
1661 }
1662
1663
1664 /**
1665 * @brief Encode a WBXML Tag
1666 * @param encoder The WBXML Encoder
1667 * @param node The element to encode
1668 * @param has_content Does the element has content ?
1669 * @return WBXML_OK if encoding is OK, an error code otherwise
1670 */
wbxml_encode_tag(WBXMLEncoder * encoder,WBXMLTreeNode * node,WB_BOOL has_content)1671 static WBXMLError wbxml_encode_tag(WBXMLEncoder *encoder, WBXMLTreeNode *node, WB_BOOL has_content)
1672 {
1673 const WBXMLTagEntry *tag = NULL;
1674 WB_UTINY token = 0x00, page = 0x00;
1675
1676 if (!node || !node->name) {
1677 return WBXML_ERROR_UNKNOWN_TAG;
1678 }
1679 if (node->name->type == WBXML_VALUE_TOKEN) {
1680 token = node->name->u.token->wbxmlToken;
1681 page = node->name->u.token->wbxmlCodePage;
1682
1683 /* Current Tag */
1684 encoder->current_tag = node->name->u.token;
1685 }
1686 else {
1687 /* Search tag in Tags Table */
1688 if ((tag = wbxml_tables_get_tag_from_xml(encoder->lang, encoder->tagCodePage, wbxml_tag_get_xml_name(node->name))) != NULL)
1689 {
1690 token = tag->wbxmlToken;
1691 page = tag->wbxmlCodePage;
1692
1693 /* Current Tag */
1694 encoder->current_tag = tag;
1695 }
1696 else
1697 encoder->current_tag = NULL;
1698 }
1699
1700 /* Check if this element has content */
1701 if (has_content)
1702 token |= WBXML_TOKEN_WITH_CONTENT;
1703
1704 /* Check if this element has attributes */
1705 /** @todo Check if the attributes will really be tokenized. There can be ignored attributes, and so NO attribute
1706 * tokenized at all.
1707 */
1708 if ((node->attrs != NULL) && (encoder->lang->attrTable != NULL) /** @todo Fast patch for SyncML (change this) */)
1709 token |= WBXML_TOKEN_WITH_ATTRS;
1710
1711 /* Encode Token */
1712 if ((token & WBXML_TOKEN_MASK) == 0x00)
1713 return wbxml_encode_tag_literal(encoder, (WB_UTINY *) wbxml_tag_get_xml_name(node->name), token);
1714 else
1715 return wbxml_encode_tag_token(encoder, token, page);
1716 }
1717
1718
1719 /**
1720 * @brief Encode a WBXML Literal Token
1721 * @param encoder The WBXML Encoder
1722 * @param tag The literal tag to encode
1723 * @param mask The WBXML Mask for this tag
1724 * @return WBXML_OK if encoding is OK, an error code otherwise
1725 * @note stag = (literalTag index)
1726 * literalTag = LITERAL | LITERAL_A | LITERAL_C | LITERAL_AC
1727 * index = mb_u_int32
1728 */
wbxml_encode_tag_literal(WBXMLEncoder * encoder,const WB_UTINY * tag,WB_UTINY mask)1729 static WBXMLError wbxml_encode_tag_literal(WBXMLEncoder *encoder, const WB_UTINY *tag, WB_UTINY mask)
1730 {
1731 #if defined( WBXML_ENCODER_USE_STRTBL )
1732 WBXMLStringTableElement *elt = NULL;
1733 WBXMLBuffer *buff = NULL;
1734 WB_ULONG index = 0;
1735 WB_BOOL added = FALSE;
1736
1737 /* If String Table generation is disabled, we can't generate this Literal Tag */
1738 if (!encoder->use_strtbl)
1739 return WBXML_ERROR_STRTBL_DISABLED;
1740
1741 /* Add tag in String Table */
1742 if (((buff = wbxml_buffer_create(tag, WBXML_STRLEN(tag), WBXML_STRLEN(tag))) == NULL) ||
1743 ((elt = wbxml_strtbl_element_create(buff, FALSE)) == NULL) ||
1744 (!wbxml_strtbl_add_element(encoder, elt, &index, &added)))
1745 {
1746 wbxml_strtbl_element_destroy(elt);
1747 wbxml_buffer_destroy(buff);
1748 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
1749 }
1750
1751 /* If already exists in String Table: clean-up */
1752 if (!added)
1753 wbxml_strtbl_element_destroy(elt);
1754
1755 /* Encode literalTag index */
1756 if ((!wbxml_buffer_append_char(encoder->output, (WB_UTINY) (WBXML_LITERAL | mask))) ||
1757 (!wbxml_buffer_append_mb_uint_32(encoder->output, index)))
1758 {
1759 return WBXML_ERROR_ENCODER_APPEND_DATA;
1760 }
1761
1762 return WBXML_OK;
1763 #else
1764 /* No String Table Support */
1765 return WBXML_ERROR_STRTBL_DISABLED;
1766 #endif /* WBXML_ENCODER_USE_STRTBL */
1767 }
1768
1769
1770 /**
1771 * @brief Encode a WBXML Tag Token
1772 * @param encoder The WBXML Encoder
1773 * @param token The WBXML Tag Token to encode
1774 * @param page The WBXML CodePage for this Token
1775 * @return WBXML_OK if encoding is OK, an error code otherwise
1776 * @note element = ([switchPage] stag)
1777 * switchPage = SWITCH_PAGE pageindex
1778 * stag = TAG
1779 * pageindex = u_int8
1780 */
wbxml_encode_tag_token(WBXMLEncoder * encoder,WB_UTINY token,WB_UTINY page)1781 static WBXMLError wbxml_encode_tag_token(WBXMLEncoder *encoder, WB_UTINY token, WB_UTINY page)
1782 {
1783 /* Switch Page if needed */
1784 if (encoder->tagCodePage != page)
1785 {
1786 if ((!wbxml_buffer_append_char(encoder->output, WBXML_SWITCH_PAGE)) ||
1787 (!wbxml_buffer_append_char(encoder->output, page)))
1788 {
1789 return WBXML_ERROR_ENCODER_APPEND_DATA;
1790 }
1791
1792 encoder->tagCodePage = page;
1793 }
1794
1795 /* Add Token */
1796 if (!wbxml_buffer_append_char(encoder->output, token))
1797 return WBXML_ERROR_ENCODER_APPEND_DATA;
1798
1799 return WBXML_OK;
1800 }
1801
1802
1803 /**
1804 * @brief Encode a WBXML Attribute
1805 * @param encoder [in] The WBXML Encoder
1806 * @param attribute [in] The Attribute to encode
1807 * @return WBXML_OK if encoding is OK, an error code otherwise
1808 * @note attribute = attrStart *attrValue
1809 */
wbxml_encode_attr(WBXMLEncoder * encoder,WBXMLAttribute * attribute)1810 static WBXMLError wbxml_encode_attr(WBXMLEncoder *encoder, WBXMLAttribute *attribute)
1811 {
1812 WB_UTINY *value = NULL;
1813 WBXMLError ret = WBXML_OK;
1814
1815 /* Encode Attribute Start */
1816 if ((ret = wbxml_encode_attr_start(encoder, attribute, &value)) != WBXML_OK)
1817 return ret;
1818
1819 /* Encode Attribute Value */
1820 if (value != NULL) {
1821 if ((ret = wbxml_encode_value_element_buffer(encoder, value, WBXML_VALUE_ELEMENT_CTX_ATTR)) != WBXML_OK)
1822 return ret;
1823 }
1824
1825 /* Reset Current Attribute */
1826 encoder->current_attr = NULL;
1827
1828 return WBXML_OK;
1829 }
1830
1831
1832 /**
1833 * @brief Encode a WBXML Attribute Start
1834 * @param encoder [in] The WBXML Encoder
1835 * @param attribute [in] The Attribute
1836 * @param value [out] Pointer to the value to encode
1837 * @return WBXML_OK if encoding is OK, an error code otherwise
1838 * @note The 'value' result correspond to the value there is still to encode
1839 * For example, in Wireless-Village, to encode:
1840 * xmlns="http://www.wireless-village.org/CSP1.1"
1841 * We first encode:
1842 * xmlns="http://www.wireless-village.org/CSP (start token: 0x05)
1843 * Then:
1844 * "1.1" as an inline string
1845 */
wbxml_encode_attr_start(WBXMLEncoder * encoder,WBXMLAttribute * attribute,WB_UTINY ** value)1846 static WBXMLError wbxml_encode_attr_start(WBXMLEncoder *encoder, WBXMLAttribute *attribute, WB_UTINY **value)
1847 {
1848 const WBXMLAttrEntry *attr = NULL;
1849 WB_UTINY *value_left = NULL;
1850 WB_UTINY token = 0x00, page = 0x00;
1851
1852 *value = wbxml_buffer_get_cstr(attribute->value);
1853
1854 if (attribute->name->type == WBXML_VALUE_TOKEN) {
1855 /* We already have Token / Page pair for this Attribute Start */
1856 token = attribute->name->u.token->wbxmlToken;
1857 page = attribute->name->u.token->wbxmlCodePage;
1858
1859 /* Current Attribute */
1860 encoder->current_attr = attribute->name->u.token;
1861
1862 /* If there is a Start Value associated to the Attribute Name token... */
1863 if (attribute->name->u.token->xmlValue != NULL)
1864 {
1865 /* ... Check that we have it at start of full Attribute Value */
1866 if (WBXML_STRNCMP(wbxml_buffer_get_cstr(attribute->value),
1867 attribute->name->u.token->xmlValue,
1868 WBXML_STRLEN(attribute->name->u.token->xmlValue)) == 0)
1869 {
1870 /* Check if you have still a part in the Attribute Value to encode */
1871 if (wbxml_buffer_len(attribute->value) > WBXML_STRLEN(attribute->name->u.token->xmlValue))
1872 {
1873 /* There is still a part in the Value to encode */
1874 *value = wbxml_buffer_get_cstr(attribute->value) + WBXML_STRLEN(attribute->name->u.token->xmlValue);
1875 }
1876 else
1877 *value = NULL;
1878 }
1879 else {
1880 /** @todo Should we stop everything and generate an error ? */
1881 WBXML_WARNING((WBXML_ENCODER, "wbxml_encode_attr_start() => Attribute Value doesn't match Attribute Token"));
1882
1883 /* Current Attribute */
1884 encoder->current_attr = NULL;
1885
1886 /* Encode Attribute Literal */
1887 return wbxml_encode_attr_start_literal(encoder, wbxml_attribute_get_xml_name(attribute));
1888 }
1889 }
1890
1891 /* Encode Attribute Token */
1892 return wbxml_encode_attr_token(encoder, token, page);
1893 }
1894 else {
1895 /* Search in Attribute table */
1896 if ((attr = wbxml_tables_get_attr_from_xml(encoder->lang,
1897 (WB_UTINY *)attribute->name->u.token->xmlName,
1898 wbxml_buffer_get_cstr(attribute->value),
1899 &value_left)) != NULL)
1900 {
1901 token = attr->wbxmlToken;
1902 page = attr->wbxmlCodePage;
1903
1904 /* Current Attribute */
1905 encoder->current_attr = attr;
1906
1907 /* If there is still a part in Attribute Value to encode */
1908 *value = value_left;
1909
1910 /* Encode Attribute Token */
1911 return wbxml_encode_attr_token(encoder, token, page);
1912 }
1913 else {
1914 /* Current Attribute */
1915 encoder->current_attr = NULL;
1916
1917 /* Encode Attribute Literal */
1918 return wbxml_encode_attr_start_literal(encoder, wbxml_attribute_get_xml_name(attribute));
1919 }
1920 }
1921 }
1922
1923
1924 /**
1925 * @brief Encode a WBXML Attribute Value
1926 * @param encoder The WBXML Encoder
1927 * @param buffer The Value Element Buffer to encode
1928 * @param ctx Value Element Context (Attribute Value or Content)
1929 * @return WBXML_OK if encoding is OK, an error code otherwise
1930 * @note attrStart = *attrValue
1931 * attrValue = string | extension | entity | opaque
1932 *
1933 * AND: element = *content
1934 * content = string | extension | entity | opaque
1935 */
wbxml_encode_value_element_buffer(WBXMLEncoder * encoder,WB_UTINY * buffer,WBXMLValueElementCtx ctx)1936 static WBXMLError wbxml_encode_value_element_buffer(WBXMLEncoder *encoder, WB_UTINY *buffer, WBXMLValueElementCtx ctx)
1937 {
1938 WBXMLList *lresult = NULL;
1939 WBXMLBuffer *buff = NULL;
1940 WBXMLValueElement *elt = NULL, *new_elt = NULL;
1941 WB_ULONG i = 0, j = 0, index = 0;
1942 WB_UTINY *the_buffer = buffer;
1943 WBXMLError ret = WBXML_OK;
1944
1945 #if defined( WBXML_ENCODER_USE_STRTBL )
1946 WBXMLStringTableElement *strtbl_elt = NULL;
1947 #endif /* WBXML_ENCODER_USE_STRTBL */
1948
1949 if ((buffer == NULL) || (*buffer == '\0'))
1950 return WBXML_OK;
1951
1952
1953 /*********************************************************
1954 * Encoder Language Specific Attribute Values
1955 */
1956
1957 if (ctx == WBXML_VALUE_ELEMENT_CTX_ATTR) {
1958 switch (encoder->lang->langID) {
1959 #if defined( WBXML_SUPPORT_SI )
1960 case WBXML_LANG_SI10:
1961 /* SI 1.0: Encode date for 'created' and 'si-expires' attributes */
1962 if (encoder->current_attr == NULL)
1963 break;
1964
1965 if ((encoder->current_attr->wbxmlCodePage == 0x00) &&
1966 ((encoder->current_attr->wbxmlToken == 0x0a) || (encoder->current_attr->wbxmlToken == 0x10)))
1967 {
1968 return wbxml_encode_datetime(encoder, buffer);
1969 }
1970 break;
1971 #endif /* WBXML_SUPPORT_SI */
1972
1973 #if defined( WBXML_SUPPORT_EMN )
1974 case WBXML_LANG_EMN10:
1975 /* EMN 1.0: Encode date for 'timestamp' attribute */
1976 if (encoder->current_attr == NULL)
1977 break;
1978
1979 if ((encoder->current_attr->wbxmlCodePage == 0x00) && (encoder->current_attr->wbxmlToken == 0x05))
1980 {
1981 return wbxml_encode_datetime(encoder, buffer);
1982 }
1983 break;
1984 #endif /* WBXML_SUPPORT_EMN */
1985
1986 #if defined( WBXML_SUPPORT_OTA_SETTINGS )
1987 case WBXML_LANG_OTA_SETTINGS:
1988 /**
1989 * Nokia OTA Settings support for the ICON value in bookmarks.
1990 * The encoding is done using base64 encoded images in XML, and encoding it as OPAQUE data in the WBXML.
1991 * The icon is embedded using an PARM element with name ICON.
1992 */
1993 if ((encoder->current_attr->wbxmlCodePage == 0x00) &&
1994 (encoder->current_attr->wbxmlToken == 0x11))
1995 {
1996 if ((ret = wbxml_encode_ota_nokia_icon(encoder, buffer)) != WBXML_NOT_ENCODED)
1997 return ret;
1998 }
1999 break;
2000 #endif /* WBXML_SUPPORT_OTA_SETTINGS */
2001
2002 default:
2003 break;
2004 }
2005 }
2006
2007
2008 /*********************************************************
2009 * Encoder Language Specific Content Text Values
2010 */
2011
2012 /* If this is a Text Content (not in a CDATA section) */
2013 if ((ctx == WBXML_VALUE_ELEMENT_CTX_CONTENT) && (!encoder->in_cdata))
2014 {
2015 #if defined( WBXML_SUPPORT_WV )
2016 /* If this is a Wireless-Village 1.1 / 1.2 document */
2017 if ((encoder->lang->langID == WBXML_LANG_WV_CSP11) ||
2018 (encoder->lang->langID == WBXML_LANG_WV_CSP12))
2019 {
2020 /* Here we try to encode Specific WV Content. If this buffer is not a WV Data Type buffer, or
2021 * if it can't be FULLY encoded as an Extension Token, then this function returns WBXML_NOT_ENCODED.
2022 * If so, the buffer will be encoded as String latter.
2023 */
2024 if ((ret = wbxml_encode_wv_content(encoder, buffer)) != WBXML_NOT_ENCODED)
2025 return ret;
2026 }
2027 #endif /* WBXML_SUPPORT_WV */
2028
2029 #if defined( WBXML_SUPPORT_DRMREL )
2030 /* If this is a DRMREL 1.0 document */
2031 if (encoder->lang->langID == WBXML_LANG_DRMREL10)
2032 {
2033 /* Here we try to encode Specific DRMREL Content. If this buffer is not a DRMREL Data Type buffer
2034 * this function returns WBXML_NOT_ENCODED.
2035 * If so, the buffer will be encoded as String latter.
2036 */
2037 if ((ret = wbxml_encode_drmrel_content(encoder, buffer)) != WBXML_NOT_ENCODED)
2038 return ret;
2039 }
2040 #endif /* WBXML_SUPPORT_DRMREL */
2041
2042 #if defined( WBXML_SUPPORT_SYNCML )
2043 /* If this is a SyncML document ? */
2044 if ((encoder->lang->langID == WBXML_LANG_SYNCML_SYNCML10) ||
2045 (encoder->lang->langID == WBXML_LANG_SYNCML_SYNCML11) ||
2046 (encoder->lang->langID == WBXML_LANG_SYNCML_SYNCML12))
2047 {
2048 /** @todo We must check too if we are in a <Type> */
2049
2050 /* Change text in <Type> from "application/vnd.syncml-devinf+xml" to "application/vnd.syncml-devinf+wbxml" */
2051 if (WBXML_STRCASECMP(buffer, "application/vnd.syncml-devinf+xml") == 0) {
2052 the_buffer = (WB_UTINY*) "application/vnd.syncml-devinf+wbxml";
2053 }
2054 /* Change text in <Type> from "application/vnd.syncml.dmtnds+xml" to "application/vnd.syncml.dmtnds+wbxml" */
2055 if (WBXML_STRCASECMP(buffer, "application/vnd.syncml.dmtnds+xml") == 0) {
2056 the_buffer = (WB_UTINY*) "application/vnd.syncml.dmtnds+wbxml";
2057 }
2058 }
2059 #endif /* WBXML_SUPPORT_SYNCML */
2060 }
2061
2062
2063 /*********************************************************
2064 * @todo Search first for simple cases !
2065 */
2066
2067
2068 /*********************************************************
2069 * We search the list of Value Elements that represents
2070 * this Value buffer
2071 */
2072
2073 /* Create Result List */
2074 if ((lresult = wbxml_list_create()) == NULL)
2075 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
2076
2077 /* Create primary Buffer */
2078 if ((buff = wbxml_buffer_create_from_cstr(the_buffer)) == NULL) {
2079 wbxml_list_destroy(lresult, NULL);
2080 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
2081 }
2082
2083 /* Create Value Element for this buffer */
2084 if ((elt = wbxml_value_element_create()) == NULL) {
2085 wbxml_buffer_destroy(buff);
2086 wbxml_list_destroy(lresult, NULL);
2087 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
2088 }
2089
2090 elt->type = WBXML_VALUE_ELEMENT_STRING;
2091 elt->u.str = buff;
2092
2093 /* Append this Buffer to Result List */
2094 if (!wbxml_list_append(lresult, elt)) {
2095 wbxml_value_element_destroy(elt);
2096 wbxml_list_destroy(lresult, NULL);
2097 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
2098 }
2099
2100 /* If this is an Attribute Value */
2101 if (ctx == WBXML_VALUE_ELEMENT_CTX_ATTR)
2102 {
2103 /*********************************************************
2104 * Search for Attribute Value Tokens
2105 */
2106
2107 if (encoder->lang->attrValueTable != NULL) {
2108 /* For each Attribute Value Token */
2109 j = 0;
2110 while (encoder->lang->attrValueTable[j].xmlName != NULL)
2111 {
2112 /* For each Value Element */
2113 for (i = 0; i < wbxml_list_len(lresult); i++) {
2114 if ((elt = (WBXMLValueElement *) wbxml_list_get(lresult, i)) == NULL)
2115 continue;
2116
2117 if (elt->type != WBXML_VALUE_ELEMENT_STRING)
2118 continue;
2119
2120 /* Is this Attribute Value contained in this Buffer ? */
2121 if (wbxml_buffer_search_cstr(elt->u.str, (WB_UTINY *)encoder->lang->attrValueTable[j].xmlName, 0, &index)) {
2122 /* Create new Value Element */
2123 if ((new_elt = wbxml_value_element_create()) == NULL) {
2124 wbxml_list_destroy(lresult, wbxml_value_element_destroy_item);
2125 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
2126 }
2127
2128 new_elt->type = WBXML_VALUE_ELEMENT_ATTR_TOKEN;
2129 new_elt->u.attr = &(encoder->lang->attrValueTable[j]);
2130
2131 /* Insert new Value Element in List */
2132 if (!wbxml_list_insert(lresult, (void *) new_elt, i + 1)) {
2133 wbxml_value_element_destroy(new_elt);
2134 wbxml_list_destroy(lresult, wbxml_value_element_destroy_item);
2135 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
2136 }
2137
2138 /* Check if there is still the end of the String to encode */
2139 if (index + WBXML_STRLEN(encoder->lang->attrValueTable[j].xmlName) < wbxml_buffer_len(elt->u.str)) {
2140 /* Create new Value Element */
2141 if ((new_elt = wbxml_value_element_create()) == NULL) {
2142 wbxml_list_destroy(lresult, wbxml_value_element_destroy_item);
2143 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
2144 }
2145
2146 new_elt->type = WBXML_VALUE_ELEMENT_STRING;
2147 new_elt->u.str = wbxml_buffer_create_from_cstr(wbxml_buffer_get_cstr(elt->u.str) + index + WBXML_STRLEN(encoder->lang->attrValueTable[j].xmlName));
2148
2149 /* Insert new Value Element in List */
2150 if ((new_elt->u.str == NULL) ||
2151 !wbxml_list_insert(lresult, (void *) new_elt, i + 2))
2152 {
2153 wbxml_value_element_destroy(new_elt);
2154 wbxml_list_destroy(lresult, wbxml_value_element_destroy_item);
2155 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
2156 }
2157 }
2158
2159 /* Remove the Attribute Value found in Value Element */
2160 wbxml_buffer_delete(elt->u.str, index, wbxml_buffer_len(elt->u.str) - index);
2161 } /* if */
2162 } /* for */
2163 j++;
2164 } /* while */
2165 } /* if */
2166 }
2167
2168 /* If this is a Text Content (not in a CDATA section) */
2169 if ((ctx == WBXML_VALUE_ELEMENT_CTX_CONTENT) && (!encoder->in_cdata))
2170 {
2171 /*********************************************************
2172 * Search for Extension Tokens
2173 */
2174
2175 /** @todo Finish Extension Tokens Search */
2176
2177 if (encoder->lang->extValueTable != NULL) {
2178 /* For each Extension Token */
2179 j = 0;
2180 while (encoder->lang->extValueTable[j].xmlName != NULL)
2181 {
2182 /* For each Value Element */
2183 for (i = 0; i < wbxml_list_len(lresult); i++) {
2184 if ((elt = (WBXMLValueElement *) wbxml_list_get(lresult, i)) == NULL)
2185 continue;
2186
2187 if (elt->type != WBXML_VALUE_ELEMENT_STRING)
2188 continue;
2189
2190 /* Ignores the "1 char Extension Tokens" */
2191 if (WBXML_STRLEN(encoder->lang->extValueTable[j].xmlName) < 2)
2192 continue;
2193
2194 /* Is this Extension Token contained in this Buffer ?
2195 *
2196 * The Extension Token must start at the beginning of
2197 * the buffer. Otherwise we can damage normal text
2198 * entities like 'My IM-application.' If 'IM' is an
2199 * Extension Token.
2200 *
2201 * Assumption: The buffer is already normalized.
2202 */
2203 if (wbxml_buffer_compare_cstr(elt->u.str, (WB_TINY *) encoder->lang->extValueTable[j].xmlName) == 0)
2204 {
2205 /* Create new Value Element */
2206 if ((new_elt = wbxml_value_element_create()) == NULL) {
2207 wbxml_list_destroy(lresult, wbxml_value_element_destroy_item);
2208 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
2209 }
2210
2211 new_elt->type = WBXML_VALUE_ELEMENT_EXTENSION;
2212 new_elt->u.ext = &(encoder->lang->extValueTable[j]);
2213
2214 /* Insert new Value Element in List */
2215 if (!wbxml_list_insert(lresult, (void *) new_elt, i + 1)) {
2216 wbxml_value_element_destroy(new_elt);
2217 wbxml_list_destroy(lresult, wbxml_value_element_destroy_item);
2218 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
2219 }
2220
2221 /* Check if there is still the end of the String to encode */
2222 if (index + WBXML_STRLEN(encoder->lang->extValueTable[j].xmlName) < wbxml_buffer_len(elt->u.str)) {
2223 /* Create new Value Element */
2224 if ((new_elt = wbxml_value_element_create()) == NULL) {
2225 wbxml_list_destroy(lresult, wbxml_value_element_destroy_item);
2226 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
2227 }
2228
2229 new_elt->type = WBXML_VALUE_ELEMENT_STRING;
2230 new_elt->u.str = wbxml_buffer_create_from_cstr(wbxml_buffer_get_cstr(elt->u.str) + index + WBXML_STRLEN(encoder->lang->extValueTable[j].xmlName));
2231
2232 /* Insert new Value Element in List */
2233 if ((new_elt->u.str == NULL) ||
2234 !wbxml_list_insert(lresult, (void *) new_elt, i + 2))
2235 {
2236 wbxml_value_element_destroy(new_elt);
2237 wbxml_list_destroy(lresult, wbxml_value_element_destroy_item);
2238 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
2239 }
2240 }
2241
2242 /* Remove the Attribute Value found in Value Element */
2243 wbxml_buffer_delete(elt->u.str, index, wbxml_buffer_len(elt->u.str) - index);
2244 } /* if */
2245 } /* for */
2246 j++;
2247 } /* while */
2248 } /* if */
2249 }
2250
2251
2252 #if defined( WBXML_ENCODER_USE_STRTBL )
2253
2254 /***********************************************************************
2255 * Search for String Table References
2256 * (except if this is a Content string and we are in a CDATA section)
2257 */
2258
2259 if (encoder->use_strtbl && !(encoder->in_cdata && (ctx == WBXML_VALUE_ELEMENT_CTX_CONTENT))) {
2260 /* For each String Table Element */
2261 for (j = 0; j < wbxml_list_len(encoder->strstbl); j++) {
2262 if ((strtbl_elt = (WBXMLStringTableElement *) wbxml_list_get(encoder->strstbl, j)) == NULL)
2263 continue;
2264
2265 /* For each Value Element */
2266 for (i = 0; i < wbxml_list_len(lresult); i++) {
2267 if ((elt = (WBXMLValueElement *) wbxml_list_get(lresult, i)) == NULL)
2268 continue;
2269
2270 if (elt->type != WBXML_VALUE_ELEMENT_STRING)
2271 continue;
2272
2273 /* Is the String Table Element contained in this Buffer ? */
2274 if (wbxml_buffer_search(elt->u.str, strtbl_elt->string, 0, &index)) {
2275 /* Create new Value Element */
2276 if ((new_elt = wbxml_value_element_create()) == NULL) {
2277 wbxml_list_destroy(lresult, wbxml_value_element_destroy_item);
2278 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
2279 }
2280
2281 new_elt->type = WBXML_VALUE_ELEMENT_TABLEREF;
2282 new_elt->u.index = strtbl_elt->offset;
2283
2284 /* Insert new Value Element in List */
2285 if (!wbxml_list_insert(lresult, (void *) new_elt, i + 1)) {
2286 wbxml_value_element_destroy(new_elt);
2287 wbxml_list_destroy(lresult, wbxml_value_element_destroy_item);
2288 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
2289 }
2290
2291 /* Check if there is still the end of the String to encode */
2292 if (index + wbxml_buffer_len(strtbl_elt->string) < wbxml_buffer_len(elt->u.str)) {
2293 /* Create new Value Element */
2294 if ((new_elt = wbxml_value_element_create()) == NULL) {
2295 wbxml_list_destroy(lresult, wbxml_value_element_destroy_item);
2296 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
2297 }
2298
2299 new_elt->type = WBXML_VALUE_ELEMENT_STRING;
2300 new_elt->u.str = wbxml_buffer_create_from_cstr(wbxml_buffer_get_cstr(elt->u.str) + index + wbxml_buffer_len(strtbl_elt->string));
2301
2302 /* Insert new Value Element in List */
2303 if ((new_elt->u.str == NULL) ||
2304 !wbxml_list_insert(lresult, (void *) new_elt, i + 2))
2305 {
2306 wbxml_value_element_destroy(new_elt);
2307 wbxml_list_destroy(lresult, wbxml_value_element_destroy_item);
2308 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
2309 }
2310 }
2311
2312 /* Remove the Attribute Value found in Value Element */
2313 wbxml_buffer_delete(elt->u.str, index, wbxml_buffer_len(elt->u.str) - index);
2314 } /* if */
2315 } /* for */
2316 } /* for */
2317 } /* if */
2318
2319 #endif /* WBXML_ENCODER_USE_STRTBL */
2320
2321
2322 /*********************************************************
2323 * Encode Value Element Buffer
2324 */
2325
2326 ret = wbxml_encode_value_element_list(encoder, lresult);
2327
2328 /* Clean-up */
2329 wbxml_list_destroy(lresult, wbxml_value_element_destroy_item);
2330
2331 return ret;
2332 }
2333
2334
2335 /**
2336 * @brief Encode a WBXML Value Element List
2337 * @param encoder The WBXML Encoder
2338 * @param list The Value Element list
2339 * @return WBXML_OK if encoding is OK, an error code otherwise
2340 */
wbxml_encode_value_element_list(WBXMLEncoder * encoder,WBXMLList * list)2341 static WBXMLError wbxml_encode_value_element_list(WBXMLEncoder *encoder, WBXMLList *list)
2342 {
2343 WBXMLValueElement *elt = NULL;
2344 WB_ULONG i = 0;
2345 WBXMLError ret = WBXML_OK;
2346
2347 if (encoder == NULL)
2348 return WBXML_ERROR_INTERNAL;
2349
2350 if (list == NULL)
2351 return WBXML_OK;
2352
2353 for (i = 0; i < wbxml_list_len(list); i++) {
2354 if ((elt = (WBXMLValueElement *) wbxml_list_get(list, i)) == NULL)
2355 continue;
2356
2357 switch (elt->type) {
2358 case WBXML_VALUE_ELEMENT_STRING:
2359 /* Inline String */
2360 if (wbxml_buffer_len(elt->u.str) > 0) {
2361 if ((ret = wbxml_encode_inline_string(encoder, elt->u.str)) != WBXML_OK)
2362 return ret;
2363 }
2364 break;
2365
2366 #if defined( WBXML_ENCODER_USE_STRTBL )
2367 case WBXML_VALUE_ELEMENT_TABLEREF:
2368 /* String Table Reference */
2369 if ((ret = wbxml_encode_tableref(encoder, elt->u.index)) != WBXML_OK)
2370 return ret;
2371 break;
2372 #endif /* WBXML_ENCODER_USE_STRTBL */
2373
2374 case WBXML_VALUE_ELEMENT_EXTENSION:
2375 /* Encode Extension Token */
2376 if ((ret = wbxml_encode_inline_integer_extension_token(encoder, WBXML_EXT_T_0, elt->u.ext->wbxmlToken)) != WBXML_OK)
2377 return ret;
2378 break;
2379
2380 case WBXML_VALUE_ELEMENT_OPAQUE:
2381 /** @todo Opaque */
2382 break;
2383
2384 case WBXML_VALUE_ELEMENT_ATTR_TOKEN:
2385 /* Attribute Value Token */
2386 if ((ret = wbxml_encode_attr_token(encoder, elt->u.attr->wbxmlToken, elt->u.attr->wbxmlCodePage)) != WBXML_OK)
2387 return ret;
2388 break;
2389
2390 default:
2391 return WBXML_ERROR_INTERNAL;
2392 }
2393 }
2394
2395 return WBXML_OK;
2396 }
2397
2398
2399 /**
2400 * @brief Encode a WBXML Literal Attribute Start
2401 * @param encoder The WBXML Encoder
2402 * @param attr The literal attr name to encode
2403 * @return WBXML_OK if encoding is OK, an error code otherwise
2404 * @note attrStart = (LITERAL index)
2405 * index = mb_u_int32
2406 */
wbxml_encode_attr_start_literal(WBXMLEncoder * encoder,const WB_UTINY * attr)2407 static WBXMLError wbxml_encode_attr_start_literal(WBXMLEncoder *encoder, const WB_UTINY *attr)
2408 {
2409 #if defined( WBXML_ENCODER_USE_STRTBL )
2410 WBXMLStringTableElement *elt = NULL;
2411 WBXMLBuffer *buff = NULL;
2412 WB_ULONG index = 0;
2413 WB_BOOL added = FALSE;
2414
2415 /* If String Table generation is disabled, we can't generate this Literal */
2416 if (!encoder->use_strtbl)
2417 return WBXML_ERROR_STRTBL_DISABLED;
2418
2419 /* Add tag in String Table */
2420 if (((buff = wbxml_buffer_create(attr, WBXML_STRLEN(attr), WBXML_STRLEN(attr))) == NULL) ||
2421 ((elt = wbxml_strtbl_element_create(buff, FALSE)) == NULL) ||
2422 (!wbxml_strtbl_add_element(encoder, elt, &index, &added)))
2423 {
2424 wbxml_strtbl_element_destroy(elt);
2425 wbxml_buffer_destroy(buff);
2426 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
2427 }
2428
2429 /* If already exists in String Table: clean-up */
2430 if (!added)
2431 wbxml_strtbl_element_destroy(elt);
2432
2433 /* Encode LITERAL index */
2434 if ((!wbxml_buffer_append_char(encoder->output, WBXML_LITERAL)) ||
2435 (!wbxml_buffer_append_mb_uint_32(encoder->output, index)))
2436 {
2437 return WBXML_ERROR_ENCODER_APPEND_DATA;
2438 }
2439
2440 return WBXML_OK;
2441 #else
2442 /* No String Table Support */
2443 return WBXML_ERROR_STRTBL_DISABLED;
2444 #endif /* WBXML_ENCODER_USE_STRTBL */
2445 }
2446
2447
2448 /**
2449 * @brief Encode a WBXML Attribute Token
2450 * @param encoder The WBXML Encoder
2451 * @param token The WBXML Attribute Token to encode
2452 * @param page The WBXML CodePage for this Token
2453 * @return WBXML_OK if encoding is OK, an error code otherwise
2454 * @note attrStart = ([switchPage] ATTRSTART)
2455 * switchPage = SWITCH_PAGE pageindex
2456 * pageindex = u_int8
2457 *
2458 * And: attrValue = ([switchPage] ATTRVALUE)
2459 */
wbxml_encode_attr_token(WBXMLEncoder * encoder,WB_UTINY token,WB_UTINY page)2460 static WBXMLError wbxml_encode_attr_token(WBXMLEncoder *encoder, WB_UTINY token, WB_UTINY page)
2461 {
2462 /* Switch Page if needed */
2463 if (encoder->attrCodePage != page)
2464 {
2465 if ((!wbxml_buffer_append_char(encoder->output, WBXML_SWITCH_PAGE)) ||
2466 (!wbxml_buffer_append_char(encoder->output, page)))
2467 {
2468 return WBXML_ERROR_ENCODER_APPEND_DATA;
2469 }
2470
2471 encoder->attrCodePage = page;
2472 }
2473
2474 /* Add Token */
2475 if (!wbxml_buffer_append_char(encoder->output, token))
2476 return WBXML_ERROR_ENCODER_APPEND_DATA;
2477
2478 return WBXML_OK;
2479 }
2480
2481
2482 /**
2483 * @brief Encode a WBXML Inline String
2484 * @param encoder The WBXML Encoder
2485 * @param str The String to encode
2486 * @return WBXML_OK if encoding is OK, an error code otherwise
2487 */
wbxml_encode_inline_string(WBXMLEncoder * encoder,WBXMLBuffer * str)2488 static WBXMLError wbxml_encode_inline_string(WBXMLEncoder *encoder, WBXMLBuffer *str)
2489 {
2490 /* Add STR_I */
2491 if (!wbxml_buffer_append_char(encoder->output, WBXML_STR_I))
2492 return WBXML_ERROR_ENCODER_APPEND_DATA;
2493
2494 /* Add String */
2495 if (!wbxml_buffer_append(encoder->output, str))
2496 return WBXML_ERROR_ENCODER_APPEND_DATA;
2497
2498 /* Add Null Termination */
2499 if (!wbxml_buffer_append_char(encoder->output, WBXML_STR_END))
2500 return WBXML_ERROR_ENCODER_APPEND_DATA;
2501
2502 return WBXML_OK;
2503 }
2504
2505
2506 /**
2507 * @brief Encode a WBXML Inline Integer Extension Token
2508 * @param encoder The WBXML Encoder
2509 * @param ext Extension Type (WBXML_EXT_T_0, WBXML_EXT_T_1 or WBXML_EXT_T_2)
2510 * @param value The Extension Token Value
2511 * @return WBXML_OK if encoding is OK, an error code otherwise
2512 * @note (WBXML 1.3 - 5.8.4.2) Inline integrer extension token = EXT_T* mb_u_int32
2513 */
wbxml_encode_inline_integer_extension_token(WBXMLEncoder * encoder,WB_UTINY ext,WB_UTINY value)2514 static WBXMLError wbxml_encode_inline_integer_extension_token(WBXMLEncoder *encoder, WB_UTINY ext, WB_UTINY value)
2515 {
2516 /* Add EXT_T* */
2517 if (!wbxml_buffer_append_char(encoder->output, ext))
2518 return WBXML_ERROR_ENCODER_APPEND_DATA;
2519
2520 /* Add Value */
2521 if (!wbxml_buffer_append_mb_uint_32(encoder->output, (WB_ULONG) value))
2522 return WBXML_ERROR_ENCODER_APPEND_DATA;
2523
2524 return WBXML_OK;
2525 }
2526
2527
2528 #if 0
2529 /**
2530 * @brief Encode a WBXML Entity
2531 * @param encoder The WBXML Encoder
2532 * @param value The Entity to encode
2533 * @return WBXML_OK if encoding is OK, an error code otherwise
2534 * @note (WBXML 1.3 - 5.8.4.3) entity = ENTITY entcode
2535 * entcode = mb_u_int32
2536 */
2537 static WBXMLError wbxml_encode_entity(WBXMLEncoder *encoder, WB_ULONG value)
2538 {
2539 /* Add ENTITY */
2540 if (!wbxml_buffer_append_char(encoder->output, WBXML_ENTITY))
2541 return WBXML_ERROR_ENCODER_APPEND_DATA;
2542
2543 /* Add entcode */
2544 if (!wbxml_buffer_append_mb_uint_32(encoder->output, value))
2545 return WBXML_ERROR_ENCODER_APPEND_DATA;
2546
2547 return WBXML_OK;
2548 }
2549 #endif /* 0 */
2550
2551
2552 /**
2553 * @brief Encode a WBXML Opaque, given a Buffer
2554 * @param encoder The WBXML Encoder
2555 * @param buff The Buffer to encode
2556 * @return WBXML_OK if encoding is OK, an error code otherwise
2557 * @note This function is simple a wrapper to wbxml_encode_opaque_data()
2558 */
wbxml_encode_opaque(WBXMLEncoder * encoder,WBXMLBuffer * buff)2559 static WBXMLError wbxml_encode_opaque(WBXMLEncoder *encoder, WBXMLBuffer *buff)
2560 {
2561 return wbxml_encode_opaque_data(encoder, wbxml_buffer_get_cstr(buff), wbxml_buffer_len(buff));
2562 }
2563
2564
2565 /**
2566 * @brief Encode a WBXML Opaque
2567 * @param encoder The WBXML Encoder
2568 * @param data The data to encode
2569 * @param data_len The data length to encode
2570 * @return WBXML_OK if encoding is OK, an error code otherwise
2571 * @note opaque = OPAQUE length *byte
2572 * length = mb_u_int32
2573 */
wbxml_encode_opaque_data(WBXMLEncoder * encoder,WB_UTINY * data,WB_ULONG data_len)2574 static WBXMLError wbxml_encode_opaque_data(WBXMLEncoder *encoder, WB_UTINY *data, WB_ULONG data_len)
2575 {
2576 /* Add WBXML_OPAQUE */
2577 if (!wbxml_buffer_append_char(encoder->output, WBXML_OPAQUE))
2578 return WBXML_ERROR_ENCODER_APPEND_DATA;
2579
2580 /* Add Length */
2581 if (!wbxml_buffer_append_mb_uint_32(encoder->output, data_len))
2582 return WBXML_ERROR_ENCODER_APPEND_DATA;
2583
2584 /* Add Buffer */
2585 if (!wbxml_buffer_append_data(encoder->output, data, data_len))
2586 return WBXML_ERROR_ENCODER_APPEND_DATA;
2587
2588 return WBXML_OK;
2589 }
2590
2591
2592 #if defined( WBXML_ENCODER_USE_STRTBL )
2593 /**
2594 * @brief Encode a WBXML String Table Reference
2595 * @param encoder The WBXML Encoder
2596 * @param offset The String Table offset
2597 * @return WBXML_OK if encoding is OK, an error code otherwise
2598 * @note tableref = STR_T index
2599 */
wbxml_encode_tableref(WBXMLEncoder * encoder,WB_ULONG offset)2600 static WBXMLError wbxml_encode_tableref(WBXMLEncoder *encoder, WB_ULONG offset)
2601 {
2602 /* Add WBXML_STR_T */
2603 if (!wbxml_buffer_append_char(encoder->output, WBXML_STR_T))
2604 return WBXML_ERROR_ENCODER_APPEND_DATA;
2605
2606 /* Add String */
2607 if (!wbxml_buffer_append_mb_uint_32(encoder->output, offset))
2608 return WBXML_ERROR_ENCODER_APPEND_DATA;
2609
2610 return WBXML_OK;
2611 }
2612 #endif /* WBXML_ENCODER_USE_STRTBL */
2613
2614
2615 /**
2616 * @brief Create a WBXMLValueElement structure
2617 * @return The newly created WBXMLValueElement structure, or NULL if not enough memory
2618 */
wbxml_value_element_create(void)2619 static WBXMLValueElement *wbxml_value_element_create(void)
2620 {
2621 WBXMLValueElement *elt = NULL;
2622
2623 if ((elt = wbxml_malloc(sizeof(WBXMLValueElement))) == NULL)
2624 return NULL;
2625
2626 elt->type = WBXML_VALUE_ELEMENT_STRING;
2627 elt->u.str = NULL;
2628
2629 return elt;
2630 }
2631
2632
2633 /**
2634 * @brief Destroy a WBXMLValueElement structure
2635 * @param elt The WBXMLValueElement structure to destroy
2636 */
wbxml_value_element_destroy(WBXMLValueElement * elt)2637 static void wbxml_value_element_destroy(WBXMLValueElement *elt)
2638 {
2639 if (elt == NULL)
2640 return;
2641
2642 switch (elt->type) {
2643 case WBXML_VALUE_ELEMENT_STRING:
2644 wbxml_buffer_destroy(elt->u.str);
2645 break;
2646 case WBXML_VALUE_ELEMENT_OPAQUE:
2647 wbxml_buffer_destroy(elt->u.buff);
2648 break;
2649 default:
2650 /* Nothing to destroy */
2651 break;
2652 }
2653
2654 wbxml_free((void*) elt);
2655 }
2656
2657
2658 /**
2659 * @brief Destroy a WBXMLValueElement structure (for wbxml_list_destroy() function)
2660 * @param elt The WBXMLValueElement structure to destroy
2661 */
wbxml_value_element_destroy_item(void * elt)2662 static void wbxml_value_element_destroy_item(void *elt)
2663 {
2664 wbxml_value_element_destroy((WBXMLValueElement *) elt);
2665 }
2666
2667
2668 /**
2669 * @brief Encode an encapsulated WBXML Tree to WBXML
2670 * @param encoder [in] The WBXML Encoder
2671 * @param tree [in] The WBXML Tree to encode
2672 * @return WBXML_OK if encoding is OK, an error code otherwise
2673 */
wbxml_encode_tree(WBXMLEncoder * encoder,WBXMLTree * tree)2674 static WBXMLError wbxml_encode_tree(WBXMLEncoder *encoder, WBXMLTree *tree)
2675 {
2676 WBXMLEncoder *new_encoder = NULL;
2677 WB_UTINY *wbxml = NULL;
2678 WB_ULONG wbxml_len = 0;
2679 WBXMLError ret = WBXML_OK;
2680
2681 if ((new_encoder = encoder_duplicate(encoder)) == NULL)
2682 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
2683
2684 /* Set Tree */
2685 new_encoder->tree = tree;
2686
2687 /* Encode to WBXML */
2688 if ((ret = wbxml_encoder_encode_tree_to_wbxml(new_encoder, &wbxml, &wbxml_len)) != WBXML_OK) {
2689 wbxml_encoder_destroy(new_encoder);
2690 return ret;
2691 }
2692
2693 /* Clean-up */
2694 wbxml_encoder_destroy(new_encoder);
2695
2696 /* Add WBXML_OPAQUE */
2697 if (!wbxml_buffer_append_char(encoder->output, WBXML_OPAQUE)) {
2698 wbxml_free(wbxml);
2699 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
2700 }
2701
2702 /* Add Length */
2703 if (!wbxml_buffer_append_mb_uint_32(encoder->output, wbxml_len)) {
2704 wbxml_free(wbxml);
2705 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
2706 }
2707
2708 /* Append wbxml to output */
2709 if (!wbxml_buffer_append_data(encoder->output, wbxml, wbxml_len)) {
2710 wbxml_free(wbxml);
2711 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
2712 }
2713
2714 /* Clean-up */
2715 wbxml_free(wbxml);
2716
2717 return WBXML_OK;
2718 }
2719
2720
2721 /****************************************
2722 * Language Specific Encoding Functions
2723 */
2724
2725 #if ( defined( WBXML_SUPPORT_SI ) || defined( WBXML_SUPPORT_EMN ) )
2726
2727 /*******************
2728 * SI 1.0 / EMN 1.0
2729 */
2730
2731 /**
2732 * @brief Encode SI %Datetime attribute value
2733 * @param encoder The WBXML Encoder
2734 * @param buffer The %Datetime value to encode
2735 * @return WBXML_OK if encoded, another error code otherwise
2736 * @note [SI] - 8.2.2. Encoding of %Datetime
2737 */
wbxml_encode_datetime(WBXMLEncoder * encoder,WB_UTINY * buffer)2738 static WBXMLError wbxml_encode_datetime(WBXMLEncoder *encoder, WB_UTINY *buffer)
2739 {
2740 WBXMLBuffer *tmp = NULL;
2741 WB_ULONG i = 0;
2742 WB_UTINY ch = 0;
2743 WBXMLError ret = WBXML_OK;
2744
2745
2746 if ((tmp = wbxml_buffer_create_from_cstr(buffer)) == NULL)
2747 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
2748
2749 /* Remove non-digit characters */
2750 while (i < wbxml_buffer_len(tmp)) {
2751 /* Get char */
2752 if (!wbxml_buffer_get_char(tmp, i, &ch)) {
2753 wbxml_buffer_destroy(tmp);
2754 return WBXML_ERROR_INTERNAL;
2755 }
2756
2757 if (!WBXML_ISDIGIT(ch)) {
2758 if ((ch != 'T') && (ch != 'Z') && (ch != '-') && (ch != ':')) {
2759 wbxml_buffer_destroy(tmp);
2760 return WBXML_ERROR_BAD_DATETIME;
2761 }
2762
2763 /* Remove it */
2764 wbxml_buffer_delete(tmp, i, 1);
2765 }
2766 else
2767 i++;
2768 }
2769
2770 /* Convert Ascii to Binary buffer */
2771 wbxml_buffer_hex_to_binary(tmp);
2772
2773 /* Remove trailing zero */
2774 wbxml_buffer_remove_trailing_zeros(tmp);
2775
2776 /* Encode it to Opaque */
2777 ret = wbxml_encode_opaque(encoder, tmp);
2778
2779 wbxml_buffer_destroy(tmp);
2780
2781 return ret;
2782 }
2783
2784 #endif /* WBXML_SUPPORT_SI || WBXML_SUPPORT_EMN */
2785
2786
2787 #if defined( WBXML_SUPPORT_WV )
2788
2789 /*******************
2790 * WV 1.1 / WV 1.2
2791 */
2792
2793 /**
2794 * @brief Encode a Wireless-Village Content buffer
2795 * @param encoder The WBXML Encoder
2796 * @param buffer The buffer to encode
2797 * @return WBXML_OK if encoded, WBXML_NOT_ENCODED if not encoded, another error code otherwise
2798 * @note This function encodes a Specific WV Data Type content, or an exact Extension Token.
2799 * If not found, this is not encoded... and it will be encoded latter as an Inline String
2800 * in wbxml_encode_value_element_buffer(). We don't deal here if this buffer CONTAINS
2801 * Extension Tokens.
2802 */
wbxml_encode_wv_content(WBXMLEncoder * encoder,WB_UTINY * buffer)2803 static WBXMLError wbxml_encode_wv_content(WBXMLEncoder *encoder, WB_UTINY *buffer)
2804 {
2805 const WBXMLExtValueEntry *ext = NULL;
2806 WBXMLWVDataType data_type = WBXML_WV_DATA_TYPE_STRING;
2807 /* WB_ULONG ucs4_ch = 0; */
2808
2809 /*
2810 * Specific Data Type Elements:
2811 *
2812 * Boolean:
2813 * Acceptance (0x00 / 0x05)
2814 * InUse (0x00 / 0x18)
2815 * Poll (0x00 / 0x21)
2816 * AllFunctionsRequest (0x01 / 0x06)
2817 * CapabilityRequest (0x01 / 0x0B)
2818 * CompletionFlag (0x01 / 0x34)
2819 * ReceiveList (0x01 / 0x36) [WV 1.2]
2820 * AnyContent (0x03 / 0x09)
2821 * DefaultList (0x04 / 0x0B)
2822 * Auto-Subscribe (0x04 / 0x1E) [WV 1.2]
2823 * DeliveryReport (0x06 / 0x08)
2824 * JoinGroup (0x07 / 0x21)
2825 * JoinedRequest (0x07 / 0x10)
2826 * SubscribeNotification (0x07 / 0x22)
2827 * CIR (0x09 / 0x05) [WV 1.2]
2828 *
2829 * Integer:
2830 * Code (0x00 / 0x0B)
2831 * ContentSize (0x00 / 0x0F)
2832 * MessageCount (0x00 / 0x1A)
2833 * Validity (0x00 / 0x3C)
2834 * KeepAliveTime (0x01 / 0x1C)
2835 * SearchFindings (0x01 / 0x25)
2836 * SearchID (0x01 / 0x26)
2837 * SearchIndex (0x01 / 0x27)
2838 * SearchLimit (0x01 / 0x28)
2839 * TimeToLive (0x01 / 0x32)
2840 * AcceptedCharSet (0x03 / 0x05)
2841 * AcceptedContentLength (0x03 / 0x06)
2842 * MultiTrans (0x03 / 0x0C)
2843 * ParserSize (0x03 / 0x0D)
2844 * ServerPollMin (0x03 / 0x0E)
2845 * TCPPort (0x03 / 0x12)
2846 * UDPPort (0x03 / 0x13)
2847 * HistoryPeriod (0x09 / 0x08) [WV 1.2]
2848 * MaxWatcherList (0x09 / 0x0A) [WV 1.2]
2849 *
2850 * Date and Time:
2851 * DateTime (0x00 / 0x11)
2852 * DeliveryTime (0x06 / 0x1A)
2853 *
2854 * Binary:
2855 * ContentData (0x00 / 0x0D) (only if we have a: "<ContentEncoding>BASE64</ContentEncoding>" associated)
2856 */
2857
2858 /****************************************
2859 * Get the Data Type of Current Element
2860 */
2861
2862 if (encoder->current_tag != NULL)
2863 {
2864 switch (encoder->current_tag->wbxmlCodePage) {
2865 case 0x00:
2866 /* Code Page: 0x00 */
2867 switch (encoder->current_tag->wbxmlToken) {
2868 case 0x05: /* Acceptance */
2869 case 0x18: /* InUse */
2870 case 0x21: /* Poll */
2871 /* BOOLEAN */
2872 data_type = WBXML_WV_DATA_TYPE_BOOLEAN;
2873 break;
2874 case 0x0B: /* Code */
2875 case 0x0F: /* ContentSize */
2876 case 0x1A: /* MessageCount */
2877 case 0x3C: /* Validity */
2878 /* INTEGER */
2879 data_type = WBXML_WV_DATA_TYPE_INTEGER;
2880 break;
2881 case 0x11: /* DateTime */
2882 /* DATE_AND_TIME */
2883 data_type = WBXML_WV_DATA_TYPE_DATE_AND_TIME;
2884 break;
2885 case 0x0D: /* ContentData */
2886 /* BINARY */
2887 /** @todo Check if we have a: "<ContentEncoding>BASE64</ContentEncoding>" associated */
2888 /*
2889 if (base64_encoded)
2890 data_type = WBXML_WV_DATA_TYPE_BINARY;
2891 else
2892 */
2893 data_type = WBXML_WV_DATA_TYPE_STRING;
2894 break;
2895 default:
2896 /* STRING */
2897 data_type = WBXML_WV_DATA_TYPE_STRING;
2898 break;
2899 }
2900 break;
2901 case 0x01:
2902 /* Code Page: 0x01 */
2903 switch (encoder->current_tag->wbxmlToken) {
2904 case 0x06: /* AllFunctionsRequest */
2905 case 0x0B: /* CapabilityRequest */
2906 case 0x34: /* CompletionFlag */
2907 case 0x36: /* ReceiveList */
2908 /* BOOLEAN */
2909 data_type = WBXML_WV_DATA_TYPE_BOOLEAN;
2910 break;
2911 case 0x1C: /* KeepAliveTime */
2912 case 0x25: /* SearchFindings */
2913 case 0x26: /* SearchID */
2914 case 0x27: /* SearchIndex */
2915 case 0x28: /* SearchLimit */
2916 case 0x32: /* TimeToLive */
2917 /* INTEGER */
2918 data_type = WBXML_WV_DATA_TYPE_INTEGER;
2919 break;
2920 default:
2921 /* STRING */
2922 data_type = WBXML_WV_DATA_TYPE_STRING;
2923 break;
2924 }
2925 break;
2926 case 0x03:
2927 /* Code Page: 0x03 */
2928 switch (encoder->current_tag->wbxmlToken) {
2929 case 0x09: /* AnyContent */
2930 /* BOOLEAN */
2931 data_type = WBXML_WV_DATA_TYPE_BOOLEAN;
2932 break;
2933 case 0x05: /* AcceptedCharSet */
2934 case 0x06: /* AcceptedContentLength */
2935 case 0x0C: /* MultiTrans */
2936 case 0x0D: /* ParserSize */
2937 case 0x0E: /* ServerPollMin */
2938 case 0x12: /* TCPPort */
2939 case 0x13: /* UDPPort */
2940 /* INTEGER */
2941 data_type = WBXML_WV_DATA_TYPE_INTEGER;
2942 break;
2943 default:
2944 /* STRING */
2945 data_type = WBXML_WV_DATA_TYPE_STRING;
2946 break;
2947 }
2948 break;
2949 case 0x04:
2950 /* Code Page: 0x04 */
2951 switch (encoder->current_tag->wbxmlToken) {
2952 case 0x0B: /* DefaultList */
2953 case 0x1E: /* Auto-Subscribe */
2954 /* BOOLEAN */
2955 data_type = WBXML_WV_DATA_TYPE_BOOLEAN;
2956 break;
2957 default:
2958 /* STRING */
2959 data_type = WBXML_WV_DATA_TYPE_STRING;
2960 break;
2961 }
2962 break;
2963 case 0x06:
2964 /* Code Page: 0x06 */
2965 switch (encoder->current_tag->wbxmlToken) {
2966 case 0x08: /* DeliveryReport */
2967 /* BOOLEAN */
2968 data_type = WBXML_WV_DATA_TYPE_BOOLEAN;
2969 break;
2970 case 0x1A: /* DeliveryTime */
2971 /* DATE AND TIME */
2972 data_type = WBXML_WV_DATA_TYPE_DATE_AND_TIME;
2973 break;
2974 default:
2975 /* STRING */
2976 data_type = WBXML_WV_DATA_TYPE_STRING;
2977 break;
2978 }
2979 break;
2980 case 0x07:
2981 /* Code Page: 0x07 */
2982 switch (encoder->current_tag->wbxmlToken) {
2983 case 0x21: /* JoinGroup */
2984 case 0x10: /* JoinedRequest */
2985 case 0x22: /* SubscribeNotification */
2986 /* BOOLEAN */
2987 data_type = WBXML_WV_DATA_TYPE_BOOLEAN;
2988 break;
2989 default:
2990 /* STRING */
2991 data_type = WBXML_WV_DATA_TYPE_STRING;
2992 break;
2993 }
2994 break;
2995 case 0x09:
2996 /* Code Page: 0x09 */
2997 switch (encoder->current_tag->wbxmlToken) {
2998 case 0x05: /* CIR */
2999 /* BOOLEAN */
3000 data_type = WBXML_WV_DATA_TYPE_BOOLEAN;
3001 break;
3002 case 0x08: /* HistoryPeriod */
3003 case 0x0A: /* MaxWatcherList */
3004 /* INTEGER */
3005 data_type = WBXML_WV_DATA_TYPE_INTEGER;
3006 break;
3007 default:
3008 /* STRING */
3009 data_type = WBXML_WV_DATA_TYPE_STRING;
3010 break;
3011 }
3012 break;
3013 default:
3014 data_type = WBXML_WV_DATA_TYPE_STRING;
3015 break;
3016 }
3017 }
3018
3019
3020 /****************************************
3021 * Encode, given the Data Type
3022 */
3023
3024 switch (data_type) {
3025 case WBXML_WV_DATA_TYPE_INTEGER:
3026 /* Integer: Encode it */
3027 return wbxml_encode_wv_integer(encoder, buffer);
3028 break;
3029 case WBXML_WV_DATA_TYPE_DATE_AND_TIME:
3030 /* Date and time can be encoded as OPAQUE data or as a string as specified in [ISO8601]. */
3031 return wbxml_encode_wv_datetime(encoder, buffer);
3032 break;
3033 case WBXML_WV_DATA_TYPE_BINARY:
3034 /** @todo Binary Encoding !! */
3035 break;
3036 case WBXML_WV_DATA_TYPE_BOOLEAN:
3037 /* Booleans are handled by the "T" and "F" extension tokens */
3038 case WBXML_WV_DATA_TYPE_STRING:
3039 /* Check if this buffer is an EXACT Extension Token */
3040 if ((ext = wbxml_tables_get_ext_from_xml(encoder->lang, buffer)) != NULL)
3041 return wbxml_encode_inline_integer_extension_token(encoder, WBXML_EXT_T_0, ext->wbxmlToken);
3042 else {
3043 if (WBXML_STRLEN(buffer) == 1)
3044 {
3045 /**
3046 * @todo [OMA WV 1.1] - 6.1 : A single character can be encoded as ENTITY (0x02) followed
3047 * by a mb_u_int32 containing the entity number.
3048 */
3049
3050 /*
3051 if (convert_char_to_ucs4(*buffer, &ucs4_ch))
3052 return wbxml_encode_entity(encoder, ucs4_ch);
3053 */
3054 }
3055
3056 /* Else: noting encoded... this will be latter as an inline string */
3057 }
3058 break;
3059 default:
3060 /* Hu ? */
3061 break;
3062 }
3063
3064 return WBXML_NOT_ENCODED;
3065 }
3066
3067
3068 /**
3069 * @brief Encode a Wireless-Village Integer
3070 * @param encoder The WBXML Encoder
3071 * @param buffer The buffer that contains the string representation of the integer to encode
3072 * @return WBXML_OK if OK, another error code otherwise
3073 */
wbxml_encode_wv_integer(WBXMLEncoder * encoder,WB_UTINY * buffer)3074 static WBXMLError wbxml_encode_wv_integer(WBXMLEncoder *encoder, WB_UTINY *buffer)
3075 {
3076 WB_UTINY octets[4];
3077 WB_ULONG the_int = 0, start = 0;
3078 WB_LONG i = 0;
3079
3080 if ((encoder == NULL) || (buffer == NULL))
3081 return WBXML_ERROR_INTERNAL;
3082
3083 if (buffer[1] == 'x' || buffer[1] == 'X') {
3084 the_int = (WB_ULONG) strtol((const WB_TINY *) buffer , NULL , 16);
3085 } else {
3086 the_int = (WB_ULONG) atol((const WB_TINY *) buffer);
3087 }
3088
3089
3090 for (i = 3; the_int > 0 && i >= 0; i--) {
3091 octets[i] = (WB_UTINY)(the_int & 0xff);
3092 the_int >>= 8;
3093 }
3094
3095 start = i + 1;
3096
3097 /* Add WBXML_OPAQUE */
3098 if (!wbxml_buffer_append_char(encoder->output, WBXML_OPAQUE))
3099 return WBXML_ERROR_ENCODER_APPEND_DATA;
3100
3101 /* Add Integer Length */
3102 if (!wbxml_buffer_append_mb_uint_32(encoder->output, 4 - start))
3103 return WBXML_ERROR_ENCODER_APPEND_DATA;
3104
3105 /* Add Integer */
3106 if (!wbxml_buffer_append_data(encoder->output, octets + start, (WB_UTINY)(4 - start)))
3107 return WBXML_ERROR_ENCODER_APPEND_DATA;
3108
3109 return WBXML_OK;
3110 }
3111
3112
3113 /**
3114 * @brief Encode inline WV Date and Time content value
3115 * @param encoder The WBXML Encoder
3116 * @param buffer The ISO 8601 Date and Time value to encode
3117 * @return WBXML_OK if encoded, another error code otherwise
3118 * @note [WV] - 6.6 Date and Time
3119 * @note
3120 * Encoded Format:
3121 * - ISO 8601 string (see expected format)
3122 *
3123 * Expected Format (ISO 8601):
3124 * 20011019T0950Z
3125 * 20011019T095031Z
3126 * 2001-10-19T09:50:31Z (with number seperators)
3127 * 2001-10-19T09:50:31+01:00 (with explicit positive time zone)
3128 * 2001-10-19T09:50:31+05:00 (with explicit negative time zone)
3129 */
wbxml_encode_wv_datetime_inline(WBXMLEncoder * encoder,WB_UTINY * buffer)3130 static WBXMLError wbxml_encode_wv_datetime_inline(WBXMLEncoder *encoder, WB_UTINY *buffer)
3131 {
3132 WBXMLError result = WBXML_OK;
3133 WBXMLBuffer *tmp = NULL;
3134
3135 /* Create temp Buffer */
3136 if ((tmp = wbxml_buffer_create_from_cstr(buffer)) == NULL) {
3137 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
3138 }
3139
3140 /* Add buffer to encoder */
3141 result = wbxml_encode_inline_string(encoder, tmp);
3142
3143 /* Cleanup buffer */
3144 wbxml_buffer_destroy(tmp);
3145
3146 return result;
3147 }
3148
3149
3150 /**
3151 * @brief Encode opaque WV Date and Time content value
3152 * @param encoder The WBXML Encoder
3153 * @param buffer The ISO 8601 Date and Time value to encode
3154 * @return WBXML_OK if encoded, another error code otherwise
3155 * @note [WV] - 6.6 Date and Time
3156 * @note
3157 * Encoded Format: (6 octets)
3158 * - The first 2 bits are reserved, and both must be 0.
3159 * - Year is encoded by 12 bits (0 to 4095)
3160 * - Month is encoded by 4 bits (1 to 12)
3161 * - Day is encoded by 5 bits (1 to 31)
3162 * - Hour is encoded by 5 bits (0 to 23)
3163 * - Minute is encoded by 6 bits (0 to 59)
3164 * - Second is encoded by 6 bits (0 to 59)
3165 * - Time zone is encoded in 1 byte [ISO8601].
3166 *
3167 * eg:
3168 * Binary: 00 011111010001 1010 10011 01001 110010 011111 01011010
3169 * Octets: (-------)(-------)(--------)(-------)(-------) (------)
3170 *
3171 * Expected Format (ISO 8601):
3172 * 20011019T0950 (missing seconds and time zone)
3173 * 20011019T0950Z (missing seconds)
3174 * 20011019T095031 (missing time zone)
3175 * 20011019T095031Z
3176 * 20011019T095031A (UTC+1)
3177 */
wbxml_encode_wv_datetime_opaque(WBXMLEncoder * encoder,WB_UTINY * buffer)3178 static WBXMLError wbxml_encode_wv_datetime_opaque(WBXMLEncoder *encoder, WB_UTINY *buffer)
3179 {
3180 WBXMLBuffer *tmp = NULL;
3181 WB_ULONG i = 0, len = 0;
3182 WB_UTINY ch = 0;
3183 WBXMLError ret = WBXML_OK;
3184 WB_UTINY octets[6];
3185 WBXMLBuffer *component = NULL;
3186
3187 /* definitions first ... or some compilers don't like it */
3188 unsigned int year, month, day, hour, minute, second;
3189
3190 len = WBXML_STRLEN(buffer);
3191
3192 /* Create temp Buffer */
3193 if ((tmp = wbxml_buffer_create_from_cstr(buffer)) == NULL) {
3194 ret = WBXML_ERROR_NOT_ENOUGH_MEMORY;
3195 goto error;
3196 }
3197
3198 /* Check Length */
3199 if ((len == 13) || (len == 14)) {
3200 /* This is illegal but we can tolerate datetimes
3201 * which forget the seconds.
3202 */
3203 WBXML_WARNING((WBXML_CONV, "The WV datetime %s is missing the seconds.", buffer));
3204 if (len == 13) {
3205 wbxml_buffer_append_cstr(tmp, "00");
3206 } else {
3207 wbxml_buffer_insert_cstr(tmp, (WB_UTINY *) "00", 13);
3208 }
3209 len = wbxml_buffer_len(tmp);
3210 }
3211 if ((len != 15) && (len != 16)) {
3212 WBXML_ERROR((WBXML_CONV, "The length of a WV datetime must be 15 or 16."));
3213 ret = WBXML_ERROR_WV_DATETIME_FORMAT;
3214 goto error;
3215 }
3216
3217 /* Check position of 'T' */
3218 if (*(buffer+8) != 'T') {
3219 WBXML_ERROR((WBXML_CONV, "The 9th character of a WV datetime must be 'T'."));
3220 ret = WBXML_ERROR_WV_DATETIME_FORMAT;
3221 goto error;
3222 }
3223
3224 /* Check position of time zone */
3225 if (len == 16) {
3226 if (!wbxml_buffer_get_char(tmp, 15, &ch)) {
3227 ret = WBXML_ERROR_INTERNAL;
3228 goto error;
3229 }
3230 if (ch < 'A' || ch == 'J' || ch > 'Z') {
3231 WBXML_ERROR((WBXML_CONV, "If the length of a WV datetime is 16 then the last character must be the time zone."));
3232 ret = WBXML_ERROR_WV_DATETIME_FORMAT;
3233 goto error;
3234 }
3235
3236 /* There is a time zone. */
3237 octets[5] = ch;
3238
3239 /* delete time zone */
3240 wbxml_buffer_delete(tmp, 15, 1);
3241 } else {
3242 /* There is no time zone. */
3243 octets[5] = 0;
3244 }
3245
3246 /* delete 'T' */
3247 wbxml_buffer_delete(tmp, 8, 1);
3248
3249 /* Check if you have only digits characters */
3250 while (i < wbxml_buffer_len(tmp)) {
3251 /* Get char */
3252 if (!wbxml_buffer_get_char(tmp, i, &ch)) {
3253 ret = WBXML_ERROR_INTERNAL;
3254 goto error;
3255 }
3256
3257 if (!WBXML_ISDIGIT(ch)) {
3258 ret = WBXML_ERROR_WV_DATETIME_FORMAT;
3259 goto error;
3260 }
3261 else
3262 i++;
3263 }
3264
3265 WBXML_DEBUG((WBXML_CONV, "Starting WV datetime conversion ..."));
3266
3267 /* Set Year */
3268 component = wbxml_buffer_duplicate(tmp);
3269 if (!component) {
3270 ret = WBXML_ERROR_NOT_ENOUGH_MEMORY;
3271 goto error;
3272 }
3273 wbxml_buffer_delete(component, 4, 10);
3274 year = strtoul((const char *)wbxml_buffer_get_cstr(component), NULL, 10);
3275 wbxml_buffer_destroy(component);
3276 octets[0] = (WB_UTINY) ((year & 0xfc0) >> 6); /* 6 bits */
3277 octets[1] = (WB_UTINY) (year & 0x3f); /* 6 bits */
3278
3279 /* Set Month */
3280 component = wbxml_buffer_duplicate(tmp);
3281 if (!component) {
3282 ret = WBXML_ERROR_NOT_ENOUGH_MEMORY;
3283 goto error;
3284 }
3285 wbxml_buffer_delete(component, 0, 4);
3286 wbxml_buffer_delete(component, 2, 8);
3287 month = strtoul((const char *)wbxml_buffer_get_cstr(component), NULL, 10);
3288 wbxml_buffer_destroy(component);
3289 octets[1] <<= 2;
3290 octets[1] += (WB_UTINY) ((month & 0xc) >> 2); /* 2 bits */
3291 octets[2] = (WB_UTINY) (month & 0x3); /* 2 bits */
3292
3293 /* Set Day */
3294 component = wbxml_buffer_duplicate(tmp);
3295 if (!component) {
3296 ret = WBXML_ERROR_NOT_ENOUGH_MEMORY;
3297 goto error;
3298 }
3299 wbxml_buffer_delete(component, 0, 6);
3300 wbxml_buffer_delete(component, 2, 6);
3301 day = strtoul((const char *)wbxml_buffer_get_cstr(component), NULL, 10);
3302 wbxml_buffer_destroy(component);
3303 octets[2] <<= 5;
3304 octets[2] += (WB_UTINY) (day & 0x1f); /* 5 bits */
3305
3306 /* Set Hour */
3307 component = wbxml_buffer_duplicate(tmp);
3308 if (!component) {
3309 ret = WBXML_ERROR_NOT_ENOUGH_MEMORY;
3310 goto error;
3311 }
3312 wbxml_buffer_delete(component, 0, 8);
3313 wbxml_buffer_delete(component, 2, 4);
3314 hour = strtoul((const char *)wbxml_buffer_get_cstr(component), NULL, 10);
3315 wbxml_buffer_destroy(component);
3316 octets[2] <<=1;
3317 octets[2] += (WB_UTINY) ((hour & 0x10) >> 4); /* 1 bit */
3318 octets[3] = (WB_UTINY) (hour & 0xf); /* 4 bits */
3319
3320 /* Set Minute */
3321 component = wbxml_buffer_duplicate(tmp);
3322 if (!component) {
3323 ret = WBXML_ERROR_NOT_ENOUGH_MEMORY;
3324 goto error;
3325 }
3326 wbxml_buffer_delete(component, 0, 10);
3327 wbxml_buffer_delete(component, 2, 2);
3328 minute = strtoul((const char *)wbxml_buffer_get_cstr(component), NULL, 10);
3329 wbxml_buffer_destroy(component);
3330 octets[3] <<=4;
3331 octets[3] += (WB_UTINY) ((minute & 0x3c) >> 2); /* 4 bits */
3332 octets[4] = (WB_UTINY) (minute & 0x3); /* 2 bits */
3333
3334 /* Set Second */
3335 component = wbxml_buffer_duplicate(tmp);
3336 if (!component) {
3337 ret = WBXML_ERROR_NOT_ENOUGH_MEMORY;
3338 goto error;
3339 }
3340 wbxml_buffer_delete(component, 0, 12);
3341 second = strtoul((const char *)wbxml_buffer_get_cstr(component), NULL, 10);
3342 wbxml_buffer_destroy(component);
3343 octets[4] <<=6;
3344 octets[4] += (WB_UTINY) (second & 0x3f); /* 6 bits */
3345
3346 WBXML_DEBUG((WBXML_CONV, "WV datetime: %x %x %x %x %x %x", octets[0], octets[1], octets[2], octets[3], octets[4], octets[5]));
3347
3348 /* Encode it to Opaque */
3349 ret = wbxml_encode_opaque_data(encoder, octets, 6);
3350
3351 error:
3352 if (tmp)
3353 wbxml_buffer_destroy(tmp);
3354 return ret;
3355 }
3356
3357
3358 /**
3359 * @brief Encode WV Date and Time content value
3360 * @param encoder The WBXML Encoder
3361 * @param buffer The ISO 8601 Date and Time value to encode
3362 * @return WBXML_OK if encoded, another error code otherwise
3363 * @note [WV] - 6.6 Date and Time
3364 * @note This function only decides which kind of datetime
3365 * encoding should be used and calls the appropriate
3366 * function. Please see wbxml_encode_wv_datetime_opaque
3367 * and wbxml_encode_wv_datetime_inline for more details.
3368 * @note Both encoding mechanisms were implemented to be able
3369 * to test the parsing of both encoding scheme. This is
3370 * necessary because other implementations can decide by
3371 * their own which encoding scheme they use.
3372 */
wbxml_encode_wv_datetime(WBXMLEncoder * encoder,WB_UTINY * buffer)3373 static WBXMLError wbxml_encode_wv_datetime(WBXMLEncoder *encoder, WB_UTINY *buffer)
3374 {
3375 WB_BOOL use_inline = FALSE;
3376 WB_ULONG len = WBXML_STRLEN(buffer);
3377
3378 /* long version of ISO 8601 should be inline encoded */
3379 if (strchr((WB_TINY *) buffer, '-'))
3380 use_inline = TRUE;
3381 if (strchr((WB_TINY *) buffer, '+'))
3382 use_inline = TRUE;
3383 if (strchr((WB_TINY *) buffer, ':'))
3384 use_inline = TRUE;
3385
3386 /* timezone Z should be inline encoded */
3387 if (buffer[len - 1] == 'Z')
3388 use_inline = TRUE;
3389
3390 if (use_inline) {
3391 WBXML_DEBUG((WBXML_CONV, "WV datetime conversion: INLINE"));
3392 return wbxml_encode_wv_datetime_inline(encoder, buffer);
3393 } else {
3394 WBXML_DEBUG((WBXML_CONV, "WV datetime conversion: OPAQUE"));
3395 return wbxml_encode_wv_datetime_opaque(encoder, buffer);
3396 }
3397 }
3398
3399 #endif /* WBXML_SUPPORT_WV */
3400
3401
3402 #if defined( WBXML_SUPPORT_DRMREL )
3403
3404 /*******************
3405 * DRMREL 1.0
3406 */
3407
3408 /**
3409 * @brief Encode a DRMREL Content buffer
3410 * @param encoder The WBXML Encoder
3411 * @param buffer The buffer to encode
3412 * @return WBXML_OK if encoded, WBXML_NOT_ENCODED if not encoded, another error code otherwise
3413 * @note This function encodes a Specific DRMREL content.
3414 * If not found, this is not encoded... and it will be encoded latter as an Inline String
3415 * in wbxml_encode_value_element_buffer().
3416 */
wbxml_encode_drmrel_content(WBXMLEncoder * encoder,WB_UTINY * buffer)3417 static WBXMLError wbxml_encode_drmrel_content(WBXMLEncoder *encoder, WB_UTINY *buffer)
3418 {
3419 WB_UTINY *data = NULL;
3420 WB_LONG data_len = 0;
3421 const WBXMLTagEntry *current_tag = NULL;
3422
3423 if ((encoder->current_text_parent != NULL) &&
3424 (encoder->current_text_parent->name != NULL) &&
3425 (encoder->current_text_parent->name->type == WBXML_VALUE_TOKEN))
3426 {
3427 current_tag = encoder->current_text_parent->name->u.token;
3428 }
3429
3430 if (current_tag != NULL)
3431 {
3432 if ((current_tag->wbxmlCodePage == 0x00) &&
3433 (current_tag->wbxmlToken == 0x0C))
3434 {
3435 /* <ds:KeyValue> content: "Encoded in binary format, i.e., no base64 encoding" */
3436
3437 /* Decode Base64 */
3438 if ((data_len = wbxml_base64_decode(buffer, -1, &data)) < 0)
3439 return WBXML_NOT_ENCODED;
3440
3441 /* Add WBXML_OPAQUE */
3442 if (!wbxml_buffer_append_char(encoder->output, WBXML_OPAQUE))
3443 {
3444 wbxml_free(data);
3445 return WBXML_ERROR_ENCODER_APPEND_DATA;
3446 }
3447
3448 /* Add Data Length */
3449 if (!wbxml_buffer_append_mb_uint_32(encoder->output, (WB_ULONG) data_len))
3450 {
3451 wbxml_free(data);
3452 return WBXML_ERROR_ENCODER_APPEND_DATA;
3453 }
3454
3455 /* Add Data */
3456 if (!wbxml_buffer_append_data(encoder->output, data, data_len))
3457 {
3458 wbxml_free(data);
3459 return WBXML_ERROR_ENCODER_APPEND_DATA;
3460 }
3461
3462 /* Free Data */
3463 wbxml_free(data);
3464
3465 return WBXML_OK;
3466 }
3467 }
3468
3469 return WBXML_NOT_ENCODED;
3470 }
3471
3472 #endif /* WBXML_SUPPORT_DRMREL */
3473
3474
3475 #if defined( WBXML_SUPPORT_OTA_SETTINGS )
3476
3477 /*******************
3478 * OTA Settings
3479 */
3480
3481 /**
3482 * @brief Encode a OTA ICON as opaque data
3483 * @param encoder The WBXML Encoder
3484 * @param buffer The buffer to encode
3485 * @return WBXML_OK if encoded, WBXML_NOT_ENCODED if not encoded, another error code otherwise
3486 * @note Nokia OTA Settings support for the ICON value in bookmarks.
3487 *
3488 * Nokia introduced a proprietary way of including icons in the old Nokia OTA Settings format when sending bookmarks.
3489 * The encoding is done using base64 encoded images in XML, and encoding it as OPAQUE data in the WBXML.
3490 * The icon is embedded using an PARM element with name ICON.
3491 *
3492 * E.g. the following bookmark (XML) is valid:
3493 *
3494 * <?xml version="1.0"?>
3495 * <!DOCTYPE CHARACTERISTIC-LIST PUBLIC "-//WAPFORUM//DTD NOKIA-OTA 1.0//EN" "http://localhost:8080/OMABootSendWEB/DTD/characteristic_list.dtd">
3496 *
3497 * <CHARACTERISTIC-LIST>
3498 * <CHARACTERISTIC TYPE="BOOKMARK">
3499 * <PARM NAME="NAME" VALUE="TV2"/>
3500 * <PARM NAME="URL" VALUE="http://wap.tv2.dk"/>
3501 * <PARM NAME="ICON" VALUE="R0lGODlhIAAgAPMAAP//AP8zAMwAAJkAAGYAAN0AAKoAAIgAAHcAAFUAAEQAACIAABEAALu7u8jIyP8AMyH5BAEAAA4ALAAAAAAgACAAQATh0MlJq704Z8bkucyiJARyHEM6HAjCNJw2hWNpnmdLJMrSyUBMICApAAqbhUiheDVgicQg8dPQSKaBQVAQGFaIXa8KDC2ZaCU5yL4QPe3yoXAIfDacfJVBZV9JNi16fWUiWChbAl5gBAxjMlclKFoGX4w8PkF/BJydO5hrbXp5caUYd6YycwVvqRY4R64goa4dMRKtGBxKaqNShIVMUSUcTwxTtCCGnC04LMWkkMtZlJbPMLdJNVlbXV8sYplW04iKi+Cg0tvUKixh6eqALfM64cnKwlH6PI+mu7y8sskaCMFFADs="/>
3502 * </CHARACTERISTIC>
3503 * </CHARACTERISTIC-LIST>
3504 *
3505 * If not found, this is not encoded... and it will be encoded latter as an Inline String in wbxml_encode_value_element_buffer().
3506 */
wbxml_encode_ota_nokia_icon(WBXMLEncoder * encoder,WB_UTINY * buffer)3507 static WBXMLError wbxml_encode_ota_nokia_icon(WBXMLEncoder *encoder, WB_UTINY *buffer)
3508 {
3509 WBXMLError ret = WBXML_NOT_ENCODED;
3510
3511 /* Is a VALUE attribute ? */
3512 if ((encoder->current_tag != NULL) &&
3513 (encoder->current_attr->wbxmlCodePage == 0x00) &&
3514 (encoder->current_attr->wbxmlToken == 0x11) &&
3515 (encoder->current_node && encoder->current_node->attrs))
3516 {
3517 WBXMLList *attrs = encoder->current_node->attrs;
3518 WB_ULONG index = 0;
3519 WB_ULONG nb_attrs = wbxml_list_len(attrs);
3520 WB_BOOL found = FALSE;
3521
3522 /* Search for a NAME="ICON" attribute */
3523 while (!found && (index < nb_attrs)) {
3524 WBXMLAttribute *attr = (WBXMLAttribute*)wbxml_list_get(attrs, index);
3525
3526 if ((WBXML_STRCMP("NAME", wbxml_attribute_get_xml_name(attr)) == 0) &&
3527 (WBXML_STRCMP("ICON", wbxml_attribute_get_xml_value(attr)) == 0))
3528 {
3529 WB_UTINY *data = NULL;
3530 WB_LONG data_len = 0;
3531
3532 /* Decode Base64 */
3533 if ((data_len = wbxml_base64_decode(buffer, -1, &data)) < 0)
3534 return WBXML_NOT_ENCODED;
3535
3536 /* Encode opaque */
3537 if ((ret = wbxml_encode_opaque_data(encoder, data, data_len)) != WBXML_OK)
3538 return ret;
3539
3540 /* Free Data */
3541 wbxml_free(data);
3542
3543 found = TRUE;
3544 }
3545
3546 index++;
3547 }
3548 }
3549
3550 return ret;
3551 }
3552
3553 #endif /* WBXML_SUPPORT_OTA_SETTINGS */
3554
3555
3556 #if defined( WBXML_ENCODER_USE_STRTBL )
3557
3558 /****************************
3559 * String Table Functions
3560 */
3561
3562 /**
3563 * @brief Create a String Table element
3564 * @param string The WBXMLBuffer containing the String
3565 * @param is_stat If set to TRUE, this Buffer won't be destroyed in wbxml_strtbl_element_destroy() function
3566 * @return The newly created String Table Element, or NULL if not enought memory
3567 */
wbxml_strtbl_element_create(WBXMLBuffer * string,WB_BOOL is_stat)3568 static WBXMLStringTableElement *wbxml_strtbl_element_create(WBXMLBuffer *string, WB_BOOL is_stat)
3569 {
3570 WBXMLStringTableElement *elt = NULL;
3571
3572 if ((elt = wbxml_malloc(sizeof(WBXMLStringTableElement))) == NULL)
3573 return NULL;
3574
3575 elt->string = string;
3576 elt->offset = 0;
3577 elt->count = 0;
3578 elt->stat = is_stat;
3579
3580 return elt;
3581 }
3582
3583
3584 /**
3585 * @brief Destroy a String Table element
3586 * @param element The element to destroy
3587 */
wbxml_strtbl_element_destroy(WBXMLStringTableElement * element)3588 static void wbxml_strtbl_element_destroy(WBXMLStringTableElement *element)
3589 {
3590 if (element == NULL)
3591 return;
3592
3593 if (!element->stat)
3594 wbxml_buffer_destroy(element->string);
3595
3596 wbxml_free(element);
3597 }
3598
3599
3600 /**
3601 * @brief Destroy a String Table element (for wbxml_list_destroy())
3602 * @param element The element to destroy
3603 */
wbxml_strtbl_element_destroy_item(void * element)3604 static void wbxml_strtbl_element_destroy_item(void *element)
3605 {
3606 wbxml_strtbl_element_destroy((WBXMLStringTableElement *) element);
3607 }
3608
3609
3610 /**
3611 * @brief Initialize the String Table
3612 * @param encoder The WBXML Encoder
3613 * @param root The root element of LibXML Tree
3614 */
wbxml_strtbl_initialize(WBXMLEncoder * encoder,WBXMLTreeNode * root)3615 static WBXMLError wbxml_strtbl_initialize(WBXMLEncoder *encoder, WBXMLTreeNode *root)
3616 {
3617 WBXMLList *strings = NULL, *one_ref = NULL;
3618 WBXMLError ret;
3619
3620 if ((strings = wbxml_list_create()) == NULL)
3621 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
3622
3623 /* Collect all Strings:
3624 * [out] 'strings' is the list of pointers to WBXMLBuffer. This Buffers must not be freed.
3625 */
3626 wbxml_strtbl_collect_strings(encoder, root, strings);
3627
3628 /* Insert, in String Table, Strings that are referenced more than one time
3629 * [out] 'strings' is NULL
3630 * 'one_ref' is the list of strings referenced only ONE time (list of WBXMLStringTableElement*)
3631 * Strings referenced more than one time are added to String Table
3632 */
3633 if ((ret = wbxml_strtbl_check_references(encoder, &strings, &one_ref, TRUE)) != WBXML_OK) {
3634 wbxml_list_destroy(strings, NULL);
3635 return ret;
3636 }
3637
3638 /* 'strings' is destroyed after call of wbxml_strtbl_check_references() */
3639
3640 /* Split Strings refered only one time in Words
3641 * [out] 'strings' is the list of words. This words (WBXMLBuffer) must be freed
3642 */
3643 if ((ret = wbxml_strtbl_collect_words(one_ref, &strings)) != WBXML_OK) {
3644 wbxml_list_destroy(one_ref, wbxml_strtbl_element_destroy_item);
3645 return ret;
3646 }
3647
3648 /* Destroy References List */
3649 wbxml_list_destroy(one_ref, wbxml_strtbl_element_destroy_item);
3650 one_ref = NULL;
3651
3652 /* Keep Strings referenced more than one time */
3653 if (strings != NULL)
3654 wbxml_strtbl_check_references(encoder, &strings, &one_ref, FALSE);
3655
3656 /* 'strings' is destroyed after call of wbxml_strtbl_check_references() */
3657
3658 /* Cleanup */
3659 wbxml_list_destroy(one_ref, wbxml_strtbl_element_destroy_item);
3660
3661 return WBXML_OK;
3662 }
3663
3664
3665 /**
3666 * @brief Collect Strings in XML Document (in Text Content and Attribute Values)
3667 * @param encoder [in] The WBXML Encoder
3668 * @param node [in] The current element node of LibXML Tree
3669 * @param strings [out] List of WBXMLBuffer buffers corresponding to Collected Strings
3670 */
wbxml_strtbl_collect_strings(WBXMLEncoder * encoder,WBXMLTreeNode * node,WBXMLList * strings)3671 static void wbxml_strtbl_collect_strings(WBXMLEncoder *encoder, WBXMLTreeNode *node, WBXMLList *strings)
3672 {
3673 const WBXMLAttrEntry *attr_entry = NULL;
3674 WBXMLAttribute *attr = NULL;
3675 WB_ULONG i = 0;
3676 WB_UTINY *value_left = NULL;
3677
3678 switch (node->type)
3679 {
3680 case WBXML_TREE_TEXT_NODE:
3681 /* Ignore blank nodes */
3682 if (wbxml_buffer_contains_only_whitespaces(node->content))
3683 break;
3684
3685 /** @todo Shrink / Strip Blanks */
3686
3687 /* Only add this string if it is big enought */
3688 if (wbxml_buffer_len(node->content) > WBXML_ENCODER_STRING_TABLE_MIN) {
3689 wbxml_list_append(strings, node->content);
3690 WBXML_DEBUG((WBXML_ENCODER, "Strtbl - Collecting String: %s", wbxml_buffer_get_cstr(node->content)));
3691 }
3692 break;
3693
3694 case WBXML_TREE_ELEMENT_NODE:
3695 /* Collect strings in Attributes Values too */
3696 if (node->attrs != NULL) {
3697 for (i = 0; i < wbxml_list_len(node->attrs); i++) {
3698 /* Get attribute */
3699 attr = wbxml_list_get(node->attrs, i);
3700
3701 /* Only add this string if it is big enought */
3702 if (attr && wbxml_buffer_len(attr->value) > WBXML_ENCODER_STRING_TABLE_MIN) {
3703 /* This mustn't be a tokenisable Attribute Start */
3704 attr_entry = wbxml_tables_get_attr_from_xml(encoder->lang,
3705 (WB_UTINY *) wbxml_attribute_get_xml_name(attr),
3706 (WB_UTINY *) wbxml_attribute_get_xml_value(attr),
3707 &value_left);
3708
3709 /* - If attr_entry is NULL: no Attribute Start found
3710 * - If attr_entry is not NULL: and Attribute Start is found, but it can be the one with
3711 * no Attribute Value associated. So just check that the 'value_left' is the same than
3712 * the attribute value we where searching for
3713 */
3714 if ((attr_entry == NULL) || ((attr_entry != NULL) && (value_left == (WB_UTINY *) wbxml_attribute_get_xml_value(attr))))
3715 {
3716 /* It mustn't contain a tokenisable Attribute Value */
3717 if (!wbxml_tables_contains_attr_value_from_xml(encoder->lang,
3718 (WB_UTINY *) wbxml_attribute_get_xml_value(attr)))
3719 {
3720 wbxml_list_append(strings, attr->value);
3721 WBXML_DEBUG((WBXML_ENCODER, "Strtbl - Collecting String: %s", wbxml_buffer_get_cstr(attr->value)));
3722 }
3723 }
3724 }
3725 }
3726 }
3727 break;
3728
3729 default:
3730 /* NOOP */
3731 break;
3732 }
3733
3734 if (node->children != NULL)
3735 wbxml_strtbl_collect_strings(encoder, node->children, strings);
3736
3737 if (node->next != NULL)
3738 wbxml_strtbl_collect_strings(encoder, node->next, strings);
3739 }
3740
3741
3742 /**
3743 * @brief Split Strings into Words
3744 * @param elements [in] List of String Table Elements to split
3745 * @param result [out] Resulting list of Words
3746 * @return WBXML_OK is no error, another error code otherwise
3747 */
wbxml_strtbl_collect_words(WBXMLList * elements,WBXMLList ** result)3748 static WBXMLError wbxml_strtbl_collect_words(WBXMLList *elements, WBXMLList **result)
3749 {
3750 WBXMLStringTableElement *elt = NULL;
3751 WBXMLList *list = NULL, *temp_list = NULL;
3752 WBXMLBuffer *word = NULL;
3753 WB_ULONG i = 0;
3754
3755 *result = NULL;
3756
3757 for (i = 0; i < wbxml_list_len(elements); i++)
3758 {
3759 elt = (WBXMLStringTableElement *) wbxml_list_get(elements, i);
3760 if (elt == NULL) {
3761 /* There is a bug inside the wbxml strtbl implementation.
3762 wbxml_list must be used in a wrong way.
3763 */
3764 wbxml_list_destroy(list, wbxml_buffer_destroy_item);
3765 return WBXML_ERROR_INTERNAL;
3766 }
3767
3768 if (list == NULL) {
3769 if ((list = wbxml_buffer_split_words(elt->string)) == NULL) {
3770 wbxml_list_destroy(list, wbxml_buffer_destroy_item);
3771 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
3772 }
3773 } else {
3774 if ((temp_list = wbxml_buffer_split_words(elt->string)) == NULL) {
3775 wbxml_list_destroy(list, wbxml_buffer_destroy_item);
3776 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
3777 }
3778
3779 while ((word = wbxml_list_extract_first(temp_list)) != NULL) {
3780 if (!wbxml_list_append(list, word)) {
3781 wbxml_buffer_destroy(word);
3782 wbxml_list_destroy(temp_list, wbxml_buffer_destroy_item);
3783 wbxml_list_destroy(list, wbxml_buffer_destroy_item);
3784 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
3785 }
3786 }
3787
3788 wbxml_list_destroy(temp_list, NULL);
3789 }
3790 }
3791
3792 *result = list;
3793
3794 return WBXML_OK;
3795 }
3796
3797
3798 /**
3799 * @brief Append the String Table to result Buffer
3800 * @param buff The Buffer to append the String Table to
3801 * @param strstbl The String Table to append
3802 */
wbxml_strtbl_construct(WBXMLBuffer * buff,WBXMLList * strstbl)3803 static WBXMLError wbxml_strtbl_construct(WBXMLBuffer *buff, WBXMLList *strstbl)
3804 {
3805 WBXMLStringTableElement *elt = NULL;
3806 WB_ULONG i = 0;
3807
3808 if ((buff == NULL) || (strstbl == NULL))
3809 return WBXML_ERROR_BAD_PARAMETER;
3810
3811 for (i = 0; i < wbxml_list_len(strstbl); i++)
3812 {
3813 if ((elt = wbxml_list_get(strstbl, i)) == NULL)
3814 continue;
3815
3816 if (!wbxml_buffer_append(buff, elt->string))
3817 return WBXML_ERROR_ENCODER_APPEND_DATA;
3818
3819 if (!wbxml_buffer_append_char(buff, WBXML_STR_END))
3820 return WBXML_ERROR_ENCODER_APPEND_DATA;
3821 }
3822
3823 return WBXML_OK;
3824 }
3825
3826
3827 /**
3828 * @brief Check strings that have multiple references, add them to string table
3829 * and return strings that have only one reference
3830 * @param encoder The WBXML Encoder
3831 * @param strings The List of Strings to check (List of WBXMLBuffer) : This list is freed by this function
3832 * @param one_ref List of strings that have only one reference (List of WBXMLStringTableElement)
3833 * @param stat_buff If set to TRUE, Buffers referenced by 'strings' must NOT be destroyed.
3834 * @return WBXML_OK if no error, another error code otherwise
3835 * @warning All elements of 'strings' list are removed from this list
3836 */
wbxml_strtbl_check_references(WBXMLEncoder * encoder,WBXMLList ** strings,WBXMLList ** one_ref,WB_BOOL stat_buff)3837 static WBXMLError wbxml_strtbl_check_references(WBXMLEncoder *encoder, WBXMLList **strings, WBXMLList **one_ref, WB_BOOL stat_buff)
3838 {
3839 WBXMLList *referenced = NULL, *result = NULL;
3840 WBXMLBuffer *string = NULL;
3841 WBXMLStringTableElement *ref = NULL;
3842 WB_ULONG j = 0;
3843 WB_BOOL added = FALSE;
3844
3845 if ((strings == NULL) || (one_ref == NULL))
3846 return WBXML_ERROR_INTERNAL;
3847
3848 *one_ref = NULL;
3849
3850 /* Create list of String References */
3851 if ((referenced = wbxml_list_create()) == NULL)
3852 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
3853
3854
3855 /*********************
3856 * Count References
3857 */
3858
3859 while (wbxml_list_len(*strings) > 0)
3860 {
3861 string = (WBXMLBuffer *) wbxml_list_extract_first(*strings);
3862
3863 /* Check if we have already found this String */
3864 for (j = 0; j < wbxml_list_len(referenced); j++)
3865 {
3866 ref = (WBXMLStringTableElement *) wbxml_list_get(referenced, j);
3867 if (ref == NULL)
3868 {
3869 /* There is a bug inside wbxml_strtbl_check_references.
3870 wbxml_list must be used in a wrong way.
3871 */
3872 if (!stat_buff)
3873 wbxml_buffer_destroy(string);
3874 string = NULL;
3875 wbxml_list_destroy(referenced, wbxml_strtbl_element_destroy_item);
3876 return WBXML_ERROR_INTERNAL;
3877 }
3878
3879 if (wbxml_buffer_compare(ref->string, string) == 0)
3880 {
3881 if (!stat_buff)
3882 wbxml_buffer_destroy(string);
3883
3884 string = NULL;
3885 ref->count++;
3886 break;
3887 }
3888 }
3889
3890 if (string != NULL)
3891 {
3892 /* New Reference Element */
3893 if ((ref = wbxml_strtbl_element_create(string, stat_buff)) == NULL)
3894 {
3895 wbxml_list_destroy(referenced, wbxml_strtbl_element_destroy_item);
3896
3897 if (!stat_buff)
3898 wbxml_list_destroy(*strings, wbxml_buffer_destroy_item);
3899 else
3900 wbxml_list_destroy(*strings, NULL);
3901
3902 *strings = NULL;
3903 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
3904 }
3905
3906 ref->count++;
3907
3908 if (!wbxml_list_append(referenced, (void *) ref))
3909 {
3910 wbxml_list_destroy(referenced, wbxml_strtbl_element_destroy_item);
3911
3912 if (!stat_buff)
3913 wbxml_list_destroy(*strings, wbxml_buffer_destroy_item);
3914 else
3915 wbxml_list_destroy(*strings, NULL);
3916
3917 *strings = NULL;
3918 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
3919 }
3920 }
3921 }
3922
3923
3924 wbxml_list_destroy(*strings, NULL);
3925 *strings = NULL;
3926
3927
3928 /***********************************************
3929 * Remove Strings that have only One reference
3930 */
3931
3932 if ((result = wbxml_list_create()) == NULL) {
3933 wbxml_list_destroy(referenced, wbxml_strtbl_element_destroy_item);
3934 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
3935 }
3936
3937 while (wbxml_list_len(referenced) > 0)
3938 {
3939 ref = (WBXMLStringTableElement *) wbxml_list_extract_first(referenced);
3940 if ((ref->count > 1) && (wbxml_buffer_len(ref->string) > WBXML_ENCODER_STRING_TABLE_MIN)) {
3941 /* Add Element to String Table */
3942 if (!wbxml_strtbl_add_element(encoder, ref, NULL, &added)) {
3943 wbxml_strtbl_element_destroy(ref);
3944 wbxml_list_destroy(referenced, wbxml_strtbl_element_destroy_item);
3945 wbxml_list_destroy(result, wbxml_strtbl_element_destroy_item);
3946 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
3947 }
3948
3949 if (!added) {
3950 wbxml_strtbl_element_destroy(ref);
3951 }
3952 }
3953 else {
3954 /* Add Element in resulting 'not added in String Table' list */
3955 if (!wbxml_list_append(result, (void *) ref)) {
3956 wbxml_strtbl_element_destroy(ref);
3957 wbxml_list_destroy(referenced, wbxml_strtbl_element_destroy_item);
3958 wbxml_list_destroy(result, wbxml_strtbl_element_destroy_item);
3959 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
3960 }
3961 }
3962 }
3963
3964 wbxml_list_destroy(referenced, wbxml_strtbl_element_destroy_item);
3965
3966 *one_ref = result;
3967
3968 return WBXML_OK;
3969 }
3970
3971
3972 /**
3973 * @brief Add a String in String table
3974 * @param encoder [in] The WBXML Encoder
3975 * @param elt [in] The Element to add
3976 * @param index [out] The index in String Table
3977 * @param added [out] TRUE if really added, or FALSe if already in String Table
3978 * @return TRUE if no error, FALSE is Memory Error
3979 */
wbxml_strtbl_add_element(WBXMLEncoder * encoder,WBXMLStringTableElement * elt,WB_ULONG * index,WB_BOOL * added)3980 static WB_BOOL wbxml_strtbl_add_element(WBXMLEncoder *encoder, WBXMLStringTableElement *elt, WB_ULONG *index, WB_BOOL *added)
3981 {
3982 WBXMLStringTableElement *elt_tmp = NULL;
3983 WB_ULONG i = 0;
3984
3985 if ((encoder == NULL) || (encoder->strstbl == NULL) || (elt == NULL) || (elt->string == NULL))
3986 return FALSE;
3987
3988 *added = FALSE;
3989
3990 /* Check if this element already exists in String Table */
3991 for (i = 0; i < wbxml_list_len(encoder->strstbl); i++)
3992 {
3993 if ((elt_tmp = wbxml_list_get(encoder->strstbl, i)) == NULL)
3994 continue;
3995
3996 if ((wbxml_buffer_len(elt_tmp->string) == wbxml_buffer_len(elt->string)) &&
3997 (wbxml_buffer_compare(elt_tmp->string, elt->string) == 0))
3998 {
3999 /* The String already exists in the String Table */
4000 if (index != NULL)
4001 *index = elt_tmp->offset;
4002 return TRUE;
4003 }
4004 }
4005
4006 /* Add this string to String Table */
4007 elt->offset = encoder->strstbl_len;
4008
4009 if (!wbxml_list_append(encoder->strstbl, (void *) elt))
4010 return FALSE;
4011
4012 /* Index in String Table */
4013 if (index != NULL)
4014 *index = encoder->strstbl_len;
4015
4016 /* New String Table length */
4017 encoder->strstbl_len += wbxml_buffer_len(elt->string) + 1;
4018
4019 *added = TRUE;
4020
4021 return TRUE;
4022 }
4023
4024 #endif /* WBXML_ENCODER_USE_STRTBL */
4025
4026
4027 /*****************************************
4028 * XML Output Functions
4029 */
4030
4031 /****************************
4032 * Build XML Result
4033 */
4034
4035 /**
4036 * @brief Build XML Result
4037 * @param encoder [in] The WBXML Encoder
4038 * @param xml [out] Resulting XML document
4039 * @param xml_len [out] XML document length
4040 * @return WBXML_OK if built is OK, an error code otherwise
4041 */
xml_build_result(WBXMLEncoder * encoder,WB_UTINY ** xml,WB_ULONG * xml_len)4042 static WBXMLError xml_build_result(WBXMLEncoder *encoder, WB_UTINY **xml, WB_ULONG *xml_len)
4043 {
4044 WBXMLBuffer *header = NULL;
4045 WB_ULONG len = 0;
4046 WBXMLError ret = WBXML_OK;
4047
4048 if (xml == NULL)
4049 return WBXML_ERROR_BAD_PARAMETER;
4050
4051 /* Init */
4052 if (xml_len != NULL)
4053 *xml_len = 0;
4054
4055 if (encoder->flow_mode == TRUE) {
4056 /* Header already built */
4057 header = encoder->output_header;
4058 }
4059 else {
4060 /* Create Header Buffer */
4061 if ((header = wbxml_buffer_create("", 0, WBXML_ENCODER_XML_HEADER_MALLOC_BLOCK)) == NULL)
4062 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
4063
4064 /* Fill Header Buffer */
4065 if (encoder->xml_encode_header) {
4066 if ((ret = xml_fill_header(encoder, header)) != WBXML_OK) {
4067 wbxml_buffer_destroy(header);
4068 return ret;
4069 }
4070 }
4071 }
4072
4073 /* Result Buffer Length */
4074 len = wbxml_buffer_len(header) + wbxml_buffer_len(encoder->output);
4075
4076 /* Create Result Buffer */
4077 *xml = wbxml_malloc((len + 1) * sizeof(WB_UTINY));
4078 if (*xml == NULL) {
4079 if (encoder->flow_mode == FALSE)
4080 wbxml_buffer_destroy(header);
4081 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
4082 }
4083
4084 /** @todo Use the 'output_charset' field */
4085
4086 /* Copy Header to Result */
4087 memcpy(*xml, wbxml_buffer_get_cstr(header), wbxml_buffer_len(header));
4088
4089 /* Copy XML Document to Result */
4090 memcpy(*xml + wbxml_buffer_len(header), wbxml_buffer_get_cstr(encoder->output), wbxml_buffer_len(encoder->output));
4091
4092 /** @todo Remove this NULL char if not needed by charset */
4093
4094 /* NULL Terminated Buffer */
4095 (*xml)[len] = '\0';
4096
4097 /* Set length */
4098 if (xml_len != NULL)
4099 *xml_len = len;
4100
4101 /* Clean-up */
4102 if (encoder->flow_mode == FALSE)
4103 wbxml_buffer_destroy(header);
4104
4105 return WBXML_OK;
4106 }
4107
4108
4109 /**
4110 * @brief Fill the XML Header
4111 * @param encoder The WBXML Encoder
4112 * @param header The Buffer to Fill
4113 * @return WBXML_OK if built is OK, an error code otherwise
4114 */
xml_fill_header(WBXMLEncoder * encoder,WBXMLBuffer * header)4115 static WBXMLError xml_fill_header(WBXMLEncoder *encoder, WBXMLBuffer *header)
4116 {
4117 if ((encoder == NULL) || (header == NULL))
4118 return WBXML_ERROR_BAD_PARAMETER;
4119
4120 /** @todo Add 'encoding' info */
4121
4122 /* <?xml version=\"1.0\"?> */
4123 if (!wbxml_buffer_append_cstr(header, WBXML_ENCODER_XML_HEADER))
4124 return WBXML_ERROR_ENCODER_APPEND_DATA;
4125
4126 /* New Line */
4127 if (encoder->xml_gen_type == WBXML_GEN_XML_INDENT) {
4128 if (!xml_encode_new_line(header))
4129 return WBXML_ERROR_ENCODER_APPEND_DATA;
4130 }
4131
4132 /* <!DOCTYPE */
4133 if (!wbxml_buffer_append_cstr(header, WBXML_ENCODER_XML_DOCTYPE))
4134 return WBXML_ERROR_ENCODER_APPEND_DATA;
4135
4136 /* Check that the language is set */
4137 if (encoder->lang == NULL)
4138 return WBXML_ERROR_LANG_TABLE_UNDEFINED;
4139
4140 /* Root Element */
4141 if (!wbxml_buffer_append_cstr(header, encoder->lang->publicID->xmlRootElt))
4142 return WBXML_ERROR_ENCODER_APPEND_DATA;
4143
4144 if (encoder->lang->publicID->xmlPublicID &&
4145 WBXML_STRLEN(encoder->lang->publicID->xmlPublicID)) {
4146
4147 /* PUBLIC " */
4148 if (!wbxml_buffer_append_cstr(header, WBXML_ENCODER_XML_PUBLIC_START))
4149 return WBXML_ERROR_ENCODER_APPEND_DATA;
4150
4151 /* Public ID */
4152 if (!wbxml_buffer_append_cstr(header, encoder->lang->publicID->xmlPublicID))
4153 return WBXML_ERROR_ENCODER_APPEND_DATA;
4154
4155 /* " */
4156 if (!wbxml_buffer_append_cstr(header, WBXML_ENCODER_XML_PUBLIC_END))
4157 return WBXML_ERROR_ENCODER_APPEND_DATA;
4158 } else {
4159 /* SYSTEM */
4160 if (!wbxml_buffer_append_cstr(header, WBXML_ENCODER_XML_SYSTEM))
4161 return WBXML_ERROR_ENCODER_APPEND_DATA;
4162 }
4163
4164 /* DTD */
4165 if (!wbxml_buffer_append_cstr(header, WBXML_ENCODER_XML_DTD))
4166 return WBXML_ERROR_ENCODER_APPEND_DATA;
4167
4168 /* DTD */
4169 if (!wbxml_buffer_append_cstr(header, encoder->lang->publicID->xmlDTD))
4170 return WBXML_ERROR_ENCODER_APPEND_DATA;
4171
4172 /* "> */
4173 if (!wbxml_buffer_append_cstr(header, WBXML_ENCODER_XML_END_DTD))
4174 return WBXML_ERROR_ENCODER_APPEND_DATA;
4175
4176 /* New Line */
4177 if (encoder->xml_gen_type == WBXML_GEN_XML_INDENT) {
4178 if (!xml_encode_new_line(header))
4179 return WBXML_ERROR_ENCODER_APPEND_DATA;
4180 }
4181
4182 return WBXML_OK;
4183 }
4184
4185
4186 /****************************
4187 * XML Encoding Functions
4188 */
4189
4190 /**
4191 * @brief Encode an XML Tag
4192 * @param encoder The WBXML Encoder
4193 * @param node The element to encode
4194 * @return WBXML_OK if encoding is OK, an error code otherwise
4195 */
xml_encode_tag(WBXMLEncoder * encoder,WBXMLTreeNode * node)4196 static WBXMLError xml_encode_tag(WBXMLEncoder *encoder, WBXMLTreeNode *node)
4197 {
4198 const WB_TINY *ns = NULL;
4199 WB_UTINY i;
4200
4201 /* Set as current Tag */
4202 if (node->name->type == WBXML_VALUE_TOKEN)
4203 encoder->current_tag = node->name->u.token;
4204 else
4205 encoder->current_tag = NULL;
4206
4207 /* Indent */
4208 if (encoder->xml_gen_type == WBXML_GEN_XML_INDENT) {
4209 for (i=0; i<(encoder->indent * encoder->indent_delta); i++) {
4210 if (!wbxml_buffer_append_char(encoder->output, ' '))
4211 return WBXML_ERROR_ENCODER_APPEND_DATA;
4212 }
4213 }
4214
4215 /* Append < */
4216 if (!wbxml_buffer_append_char(encoder->output, '<'))
4217 return WBXML_ERROR_ENCODER_APPEND_DATA;
4218
4219 /* Append Element Name */
4220 if (!wbxml_buffer_append_cstr(encoder->output, wbxml_tag_get_xml_name(node->name)))
4221 return WBXML_ERROR_ENCODER_APPEND_DATA;
4222
4223 /* NameSpace handling: Check if Current Node Code Page is different than Parent Node Code Page */
4224 if ((encoder->lang->nsTable != NULL) &&
4225 ((node->parent == NULL) ||
4226 ((node->parent->type == WBXML_TREE_ELEMENT_NODE) &&
4227 (node->parent->name->type == WBXML_VALUE_TOKEN) &&
4228 (node->type == WBXML_TREE_ELEMENT_NODE) &&
4229 (node->name->type == WBXML_VALUE_TOKEN) &&
4230 (node->parent->name->u.token->wbxmlCodePage != node->name->u.token->wbxmlCodePage))))
4231 {
4232 if ((ns = wbxml_tables_get_xmlns(encoder->lang->nsTable, node->name->u.token->wbxmlCodePage)) != NULL)
4233 {
4234 /* Append xmlns=" */
4235 if (!wbxml_buffer_append_cstr(encoder->output, " xmlns=\""))
4236 return WBXML_ERROR_ENCODER_APPEND_DATA;
4237
4238 /* Append NameSpace */
4239 if (!wbxml_buffer_append_cstr(encoder->output, ns))
4240 return WBXML_ERROR_ENCODER_APPEND_DATA;
4241
4242 /* Append " */
4243 if (!wbxml_buffer_append_char(encoder->output, '"'))
4244 return WBXML_ERROR_ENCODER_APPEND_DATA;
4245 }
4246 }
4247
4248 return WBXML_OK;
4249 }
4250
4251
4252 /**
4253 * @brief Encode an XML End Tag
4254 * @param encoder The WBXML Encoder
4255 * @param node Tag
4256 * @return WBXML_OK if encoding is OK, an error code otherwise
4257 */
xml_encode_end_tag(WBXMLEncoder * encoder,WBXMLTreeNode * node)4258 static WBXMLError xml_encode_end_tag(WBXMLEncoder *encoder, WBXMLTreeNode *node)
4259 {
4260 WB_UTINY i;
4261
4262 if (encoder->xml_gen_type == WBXML_GEN_XML_INDENT) {
4263
4264 #if defined( WBXML_ENCODER_XML_NO_EMPTY_ELT_INDENT )
4265 if (wbxml_tree_node_have_child_elt(node)) {
4266 #endif /* WBXML_ENCODER_XML_NO_EMPTY_ELT_INDENT */
4267
4268 /* Add a New Line if there were content in this element */
4269 if (encoder->in_content) {
4270 if (!xml_encode_new_line(encoder->output))
4271 return WBXML_ERROR_ENCODER_APPEND_DATA;
4272 }
4273
4274 encoder->indent--;
4275
4276 /* Indent End Element */
4277 for (i=0; i<(encoder->indent * encoder->indent_delta); i++) {
4278 if (!wbxml_buffer_append_char(encoder->output, ' '))
4279 return WBXML_ERROR_ENCODER_APPEND_DATA;
4280 }
4281
4282 #if defined( WBXML_ENCODER_XML_NO_EMPTY_ELT_INDENT )
4283 }
4284 #endif /* WBXML_ENCODER_XML_NO_EMPTY_ELT_INDENT */
4285
4286 }
4287
4288 /* Append </ */
4289 if (!wbxml_buffer_append_cstr(encoder->output, "</"))
4290 return WBXML_ERROR_ENCODER_APPEND_DATA;
4291
4292 /* Append Element Name */
4293 if (!wbxml_buffer_append_cstr(encoder->output, wbxml_tag_get_xml_name(node->name)))
4294 return WBXML_ERROR_ENCODER_APPEND_DATA;
4295
4296 /* Append > */
4297 if (!wbxml_buffer_append_char(encoder->output, '>'))
4298 return WBXML_ERROR_ENCODER_APPEND_DATA;
4299
4300 /* New Line */
4301 if (encoder->xml_gen_type == WBXML_GEN_XML_INDENT) {
4302 if (!xml_encode_new_line(encoder->output))
4303 return WBXML_ERROR_ENCODER_APPEND_DATA;
4304 }
4305
4306 /* No more in content */
4307 encoder->in_content = FALSE;
4308
4309 return WBXML_OK;
4310 }
4311
4312
4313 /**
4314 * @brief Encode a XML Attribute
4315 * @param encoder [in] The WBXML Encoder
4316 * @param attribute [in] The Attribute to encode
4317 * @return WBXML_OK if encoding is OK, an error code otherwise
4318 */
xml_encode_attr(WBXMLEncoder * encoder,WBXMLAttribute * attribute)4319 static WBXMLError xml_encode_attr(WBXMLEncoder *encoder, WBXMLAttribute *attribute)
4320 {
4321 /* Append a space */
4322 if (!wbxml_buffer_append_char(encoder->output, ' '))
4323 return WBXML_ERROR_ENCODER_APPEND_DATA;
4324
4325 /* Append Attribute Name */
4326 if (!wbxml_buffer_append_cstr(encoder->output, wbxml_attribute_get_xml_name(attribute)))
4327 return WBXML_ERROR_ENCODER_APPEND_DATA;
4328
4329 /* Append =" */
4330 if (!wbxml_buffer_append_cstr(encoder->output, "=\""))
4331 return WBXML_ERROR_ENCODER_APPEND_DATA;
4332
4333 if (wbxml_attribute_get_xml_value(attribute) != NULL) {
4334 /* Fix Attribute Value text */
4335 WBXMLBuffer *tmp = NULL;
4336
4337 /* Work with a temporary copy */
4338 if ((tmp = wbxml_buffer_create_from_cstr(wbxml_attribute_get_xml_value(attribute))) == NULL)
4339 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
4340
4341 /* Fix text */
4342 if (xml_encode_text_entities(encoder, tmp)) {
4343 wbxml_buffer_destroy(tmp);
4344 return WBXML_ERROR_ENCODER_APPEND_DATA;
4345 }
4346
4347 wbxml_buffer_destroy(tmp);
4348 }
4349
4350 /* Append " */
4351 if (!wbxml_buffer_append_char(encoder->output, '"'))
4352 return WBXML_ERROR_ENCODER_APPEND_DATA;
4353
4354 return WBXML_OK;
4355 }
4356
4357
4358 /**
4359 * @brief Encode a End of XML Attributes List
4360 * @param encoder [in] The WBXML Encoder
4361 * @param node [in] Current node
4362 * @return WBXML_OK if encoding is OK, an error code otherwise
4363 */
xml_encode_end_attrs(WBXMLEncoder * encoder,WBXMLTreeNode * node)4364 static WBXMLError xml_encode_end_attrs(WBXMLEncoder *encoder, WBXMLTreeNode *node)
4365 {
4366 #if defined( WBXML_ENCODER_XML_GEN_EMPTY_ELT )
4367
4368 if (node->children == NULL) {
4369 /* Append " />" */
4370 if (!wbxml_buffer_append_cstr(encoder->output, "/>"))
4371 return WBXML_ERROR_ENCODER_APPEND_DATA;
4372
4373 /* New Line */
4374 if (encoder->xml_gen_type == WBXML_GEN_XML_INDENT) {
4375 if (!xml_encode_new_line(encoder->output))
4376 return WBXML_ERROR_ENCODER_APPEND_DATA;
4377 }
4378 }
4379 else {
4380
4381 #endif /* WBXML_ENCODER_XML_GEN_EMPTY_ELT */
4382
4383 /* Append > */
4384 if (!wbxml_buffer_append_char(encoder->output, '>'))
4385 return WBXML_ERROR_ENCODER_APPEND_DATA;
4386
4387 /* New Line */
4388 if (encoder->xml_gen_type == WBXML_GEN_XML_INDENT) {
4389
4390 #if defined( WBXML_ENCODER_XML_NO_EMPTY_ELT_INDENT )
4391 if (wbxml_tree_node_have_child_elt(node)) {
4392 #endif /* WBXML_ENCODER_XML_NO_EMPTY_ELT_INDENT */
4393
4394 if (!xml_encode_new_line(encoder->output))
4395 return WBXML_ERROR_ENCODER_APPEND_DATA;
4396
4397 /* Increment indentation */
4398 encoder->indent++;
4399
4400 #if defined( WBXML_ENCODER_XML_NO_EMPTY_ELT_INDENT )
4401 }
4402 #endif /* WBXML_ENCODER_XML_NO_EMPTY_ELT_INDENT */
4403
4404 }
4405
4406 #if defined( WBXML_ENCODER_XML_GEN_EMPTY_ELT )
4407
4408 }
4409
4410 #endif /* WBXML_ENCODER_XML_GEN_EMPTY_ELT */
4411
4412 return WBXML_OK;
4413 }
4414
4415 /**
4416 * @brief Encode an XML Text
4417 * @param encoder The WBXML Encoder
4418 * @param node The node containing XML Text to encode
4419 * @return WBXML_OK if encoding is OK, an error code otherwise
4420 */
xml_encode_text(WBXMLEncoder * encoder,WBXMLTreeNode * node)4421 static WBXMLError xml_encode_text(WBXMLEncoder *encoder, WBXMLTreeNode *node)
4422 {
4423 WBXMLBuffer *str = node->content;
4424 WBXMLBuffer *tmp = NULL;
4425 WB_UTINY i = 0;
4426
4427 if (encoder->in_cdata) {
4428 /* If we are in a CDATA section, do not modify the text to encode */
4429 if (!wbxml_buffer_append(encoder->output, str))
4430 return WBXML_ERROR_ENCODER_APPEND_DATA;
4431 }
4432 else {
4433 /* Work with a temporary copy */
4434 if ((tmp = wbxml_buffer_duplicate(str)) == NULL)
4435 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
4436
4437 /* Indent */
4438 if ((encoder->xml_gen_type == WBXML_GEN_XML_INDENT) &&
4439 (!encoder->in_content))
4440 {
4441 #if defined( WBXML_ENCODER_XML_NO_EMPTY_ELT_INDENT )
4442 if (wbxml_tree_node_have_child_elt(node)) {
4443 #endif /* WBXML_ENCODER_XML_NO_EMPTY_ELT_INDENT */
4444
4445 /* Indent Content (only indent in first call to xml_encode_text()) */
4446 for (i=0; i<(encoder->indent * encoder->indent_delta); i++) {
4447 if (!wbxml_buffer_append_char(encoder->output, ' ')) {
4448 wbxml_buffer_destroy(tmp);
4449 return WBXML_ERROR_ENCODER_APPEND_DATA;
4450 }
4451 }
4452
4453 #if defined( WBXML_ENCODER_XML_NO_EMPTY_ELT_INDENT )
4454 }
4455 #endif /* WBXML_ENCODER_XML_NO_EMPTY_ELT_INDENT */
4456 }
4457
4458 #if defined( WBXML_SUPPORT_SYNCML )
4459 /* Change text in <Type> from "application/vnd.syncml-devinf+wbxml" to "application/vnd.syncml-devinf+xml" */
4460 if (((encoder->lang->langID == WBXML_LANG_SYNCML_SYNCML10) ||
4461 (encoder->lang->langID == WBXML_LANG_SYNCML_SYNCML11) ||
4462 (encoder->lang->langID == WBXML_LANG_SYNCML_SYNCML12)) &&
4463 (encoder->current_tag != NULL) &&
4464 (encoder->current_tag->wbxmlCodePage == 0x01 ) &&
4465 (encoder->current_tag->wbxmlToken == 0x13 ) &&
4466 (wbxml_buffer_compare_cstr(tmp, "application/vnd.syncml-devinf+wbxml") == 0))
4467 {
4468 wbxml_buffer_destroy(tmp);
4469
4470 /* Change Content */
4471 if ((tmp = wbxml_buffer_create_from_cstr("application/vnd.syncml-devinf+xml")) == NULL)
4472 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
4473 }
4474 /* Change text in <Type> from "application/vnd.syncml.dmtnds+wbxml" to "application/vnd.syncml.dmtnds+xml" */
4475 if ((encoder->lang->langID == WBXML_LANG_SYNCML_SYNCML12) &&
4476 (encoder->current_tag != NULL) &&
4477 (encoder->current_tag->wbxmlCodePage == 0x01 ) &&
4478 (encoder->current_tag->wbxmlToken == 0x13 ) &&
4479 (wbxml_buffer_compare_cstr(tmp, "application/vnd.syncml.dmtnds+wbxml") == 0))
4480 {
4481 wbxml_buffer_destroy(tmp);
4482
4483 /* Change Content */
4484 if ((tmp = wbxml_buffer_create_from_cstr("application/vnd.syncml.dmtnds+xml")) == NULL)
4485 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
4486 }
4487 #endif /* WBXML_SUPPORT_SYNCML */
4488
4489 /* Some elements are transferred as WBXML opaque data. They contain
4490 * binary data that isn't necessary valid in XML, so return them in Base
4491 * 64.
4492 */
4493 if (encoder->current_tag != NULL &&
4494 encoder->current_tag->options & WBXML_TAG_OPTION_BINARY)
4495 {
4496 WBXMLError ret;
4497 if ((ret = wbxml_buffer_encode_base64(tmp)) != WBXML_OK) {
4498 wbxml_buffer_destroy(tmp);
4499 return ret;
4500 }
4501 }
4502
4503 /* Fix text */
4504 if (xml_encode_text_entities(encoder, tmp)) {
4505 wbxml_buffer_destroy(tmp);
4506 return WBXML_ERROR_ENCODER_APPEND_DATA;
4507 }
4508
4509 /* Clean-up */
4510 wbxml_buffer_destroy(tmp);
4511 }
4512
4513 encoder->in_content = TRUE;
4514
4515 return WBXML_OK;
4516 }
4517
4518
4519 /**
4520 * @brief Append a New Line to a Buffer
4521 * @param buff The Buffer
4522 * @return TRUE if added, FALSE otherwise
4523 */
xml_encode_new_line(WBXMLBuffer * buff)4524 static WB_BOOL xml_encode_new_line(WBXMLBuffer *buff)
4525 {
4526 if (buff == NULL)
4527 return FALSE;
4528
4529 return wbxml_buffer_append_data(buff, WBXML_ENCODER_XML_NEW_LINE, WBXML_STRLEN(WBXML_ENCODER_XML_NEW_LINE));
4530 }
4531
4532
4533 /**
4534 * @brief Fix an XML text buffer (content text or attribute value)
4535 * @param buff The Buffer to fix
4536 * @param normalize Normalize text ?
4537 * @return WBXML_OK if ok, an Error Code otherwise
4538 * @note Reference: http://www.w3.org/TR/2004/REC-xml-20040204/#syntax
4539 */
xml_encode_text_entities(WBXMLEncoder * encoder,WBXMLBuffer * buff)4540 static WBXMLError xml_encode_text_entities(WBXMLEncoder *encoder, WBXMLBuffer *buff)
4541 {
4542 WB_ULONG i = 0;
4543 WB_UTINY ch;
4544 WB_BOOL normalize = (WB_BOOL) (encoder->xml_gen_type == WBXML_GEN_XML_CANONICAL);
4545
4546 for (i = 0; i < wbxml_buffer_len(buff); i++) {
4547 if (!wbxml_buffer_get_char(buff, i, &ch))
4548 continue;
4549
4550 switch (ch) {
4551 case '<':
4552 /* Write "<" */
4553 if (!wbxml_buffer_append_cstr(encoder->output, (WB_UTINY *) xml_lt))
4554 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
4555
4556 break;
4557
4558 case '>':
4559 /* Write ">" */
4560 if (!wbxml_buffer_append_cstr(encoder->output, (WB_UTINY *) xml_gt))
4561 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
4562
4563 break;
4564
4565 case '&':
4566 /* Write "&" */
4567 if (!wbxml_buffer_append_cstr(encoder->output, (WB_UTINY *) xml_amp))
4568 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
4569
4570 break;
4571
4572 case '"':
4573 /* Write """ */
4574 if (!wbxml_buffer_append_cstr(encoder->output, (WB_UTINY *) xml_quot))
4575 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
4576
4577 break;
4578
4579 case '\'':
4580 /* Write "'" */
4581 if (!wbxml_buffer_append_cstr(encoder->output, (WB_UTINY *) xml_apos))
4582 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
4583
4584 break;
4585
4586 case '\r':
4587 if (normalize) {
4588 /* Write " " */
4589 if (!wbxml_buffer_append_cstr(encoder->output, (WB_UTINY *) xml_slashr))
4590 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
4591
4592 break;
4593 }
4594
4595 case '\n':
4596 if (normalize) {
4597 /* Write " " */
4598 if (!wbxml_buffer_append_cstr(encoder->output, (WB_UTINY *) xml_slashn))
4599 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
4600 break;
4601 }
4602
4603 case '\t':
4604 if (normalize) {
4605 /* Write "	" */
4606 if (!wbxml_buffer_append_cstr(encoder->output, (WB_UTINY *) xml_tab))
4607 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
4608 break;
4609 }
4610
4611 default:
4612 if (!wbxml_buffer_append_char(encoder->output, ch))
4613 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
4614
4615 break;
4616 }
4617 }
4618
4619 return WBXML_OK;
4620 }
4621
4622
4623 /**
4624 * @brief Encode a begin of CDATA section
4625 * @param encoder The WBXML Encoder
4626 * @return WBXML_OK if encoding is OK, an error code otherwise
4627 */
xml_encode_cdata(WBXMLEncoder * encoder)4628 static WBXMLError xml_encode_cdata(WBXMLEncoder *encoder)
4629 {
4630 /* Append <![CDATA[ */
4631 if (!wbxml_buffer_append_cstr(encoder->output, "<![CDATA["))
4632 return WBXML_ERROR_ENCODER_APPEND_DATA;
4633
4634 return WBXML_OK;
4635 }
4636
4637
4638 /**
4639 * @brief Encode an end of CDATA section
4640 * @param encoder The WBXML Encoder
4641 * @return WBXML_OK if encoding is OK, an error code otherwise
4642 */
xml_encode_end_cdata(WBXMLEncoder * encoder)4643 static WBXMLError xml_encode_end_cdata(WBXMLEncoder *encoder)
4644 {
4645 /* Append ]]> */
4646 if (!wbxml_buffer_append_cstr(encoder->output, "]]>"))
4647 return WBXML_ERROR_ENCODER_APPEND_DATA;
4648
4649 return WBXML_OK;
4650 }
4651
4652
4653 /**
4654 * @brief Encode an encapsulated WBXML Tree to XML
4655 * @param encoder [in] The WBXML Encoder
4656 * @param tree [in] The WBXML Tree to encode
4657 * @return WBXML_OK if encoding is OK, an error code otherwise
4658 */
xml_encode_tree(WBXMLEncoder * encoder,WBXMLTree * tree)4659 static WBXMLError xml_encode_tree(WBXMLEncoder *encoder, WBXMLTree *tree)
4660 {
4661 WBXMLEncoder *new_encoder = NULL;
4662 WB_UTINY *xml = NULL;
4663 WB_ULONG xml_len = 0;
4664 WBXMLError ret = WBXML_OK;
4665
4666 if ((new_encoder = encoder_duplicate(encoder)) == NULL)
4667 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
4668
4669 /* Set Tree */
4670 new_encoder->tree = tree;
4671
4672 /* Encode to XML */
4673 if ((ret = wbxml_encoder_encode_tree_to_xml(new_encoder, &xml, &xml_len)) != WBXML_OK) {
4674 wbxml_encoder_destroy(new_encoder);
4675 return ret;
4676 }
4677
4678 /* Clean-up */
4679 wbxml_encoder_destroy(new_encoder);
4680
4681 /** @bug Handle output_charset ! */
4682
4683 /* Append xml to output */
4684 if (!wbxml_buffer_append_cstr(encoder->output, xml)) {
4685 wbxml_free(xml);
4686 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
4687 }
4688
4689 /* Clean-up */
4690 wbxml_free(xml);
4691
4692 return WBXML_OK;
4693 }
4694