2 * Routines for wbxml dissection
3 * Copyright 2003, Olivier Biot <olivier.biot (ad) siemens.com>
5 * $Id: packet-wbxml.c,v 1.9 2003/05/01 18:18:20 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 /* See WAP-104-WBXML */
190 static const value_string vals_wbxml10_global_tokens[] = {
191 { 0x00, "SWITCH_PAGE" },
201 { 0x44, "LITERAL_C" },
207 { 0x84, "LITERAL_A" },
212 { 0xC3, "RESERVED_2" },
213 { 0xC4, "LITERAL_AC" },
218 /* See WAP-135-WBXML, WAP-154-WBXML, WAP-192-WBXML */
219 static const value_string vals_wbxml1x_global_tokens[] = {
220 { 0x00, "SWITCH_PAGE" },
230 { 0x44, "LITERAL_C" },
236 { 0x84, "LITERAL_A" },
242 { 0xC4, "LITERAL_AC" },
248 /********************** WBXML token mapping definition **********************/
253 * Wireless Markup Language
254 ***************************************/
256 /***** Global extension tokens *****/
257 static const value_string wbxml_wmlc10_global_cp0[] = {
258 { 0x40, "Variable substitution - escaped" },
259 { 0x41, "Variable substitution - unescaped" },
260 { 0x42, "Variable substitution - no transformation" },
261 { 0x80, "Variable substitution - escaped" },
262 { 0x81, "Variable substitution - unescaped" },
263 { 0x82, "Variable substitution - no transformation" },
264 { 0xC0, "Reserved" },
265 { 0xC1, "Reserved" },
266 { 0xC2, "Reserved" },
271 /***** Tag tokens *****/
272 static const value_string wbxml_wmlc10_tags_cp0[] = {
273 /* 0x00 -- 0x04 GLOBAL */
283 { 0xEA, "FIELDSET" },
293 { 0xF4, "OPTGROUP" },
300 { 0xFB, "TEMPLATE" },
309 /***** Attribute Start tokens *****/
310 static const value_string wbxml_wmlc10_attrStart_cp0[] = {
311 /* 0x00 -- 0x04 GLOBAL */
312 { 0x05, "ACCEPT-CHARSET=" },
313 { 0x06, "ALIGN='BOTTOM'" },
314 { 0x07, "ALIGN='CENTER'" },
315 { 0x08, "ALIGN='LEFT'" },
316 { 0x09, "ALIGN='MIDDLE'" },
317 { 0x0A, "ALIGN='RIGHT'" },
318 { 0x0B, "ALIGN='TOP'" },
320 { 0x0D, "CONTENT=" },
321 { 0x0E, "DEFAULT=" },
323 { 0x10, "EMPTYOK='FALSE'" },
324 { 0x11, "EMPTYOK='TRUE'" },
328 { 0x15, "IDEFAULT=" },
332 { 0x19, "LOCALSRC=" },
333 { 0x1A, "MAXLENGTH=" },
334 { 0x1B, "METHOD='GET'" },
335 { 0x1C, "METHOD='POST'" },
336 { 0x1D, "MODE='NOWRAP'" },
337 { 0x1E, "MODE='WRAP'" },
338 { 0x1F, "MULTIPLE='FALSE'" },
339 { 0x20, "MULTIPLE='TRUE'" },
341 { 0x22, "NEWCONTEXT='FALSE'" },
342 { 0x23, "NEWCONTEXT='TRUE'" },
343 { 0x24, "ONCLICK=" },
344 { 0x25, "ONENTERBACKWARD=" },
345 { 0x26, "ONENTERFORWARD=" },
346 { 0x27, "ONTIMER=" },
347 { 0x28, "OPTIONAL='FALSE'" },
348 { 0x29, "OPTIONAL='TRUE'" },
350 { 0x2B, "POSTDATA=" },
351 { 0x2C, "PUBLIC='FALSE'" },
352 { 0x2D, "PUBLIC='TRUE'" },
354 { 0x2F, "SENDREFERER='FALSE'" },
355 { 0x30, "SENDREFERER='TRUE'" },
358 { 0x33, "STYLE='LIST'" },
359 { 0x34, "STYLE='SET'" },
360 { 0x35, "TABINDEX=" },
363 { 0x38, "TYPE='ACCEPT'" },
364 { 0x39, "TYPE='DELETE'" },
365 { 0x3A, "TYPE='HELP'" },
366 { 0x3B, "TYPE='PASSWORD'" },
367 { 0x3C, "TYPE='ONCLICK'" },
368 { 0x3D, "TYPE='ONENTERBACKWARD'" },
369 { 0x3E, "TYPE='ONENTERFORWARD'" },
370 { 0x3F, "TYPE='ONTIMER'" },
371 /* 0x40 -- 0x44 GLOBAL */
372 { 0x45, "TYPE='OPTIONS'" },
373 { 0x46, "TYPE='PREV'" },
374 { 0x47, "TYPE='RESET'" },
375 { 0x48, "TYPE='TEXT'" },
376 { 0x49, "TYPE='vnd.'" },
378 { 0x4B, "URL='http://'" },
379 { 0x4C, "URL='https://'" },
380 { 0x4D, "USER-AGENT=" },
384 { 0x51, "xml:lang=" },
389 /***** Attribute Value tokens *****/
390 static const value_string wbxml_wmlc10_attrValue_cp0[] = {
391 /* 0x80 -- 0x84 GLOBAL */
396 { 0x89, "'ACCEPT'" },
397 { 0x8A, "'BOTTOM'" },
399 { 0x8C, "'DELETE'" },
401 { 0x8E, "'http://'" },
402 { 0x8F, "'http://www.'" },
403 { 0x90, "'https://'" },
404 { 0x91, "'https://www.'" },
406 { 0x93, "'MIDDLE'" },
407 { 0x94, "'NOWRAP'" },
408 { 0x95, "'ONCLICK'" },
409 { 0x96, "'ONENTERBACKWARD'" },
410 { 0x97, "'ONENTERFORWARD'" },
411 { 0x98, "'ONTIMER'" },
412 { 0x99, "'OPTIONS'" },
413 { 0x9A, "'PASSWORD'" },
418 { 0x9F, "'UNKNOWN'" },
425 /***** Token code page aggregation *****/
426 static const value_valuestring wbxml_wmlc10_global[] = {
427 { 0, wbxml_wmlc10_global_cp0 },
431 static const value_valuestring wbxml_wmlc10_tags[] = {
432 { 0, wbxml_wmlc10_tags_cp0 },
436 static const value_valuestring wbxml_wmlc10_attrStart[] = {
437 { 0, wbxml_wmlc10_attrStart_cp0 },
441 static const value_valuestring wbxml_wmlc10_attrValue[] = {
442 { 0, wbxml_wmlc10_attrValue_cp0 },
452 * Wireless Markup Language
453 ***************************************/
455 /***** Global extension tokens *****/
456 /* Same as in WML 1.0 */
458 /***** Tag tokens *****/
459 static const value_string wbxml_wmlc11_tags_cp0[] = {
460 /* 0x00 -- 0x04 GLOBAL */
467 { 0x21, "postfield" },
476 { 0x2A, "fieldset" },
486 { 0x34, "optgroup" },
493 { 0x3B, "template" },
502 /***** Attribute Start tokens *****/
503 static const value_string wbxml_wmlc11_attrStart_cp0[] = {
504 /* 0x00 -- 0x04 GLOBAL */
505 { 0x05, "accept-charset=" },
506 { 0x06, "align='bottom'" },
507 { 0x07, "align='center'" },
508 { 0x08, "align='left'" },
509 { 0x09, "align='middle'" },
510 { 0x0A, "align='right'" },
511 { 0x0B, "align='top'" },
513 { 0x0D, "content=" },
516 { 0x10, "emptyok='false'" },
517 { 0x11, "emptyok='true'" },
525 { 0x19, "localsrc=" },
526 { 0x1A, "maxlength=" },
527 { 0x1B, "method='get'" },
528 { 0x1C, "method='post'" },
529 { 0x1D, "mode='nowrap'" },
530 { 0x1E, "mode='wrap'" },
531 { 0x1F, "multiple='false'" },
532 { 0x20, "multiple='true'" },
534 { 0x22, "newcontext='false'" },
535 { 0x23, "newcontext='true'" },
537 { 0x25, "onenterbackward=" },
538 { 0x26, "onenterforward=" },
539 { 0x27, "ontimer=" },
540 { 0x28, "optional='false'" },
541 { 0x29, "optional='true'" },
545 { 0x2F, "sendreferer='false'" },
546 { 0x30, "sendreferer='true'" },
549 { 0x33, "ordered='false'" },
550 { 0x34, "ordered='true'" },
551 { 0x35, "tabindex=" },
554 { 0x38, "type='accept'" },
555 { 0x39, "type='delete'" },
556 { 0x3A, "type='help'" },
557 { 0x3B, "type='password'" },
558 { 0x3C, "type='onpick'" },
559 { 0x3D, "type='onenterbackward'" },
560 { 0x3E, "type='onenterforward'" },
561 { 0x3F, "type='ontimer'" },
562 /* 0x40 -- 0x44 GLOBAL */
563 { 0x45, "type='options'" },
564 { 0x46, "type='prev'" },
565 { 0x47, "type='reset'" },
566 { 0x48, "type='text'" },
567 { 0x49, "type='vnd.'" },
569 { 0x4B, "href='http://'" },
570 { 0x4C, "href='https://'" },
574 { 0x50, "xml:lang=" },
577 { 0x53, "columns=" },
580 { 0x56, "forua='false'" },
581 { 0x57, "forua='true'" },
582 { 0x58, "src='http://'" },
583 { 0x59, "src='https://'" },
584 { 0x5A, "http-equiv=" },
585 { 0x5B, "http-equiv='Content-Type'" },
586 { 0x5C, "content='application/vnd.wap.wmlc;charset='" },
587 { 0x5D, "http-equiv='Expires'" },
592 /***** Attribute Value tokens *****/
593 static const value_string wbxml_wmlc11_attrValue_cp0[] = {
594 /* 0x80 -- 0x84 GLOBAL */
599 { 0x89, "'accept'" },
600 { 0x8A, "'bottom'" },
602 { 0x8C, "'delete'" },
604 { 0x8E, "'http://'" },
605 { 0x8F, "'http://www.'" },
606 { 0x90, "'https://'" },
607 { 0x91, "'https://www.'" },
609 { 0x93, "'middle'" },
610 { 0x94, "'nowrap'" },
611 { 0x95, "'onpick'" },
612 { 0x96, "'onenterbackward'" },
613 { 0x97, "'onenterforward'" },
614 { 0x98, "'ontimer'" },
615 { 0x99, "'options'" },
616 { 0x9A, "'password'" },
621 { 0x9F, "'unknown'" },
628 /***** Token code page aggregation *****/
629 static const value_valuestring wbxml_wmlc11_global[] = {
630 { 0, wbxml_wmlc10_global_cp0 }, /* Same as WML 1.0 */
634 static const value_valuestring wbxml_wmlc11_tags[] = {
635 { 0, wbxml_wmlc11_tags_cp0 },
639 static const value_valuestring wbxml_wmlc11_attrStart[] = {
640 { 0, wbxml_wmlc11_attrStart_cp0 },
644 static const value_valuestring wbxml_wmlc11_attrValue[] = {
645 { 0, wbxml_wmlc11_attrValue_cp0 },
655 * Wireless Markup Language
656 ***************************************/
658 /***** Global extension tokens *****/
659 /* Same as in WML 1.0 */
661 /***** Tag tokens *****/
662 static const value_string wbxml_wmlc12_tags_cp0[] = {
663 /* 0x00 -- 0x04 GLOBAL */
671 { 0x21, "postfield" },
680 { 0x2A, "fieldset" },
690 { 0x34, "optgroup" },
697 { 0x3B, "template" },
706 /***** Attribute Start tokens *****/
707 static const value_string wbxml_wmlc12_attrStart_cp0[] = {
708 /* 0x00 -- 0x04 GLOBAL */
709 { 0x05, "accept-charset=" },
710 { 0x06, "align='bottom'" },
711 { 0x07, "align='center'" },
712 { 0x08, "align='left'" },
713 { 0x09, "align='middle'" },
714 { 0x0A, "align='right'" },
715 { 0x0B, "align='top'" },
717 { 0x0D, "content=" },
720 { 0x10, "emptyok='false'" },
721 { 0x11, "emptyok='true'" },
729 { 0x19, "localsrc=" },
730 { 0x1A, "maxlength=" },
731 { 0x1B, "method='get'" },
732 { 0x1C, "method='post'" },
733 { 0x1D, "mode='nowrap'" },
734 { 0x1E, "mode='wrap'" },
735 { 0x1F, "multiple='false'" },
736 { 0x20, "multiple='true'" },
738 { 0x22, "newcontext='false'" },
739 { 0x23, "newcontext='true'" },
741 { 0x25, "onenterbackward=" },
742 { 0x26, "onenterforward=" },
743 { 0x27, "ontimer=" },
744 { 0x28, "optional='false'" },
745 { 0x29, "optional='true'" },
749 { 0x2F, "sendreferer='false'" },
750 { 0x30, "sendreferer='true'" },
753 { 0x33, "ordered='false'" },
754 { 0x34, "ordered='true'" },
755 { 0x35, "tabindex=" },
758 { 0x38, "type='accept'" },
759 { 0x39, "type='delete'" },
760 { 0x3A, "type='help'" },
761 { 0x3B, "type='password'" },
762 { 0x3C, "type='onpick'" },
763 { 0x3D, "type='onenterbackward'" },
764 { 0x3E, "type='onenterforward'" },
765 { 0x3F, "type='ontimer'" },
766 /* 0x40 -- 0x44 GLOBAL */
767 { 0x45, "type='options'" },
768 { 0x46, "type='prev'" },
769 { 0x47, "type='reset'" },
770 { 0x48, "type='text'" },
771 { 0x49, "type='vnd.'" },
773 { 0x4B, "href='http://'" },
774 { 0x4C, "href='https://'" },
778 { 0x50, "xml:lang=" },
781 { 0x53, "columns=" },
784 { 0x56, "forua='false'" },
785 { 0x57, "forua='true'" },
786 { 0x58, "src='http://'" },
787 { 0x59, "src='https://'" },
788 { 0x5A, "http-equiv=" },
789 { 0x5B, "http-equiv='Content-Type'" },
790 { 0x5C, "content='application/vnd.wap.wmlc;charset='" },
791 { 0x5D, "http-equiv='Expires'" },
792 { 0x5E, "accesskey=" },
793 { 0x5F, "enctype=" },
794 { 0x60, "enctype='application/x-www-form-urlencoded'" },
795 { 0x61, "enctype='multipart/form-data'" },
800 /***** Attribute Value tokens *****/
801 /* Same as in WML 1.1 */
803 /***** Token code page aggregation *****/
804 static const value_valuestring wbxml_wmlc12_global[] = {
805 { 0, wbxml_wmlc10_global_cp0 }, /* Same as WML 1.0 */
809 static const value_valuestring wbxml_wmlc12_tags[] = {
810 { 0, wbxml_wmlc12_tags_cp0 },
814 static const value_valuestring wbxml_wmlc12_attrStart[] = {
815 { 0, wbxml_wmlc12_attrStart_cp0 },
819 static const value_valuestring wbxml_wmlc12_attrValue[] = {
820 { 0, wbxml_wmlc11_attrValue_cp0 }, /* Same as WML 1.1 */
830 * Wireless Markup Language
831 ***************************************/
833 /***** Global extension tokens *****/
834 /* Same as in WML 1.0 */
836 /***** Tag tokens *****/
837 /* Same as in WML 1.2 */
839 /***** Attribute Start tokens *****/
840 static const value_string wbxml_wmlc13_attrStart_cp0[] = {
841 /* 0x00 -- 0x04 GLOBAL */
842 { 0x05, "accept-charset=" },
843 { 0x06, "align='bottom'" },
844 { 0x07, "align='center'" },
845 { 0x08, "align='left'" },
846 { 0x09, "align='middle'" },
847 { 0x0A, "align='right'" },
848 { 0x0B, "align='top'" },
850 { 0x0D, "content=" },
853 { 0x10, "emptyok='false'" },
854 { 0x11, "emptyok='true'" },
862 { 0x19, "localsrc=" },
863 { 0x1A, "maxlength=" },
864 { 0x1B, "method='get'" },
865 { 0x1C, "method='post'" },
866 { 0x1D, "mode='nowrap'" },
867 { 0x1E, "mode='wrap'" },
868 { 0x1F, "multiple='false'" },
869 { 0x20, "multiple='true'" },
871 { 0x22, "newcontext='false'" },
872 { 0x23, "newcontext='true'" },
874 { 0x25, "onenterbackward=" },
875 { 0x26, "onenterforward=" },
876 { 0x27, "ontimer=" },
877 { 0x28, "optional='false'" },
878 { 0x29, "optional='true'" },
882 { 0x2F, "sendreferer='false'" },
883 { 0x30, "sendreferer='true'" },
886 { 0x33, "ordered='false'" },
887 { 0x34, "ordered='true'" },
888 { 0x35, "tabindex=" },
891 { 0x38, "type='accept'" },
892 { 0x39, "type='delete'" },
893 { 0x3A, "type='help'" },
894 { 0x3B, "type='password'" },
895 { 0x3C, "type='onpick'" },
896 { 0x3D, "type='onenterbackward'" },
897 { 0x3E, "type='onenterforward'" },
898 { 0x3F, "type='ontimer'" },
899 /* 0x40 -- 0x44 GLOBAL */
900 { 0x45, "type='options'" },
901 { 0x46, "type='prev'" },
902 { 0x47, "type='reset'" },
903 { 0x48, "type='text'" },
904 { 0x49, "type='vnd.'" },
906 { 0x4B, "href='http://'" },
907 { 0x4C, "href='https://'" },
911 { 0x50, "xml:lang=" },
914 { 0x53, "columns=" },
917 { 0x56, "forua='false'" },
918 { 0x57, "forua='true'" },
919 { 0x58, "src='http://'" },
920 { 0x59, "src='https://'" },
921 { 0x5A, "http-equiv=" },
922 { 0x5B, "http-equiv='Content-Type'" },
923 { 0x5C, "content='application/vnd.wap.wmlc;charset='" },
924 { 0x5D, "http-equiv='Expires'" },
925 { 0x5E, "accesskey=" },
926 { 0x5F, "enctype=" },
927 { 0x60, "enctype='application/x-www-form-urlencoded'" },
928 { 0x61, "enctype='multipart/form-data'" },
929 { 0x62, "xml:space='preserve'" },
930 { 0x63, "xml:space='default'" },
931 { 0x64, "cache-control='no-cache'" },
936 /***** Attribute Value tokens *****/
937 /* Same as in WML 1.1 */
939 /***** Token code page aggregation *****/
940 static const value_valuestring wbxml_wmlc13_global[] = {
941 { 0, wbxml_wmlc10_global_cp0 }, /* Same as WML 1.0 */
945 static const value_valuestring wbxml_wmlc13_tags[] = {
946 { 0, wbxml_wmlc12_tags_cp0 },
950 static const value_valuestring wbxml_wmlc13_attrStart[] = {
951 { 0, wbxml_wmlc13_attrStart_cp0 },
955 static const value_valuestring wbxml_wmlc13_attrValue[] = {
956 { 0, wbxml_wmlc11_attrValue_cp0 }, /* Same as WML 1.1 */
967 ***************************************/
969 /***** Global extension tokens *****/
971 /***** Tag tokens *****/
972 static const value_string wbxml_sic10_tags_cp0[] = {
973 /* 0x00 -- 0x04 GLOBAL */
975 { 0x06, "indication" },
982 /***** Attribute Start tokens *****/
983 static const value_string wbxml_sic10_attrStart_cp0[] = {
984 /* 0x00 -- 0x04 GLOBAL */
985 { 0x05, "action='signal-none'" },
986 { 0x06, "action='signal-low'" },
987 { 0x07, "action='signal-medium'" },
988 { 0x08, "action='signal-high'" },
989 { 0x09, "action='delete'" },
990 { 0x0a, "created=" },
992 { 0x0c, "href='http://'" },
993 { 0x0d, "href='http://www.'" },
994 { 0x0e, "href='https://'" },
995 { 0x0f, "href='https://www.'" },
996 { 0x10, "si-expires=" },
1003 /***** Attribute Value tokens *****/
1004 static const value_string wbxml_sic10_attrValue_cp0[] = {
1005 /* 0x80 -- 0x84 GLOBAL */
1006 { 0x85, "'.com/'" },
1007 { 0x86, "'.edu/'" },
1008 { 0x87, "'.net/'" },
1009 { 0x88, "'.org/'" },
1014 /***** Token code page aggregation *****/
1015 static const value_valuestring wbxml_sic10_tags[] = {
1016 { 0, wbxml_sic10_tags_cp0 },
1020 static const value_valuestring wbxml_sic10_attrStart[] = {
1021 { 0, wbxml_sic10_attrStart_cp0 },
1025 static const value_valuestring wbxml_sic10_attrValue[] = {
1026 { 0, wbxml_sic10_attrValue_cp0 },
1037 ***************************************/
1039 /***** Global extension tokens *****/
1041 /***** Tag tokens *****/
1042 static const value_string wbxml_slc10_tags_cp0[] = {
1043 /* 0x00 -- 0x04 GLOBAL */
1049 /***** Attribute Start tokens *****/
1050 static const value_string wbxml_slc10_attrStart_cp0[] = {
1051 /* 0x00 -- 0x04 GLOBAL */
1052 { 0x05, "action='execute-low'" },
1053 { 0x06, "action='execute-high'" },
1054 { 0x07, "action='cache'" },
1056 { 0x09, "href='http://'" },
1057 { 0x0a, "href='http://www.'" },
1058 { 0x0b, "href='https://'" },
1059 { 0x0c, "href='https://www.'" },
1064 /***** Attribute Value tokens *****/
1065 /* Same as in SI 1.0 */
1067 /***** Token code page aggregation *****/
1068 static const value_valuestring wbxml_slc10_tags[] = {
1069 { 0, wbxml_slc10_tags_cp0 },
1073 static const value_valuestring wbxml_slc10_attrStart[] = {
1074 { 0, wbxml_slc10_attrStart_cp0 },
1078 static const value_valuestring wbxml_slc10_attrValue[] = {
1079 { 0, wbxml_sic10_attrValue_cp0 }, /* Same as SI 1.0 */
1090 ***************************************/
1092 /***** Global extension tokens *****/
1094 /***** Tag tokens *****/
1095 static const value_string wbxml_coc10_tags_cp0[] = {
1096 /* 0x00 -- 0x04 GLOBAL */
1098 { 0x06, "invalidate-object" },
1099 { 0x07, "invalidate-service" },
1104 /***** Attribute Start tokens *****/
1105 static const value_string wbxml_coc10_attrStart_cp0[] = {
1106 /* 0x00 -- 0x04 GLOBAL */
1108 { 0x06, "uri='http://'" },
1109 { 0x07, "uri='http://www.'" },
1110 { 0x08, "uri='https://'" },
1111 { 0x09, "uri='https://www.'" },
1116 /***** Attribute Value tokens *****/
1117 /* Same as in SI 1.0 */
1119 /***** Token code page aggregation *****/
1120 static const value_valuestring wbxml_coc10_tags[] = {
1121 { 0, wbxml_coc10_tags_cp0 },
1125 static const value_valuestring wbxml_coc10_attrStart[] = {
1126 { 0, wbxml_coc10_attrStart_cp0 },
1130 static const value_valuestring wbxml_coc10_attrValue[] = {
1131 { 0, wbxml_sic10_attrValue_cp0 }, /* Same as SI 1.0 */
1141 * Client Provisioning
1142 ***************************************/
1144 /***** Global extension tokens *****/
1146 /***** Tag tokens *****/
1147 static const value_string wbxml_provc10_tags_cp0[] = {
1148 /* 0x00 -- 0x04 GLOBAL */
1149 { 0x05, "wap-provisioningdoc" },
1150 { 0x06, "characteristic" },
1156 /***** Attribute Start tokens *****/
1157 static const value_string wbxml_provc10_attrStart_cp0[] = {
1158 /* 0x00 -- 0x04 GLOBAL */
1161 { 0x07, "name='NAME'" },
1162 { 0x08, "name='NAP-ADDRESS'" },
1163 { 0x09, "name='NAP-ADDRTYPE'" },
1164 { 0x0A, "name='CALLTYPE'" },
1165 { 0x0B, "name='VALIDUNTIL'" },
1166 { 0x0C, "name='AUTHTYPE'" },
1167 { 0x0D, "name='AUTHNAME'" },
1168 { 0x0E, "name='AUTHSECRET'" },
1169 { 0x0F, "name='LINGER'" },
1170 { 0x10, "name='BEARER'" },
1171 { 0x11, "name='NAPID'" },
1172 { 0x12, "name='COUNTRY'" },
1173 { 0x13, "name='NETWORK'" },
1174 { 0x14, "name='INTERNET'" },
1175 { 0x15, "name='PROXY-ID'" },
1176 { 0x16, "name='PROXY-PROVIDER-ID'" },
1177 { 0x17, "name='DOMAIN'" },
1178 { 0x18, "name='PROVURL'" },
1179 { 0x19, "name='PXAUTH-TYPE'" },
1180 { 0x1A, "name='PXAUTH-ID'" },
1181 { 0x1B, "name='PXAUTH-PW'" },
1182 { 0x1C, "name='STARTPAGE'" },
1183 { 0x1D, "name='BASAUTH-ID'" },
1184 { 0x1E, "name='BASAUTH-PW'" },
1185 { 0x1F, "name='PUSHENABLED'" },
1186 { 0x20, "name='PXADDR'" },
1187 { 0x21, "name='PXADDRTYPE'" },
1188 { 0x22, "name='TO-NAPID'" },
1189 { 0x23, "name='PORTNBR'" },
1190 { 0x24, "name='SERVICE'" },
1191 { 0x25, "name='LINKSPEED'" },
1192 { 0x26, "name='DNLINKSPEED'" },
1193 { 0x27, "name='LOCAL-ADDR'" },
1194 { 0x28, "name='LOCAL-ADDRTYPE'" },
1195 { 0x29, "name='CONTEXT-ALLOW'" },
1196 { 0x2A, "name='TRUST'" },
1197 { 0x2B, "name='MASTER'" },
1198 { 0x2C, "name='SID'" },
1199 { 0x2D, "name='SOC'" },
1200 { 0x2E, "name='WSP-VERSION'" },
1201 { 0x2F, "name='PHYSICAL-PROXY-ID'" },
1202 { 0x30, "name='CLIENT-ID'" },
1203 { 0x31, "name='DELIVERY-ERR-SDU'" },
1204 { 0x32, "name='DELIVERY-ORDER'" },
1205 { 0x33, "name='TRAFFIC-CLASS'" },
1206 { 0x34, "name='MAX-SDU-SIZE'" },
1207 { 0x35, "name='MAX-BITRATE-UPLINK'" },
1208 { 0x36, "name='MAX-BITRATE-DNLINK'" },
1209 { 0x37, "name='RESIDUAL-BER'" },
1210 { 0x38, "name='SDU-ERROR-RATIO'" },
1211 { 0x39, "name='TRAFFIC-HANDL-PRIO'" },
1212 { 0x3A, "name='TRANSFER-DELAY'" },
1213 { 0x3B, "name='GUARANTEED-BITRATE-UPLINK'" },
1214 { 0x3C, "name='GUARANTEED-BITRATE-DNLINK'" },
1216 /* 0x40 -- 0x44 GLOBAL */
1217 { 0x45, "version=" },
1218 { 0x46, "version='1.0'" },
1221 { 0x51, "type='PXLOGICAL'" },
1222 { 0x52, "type='PXPHYSICAL'" },
1223 { 0x53, "type='PORT'" },
1224 { 0x54, "type='VALIDITY'" },
1225 { 0x55, "type='NAPDEF'" },
1226 { 0x56, "type='BOOTSTRAP'" },
1227 { 0x57, "type='VENDORCONFIG'" },
1228 { 0x58, "type='CLIENTIDENTITY'" },
1229 { 0x59, "type='PXAUTHINFO'" },
1230 { 0x5A, "type='NAPAUTHINFO'" },
1235 /***** Attribute Start tokens *****/
1236 static const value_string wbxml_provc10_attrValue_cp0[] = {
1237 /* 0x80 -- 0x84 GLOBAL */
1241 { 0x88, "'ALPHA'" },
1243 { 0x8A, "'SCODE'" },
1244 { 0x8B, "'TETRA-ITSI'" },
1247 { 0x90, "'ANALOG-MODEM'" },
1248 { 0x91, "'V.120'" },
1249 { 0x92, "'V.110'" },
1251 { 0x94, "'BIT-TRANSPARENT'" },
1252 { 0x95, "'DIRECT-ASYNCHRONOUS-DATA-SERVICE'" },
1256 { 0x9C, "'HTTP-BASIC'" },
1257 { 0x9D, "'HTTP-DIGEST'" },
1258 { 0x9E, "'WTLS-SS'" },
1260 { 0xA2, "'GSM-USSD'" },
1261 { 0xA3, "'GSM-SMS'" },
1262 { 0xA4, "'ANSI-136-GUTS'" },
1263 { 0xA5, "'IS-95-CDMA-SMS'" },
1264 { 0xA6, "'IS-95-CDMA-CSD'" },
1265 { 0xA7, "'IS-95-CDMA-PACKET'" },
1266 { 0xA8, "'ANSI-136-CSD'" },
1267 { 0xA9, "'ANSI-136-GPRS'" },
1268 { 0xAA, "'GSM-CSD'" },
1269 { 0xAB, "'GSM-GPRS'" },
1270 { 0xAC, "'AMPS-CDPD'" },
1271 { 0xAD, "'PDC-CSD'" },
1272 { 0xAE, "'PDC-PACKET'" },
1273 { 0xAF, "'IDEN-SMS'" },
1274 { 0xB0, "'IDEN-CSD'" },
1275 { 0xB1, "'IDEN-PACKET'" },
1276 { 0xB2, "'FLEX/REFLEX'" },
1277 { 0xB3, "'PHS-SMS'" },
1278 { 0xB4, "'PHS-CSD'" },
1279 { 0xB5, "'TETRA-SDS'" },
1280 { 0xB6, "'TETRA-PACKET'" },
1281 { 0xB7, "'ANSI-136-GHOST'" },
1282 { 0xB8, "'MOBITEX-MPAK'" },
1284 /* 0xC0 -- 0xC4 GLOBAL */
1285 { 0xC5, "'AUTOBAUDING'" },
1287 { 0xCA, "'CL-WSP'" },
1288 { 0xCB, "'CO-WSP'" },
1289 { 0xCC, "'CL-SEC-WSP'" },
1290 { 0xCD, "'CO-SEC-WSP'" },
1291 { 0xCE, "'CL-SEC-WTA'" },
1292 { 0xCF, "'CO-SEC-WTA'" },
1297 /***** Token code page aggregation *****/
1298 static const value_valuestring wbxml_provc10_tags[] = {
1299 { 0, wbxml_provc10_tags_cp0 },
1303 static const value_valuestring wbxml_provc10_attrStart[] = {
1304 { 0, wbxml_provc10_attrStart_cp0 },
1308 static const value_valuestring wbxml_provc10_attrValue[] = {
1309 { 0, wbxml_provc10_attrValue_cp0 },
1319 * Email Notification
1320 ***************************************/
1322 /***** Global extension tokens *****/
1324 /***** Tag tokens *****/
1325 static const value_string wbxml_emnc10_tags_cp0[] = {
1326 /* 0x00 -- 0x04 GLOBAL */
1332 /***** Attribute Start tokens *****/
1333 static const value_string wbxml_emnc10_attrStart_cp0[] = {
1334 /* 0x00 -- 0x04 GLOBAL */
1335 { 0x05, "timestamp=" },
1336 { 0x06, "mailbox=" },
1337 { 0x07, "mailbox='mailat:'" },
1338 { 0x08, "mailbox='pop://'" },
1339 { 0x09, "mailbox='imap://'" },
1340 { 0x0a, "mailbox='http://'" },
1341 { 0x0b, "mailbox='http://www.'" },
1342 { 0x0c, "mailbox='https://'" },
1343 { 0x0D, "mailbox='https://www.'" },
1348 /***** Attribute Value tokens *****/
1349 /* Same as in SI 1.0 */
1351 /***** Token code page aggregation *****/
1352 static const value_valuestring wbxml_emnc10_tags[] = {
1353 { 0, wbxml_emnc10_tags_cp0 },
1357 static const value_valuestring wbxml_emnc10_attrStart[] = {
1358 { 0, wbxml_emnc10_attrStart_cp0 },
1362 static const value_valuestring wbxml_emnc10_attrValue[] = {
1363 { 0, wbxml_sic10_attrValue_cp0 }, /* Same as SI 1.0 */
1373 * SyncML Representation Protocol
1374 ***************************************/
1376 /***** Global extension tokens *****/
1378 /***** Tag tokens *****/
1379 static const value_string wbxml_syncmlc10_tags_cp0[] = { /* SyncML 1.0 */
1380 /* 0x00 -- 0x04 GLOBAL */
1383 { 0x07, "Archive" },
1398 { 0x16, "LocName" },
1401 { 0x19, "MapItem" },
1406 { 0x1E, "NoResults" },
1408 { 0x20, "Replace" },
1409 { 0x21, "RespURI" },
1410 { 0x22, "Results" },
1412 { 0x24, "Sequence" },
1413 { 0x25, "SessionID" },
1416 { 0x28, "SourceRef" },
1419 { 0x2B, "SyncBody" },
1420 { 0x2C, "SyncHdr" },
1423 { 0x2F, "TargetRef" },
1424 /* 0x30 - Reserved */
1426 { 0x32, "VerProto" },
1431 static const value_string wbxml_syncmlc10_tags_cp1[] = { /* MetInf 1.0 */
1432 /* 0x00 -- 0x04 GLOBAL */
1437 { 0x09, "FreeMem" },
1440 { 0x0C, "MaxMsgSize" },
1444 { 0x10, "NextNonce" },
1445 { 0x11, "SharedMem" },
1448 { 0x14, "Version" },
1453 /***** Attribute Start tokens *****/
1455 /***** Attribute Value tokens *****/
1457 /***** Token code page aggregation *****/
1458 static const value_valuestring wbxml_syncmlc10_tags[] = {
1459 { 0, wbxml_syncmlc10_tags_cp0 }, /* -//SYNCML//DTD SyncML 1.0//EN */
1460 { 0, wbxml_syncmlc10_tags_cp1 }, /* -//SYNCML//DTD MetInf 1.0//EN */
1470 * SyncML Representation Protocol
1471 ***************************************/
1473 /***** Global extension tokens *****/
1475 /***** Tag tokens *****/
1476 static const value_string wbxml_syncmlc11_tags_cp0[] = { /* SyncML 1.1 */
1477 /* 0x00 -- 0x04 GLOBAL */
1480 { 0x07, "Archive" },
1495 { 0x16, "LocName" },
1498 { 0x19, "MapItem" },
1503 { 0x1e, "NoResults" },
1505 { 0x20, "Replace" },
1506 { 0x21, "RespURI" },
1507 { 0x22, "Results" },
1509 { 0x24, "Sequence" },
1510 { 0x25, "SessionID" },
1513 { 0x28, "SourceRef" },
1516 { 0x2b, "SyncBody" },
1517 { 0x2c, "SyncHdr" },
1520 { 0x2f, "TargetRef" },
1521 /* 0x30 - Reserved */
1523 { 0x32, "VerProto" },
1524 { 0x33, "NumberOfChanges" },
1525 { 0x34, "MoreData" },
1530 static const value_string wbxml_syncmlc11_tags_cp1[] = { /* MetInf 1.1 */
1531 /* 0x00 -- 0x04 GLOBAL */
1536 { 0x09, "FreeMem" },
1539 { 0x0C, "MaxMsgSize" },
1543 { 0x10, "NextNonce" },
1544 { 0x11, "SharedMem" },
1547 { 0x14, "Version" },
1548 { 0x15, "MaxObjSize" },
1553 /***** Attribute Start tokens *****/
1555 /***** Attribute Value tokens *****/
1557 /***** Token code page aggregation *****/
1558 static const value_valuestring wbxml_syncmlc11_tags[] = {
1559 { 0, wbxml_syncmlc11_tags_cp0 }, /* -//SYNCML//DTD SyncML 1.1//EN */
1560 { 0, wbxml_syncmlc11_tags_cp1 }, /* -//SYNCML//DTD MetInf 1.1//EN */
1571 ***************************************/
1573 /***** Global extension tokens *****/
1575 /***** Tag tokens *****/
1576 static const value_string wbxml_channelc10_tags_cp0[] = {
1577 /* 0x00 -- 0x04 GLOBAL */
1578 { 0x05, "channel" },
1580 { 0x07, "abstract" },
1581 { 0x08, "resource" },
1586 /***** Attribute Start tokens *****/
1587 static const value_string wbxml_channelc10_attrStart_cp0[] = {
1588 /* 0x00 -- 0x04 GLOBAL */
1589 { 0x05, "maxspace" },
1592 { 0x08, "href='http://'" },
1593 { 0x09, "href='https://'" },
1594 { 0x0A, "lastmod" },
1597 { 0x0D, "success" },
1598 { 0x0E, "success='http://'" },
1599 { 0x0F, "success='https://'" },
1600 { 0x10, "failure" },
1601 { 0x11, "failure='http://'" },
1602 { 0x12, "failure='https://'" },
1603 { 0x13, "EventId" },
1608 /***** Attribute Value tokens *****/
1610 /***** Token code page aggregation *****/
1611 static const value_valuestring wbxml_channelc10_tags[] = {
1612 { 0, wbxml_channelc10_tags_cp0 },
1616 static const value_valuestring wbxml_channelc10_attrStart[] = {
1617 { 0, wbxml_channelc10_attrStart_cp0 },
1625 /********************** WBXML token mapping aggregation **********************/
1628 /* The following structure links content types to their token mapping and
1629 * contains arrays of pointers to value_string arrays (one per code page).
1631 typedef struct _wbxml_token_map {
1632 const guint32 publicid; /* WBXML DTD number - see WINA */
1633 const guint8 defined; /* Are there mapping tables defined */
1634 const value_valuestring *global; /* Global token map */
1635 const value_valuestring *tags; /* Tag token map */
1636 const value_valuestring *attrStart; /* Attribute Start token map */
1637 const value_valuestring *attrValue; /* Attribute Value token map */
1640 static const wbxml_token_map *wbxml_content_map (guint32 publicid);
1643 ** Aggregation of content type and aggregated code pages
1644 ** Content type map lookup will stop at the 1st entry with 2nd member = FALSE
1646 static const wbxml_token_map map[] = {
1647 #ifdef Test_the_parsers_without_token_mappings
1648 { 0, FALSE, NULL, NULL, NULL, NULL },
1650 { 0x02, TRUE, /* WML 1.0 */
1651 wbxml_wmlc10_global,
1653 wbxml_wmlc10_attrStart,
1654 wbxml_wmlc10_attrValue
1656 #ifdef remove_directive_and_set_TRUE_if_mapping_available
1657 { 0x03, FALSE, /* WTA 1.0 (deprecated) */
1658 NULL, NULL, NULL, NULL
1661 { 0x04, TRUE, /* WML 1.1 */
1662 wbxml_wmlc11_global,
1664 wbxml_wmlc11_attrStart,
1665 wbxml_wmlc11_attrValue
1667 { 0x05, TRUE, /* SI 1.0 */
1668 NULL, /* wbxml_sic10_global - does not exist */
1670 wbxml_sic10_attrStart,
1671 wbxml_sic10_attrValue
1673 { 0x06, TRUE, /* SL 1.0 */
1674 NULL, /* wbxml_slc10_global - does not exist */
1676 wbxml_slc10_attrStart,
1677 wbxml_slc10_attrValue
1679 { 0x07, TRUE, /* CO 1.0 */
1680 NULL, /* wbxml_coc10_global - does not exist */
1682 wbxml_coc10_attrStart,
1683 wbxml_coc10_attrValue
1685 { 0x08, TRUE, /* CHANNEL 1.0 (deprecated) */
1686 NULL, /* wbxml_channelc10_global - does not exist */
1687 wbxml_channelc10_tags,
1688 wbxml_channelc10_attrStart,
1689 NULL, /* wbxml_channelc10_attrValue - does not exist */
1691 { 0x09, TRUE, /* WML 1.2 */
1692 wbxml_wmlc12_global,
1694 wbxml_wmlc12_attrStart,
1695 wbxml_wmlc12_attrValue
1697 { 0x0A, TRUE, /* WML 1.3 */
1698 wbxml_wmlc13_global,
1700 wbxml_wmlc13_attrStart,
1701 wbxml_wmlc13_attrValue
1703 { 0x0B, TRUE, /* PROV 1.0 */
1704 NULL, /* wbxml_provc10_global - does not exist */
1706 wbxml_provc10_attrStart,
1707 wbxml_provc10_attrValue
1709 #ifdef remove_directive_and_set_TRUE_if_mapping_available
1710 { 0x0C, FALSE, /* WTA-WML 1.2 */
1711 NULL, NULL, NULL, NULL
1714 { 0x0D, TRUE, /* EMN 1.0 */
1715 NULL, /* wbxml_emnc10_global - does not exist */
1717 wbxml_emnc10_attrStart,
1718 wbxml_emnc10_attrValue
1720 #ifdef remove_directive_and_set_TRUE_if_mapping_available
1721 { 0x0E, FALSE, /* DRMREL 1.0 */
1722 NULL, NULL, NULL, NULL
1725 { 0x0FD1, TRUE, /* SyncML 1.0 */
1726 NULL, /* wbxml_syncmlc10_global - does not exist */
1727 wbxml_syncmlc10_tags,
1728 NULL, /* wbxml_syncmlc10_attrStart - does not exist */
1729 NULL, /* wbxml_syncmlc10_attrValue - does not exist */
1731 { 0x0FD3, TRUE, /* SyncML 1.1 */
1732 NULL, /* wbxml_syncmlc11_global - does not exist */
1733 wbxml_syncmlc11_tags,
1734 NULL, /* wbxml_syncmlc11_attrStart - does not exist */
1735 NULL, /* wbxml_syncmlc11_attrValue - does not exist */
1737 { 0x1108, TRUE, /* Phone.com - WML+ 1.1 */
1738 /* Note: I assumed WML+ 1.1 would be not that different from WML 1.1,
1739 * the real mapping should come from Phone.com (OpenWave)! */
1740 wbxml_wmlc11_global, /* Not 100% true */
1741 wbxml_wmlc11_tags, /* Not 100% true */
1742 wbxml_wmlc11_attrStart, /* Not 100% true */
1743 wbxml_wmlc11_attrValue /* Not 100% true */
1745 { 0x110D, TRUE, /* Phone.com - WML+ 1.3 */
1746 /* Note: I assumed WML+ 1.3 would be not that different from WML 1.3,
1747 * the real mapping should come from Phone.com (OpenWave)! */
1748 wbxml_wmlc13_global, /* Not 100% true */
1749 wbxml_wmlc13_tags, /* Not 100% true */
1750 wbxml_wmlc13_attrStart, /* Not 100% true */
1751 wbxml_wmlc13_attrValue /* Not 100% true */
1754 { 0, FALSE, NULL, NULL, NULL, NULL }
1758 /* WBXML content token mapping depends on the following parameters:
1759 * - Content type (guint32)
1760 * - Token type (global, tags, attrStart, attrValue)
1761 * - Code page for tag and attribute
1763 * This results in the following steps:
1764 * 1. Retrieve content type mapping
1765 * 2. If exists, retrieve token type mapping
1766 * 3. If exists, retrieve required code page
1767 * 4. If exists, retrieve token mapping
1770 /* Return token mapping for a given content mapping entry. */
1772 map_token (const value_valuestring *token_map, guint8 codepage, guint8 token) {
1773 const value_string *vs;
1776 if (token_map) { /* Found map */
1777 if ((vs = val_to_valstr (codepage, token_map))) {
1778 /* Found codepage map */
1779 s = match_strval (token, vs);
1780 if (s) /* Found valid token */
1782 /* No valid token mapping in specified code page of token map */
1783 return "(Requested token not defined for this content type)";
1785 /* There is no token map entry for the requested code page */
1786 return "(Requested token code page not defined for this content type)";
1788 /* The token map does not exist */
1789 return "(Requested token map not defined for this content type)";
1793 /* Returns a pointer to the WBXML token map for the given WBXML public
1794 * identifier value (see WINA for a table with defined identifiers). */
1795 static const wbxml_token_map *wbxml_content_map (guint32 publicid) {
1798 while (map[i].defined) {
1799 if (map[i].publicid == publicid)
1807 /************************** Function prototypes **************************/
1811 dissect_wbxml(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
1814 proto_register_wbxml(void);
1816 /* Parse and display the WBXML string table */
1818 show_wbxml_string_table (proto_tree *tree, tvbuff_t *tvb, guint32 str_tbl,
1819 guint32 str_tbl_len);
1821 /* Return a pointer to the string in the string table.
1822 * Can also be hacked for inline string retrieval. */
1824 strtbl_lookup (tvbuff_t *tvb, guint32 str_tbl, guint32 offset, guint32 *len);
1826 /* Parse data while in STAG state */
1828 parse_wbxml_tag (proto_tree *tree, tvbuff_t *tvb, guint32 offset,
1829 guint32 str_tbl, guint8 *level,
1830 guint32 *parsed_length);
1832 /* Parse data while in STAG state;
1833 * interpret tokens as defined by content type */
1835 parse_wbxml_tag_defined (proto_tree *tree, tvbuff_t *tvb, guint32 offset,
1836 guint32 str_tbl, guint8 *level,
1837 guint32 *parsed_length,
1838 const wbxml_token_map *map);
1840 /* Parse data while in ATTR state */
1842 parse_wbxml_attribute_list (proto_tree *tree, tvbuff_t *tvb,
1843 guint32 offset, guint32 str_tbl, guint8 level,
1844 guint32 *parsed_length);
1846 /* Parse data while in ATTR state;
1847 * interpret tokens as defined by content type */
1849 parse_wbxml_attribute_list_defined (proto_tree *tree, tvbuff_t *tvb,
1850 guint32 offset, guint32 str_tbl, guint8 level,
1851 guint32 *parsed_length,
1852 const wbxml_token_map *map);
1855 /****************** WBXML protocol dissection functions ******************/
1858 /* Code to actually dissect the packets */
1860 dissect_wbxml(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1862 /* Set up structures needed to add the protocol subtree and manage it */
1864 proto_tree *wbxml_tree; /* Main WBXML tree */
1865 proto_tree *wbxml_str_tbl_tree; /* String table subtree */
1866 proto_tree *wbxml_content_tree; /* Content subtree */
1872 guint32 charset_len;
1874 guint32 publicid_index = 0;
1875 guint32 publicid_len;
1877 guint32 str_tbl_len;
1878 guint8 level = 0; /* WBXML recursion level */
1879 const wbxml_token_map *content_map = NULL;
1883 * Version 1.0: version publicid strtbl BODY
1884 * Version 1.x: version publicid charset strtbl BODY
1886 * Last valid format: WBXML 1.3
1888 switch ( version = tvb_get_guint8 (tvb, 0) ) {
1889 case 0x00: /* WBXML/1.0 */
1892 case 0x01: /* WBXML/1.1 */
1893 case 0x02: /* WBXML/1.2 */
1894 case 0x03: /* WBXML/1.3 */
1901 if (check_col(pinfo->cinfo, COL_INFO))
1902 col_append_fstr(pinfo->cinfo, COL_INFO, " (WBXML %s:",
1903 match_strval (version, vals_wbxml_versions));
1905 /* In the interest of speed, if "tree" is NULL, don't do any work not
1906 necessary to generate protocol tree items. */
1908 /* create display subtree for the protocol */
1909 ti = proto_tree_add_item (tree, proto_wbxml, tvb, 0, -1, FALSE);
1910 wbxml_tree = proto_item_add_subtree(ti, ett_wbxml);
1913 proto_tree_add_uint (wbxml_tree, hf_wbxml_version,
1914 tvb, 0, 1, version);
1917 publicid = tvb_get_guintvar(tvb, 1, &publicid_len);
1918 if (publicid) { /* Known Public ID */
1919 if (check_col(pinfo->cinfo, COL_INFO))
1920 col_append_fstr(pinfo->cinfo, COL_INFO, " Public ID \"%s\")",
1921 match_strval (publicid, vals_wbxml_public_ids));
1922 proto_tree_add_uint(wbxml_tree, hf_wbxml_public_id_known,
1923 tvb, 1, publicid_len, publicid);
1924 } else { /* Public identifier in string table */
1925 publicid_index = tvb_get_guintvar (tvb, 1+publicid_len, &len);
1926 publicid_len += len;
1928 offset = 1 + publicid_len;
1930 /* Version-specific handling of Charset */
1931 switch ( version ) {
1932 case 0x00: /* WBXML/1.0 */
1936 case 0x01: /* WBXML/1.1 */
1937 case 0x02: /* WBXML/1.2 */
1938 case 0x03: /* WBXML/1.3 */
1940 charset = tvb_get_guintvar (tvb, offset, &charset_len);
1941 offset += charset_len;
1944 default: /* Impossible since return already earlier */
1948 /* String table: read string table length in bytes */
1949 str_tbl_len = tvb_get_guintvar (tvb, offset, &len);
1950 str_tbl = offset + len; /* Start of 1st string in string table */
1952 /* Now we can add public ID, charset (if available),
1953 * and string table */
1954 if ( ! publicid ) { /* Read Public ID from string table */
1955 token = strtbl_lookup (tvb, str_tbl, publicid_index, NULL);
1956 if (check_col(pinfo->cinfo, COL_INFO))
1957 col_append_fstr(pinfo->cinfo, COL_INFO, " Public ID \"%s\")",
1959 proto_tree_add_string (wbxml_tree, hf_wbxml_public_id_literal,
1960 tvb, 1, publicid_len, token?token:"[NULL STRING]");
1962 if ( version ) { /* Charset */
1963 proto_tree_add_uint (wbxml_tree, hf_wbxml_charset,
1964 tvb, 1+publicid_len, charset_len, charset);
1967 ti = proto_tree_add_text(wbxml_tree,
1968 tvb, offset, len + str_tbl_len, "String table: %u bytes",
1971 if (wbxml_tree && str_tbl_len) { /* Display string table as subtree */
1972 wbxml_str_tbl_tree = proto_item_add_subtree (ti,
1974 show_wbxml_string_table (wbxml_str_tbl_tree, tvb,
1975 str_tbl, str_tbl_len);
1978 /* Data starts HERE */
1979 offset += len + str_tbl_len;
1981 /* The WBXML BODY starts here */
1982 ti = proto_tree_add_text (wbxml_tree, tvb, offset, -1,
1983 "Data representation");
1984 wbxml_content_tree = proto_item_add_subtree (ti, ett_wbxml_content);
1986 /* The parse_wbxml_X() functions will process the content correctly,
1987 * irrespective of the WBXML version used. For the WBXML body, this
1988 * means that there is a different processing for the global token
1989 * RESERVED_2 (WBXML 1.0) or OPAQUE (WBXML 1.x with x > 0). */
1990 if (wbxml_tree) { /* Show only if visible */
1992 /* Retrieve the content token mapping if available */
1993 content_map = wbxml_content_map (publicid);
1995 /* Is there a defined token mapping for publicid? */
1996 if (content_map->defined) {
1997 proto_tree_add_text (wbxml_content_tree, tvb,
1999 "Level | State | Codepage "
2000 "| WBXML Token Description "
2002 parse_wbxml_tag_defined (wbxml_content_tree,
2003 tvb, offset, str_tbl, &level,
2008 proto_tree_add_text (wbxml_content_tree, tvb,
2010 "[Rendering of this content type"
2011 " not (yet) supported]");
2013 /* Default: WBXML only, no interpretation of the content */
2014 proto_tree_add_text (wbxml_content_tree, tvb, offset, -1,
2015 "Level | State | Codepage "
2016 "| WBXML Token Description "
2018 parse_wbxml_tag (wbxml_content_tree, tvb, offset,
2019 str_tbl, &level, &len);
2022 proto_tree_add_text (wbxml_content_tree, tvb, offset, -1,
2023 "WBXML 1.0 decoding not (yet) supported");
2030 /* Return a pointer to the string in the string table.
2031 * Can also be hacked for inline string retrieval. */
2033 strtbl_lookup (tvbuff_t *tvb, guint32 str_tbl, guint32 offset, guint32 *len)
2035 if (len) { /* The "hack" call for inline string reading */
2036 *len = tvb_strsize (tvb, str_tbl+offset);
2037 return tvb_get_ptr (tvb, str_tbl+offset, *len);
2038 } else { /* Normal string table reading */
2039 return tvb_get_ptr (tvb, str_tbl+offset,
2040 tvb_strsize (tvb, str_tbl+offset));
2045 /* Parse and display the WBXML string table (in a 3-column table format).
2046 * This function displays:
2047 * - the offset in the string table,
2048 * - the length of the string
2052 show_wbxml_string_table (proto_tree *tree, tvbuff_t *tvb, guint32 str_tbl,
2053 guint32 str_tbl_len)
2055 guint32 off = str_tbl;
2057 guint32 end = str_tbl + str_tbl_len;
2060 proto_tree_add_text (tree, tvb, off, end,
2061 "Start | Length | String");
2063 /* Hack the string table lookup function */
2064 str = strtbl_lookup (tvb, off, 0, &len);
2065 proto_tree_add_text (tree, tvb, off, len,
2067 off - str_tbl, len, str);
2073 /* Indentation code is based on a static const array of space characters.
2074 * At least one single space is returned */
2075 static const char indent_buffer[514] = " "
2084 ; /* Generate XML indentation (length = 1 + 2 * 256 + 1 for '\0') */
2086 static const char * Indent (guint8 level) {
2087 return indent_buffer + (512 - 2 * (level));
2091 /********************
2092 * WBXML tag tokens *
2093 ********************
2095 * Bit Mask : Example
2096 * -------------------
2097 * 00.. .... : <tag />
2104 * atrtribute1="value1"
2105 * atrtribute2="value2"
2109 * atrtribute1="value1"
2110 * atrtribute2="value2"
2116 * - An XML PI is parsed as an attribute list (same syntax).
2117 * - A code page switch only applies to the single token that follows.
2121 /* This function parses the WBXML and maps known token interpretations
2122 * to the WBXML tokens. As a result, the original XML document can be
2123 * recreated. Indentation is generated in order to ease reading.
2125 * Attribute parsing is done in parse_wbxml_attribute_list_defined().
2127 * The wbxml_token_map entry *map contains the actual token mapping.
2129 * NOTE: In order to parse the content, some recursion is required.
2130 * However, for performance reasons, recursion has been avoided
2131 * where possible (tags without content within tags with content).
2132 * This is achieved by means of the parsing_tag_content and tag_save*
2135 * NOTE: See above for known token mappings.
2137 * NOTE: As tags can be opened and closed, a tag representation lookup
2138 * may happen once or twice for a given tag. For efficiency reasons,
2139 * the literal tag value is stored and used throughout the code.
2140 * With the introduction of code page support, this solution is robust
2141 * as the lookup only occurs once, removing the need for storage of
2142 * the used code page.
2145 parse_wbxml_tag_defined (proto_tree *tree, tvbuff_t *tvb, guint32 offset,
2146 guint32 str_tbl, guint8 *level,
2147 guint32 *parsed_length,
2148 const wbxml_token_map *map)
2150 guint32 tvb_len = tvb_reported_length (tvb);
2151 guint32 off = offset;
2157 guint32 tag_len; /* Length of the index (uintvar) from a LITERAL tag */
2158 guint8 tag_save_known = 0; /* Will contain peek & 0x3F (tag identity) */
2159 guint8 tag_new_known = 0; /* Will contain peek & 0x3F (tag identity) */
2160 const char *tag_save_literal; /* Will contain the LITERAL tag identity */
2161 const char *tag_new_literal; /* Will contain the LITERAL tag identity */
2162 guint8 codepage_stag = 0; /* Initial codepage in state = STAG */
2163 guint8 parsing_tag_content = FALSE; /* Are we parsing content from a
2164 tag with content: <x>Content</x>
2166 The initial state is FALSE.
2167 This state will trigger recursion. */
2168 tag_save_literal = NULL; /* Prevents compiler warning */
2171 printf ("WBXML - parse_wbxml_tag_defined (level = %d, offset = %d)\n",
2174 while (off < tvb_len) {
2175 peek = tvb_get_guint8 (tvb, off);
2177 printf("WBXML - STAG: level = %3d, peek = 0x%02X, off = %d, "
2179 *level, peek, off, tvb_len);
2181 if ((peek & 0x3F) < 4) switch (peek) { /* Global tokens in state = STAG
2182 but not the LITERAL tokens */
2183 case 0x00: /* SWITCH_PAGE */
2184 codepage_stag = tvb_get_guint8 (tvb, off+1);
2185 proto_tree_add_text (tree, tvb, off, 2,
2186 " | Tag | T 0->%3d "
2187 "| SWITCH_PAGE (Tag code page) "
2192 case 0x01: /* END: only possible for Tag with Content */
2193 if (tag_save_known) { /* Known TAG */
2194 proto_tree_add_text (tree, tvb, off, 1,
2196 "| END (Known Tag 0x%02X) "
2198 *level, tag_save_known, Indent (*level),
2199 tag_save_literal); /* We already looked it up! */
2200 } else { /* Literal TAG */
2201 proto_tree_add_text (tree, tvb, off, 1,
2203 "| END (Literal Tag) "
2205 *level, Indent (*level),
2210 *parsed_length = off - offset;
2211 /* Reset code page: not needed as return from recursion */
2214 case 0x02: /* ENTITY */
2215 ent = tvb_get_guintvar (tvb, off+1, &len);
2216 proto_tree_add_text (tree, tvb, off, 1+len,
2220 *level, Indent (*level), ent);
2223 case 0x03: /* STR_I */
2224 /* Hack the string table lookup function */
2225 str = strtbl_lookup (tvb, off+1, 0, &len);
2226 proto_tree_add_text (tree, tvb, off, 1+len,
2228 "| STR_I (Inline string) "
2230 *level, Indent(*level), str);
2233 case 0x40: /* EXT_I_0 */
2234 case 0x41: /* EXT_I_1 */
2235 case 0x42: /* EXT_I_2 */
2236 /* Extension tokens */
2237 /* Hack the string table lookup function */
2238 str = strtbl_lookup (tvb, off+1, 0, &len);
2239 if (codepage_stag) { /* Not default code page */
2240 proto_tree_add_text (tree, tvb, off, 1+len,
2241 " %3d | Tag | T %3d->0 "
2242 "| EXT_I_%1x (Extension Token) "
2244 *level, codepage_stag, peek & 0x0f, Indent (*level),
2245 map_token (map->global, codepage_stag, peek), str);
2246 /* Reset code page */
2248 } else { /* Code page 0 */
2249 proto_tree_add_text (tree, tvb, off, 1+len,
2251 "| EXT_I_%1x (Extension Token) "
2253 *level, peek & 0x0f, Indent (*level),
2254 map_token (map->global, codepage_stag, peek), str);
2259 proto_tree_add_text (tree, tvb, off, 1,
2261 "| PI (XML Processing Instruction) "
2263 *level, Indent (*level));
2264 parse_wbxml_attribute_list_defined (tree, tvb, off, str_tbl,
2267 proto_tree_add_text (tree, tvb, off-1, 1,
2271 *level, Indent (*level));
2273 case 0x80: /* EXT_T_0 */
2274 case 0x81: /* EXT_T_1 */
2275 case 0x82: /* EXT_T_2 */
2276 /* Extension tokens */
2277 index = tvb_get_guintvar (tvb, off+1, &len);
2278 str = strtbl_lookup (tvb, str_tbl, index, NULL);
2279 if (codepage_stag) { /* Not default code page */
2280 proto_tree_add_text (tree, tvb, off, 1+len,
2281 " %3d | Tag | T %3d->0 "
2282 "| EXT_T_%1x (Extension Token) "
2284 *level, codepage_stag, peek & 0x0f, Indent (*level),
2285 map_token (map->global, codepage_stag, peek), str);
2286 /* Reset code page */
2288 } else { /* Code page 0 */
2289 proto_tree_add_text (tree, tvb, off, 1+len,
2291 "| EXT_T_%1x (Extension Token) "
2293 *level, peek & 0x0f, Indent (*level),
2294 map_token (map->global, codepage_stag, peek), str);
2298 case 0x83: /* STR_T */
2299 index = tvb_get_guintvar (tvb, off+1, &len);
2300 str = strtbl_lookup (tvb, str_tbl, index, NULL);
2301 proto_tree_add_text (tree, tvb, off, 1+len,
2303 "| STR_T (Tableref string) "
2305 *level, Indent (*level), str);
2308 case 0xC0: /* EXT_0 */
2309 case 0xC1: /* EXT_1 */
2310 case 0xC2: /* EXT_2 */
2311 /* Extension tokens */
2312 if (codepage_stag) { /* Not default code page */
2313 proto_tree_add_text (tree, tvb, off, 1,
2314 " %3d | Tag | T %3d->0 "
2315 "| EXT_%1x (Extension Token) "
2317 *level, codepage_stag, peek & 0x0f, Indent (*level),
2318 map_token (map->global, codepage_stag, peek));
2319 /* Reset code page */
2321 } else { /* Code page 0 */
2322 proto_tree_add_text (tree, tvb, off, 1,
2324 "| EXT_%1x (Extension Token) "
2326 *level, peek & 0x0f, Indent (*level),
2327 map_token (map->global, codepage_stag, peek));
2331 case 0xC3: /* OPAQUE - WBXML 1.1 and newer */
2332 if (tvb_get_guint8 (tvb, 0)) { /* WBXML 1.x (x > 0) */
2333 index = tvb_get_guintvar (tvb, off+1, &len);
2334 proto_tree_add_text (tree, tvb, off, 1 + len + index,
2336 "| OPAQUE (Opaque data) "
2337 "| %s(%d bytes of opaque data)",
2338 *level, Indent (*level), index);
2340 } else { /* WBXML 1.0 - RESERVED_2 token (invalid) */
2341 proto_tree_add_text (tree, tvb, off, 1,
2343 "| RESERVED_2 (Invalid Token!) "
2344 "| WBXML 1.0 parsing stops here.");
2345 /* Stop processing as it is impossible to parse now */
2347 *parsed_length = off - offset;
2352 /* No default clause, as all cases have been treated */
2353 } else { /* LITERAL or Known TAG */
2354 /* We must store the initial tag, and also retrieve the new tag.
2355 * For efficiency reasons, we store the literal tag representation
2356 * for known tags too, so we can easily close the tag without the
2357 * need of a new lookup and avoiding storage of token codepage.
2359 * There are 4 possibilities:
2361 * 1. Known tag followed by a known tag
2362 * 2. Known tag followed by a LITERAL tag
2363 * 3. LITERAL tag followed by Known tag
2364 * 4. LITERAL tag followed by LITERAL tag
2367 /* Store the new tag */
2369 if ((peek & 0x3F) == 4) { /* LITERAL */
2370 index = tvb_get_guintvar (tvb, off+1, &tag_len);
2371 tag_new_literal = strtbl_lookup (tvb, str_tbl, index, NULL);
2372 tag_new_known = 0; /* invalidate known tag_new */
2373 } else { /* Known tag */
2374 tag_new_known = peek & 0x3F;
2375 tag_new_literal = map_token (map->tags, codepage_stag,
2377 /* Stored looked up tag name string */
2380 /* Parsing of TAG starts HERE */
2381 if (peek & 0x40) { /* Content present */
2383 * [!] An explicit END token is expected in these cases!
2384 * ==> Recursion possible if we encounter a tag with content;
2385 * recursion will return at the explicit END token.
2387 if (parsing_tag_content) { /* Recurse */
2389 printf ("WBXML: Tag in Tag - RECURSE! (off = %d)\n",off);
2391 /* Do not process the attribute list:
2392 * recursion will take care of it */
2394 parse_wbxml_tag_defined (tree, tvb, off, str_tbl, level,
2397 } else { /* Now we will have content to parse */
2398 /* Save the start tag so we can properly close it later. */
2399 if ((peek & 0x3F) == 4) { /* Literal tag */
2400 tag_save_literal = tag_new_literal;
2402 } else { /* Known tag */
2403 tag_save_known = tag_new_known;
2404 tag_save_literal = tag_new_literal;
2405 /* The last statement avoids needless lookups */
2407 /* Process the attribute list if present */
2408 if (peek & 0x80) { /* Content and Attribute list present */
2409 if (tag_new_known) { /* Known tag */
2410 if (codepage_stag) { /* Not default code page */
2411 proto_tree_add_text (tree, tvb, off, 1,
2412 " %3d | Tag | T %3d->0 "
2413 "| Known Tag 0x%02X (AC) "
2415 *level, codepage_stag, tag_new_known,
2416 Indent (*level), tag_new_literal);
2417 /* Tag string already looked up earlier! */
2418 /* Reset code page */
2420 } else { /* Code page 0 */
2421 proto_tree_add_text (tree, tvb, off, 1,
2423 "| Known Tag 0x%02X (AC) "
2425 *level, tag_new_known,
2426 Indent (*level), tag_new_literal);
2427 /* Tag string already looked up earlier! */
2430 } else { /* LITERAL tag */
2431 proto_tree_add_text (tree, tvb, off, 1,
2433 "| LITERAL_AC (Literal tag) (AC) "
2435 *level, Indent (*level), tag_new_literal);
2438 parse_wbxml_attribute_list_defined (tree, tvb,
2439 off, str_tbl, *level, &len, map);
2441 proto_tree_add_text (tree, tvb, off-1, 1,
2443 "| END (attribute list) "
2445 *level, Indent (*level));
2446 } else { /* Content, no Attribute list */
2447 if (tag_new_known) { /* Known tag */
2448 if (codepage_stag) { /* Not default code page */
2449 proto_tree_add_text (tree, tvb, off, 1,
2450 " %3d | Tag | T %3d->0 "
2451 "| Known Tag 0x%02X (.C) "
2453 *level, codepage_stag, tag_new_known,
2456 /* Tag string already looked up earlier! */
2457 /* Reset code page */
2459 } else { /* Code page 0 */
2460 proto_tree_add_text (tree, tvb, off, 1,
2462 "| Known Tag 0x%02X (.C) "
2464 *level, tag_new_known,
2467 /* Tag string already looked up earlier! */
2470 } else { /* LITERAL tag */
2471 proto_tree_add_text (tree, tvb, off, 1,
2473 "| LITERAL_C (Literal Tag) (.C) "
2475 *level, Indent (*level), tag_new_literal);
2479 /* The data that follows in the parsing process
2480 * represents content for the opening tag
2481 * we've just processed in the lines above.
2482 * Next time we encounter a tag with content: recurse
2484 parsing_tag_content = TRUE;
2486 printf ("WBXML: Tag in Tag - No recursion this time! "
2487 "(off = %d)\n", off);
2490 } else { /* No Content */
2492 printf ("WBXML: <Tag/> in Tag - No recursion! "
2493 "(off = %d)\n", off);
2496 if (peek & 0x80) { /* No Content, Attribute list present */
2497 if (tag_new_known) { /* Known tag */
2498 if (codepage_stag) { /* Not default code page */
2499 proto_tree_add_text (tree, tvb, off, 1,
2500 " %3d | Tag | T %3d->0 "
2501 "| Known Tag 0x%02X (A.) "
2503 *level, codepage_stag, tag_new_known,
2504 Indent (*level), tag_new_literal);
2505 /* Tag string already looked up earlier! */
2506 /* Reset code page */
2508 } else { /* Code page 0 */
2509 proto_tree_add_text (tree, tvb, off, 1,
2511 "| Known Tag 0x%02X (A.) "
2513 *level, tag_new_known,
2514 Indent (*level), tag_new_literal);
2515 /* Tag string already looked up earlier! */
2518 parse_wbxml_attribute_list_defined (tree, tvb,
2519 off, str_tbl, *level, &len, map);
2521 proto_tree_add_text (tree, tvb, off-1, 1,
2523 "| END (Known Tag) "
2525 *level, Indent (*level));
2526 } else { /* LITERAL tag */
2527 proto_tree_add_text (tree, tvb, off, 1,
2529 "| LITERAL_A (Literal Tag) (A.) "
2531 *level, Indent (*level), tag_new_literal);
2533 parse_wbxml_attribute_list_defined (tree, tvb,
2534 off, str_tbl, *level, &len, map);
2536 proto_tree_add_text (tree, tvb, off-1, 1,
2538 "| END (Literal Tag) "
2540 *level, Indent (*level));
2542 } else { /* No Content, No Attribute list */
2543 if (tag_new_known) { /* Known tag */
2544 if (codepage_stag) { /* Not default code page */
2545 proto_tree_add_text (tree, tvb, off, 1,
2546 " %3d | Tag | T %3d->0 "
2547 "| Known Tag 0x%02x (..) "
2549 *level, codepage_stag, tag_new_known,
2550 Indent (*level), tag_new_literal);
2551 /* Tag string already looked up earlier! */
2552 /* Reset code page */
2554 } else { /* Code page 0 */
2555 proto_tree_add_text (tree, tvb, off, 1,
2557 "| Known Tag 0x%02x (..) "
2559 *level, tag_new_known,
2560 Indent (*level), tag_new_literal);
2561 /* Tag string already looked up earlier! */
2564 } else { /* LITERAL tag */
2565 proto_tree_add_text (tree, tvb, off, 1,
2567 "| LITERAL (Literal Tag) (..) "
2569 *level, Indent (*level), tag_new_literal);
2574 /* TODO: Do I have to reset code page here? */
2576 } /* if (tag & 0x3F) >= 5 */
2581 /* This function performs the WBXML decoding as in parse_wbxml_tag_defined()
2582 * but this time no WBXML mapping is performed.
2584 * Attribute parsing is done in parse_wbxml_attribute_list().
2587 parse_wbxml_tag (proto_tree *tree, tvbuff_t *tvb, guint32 offset,
2588 guint32 str_tbl, guint8 *level,
2589 guint32 *parsed_length)
2591 guint32 tvb_len = tvb_reported_length (tvb);
2592 guint32 off = offset;
2598 guint32 tag_len; /* Length of the index (uintvar) from a LITERAL tag */
2599 guint8 tag_save_known = 0; /* Will contain peek & 0x3F (tag identity) */
2600 guint8 tag_new_known = 0; /* Will contain peek & 0x3F (tag identity) */
2601 const char *tag_save_literal; /* Will contain the LITERAL tag identity */
2602 const char *tag_new_literal; /* Will contain the LITERAL tag identity */
2603 char tag_save_buf[10]; /* Will contain "tag_0x%02X" */
2604 char tag_new_buf[10]; /* Will contain "tag_0x%02X" */
2605 guint8 codepage_stag = 0; /* Initial codepage in state = STAG */
2606 guint8 parsing_tag_content = FALSE; /* Are we parsing content from a
2607 tag with content: <x>Content</x>
2609 The initial state is FALSE.
2610 This state will trigger recursion. */
2611 tag_save_literal = NULL; /* Prevents compiler warning */
2614 printf ("WBXML - parse_wbxml_tag (level = %d, offset = %d)\n",
2617 while (off < tvb_len) {
2618 peek = tvb_get_guint8 (tvb, off);
2620 printf("WBXML - STAG: level = %3d, peek = 0x%02X, off = %d, "
2622 *level, peek, off, tvb_len);
2624 if ((peek & 0x3F) < 4) switch (peek) { /* Global tokens in state = STAG
2625 but not the LITERAL tokens */
2626 case 0x00: /* SWITCH_PAGE */
2627 codepage_stag = tvb_get_guint8 (tvb, off+1);
2628 proto_tree_add_text (tree, tvb, off, 2,
2629 " | Tag | T 0->%3d "
2630 "| SWITCH_PAGE (Tag code page) "
2635 case 0x01: /* END: only possible for Tag with Content */
2636 if (tag_save_known) { /* Known TAG */
2637 proto_tree_add_text (tree, tvb, off, 1,
2639 "| END (Known Tag 0x%02X) "
2641 *level, tag_save_known, Indent (*level),
2642 tag_save_literal); /* We already looked it up! */
2643 } else { /* Literal TAG */
2644 proto_tree_add_text (tree, tvb, off, 1,
2646 "| END (Literal Tag) "
2648 *level, Indent (*level),
2653 *parsed_length = off - offset;
2654 /* Reset code page: not needed as return from recursion */
2657 case 0x02: /* ENTITY */
2658 ent = tvb_get_guintvar (tvb, off+1, &len);
2659 proto_tree_add_text (tree, tvb, off, 1+len,
2663 *level, Indent (*level), ent);
2666 case 0x03: /* STR_I */
2667 /* Hack the string table lookup function */
2668 str = strtbl_lookup (tvb, off+1, 0, &len);
2669 proto_tree_add_text (tree, tvb, off, 1+len,
2671 "| STR_I (Inline string) "
2673 *level, Indent(*level), str);
2676 case 0x40: /* EXT_I_0 */
2677 case 0x41: /* EXT_I_1 */
2678 case 0x42: /* EXT_I_2 */
2679 /* Extension tokens */
2680 /* Hack the string table lookup function */
2681 str = strtbl_lookup (tvb, off+1, 0, &len);
2682 if (codepage_stag) { /* Not default code page */
2683 proto_tree_add_text (tree, tvb, off, 1+len,
2684 " %3d | Tag | T %3d->0 "
2685 "| EXT_I_%1x (Extension Token) "
2686 "| %s(Inline string extension: \'%s\')",
2687 *level, codepage_stag, peek & 0x0f, Indent (*level),
2689 /* Reset code page */
2691 } else { /* Code page 0 */
2692 proto_tree_add_text (tree, tvb, off, 1+len,
2694 "| EXT_I_%1x (Extension Token) "
2695 "| %s(Inline string extension: \'%s\')",
2696 *level, peek & 0x0f, Indent (*level),
2702 proto_tree_add_text (tree, tvb, off, 1,
2704 "| PI (XML Processing Instruction) "
2706 *level, Indent (*level));
2707 parse_wbxml_attribute_list (tree, tvb, off, str_tbl,
2710 proto_tree_add_text (tree, tvb, off-1, 1,
2714 *level, Indent (*level));
2716 case 0x80: /* EXT_T_0 */
2717 case 0x81: /* EXT_T_1 */
2718 case 0x82: /* EXT_T_2 */
2719 /* Extension tokens */
2720 index = tvb_get_guintvar (tvb, off+1, &len);
2721 str = strtbl_lookup (tvb, str_tbl, index, NULL);
2722 if (codepage_stag) { /* Not default code page */
2723 proto_tree_add_text (tree, tvb, off, 1+len,
2724 " %3d | Tag | T %3d->0 "
2725 "| EXT_T_%1x (Extension Token) "
2726 "| %s(Tableref string extension: \'%s\')",
2727 *level, codepage_stag, peek & 0x0f, Indent (*level),
2729 /* Reset code page */
2731 } else { /* Code page 0 */
2732 proto_tree_add_text (tree, tvb, off, 1+len,
2734 "| EXT_T_%1x (Extension Token) "
2735 "| %s(Tableref string extension: \'%s\')",
2736 *level, peek & 0x0f, Indent (*level),
2741 case 0x83: /* STR_T */
2742 index = tvb_get_guintvar (tvb, off+1, &len);
2743 str = strtbl_lookup (tvb, str_tbl, index, NULL);
2744 proto_tree_add_text (tree, tvb, off, 1+len,
2746 "| STR_T (Tableref string) "
2748 *level, Indent (*level), str);
2751 case 0xC0: /* EXT_0 */
2752 case 0xC1: /* EXT_1 */
2753 case 0xC2: /* EXT_2 */
2754 /* Extension tokens */
2755 if (codepage_stag) { /* Not default code page */
2756 proto_tree_add_text (tree, tvb, off, 1,
2757 " %3d | Tag | T %3d->0 "
2758 "| EXT_%1x (Extension Token) "
2759 "| %s(Single-byte extension)",
2760 *level, codepage_stag, peek & 0x0f,
2762 /* Reset code page */
2764 } else { /* Code page 0 */
2765 proto_tree_add_text (tree, tvb, off, 1,
2767 "| EXT_%1x (Extension Token) "
2768 "| %s(Single-byte extension)",
2769 *level, peek & 0x0f, Indent (*level));
2773 case 0xC3: /* OPAQUE - WBXML 1.1 and newer */
2774 if (tvb_get_guint8 (tvb, 0)) { /* WBXML 1.x (x > 0) */
2775 index = tvb_get_guintvar (tvb, off+1, &len);
2776 proto_tree_add_text (tree, tvb, off, 1 + len + index,
2778 "| OPAQUE (Opaque data) "
2779 "| %s(%d bytes of opaque data)",
2780 *level, Indent (*level), index);
2782 } else { /* WBXML 1.0 - RESERVED_2 token (invalid) */
2783 proto_tree_add_text (tree, tvb, off, 1,
2785 "| RESERVED_2 (Invalid Token!) "
2786 "| WBXML 1.0 parsing stops here.");
2787 /* Stop processing as it is impossible to parse now */
2789 *parsed_length = off - offset;
2794 /* No default clause, as all cases have been treated */
2795 } else { /* LITERAL or Known TAG */
2796 /* We must store the initial tag, and also retrieve the new tag.
2797 * For efficiency reasons, we store the literal tag representation
2798 * for known tags too, so we can easily close the tag without the
2799 * need of a new lookup and avoiding storage of token codepage.
2801 * There are 4 possibilities:
2803 * 1. Known tag followed by a known tag
2804 * 2. Known tag followed by a LITERAL tag
2805 * 3. LITERAL tag followed by Known tag
2806 * 4. LITERAL tag followed by LITERAL tag
2809 /* Store the new tag */
2811 if ((peek & 0x3F) == 4) { /* LITERAL */
2812 index = tvb_get_guintvar (tvb, off+1, &tag_len);
2813 tag_new_literal = strtbl_lookup (tvb, str_tbl, index, NULL);
2814 tag_new_known = 0; /* invalidate known tag_new */
2815 } else { /* Known tag */
2816 tag_new_known = peek & 0x3F;
2817 sprintf (tag_new_buf, "Tag_0x%02X",
2819 tag_new_literal = tag_new_buf;
2820 /* Stored looked up tag name string */
2823 /* Parsing of TAG starts HERE */
2824 if (peek & 0x40) { /* Content present */
2826 * [!] An explicit END token is expected in these cases!
2827 * ==> Recursion possible if we encounter a tag with content;
2828 * recursion will return at the explicit END token.
2830 if (parsing_tag_content) { /* Recurse */
2832 printf ("WBXML: Tag in Tag - RECURSE! (off = %d)\n",off);
2834 /* Do not process the attribute list:
2835 * recursion will take care of it */
2837 parse_wbxml_tag (tree, tvb, off, str_tbl, level,
2840 } else { /* Now we will have content to parse */
2841 /* Save the start tag so we can properly close it later. */
2842 if ((peek & 0x3F) == 4) { /* Literal tag */
2843 tag_save_literal = tag_new_literal;
2845 } else { /* Known tag */
2846 tag_save_known = tag_new_known;
2847 sprintf (tag_save_buf, "Tag_0x%02X",
2849 tag_save_literal = tag_save_buf;
2850 /* The last statement avoids needless lookups */
2852 /* Process the attribute list if present */
2853 if (peek & 0x80) { /* Content and Attribute list present */
2854 if (tag_new_known) { /* Known tag */
2855 if (codepage_stag) { /* Not default code page */
2856 proto_tree_add_text (tree, tvb, off, 1,
2857 " %3d | Tag | T %3d->0 "
2858 "| Known Tag 0x%02X (AC) "
2860 *level, codepage_stag, tag_new_known,
2861 Indent (*level), tag_new_literal);
2862 /* Tag string already looked up earlier! */
2863 /* Reset code page */
2865 } else { /* Code page 0 */
2866 proto_tree_add_text (tree, tvb, off, 1,
2868 "| Known Tag 0x%02X (AC) "
2870 *level, tag_new_known,
2871 Indent (*level), tag_new_literal);
2872 /* Tag string already looked up earlier! */
2875 } else { /* LITERAL tag */
2876 proto_tree_add_text (tree, tvb, off, 1,
2878 "| LITERAL_AC (Literal tag) (AC) "
2880 *level, Indent (*level), tag_new_literal);
2883 parse_wbxml_attribute_list (tree, tvb,
2884 off, str_tbl, *level, &len);
2886 proto_tree_add_text (tree, tvb, off-1, 1,
2888 "| END (attribute list) "
2890 *level, Indent (*level));
2891 } else { /* Content, no Attribute list */
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 (.C) "
2898 *level, codepage_stag, tag_new_known,
2901 /* Tag string already looked up earlier! */
2902 /* Reset code page */
2904 } else { /* Code page 0 */
2905 proto_tree_add_text (tree, tvb, off, 1,
2907 "| Known Tag 0x%02X (.C) "
2909 *level, tag_new_known,
2912 /* Tag string already looked up earlier! */
2915 } else { /* LITERAL tag */
2916 proto_tree_add_text (tree, tvb, off, 1,
2918 "| LITERAL_C (Literal Tag) (.C) "
2920 *level, Indent (*level), tag_new_literal);
2924 /* The data that follows in the parsing process
2925 * represents content for the opening tag
2926 * we've just processed in the lines above.
2927 * Next time we encounter a tag with content: recurse
2929 parsing_tag_content = TRUE;
2931 printf ("WBXML: Tag in Tag - No recursion this time! "
2932 "(off = %d)\n", off);
2935 } else { /* No Content */
2937 printf ("WBXML: <Tag/> in Tag - No recursion! "
2938 "(off = %d)\n", off);
2941 if (peek & 0x80) { /* No Content, Attribute list present */
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 (A.) "
2948 *level, codepage_stag, tag_new_known,
2949 Indent (*level), tag_new_literal);
2950 /* Tag string already looked up earlier! */
2951 /* Reset code page */
2953 } else { /* Code page 0 */
2954 proto_tree_add_text (tree, tvb, off, 1,
2956 "| Known Tag 0x%02X (A.) "
2958 *level, tag_new_known,
2959 Indent (*level), tag_new_literal);
2960 /* Tag string already looked up earlier! */
2963 parse_wbxml_attribute_list (tree, tvb,
2964 off, str_tbl, *level, &len);
2966 proto_tree_add_text (tree, tvb, off-1, 1,
2968 "| END (Known Tag) "
2970 *level, Indent (*level));
2971 } else { /* LITERAL tag */
2972 proto_tree_add_text (tree, tvb, off, 1,
2974 "| LITERAL_A (Literal Tag) (A.) "
2976 *level, Indent (*level), tag_new_literal);
2978 parse_wbxml_attribute_list (tree, tvb,
2979 off, str_tbl, *level, &len);
2981 proto_tree_add_text (tree, tvb, off-1, 1,
2983 "| END (Literal Tag) "
2985 *level, Indent (*level));
2987 } else { /* No Content, No Attribute list */
2988 if (tag_new_known) { /* Known tag */
2989 if (codepage_stag) { /* Not default code page */
2990 proto_tree_add_text (tree, tvb, off, 1,
2991 " %3d | Tag | T %3d->0 "
2992 "| Known Tag 0x%02x (..) "
2994 *level, codepage_stag, tag_new_known,
2995 Indent (*level), tag_new_literal);
2996 /* Tag string already looked up earlier! */
2997 /* Reset code page */
2999 } else { /* Code page 0 */
3000 proto_tree_add_text (tree, tvb, off, 1,
3002 "| Known Tag 0x%02x (..) "
3004 *level, tag_new_known,
3005 Indent (*level), tag_new_literal);
3006 /* Tag string already looked up earlier! */
3009 } else { /* LITERAL tag */
3010 proto_tree_add_text (tree, tvb, off, 1,
3012 "| LITERAL (Literal Tag) (..) "
3014 *level, Indent (*level), tag_new_literal);
3019 /* TODO: Do I have to reset code page here? */
3021 } /* if (tag & 0x3F) >= 5 */
3026 /**************************
3027 * WBXML Attribute tokens *
3028 **************************
3029 * Bit Mask : Example
3030 * -------------------
3031 * 0... .... : attr= (attribute name)
3032 * href='http://' (attribute name with start of attribute value)
3033 * 1... .... : 'www.' (attribute value, or part of it)
3038 /* This function parses the WBXML and maps known token interpretations
3039 * to the WBXML tokens. As a result, the original XML document can be
3040 * recreated. Indentation is generated in order to ease reading.
3042 * This function performs attribute list parsing.
3044 * The wbxml_token_map entry *map contains the actual token mapping.
3046 * NOTE: See above for known token mappings.
3049 parse_wbxml_attribute_list_defined (proto_tree *tree, tvbuff_t *tvb,
3050 guint32 offset, guint32 str_tbl, guint8 level,
3051 guint32 *parsed_length,
3052 const wbxml_token_map *map)
3054 guint32 tvb_len = tvb_reported_length (tvb);
3055 guint32 off = offset;
3061 guint8 codepage_attr = 0; /* Initial codepage in state = ATTR */
3064 printf ("WBXML - parse_wbxml_attr_defined (level = %d, offset = %d)\n",
3067 /* Parse attributes */
3068 while (off < tvb_len) {
3069 peek = tvb_get_guint8 (tvb, off);
3071 printf("WBXML - ATTR: level = %3d, peek = 0x%02X, off = %d, "
3073 level, peek, off, tvb_len);
3075 if ((peek & 0x3F) < 5) switch (peek) { /* Global tokens
3077 case 0x00: /* SWITCH_PAGE */
3078 codepage_attr = tvb_get_guint8 (tvb, off+1);
3079 proto_tree_add_text (tree, tvb, off, 2,
3080 " | Attr | A 0->%3d "
3081 "| SWITCH_PAGE (Attr code page) |",
3085 case 0x01: /* END */
3087 * The Attribute END token means either ">" or "/>"
3088 * and as a consequence both must be treated separately.
3089 * This is done in the TAG state parser.
3092 *parsed_length = off - offset;
3094 case 0x02: /* ENTITY */
3095 ent = tvb_get_guintvar (tvb, off+1, &len);
3096 proto_tree_add_text (tree, tvb, off, 1+len,
3100 level, Indent (level), ent);
3103 case 0x03: /* STR_I */
3104 /* Hack the string table lookup function */
3105 str = strtbl_lookup (tvb, off+1, 0, &len);
3106 proto_tree_add_text (tree, tvb, off, 1+len,
3108 "| STR_I (Inline string) "
3110 level, Indent (level), str);
3113 case 0x04: /* LITERAL */
3114 index = tvb_get_guintvar (tvb, off+1, &len);
3115 str = strtbl_lookup (tvb, str_tbl, index, NULL);
3116 proto_tree_add_text (tree, tvb, off, 1+len,
3118 "| LITERAL (Literal Attribute) "
3120 level, Indent (level), str);
3123 case 0x40: /* EXT_I_0 */
3124 case 0x41: /* EXT_I_1 */
3125 case 0x42: /* EXT_I_2 */
3126 /* Extension tokens */
3127 /* Hack the string table lookup function */
3128 str = strtbl_lookup (tvb, off+1, 0, &len);
3129 if (codepage_attr) { /* Not default code page */
3130 proto_tree_add_text (tree, tvb, off, 1+len,
3131 " %3d | Attr | A %3d->0 "
3132 "| EXT_I_%1x (Extension Token) "
3134 level, codepage_attr, peek & 0x0f, Indent (level),
3135 map_token (map->global, codepage_attr, peek), str);
3136 /* Reset code page */
3138 } else { /* Code page 0 */
3139 proto_tree_add_text (tree, tvb, off, 1+len,
3141 "| EXT_I_%1x (Extension Token) "
3143 level, peek & 0x0f, Indent (level),
3144 map_token (map->global, codepage_attr, peek), str);
3148 /* 0x43 impossible in ATTR state */
3149 /* 0x44 impossible in ATTR state */
3150 case 0x80: /* EXT_T_0 */
3151 case 0x81: /* EXT_T_1 */
3152 case 0x82: /* EXT_T_2 */
3153 /* Extension tokens */
3154 index = tvb_get_guintvar (tvb, off+1, &len);
3155 str = strtbl_lookup (tvb, str_tbl, index, NULL);
3156 if (codepage_attr) { /* Not default code page */
3157 proto_tree_add_text (tree, tvb, off, 1+len,
3158 " %3d | Attr | A %3d->0 "
3159 "| EXT_T_%1x (Extension Token) "
3161 level, codepage_attr, peek & 0x0f, Indent (level),
3162 map_token (map->global, codepage_attr, peek), str);
3163 /* Reset code page */
3165 } else { /* Code page 0 */
3166 proto_tree_add_text (tree, tvb, off, 1+len,
3168 "| EXT_T_%1x (Extension Token) "
3170 level, peek & 0x0f, Indent (level),
3171 map_token (map->global, codepage_attr, peek), str);
3175 case 0x83: /* STR_T */
3176 index = tvb_get_guintvar (tvb, off+1, &len);
3177 str = strtbl_lookup (tvb, str_tbl, index, NULL);
3178 proto_tree_add_text (tree, tvb, off, 1+len,
3180 "| STR_T (Tableref string) "
3182 level, Indent (level), str);
3185 /* 0x84 impossible in ATTR state */
3186 case 0xC0: /* EXT_0 */
3187 case 0xC1: /* EXT_1 */
3188 case 0xC2: /* EXT_2 */
3189 /* Extension tokens */
3190 if (codepage_attr) { /* Not default code page */
3191 proto_tree_add_text (tree, tvb, off, 1,
3192 " %3d | Attr | A %3d->0 "
3193 "| EXT_%1x (Extension Token) "
3195 level, codepage_attr, peek & 0x0f, Indent (level),
3196 map_token (map->global, codepage_attr, peek));
3197 /* Reset code page */
3199 } else { /* Code page 0 */
3200 proto_tree_add_text (tree, tvb, off, 1,
3202 "| EXT_%1x (Extension Token) "
3204 level, peek & 0x0f, Indent (level),
3205 map_token (map->global, codepage_attr, peek));
3209 case 0xC3: /* OPAQUE - WBXML 1.1 and newer */
3210 if (tvb_get_guint8 (tvb, 0)) { /* WBXML 1.x (x > 0) */
3211 index = tvb_get_guintvar (tvb, off+1, &len);
3212 proto_tree_add_text (tree, tvb, off, 1 + len + index,
3214 "| OPAQUE (Opaque data) "
3215 "| %s(%d bytes of opaque data)",
3216 level, Indent (level), index);
3218 } else { /* WBXML 1.0 - RESERVED_2 token (invalid) */
3219 proto_tree_add_text (tree, tvb, off, 1,
3221 "| RESERVED_2 (Invalid Token!) "
3222 "| WBXML 1.0 parsing stops here.");
3223 /* Stop processing as it is impossible to parse now */
3225 *parsed_length = off - offset;
3229 /* 0xC4 impossible in ATTR state */
3231 proto_tree_add_text (tree, tvb, off, 1,
3233 "| %-10s (Invalid Token!) "
3234 "| WBXML parsing stops here.",
3235 level, match_strval (peek, vals_wbxml1x_global_tokens));
3236 /* Move to end of buffer */
3239 } else { /* Known atribute token */
3240 if (peek & 0x80) { /* attrValue */
3241 if (codepage_attr) { /* Not default code page */
3242 proto_tree_add_text (tree, tvb, off, 1,
3243 " %3d | Attr | A %3d->0 "
3244 "| Known attrValue 0x%02X "
3246 level, codepage_attr, peek & 0x7f, Indent (level),
3247 map_token (map->attrValue, codepage_attr, peek));
3248 /* Reset code page */
3250 } else { /* Code page 0 */
3251 proto_tree_add_text (tree, tvb, off, 1,
3253 "| Known attrValue 0x%02X "
3255 level, peek & 0x7f, Indent (level),
3256 map_token (map->attrValue, codepage_attr, peek));
3259 } else { /* attrStart */
3260 if (codepage_attr) { /* Not default code page */
3261 proto_tree_add_text (tree, tvb, off, 1,
3262 " %3d | Attr | A %3d->0 "
3263 "| Known attrStart 0x%02X "
3265 level, codepage_attr, peek & 0x7f, Indent (level),
3266 map_token (map->attrStart, codepage_attr, peek));
3267 /* Reset code page */
3269 } else { /* Code page 0 */
3270 proto_tree_add_text (tree, tvb, off, 1,
3272 "| Known attrStart 0x%02X "
3274 level, peek & 0x7f, Indent (level),
3275 map_token (map->attrStart, codepage_attr, peek));
3284 /* This function performs the WBXML attribute decoding as in
3285 * parse_wbxml_attribute_list_defined() but this time no WBXML mapping
3288 * This function performs attribute list parsing.
3290 * NOTE: Code page switches not yet processed in the code!
3293 parse_wbxml_attribute_list (proto_tree *tree, tvbuff_t *tvb,
3294 guint32 offset, guint32 str_tbl, guint8 level,
3295 guint32 *parsed_length)
3297 guint32 tvb_len = tvb_reported_length (tvb);
3298 guint32 off = offset;
3304 guint8 codepage_attr = 0; /* Initial codepage in state = ATTR */
3307 printf ("WBXML - parse_wbxml_attr (level = %d, offset = %d)\n",
3310 /* Parse attributes */
3311 while (off < tvb_len) {
3312 peek = tvb_get_guint8 (tvb, off);
3314 printf("WBXML - ATTR: level = %3d, peek = 0x%02X, off = %d, "
3316 level, peek, off, tvb_len);
3318 if ((peek & 0x3F) < 5) switch (peek) { /* Global tokens
3320 case 0x00: /* SWITCH_PAGE */
3321 codepage_attr = tvb_get_guint8 (tvb, off+1);
3322 proto_tree_add_text (tree, tvb, off, 2,
3323 " | Attr | A 0->%3d "
3324 "| SWITCH_PAGE (Attr code page) |",
3328 case 0x01: /* END */
3330 * The Attribute END token means either ">" or "/>"
3331 * and as a consequence both must be treated separately.
3332 * This is done in the TAG state parser.
3335 *parsed_length = off - offset;
3337 case 0x02: /* ENTITY */
3338 ent = tvb_get_guintvar (tvb, off+1, &len);
3339 proto_tree_add_text (tree, tvb, off, 1+len,
3343 level, Indent (level), ent);
3346 case 0x03: /* STR_I */
3347 /* Hack the string table lookup function */
3348 str = strtbl_lookup (tvb, off+1, 0, &len);
3349 proto_tree_add_text (tree, tvb, off, 1+len,
3351 "| STR_I (Inline string) "
3353 level, Indent (level), str);
3356 case 0x04: /* LITERAL */
3357 index = tvb_get_guintvar (tvb, off+1, &len);
3358 str = strtbl_lookup (tvb, str_tbl, index, NULL);
3359 proto_tree_add_text (tree, tvb, off, 1+len,
3361 "| LITERAL (Literal Attribute) "
3363 level, Indent (level), str);
3366 case 0x40: /* EXT_I_0 */
3367 case 0x41: /* EXT_I_1 */
3368 case 0x42: /* EXT_I_2 */
3369 /* Extension tokens */
3370 /* Hack the string table lookup function */
3371 str = strtbl_lookup (tvb, off+1, 0, &len);
3372 if (codepage_attr) { /* Not default code page */
3373 proto_tree_add_text (tree, tvb, off, 1+len,
3374 " %3d | Attr | A %3d->0 "
3375 "| EXT_I_%1x (Extension Token) "
3376 "| %s(Inline string extension: \'%s\')",
3377 level, codepage_attr, peek & 0x0f, Indent (level),
3379 /* Reset code page */
3381 } else { /* Code page 0 */
3382 proto_tree_add_text (tree, tvb, off, 1+len,
3384 "| EXT_I_%1x (Extension Token) "
3385 "| %s(Inline string extension: \'%s\')",
3386 level, peek & 0x0f, Indent (level),
3391 /* 0x43 impossible in ATTR state */
3392 /* 0x44 impossible in ATTR state */
3393 case 0x80: /* EXT_T_0 */
3394 case 0x81: /* EXT_T_1 */
3395 case 0x82: /* EXT_T_2 */
3396 /* Extension tokens */
3397 index = tvb_get_guintvar (tvb, off+1, &len);
3398 str = strtbl_lookup (tvb, str_tbl, index, NULL);
3399 if (codepage_attr) { /* Not default code page */
3400 proto_tree_add_text (tree, tvb, off, 1+len,
3401 " %3d | Attr | A %3d->0 "
3402 "| EXT_T_%1x (Extension Token) "
3403 "| %s(Tableref string extension: \'%s\')",
3404 level, codepage_attr, peek & 0x0f, Indent (level),
3406 /* Reset code page */
3408 } else { /* Code page 0 */
3409 proto_tree_add_text (tree, tvb, off, 1+len,
3411 "| EXT_T_%1x (Extension Token) "
3412 "| %s(Tableref string extension: \'%s\')",
3413 level, peek & 0x0f, Indent (level),
3418 case 0x83: /* STR_T */
3419 index = tvb_get_guintvar (tvb, off+1, &len);
3420 str = strtbl_lookup (tvb, str_tbl, index, NULL);
3421 proto_tree_add_text (tree, tvb, off, 1+len,
3423 "| STR_T (Tableref string) "
3425 level, Indent (level), str);
3428 /* 0x84 impossible in ATTR state */
3429 case 0xC0: /* EXT_0 */
3430 case 0xC1: /* EXT_1 */
3431 case 0xC2: /* EXT_2 */
3432 /* Extension tokens */
3433 if (codepage_attr) { /* Not default code page */
3434 proto_tree_add_text (tree, tvb, off, 1,
3435 " %3d | Attr | A %3d->0 "
3436 "| EXT_%1x (Extension Token) "
3437 "| %s(Single-byte extension)",
3438 level, codepage_attr, peek & 0x0f, Indent (level));
3439 /* Reset code page */
3441 } else { /* Code page 0 */
3442 proto_tree_add_text (tree, tvb, off, 1,
3444 "| EXT_%1x (Extension Token) "
3445 "| %s(Single-byte extension)",
3446 level, peek & 0x0f, Indent (level));
3450 case 0xC3: /* OPAQUE - WBXML 1.1 and newer */
3451 if (tvb_get_guint8 (tvb, 0)) { /* WBXML 1.x (x > 0) */
3452 index = tvb_get_guintvar (tvb, off+1, &len);
3453 proto_tree_add_text (tree, tvb, off, 1 + len + index,
3455 "| OPAQUE (Opaque data) "
3456 "| %s(%d bytes of opaque data)",
3457 level, Indent (level), index);
3459 } else { /* WBXML 1.0 - RESERVED_2 token (invalid) */
3460 proto_tree_add_text (tree, tvb, off, 1,
3462 "| RESERVED_2 (Invalid Token!) "
3463 "| WBXML 1.0 parsing stops here.");
3464 /* Stop processing as it is impossible to parse now */
3466 *parsed_length = off - offset;
3470 /* 0xC4 impossible in ATTR state */
3472 proto_tree_add_text (tree, tvb, off, 1,
3474 "| %-10s (Invalid Token!) "
3475 "| WBXML parsing stops here.",
3476 level, match_strval (peek, vals_wbxml1x_global_tokens));
3477 /* Move to end of buffer */
3480 } else { /* Known atribute token */
3481 if (peek & 0x80) { /* attrValue */
3482 if (codepage_attr) { /* Not default code page */
3483 proto_tree_add_text (tree, tvb, off, 1,
3484 " %3d | Attr | A %3d->0 "
3485 "| Known attrValue 0x%02X "
3486 "| %sattrValue_0x%02X",
3487 level, codepage_attr, peek & 0x7f, Indent (level),
3489 /* Reset code page */
3491 } else { /* Code page 0 */
3492 proto_tree_add_text (tree, tvb, off, 1,
3494 "| Known attrValue 0x%02X "
3495 "| %sattrValue_0x%02X",
3496 level, peek & 0x7f, Indent (level),
3500 } else { /* attrStart */
3501 if (codepage_attr) { /* Not default code page */
3502 proto_tree_add_text (tree, tvb, off, 1,
3503 " %3d | Attr | A %3d->0 "
3504 "| Known attrStart 0x%02X "
3505 "| %sattrStart_0x%02X",
3506 level, codepage_attr, peek & 0x7f, Indent (level),
3508 /* Reset code page */
3510 } else { /* Code page 0 */
3511 proto_tree_add_text (tree, tvb, off, 1,
3513 "| Known attrStart 0x%02X "
3514 "| %sattrStart_0x%02X",
3515 level, peek & 0x7f, Indent (level),
3525 /****************** Register the protocol with Ethereal ******************/
3528 /* This format is required because a script is used to build the C function
3529 * that calls the protocol registration. */
3532 proto_register_wbxml(void)
3533 { /* Setup list of header fields. See Section 1.6.1 for details. */
3534 static hf_register_info hf[] = {
3535 { &hf_wbxml_version,
3539 VALS ( vals_wbxml_versions ), 0x00,
3540 "WBXML Version", HFILL }
3542 { &hf_wbxml_public_id_known,
3543 { "Public Identifier (known)",
3544 "wbxml.public_id.known",
3545 FT_UINT32, BASE_HEX,
3546 VALS ( vals_wbxml_public_ids ), 0x00,
3547 "WBXML Known Public Identifier (integer)", HFILL }
3549 { &hf_wbxml_public_id_literal,
3550 { "Public Identifier (literal)",
3551 "wbxml.public_id.literal",
3552 FT_STRING, BASE_NONE,
3554 "WBXML Literal Public Identifier (text string)", HFILL }
3556 { &hf_wbxml_charset,
3559 FT_UINT32, BASE_HEX,
3560 VALS ( vals_character_sets ), 0x00,
3561 "WBXML Character Set", HFILL }
3565 /* Setup protocol subtree array */
3566 static gint *ett[] = {
3572 /* Register the protocol name and description */
3573 proto_wbxml = proto_register_protocol(
3579 /* Required function calls to register the header fields
3580 * and subtrees used */
3581 proto_register_field_array(proto_wbxml, hf, array_length(hf));
3582 proto_register_subtree_array(ett, array_length(ett));
3584 register_dissector("wbxml", dissect_wbxml, proto_wbxml);
3589 proto_reg_handoff_wbxml(void)
3591 dissector_handle_t wbxml_handle;
3593 /* Heuristic dissectors would be declared by means of:
3594 * heur_dissector_add("wsp", dissect_wbxml_heur, proto_wbxml);
3597 wbxml_handle = create_dissector_handle(dissect_wbxml, proto_wbxml);
3599 /* Register the WSP content types (defined as protocol port)
3600 * for WBXML dissection.
3602 * See http://www.wapforum.org/wina/wsp-content-type.htm
3605 /**** Well-known WBXML WSP Content-Type values ****/
3607 /* application/vnd.wap.wmlc */
3608 dissector_add("wsp.content_type.type", 0x14, wbxml_handle);
3610 /* application/vnd.wap.wta-eventc */
3611 dissector_add("wsp.content_type.type", 0x16, wbxml_handle);
3613 /* application/vnd.wap.wbxml */
3614 dissector_add("wsp.content_type.type", 0x29, wbxml_handle);
3616 /* application/vnd.wap.sic */
3617 dissector_add("wsp.content_type.type", 0x2E, wbxml_handle);
3619 /* application/vnd.wap.slc */
3620 dissector_add("wsp.content_type.type", 0x30, wbxml_handle);
3622 /* application/vnd.wap.coc */
3623 dissector_add("wsp.content_type.type", 0x32, wbxml_handle);
3625 /* application/vnd.wap.connectivity-wbxml */
3626 dissector_add("wsp.content_type.type", 0x36, wbxml_handle);
3628 /* application/vnd.wap.locc+wbxml */
3629 dissector_add("wsp.content_type.type", 0x40, wbxml_handle);
3631 /* application/vnd.syncml.dm+wbxml */
3632 dissector_add("wsp.content_type.type", 0x42, wbxml_handle);
3634 /* application/vnd.oma.drm.rights+wbxml */
3635 dissector_add("wsp.content_type.type", 0x4B, wbxml_handle);
3637 #ifdef WSP_DISSECTOR_REGISTERS_ContentType_AS_FourByteGuint
3639 /**** Registered WBXML WSP Content-Type values ****/
3641 /* application/vnd.uplanet.cacheop-wbxml */
3642 dissector_add("wsp.content_type.type", 0x0201, wbxml_handle);
3644 /* application/vnd.uplanet.alert-wbxml */
3645 dissector_add("wsp.content_type.type", 0x0203, wbxml_handle);
3647 /* application/vnd.uplanet.list-wbxml */
3648 dissector_add("wsp.content_type.type", 0x0204, wbxml_handle);
3650 /* application/vnd.uplanet.listcmd-wbxml */
3651 dissector_add("wsp.content_type.type", 0x0205, wbxml_handle);
3653 /* application/vnd.uplanet.channel-wbxml */
3654 dissector_add("wsp.content_type.type", 0x0206, wbxml_handle);
3656 /* application/vnd.uplanet.bearer-choice-wbxml */
3657 dissector_add("wsp.content_type.type", 0x0209, wbxml_handle);
3659 /* application/vnd.phonecom.mmc-wbxml */
3660 dissector_add("wsp.content_type.type", 0x020A, wbxml_handle);
3662 /* application/vnd.nokia.syncset+wbxml */
3663 dissector_add("wsp.content_type.type", 0x020B, wbxml_handle);