2 * Routines for wbxml dissection
3 * Copyright 2003, Olivier Biot <olivier.biot (ad) siemens.com>
5 * $Id: packet-wbxml.c,v 1.13 2003/11/19 22:55:27 guy Exp $
7 * Ethereal - Network traffic analyzer
8 * By Gerald Combs <gerald@ethereal.com>
9 * Copyright 1998 Gerald Combs
11 * WAP Binary XML decoding functionality provided by Olivier Biot.
13 * The WAP specifications are found at the WAP Forum:
14 * http://www.wapforum.org/what/Technical.htm
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License
18 * as published by the Free Software Foundation; either version 2
19 * of the License, or (at your option) any later version.
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
31 /* Edit this file with 4-space tabulation */
43 #ifdef NEED_SNPRINTF_H
44 # include "snprintf.h"
47 #include <epan/packet.h>
49 /* We need the function tvb_get_guintvar() */
50 #include "packet-wap.h"
52 /* The code in this source file dissects the WAP Binary XML content,
53 * and if possible renders it. WBXML mappings are defined in the
54 * "wbxml_map[]" array.
58 * - Code page switches only apply to the following token. In the WBXML/1.x
59 * ABNF notation, it can be proven that the switch_page can only precede
60 * the following tokens:
61 * o stag : TAG | LITERAL | LITERAL_A | LITERAL_C | LITERAL_AC
62 * o attr : ATTRSTART | ATTRVALUE
63 * o extension : EXT_I | EXT_T | EXT
64 * Code page switches are displayed in a separate column. The only allowed
65 * code page switches are from code page 0 to another codepage (by means of
66 * a SWITCH_PAGE token), and from this other code page back to code page 0
67 * (this happens automatically).
69 * - In order to render the XML content, recursion is inevitable at some
70 * point (when a tag with content occurs in the content of a tag with
71 * content). The code will however not recurse if this is not strictly
72 * required (e.g., tag without content in the content of a tag with
75 * - I found it useful to display the XML nesting level as a first "column",
76 * followed by the abbreviated WBXML token interpretation. When a mapping
77 * is defined for the parsed WBXML content, then the XML rendering is
78 * displayed with appropriate indentation (maximum nesting level = 255,
79 * after which the nesting and level will safely roll-over to 0).
81 * - The WAP Forum defines the order of precedence for finding out the
82 * WBXML content type (same rules for charset) as follows:
83 * 1. Look in the Content-Type WSP header
84 * 2. Look in the WBXML header
85 * Currently there is no means of using content type parameters:
87 * o Charset=<charset_of_the_content>
88 * So it is possible some WBXML content types are incorrectly parsed.
89 * This would only be the case when the content type declaration in the
90 * WSP Content-Type header would be different (or would have parameters
91 * which are relevant to the WBXML decoding) from the content type
92 * identifier specified in the WBXML header.
93 * TODO: investigate this and provide correct decoding at all times.
96 typedef struct _value_valuestring {
98 const value_string *valstrptr;
101 /* Tries to match val against each element in the value_value_string array vvs.
102 * Returns the associated value_string ptr on a match, or NULL on failure. */
103 static const value_string *
104 val_to_valstr(guint32 val, const value_valuestring *vvs)
108 while (vvs[i].valstrptr) {
109 if (vvs[i].value == val)
110 return(vvs[i].valstrptr);
118 /************************** Variable declarations **************************/
121 /* Initialize the protocol and registered fields */
122 static int proto_wbxml = -1;
123 static int hf_wbxml_version = -1;
124 static int hf_wbxml_public_id_known = -1;
125 static int hf_wbxml_public_id_literal = -1;
126 static int hf_wbxml_charset = -1;
128 /* Initialize the subtree pointers */
129 static gint ett_wbxml = -1;
130 static gint ett_wbxml_str_tbl = -1;
131 static gint ett_wbxml_content = -1;
134 /**************** WBXML related declarations and definitions ****************/
137 /* WBXML public ID mappings. For an up-to-date list, see
138 * http://www.wapforum.org/wina/wbxml-public-docid.htm */
139 static const value_string vals_wbxml_public_ids[] = {
140 /* 0x00 = literal public identifier */
141 { 0x01, "Unknown / missing Public Identifier" },
142 { 0x02, "-//WAPFORUM//DTD WML 1.0//EN (WML 1.0)" },
143 { 0x03, "-//WAPFORUM//DTD WTA 1.0//EN (WTA Event 1.0) - Deprecated" },
144 { 0x04, "-//WAPFORUM//DTD WML 1.1//EN (WML 1.1)" },
145 { 0x05, "-//WAPFORUM//DTD SI 1.0//EN (Service Indication 1.0)" },
146 { 0x06, "-//WAPFORUM//DTD SL 1.0//EN (Service Loading 1.0)" },
147 { 0x07, "-//WAPFORUM//DTD CO 1.0//EN (Cache Operation 1.0)" },
148 { 0x08, "-//WAPFORUM//DTD CHANNEL 1.0//EN (Channel 1.1)" },
149 { 0x09, "-//WAPFORUM//DTD WML 1.2//EN (WML 1.2)" },
150 { 0x0a, "-//WAPFORUM//DTD WML 1.3//EN (WML 1.3)" },
151 { 0x0b, "-//WAPFORUM//DTD PROV 1.0//EN (Provisioning 1.0)" },
152 { 0x0c, "-//WAPFORUM//DTD WTA-WML 1.2//EN (WTA-WML 1.2)" },
153 { 0x0d, "-//WAPFORUM//DTD EMN 1.0//EN (Email Notification 1.0)" },
154 { 0x0e, "-//WAPFORUM//DTD DRMREL 1.0//EN (DRMREL 1.0)" },
156 /* Registered values - www.syncml.org */
157 { 0x0fd1, "-//SYNCML//DTD SyncML 1.0//EN (SyncML 1.0)" },
158 { 0x0fd3, "-//SYNCML//DTD SyncML 1.1//EN (SyncML 1.1)" },
160 /* Registered values - www.wapforum.org/wina/ */
161 { 0x1100, "-//PHONE.COM//DTD ALERT 1.0//EN" },
162 { 0x1101, "-//PHONE.COM//DTD CACHE-OPERATION 1.0//EN" },
163 { 0x1102, "-//PHONE.COM//DTD SIGNAL 1.0//EN" },
164 { 0x1103, "-//PHONE.COM//DTD LIST 1.0//EN" },
165 { 0x1104, "-//PHONE.COM//DTD LISTCMD 1.0//EN" },
166 { 0x1105, "-//PHONE.COM//DTD CHANNEL 1.0//EN" },
167 { 0x1106, "-//PHONE.COM//DTD MMC 1.0//EN" },
168 { 0x1107, "-//PHONE.COM//DTD BEARER-CHOICE 1.0//EN" },
169 { 0x1108, "-//PHONE.COM//DTD WML 1.1//EN (WML+ 1.1)" },
170 { 0x1109, "-//PHONE.COM//DTD CHANNEL 1.1//EN" },
171 { 0x110a, "-//PHONE.COM//DTD LIST 1.1//EN" },
172 { 0x110b, "-//PHONE.COM//DTD LISTCMD 1.1//EN" },
173 { 0x110c, "-//PHONE.COM//DTD MMC 1.1//EN" },
174 { 0x110d, "-//PHONE.COM//DTD WML 1.3//EN (WML+ 1.3)" },
175 { 0x110e, "-//PHONE.COM//DTD MMC 2.0//EN" },
180 static const value_string vals_wbxml_versions[] = {
181 { 0x00, "1.0" }, /* WAP-104-WBXML */
182 { 0x01, "1.1" }, /* WAP-135-WBXML */
183 { 0x02, "1.2" }, /* WAP-154-WBXML */
184 { 0x03, "1.3" }, /* WAP-192-WBXML */
189 /* WBXML 1.0 global tokens: WAP-104-WBXML
190 * Same token mapping as in vals_wbxml1x_global_tokens, but:
191 * { 0xC3, "RESERVED_2" }
194 /* WBXML 1.x (x>0) global tokens: WAP-135-WBXML, WAP-154-WBXML, WAP-192-WBXML
196 static const value_string vals_wbxml1x_global_tokens[] = {
197 { 0x00, "SWITCH_PAGE" },
207 { 0x44, "LITERAL_C" },
213 { 0x84, "LITERAL_A" },
219 { 0xC4, "LITERAL_AC" },
225 /********************** WBXML token mapping definition **********************/
230 * Wireless Markup Language
231 ***************************************/
233 /***** Global extension tokens *****/
234 static const value_string wbxml_wmlc10_global_cp0[] = {
235 { 0x40, "Variable substitution - escaped" },
236 { 0x41, "Variable substitution - unescaped" },
237 { 0x42, "Variable substitution - no transformation" },
238 { 0x80, "Variable substitution - escaped" },
239 { 0x81, "Variable substitution - unescaped" },
240 { 0x82, "Variable substitution - no transformation" },
241 { 0xC0, "Reserved" },
242 { 0xC1, "Reserved" },
243 { 0xC2, "Reserved" },
248 /***** Tag tokens *****/
249 static const value_string wbxml_wmlc10_tags_cp0[] = {
250 /* 0x00 -- 0x04 GLOBAL */
260 { 0xEA, "FIELDSET" },
270 { 0xF4, "OPTGROUP" },
277 { 0xFB, "TEMPLATE" },
286 /***** Attribute Start tokens *****/
287 static const value_string wbxml_wmlc10_attrStart_cp0[] = {
288 /* 0x00 -- 0x04 GLOBAL */
289 { 0x05, "ACCEPT-CHARSET=" },
290 { 0x06, "ALIGN='BOTTOM'" },
291 { 0x07, "ALIGN='CENTER'" },
292 { 0x08, "ALIGN='LEFT'" },
293 { 0x09, "ALIGN='MIDDLE'" },
294 { 0x0A, "ALIGN='RIGHT'" },
295 { 0x0B, "ALIGN='TOP'" },
297 { 0x0D, "CONTENT=" },
298 { 0x0E, "DEFAULT=" },
300 { 0x10, "EMPTYOK='FALSE'" },
301 { 0x11, "EMPTYOK='TRUE'" },
305 { 0x15, "IDEFAULT=" },
309 { 0x19, "LOCALSRC=" },
310 { 0x1A, "MAXLENGTH=" },
311 { 0x1B, "METHOD='GET'" },
312 { 0x1C, "METHOD='POST'" },
313 { 0x1D, "MODE='NOWRAP'" },
314 { 0x1E, "MODE='WRAP'" },
315 { 0x1F, "MULTIPLE='FALSE'" },
316 { 0x20, "MULTIPLE='TRUE'" },
318 { 0x22, "NEWCONTEXT='FALSE'" },
319 { 0x23, "NEWCONTEXT='TRUE'" },
320 { 0x24, "ONCLICK=" },
321 { 0x25, "ONENTERBACKWARD=" },
322 { 0x26, "ONENTERFORWARD=" },
323 { 0x27, "ONTIMER=" },
324 { 0x28, "OPTIONAL='FALSE'" },
325 { 0x29, "OPTIONAL='TRUE'" },
327 { 0x2B, "POSTDATA=" },
328 { 0x2C, "PUBLIC='FALSE'" },
329 { 0x2D, "PUBLIC='TRUE'" },
331 { 0x2F, "SENDREFERER='FALSE'" },
332 { 0x30, "SENDREFERER='TRUE'" },
335 { 0x33, "STYLE='LIST'" },
336 { 0x34, "STYLE='SET'" },
337 { 0x35, "TABINDEX=" },
340 { 0x38, "TYPE='ACCEPT'" },
341 { 0x39, "TYPE='DELETE'" },
342 { 0x3A, "TYPE='HELP'" },
343 { 0x3B, "TYPE='PASSWORD'" },
344 { 0x3C, "TYPE='ONCLICK'" },
345 { 0x3D, "TYPE='ONENTERBACKWARD'" },
346 { 0x3E, "TYPE='ONENTERFORWARD'" },
347 { 0x3F, "TYPE='ONTIMER'" },
348 /* 0x40 -- 0x44 GLOBAL */
349 { 0x45, "TYPE='OPTIONS'" },
350 { 0x46, "TYPE='PREV'" },
351 { 0x47, "TYPE='RESET'" },
352 { 0x48, "TYPE='TEXT'" },
353 { 0x49, "TYPE='vnd.'" },
355 { 0x4B, "URL='http://'" },
356 { 0x4C, "URL='https://'" },
357 { 0x4D, "USER-AGENT=" },
361 { 0x51, "xml:lang=" },
366 /***** Attribute Value tokens *****/
367 static const value_string wbxml_wmlc10_attrValue_cp0[] = {
368 /* 0x80 -- 0x84 GLOBAL */
373 { 0x89, "'ACCEPT'" },
374 { 0x8A, "'BOTTOM'" },
376 { 0x8C, "'DELETE'" },
378 { 0x8E, "'http://'" },
379 { 0x8F, "'http://www.'" },
380 { 0x90, "'https://'" },
381 { 0x91, "'https://www.'" },
383 { 0x93, "'MIDDLE'" },
384 { 0x94, "'NOWRAP'" },
385 { 0x95, "'ONCLICK'" },
386 { 0x96, "'ONENTERBACKWARD'" },
387 { 0x97, "'ONENTERFORWARD'" },
388 { 0x98, "'ONTIMER'" },
389 { 0x99, "'OPTIONS'" },
390 { 0x9A, "'PASSWORD'" },
395 { 0x9F, "'UNKNOWN'" },
402 /***** Token code page aggregation *****/
403 static const value_valuestring wbxml_wmlc10_global[] = {
404 { 0, wbxml_wmlc10_global_cp0 },
408 static const value_valuestring wbxml_wmlc10_tags[] = {
409 { 0, wbxml_wmlc10_tags_cp0 },
413 static const value_valuestring wbxml_wmlc10_attrStart[] = {
414 { 0, wbxml_wmlc10_attrStart_cp0 },
418 static const value_valuestring wbxml_wmlc10_attrValue[] = {
419 { 0, wbxml_wmlc10_attrValue_cp0 },
429 * Wireless Markup Language
430 ***************************************/
432 /***** Global extension tokens *****/
433 /* Same as in WML 1.0 */
435 /***** Tag tokens *****/
436 static const value_string wbxml_wmlc11_tags_cp0[] = {
437 /* 0x00 -- 0x04 GLOBAL */
444 { 0x21, "postfield" },
453 { 0x2A, "fieldset" },
463 { 0x34, "optgroup" },
470 { 0x3B, "template" },
479 /***** Attribute Start tokens *****/
480 static const value_string wbxml_wmlc11_attrStart_cp0[] = {
481 /* 0x00 -- 0x04 GLOBAL */
482 { 0x05, "accept-charset=" },
483 { 0x06, "align='bottom'" },
484 { 0x07, "align='center'" },
485 { 0x08, "align='left'" },
486 { 0x09, "align='middle'" },
487 { 0x0A, "align='right'" },
488 { 0x0B, "align='top'" },
490 { 0x0D, "content=" },
493 { 0x10, "emptyok='false'" },
494 { 0x11, "emptyok='true'" },
502 { 0x19, "localsrc=" },
503 { 0x1A, "maxlength=" },
504 { 0x1B, "method='get'" },
505 { 0x1C, "method='post'" },
506 { 0x1D, "mode='nowrap'" },
507 { 0x1E, "mode='wrap'" },
508 { 0x1F, "multiple='false'" },
509 { 0x20, "multiple='true'" },
511 { 0x22, "newcontext='false'" },
512 { 0x23, "newcontext='true'" },
514 { 0x25, "onenterbackward=" },
515 { 0x26, "onenterforward=" },
516 { 0x27, "ontimer=" },
517 { 0x28, "optional='false'" },
518 { 0x29, "optional='true'" },
522 { 0x2F, "sendreferer='false'" },
523 { 0x30, "sendreferer='true'" },
526 { 0x33, "ordered='false'" },
527 { 0x34, "ordered='true'" },
528 { 0x35, "tabindex=" },
531 { 0x38, "type='accept'" },
532 { 0x39, "type='delete'" },
533 { 0x3A, "type='help'" },
534 { 0x3B, "type='password'" },
535 { 0x3C, "type='onpick'" },
536 { 0x3D, "type='onenterbackward'" },
537 { 0x3E, "type='onenterforward'" },
538 { 0x3F, "type='ontimer'" },
539 /* 0x40 -- 0x44 GLOBAL */
540 { 0x45, "type='options'" },
541 { 0x46, "type='prev'" },
542 { 0x47, "type='reset'" },
543 { 0x48, "type='text'" },
544 { 0x49, "type='vnd.'" },
546 { 0x4B, "href='http://'" },
547 { 0x4C, "href='https://'" },
551 { 0x50, "xml:lang=" },
554 { 0x53, "columns=" },
557 { 0x56, "forua='false'" },
558 { 0x57, "forua='true'" },
559 { 0x58, "src='http://'" },
560 { 0x59, "src='https://'" },
561 { 0x5A, "http-equiv=" },
562 { 0x5B, "http-equiv='Content-Type'" },
563 { 0x5C, "content='application/vnd.wap.wmlc;charset='" },
564 { 0x5D, "http-equiv='Expires'" },
569 /***** Attribute Value tokens *****/
570 static const value_string wbxml_wmlc11_attrValue_cp0[] = {
571 /* 0x80 -- 0x84 GLOBAL */
576 { 0x89, "'accept'" },
577 { 0x8A, "'bottom'" },
579 { 0x8C, "'delete'" },
581 { 0x8E, "'http://'" },
582 { 0x8F, "'http://www.'" },
583 { 0x90, "'https://'" },
584 { 0x91, "'https://www.'" },
586 { 0x93, "'middle'" },
587 { 0x94, "'nowrap'" },
588 { 0x95, "'onpick'" },
589 { 0x96, "'onenterbackward'" },
590 { 0x97, "'onenterforward'" },
591 { 0x98, "'ontimer'" },
592 { 0x99, "'options'" },
593 { 0x9A, "'password'" },
598 { 0x9F, "'unknown'" },
605 /***** Token code page aggregation *****/
606 static const value_valuestring wbxml_wmlc11_global[] = {
607 { 0, wbxml_wmlc10_global_cp0 }, /* Same as WML 1.0 */
611 static const value_valuestring wbxml_wmlc11_tags[] = {
612 { 0, wbxml_wmlc11_tags_cp0 },
616 static const value_valuestring wbxml_wmlc11_attrStart[] = {
617 { 0, wbxml_wmlc11_attrStart_cp0 },
621 static const value_valuestring wbxml_wmlc11_attrValue[] = {
622 { 0, wbxml_wmlc11_attrValue_cp0 },
632 * Wireless Markup Language
633 ***************************************/
635 /***** Global extension tokens *****/
636 /* Same as in WML 1.0 */
638 /***** Tag tokens *****/
639 static const value_string wbxml_wmlc12_tags_cp0[] = {
640 /* 0x00 -- 0x04 GLOBAL */
648 { 0x21, "postfield" },
657 { 0x2A, "fieldset" },
667 { 0x34, "optgroup" },
674 { 0x3B, "template" },
683 /***** Attribute Start tokens *****/
684 static const value_string wbxml_wmlc12_attrStart_cp0[] = {
685 /* 0x00 -- 0x04 GLOBAL */
686 { 0x05, "accept-charset=" },
687 { 0x06, "align='bottom'" },
688 { 0x07, "align='center'" },
689 { 0x08, "align='left'" },
690 { 0x09, "align='middle'" },
691 { 0x0A, "align='right'" },
692 { 0x0B, "align='top'" },
694 { 0x0D, "content=" },
697 { 0x10, "emptyok='false'" },
698 { 0x11, "emptyok='true'" },
706 { 0x19, "localsrc=" },
707 { 0x1A, "maxlength=" },
708 { 0x1B, "method='get'" },
709 { 0x1C, "method='post'" },
710 { 0x1D, "mode='nowrap'" },
711 { 0x1E, "mode='wrap'" },
712 { 0x1F, "multiple='false'" },
713 { 0x20, "multiple='true'" },
715 { 0x22, "newcontext='false'" },
716 { 0x23, "newcontext='true'" },
718 { 0x25, "onenterbackward=" },
719 { 0x26, "onenterforward=" },
720 { 0x27, "ontimer=" },
721 { 0x28, "optional='false'" },
722 { 0x29, "optional='true'" },
726 { 0x2F, "sendreferer='false'" },
727 { 0x30, "sendreferer='true'" },
730 { 0x33, "ordered='false'" },
731 { 0x34, "ordered='true'" },
732 { 0x35, "tabindex=" },
735 { 0x38, "type='accept'" },
736 { 0x39, "type='delete'" },
737 { 0x3A, "type='help'" },
738 { 0x3B, "type='password'" },
739 { 0x3C, "type='onpick'" },
740 { 0x3D, "type='onenterbackward'" },
741 { 0x3E, "type='onenterforward'" },
742 { 0x3F, "type='ontimer'" },
743 /* 0x40 -- 0x44 GLOBAL */
744 { 0x45, "type='options'" },
745 { 0x46, "type='prev'" },
746 { 0x47, "type='reset'" },
747 { 0x48, "type='text'" },
748 { 0x49, "type='vnd.'" },
750 { 0x4B, "href='http://'" },
751 { 0x4C, "href='https://'" },
755 { 0x50, "xml:lang=" },
758 { 0x53, "columns=" },
761 { 0x56, "forua='false'" },
762 { 0x57, "forua='true'" },
763 { 0x58, "src='http://'" },
764 { 0x59, "src='https://'" },
765 { 0x5A, "http-equiv=" },
766 { 0x5B, "http-equiv='Content-Type'" },
767 { 0x5C, "content='application/vnd.wap.wmlc;charset='" },
768 { 0x5D, "http-equiv='Expires'" },
769 { 0x5E, "accesskey=" },
770 { 0x5F, "enctype=" },
771 { 0x60, "enctype='application/x-www-form-urlencoded'" },
772 { 0x61, "enctype='multipart/form-data'" },
777 /***** Attribute Value tokens *****/
778 /* Same as in WML 1.1 */
780 /***** Token code page aggregation *****/
781 static const value_valuestring wbxml_wmlc12_global[] = {
782 { 0, wbxml_wmlc10_global_cp0 }, /* Same as WML 1.0 */
786 static const value_valuestring wbxml_wmlc12_tags[] = {
787 { 0, wbxml_wmlc12_tags_cp0 },
791 static const value_valuestring wbxml_wmlc12_attrStart[] = {
792 { 0, wbxml_wmlc12_attrStart_cp0 },
796 static const value_valuestring wbxml_wmlc12_attrValue[] = {
797 { 0, wbxml_wmlc11_attrValue_cp0 }, /* Same as WML 1.1 */
807 * Wireless Markup Language
808 ***************************************/
810 /***** Global extension tokens *****/
811 /* Same as in WML 1.0 */
813 /***** Tag tokens *****/
814 /* Same as in WML 1.2 */
816 /***** Attribute Start tokens *****/
817 static const value_string wbxml_wmlc13_attrStart_cp0[] = {
818 /* 0x00 -- 0x04 GLOBAL */
819 { 0x05, "accept-charset=" },
820 { 0x06, "align='bottom'" },
821 { 0x07, "align='center'" },
822 { 0x08, "align='left'" },
823 { 0x09, "align='middle'" },
824 { 0x0A, "align='right'" },
825 { 0x0B, "align='top'" },
827 { 0x0D, "content=" },
830 { 0x10, "emptyok='false'" },
831 { 0x11, "emptyok='true'" },
839 { 0x19, "localsrc=" },
840 { 0x1A, "maxlength=" },
841 { 0x1B, "method='get'" },
842 { 0x1C, "method='post'" },
843 { 0x1D, "mode='nowrap'" },
844 { 0x1E, "mode='wrap'" },
845 { 0x1F, "multiple='false'" },
846 { 0x20, "multiple='true'" },
848 { 0x22, "newcontext='false'" },
849 { 0x23, "newcontext='true'" },
851 { 0x25, "onenterbackward=" },
852 { 0x26, "onenterforward=" },
853 { 0x27, "ontimer=" },
854 { 0x28, "optional='false'" },
855 { 0x29, "optional='true'" },
859 { 0x2F, "sendreferer='false'" },
860 { 0x30, "sendreferer='true'" },
863 { 0x33, "ordered='false'" },
864 { 0x34, "ordered='true'" },
865 { 0x35, "tabindex=" },
868 { 0x38, "type='accept'" },
869 { 0x39, "type='delete'" },
870 { 0x3A, "type='help'" },
871 { 0x3B, "type='password'" },
872 { 0x3C, "type='onpick'" },
873 { 0x3D, "type='onenterbackward'" },
874 { 0x3E, "type='onenterforward'" },
875 { 0x3F, "type='ontimer'" },
876 /* 0x40 -- 0x44 GLOBAL */
877 { 0x45, "type='options'" },
878 { 0x46, "type='prev'" },
879 { 0x47, "type='reset'" },
880 { 0x48, "type='text'" },
881 { 0x49, "type='vnd.'" },
883 { 0x4B, "href='http://'" },
884 { 0x4C, "href='https://'" },
888 { 0x50, "xml:lang=" },
891 { 0x53, "columns=" },
894 { 0x56, "forua='false'" },
895 { 0x57, "forua='true'" },
896 { 0x58, "src='http://'" },
897 { 0x59, "src='https://'" },
898 { 0x5A, "http-equiv=" },
899 { 0x5B, "http-equiv='Content-Type'" },
900 { 0x5C, "content='application/vnd.wap.wmlc;charset='" },
901 { 0x5D, "http-equiv='Expires'" },
902 { 0x5E, "accesskey=" },
903 { 0x5F, "enctype=" },
904 { 0x60, "enctype='application/x-www-form-urlencoded'" },
905 { 0x61, "enctype='multipart/form-data'" },
906 { 0x62, "xml:space='preserve'" },
907 { 0x63, "xml:space='default'" },
908 { 0x64, "cache-control='no-cache'" },
913 /***** Attribute Value tokens *****/
914 /* Same as in WML 1.1 */
916 /***** Token code page aggregation *****/
917 static const value_valuestring wbxml_wmlc13_global[] = {
918 { 0, wbxml_wmlc10_global_cp0 }, /* Same as WML 1.0 */
922 static const value_valuestring wbxml_wmlc13_tags[] = {
923 { 0, wbxml_wmlc12_tags_cp0 },
927 static const value_valuestring wbxml_wmlc13_attrStart[] = {
928 { 0, wbxml_wmlc13_attrStart_cp0 },
932 static const value_valuestring wbxml_wmlc13_attrValue[] = {
933 { 0, wbxml_wmlc11_attrValue_cp0 }, /* Same as WML 1.1 */
944 ***************************************/
946 /***** Global extension tokens *****/
948 /***** Tag tokens *****/
949 static const value_string wbxml_sic10_tags_cp0[] = {
950 /* 0x00 -- 0x04 GLOBAL */
952 { 0x06, "indication" },
959 /***** Attribute Start tokens *****/
960 static const value_string wbxml_sic10_attrStart_cp0[] = {
961 /* 0x00 -- 0x04 GLOBAL */
962 { 0x05, "action='signal-none'" },
963 { 0x06, "action='signal-low'" },
964 { 0x07, "action='signal-medium'" },
965 { 0x08, "action='signal-high'" },
966 { 0x09, "action='delete'" },
967 { 0x0a, "created=" },
969 { 0x0c, "href='http://'" },
970 { 0x0d, "href='http://www.'" },
971 { 0x0e, "href='https://'" },
972 { 0x0f, "href='https://www.'" },
973 { 0x10, "si-expires=" },
980 /***** Attribute Value tokens *****/
981 static const value_string wbxml_sic10_attrValue_cp0[] = {
982 /* 0x80 -- 0x84 GLOBAL */
991 /***** Token code page aggregation *****/
992 static const value_valuestring wbxml_sic10_tags[] = {
993 { 0, wbxml_sic10_tags_cp0 },
997 static const value_valuestring wbxml_sic10_attrStart[] = {
998 { 0, wbxml_sic10_attrStart_cp0 },
1002 static const value_valuestring wbxml_sic10_attrValue[] = {
1003 { 0, wbxml_sic10_attrValue_cp0 },
1014 ***************************************/
1016 /***** Global extension tokens *****/
1018 /***** Tag tokens *****/
1019 static const value_string wbxml_slc10_tags_cp0[] = {
1020 /* 0x00 -- 0x04 GLOBAL */
1026 /***** Attribute Start tokens *****/
1027 static const value_string wbxml_slc10_attrStart_cp0[] = {
1028 /* 0x00 -- 0x04 GLOBAL */
1029 { 0x05, "action='execute-low'" },
1030 { 0x06, "action='execute-high'" },
1031 { 0x07, "action='cache'" },
1033 { 0x09, "href='http://'" },
1034 { 0x0a, "href='http://www.'" },
1035 { 0x0b, "href='https://'" },
1036 { 0x0c, "href='https://www.'" },
1041 /***** Attribute Value tokens *****/
1042 /* Same as in SI 1.0 */
1044 /***** Token code page aggregation *****/
1045 static const value_valuestring wbxml_slc10_tags[] = {
1046 { 0, wbxml_slc10_tags_cp0 },
1050 static const value_valuestring wbxml_slc10_attrStart[] = {
1051 { 0, wbxml_slc10_attrStart_cp0 },
1055 static const value_valuestring wbxml_slc10_attrValue[] = {
1056 { 0, wbxml_sic10_attrValue_cp0 }, /* Same as SI 1.0 */
1067 ***************************************/
1069 /***** Global extension tokens *****/
1071 /***** Tag tokens *****/
1072 static const value_string wbxml_coc10_tags_cp0[] = {
1073 /* 0x00 -- 0x04 GLOBAL */
1075 { 0x06, "invalidate-object" },
1076 { 0x07, "invalidate-service" },
1081 /***** Attribute Start tokens *****/
1082 static const value_string wbxml_coc10_attrStart_cp0[] = {
1083 /* 0x00 -- 0x04 GLOBAL */
1085 { 0x06, "uri='http://'" },
1086 { 0x07, "uri='http://www.'" },
1087 { 0x08, "uri='https://'" },
1088 { 0x09, "uri='https://www.'" },
1093 /***** Attribute Value tokens *****/
1094 /* Same as in SI 1.0 */
1096 /***** Token code page aggregation *****/
1097 static const value_valuestring wbxml_coc10_tags[] = {
1098 { 0, wbxml_coc10_tags_cp0 },
1102 static const value_valuestring wbxml_coc10_attrStart[] = {
1103 { 0, wbxml_coc10_attrStart_cp0 },
1107 static const value_valuestring wbxml_coc10_attrValue[] = {
1108 { 0, wbxml_sic10_attrValue_cp0 }, /* Same as SI 1.0 */
1118 * Client Provisioning
1119 ***************************************/
1121 /***** Global extension tokens *****/
1123 /***** Tag tokens *****/
1124 static const value_string wbxml_provc10_tags_cp0[] = {
1125 /* 0x00 -- 0x04 GLOBAL */
1126 { 0x05, "wap-provisioningdoc" },
1127 { 0x06, "characteristic" },
1133 /***** Attribute Start tokens *****/
1134 static const value_string wbxml_provc10_attrStart_cp0[] = {
1135 /* 0x00 -- 0x04 GLOBAL */
1138 { 0x07, "name='NAME'" },
1139 { 0x08, "name='NAP-ADDRESS'" },
1140 { 0x09, "name='NAP-ADDRTYPE'" },
1141 { 0x0A, "name='CALLTYPE'" },
1142 { 0x0B, "name='VALIDUNTIL'" },
1143 { 0x0C, "name='AUTHTYPE'" },
1144 { 0x0D, "name='AUTHNAME'" },
1145 { 0x0E, "name='AUTHSECRET'" },
1146 { 0x0F, "name='LINGER'" },
1147 { 0x10, "name='BEARER'" },
1148 { 0x11, "name='NAPID'" },
1149 { 0x12, "name='COUNTRY'" },
1150 { 0x13, "name='NETWORK'" },
1151 { 0x14, "name='INTERNET'" },
1152 { 0x15, "name='PROXY-ID'" },
1153 { 0x16, "name='PROXY-PROVIDER-ID'" },
1154 { 0x17, "name='DOMAIN'" },
1155 { 0x18, "name='PROVURL'" },
1156 { 0x19, "name='PXAUTH-TYPE'" },
1157 { 0x1A, "name='PXAUTH-ID'" },
1158 { 0x1B, "name='PXAUTH-PW'" },
1159 { 0x1C, "name='STARTPAGE'" },
1160 { 0x1D, "name='BASAUTH-ID'" },
1161 { 0x1E, "name='BASAUTH-PW'" },
1162 { 0x1F, "name='PUSHENABLED'" },
1163 { 0x20, "name='PXADDR'" },
1164 { 0x21, "name='PXADDRTYPE'" },
1165 { 0x22, "name='TO-NAPID'" },
1166 { 0x23, "name='PORTNBR'" },
1167 { 0x24, "name='SERVICE'" },
1168 { 0x25, "name='LINKSPEED'" },
1169 { 0x26, "name='DNLINKSPEED'" },
1170 { 0x27, "name='LOCAL-ADDR'" },
1171 { 0x28, "name='LOCAL-ADDRTYPE'" },
1172 { 0x29, "name='CONTEXT-ALLOW'" },
1173 { 0x2A, "name='TRUST'" },
1174 { 0x2B, "name='MASTER'" },
1175 { 0x2C, "name='SID'" },
1176 { 0x2D, "name='SOC'" },
1177 { 0x2E, "name='WSP-VERSION'" },
1178 { 0x2F, "name='PHYSICAL-PROXY-ID'" },
1179 { 0x30, "name='CLIENT-ID'" },
1180 { 0x31, "name='DELIVERY-ERR-SDU'" },
1181 { 0x32, "name='DELIVERY-ORDER'" },
1182 { 0x33, "name='TRAFFIC-CLASS'" },
1183 { 0x34, "name='MAX-SDU-SIZE'" },
1184 { 0x35, "name='MAX-BITRATE-UPLINK'" },
1185 { 0x36, "name='MAX-BITRATE-DNLINK'" },
1186 { 0x37, "name='RESIDUAL-BER'" },
1187 { 0x38, "name='SDU-ERROR-RATIO'" },
1188 { 0x39, "name='TRAFFIC-HANDL-PRIO'" },
1189 { 0x3A, "name='TRANSFER-DELAY'" },
1190 { 0x3B, "name='GUARANTEED-BITRATE-UPLINK'" },
1191 { 0x3C, "name='GUARANTEED-BITRATE-DNLINK'" },
1193 /* 0x40 -- 0x44 GLOBAL */
1194 { 0x45, "version=" },
1195 { 0x46, "version='1.0'" },
1198 { 0x51, "type='PXLOGICAL'" },
1199 { 0x52, "type='PXPHYSICAL'" },
1200 { 0x53, "type='PORT'" },
1201 { 0x54, "type='VALIDITY'" },
1202 { 0x55, "type='NAPDEF'" },
1203 { 0x56, "type='BOOTSTRAP'" },
1204 { 0x57, "type='VENDORCONFIG'" },
1205 { 0x58, "type='CLIENTIDENTITY'" },
1206 { 0x59, "type='PXAUTHINFO'" },
1207 { 0x5A, "type='NAPAUTHINFO'" },
1212 /***** Attribute Start tokens *****/
1213 static const value_string wbxml_provc10_attrValue_cp0[] = {
1214 /* 0x80 -- 0x84 GLOBAL */
1218 { 0x88, "'ALPHA'" },
1220 { 0x8A, "'SCODE'" },
1221 { 0x8B, "'TETRA-ITSI'" },
1224 { 0x90, "'ANALOG-MODEM'" },
1225 { 0x91, "'V.120'" },
1226 { 0x92, "'V.110'" },
1228 { 0x94, "'BIT-TRANSPARENT'" },
1229 { 0x95, "'DIRECT-ASYNCHRONOUS-DATA-SERVICE'" },
1233 { 0x9C, "'HTTP-BASIC'" },
1234 { 0x9D, "'HTTP-DIGEST'" },
1235 { 0x9E, "'WTLS-SS'" },
1237 { 0xA2, "'GSM-USSD'" },
1238 { 0xA3, "'GSM-SMS'" },
1239 { 0xA4, "'ANSI-136-GUTS'" },
1240 { 0xA5, "'IS-95-CDMA-SMS'" },
1241 { 0xA6, "'IS-95-CDMA-CSD'" },
1242 { 0xA7, "'IS-95-CDMA-PACKET'" },
1243 { 0xA8, "'ANSI-136-CSD'" },
1244 { 0xA9, "'ANSI-136-GPRS'" },
1245 { 0xAA, "'GSM-CSD'" },
1246 { 0xAB, "'GSM-GPRS'" },
1247 { 0xAC, "'AMPS-CDPD'" },
1248 { 0xAD, "'PDC-CSD'" },
1249 { 0xAE, "'PDC-PACKET'" },
1250 { 0xAF, "'IDEN-SMS'" },
1251 { 0xB0, "'IDEN-CSD'" },
1252 { 0xB1, "'IDEN-PACKET'" },
1253 { 0xB2, "'FLEX/REFLEX'" },
1254 { 0xB3, "'PHS-SMS'" },
1255 { 0xB4, "'PHS-CSD'" },
1256 { 0xB5, "'TETRA-SDS'" },
1257 { 0xB6, "'TETRA-PACKET'" },
1258 { 0xB7, "'ANSI-136-GHOST'" },
1259 { 0xB8, "'MOBITEX-MPAK'" },
1261 /* 0xC0 -- 0xC4 GLOBAL */
1262 { 0xC5, "'AUTOBAUDING'" },
1264 { 0xCA, "'CL-WSP'" },
1265 { 0xCB, "'CO-WSP'" },
1266 { 0xCC, "'CL-SEC-WSP'" },
1267 { 0xCD, "'CO-SEC-WSP'" },
1268 { 0xCE, "'CL-SEC-WTA'" },
1269 { 0xCF, "'CO-SEC-WTA'" },
1274 /***** Token code page aggregation *****/
1275 static const value_valuestring wbxml_provc10_tags[] = {
1276 { 0, wbxml_provc10_tags_cp0 },
1280 static const value_valuestring wbxml_provc10_attrStart[] = {
1281 { 0, wbxml_provc10_attrStart_cp0 },
1285 static const value_valuestring wbxml_provc10_attrValue[] = {
1286 { 0, wbxml_provc10_attrValue_cp0 },
1296 * Email Notification
1297 ***************************************/
1299 /***** Global extension tokens *****/
1301 /***** Tag tokens *****/
1302 static const value_string wbxml_emnc10_tags_cp0[] = {
1303 /* 0x00 -- 0x04 GLOBAL */
1309 /***** Attribute Start tokens *****/
1310 static const value_string wbxml_emnc10_attrStart_cp0[] = {
1311 /* 0x00 -- 0x04 GLOBAL */
1312 { 0x05, "timestamp=" },
1313 { 0x06, "mailbox=" },
1314 { 0x07, "mailbox='mailat:'" },
1315 { 0x08, "mailbox='pop://'" },
1316 { 0x09, "mailbox='imap://'" },
1317 { 0x0a, "mailbox='http://'" },
1318 { 0x0b, "mailbox='http://www.'" },
1319 { 0x0c, "mailbox='https://'" },
1320 { 0x0D, "mailbox='https://www.'" },
1325 /***** Attribute Value tokens *****/
1326 /* Same as in SI 1.0 */
1328 /***** Token code page aggregation *****/
1329 static const value_valuestring wbxml_emnc10_tags[] = {
1330 { 0, wbxml_emnc10_tags_cp0 },
1334 static const value_valuestring wbxml_emnc10_attrStart[] = {
1335 { 0, wbxml_emnc10_attrStart_cp0 },
1339 static const value_valuestring wbxml_emnc10_attrValue[] = {
1340 { 0, wbxml_sic10_attrValue_cp0 }, /* Same as SI 1.0 */
1350 * SyncML Representation Protocol
1351 ***************************************/
1353 /***** Global extension tokens *****/
1355 /***** Tag tokens *****/
1356 static const value_string wbxml_syncmlc10_tags_cp0[] = { /* SyncML 1.0 */
1357 /* 0x00 -- 0x04 GLOBAL */
1360 { 0x07, "Archive" },
1375 { 0x16, "LocName" },
1378 { 0x19, "MapItem" },
1383 { 0x1E, "NoResults" },
1385 { 0x20, "Replace" },
1386 { 0x21, "RespURI" },
1387 { 0x22, "Results" },
1389 { 0x24, "Sequence" },
1390 { 0x25, "SessionID" },
1393 { 0x28, "SourceRef" },
1396 { 0x2B, "SyncBody" },
1397 { 0x2C, "SyncHdr" },
1400 { 0x2F, "TargetRef" },
1401 /* 0x30 - Reserved */
1403 { 0x32, "VerProto" },
1408 static const value_string wbxml_syncmlc10_tags_cp1[] = { /* MetInf 1.0 */
1409 /* 0x00 -- 0x04 GLOBAL */
1414 { 0x09, "FreeMem" },
1417 { 0x0C, "MaxMsgSize" },
1421 { 0x10, "NextNonce" },
1422 { 0x11, "SharedMem" },
1425 { 0x14, "Version" },
1430 /***** Attribute Start tokens *****/
1432 /***** Attribute Value tokens *****/
1434 /***** Token code page aggregation *****/
1435 static const value_valuestring wbxml_syncmlc10_tags[] = {
1436 { 0, wbxml_syncmlc10_tags_cp0 }, /* -//SYNCML//DTD SyncML 1.0//EN */
1437 { 0, wbxml_syncmlc10_tags_cp1 }, /* -//SYNCML//DTD MetInf 1.0//EN */
1447 * SyncML Representation Protocol
1448 ***************************************/
1450 /***** Global extension tokens *****/
1452 /***** Tag tokens *****/
1453 static const value_string wbxml_syncmlc11_tags_cp0[] = { /* SyncML 1.1 */
1454 /* 0x00 -- 0x04 GLOBAL */
1457 { 0x07, "Archive" },
1472 { 0x16, "LocName" },
1475 { 0x19, "MapItem" },
1480 { 0x1e, "NoResults" },
1482 { 0x20, "Replace" },
1483 { 0x21, "RespURI" },
1484 { 0x22, "Results" },
1486 { 0x24, "Sequence" },
1487 { 0x25, "SessionID" },
1490 { 0x28, "SourceRef" },
1493 { 0x2b, "SyncBody" },
1494 { 0x2c, "SyncHdr" },
1497 { 0x2f, "TargetRef" },
1498 /* 0x30 - Reserved */
1500 { 0x32, "VerProto" },
1501 { 0x33, "NumberOfChanges" },
1502 { 0x34, "MoreData" },
1507 static const value_string wbxml_syncmlc11_tags_cp1[] = { /* MetInf 1.1 */
1508 /* 0x00 -- 0x04 GLOBAL */
1513 { 0x09, "FreeMem" },
1516 { 0x0C, "MaxMsgSize" },
1520 { 0x10, "NextNonce" },
1521 { 0x11, "SharedMem" },
1524 { 0x14, "Version" },
1525 { 0x15, "MaxObjSize" },
1530 /***** Attribute Start tokens *****/
1532 /***** Attribute Value tokens *****/
1534 /***** Token code page aggregation *****/
1535 static const value_valuestring wbxml_syncmlc11_tags[] = {
1536 { 0, wbxml_syncmlc11_tags_cp0 }, /* -//SYNCML//DTD SyncML 1.1//EN */
1537 { 0, wbxml_syncmlc11_tags_cp1 }, /* -//SYNCML//DTD MetInf 1.1//EN */
1548 ***************************************/
1550 /***** Global extension tokens *****/
1552 /***** Tag tokens *****/
1553 static const value_string wbxml_channelc10_tags_cp0[] = {
1554 /* 0x00 -- 0x04 GLOBAL */
1555 { 0x05, "channel" },
1557 { 0x07, "abstract" },
1558 { 0x08, "resource" },
1563 /***** Attribute Start tokens *****/
1564 static const value_string wbxml_channelc10_attrStart_cp0[] = {
1565 /* 0x00 -- 0x04 GLOBAL */
1566 { 0x05, "maxspace" },
1569 { 0x08, "href='http://'" },
1570 { 0x09, "href='https://'" },
1571 { 0x0A, "lastmod" },
1574 { 0x0D, "success" },
1575 { 0x0E, "success='http://'" },
1576 { 0x0F, "success='https://'" },
1577 { 0x10, "failure" },
1578 { 0x11, "failure='http://'" },
1579 { 0x12, "failure='https://'" },
1580 { 0x13, "EventId" },
1585 /***** Attribute Value tokens *****/
1587 /***** Token code page aggregation *****/
1588 static const value_valuestring wbxml_channelc10_tags[] = {
1589 { 0, wbxml_channelc10_tags_cp0 },
1593 static const value_valuestring wbxml_channelc10_attrStart[] = {
1594 { 0, wbxml_channelc10_attrStart_cp0 },
1602 /********************** WBXML token mapping aggregation **********************/
1605 /* The following structure links content types to their token mapping and
1606 * contains arrays of pointers to value_string arrays (one per code page).
1608 typedef struct _wbxml_token_map {
1609 const guint32 publicid; /* WBXML DTD number - see WINA */
1610 const guint8 defined; /* Are there mapping tables defined */
1611 const value_valuestring *global; /* Global token map */
1612 const value_valuestring *tags; /* Tag token map */
1613 const value_valuestring *attrStart; /* Attribute Start token map */
1614 const value_valuestring *attrValue; /* Attribute Value token map */
1617 static const wbxml_token_map *wbxml_content_map (guint32 publicid);
1620 ** Aggregation of content type and aggregated code pages
1621 ** Content type map lookup will stop at the 1st entry with 2nd member = FALSE
1623 static const wbxml_token_map map[] = {
1624 #ifdef Test_the_WBXML_parser_without_token_mappings
1625 { 0, FALSE, NULL, NULL, NULL, NULL },
1627 { 0x02, TRUE, /* WML 1.0 */
1628 wbxml_wmlc10_global,
1630 wbxml_wmlc10_attrStart,
1631 wbxml_wmlc10_attrValue
1633 #ifdef remove_directive_and_set_TRUE_if_mapping_available
1634 { 0x03, FALSE, /* WTA 1.0 (deprecated) */
1635 NULL, NULL, NULL, NULL
1638 { 0x04, TRUE, /* WML 1.1 */
1639 wbxml_wmlc11_global,
1641 wbxml_wmlc11_attrStart,
1642 wbxml_wmlc11_attrValue
1644 { 0x05, TRUE, /* SI 1.0 */
1645 NULL, /* wbxml_sic10_global - does not exist */
1647 wbxml_sic10_attrStart,
1648 wbxml_sic10_attrValue
1650 { 0x06, TRUE, /* SL 1.0 */
1651 NULL, /* wbxml_slc10_global - does not exist */
1653 wbxml_slc10_attrStart,
1654 wbxml_slc10_attrValue
1656 { 0x07, TRUE, /* CO 1.0 */
1657 NULL, /* wbxml_coc10_global - does not exist */
1659 wbxml_coc10_attrStart,
1660 wbxml_coc10_attrValue
1662 { 0x08, TRUE, /* CHANNEL 1.0 (deprecated) */
1663 NULL, /* wbxml_channelc10_global - does not exist */
1664 wbxml_channelc10_tags,
1665 wbxml_channelc10_attrStart,
1666 NULL, /* wbxml_channelc10_attrValue - does not exist */
1668 { 0x09, TRUE, /* WML 1.2 */
1669 wbxml_wmlc12_global,
1671 wbxml_wmlc12_attrStart,
1672 wbxml_wmlc12_attrValue
1674 { 0x0A, TRUE, /* WML 1.3 */
1675 wbxml_wmlc13_global,
1677 wbxml_wmlc13_attrStart,
1678 wbxml_wmlc13_attrValue
1680 { 0x0B, TRUE, /* PROV 1.0 */
1681 NULL, /* wbxml_provc10_global - does not exist */
1683 wbxml_provc10_attrStart,
1684 wbxml_provc10_attrValue
1686 #ifdef remove_directive_and_set_TRUE_if_mapping_available
1687 { 0x0C, FALSE, /* WTA-WML 1.2 */
1688 NULL, NULL, NULL, NULL
1691 { 0x0D, TRUE, /* EMN 1.0 */
1692 NULL, /* wbxml_emnc10_global - does not exist */
1694 wbxml_emnc10_attrStart,
1695 wbxml_emnc10_attrValue
1697 #ifdef remove_directive_and_set_TRUE_if_mapping_available
1698 { 0x0E, FALSE, /* DRMREL 1.0 */
1699 NULL, NULL, NULL, NULL
1702 { 0x0FD1, TRUE, /* SyncML 1.0 */
1703 NULL, /* wbxml_syncmlc10_global - does not exist */
1704 wbxml_syncmlc10_tags,
1705 NULL, /* wbxml_syncmlc10_attrStart - does not exist */
1706 NULL, /* wbxml_syncmlc10_attrValue - does not exist */
1708 { 0x0FD3, TRUE, /* SyncML 1.1 */
1709 NULL, /* wbxml_syncmlc11_global - does not exist */
1710 wbxml_syncmlc11_tags,
1711 NULL, /* wbxml_syncmlc11_attrStart - does not exist */
1712 NULL, /* wbxml_syncmlc11_attrValue - does not exist */
1714 { 0x1108, TRUE, /* Phone.com - WML+ 1.1 */
1715 /* Note: I assumed WML+ 1.1 would be not that different from WML 1.1,
1716 * the real mapping should come from Phone.com (OpenWave)! */
1717 wbxml_wmlc11_global, /* Not 100% true */
1718 wbxml_wmlc11_tags, /* Not 100% true */
1719 wbxml_wmlc11_attrStart, /* Not 100% true */
1720 wbxml_wmlc11_attrValue /* Not 100% true */
1722 { 0x110D, TRUE, /* Phone.com - WML+ 1.3 */
1723 /* Note: I assumed WML+ 1.3 would be not that different from WML 1.3,
1724 * the real mapping should come from Phone.com (OpenWave)! */
1725 wbxml_wmlc13_global, /* Not 100% true */
1726 wbxml_wmlc13_tags, /* Not 100% true */
1727 wbxml_wmlc13_attrStart, /* Not 100% true */
1728 wbxml_wmlc13_attrValue /* Not 100% true */
1731 { 0, FALSE, NULL, NULL, NULL, NULL }
1735 /* WBXML content token mapping depends on the following parameters:
1736 * - Content type (guint32)
1737 * - Token type (global, tags, attrStart, attrValue)
1738 * - Code page for tag and attribute
1740 * This results in the following steps:
1741 * 1. Retrieve content type mapping
1742 * 2. If exists, retrieve token type mapping
1743 * 3. If exists, retrieve required code page
1744 * 4. If exists, retrieve token mapping
1747 /* Return token mapping for a given content mapping entry. */
1749 map_token (const value_valuestring *token_map, guint8 codepage, guint8 token) {
1750 const value_string *vs;
1753 if (token_map) { /* Found map */
1754 if ((vs = val_to_valstr (codepage, token_map))) {
1755 /* Found codepage map */
1756 s = match_strval (token, vs);
1757 if (s) /* Found valid token */
1759 /* No valid token mapping in specified code page of token map */
1760 return "(Requested token not defined for this content type)";
1762 /* There is no token map entry for the requested code page */
1763 return "(Requested token code page not defined for this content type)";
1765 /* The token map does not exist */
1766 return "(Requested token map not defined for this content type)";
1770 /* Returns a pointer to the WBXML token map for the given WBXML public
1771 * identifier value (see WINA for a table with defined identifiers). */
1772 static const wbxml_token_map *wbxml_content_map (guint32 publicid) {
1775 while (map[i].defined) {
1776 if (map[i].publicid == publicid)
1784 /************************** Function prototypes **************************/
1788 dissect_wbxml(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
1791 proto_register_wbxml(void);
1793 /* Parse and display the WBXML string table */
1795 show_wbxml_string_table (proto_tree *tree, tvbuff_t *tvb, guint32 str_tbl,
1796 guint32 str_tbl_len);
1798 /* Parse data while in STAG state */
1800 parse_wbxml_tag (proto_tree *tree, tvbuff_t *tvb, guint32 offset,
1801 guint32 str_tbl, guint8 *level,
1802 guint32 *parsed_length);
1804 /* Parse data while in STAG state;
1805 * interpret tokens as defined by content type */
1807 parse_wbxml_tag_defined (proto_tree *tree, tvbuff_t *tvb, guint32 offset,
1808 guint32 str_tbl, guint8 *level,
1809 guint32 *parsed_length,
1810 const wbxml_token_map *map);
1812 /* Parse data while in ATTR state */
1814 parse_wbxml_attribute_list (proto_tree *tree, tvbuff_t *tvb,
1815 guint32 offset, guint32 str_tbl, guint8 level,
1816 guint32 *parsed_length);
1818 /* Parse data while in ATTR state;
1819 * interpret tokens as defined by content type */
1821 parse_wbxml_attribute_list_defined (proto_tree *tree, tvbuff_t *tvb,
1822 guint32 offset, guint32 str_tbl, guint8 level,
1823 guint32 *parsed_length,
1824 const wbxml_token_map *map);
1827 /****************** WBXML protocol dissection functions ******************/
1830 /* Code to actually dissect the packets */
1832 dissect_wbxml(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1834 /* Set up structures needed to add the protocol subtree and manage it */
1836 proto_tree *wbxml_tree; /* Main WBXML tree */
1837 proto_tree *wbxml_str_tbl_tree; /* String table subtree */
1838 proto_tree *wbxml_content_tree; /* Content subtree */
1843 guint32 charset_len;
1845 guint32 publicid_index = 0;
1846 guint32 publicid_len;
1848 guint32 str_tbl_len;
1849 guint8 level = 0; /* WBXML recursion level */
1850 const wbxml_token_map *content_map = NULL;
1854 * Version 1.0: version publicid strtbl BODY
1855 * Version 1.x: version publicid charset strtbl BODY
1857 * Last valid format: WBXML 1.3
1859 switch ( version = tvb_get_guint8 (tvb, 0) ) {
1860 case 0x00: /* WBXML/1.0 */
1863 case 0x01: /* WBXML/1.1 */
1864 case 0x02: /* WBXML/1.2 */
1865 case 0x03: /* WBXML/1.3 */
1872 if (check_col(pinfo->cinfo, COL_INFO))
1873 col_append_fstr(pinfo->cinfo, COL_INFO, " (WBXML %s:",
1874 match_strval (version, vals_wbxml_versions));
1876 /* In the interest of speed, if "tree" is NULL, don't do any work not
1877 necessary to generate protocol tree items. */
1879 /* create display subtree for the protocol */
1880 ti = proto_tree_add_item (tree, proto_wbxml, tvb, 0, -1, FALSE);
1881 wbxml_tree = proto_item_add_subtree(ti, ett_wbxml);
1884 proto_tree_add_uint (wbxml_tree, hf_wbxml_version,
1885 tvb, 0, 1, version);
1888 publicid = tvb_get_guintvar(tvb, 1, &publicid_len);
1889 if (publicid) { /* Known Public ID */
1890 if (check_col(pinfo->cinfo, COL_INFO))
1891 col_append_fstr(pinfo->cinfo, COL_INFO, " Public ID \"%s\")",
1892 match_strval (publicid, vals_wbxml_public_ids));
1893 proto_tree_add_uint(wbxml_tree, hf_wbxml_public_id_known,
1894 tvb, 1, publicid_len, publicid);
1895 } else { /* Public identifier in string table */
1896 publicid_index = tvb_get_guintvar (tvb, 1+publicid_len, &len);
1897 publicid_len += len;
1899 offset = 1 + publicid_len;
1901 /* Version-specific handling of Charset */
1902 switch ( version ) {
1903 case 0x00: /* WBXML/1.0 */
1907 case 0x01: /* WBXML/1.1 */
1908 case 0x02: /* WBXML/1.2 */
1909 case 0x03: /* WBXML/1.3 */
1911 charset = tvb_get_guintvar (tvb, offset, &charset_len);
1912 offset += charset_len;
1915 default: /* Impossible since return already earlier */
1919 /* String table: read string table length in bytes */
1920 str_tbl_len = tvb_get_guintvar (tvb, offset, &len);
1921 str_tbl = offset + len; /* Start of 1st string in string table */
1923 /* Now we can add public ID, charset (if available),
1924 * and string table */
1925 if ( ! publicid ) { /* Read Public ID from string table */
1926 len = tvb_strsize (tvb, str_tbl+publicid_index);
1927 if (check_col(pinfo->cinfo, COL_INFO))
1928 col_append_fstr(pinfo->cinfo, COL_INFO, " Public ID \"%s\")",
1929 tvb_format_text (tvb,
1930 str_tbl+publicid_index,
1932 proto_tree_add_item (wbxml_tree, hf_wbxml_public_id_literal,
1933 tvb, 1, publicid_len, FALSE);
1935 if ( version ) { /* Charset */
1936 proto_tree_add_uint (wbxml_tree, hf_wbxml_charset,
1937 tvb, 1+publicid_len, charset_len, charset);
1940 ti = proto_tree_add_text(wbxml_tree,
1941 tvb, offset, len + str_tbl_len, "String table: %u bytes",
1944 if (wbxml_tree && str_tbl_len) { /* Display string table as subtree */
1945 wbxml_str_tbl_tree = proto_item_add_subtree (ti,
1947 show_wbxml_string_table (wbxml_str_tbl_tree, tvb,
1948 str_tbl, str_tbl_len);
1951 /* Data starts HERE */
1952 offset += len + str_tbl_len;
1954 /* The WBXML BODY starts here */
1955 ti = proto_tree_add_text (wbxml_tree, tvb, offset, -1,
1956 "Data representation");
1957 wbxml_content_tree = proto_item_add_subtree (ti, ett_wbxml_content);
1959 /* The parse_wbxml_X() functions will process the content correctly,
1960 * irrespective of the WBXML version used. For the WBXML body, this
1961 * means that there is a different processing for the global token
1962 * RESERVED_2 (WBXML 1.0) or OPAQUE (WBXML 1.x with x > 0). */
1963 if (wbxml_tree) { /* Show only if visible */
1965 /* Retrieve the content token mapping if available */
1966 content_map = wbxml_content_map (publicid);
1968 /* Is there a defined token mapping for publicid? */
1969 if (content_map->defined) {
1970 proto_tree_add_text (wbxml_content_tree, tvb,
1972 "Level | State | Codepage "
1973 "| WBXML Token Description "
1975 parse_wbxml_tag_defined (wbxml_content_tree,
1976 tvb, offset, str_tbl, &level,
1981 proto_tree_add_text (wbxml_content_tree, tvb,
1983 "[Rendering of this content type"
1984 " not (yet) supported]");
1986 /* Default: WBXML only, no interpretation of the content */
1987 proto_tree_add_text (wbxml_content_tree, tvb, offset, -1,
1988 "Level | State | Codepage "
1989 "| WBXML Token Description "
1991 parse_wbxml_tag (wbxml_content_tree, tvb, offset,
1992 str_tbl, &level, &len);
2000 /* Parse and display the WBXML string table (in a 3-column table format).
2001 * This function displays:
2002 * - the offset in the string table,
2003 * - the length of the string
2007 show_wbxml_string_table (proto_tree *tree, tvbuff_t *tvb, guint32 str_tbl,
2008 guint32 str_tbl_len)
2010 guint32 off = str_tbl;
2012 guint32 end = str_tbl + str_tbl_len;
2014 proto_tree_add_text (tree, tvb, off, end,
2015 "Start | Length | String");
2017 len = tvb_strsize (tvb, off);
2018 proto_tree_add_text (tree, tvb, off, len,
2021 tvb_format_text (tvb, off, len-1));
2027 /* Indentation code is based on a static const array of space characters.
2028 * At least one single space is returned */
2029 static const char indent_buffer[514] = " "
2038 ; /* Generate XML indentation (length = 1 + 2 * 256 + 1 for '\0') */
2040 static const char * Indent (guint8 level) {
2041 return indent_buffer + (512 - 2 * (level));
2045 /********************
2046 * WBXML tag tokens *
2047 ********************
2049 * Bit Mask : Example
2050 * -------------------
2051 * 00.. .... : <tag />
2058 * atrtribute1="value1"
2059 * atrtribute2="value2"
2063 * atrtribute1="value1"
2064 * atrtribute2="value2"
2070 * - An XML PI is parsed as an attribute list (same syntax).
2071 * - A code page switch only applies to the single token that follows.
2075 /* This function parses the WBXML and maps known token interpretations
2076 * to the WBXML tokens. As a result, the original XML document can be
2077 * recreated. Indentation is generated in order to ease reading.
2079 * Attribute parsing is done in parse_wbxml_attribute_list_defined().
2081 * The wbxml_token_map entry *map contains the actual token mapping.
2083 * NOTE: In order to parse the content, some recursion is required.
2084 * However, for performance reasons, recursion has been avoided
2085 * where possible (tags without content within tags with content).
2086 * This is achieved by means of the parsing_tag_content and tag_save*
2089 * NOTE: See above for known token mappings.
2091 * NOTE: As tags can be opened and closed, a tag representation lookup
2092 * may happen once or twice for a given tag. For efficiency reasons,
2093 * the literal tag value is stored and used throughout the code.
2094 * With the introduction of code page support, this solution is robust
2095 * as the lookup only occurs once, removing the need for storage of
2096 * the used code page.
2099 parse_wbxml_tag_defined (proto_tree *tree, tvbuff_t *tvb, guint32 offset,
2100 guint32 str_tbl, guint8 *level,
2101 guint32 *parsed_length,
2102 const wbxml_token_map *map)
2104 guint32 tvb_len = tvb_reported_length (tvb);
2105 guint32 off = offset;
2111 guint32 tag_len; /* Length of the index (uintvar) from a LITERAL tag */
2112 guint8 tag_save_known = 0; /* Will contain peek & 0x3F (tag identity) */
2113 guint8 tag_new_known = 0; /* Will contain peek & 0x3F (tag identity) */
2114 const char *tag_save_literal; /* Will contain the LITERAL tag identity */
2115 const char *tag_new_literal; /* Will contain the LITERAL tag identity */
2116 guint8 codepage_stag = 0; /* Initial codepage in state = STAG */
2117 guint8 parsing_tag_content = FALSE; /* Are we parsing content from a
2118 tag with content: <x>Content</x>
2120 The initial state is FALSE.
2121 This state will trigger recursion. */
2122 tag_save_literal = NULL; /* Prevents compiler warning */
2125 printf ("WBXML - parse_wbxml_tag_defined (level = %d, offset = %d)\n",
2128 while (off < tvb_len) {
2129 peek = tvb_get_guint8 (tvb, off);
2131 printf("WBXML - STAG: level = %3d, peek = 0x%02X, off = %d, "
2133 *level, peek, off, tvb_len);
2135 if ((peek & 0x3F) < 4) switch (peek) { /* Global tokens in state = STAG
2136 but not the LITERAL tokens */
2137 case 0x00: /* SWITCH_PAGE */
2138 codepage_stag = tvb_get_guint8 (tvb, off+1);
2139 proto_tree_add_text (tree, tvb, off, 2,
2140 " | Tag | T 0->%3d "
2141 "| SWITCH_PAGE (Tag code page) "
2146 case 0x01: /* END: only possible for Tag with Content */
2147 if (tag_save_known) { /* Known TAG */
2148 proto_tree_add_text (tree, tvb, off, 1,
2150 "| END (Known Tag 0x%02X) "
2152 *level, tag_save_known, Indent (*level),
2153 tag_save_literal); /* We already looked it up! */
2154 } else { /* Literal TAG */
2155 proto_tree_add_text (tree, tvb, off, 1,
2157 "| END (Literal Tag) "
2159 *level, Indent (*level),
2164 *parsed_length = off - offset;
2165 /* Reset code page: not needed as return from recursion */
2167 printf("WBXML - STAG: level = %u, Return: len = %u\n", *level, *parsed_length);
2171 case 0x02: /* ENTITY */
2172 ent = tvb_get_guintvar (tvb, off+1, &len);
2173 proto_tree_add_text (tree, tvb, off, 1+len,
2177 *level, Indent (*level), ent);
2180 case 0x03: /* STR_I */
2181 len = tvb_strsize (tvb, off+1);
2182 proto_tree_add_text (tree, tvb, off, 1+len,
2184 "| STR_I (Inline string) "
2186 *level, Indent(*level),
2187 tvb_format_text (tvb, off+1, len-1));
2190 case 0x40: /* EXT_I_0 */
2191 case 0x41: /* EXT_I_1 */
2192 case 0x42: /* EXT_I_2 */
2193 /* Extension tokens */
2194 len = tvb_strsize (tvb, off+1);
2195 if (codepage_stag) { /* Not default code page */
2196 proto_tree_add_text (tree, tvb, off, 1+len,
2197 " %3d | Tag | T %3d->0 "
2198 "| EXT_I_%1x (Extension Token) "
2200 *level, codepage_stag, peek & 0x0f, Indent (*level),
2201 map_token (map->global, codepage_stag, peek),
2202 tvb_format_text (tvb, off+1, len-1));
2203 /* Reset code page */
2205 } else { /* Code page 0 */
2206 proto_tree_add_text (tree, tvb, off, 1+len,
2208 "| EXT_I_%1x (Extension Token) "
2210 *level, peek & 0x0f, Indent (*level),
2211 map_token (map->global, codepage_stag, peek),
2212 tvb_format_text (tvb, off+1, len-1));
2217 proto_tree_add_text (tree, tvb, off, 1,
2219 "| PI (XML Processing Instruction) "
2221 *level, Indent (*level));
2222 parse_wbxml_attribute_list_defined (tree, tvb, off, str_tbl,
2224 /* Check that there is still room in packet */
2226 if (off >= tvb_len) {
2227 proto_tree_add_text (tree, tvb, off, 1,
2232 printf("WBXML - STAG: level = %u, Return: len = %u (short frame)\n",
2233 *level, *parsed_length);
2237 proto_tree_add_text (tree, tvb, off-1, 1,
2241 *level, Indent (*level));
2243 case 0x80: /* EXT_T_0 */
2244 case 0x81: /* EXT_T_1 */
2245 case 0x82: /* EXT_T_2 */
2246 /* Extension tokens */
2247 index = tvb_get_guintvar (tvb, off+1, &len);
2248 str_len = tvb_strsize (tvb, str_tbl+index);
2249 if (codepage_stag) { /* Not default code page */
2250 proto_tree_add_text (tree, tvb, off, 1+len,
2251 " %3d | Tag | T %3d->0 "
2252 "| EXT_T_%1x (Extension Token) "
2254 *level, codepage_stag, peek & 0x0f, Indent (*level),
2255 map_token (map->global, codepage_stag, peek),
2256 tvb_format_text (tvb, str_tbl+index, str_len-1));
2257 /* Reset code page */
2259 } else { /* Code page 0 */
2260 proto_tree_add_text (tree, tvb, off, 1+len,
2262 "| EXT_T_%1x (Extension Token) "
2264 *level, peek & 0x0f, Indent (*level),
2265 map_token (map->global, codepage_stag, peek),
2266 tvb_format_text (tvb, str_tbl+index, str_len-1));
2270 case 0x83: /* STR_T */
2271 index = tvb_get_guintvar (tvb, off+1, &len);
2272 str_len = tvb_strsize (tvb, str_tbl+index);
2273 proto_tree_add_text (tree, tvb, off, 1+len,
2275 "| STR_T (Tableref string) "
2277 *level, Indent (*level),
2278 tvb_format_text (tvb, str_tbl+index, str_len-1));
2281 case 0xC0: /* EXT_0 */
2282 case 0xC1: /* EXT_1 */
2283 case 0xC2: /* EXT_2 */
2284 /* Extension tokens */
2285 if (codepage_stag) { /* Not default code page */
2286 proto_tree_add_text (tree, tvb, off, 1,
2287 " %3d | Tag | T %3d->0 "
2288 "| EXT_%1x (Extension Token) "
2290 *level, codepage_stag, peek & 0x0f, Indent (*level),
2291 map_token (map->global, codepage_stag, peek));
2292 /* Reset code page */
2294 } else { /* Code page 0 */
2295 proto_tree_add_text (tree, tvb, off, 1,
2297 "| EXT_%1x (Extension Token) "
2299 *level, peek & 0x0f, Indent (*level),
2300 map_token (map->global, codepage_stag, peek));
2304 case 0xC3: /* OPAQUE - WBXML 1.1 and newer */
2305 if (tvb_get_guint8 (tvb, 0)) { /* WBXML 1.x (x > 0) */
2306 index = tvb_get_guintvar (tvb, off+1, &len);
2307 proto_tree_add_text (tree, tvb, off, 1 + len + index,
2309 "| OPAQUE (Opaque data) "
2310 "| %s(%d bytes of opaque data)",
2311 *level, Indent (*level), index);
2313 } else { /* WBXML 1.0 - RESERVED_2 token (invalid) */
2314 proto_tree_add_text (tree, tvb, off, 1,
2316 "| RESERVED_2 (Invalid Token!) "
2317 "| WBXML 1.0 parsing stops here.",
2319 /* Stop processing as it is impossible to parse now */
2321 *parsed_length = off - offset;
2323 printf("WBXML - STAG: level = %u, Return: len = %u\n", *level, *parsed_length);
2329 /* No default clause, as all cases have been treated */
2330 } else { /* LITERAL or Known TAG */
2331 /* We must store the initial tag, and also retrieve the new tag.
2332 * For efficiency reasons, we store the literal tag representation
2333 * for known tags too, so we can easily close the tag without the
2334 * need of a new lookup and avoiding storage of token codepage.
2336 * There are 4 possibilities:
2338 * 1. Known tag followed by a known tag
2339 * 2. Known tag followed by a LITERAL tag
2340 * 3. LITERAL tag followed by Known tag
2341 * 4. LITERAL tag followed by LITERAL tag
2344 /* Store the new tag */
2346 if ((peek & 0x3F) == 4) { /* LITERAL */
2347 index = tvb_get_guintvar (tvb, off+1, &tag_len);
2348 str_len = tvb_strsize (tvb, str_tbl+index);
2349 tag_new_literal = tvb_get_ptr (tvb, str_tbl+index, str_len);
2350 tag_new_known = 0; /* invalidate known tag_new */
2351 } else { /* Known tag */
2352 tag_new_known = peek & 0x3F;
2353 tag_new_literal = map_token (map->tags, codepage_stag,
2355 /* Stored looked up tag name string */
2358 /* Parsing of TAG starts HERE */
2359 if (peek & 0x40) { /* Content present */
2361 * [!] An explicit END token is expected in these cases!
2362 * ==> Recursion possible if we encounter a tag with content;
2363 * recursion will return at the explicit END token.
2365 if (parsing_tag_content) { /* Recurse */
2367 printf ("WBXML - STAG: Tag in Tag - RECURSE! (off = %d)\n", off);
2369 /* Do not process the attribute list:
2370 * recursion will take care of it */
2372 parse_wbxml_tag_defined (tree, tvb, off, str_tbl, level,
2375 } else { /* Now we will have content to parse */
2376 /* Save the start tag so we can properly close it later. */
2377 if ((peek & 0x3F) == 4) { /* Literal tag */
2378 tag_save_literal = tag_new_literal;
2380 } else { /* Known tag */
2381 tag_save_known = tag_new_known;
2382 tag_save_literal = tag_new_literal;
2383 /* The last statement avoids needless lookups */
2385 /* Process the attribute list if present */
2386 if (peek & 0x80) { /* Content and Attribute list present */
2387 if (tag_new_known) { /* Known tag */
2388 if (codepage_stag) { /* Not default code page */
2389 proto_tree_add_text (tree, tvb, off, 1,
2390 " %3d | Tag | T %3d->0 "
2391 "| Known Tag 0x%02X (AC) "
2393 *level, codepage_stag, tag_new_known,
2394 Indent (*level), tag_new_literal);
2395 /* Tag string already looked up earlier! */
2396 /* Reset code page */
2398 } else { /* Code page 0 */
2399 proto_tree_add_text (tree, tvb, off, 1,
2401 "| Known Tag 0x%02X (AC) "
2403 *level, tag_new_known,
2404 Indent (*level), tag_new_literal);
2405 /* Tag string already looked up earlier! */
2408 } else { /* LITERAL tag */
2409 proto_tree_add_text (tree, tvb, off, 1,
2411 "| LITERAL_AC (Literal tag) (AC) "
2413 *level, Indent (*level), tag_new_literal);
2416 parse_wbxml_attribute_list_defined (tree, tvb,
2417 off, str_tbl, *level, &len, map);
2418 /* Check that there is still room in packet */
2420 if (off >= tvb_len) {
2421 proto_tree_add_text (tree, tvb, off, 1,
2426 printf("WBXML - STAG: level = %u, Return: len = %u (short frame)\n",
2427 *level, *parsed_length);
2431 proto_tree_add_text (tree, tvb, off-1, 1,
2433 "| END (attribute list) "
2435 *level, Indent (*level));
2436 } else { /* Content, no Attribute list */
2437 if (tag_new_known) { /* Known tag */
2438 if (codepage_stag) { /* Not default code page */
2439 proto_tree_add_text (tree, tvb, off, 1,
2440 " %3d | Tag | T %3d->0 "
2441 "| Known Tag 0x%02X (.C) "
2443 *level, codepage_stag, tag_new_known,
2446 /* Tag string already looked up earlier! */
2447 /* Reset code page */
2449 } else { /* Code page 0 */
2450 proto_tree_add_text (tree, tvb, off, 1,
2452 "| Known Tag 0x%02X (.C) "
2454 *level, tag_new_known,
2457 /* Tag string already looked up earlier! */
2460 } else { /* LITERAL tag */
2461 proto_tree_add_text (tree, tvb, off, 1,
2463 "| LITERAL_C (Literal Tag) (.C) "
2465 *level, Indent (*level), tag_new_literal);
2469 /* The data that follows in the parsing process
2470 * represents content for the opening tag
2471 * we've just processed in the lines above.
2472 * Next time we encounter a tag with content: recurse
2474 parsing_tag_content = TRUE;
2476 printf ("WBXML: Tag in Tag - No recursion this time! "
2477 "(off = %d)\n", off);
2480 } else { /* No Content */
2482 printf ("WBXML: <Tag/> in Tag - No recursion! "
2483 "(off = %d)\n", off);
2486 if (peek & 0x80) { /* No Content, Attribute list present */
2487 if (tag_new_known) { /* Known tag */
2488 if (codepage_stag) { /* Not default code page */
2489 proto_tree_add_text (tree, tvb, off, 1,
2490 " %3d | Tag | T %3d->0 "
2491 "| Known Tag 0x%02X (A.) "
2493 *level, codepage_stag, tag_new_known,
2494 Indent (*level), tag_new_literal);
2495 /* Tag string already looked up earlier! */
2496 /* Reset code page */
2498 } else { /* Code page 0 */
2499 proto_tree_add_text (tree, tvb, off, 1,
2501 "| Known Tag 0x%02X (A.) "
2503 *level, tag_new_known,
2504 Indent (*level), tag_new_literal);
2505 /* Tag string already looked up earlier! */
2508 parse_wbxml_attribute_list_defined (tree, tvb,
2509 off, str_tbl, *level, &len, map);
2510 /* Check that there is still room in packet */
2512 if (off >= tvb_len) {
2513 proto_tree_add_text (tree, tvb, off, 1,
2518 printf("WBXML - STAG: level = %u, Return: len = %u (short frame)\n",
2519 *level, *parsed_length);
2523 proto_tree_add_text (tree, tvb, off-1, 1,
2525 "| END (Known Tag) "
2527 *level, Indent (*level));
2528 } else { /* LITERAL tag */
2529 proto_tree_add_text (tree, tvb, off, 1,
2531 "| LITERAL_A (Literal Tag) (A.) "
2533 *level, Indent (*level), tag_new_literal);
2535 parse_wbxml_attribute_list_defined (tree, tvb,
2536 off, str_tbl, *level, &len, map);
2537 /* Check that there is still room in packet */
2539 if (off >= tvb_len) {
2540 proto_tree_add_text (tree, tvb, off, 1,
2545 printf("WBXML - STAG: level = %u, Return: len = %u (short frame)\n",
2546 *level, *parsed_length);
2550 proto_tree_add_text (tree, tvb, off-1, 1,
2552 "| END (Literal Tag) "
2554 *level, Indent (*level));
2556 } else { /* No Content, No Attribute list */
2557 if (tag_new_known) { /* Known tag */
2558 if (codepage_stag) { /* Not default code page */
2559 proto_tree_add_text (tree, tvb, off, 1,
2560 " %3d | Tag | T %3d->0 "
2561 "| Known Tag 0x%02x (..) "
2563 *level, codepage_stag, tag_new_known,
2564 Indent (*level), tag_new_literal);
2565 /* Tag string already looked up earlier! */
2566 /* Reset code page */
2568 } else { /* Code page 0 */
2569 proto_tree_add_text (tree, tvb, off, 1,
2571 "| Known Tag 0x%02x (..) "
2573 *level, tag_new_known,
2574 Indent (*level), tag_new_literal);
2575 /* Tag string already looked up earlier! */
2578 } else { /* LITERAL tag */
2579 proto_tree_add_text (tree, tvb, off, 1,
2581 "| LITERAL (Literal Tag) (..) "
2583 *level, Indent (*level), tag_new_literal);
2588 /* TODO: Do I have to reset code page here? */
2590 } /* if (tag & 0x3F) >= 5 */
2593 *parsed_length = off - offset;
2594 printf("WBXML - STAG: level = %u, Return: len = %u (end of function body)\n", *level, *parsed_length);
2599 /* This function performs the WBXML decoding as in parse_wbxml_tag_defined()
2600 * but this time no WBXML mapping is performed.
2602 * Attribute parsing is done in parse_wbxml_attribute_list().
2605 parse_wbxml_tag (proto_tree *tree, tvbuff_t *tvb, guint32 offset,
2606 guint32 str_tbl, guint8 *level,
2607 guint32 *parsed_length)
2609 guint32 tvb_len = tvb_reported_length (tvb);
2610 guint32 off = offset;
2616 guint32 tag_len; /* Length of the index (uintvar) from a LITERAL tag */
2617 guint8 tag_save_known = 0; /* Will contain peek & 0x3F (tag identity) */
2618 guint8 tag_new_known = 0; /* Will contain peek & 0x3F (tag identity) */
2619 const char *tag_save_literal; /* Will contain the LITERAL tag identity */
2620 const char *tag_new_literal; /* Will contain the LITERAL tag identity */
2621 char tag_save_buf[10]; /* Will contain "tag_0x%02X" */
2622 char tag_new_buf[10]; /* Will contain "tag_0x%02X" */
2623 guint8 codepage_stag = 0; /* Initial codepage in state = STAG */
2624 guint8 parsing_tag_content = FALSE; /* Are we parsing content from a
2625 tag with content: <x>Content</x>
2627 The initial state is FALSE.
2628 This state will trigger recursion. */
2629 tag_save_literal = NULL; /* Prevents compiler warning */
2632 printf ("WBXML - parse_wbxml_tag (level = %d, offset = %d)\n",
2635 while (off < tvb_len) {
2636 peek = tvb_get_guint8 (tvb, off);
2638 printf("WBXML - STAG: level = %3d, peek = 0x%02X, off = %d, "
2640 *level, peek, off, tvb_len);
2642 if ((peek & 0x3F) < 4) switch (peek) { /* Global tokens in state = STAG
2643 but not the LITERAL tokens */
2644 case 0x00: /* SWITCH_PAGE */
2645 codepage_stag = tvb_get_guint8 (tvb, off+1);
2646 proto_tree_add_text (tree, tvb, off, 2,
2647 " | Tag | T 0->%3d "
2648 "| SWITCH_PAGE (Tag code page) "
2653 case 0x01: /* END: only possible for Tag with Content */
2654 if (tag_save_known) { /* Known TAG */
2655 proto_tree_add_text (tree, tvb, off, 1,
2657 "| END (Known Tag 0x%02X) "
2659 *level, tag_save_known, Indent (*level),
2660 tag_save_literal); /* We already looked it up! */
2661 } else { /* Literal TAG */
2662 proto_tree_add_text (tree, tvb, off, 1,
2664 "| END (Literal Tag) "
2666 *level, Indent (*level),
2671 *parsed_length = off - offset;
2672 /* Reset code page: not needed as return from recursion */
2674 printf("WBXML - STAG: level = %u, Return: len = %u\n", *level, *parsed_length);
2678 case 0x02: /* ENTITY */
2679 ent = tvb_get_guintvar (tvb, off+1, &len);
2680 proto_tree_add_text (tree, tvb, off, 1+len,
2684 *level, Indent (*level), ent);
2687 case 0x03: /* STR_I */
2688 len = tvb_strsize (tvb, off+1);
2689 proto_tree_add_text (tree, tvb, off, 1+len,
2691 "| STR_I (Inline string) "
2693 *level, Indent(*level),
2694 tvb_format_text (tvb, off+1, len-1));
2697 case 0x40: /* EXT_I_0 */
2698 case 0x41: /* EXT_I_1 */
2699 case 0x42: /* EXT_I_2 */
2700 /* Extension tokens */
2701 len = tvb_strsize (tvb, off+1);
2702 if (codepage_stag) { /* Not default code page */
2703 proto_tree_add_text (tree, tvb, off, 1+len,
2704 " %3d | Tag | T %3d->0 "
2705 "| EXT_I_%1x (Extension Token) "
2706 "| %s(Inline string extension: \'%s\')",
2707 *level, codepage_stag, peek & 0x0f, Indent (*level),
2708 tvb_format_text (tvb, off+1, len-1));
2709 /* Reset code page */
2711 } else { /* Code page 0 */
2712 proto_tree_add_text (tree, tvb, off, 1+len,
2714 "| EXT_I_%1x (Extension Token) "
2715 "| %s(Inline string extension: \'%s\')",
2716 *level, peek & 0x0f, Indent (*level),
2717 tvb_format_text (tvb, off+1, len-1));
2722 proto_tree_add_text (tree, tvb, off, 1,
2724 "| PI (XML Processing Instruction) "
2726 *level, Indent (*level));
2727 parse_wbxml_attribute_list (tree, tvb, off, str_tbl,
2729 /* Check that there is still room in packet */
2731 if (off >= tvb_len) {
2732 proto_tree_add_text (tree, tvb, off, 1,
2737 printf("WBXML - STAG: level = %u, Return: len = %u (short frame)\n",
2738 *level, *parsed_length);
2742 proto_tree_add_text (tree, tvb, off-1, 1,
2746 *level, Indent (*level));
2748 case 0x80: /* EXT_T_0 */
2749 case 0x81: /* EXT_T_1 */
2750 case 0x82: /* EXT_T_2 */
2751 /* Extension tokens */
2752 index = tvb_get_guintvar (tvb, off+1, &len);
2753 str_len = tvb_strsize (tvb, str_tbl+index);
2754 if (codepage_stag) { /* Not default code page */
2755 proto_tree_add_text (tree, tvb, off, 1+len,
2756 " %3d | Tag | T %3d->0 "
2757 "| EXT_T_%1x (Extension Token) "
2758 "| %s(Tableref string extension: \'%s\')",
2759 *level, codepage_stag, peek & 0x0f, Indent (*level),
2760 tvb_format_text (tvb, str_tbl+index, str_len-1));
2761 /* Reset code page */
2763 } else { /* Code page 0 */
2764 proto_tree_add_text (tree, tvb, off, 1+len,
2766 "| EXT_T_%1x (Extension Token) "
2767 "| %s(Tableref string extension: \'%s\')",
2768 *level, peek & 0x0f, Indent (*level),
2769 tvb_format_text (tvb, str_tbl+index, str_len-1));
2773 case 0x83: /* STR_T */
2774 index = tvb_get_guintvar (tvb, off+1, &len);
2775 str_len = tvb_strsize (tvb, str_tbl+index);
2776 proto_tree_add_text (tree, tvb, off, 1+len,
2778 "| STR_T (Tableref string) "
2780 *level, Indent (*level),
2781 tvb_format_text (tvb, str_tbl+index, str_len-1));
2784 case 0xC0: /* EXT_0 */
2785 case 0xC1: /* EXT_1 */
2786 case 0xC2: /* EXT_2 */
2787 /* Extension tokens */
2788 if (codepage_stag) { /* Not default code page */
2789 proto_tree_add_text (tree, tvb, off, 1,
2790 " %3d | Tag | T %3d->0 "
2791 "| EXT_%1x (Extension Token) "
2792 "| %s(Single-byte extension)",
2793 *level, codepage_stag, peek & 0x0f,
2795 /* Reset code page */
2797 } else { /* Code page 0 */
2798 proto_tree_add_text (tree, tvb, off, 1,
2800 "| EXT_%1x (Extension Token) "
2801 "| %s(Single-byte extension)",
2802 *level, peek & 0x0f, Indent (*level));
2806 case 0xC3: /* OPAQUE - WBXML 1.1 and newer */
2807 if (tvb_get_guint8 (tvb, 0)) { /* WBXML 1.x (x > 0) */
2808 index = tvb_get_guintvar (tvb, off+1, &len);
2809 proto_tree_add_text (tree, tvb, off, 1 + len + index,
2811 "| OPAQUE (Opaque data) "
2812 "| %s(%d bytes of opaque data)",
2813 *level, Indent (*level), index);
2815 } else { /* WBXML 1.0 - RESERVED_2 token (invalid) */
2816 proto_tree_add_text (tree, tvb, off, 1,
2818 "| RESERVED_2 (Invalid Token!) "
2819 "| WBXML 1.0 parsing stops here.",
2821 /* Stop processing as it is impossible to parse now */
2823 *parsed_length = off - offset;
2825 printf("WBXML - STAG: level = %u, Return: len = %u\n", *level, *parsed_length);
2831 /* No default clause, as all cases have been treated */
2832 } else { /* LITERAL or Known TAG */
2833 /* We must store the initial tag, and also retrieve the new tag.
2834 * For efficiency reasons, we store the literal tag representation
2835 * for known tags too, so we can easily close the tag without the
2836 * need of a new lookup and avoiding storage of token codepage.
2838 * There are 4 possibilities:
2840 * 1. Known tag followed by a known tag
2841 * 2. Known tag followed by a LITERAL tag
2842 * 3. LITERAL tag followed by Known tag
2843 * 4. LITERAL tag followed by LITERAL tag
2846 /* Store the new tag */
2848 if ((peek & 0x3F) == 4) { /* LITERAL */
2849 index = tvb_get_guintvar (tvb, off+1, &tag_len);
2850 str_len = tvb_strsize (tvb, str_tbl+index);
2851 tag_new_literal = tvb_get_ptr (tvb, str_tbl+index, str_len);
2852 tag_new_known = 0; /* invalidate known tag_new */
2853 } else { /* Known tag */
2854 tag_new_known = peek & 0x3F;
2855 sprintf (tag_new_buf, "Tag_0x%02X",
2857 tag_new_literal = tag_new_buf;
2858 /* Stored looked up tag name string */
2861 /* Parsing of TAG starts HERE */
2862 if (peek & 0x40) { /* Content present */
2864 * [!] An explicit END token is expected in these cases!
2865 * ==> Recursion possible if we encounter a tag with content;
2866 * recursion will return at the explicit END token.
2868 if (parsing_tag_content) { /* Recurse */
2870 printf("WBXML - STAG: Tag in Tag - RECURSE! (off = %d)\n", off);
2872 /* Do not process the attribute list:
2873 * recursion will take care of it */
2875 parse_wbxml_tag (tree, tvb, off, str_tbl, level,
2878 } else { /* Now we will have content to parse */
2879 /* Save the start tag so we can properly close it later. */
2880 if ((peek & 0x3F) == 4) { /* Literal tag */
2881 tag_save_literal = tag_new_literal;
2883 } else { /* Known tag */
2884 tag_save_known = tag_new_known;
2885 sprintf (tag_save_buf, "Tag_0x%02X",
2887 tag_save_literal = tag_save_buf;
2888 /* The last statement avoids needless lookups */
2890 /* Process the attribute list if present */
2891 if (peek & 0x80) { /* Content and Attribute list present */
2892 if (tag_new_known) { /* Known tag */
2893 if (codepage_stag) { /* Not default code page */
2894 proto_tree_add_text (tree, tvb, off, 1,
2895 " %3d | Tag | T %3d->0 "
2896 "| Known Tag 0x%02X (AC) "
2898 *level, codepage_stag, tag_new_known,
2899 Indent (*level), tag_new_literal);
2900 /* Tag string already looked up earlier! */
2901 /* Reset code page */
2903 } else { /* Code page 0 */
2904 proto_tree_add_text (tree, tvb, off, 1,
2906 "| Known Tag 0x%02X (AC) "
2908 *level, tag_new_known,
2909 Indent (*level), tag_new_literal);
2910 /* Tag string already looked up earlier! */
2913 } else { /* LITERAL tag */
2914 proto_tree_add_text (tree, tvb, off, 1,
2916 "| LITERAL_AC (Literal tag) (AC) "
2918 *level, Indent (*level), tag_new_literal);
2921 parse_wbxml_attribute_list (tree, tvb,
2922 off, str_tbl, *level, &len);
2923 /* Check that there is still room in packet */
2925 if (off >= tvb_len) {
2926 proto_tree_add_text (tree, tvb, off, 1,
2931 printf("WBXML - STAG: level = %u, Return: len = %u (short frame)\n",
2932 *level, *parsed_length);
2936 proto_tree_add_text (tree, tvb, off-1, 1,
2938 "| END (attribute list) "
2940 *level, Indent (*level));
2941 } else { /* Content, no Attribute list */
2942 if (tag_new_known) { /* Known tag */
2943 if (codepage_stag) { /* Not default code page */
2944 proto_tree_add_text (tree, tvb, off, 1,
2945 " %3d | Tag | T %3d->0 "
2946 "| Known Tag 0x%02X (.C) "
2948 *level, codepage_stag, tag_new_known,
2951 /* Tag string already looked up earlier! */
2952 /* Reset code page */
2954 } else { /* Code page 0 */
2955 proto_tree_add_text (tree, tvb, off, 1,
2957 "| Known Tag 0x%02X (.C) "
2959 *level, tag_new_known,
2962 /* Tag string already looked up earlier! */
2965 } else { /* LITERAL tag */
2966 proto_tree_add_text (tree, tvb, off, 1,
2968 "| LITERAL_C (Literal Tag) (.C) "
2970 *level, Indent (*level), tag_new_literal);
2974 /* The data that follows in the parsing process
2975 * represents content for the opening tag
2976 * we've just processed in the lines above.
2977 * Next time we encounter a tag with content: recurse
2979 parsing_tag_content = TRUE;
2981 printf ("WBXML: Tag in Tag - No recursion this time! "
2982 "(off = %d)\n", off);
2985 } else { /* No Content */
2987 printf ("WBXML: <Tag/> in Tag - No recursion! "
2988 "(off = %d)\n", off);
2991 if (peek & 0x80) { /* No Content, Attribute list present */
2992 if (tag_new_known) { /* Known tag */
2993 if (codepage_stag) { /* Not default code page */
2994 proto_tree_add_text (tree, tvb, off, 1,
2995 " %3d | Tag | T %3d->0 "
2996 "| Known Tag 0x%02X (A.) "
2998 *level, codepage_stag, tag_new_known,
2999 Indent (*level), tag_new_literal);
3000 /* Tag string already looked up earlier! */
3001 /* Reset code page */
3003 } else { /* Code page 0 */
3004 proto_tree_add_text (tree, tvb, off, 1,
3006 "| Known Tag 0x%02X (A.) "
3008 *level, tag_new_known,
3009 Indent (*level), tag_new_literal);
3010 /* Tag string already looked up earlier! */
3013 parse_wbxml_attribute_list (tree, tvb,
3014 off, str_tbl, *level, &len);
3015 /* Check that there is still room in packet */
3017 if (off >= tvb_len) {
3018 proto_tree_add_text (tree, tvb, off, 1,
3023 printf("WBXML - STAG: level = %u, Return: len = %u (short frame)\n",
3024 *level, *parsed_length);
3028 proto_tree_add_text (tree, tvb, off-1, 1,
3030 "| END (Known Tag) "
3032 *level, Indent (*level));
3033 } else { /* LITERAL tag */
3034 proto_tree_add_text (tree, tvb, off, 1,
3036 "| LITERAL_A (Literal Tag) (A.) "
3038 *level, Indent (*level), tag_new_literal);
3040 parse_wbxml_attribute_list (tree, tvb,
3041 off, str_tbl, *level, &len);
3042 /* Check that there is still room in packet */
3044 if (off >= tvb_len) {
3045 proto_tree_add_text (tree, tvb, off, 1,
3050 printf("WBXML - STAG: level = %u, Return: len = %u (short frame)\n",
3051 *level, *parsed_length);
3055 proto_tree_add_text (tree, tvb, off-1, 1,
3057 "| END (Literal Tag) "
3059 *level, Indent (*level));
3061 } else { /* No Content, No Attribute list */
3062 if (tag_new_known) { /* Known tag */
3063 if (codepage_stag) { /* Not default code page */
3064 proto_tree_add_text (tree, tvb, off, 1,
3065 " %3d | Tag | T %3d->0 "
3066 "| Known Tag 0x%02x (..) "
3068 *level, codepage_stag, tag_new_known,
3069 Indent (*level), tag_new_literal);
3070 /* Tag string already looked up earlier! */
3071 /* Reset code page */
3073 } else { /* Code page 0 */
3074 proto_tree_add_text (tree, tvb, off, 1,
3076 "| Known Tag 0x%02x (..) "
3078 *level, tag_new_known,
3079 Indent (*level), tag_new_literal);
3080 /* Tag string already looked up earlier! */
3083 } else { /* LITERAL tag */
3084 proto_tree_add_text (tree, tvb, off, 1,
3086 "| LITERAL (Literal Tag) (..) "
3088 *level, Indent (*level), tag_new_literal);
3093 /* TODO: Do I have to reset code page here? */
3095 } /* if (tag & 0x3F) >= 5 */
3098 *parsed_length = off - offset;
3099 printf("WBXML - STAG: level = %u, Return: len = %u (end of function body)\n", *level, *parsed_length);
3104 /**************************
3105 * WBXML Attribute tokens *
3106 **************************
3107 * Bit Mask : Example
3108 * -------------------
3109 * 0... .... : attr= (attribute name)
3110 * href='http://' (attribute name with start of attribute value)
3111 * 1... .... : 'www.' (attribute value, or part of it)
3116 /* This function parses the WBXML and maps known token interpretations
3117 * to the WBXML tokens. As a result, the original XML document can be
3118 * recreated. Indentation is generated in order to ease reading.
3120 * This function performs attribute list parsing.
3122 * The wbxml_token_map entry *map contains the actual token mapping.
3124 * NOTE: See above for known token mappings.
3127 parse_wbxml_attribute_list_defined (proto_tree *tree, tvbuff_t *tvb,
3128 guint32 offset, guint32 str_tbl, guint8 level,
3129 guint32 *parsed_length,
3130 const wbxml_token_map *map)
3132 guint32 tvb_len = tvb_reported_length (tvb);
3133 guint32 off = offset;
3139 guint8 codepage_attr = 0; /* Initial codepage in state = ATTR */
3142 printf ("WBXML - parse_wbxml_attr_defined (level = %d, offset = %d)\n",
3145 /* Parse attributes */
3146 while (off < tvb_len) {
3147 peek = tvb_get_guint8 (tvb, off);
3149 printf("WBXML - ATTR: level = %3d, peek = 0x%02X, off = %d, "
3151 level, peek, off, tvb_len);
3153 if ((peek & 0x3F) < 5) switch (peek) { /* Global tokens
3155 case 0x00: /* SWITCH_PAGE */
3156 codepage_attr = tvb_get_guint8 (tvb, off+1);
3157 proto_tree_add_text (tree, tvb, off, 2,
3158 " | Attr | A 0->%3d "
3159 "| SWITCH_PAGE (Attr code page) |",
3163 case 0x01: /* END */
3165 * The Attribute END token means either ">" or "/>"
3166 * and as a consequence both must be treated separately.
3167 * This is done in the TAG state parser.
3170 *parsed_length = off - offset;
3172 printf("WBXML - ATTR: level = %u, Return: len = %u\n", level, *parsed_length);
3175 case 0x02: /* ENTITY */
3176 ent = tvb_get_guintvar (tvb, off+1, &len);
3177 proto_tree_add_text (tree, tvb, off, 1+len,
3181 level, Indent (level), ent);
3184 case 0x03: /* STR_I */
3185 len = tvb_strsize (tvb, off+1);
3186 proto_tree_add_text (tree, tvb, off, 1+len,
3188 "| STR_I (Inline string) "
3190 level, Indent (level),
3191 tvb_format_text (tvb, off+1, len-1));
3194 case 0x04: /* LITERAL */
3195 index = tvb_get_guintvar (tvb, off+1, &len);
3196 str_len = tvb_strsize (tvb, str_tbl+index);
3197 proto_tree_add_text (tree, tvb, off, 1+len,
3199 "| LITERAL (Literal Attribute) "
3201 level, Indent (level),
3202 tvb_format_text (tvb, str_tbl+index, str_len-1));
3205 case 0x40: /* EXT_I_0 */
3206 case 0x41: /* EXT_I_1 */
3207 case 0x42: /* EXT_I_2 */
3208 /* Extension tokens */
3209 len = tvb_strsize (tvb, off+1);
3210 if (codepage_attr) { /* Not default code page */
3211 proto_tree_add_text (tree, tvb, off, 1+len,
3212 " %3d | Attr | A %3d->0 "
3213 "| EXT_I_%1x (Extension Token) "
3215 level, codepage_attr, peek & 0x0f, Indent (level),
3216 map_token (map->global, codepage_attr, peek),
3217 tvb_format_text (tvb, off+1, len-1));
3218 /* Reset code page */
3220 } else { /* Code page 0 */
3221 proto_tree_add_text (tree, tvb, off, 1+len,
3223 "| EXT_I_%1x (Extension Token) "
3225 level, peek & 0x0f, Indent (level),
3226 map_token (map->global, codepage_attr, peek),
3227 tvb_format_text (tvb, off+1, len-1));
3231 /* 0x43 impossible in ATTR state */
3232 /* 0x44 impossible in ATTR state */
3233 case 0x80: /* EXT_T_0 */
3234 case 0x81: /* EXT_T_1 */
3235 case 0x82: /* EXT_T_2 */
3236 /* Extension tokens */
3237 index = tvb_get_guintvar (tvb, off+1, &len);
3238 str_len = tvb_strsize (tvb, str_tbl+index);
3239 if (codepage_attr) { /* Not default code page */
3240 proto_tree_add_text (tree, tvb, off, 1+len,
3241 " %3d | Attr | A %3d->0 "
3242 "| EXT_T_%1x (Extension Token) "
3244 level, codepage_attr, peek & 0x0f, Indent (level),
3245 map_token (map->global, codepage_attr, peek),
3246 tvb_format_text (tvb, str_tbl+index, str_len-1));
3247 /* Reset code page */
3249 } else { /* Code page 0 */
3250 proto_tree_add_text (tree, tvb, off, 1+len,
3252 "| EXT_T_%1x (Extension Token) "
3254 level, peek & 0x0f, Indent (level),
3255 map_token (map->global, codepage_attr, peek),
3256 tvb_format_text (tvb, str_tbl+index, str_len-1));
3260 case 0x83: /* STR_T */
3261 index = tvb_get_guintvar (tvb, off+1, &len);
3262 str_len = tvb_strsize (tvb, str_tbl+index);
3263 proto_tree_add_text (tree, tvb, off, 1+len,
3265 "| STR_T (Tableref string) "
3267 level, Indent (level),
3268 tvb_format_text (tvb, str_tbl+index, str_len-1));
3271 /* 0x84 impossible in ATTR state */
3272 case 0xC0: /* EXT_0 */
3273 case 0xC1: /* EXT_1 */
3274 case 0xC2: /* EXT_2 */
3275 /* Extension tokens */
3276 if (codepage_attr) { /* Not default code page */
3277 proto_tree_add_text (tree, tvb, off, 1,
3278 " %3d | Attr | A %3d->0 "
3279 "| EXT_%1x (Extension Token) "
3281 level, codepage_attr, peek & 0x0f, Indent (level),
3282 map_token (map->global, codepage_attr, peek));
3283 /* Reset code page */
3285 } else { /* Code page 0 */
3286 proto_tree_add_text (tree, tvb, off, 1,
3288 "| EXT_%1x (Extension Token) "
3290 level, peek & 0x0f, Indent (level),
3291 map_token (map->global, codepage_attr, peek));
3295 case 0xC3: /* OPAQUE - WBXML 1.1 and newer */
3296 if (tvb_get_guint8 (tvb, 0)) { /* WBXML 1.x (x > 0) */
3297 index = tvb_get_guintvar (tvb, off+1, &len);
3298 proto_tree_add_text (tree, tvb, off, 1 + len + index,
3300 "| OPAQUE (Opaque data) "
3301 "| %s(%d bytes of opaque data)",
3302 level, Indent (level), index);
3304 } else { /* WBXML 1.0 - RESERVED_2 token (invalid) */
3305 proto_tree_add_text (tree, tvb, off, 1,
3307 "| RESERVED_2 (Invalid Token!) "
3308 "| WBXML 1.0 parsing stops here.",
3310 /* Stop processing as it is impossible to parse now */
3312 *parsed_length = off - offset;
3314 printf("WBXML - ATTR: level = %u, Return: len = %u\n", level, *parsed_length);
3319 /* 0xC4 impossible in ATTR state */
3321 proto_tree_add_text (tree, tvb, off, 1,
3323 "| %-10s (Invalid Token!) "
3324 "| WBXML parsing stops here.",
3325 level, match_strval (peek, vals_wbxml1x_global_tokens));
3326 /* Move to end of buffer */
3329 } else { /* Known atribute token */
3330 if (peek & 0x80) { /* attrValue */
3331 if (codepage_attr) { /* Not default code page */
3332 proto_tree_add_text (tree, tvb, off, 1,
3333 " %3d | Attr | A %3d->0 "
3334 "| Known attrValue 0x%02X "
3336 level, codepage_attr, peek & 0x7f, Indent (level),
3337 map_token (map->attrValue, codepage_attr, peek));
3338 /* Reset code page */
3340 } else { /* Code page 0 */
3341 proto_tree_add_text (tree, tvb, off, 1,
3343 "| Known attrValue 0x%02X "
3345 level, peek & 0x7f, Indent (level),
3346 map_token (map->attrValue, codepage_attr, peek));
3349 } else { /* attrStart */
3350 if (codepage_attr) { /* Not default code page */
3351 proto_tree_add_text (tree, tvb, off, 1,
3352 " %3d | Attr | A %3d->0 "
3353 "| Known attrStart 0x%02X "
3355 level, codepage_attr, peek & 0x7f, Indent (level),
3356 map_token (map->attrStart, codepage_attr, peek));
3357 /* Reset code page */
3359 } else { /* Code page 0 */
3360 proto_tree_add_text (tree, tvb, off, 1,
3362 "| Known attrStart 0x%02X "
3364 level, peek & 0x7f, Indent (level),
3365 map_token (map->attrStart, codepage_attr, peek));
3372 *parsed_length = off - offset;
3373 printf("WBXML - ATTR: level = %u, Return: len = %u (end of function body)\n", level, *parsed_length);
3378 /* This function performs the WBXML attribute decoding as in
3379 * parse_wbxml_attribute_list_defined() but this time no WBXML mapping
3382 * This function performs attribute list parsing.
3384 * NOTE: Code page switches not yet processed in the code!
3387 parse_wbxml_attribute_list (proto_tree *tree, tvbuff_t *tvb,
3388 guint32 offset, guint32 str_tbl, guint8 level,
3389 guint32 *parsed_length)
3391 guint32 tvb_len = tvb_reported_length (tvb);
3392 guint32 off = offset;
3398 guint8 codepage_attr = 0; /* Initial codepage in state = ATTR */
3401 printf ("WBXML - parse_wbxml_attr (level = %d, offset = %d)\n",
3404 /* Parse attributes */
3405 while (off < tvb_len) {
3406 peek = tvb_get_guint8 (tvb, off);
3408 printf("WBXML - ATTR: level = %3d, peek = 0x%02X, off = %d, "
3410 level, peek, off, tvb_len);
3412 if ((peek & 0x3F) < 5) switch (peek) { /* Global tokens
3414 case 0x00: /* SWITCH_PAGE */
3415 codepage_attr = tvb_get_guint8 (tvb, off+1);
3416 proto_tree_add_text (tree, tvb, off, 2,
3417 " | Attr | A 0->%3d "
3418 "| SWITCH_PAGE (Attr code page) |",
3422 case 0x01: /* END */
3424 * The Attribute END token means either ">" or "/>"
3425 * and as a consequence both must be treated separately.
3426 * This is done in the TAG state parser.
3429 *parsed_length = off - offset;
3431 printf("WBXML - ATTR: level = %u, Return: len = %u\n", level, *parsed_length);
3434 case 0x02: /* ENTITY */
3435 ent = tvb_get_guintvar (tvb, off+1, &len);
3436 proto_tree_add_text (tree, tvb, off, 1+len,
3440 level, Indent (level), ent);
3443 case 0x03: /* STR_I */
3444 len = tvb_strsize (tvb, off+1);
3445 proto_tree_add_text (tree, tvb, off, 1+len,
3447 "| STR_I (Inline string) "
3449 level, Indent (level),
3450 tvb_format_text (tvb, off+1, len-1));
3453 case 0x04: /* LITERAL */
3454 index = tvb_get_guintvar (tvb, off+1, &len);
3455 str_len = tvb_strsize (tvb, str_tbl+index);
3456 proto_tree_add_text (tree, tvb, off, 1+len,
3458 "| LITERAL (Literal Attribute) "
3460 level, Indent (level),
3461 tvb_format_text (tvb, str_tbl+index, str_len-1));
3464 case 0x40: /* EXT_I_0 */
3465 case 0x41: /* EXT_I_1 */
3466 case 0x42: /* EXT_I_2 */
3467 /* Extension tokens */
3468 len = tvb_strsize (tvb, off+1);
3469 if (codepage_attr) { /* Not default code page */
3470 proto_tree_add_text (tree, tvb, off, 1+len,
3471 " %3d | Attr | A %3d->0 "
3472 "| EXT_I_%1x (Extension Token) "
3473 "| %s(Inline string extension: \'%s\')",
3474 level, codepage_attr, peek & 0x0f, Indent (level),
3475 tvb_format_text (tvb, off+1, len-1));
3476 /* Reset code page */
3478 } else { /* Code page 0 */
3479 proto_tree_add_text (tree, tvb, off, 1+len,
3481 "| EXT_I_%1x (Extension Token) "
3482 "| %s(Inline string extension: \'%s\')",
3483 level, peek & 0x0f, Indent (level),
3484 tvb_format_text (tvb, off+1, len-1));
3488 /* 0x43 impossible in ATTR state */
3489 /* 0x44 impossible in ATTR state */
3490 case 0x80: /* EXT_T_0 */
3491 case 0x81: /* EXT_T_1 */
3492 case 0x82: /* EXT_T_2 */
3493 /* Extension tokens */
3494 index = tvb_get_guintvar (tvb, off+1, &len);
3495 str_len = tvb_strsize (tvb, str_tbl+index);
3496 if (codepage_attr) { /* Not default code page */
3497 proto_tree_add_text (tree, tvb, off, 1+len,
3498 " %3d | Attr | A %3d->0 "
3499 "| EXT_T_%1x (Extension Token) "
3500 "| %s(Tableref string extension: \'%s\')",
3501 level, codepage_attr, peek & 0x0f, Indent (level),
3502 tvb_format_text (tvb, str_tbl+index, str_len-1));
3503 /* Reset code page */
3505 } else { /* Code page 0 */
3506 proto_tree_add_text (tree, tvb, off, 1+len,
3508 "| EXT_T_%1x (Extension Token) "
3509 "| %s(Tableref string extension: \'%s\')",
3510 level, peek & 0x0f, Indent (level),
3511 tvb_format_text (tvb, str_tbl+index, str_len-1));
3515 case 0x83: /* STR_T */
3516 index = tvb_get_guintvar (tvb, off+1, &len);
3517 str_len = tvb_strsize (tvb, str_tbl+index);
3518 proto_tree_add_text (tree, tvb, off, 1+len,
3520 "| STR_T (Tableref string) "
3522 level, Indent (level),
3523 tvb_format_text (tvb, str_tbl+index, str_len-1));
3526 /* 0x84 impossible in ATTR state */
3527 case 0xC0: /* EXT_0 */
3528 case 0xC1: /* EXT_1 */
3529 case 0xC2: /* EXT_2 */
3530 /* Extension tokens */
3531 if (codepage_attr) { /* Not default code page */
3532 proto_tree_add_text (tree, tvb, off, 1,
3533 " %3d | Attr | A %3d->0 "
3534 "| EXT_%1x (Extension Token) "
3535 "| %s(Single-byte extension)",
3536 level, codepage_attr, peek & 0x0f, Indent (level));
3537 /* Reset code page */
3539 } else { /* Code page 0 */
3540 proto_tree_add_text (tree, tvb, off, 1,
3542 "| EXT_%1x (Extension Token) "
3543 "| %s(Single-byte extension)",
3544 level, peek & 0x0f, Indent (level));
3548 case 0xC3: /* OPAQUE - WBXML 1.1 and newer */
3549 if (tvb_get_guint8 (tvb, 0)) { /* WBXML 1.x (x > 0) */
3550 index = tvb_get_guintvar (tvb, off+1, &len);
3551 proto_tree_add_text (tree, tvb, off, 1 + len + index,
3553 "| OPAQUE (Opaque data) "
3554 "| %s(%d bytes of opaque data)",
3555 level, Indent (level), index);
3557 } else { /* WBXML 1.0 - RESERVED_2 token (invalid) */
3558 proto_tree_add_text (tree, tvb, off, 1,
3560 "| RESERVED_2 (Invalid Token!) "
3561 "| WBXML 1.0 parsing stops here.",
3563 /* Stop processing as it is impossible to parse now */
3565 *parsed_length = off - offset;
3567 printf("WBXML - ATTR: level = %u, Return: len = %u\n", level, *parsed_length);
3572 /* 0xC4 impossible in ATTR state */
3574 proto_tree_add_text (tree, tvb, off, 1,
3576 "| %-10s (Invalid Token!) "
3577 "| WBXML parsing stops here.",
3578 level, match_strval (peek, vals_wbxml1x_global_tokens));
3579 /* Move to end of buffer */
3582 } else { /* Known atribute token */
3583 if (peek & 0x80) { /* attrValue */
3584 if (codepage_attr) { /* Not default code page */
3585 proto_tree_add_text (tree, tvb, off, 1,
3586 " %3d | Attr | A %3d->0 "
3587 "| Known attrValue 0x%02X "
3588 "| %sattrValue_0x%02X",
3589 level, codepage_attr, peek & 0x7f, Indent (level),
3591 /* Reset code page */
3593 } else { /* Code page 0 */
3594 proto_tree_add_text (tree, tvb, off, 1,
3596 "| Known attrValue 0x%02X "
3597 "| %sattrValue_0x%02X",
3598 level, peek & 0x7f, Indent (level),
3602 } else { /* attrStart */
3603 if (codepage_attr) { /* Not default code page */
3604 proto_tree_add_text (tree, tvb, off, 1,
3605 " %3d | Attr | A %3d->0 "
3606 "| Known attrStart 0x%02X "
3607 "| %sattrStart_0x%02X",
3608 level, codepage_attr, peek & 0x7f, Indent (level),
3610 /* Reset code page */
3612 } else { /* Code page 0 */
3613 proto_tree_add_text (tree, tvb, off, 1,
3615 "| Known attrStart 0x%02X "
3616 "| %sattrStart_0x%02X",
3617 level, peek & 0x7f, Indent (level),
3625 *parsed_length = off - offset;
3626 printf("WBXML - ATTR: level = %u, Return: len = %u (end of function body)\n", level, *parsed_length);
3631 /****************** Register the protocol with Ethereal ******************/
3634 /* This format is required because a script is used to build the C function
3635 * that calls the protocol registration. */
3638 proto_register_wbxml(void)
3639 { /* Setup list of header fields. See Section 1.6.1 for details. */
3640 static hf_register_info hf[] = {
3641 { &hf_wbxml_version,
3645 VALS ( vals_wbxml_versions ), 0x00,
3646 "WBXML Version", HFILL }
3648 { &hf_wbxml_public_id_known,
3649 { "Public Identifier (known)",
3650 "wbxml.public_id.known",
3651 FT_UINT32, BASE_HEX,
3652 VALS ( vals_wbxml_public_ids ), 0x00,
3653 "WBXML Known Public Identifier (integer)", HFILL }
3655 { &hf_wbxml_public_id_literal,
3656 { "Public Identifier (literal)",
3657 "wbxml.public_id.literal",
3658 FT_STRING, BASE_NONE,
3660 "WBXML Literal Public Identifier (text string)", HFILL }
3662 { &hf_wbxml_charset,
3665 FT_UINT32, BASE_HEX,
3666 VALS ( vals_character_sets ), 0x00,
3667 "WBXML Character Set", HFILL }
3671 /* Setup protocol subtree array */
3672 static gint *ett[] = {
3678 /* Register the protocol name and description */
3679 proto_wbxml = proto_register_protocol(
3685 /* Required function calls to register the header fields
3686 * and subtrees used */
3687 proto_register_field_array(proto_wbxml, hf, array_length(hf));
3688 proto_register_subtree_array(ett, array_length(ett));
3690 register_dissector("wbxml", dissect_wbxml, proto_wbxml);
3695 proto_reg_handoff_wbxml(void)
3697 dissector_handle_t wbxml_handle;
3699 /* Heuristic dissectors would be declared by means of:
3700 * heur_dissector_add("wsp", dissect_wbxml_heur, proto_wbxml);
3703 wbxml_handle = create_dissector_handle(dissect_wbxml, proto_wbxml);
3705 /* Register the WSP content types (defined as protocol port)
3706 * for WBXML dissection.
3708 * See http://www.wapforum.org/wina/wsp-content-type.htm
3711 /**** Well-known WBXML WSP Content-Type values ****/
3713 /* application/vnd.wap.wmlc */
3714 dissector_add("wsp.content_type.integer", 0x14, wbxml_handle);
3715 dissector_add_string("wsp.content_type.literal",
3716 "application/vnd.wap.wmlc", wbxml_handle);
3718 /* application/vnd.wap.wta-eventc */
3719 dissector_add("wsp.content_type.integer", 0x16, wbxml_handle);
3720 dissector_add_string("wsp.content_type.literal",
3721 "application/vnd.wap.wta-eventc", wbxml_handle);
3723 /* application/vnd.wap.wbxml */
3724 dissector_add("wsp.content_type.integer", 0x29, wbxml_handle);
3725 dissector_add_string("wsp.content_type.literal",
3726 "application/vnd.wap.wbxml", wbxml_handle);
3728 /* application/vnd.wap.sic */
3729 dissector_add("wsp.content_type.integer", 0x2E, wbxml_handle);
3730 dissector_add_string("wsp.content_type.literal",
3731 "application/vnd.wap.sic", wbxml_handle);
3733 /* application/vnd.wap.slc */
3734 dissector_add("wsp.content_type.integer", 0x30, wbxml_handle);
3735 dissector_add_string("wsp.content_type.literal",
3736 "application/vnd.wap.slc", wbxml_handle);
3738 /* application/vnd.wap.coc */
3739 dissector_add("wsp.content_type.integer", 0x32, wbxml_handle);
3740 dissector_add_string("wsp.content_type.literal",
3741 "application/vnd.wap.coc", wbxml_handle);
3743 /* application/vnd.wap.connectivity-wbxml */
3744 dissector_add("wsp.content_type.integer", 0x36, wbxml_handle);
3745 dissector_add_string("wsp.content_type.literal",
3746 "application/vnd.wap.connectivity-wbxml", wbxml_handle);
3748 /* application/vnd.wap.locc+wbxml */
3749 dissector_add("wsp.content_type.integer", 0x40, wbxml_handle);
3750 dissector_add_string("wsp.content_type.literal",
3751 "application/vnd.wap.locc+wbxml", wbxml_handle);
3753 /* application/vnd.syncml.dm+wbxml */
3754 dissector_add("wsp.content_type.integer", 0x42, wbxml_handle);
3755 dissector_add_string("wsp.content_type.literal",
3756 "application/vnd.syncml.dm+wbxml", wbxml_handle);
3758 /* application/vnd.oma.drm.rights+wbxml */
3759 dissector_add("wsp.content_type.integer", 0x4B, wbxml_handle);
3760 dissector_add_string("wsp.content_type.literal",
3761 "application/vnd.oma.drm.rights+wbxml", wbxml_handle);
3763 /**** Registered WBXML WSP Content-Type values ****/
3765 /* application/vnd.uplanet.cacheop-wbxml */
3766 dissector_add("wsp.content_type.integer", 0x0201, wbxml_handle);
3767 dissector_add_string("wsp.content_type.literal",
3768 "application/vnd.uplanet.cacheop-wbxml", wbxml_handle);
3770 /* application/vnd.uplanet.alert-wbxml */
3771 dissector_add("wsp.content_type.integer", 0x0203, wbxml_handle);
3772 dissector_add_string("wsp.content_type.literal",
3773 "application/vnd.uplanet.alert-wbxml", wbxml_handle);
3775 /* application/vnd.uplanet.list-wbxml */
3776 dissector_add("wsp.content_type.integer", 0x0204, wbxml_handle);
3777 dissector_add_string("wsp.content_type.literal",
3778 "application/vnd.uplanet.list-wbxml", wbxml_handle);
3780 /* application/vnd.uplanet.listcmd-wbxml */
3781 dissector_add("wsp.content_type.integer", 0x0205, wbxml_handle);
3782 dissector_add_string("wsp.content_type.literal",
3783 "application/vnd.uplanet.listcmd-wbxml", wbxml_handle);
3785 /* application/vnd.uplanet.channel-wbxml */
3786 dissector_add("wsp.content_type.integer", 0x0206, wbxml_handle);
3787 dissector_add_string("wsp.content_type.literal",
3788 "application/vnd.uplanet.channel-wbxml", wbxml_handle);
3790 /* application/vnd.uplanet.bearer-choice-wbxml */
3791 dissector_add("wsp.content_type.integer", 0x0209, wbxml_handle);
3792 dissector_add_string("wsp.content_type.literal",
3793 "application/vnd.uplanet.bearer-choice-wbxml", wbxml_handle);
3795 /* application/vnd.phonecom.mmc-wbxml */
3796 dissector_add("wsp.content_type.integer", 0x020A, wbxml_handle);
3797 dissector_add_string("wsp.content_type.literal",
3798 "application/vnd.phonecom.mmc-wbxml", wbxml_handle);
3800 /* application/vnd.nokia.syncset+wbxml */
3801 dissector_add("wsp.content_type.integer", 0x020B, wbxml_handle);
3802 dissector_add_string("wsp.content_type.literal",
3803 "application/vnd.nokia.syncset+wbxml", wbxml_handle);
3805 /***** Content types that only have a textual representation *****/
3806 dissector_add_string("wsp.content_type.literal",
3807 "application/x-wap-prov.browser-bookmarks", wbxml_handle);
3808 dissector_add_string("wsp.content_type.literal",
3809 "application/x-wap-prov.browser-settings", wbxml_handle);