2 * Routines for wbxml dissection
3 * Copyright 2003, Olivier Biot <olivier.biot (ad) siemens.com>
5 * $Id: packet-wbxml.c,v 1.18 2003/12/08 20:37:15 obiot 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 /* General-purpose debug logger.
53 * Requires double parentheses because of variable arguments of printf().
55 * Enable debug logging for WBXML by defining AM_FLAGS
56 * so that it contains "-DDEBUG_wbxml"
60 printf("%s:%u: ", __FILE__, __LINE__); \
67 /* The code in this source file dissects the WAP Binary XML content,
68 * and if possible renders it. WBXML mappings are defined in the
69 * "wbxml_map[]" array.
73 * - Code page switches only apply to the following token. In the WBXML/1.x
74 * ABNF notation, it can be proven that the switch_page can only precede
75 * the following tokens:
76 * o stag : TAG | LITERAL | LITERAL_A | LITERAL_C | LITERAL_AC
77 * o attr : ATTRSTART | ATTRVALUE
78 * o extension : EXT_I | EXT_T | EXT
79 * Code page switches are displayed in a separate column. The only allowed
80 * code page switches are from code page 0 to another codepage (by means of
81 * a SWITCH_PAGE token), and from this other code page back to code page 0
82 * (this happens automatically).
84 * - In order to render the XML content, recursion is inevitable at some
85 * point (when a tag with content occurs in the content of a tag with
86 * content). The code will however not recurse if this is not strictly
87 * required (e.g., tag without content in the content of a tag with
90 * - I found it useful to display the XML nesting level as a first "column",
91 * followed by the abbreviated WBXML token interpretation. When a mapping
92 * is defined for the parsed WBXML content, then the XML rendering is
93 * displayed with appropriate indentation (maximum nesting level = 255,
94 * after which the nesting and level will safely roll-over to 0).
96 * - The WAP Forum defines the order of precedence for finding out the
97 * WBXML content type (same rules for charset) as follows:
98 * 1. Look in the Content-Type WSP header
99 * 2. Look in the WBXML header
100 * Currently there is no means of using content type parameters:
102 * o Charset=<charset_of_the_content>
103 * So it is possible some WBXML content types are incorrectly parsed.
104 * This would only be the case when the content type declaration in the
105 * WSP Content-Type header would be different (or would have parameters
106 * which are relevant to the WBXML decoding) from the content type
107 * identifier specified in the WBXML header.
108 * TODO: investigate this and provide correct decoding at all times.
111 typedef struct _value_valuestring {
113 const value_string *valstrptr;
116 /* Tries to match val against each element in the value_value_string array vvs.
117 * Returns the associated value_string ptr on a match, or NULL on failure. */
118 static const value_string *
119 val_to_valstr(guint32 val, const value_valuestring *vvs)
123 while (vvs[i].valstrptr) {
124 if (vvs[i].value == val)
125 return(vvs[i].valstrptr);
133 /************************** Variable declarations **************************/
136 /* Initialize the protocol and registered fields */
137 static int proto_wbxml = -1;
138 static int hf_wbxml_version = -1;
139 static int hf_wbxml_public_id_known = -1;
140 static int hf_wbxml_public_id_literal = -1;
141 static int hf_wbxml_charset = -1;
143 /* Initialize the subtree pointers */
144 static gint ett_wbxml = -1;
145 static gint ett_wbxml_str_tbl = -1;
146 static gint ett_wbxml_content = -1;
149 /**************** WBXML related declarations and definitions ****************/
152 /* WBXML public ID mappings. For an up-to-date list, see
153 * http://www.wapforum.org/wina/wbxml-public-docid.htm */
154 static const value_string vals_wbxml_public_ids[] = {
155 /* 0x00 = literal public identifier */
156 { 0x01, "Unknown / missing Public Identifier" },
157 { 0x02, "-//WAPFORUM//DTD WML 1.0//EN (WML 1.0)" },
158 { 0x03, "-//WAPFORUM//DTD WTA 1.0//EN (WTA Event 1.0) - Deprecated" },
159 { 0x04, "-//WAPFORUM//DTD WML 1.1//EN (WML 1.1)" },
160 { 0x05, "-//WAPFORUM//DTD SI 1.0//EN (Service Indication 1.0)" },
161 { 0x06, "-//WAPFORUM//DTD SL 1.0//EN (Service Loading 1.0)" },
162 { 0x07, "-//WAPFORUM//DTD CO 1.0//EN (Cache Operation 1.0)" },
163 { 0x08, "-//WAPFORUM//DTD CHANNEL 1.0//EN (Channel 1.1)" },
164 { 0x09, "-//WAPFORUM//DTD WML 1.2//EN (WML 1.2)" },
165 { 0x0a, "-//WAPFORUM//DTD WML 1.3//EN (WML 1.3)" },
166 { 0x0b, "-//WAPFORUM//DTD PROV 1.0//EN (Provisioning 1.0)" },
167 { 0x0c, "-//WAPFORUM//DTD WTA-WML 1.2//EN (WTA-WML 1.2)" },
168 { 0x0d, "-//WAPFORUM//DTD EMN 1.0//EN (Email Notification 1.0)" },
169 { 0x0e, "-//WAPFORUM//DTD DRMREL 1.0//EN (DRMREL 1.0)" },
170 { 0x0f, "-//WIRELESSVILLAGE//DTD CSP 1.0//EN"
171 " (Wireless Village Client-Server Protocol DTD v1.0)" },
172 { 0x10, "-//WIRELESSVILLAGE//DTD CSP 1.1//EN"
173 " (Wireless Village Client-Server Protocol DTD v1.1)" },
175 /* Registered values - www.syncml.org */
176 { 0x0fd1, "-//SYNCML//DTD SyncML 1.0//EN (SyncML 1.0)" },
177 { 0x0fd3, "-//SYNCML//DTD SyncML 1.1//EN (SyncML 1.1)" },
179 /* Registered values - www.wapforum.org/wina/ */
180 { 0x1100, "-//PHONE.COM//DTD ALERT 1.0//EN" },
181 { 0x1101, "-//PHONE.COM//DTD CACHE-OPERATION 1.0//EN" },
182 { 0x1102, "-//PHONE.COM//DTD SIGNAL 1.0//EN" },
183 { 0x1103, "-//PHONE.COM//DTD LIST 1.0//EN" },
184 { 0x1104, "-//PHONE.COM//DTD LISTCMD 1.0//EN" },
185 { 0x1105, "-//PHONE.COM//DTD CHANNEL 1.0//EN" },
186 { 0x1106, "-//PHONE.COM//DTD MMC 1.0//EN" },
187 { 0x1107, "-//PHONE.COM//DTD BEARER-CHOICE 1.0//EN" },
188 { 0x1108, "-//PHONE.COM//DTD WML 1.1//EN (WML+ 1.1)" },
189 { 0x1109, "-//PHONE.COM//DTD CHANNEL 1.1//EN" },
190 { 0x110a, "-//PHONE.COM//DTD LIST 1.1//EN" },
191 { 0x110b, "-//PHONE.COM//DTD LISTCMD 1.1//EN" },
192 { 0x110c, "-//PHONE.COM//DTD MMC 1.1//EN" },
193 { 0x110d, "-//PHONE.COM//DTD WML 1.3//EN (WML+ 1.3)" },
194 { 0x110e, "-//PHONE.COM//DTD MMC 2.0//EN" },
195 /* 0x110F -- 0x11FF: unassigned */
196 { 0x1200, "-//3GPP2.COM//DTD IOTA 1.0//EN" },
201 static const value_string vals_wbxml_versions[] = {
202 { 0x00, "1.0" }, /* WAP-104-WBXML */
203 { 0x01, "1.1" }, /* WAP-135-WBXML */
204 { 0x02, "1.2" }, /* WAP-154-WBXML */
205 { 0x03, "1.3" }, /* WAP-192-WBXML */
210 /* WBXML 1.0 global tokens: WAP-104-WBXML
211 * Same token mapping as in vals_wbxml1x_global_tokens, but:
212 * { 0xC3, "RESERVED_2" }
215 /* WBXML 1.x (x>0) global tokens: WAP-135-WBXML, WAP-154-WBXML, WAP-192-WBXML
217 static const value_string vals_wbxml1x_global_tokens[] = {
218 { 0x00, "SWITCH_PAGE" },
228 { 0x44, "LITERAL_C" },
234 { 0x84, "LITERAL_A" },
240 { 0xC4, "LITERAL_AC" },
246 /********************** WBXML token mapping definition **********************/
251 * Wireless Markup Language
252 ***************************************/
254 /***** Global extension tokens *****/
255 static const value_string wbxml_wmlc10_global_cp0[] = {
256 { 0x40, "Variable substitution - escaped" },
257 { 0x41, "Variable substitution - unescaped" },
258 { 0x42, "Variable substitution - no transformation" },
259 { 0x80, "Variable substitution - escaped" },
260 { 0x81, "Variable substitution - unescaped" },
261 { 0x82, "Variable substitution - no transformation" },
262 { 0xC0, "Reserved" },
263 { 0xC1, "Reserved" },
264 { 0xC2, "Reserved" },
269 /***** Tag tokens *****/
270 static const value_string wbxml_wmlc10_tags_cp0[] = {
271 /* 0x00 -- 0x04 GLOBAL */
281 { 0xEA, "FIELDSET" },
291 { 0xF4, "OPTGROUP" },
298 { 0xFB, "TEMPLATE" },
307 /***** Attribute Start tokens *****/
308 static const value_string wbxml_wmlc10_attrStart_cp0[] = {
309 /* 0x00 -- 0x04 GLOBAL */
310 { 0x05, "ACCEPT-CHARSET=" },
311 { 0x06, "ALIGN='BOTTOM'" },
312 { 0x07, "ALIGN='CENTER'" },
313 { 0x08, "ALIGN='LEFT'" },
314 { 0x09, "ALIGN='MIDDLE'" },
315 { 0x0A, "ALIGN='RIGHT'" },
316 { 0x0B, "ALIGN='TOP'" },
318 { 0x0D, "CONTENT=" },
319 { 0x0E, "DEFAULT=" },
321 { 0x10, "EMPTYOK='FALSE'" },
322 { 0x11, "EMPTYOK='TRUE'" },
326 { 0x15, "IDEFAULT=" },
330 { 0x19, "LOCALSRC=" },
331 { 0x1A, "MAXLENGTH=" },
332 { 0x1B, "METHOD='GET'" },
333 { 0x1C, "METHOD='POST'" },
334 { 0x1D, "MODE='NOWRAP'" },
335 { 0x1E, "MODE='WRAP'" },
336 { 0x1F, "MULTIPLE='FALSE'" },
337 { 0x20, "MULTIPLE='TRUE'" },
339 { 0x22, "NEWCONTEXT='FALSE'" },
340 { 0x23, "NEWCONTEXT='TRUE'" },
341 { 0x24, "ONCLICK=" },
342 { 0x25, "ONENTERBACKWARD=" },
343 { 0x26, "ONENTERFORWARD=" },
344 { 0x27, "ONTIMER=" },
345 { 0x28, "OPTIONAL='FALSE'" },
346 { 0x29, "OPTIONAL='TRUE'" },
348 { 0x2B, "POSTDATA=" },
349 { 0x2C, "PUBLIC='FALSE'" },
350 { 0x2D, "PUBLIC='TRUE'" },
352 { 0x2F, "SENDREFERER='FALSE'" },
353 { 0x30, "SENDREFERER='TRUE'" },
356 { 0x33, "STYLE='LIST'" },
357 { 0x34, "STYLE='SET'" },
358 { 0x35, "TABINDEX=" },
361 { 0x38, "TYPE='ACCEPT'" },
362 { 0x39, "TYPE='DELETE'" },
363 { 0x3A, "TYPE='HELP'" },
364 { 0x3B, "TYPE='PASSWORD'" },
365 { 0x3C, "TYPE='ONCLICK'" },
366 { 0x3D, "TYPE='ONENTERBACKWARD'" },
367 { 0x3E, "TYPE='ONENTERFORWARD'" },
368 { 0x3F, "TYPE='ONTIMER'" },
369 /* 0x40 -- 0x44 GLOBAL */
370 { 0x45, "TYPE='OPTIONS'" },
371 { 0x46, "TYPE='PREV'" },
372 { 0x47, "TYPE='RESET'" },
373 { 0x48, "TYPE='TEXT'" },
374 { 0x49, "TYPE='vnd.'" },
376 { 0x4B, "URL='http://'" },
377 { 0x4C, "URL='https://'" },
378 { 0x4D, "USER-AGENT=" },
382 { 0x51, "xml:lang=" },
387 /***** Attribute Value tokens *****/
388 static const value_string wbxml_wmlc10_attrValue_cp0[] = {
389 /* 0x80 -- 0x84 GLOBAL */
394 { 0x89, "'ACCEPT'" },
395 { 0x8A, "'BOTTOM'" },
397 { 0x8C, "'DELETE'" },
399 { 0x8E, "'http://'" },
400 { 0x8F, "'http://www.'" },
401 { 0x90, "'https://'" },
402 { 0x91, "'https://www.'" },
404 { 0x93, "'MIDDLE'" },
405 { 0x94, "'NOWRAP'" },
406 { 0x95, "'ONCLICK'" },
407 { 0x96, "'ONENTERBACKWARD'" },
408 { 0x97, "'ONENTERFORWARD'" },
409 { 0x98, "'ONTIMER'" },
410 { 0x99, "'OPTIONS'" },
411 { 0x9A, "'PASSWORD'" },
416 { 0x9F, "'UNKNOWN'" },
423 /***** Token code page aggregation *****/
424 static const value_valuestring wbxml_wmlc10_global[] = {
425 { 0, wbxml_wmlc10_global_cp0 },
429 static const value_valuestring wbxml_wmlc10_tags[] = {
430 { 0, wbxml_wmlc10_tags_cp0 },
434 static const value_valuestring wbxml_wmlc10_attrStart[] = {
435 { 0, wbxml_wmlc10_attrStart_cp0 },
439 static const value_valuestring wbxml_wmlc10_attrValue[] = {
440 { 0, wbxml_wmlc10_attrValue_cp0 },
450 * Wireless Markup Language
451 ***************************************/
453 /***** Global extension tokens *****/
454 /* Same as in WML 1.0 */
456 /***** Tag tokens *****/
457 static const value_string wbxml_wmlc11_tags_cp0[] = {
458 /* 0x00 -- 0x04 GLOBAL */
465 { 0x21, "postfield" },
474 { 0x2A, "fieldset" },
484 { 0x34, "optgroup" },
491 { 0x3B, "template" },
500 /***** Attribute Start tokens *****/
501 static const value_string wbxml_wmlc11_attrStart_cp0[] = {
502 /* 0x00 -- 0x04 GLOBAL */
503 { 0x05, "accept-charset=" },
504 { 0x06, "align='bottom'" },
505 { 0x07, "align='center'" },
506 { 0x08, "align='left'" },
507 { 0x09, "align='middle'" },
508 { 0x0A, "align='right'" },
509 { 0x0B, "align='top'" },
511 { 0x0D, "content=" },
514 { 0x10, "emptyok='false'" },
515 { 0x11, "emptyok='true'" },
523 { 0x19, "localsrc=" },
524 { 0x1A, "maxlength=" },
525 { 0x1B, "method='get'" },
526 { 0x1C, "method='post'" },
527 { 0x1D, "mode='nowrap'" },
528 { 0x1E, "mode='wrap'" },
529 { 0x1F, "multiple='false'" },
530 { 0x20, "multiple='true'" },
532 { 0x22, "newcontext='false'" },
533 { 0x23, "newcontext='true'" },
535 { 0x25, "onenterbackward=" },
536 { 0x26, "onenterforward=" },
537 { 0x27, "ontimer=" },
538 { 0x28, "optional='false'" },
539 { 0x29, "optional='true'" },
543 { 0x2F, "sendreferer='false'" },
544 { 0x30, "sendreferer='true'" },
547 { 0x33, "ordered='false'" },
548 { 0x34, "ordered='true'" },
549 { 0x35, "tabindex=" },
552 { 0x38, "type='accept'" },
553 { 0x39, "type='delete'" },
554 { 0x3A, "type='help'" },
555 { 0x3B, "type='password'" },
556 { 0x3C, "type='onpick'" },
557 { 0x3D, "type='onenterbackward'" },
558 { 0x3E, "type='onenterforward'" },
559 { 0x3F, "type='ontimer'" },
560 /* 0x40 -- 0x44 GLOBAL */
561 { 0x45, "type='options'" },
562 { 0x46, "type='prev'" },
563 { 0x47, "type='reset'" },
564 { 0x48, "type='text'" },
565 { 0x49, "type='vnd.'" },
567 { 0x4B, "href='http://'" },
568 { 0x4C, "href='https://'" },
572 { 0x50, "xml:lang=" },
575 { 0x53, "columns=" },
578 { 0x56, "forua='false'" },
579 { 0x57, "forua='true'" },
580 { 0x58, "src='http://'" },
581 { 0x59, "src='https://'" },
582 { 0x5A, "http-equiv=" },
583 { 0x5B, "http-equiv='Content-Type'" },
584 { 0x5C, "content='application/vnd.wap.wmlc;charset='" },
585 { 0x5D, "http-equiv='Expires'" },
590 /***** Attribute Value tokens *****/
591 static const value_string wbxml_wmlc11_attrValue_cp0[] = {
592 /* 0x80 -- 0x84 GLOBAL */
597 { 0x89, "'accept'" },
598 { 0x8A, "'bottom'" },
600 { 0x8C, "'delete'" },
602 { 0x8E, "'http://'" },
603 { 0x8F, "'http://www.'" },
604 { 0x90, "'https://'" },
605 { 0x91, "'https://www.'" },
607 { 0x93, "'middle'" },
608 { 0x94, "'nowrap'" },
609 { 0x95, "'onpick'" },
610 { 0x96, "'onenterbackward'" },
611 { 0x97, "'onenterforward'" },
612 { 0x98, "'ontimer'" },
613 { 0x99, "'options'" },
614 { 0x9A, "'password'" },
619 { 0x9F, "'unknown'" },
626 /***** Token code page aggregation *****/
627 static const value_valuestring wbxml_wmlc11_global[] = {
628 { 0, wbxml_wmlc10_global_cp0 }, /* Same as WML 1.0 */
632 static const value_valuestring wbxml_wmlc11_tags[] = {
633 { 0, wbxml_wmlc11_tags_cp0 },
637 static const value_valuestring wbxml_wmlc11_attrStart[] = {
638 { 0, wbxml_wmlc11_attrStart_cp0 },
642 static const value_valuestring wbxml_wmlc11_attrValue[] = {
643 { 0, wbxml_wmlc11_attrValue_cp0 },
653 * Wireless Markup Language
654 ***************************************/
656 /***** Global extension tokens *****/
657 /* Same as in WML 1.0 */
659 /***** Tag tokens *****/
660 static const value_string wbxml_wmlc12_tags_cp0[] = {
661 /* 0x00 -- 0x04 GLOBAL */
669 { 0x21, "postfield" },
678 { 0x2A, "fieldset" },
688 { 0x34, "optgroup" },
695 { 0x3B, "template" },
704 /***** Attribute Start tokens *****/
705 static const value_string wbxml_wmlc12_attrStart_cp0[] = {
706 /* 0x00 -- 0x04 GLOBAL */
707 { 0x05, "accept-charset=" },
708 { 0x06, "align='bottom'" },
709 { 0x07, "align='center'" },
710 { 0x08, "align='left'" },
711 { 0x09, "align='middle'" },
712 { 0x0A, "align='right'" },
713 { 0x0B, "align='top'" },
715 { 0x0D, "content=" },
718 { 0x10, "emptyok='false'" },
719 { 0x11, "emptyok='true'" },
727 { 0x19, "localsrc=" },
728 { 0x1A, "maxlength=" },
729 { 0x1B, "method='get'" },
730 { 0x1C, "method='post'" },
731 { 0x1D, "mode='nowrap'" },
732 { 0x1E, "mode='wrap'" },
733 { 0x1F, "multiple='false'" },
734 { 0x20, "multiple='true'" },
736 { 0x22, "newcontext='false'" },
737 { 0x23, "newcontext='true'" },
739 { 0x25, "onenterbackward=" },
740 { 0x26, "onenterforward=" },
741 { 0x27, "ontimer=" },
742 { 0x28, "optional='false'" },
743 { 0x29, "optional='true'" },
747 { 0x2F, "sendreferer='false'" },
748 { 0x30, "sendreferer='true'" },
751 { 0x33, "ordered='false'" },
752 { 0x34, "ordered='true'" },
753 { 0x35, "tabindex=" },
756 { 0x38, "type='accept'" },
757 { 0x39, "type='delete'" },
758 { 0x3A, "type='help'" },
759 { 0x3B, "type='password'" },
760 { 0x3C, "type='onpick'" },
761 { 0x3D, "type='onenterbackward'" },
762 { 0x3E, "type='onenterforward'" },
763 { 0x3F, "type='ontimer'" },
764 /* 0x40 -- 0x44 GLOBAL */
765 { 0x45, "type='options'" },
766 { 0x46, "type='prev'" },
767 { 0x47, "type='reset'" },
768 { 0x48, "type='text'" },
769 { 0x49, "type='vnd.'" },
771 { 0x4B, "href='http://'" },
772 { 0x4C, "href='https://'" },
776 { 0x50, "xml:lang=" },
779 { 0x53, "columns=" },
782 { 0x56, "forua='false'" },
783 { 0x57, "forua='true'" },
784 { 0x58, "src='http://'" },
785 { 0x59, "src='https://'" },
786 { 0x5A, "http-equiv=" },
787 { 0x5B, "http-equiv='Content-Type'" },
788 { 0x5C, "content='application/vnd.wap.wmlc;charset='" },
789 { 0x5D, "http-equiv='Expires'" },
790 { 0x5E, "accesskey=" },
791 { 0x5F, "enctype=" },
792 { 0x60, "enctype='application/x-www-form-urlencoded'" },
793 { 0x61, "enctype='multipart/form-data'" },
798 /***** Attribute Value tokens *****/
799 /* Same as in WML 1.1 */
801 /***** Token code page aggregation *****/
802 static const value_valuestring wbxml_wmlc12_global[] = {
803 { 0, wbxml_wmlc10_global_cp0 }, /* Same as WML 1.0 */
807 static const value_valuestring wbxml_wmlc12_tags[] = {
808 { 0, wbxml_wmlc12_tags_cp0 },
812 static const value_valuestring wbxml_wmlc12_attrStart[] = {
813 { 0, wbxml_wmlc12_attrStart_cp0 },
817 static const value_valuestring wbxml_wmlc12_attrValue[] = {
818 { 0, wbxml_wmlc11_attrValue_cp0 }, /* Same as WML 1.1 */
828 * Wireless Markup Language
829 ***************************************/
831 /***** Global extension tokens *****/
832 /* Same as in WML 1.0 */
834 /***** Tag tokens *****/
835 /* Same as in WML 1.2 */
837 /***** Attribute Start tokens *****/
838 static const value_string wbxml_wmlc13_attrStart_cp0[] = {
839 /* 0x00 -- 0x04 GLOBAL */
840 { 0x05, "accept-charset=" },
841 { 0x06, "align='bottom'" },
842 { 0x07, "align='center'" },
843 { 0x08, "align='left'" },
844 { 0x09, "align='middle'" },
845 { 0x0A, "align='right'" },
846 { 0x0B, "align='top'" },
848 { 0x0D, "content=" },
851 { 0x10, "emptyok='false'" },
852 { 0x11, "emptyok='true'" },
860 { 0x19, "localsrc=" },
861 { 0x1A, "maxlength=" },
862 { 0x1B, "method='get'" },
863 { 0x1C, "method='post'" },
864 { 0x1D, "mode='nowrap'" },
865 { 0x1E, "mode='wrap'" },
866 { 0x1F, "multiple='false'" },
867 { 0x20, "multiple='true'" },
869 { 0x22, "newcontext='false'" },
870 { 0x23, "newcontext='true'" },
872 { 0x25, "onenterbackward=" },
873 { 0x26, "onenterforward=" },
874 { 0x27, "ontimer=" },
875 { 0x28, "optional='false'" },
876 { 0x29, "optional='true'" },
880 { 0x2F, "sendreferer='false'" },
881 { 0x30, "sendreferer='true'" },
884 { 0x33, "ordered='false'" },
885 { 0x34, "ordered='true'" },
886 { 0x35, "tabindex=" },
889 { 0x38, "type='accept'" },
890 { 0x39, "type='delete'" },
891 { 0x3A, "type='help'" },
892 { 0x3B, "type='password'" },
893 { 0x3C, "type='onpick'" },
894 { 0x3D, "type='onenterbackward'" },
895 { 0x3E, "type='onenterforward'" },
896 { 0x3F, "type='ontimer'" },
897 /* 0x40 -- 0x44 GLOBAL */
898 { 0x45, "type='options'" },
899 { 0x46, "type='prev'" },
900 { 0x47, "type='reset'" },
901 { 0x48, "type='text'" },
902 { 0x49, "type='vnd.'" },
904 { 0x4B, "href='http://'" },
905 { 0x4C, "href='https://'" },
909 { 0x50, "xml:lang=" },
912 { 0x53, "columns=" },
915 { 0x56, "forua='false'" },
916 { 0x57, "forua='true'" },
917 { 0x58, "src='http://'" },
918 { 0x59, "src='https://'" },
919 { 0x5A, "http-equiv=" },
920 { 0x5B, "http-equiv='Content-Type'" },
921 { 0x5C, "content='application/vnd.wap.wmlc;charset='" },
922 { 0x5D, "http-equiv='Expires'" },
923 { 0x5E, "accesskey=" },
924 { 0x5F, "enctype=" },
925 { 0x60, "enctype='application/x-www-form-urlencoded'" },
926 { 0x61, "enctype='multipart/form-data'" },
927 { 0x62, "xml:space='preserve'" },
928 { 0x63, "xml:space='default'" },
929 { 0x64, "cache-control='no-cache'" },
934 /***** Attribute Value tokens *****/
935 /* Same as in WML 1.1 */
937 /***** Token code page aggregation *****/
938 static const value_valuestring wbxml_wmlc13_global[] = {
939 { 0, wbxml_wmlc10_global_cp0 }, /* Same as WML 1.0 */
943 static const value_valuestring wbxml_wmlc13_tags[] = {
944 { 0, wbxml_wmlc12_tags_cp0 },
948 static const value_valuestring wbxml_wmlc13_attrStart[] = {
949 { 0, wbxml_wmlc13_attrStart_cp0 },
953 static const value_valuestring wbxml_wmlc13_attrValue[] = {
954 { 0, wbxml_wmlc11_attrValue_cp0 }, /* Same as WML 1.1 */
965 ***************************************/
967 /***** Global extension tokens *****/
969 /***** Tag tokens *****/
970 static const value_string wbxml_sic10_tags_cp0[] = {
971 /* 0x00 -- 0x04 GLOBAL */
973 { 0x06, "indication" },
980 /***** Attribute Start tokens *****/
981 static const value_string wbxml_sic10_attrStart_cp0[] = {
982 /* 0x00 -- 0x04 GLOBAL */
983 { 0x05, "action='signal-none'" },
984 { 0x06, "action='signal-low'" },
985 { 0x07, "action='signal-medium'" },
986 { 0x08, "action='signal-high'" },
987 { 0x09, "action='delete'" },
988 { 0x0a, "created=" },
990 { 0x0c, "href='http://'" },
991 { 0x0d, "href='http://www.'" },
992 { 0x0e, "href='https://'" },
993 { 0x0f, "href='https://www.'" },
994 { 0x10, "si-expires=" },
1001 /***** Attribute Value tokens *****/
1002 static const value_string wbxml_sic10_attrValue_cp0[] = {
1003 /* 0x80 -- 0x84 GLOBAL */
1004 { 0x85, "'.com/'" },
1005 { 0x86, "'.edu/'" },
1006 { 0x87, "'.net/'" },
1007 { 0x88, "'.org/'" },
1012 /***** Token code page aggregation *****/
1013 static const value_valuestring wbxml_sic10_tags[] = {
1014 { 0, wbxml_sic10_tags_cp0 },
1018 static const value_valuestring wbxml_sic10_attrStart[] = {
1019 { 0, wbxml_sic10_attrStart_cp0 },
1023 static const value_valuestring wbxml_sic10_attrValue[] = {
1024 { 0, wbxml_sic10_attrValue_cp0 },
1035 ***************************************/
1037 /***** Global extension tokens *****/
1039 /***** Tag tokens *****/
1040 static const value_string wbxml_slc10_tags_cp0[] = {
1041 /* 0x00 -- 0x04 GLOBAL */
1047 /***** Attribute Start tokens *****/
1048 static const value_string wbxml_slc10_attrStart_cp0[] = {
1049 /* 0x00 -- 0x04 GLOBAL */
1050 { 0x05, "action='execute-low'" },
1051 { 0x06, "action='execute-high'" },
1052 { 0x07, "action='cache'" },
1054 { 0x09, "href='http://'" },
1055 { 0x0a, "href='http://www.'" },
1056 { 0x0b, "href='https://'" },
1057 { 0x0c, "href='https://www.'" },
1062 /***** Attribute Value tokens *****/
1063 /* Same as in SI 1.0 */
1065 /***** Token code page aggregation *****/
1066 static const value_valuestring wbxml_slc10_tags[] = {
1067 { 0, wbxml_slc10_tags_cp0 },
1071 static const value_valuestring wbxml_slc10_attrStart[] = {
1072 { 0, wbxml_slc10_attrStart_cp0 },
1076 static const value_valuestring wbxml_slc10_attrValue[] = {
1077 { 0, wbxml_sic10_attrValue_cp0 }, /* Same as SI 1.0 */
1088 ***************************************/
1090 /***** Global extension tokens *****/
1092 /***** Tag tokens *****/
1093 static const value_string wbxml_coc10_tags_cp0[] = {
1094 /* 0x00 -- 0x04 GLOBAL */
1096 { 0x06, "invalidate-object" },
1097 { 0x07, "invalidate-service" },
1102 /***** Attribute Start tokens *****/
1103 static const value_string wbxml_coc10_attrStart_cp0[] = {
1104 /* 0x00 -- 0x04 GLOBAL */
1106 { 0x06, "uri='http://'" },
1107 { 0x07, "uri='http://www.'" },
1108 { 0x08, "uri='https://'" },
1109 { 0x09, "uri='https://www.'" },
1114 /***** Attribute Value tokens *****/
1115 /* Same as in SI 1.0 */
1117 /***** Token code page aggregation *****/
1118 static const value_valuestring wbxml_coc10_tags[] = {
1119 { 0, wbxml_coc10_tags_cp0 },
1123 static const value_valuestring wbxml_coc10_attrStart[] = {
1124 { 0, wbxml_coc10_attrStart_cp0 },
1128 static const value_valuestring wbxml_coc10_attrValue[] = {
1129 { 0, wbxml_sic10_attrValue_cp0 }, /* Same as SI 1.0 */
1139 * Client Provisioning
1140 ***************************************/
1142 /***** Global extension tokens *****/
1144 /***** Tag tokens *****/
1145 static const value_string wbxml_provc10_tags_cp0[] = {
1146 /* 0x00 -- 0x04 GLOBAL */
1147 { 0x05, "wap-provisioningdoc" },
1148 { 0x06, "characteristic" },
1154 /***** Attribute Start tokens *****/
1155 static const value_string wbxml_provc10_attrStart_cp0[] = {
1156 /* 0x00 -- 0x04 GLOBAL */
1159 { 0x07, "name='NAME'" },
1160 { 0x08, "name='NAP-ADDRESS'" },
1161 { 0x09, "name='NAP-ADDRTYPE'" },
1162 { 0x0A, "name='CALLTYPE'" },
1163 { 0x0B, "name='VALIDUNTIL'" },
1164 { 0x0C, "name='AUTHTYPE'" },
1165 { 0x0D, "name='AUTHNAME'" },
1166 { 0x0E, "name='AUTHSECRET'" },
1167 { 0x0F, "name='LINGER'" },
1168 { 0x10, "name='BEARER'" },
1169 { 0x11, "name='NAPID'" },
1170 { 0x12, "name='COUNTRY'" },
1171 { 0x13, "name='NETWORK'" },
1172 { 0x14, "name='INTERNET'" },
1173 { 0x15, "name='PROXY-ID'" },
1174 { 0x16, "name='PROXY-PROVIDER-ID'" },
1175 { 0x17, "name='DOMAIN'" },
1176 { 0x18, "name='PROVURL'" },
1177 { 0x19, "name='PXAUTH-TYPE'" },
1178 { 0x1A, "name='PXAUTH-ID'" },
1179 { 0x1B, "name='PXAUTH-PW'" },
1180 { 0x1C, "name='STARTPAGE'" },
1181 { 0x1D, "name='BASAUTH-ID'" },
1182 { 0x1E, "name='BASAUTH-PW'" },
1183 { 0x1F, "name='PUSHENABLED'" },
1184 { 0x20, "name='PXADDR'" },
1185 { 0x21, "name='PXADDRTYPE'" },
1186 { 0x22, "name='TO-NAPID'" },
1187 { 0x23, "name='PORTNBR'" },
1188 { 0x24, "name='SERVICE'" },
1189 { 0x25, "name='LINKSPEED'" },
1190 { 0x26, "name='DNLINKSPEED'" },
1191 { 0x27, "name='LOCAL-ADDR'" },
1192 { 0x28, "name='LOCAL-ADDRTYPE'" },
1193 { 0x29, "name='CONTEXT-ALLOW'" },
1194 { 0x2A, "name='TRUST'" },
1195 { 0x2B, "name='MASTER'" },
1196 { 0x2C, "name='SID'" },
1197 { 0x2D, "name='SOC'" },
1198 { 0x2E, "name='WSP-VERSION'" },
1199 { 0x2F, "name='PHYSICAL-PROXY-ID'" },
1200 { 0x30, "name='CLIENT-ID'" },
1201 { 0x31, "name='DELIVERY-ERR-SDU'" },
1202 { 0x32, "name='DELIVERY-ORDER'" },
1203 { 0x33, "name='TRAFFIC-CLASS'" },
1204 { 0x34, "name='MAX-SDU-SIZE'" },
1205 { 0x35, "name='MAX-BITRATE-UPLINK'" },
1206 { 0x36, "name='MAX-BITRATE-DNLINK'" },
1207 { 0x37, "name='RESIDUAL-BER'" },
1208 { 0x38, "name='SDU-ERROR-RATIO'" },
1209 { 0x39, "name='TRAFFIC-HANDL-PRIO'" },
1210 { 0x3A, "name='TRANSFER-DELAY'" },
1211 { 0x3B, "name='GUARANTEED-BITRATE-UPLINK'" },
1212 { 0x3C, "name='GUARANTEED-BITRATE-DNLINK'" },
1214 /* 0x40 -- 0x44 GLOBAL */
1215 { 0x45, "version=" },
1216 { 0x46, "version='1.0'" },
1219 { 0x51, "type='PXLOGICAL'" },
1220 { 0x52, "type='PXPHYSICAL'" },
1221 { 0x53, "type='PORT'" },
1222 { 0x54, "type='VALIDITY'" },
1223 { 0x55, "type='NAPDEF'" },
1224 { 0x56, "type='BOOTSTRAP'" },
1225 { 0x57, "type='VENDORCONFIG'" },
1226 { 0x58, "type='CLIENTIDENTITY'" },
1227 { 0x59, "type='PXAUTHINFO'" },
1228 { 0x5A, "type='NAPAUTHINFO'" },
1233 /***** Attribute Start tokens *****/
1234 static const value_string wbxml_provc10_attrValue_cp0[] = {
1235 /* 0x80 -- 0x84 GLOBAL */
1239 { 0x88, "'ALPHA'" },
1241 { 0x8A, "'SCODE'" },
1242 { 0x8B, "'TETRA-ITSI'" },
1245 { 0x90, "'ANALOG-MODEM'" },
1246 { 0x91, "'V.120'" },
1247 { 0x92, "'V.110'" },
1249 { 0x94, "'BIT-TRANSPARENT'" },
1250 { 0x95, "'DIRECT-ASYNCHRONOUS-DATA-SERVICE'" },
1254 { 0x9C, "'HTTP-BASIC'" },
1255 { 0x9D, "'HTTP-DIGEST'" },
1256 { 0x9E, "'WTLS-SS'" },
1258 { 0xA2, "'GSM-USSD'" },
1259 { 0xA3, "'GSM-SMS'" },
1260 { 0xA4, "'ANSI-136-GUTS'" },
1261 { 0xA5, "'IS-95-CDMA-SMS'" },
1262 { 0xA6, "'IS-95-CDMA-CSD'" },
1263 { 0xA7, "'IS-95-CDMA-PACKET'" },
1264 { 0xA8, "'ANSI-136-CSD'" },
1265 { 0xA9, "'ANSI-136-GPRS'" },
1266 { 0xAA, "'GSM-CSD'" },
1267 { 0xAB, "'GSM-GPRS'" },
1268 { 0xAC, "'AMPS-CDPD'" },
1269 { 0xAD, "'PDC-CSD'" },
1270 { 0xAE, "'PDC-PACKET'" },
1271 { 0xAF, "'IDEN-SMS'" },
1272 { 0xB0, "'IDEN-CSD'" },
1273 { 0xB1, "'IDEN-PACKET'" },
1274 { 0xB2, "'FLEX/REFLEX'" },
1275 { 0xB3, "'PHS-SMS'" },
1276 { 0xB4, "'PHS-CSD'" },
1277 { 0xB5, "'TETRA-SDS'" },
1278 { 0xB6, "'TETRA-PACKET'" },
1279 { 0xB7, "'ANSI-136-GHOST'" },
1280 { 0xB8, "'MOBITEX-MPAK'" },
1282 /* 0xC0 -- 0xC4 GLOBAL */
1283 { 0xC5, "'AUTOBAUDING'" },
1285 { 0xCA, "'CL-WSP'" },
1286 { 0xCB, "'CO-WSP'" },
1287 { 0xCC, "'CL-SEC-WSP'" },
1288 { 0xCD, "'CO-SEC-WSP'" },
1289 { 0xCE, "'CL-SEC-WTA'" },
1290 { 0xCF, "'CO-SEC-WTA'" },
1295 /***** Token code page aggregation *****/
1296 static const value_valuestring wbxml_provc10_tags[] = {
1297 { 0, wbxml_provc10_tags_cp0 },
1301 static const value_valuestring wbxml_provc10_attrStart[] = {
1302 { 0, wbxml_provc10_attrStart_cp0 },
1306 static const value_valuestring wbxml_provc10_attrValue[] = {
1307 { 0, wbxml_provc10_attrValue_cp0 },
1317 * Email Notification
1318 ***************************************/
1320 /***** Global extension tokens *****/
1322 /***** Tag tokens *****/
1323 static const value_string wbxml_emnc10_tags_cp0[] = {
1324 /* 0x00 -- 0x04 GLOBAL */
1330 /***** Attribute Start tokens *****/
1331 static const value_string wbxml_emnc10_attrStart_cp0[] = {
1332 /* 0x00 -- 0x04 GLOBAL */
1333 { 0x05, "timestamp=" },
1334 { 0x06, "mailbox=" },
1335 { 0x07, "mailbox='mailat:'" },
1336 { 0x08, "mailbox='pop://'" },
1337 { 0x09, "mailbox='imap://'" },
1338 { 0x0a, "mailbox='http://'" },
1339 { 0x0b, "mailbox='http://www.'" },
1340 { 0x0c, "mailbox='https://'" },
1341 { 0x0D, "mailbox='https://www.'" },
1346 /***** Attribute Value tokens *****/
1347 /* Same as in SI 1.0 */
1349 /***** Token code page aggregation *****/
1350 static const value_valuestring wbxml_emnc10_tags[] = {
1351 { 0, wbxml_emnc10_tags_cp0 },
1355 static const value_valuestring wbxml_emnc10_attrStart[] = {
1356 { 0, wbxml_emnc10_attrStart_cp0 },
1360 static const value_valuestring wbxml_emnc10_attrValue[] = {
1361 { 0, wbxml_sic10_attrValue_cp0 }, /* Same as SI 1.0 */
1371 * SyncML Representation Protocol
1372 ***************************************/
1374 /***** Global extension tokens *****/
1376 /***** Tag tokens *****/
1377 static const value_string wbxml_syncmlc10_tags_cp0[] = { /* SyncML 1.0 */
1378 /* 0x00 -- 0x04 GLOBAL */
1381 { 0x07, "Archive" },
1396 { 0x16, "LocName" },
1399 { 0x19, "MapItem" },
1404 { 0x1E, "NoResults" },
1406 { 0x20, "Replace" },
1407 { 0x21, "RespURI" },
1408 { 0x22, "Results" },
1410 { 0x24, "Sequence" },
1411 { 0x25, "SessionID" },
1414 { 0x28, "SourceRef" },
1417 { 0x2B, "SyncBody" },
1418 { 0x2C, "SyncHdr" },
1421 { 0x2F, "TargetRef" },
1422 /* 0x30 - Reserved */
1424 { 0x32, "VerProto" },
1429 static const value_string wbxml_syncmlc10_tags_cp1[] = { /* MetInf 1.0 */
1430 /* 0x00 -- 0x04 GLOBAL */
1435 { 0x09, "FreeMem" },
1438 { 0x0C, "MaxMsgSize" },
1442 { 0x10, "NextNonce" },
1443 { 0x11, "SharedMem" },
1446 { 0x14, "Version" },
1451 /***** Attribute Start tokens *****/
1453 /***** Attribute Value tokens *****/
1455 /***** Token code page aggregation *****/
1456 static const value_valuestring wbxml_syncmlc10_tags[] = {
1457 { 0, wbxml_syncmlc10_tags_cp0 }, /* -//SYNCML//DTD SyncML 1.0//EN */
1458 { 0, wbxml_syncmlc10_tags_cp1 }, /* -//SYNCML//DTD MetInf 1.0//EN */
1468 * SyncML Representation Protocol
1469 ***************************************/
1471 /***** Global extension tokens *****/
1473 /***** Tag tokens *****/
1474 static const value_string wbxml_syncmlc11_tags_cp0[] = { /* SyncML 1.1 */
1475 /* 0x00 -- 0x04 GLOBAL */
1478 { 0x07, "Archive" },
1493 { 0x16, "LocName" },
1496 { 0x19, "MapItem" },
1501 { 0x1e, "NoResults" },
1503 { 0x20, "Replace" },
1504 { 0x21, "RespURI" },
1505 { 0x22, "Results" },
1507 { 0x24, "Sequence" },
1508 { 0x25, "SessionID" },
1511 { 0x28, "SourceRef" },
1514 { 0x2b, "SyncBody" },
1515 { 0x2c, "SyncHdr" },
1518 { 0x2f, "TargetRef" },
1519 /* 0x30 - Reserved */
1521 { 0x32, "VerProto" },
1522 { 0x33, "NumberOfChanges" },
1523 { 0x34, "MoreData" },
1528 static const value_string wbxml_syncmlc11_tags_cp1[] = { /* MetInf 1.1 */
1529 /* 0x00 -- 0x04 GLOBAL */
1534 { 0x09, "FreeMem" },
1537 { 0x0C, "MaxMsgSize" },
1541 { 0x10, "NextNonce" },
1542 { 0x11, "SharedMem" },
1545 { 0x14, "Version" },
1546 { 0x15, "MaxObjSize" },
1551 /***** Attribute Start tokens *****/
1553 /***** Attribute Value tokens *****/
1555 /***** Token code page aggregation *****/
1556 static const value_valuestring wbxml_syncmlc11_tags[] = {
1557 { 0, wbxml_syncmlc11_tags_cp0 }, /* -//SYNCML//DTD SyncML 1.1//EN */
1558 { 0, wbxml_syncmlc11_tags_cp1 }, /* -//SYNCML//DTD MetInf 1.1//EN */
1569 ***************************************/
1571 /***** Global extension tokens *****/
1573 /***** Tag tokens *****/
1574 static const value_string wbxml_channelc10_tags_cp0[] = {
1575 /* 0x00 -- 0x04 GLOBAL */
1576 { 0x05, "channel" },
1578 { 0x07, "abstract" },
1579 { 0x08, "resource" },
1584 /***** Attribute Start tokens *****/
1585 static const value_string wbxml_channelc10_attrStart_cp0[] = {
1586 /* 0x00 -- 0x04 GLOBAL */
1587 { 0x05, "maxspace" },
1590 { 0x08, "href='http://'" },
1591 { 0x09, "href='https://'" },
1592 { 0x0A, "lastmod" },
1595 { 0x0D, "success" },
1596 { 0x0E, "success='http://'" },
1597 { 0x0F, "success='https://'" },
1598 { 0x10, "failure" },
1599 { 0x11, "failure='http://'" },
1600 { 0x12, "failure='https://'" },
1601 { 0x13, "EventId" },
1606 /***** Attribute Value tokens *****/
1608 /***** Token code page aggregation *****/
1609 static const value_valuestring wbxml_channelc10_tags[] = {
1610 { 0, wbxml_channelc10_tags_cp0 },
1614 static const value_valuestring wbxml_channelc10_attrStart[] = {
1615 { 0, wbxml_channelc10_attrStart_cp0 },
1623 /* application/x-wap-prov.browser-settings
1624 * application/x-wap-prov.browser-bookmarks
1626 * Nokia OTA Provisioning document format
1627 ***************************************/
1629 /***** Global extension tokens *****/
1631 /***** Tag tokens *****/
1632 static const value_string wbxml_nokiaprovc70_tags_cp0[] = {
1633 /* 0x00 -- 0x04 GLOBAL */
1634 { 0x05, "CHARACTERISTIC-LIST" },
1635 { 0x06, "CHARACTERISTIC" },
1641 /***** Attribute Start tokens *****/
1642 static const value_string wbxml_nokiaprovc70_attrStart_cp0[] = {
1643 /* 0x00 -- 0x04 GLOBAL */
1644 { 0x06, "TYPE='ADDRESS'" },
1645 { 0x07, "TYPE='URL'" },
1646 { 0x08, "TYPE='NAME'" },
1649 { 0x12, "NAME='BEARER'" },
1650 { 0x13, "NAME='PROXY'" },
1651 { 0x14, "NAME='PORT'" },
1652 { 0x15, "NAME='NAME'" },
1653 { 0x16, "NAME='PROXY_TYPE'" },
1654 { 0x17, "NAME='URL'" },
1655 { 0x18, "NAME='PROXY_AUTHNAME'" },
1656 { 0x19, "NAME='PROXY_AUTHSECRET'" },
1657 { 0x1A, "NAME='SMS_SMSC_ADDRESS'" },
1658 { 0x1B, "NAME='USSD_SERVICE_CODE'" },
1659 { 0x1C, "NAME='GPRS_ACCESSPOINTNAME'" },
1660 { 0x1D, "NAME='PPP_LOGINTYPE'" },
1661 { 0x1E, "NAME='PROXY_LOGINTYPE'" },
1662 { 0x21, "NAME='CSD_DIALSTRING'" },
1663 { 0x22, "NAME='PPP_AUTHTYPE'" },
1664 { 0x23, "NAME='PPP_AUTHNAME'" },
1665 { 0x24, "NAME='PPP_AUTHSECRET'" },
1666 { 0x28, "NAME='CSD_CALLTYPE'" },
1667 { 0x29, "NAME='CSD_CALLSPEED'" },
1668 { 0x45, "VALUE='GSM/CSD'" },
1669 { 0x46, "VALUE='GSM/SMS'" },
1670 { 0x47, "VALUE='GSM/USSD'" },
1671 { 0x48, "VALUE='IS-136/CSD'" },
1672 { 0x49, "VALUE='GPRS'" },
1673 { 0x60, "VALUE='9200'" },
1674 { 0x61, "VALUE='9201'" },
1675 { 0x62, "VALUE='9202'" },
1676 { 0x63, "VALUE='9203'" },
1677 { 0x64, "VALUE='AUTOMATIC'" },
1678 { 0x65, "VALUE='MANUAL'" },
1679 { 0x6A, "VALUE='AUTO'" },
1680 { 0x6B, "VALUE='9600'" },
1681 { 0x6C, "VALUE='14400'" },
1682 { 0x6D, "VALUE='19200'" },
1683 { 0x6E, "VALUE='28800'" },
1684 { 0x6F, "VALUE='38400'" },
1685 { 0x70, "VALUE='PAP'" },
1686 { 0x71, "VALUE='CHAP'" },
1687 { 0x72, "VALUE='ANALOGUE'" },
1688 { 0x73, "VALUE='ISDN'" },
1689 { 0x74, "VALUE='43200'" },
1690 { 0x75, "VALUE='57600'" },
1691 { 0x76, "VALUE='MSISDN_NO'" },
1692 { 0x77, "VALUE='IPV4'" },
1693 { 0x78, "VALUE='MS_CHAP'" },
1694 { 0x7C, "TYPE='MMSURL'" },
1695 { 0x7D, "TYPE='ID'" },
1696 { 0x7E, "NAME='ISP_NAME'" },
1697 { 0x7F, "TYPE='BOOKMARK'" },
1702 /***** Attribute Value tokens *****/
1704 /***** Token code page aggregation *****/
1705 static const value_valuestring wbxml_nokiaprovc70_tags[] = {
1706 { 0, wbxml_nokiaprovc70_tags_cp0 },
1710 static const value_valuestring wbxml_nokiaprovc70_attrStart[] = {
1711 { 0, wbxml_nokiaprovc70_attrStart_cp0 },
1720 /********************** WBXML token mapping aggregation **********************/
1723 /* The following structure links content types to their token mapping and
1724 * contains arrays of pointers to value_string arrays (one per code page).
1726 typedef struct _wbxml_token_map {
1727 const guint32 publicid; /* WBXML DTD number - see WINA (now OMNA) */
1728 const gchar *content_type; /* Content type if no WBXML DTD number */
1729 const guint8 defined; /* Are there mapping tables defined */
1730 const value_valuestring *global; /* Global token map */
1731 const value_valuestring *tags; /* Tag token map */
1732 const value_valuestring *attrStart; /* Attribute Start token map */
1733 const value_valuestring *attrValue; /* Attribute Value token map */
1736 static const wbxml_token_map *wbxml_content_map (guint32 publicid,
1737 const char *content_type);
1740 ** Aggregation of content type and aggregated code pages
1741 ** Content type map lookup will stop at the 1st entry with 3rd member = FALSE
1743 static const wbxml_token_map map[] = {
1744 #ifdef Test_the_WBXML_parser_without_token_mappings
1745 { 0, NULL, FALSE, NULL, NULL, NULL, NULL },
1747 { 0x02, NULL, TRUE, /* WML 1.0 */
1748 wbxml_wmlc10_global,
1750 wbxml_wmlc10_attrStart,
1751 wbxml_wmlc10_attrValue
1753 #ifdef remove_directive_and_set_TRUE_if_mapping_available
1754 { 0x03, NULL, FALSE, /* WTA 1.0 (deprecated) */
1755 NULL, NULL, NULL, NULL
1758 { 0x04, NULL, TRUE, /* WML 1.1 */
1759 wbxml_wmlc11_global,
1761 wbxml_wmlc11_attrStart,
1762 wbxml_wmlc11_attrValue
1764 { 0x05, NULL, TRUE, /* SI 1.0 */
1765 NULL, /* wbxml_sic10_global - does not exist */
1767 wbxml_sic10_attrStart,
1768 wbxml_sic10_attrValue
1770 { 0x06, NULL, TRUE, /* SL 1.0 */
1771 NULL, /* wbxml_slc10_global - does not exist */
1773 wbxml_slc10_attrStart,
1774 wbxml_slc10_attrValue
1776 { 0x07, NULL, TRUE, /* CO 1.0 */
1777 NULL, /* wbxml_coc10_global - does not exist */
1779 wbxml_coc10_attrStart,
1780 wbxml_coc10_attrValue
1782 { 0x08, NULL, TRUE, /* CHANNEL 1.0 (deprecated) */
1783 NULL, /* wbxml_channelc10_global - does not exist */
1784 wbxml_channelc10_tags,
1785 wbxml_channelc10_attrStart,
1786 NULL, /* wbxml_channelc10_attrValue - does not exist */
1788 { 0x09, NULL, TRUE, /* WML 1.2 */
1789 wbxml_wmlc12_global,
1791 wbxml_wmlc12_attrStart,
1792 wbxml_wmlc12_attrValue
1794 { 0x0A, NULL, TRUE, /* WML 1.3 */
1795 wbxml_wmlc13_global,
1797 wbxml_wmlc13_attrStart,
1798 wbxml_wmlc13_attrValue
1800 { 0x0B, NULL, TRUE, /* PROV 1.0 */
1801 NULL, /* wbxml_provc10_global - does not exist */
1803 wbxml_provc10_attrStart,
1804 wbxml_provc10_attrValue
1806 #ifdef remove_directive_and_set_TRUE_if_mapping_available
1807 { 0x0C, NULL, FALSE, /* WTA-WML 1.2 */
1808 NULL, NULL, NULL, NULL
1811 { 0x0D, NULL, TRUE, /* EMN 1.0 */
1812 NULL, /* wbxml_emnc10_global - does not exist */
1814 wbxml_emnc10_attrStart,
1815 wbxml_emnc10_attrValue
1817 #ifdef remove_directive_and_set_TRUE_if_mapping_available
1818 { 0x0E, NULL, FALSE, /* DRMREL 1.0 */
1819 NULL, NULL, NULL, NULL
1822 { 0x020B, NULL, TRUE, /* Nokia OTA Provisioning 7.0 */
1823 NULL, /* wbxml_nokiaprovc70_global - does not exist */
1824 wbxml_nokiaprovc70_tags,
1825 wbxml_nokiaprovc70_attrStart,
1826 NULL, /* wbxml_nokiaprovc70_attrValue - does not exist */
1828 { 0x0FD1, NULL, TRUE, /* SyncML 1.0 */
1829 NULL, /* wbxml_syncmlc10_global - does not exist */
1830 wbxml_syncmlc10_tags,
1831 NULL, /* wbxml_syncmlc10_attrStart - does not exist */
1832 NULL, /* wbxml_syncmlc10_attrValue - does not exist */
1834 { 0x0FD3, NULL, TRUE, /* SyncML 1.1 */
1835 NULL, /* wbxml_syncmlc11_global - does not exist */
1836 wbxml_syncmlc11_tags,
1837 NULL, /* wbxml_syncmlc11_attrStart - does not exist */
1838 NULL, /* wbxml_syncmlc11_attrValue - does not exist */
1840 { 0x1108, NULL, TRUE, /* Phone.com - WML+ 1.1 */
1841 /* Note: I assumed WML+ 1.1 would be not that different from WML 1.1,
1842 * the real mapping should come from Phone.com (OpenWave)! */
1843 wbxml_wmlc11_global, /* Not 100% true */
1844 wbxml_wmlc11_tags, /* Not 100% true */
1845 wbxml_wmlc11_attrStart, /* Not 100% true */
1846 wbxml_wmlc11_attrValue /* Not 100% true */
1848 { 0x110D, NULL, TRUE, /* Phone.com - WML+ 1.3 */
1849 /* Note: I assumed WML+ 1.3 would be not that different from WML 1.3,
1850 * the real mapping should come from Phone.com (OpenWave)! */
1851 wbxml_wmlc13_global, /* Not 100% true */
1852 wbxml_wmlc13_tags, /* Not 100% true */
1853 wbxml_wmlc13_attrStart, /* Not 100% true */
1854 wbxml_wmlc13_attrValue /* Not 100% true */
1857 { 0, NULL, FALSE, NULL, NULL, NULL, NULL }
1860 /* The following map contains entries only registered with a media type */
1861 static const wbxml_token_map textual_map[] = {
1862 { 0x00, "application/x-wap-prov.browser-settings", TRUE,
1863 NULL, /* wbxml_nokiaprovc70_global - does not exist */
1864 wbxml_nokiaprovc70_tags,
1865 wbxml_nokiaprovc70_attrStart,
1866 NULL, /* wbxml_nokiaprovc70_attrValue - does not exist */
1868 { 0x00, "application/x-wap-prov.browser-bookmarks", TRUE,
1869 NULL, /* wbxml_nokiaprovc70_global - does not exist */
1870 wbxml_nokiaprovc70_tags,
1871 wbxml_nokiaprovc70_attrStart,
1872 NULL, /* wbxml_nokiaprovc70_attrValue - does not exist */
1875 { 0, NULL, FALSE, NULL, NULL, NULL, NULL }
1878 /* WBXML content token mapping depends on the following parameters:
1879 * - Content type (guint32)
1880 * - Token type (global, tags, attrStart, attrValue)
1881 * - Code page for tag and attribute
1883 * This results in the following steps:
1884 * 1. Retrieve content type mapping
1885 * 2. If exists, retrieve token type mapping
1886 * 3. If exists, retrieve required code page
1887 * 4. If exists, retrieve token mapping
1890 #define wbxml_UNDEFINED_TOKEN \
1891 "(Requested token not defined for this content type)"
1892 #define wbxml_UNDEFINED_TOKEN_CODE_PAGE \
1893 "(Requested token code page not defined for this content type)"
1894 #define wbxml_UNDEFINED_TOKEN_MAP \
1895 "(Requested token map not defined for this content type)"
1896 /* Return token mapping for a given content mapping entry. */
1898 map_token (const value_valuestring *token_map, guint8 codepage, guint8 token) {
1899 const value_string *vs;
1902 if (token_map) { /* Found map */
1903 if ((vs = val_to_valstr (codepage, token_map))) {
1904 /* Found codepage map */
1905 s = match_strval (token, vs);
1906 if (s) { /* Found valid token */
1907 DebugLog(("map_token(codepage = %u, token = %u: [%s]\n", codepage, token, s));
1910 /* No valid token mapping in specified code page of token map */
1911 DebugLog(("map_token(codepage = %u, token = %u: "
1912 wbxml_UNDEFINED_TOKEN "\n", codepage, token));
1913 return wbxml_UNDEFINED_TOKEN;
1915 /* There is no token map entry for the requested code page */
1916 DebugLog(("map_token(codepage = %u, token = %u: "
1917 wbxml_UNDEFINED_TOKEN_CODE_PAGE "\n", codepage, token));
1918 return wbxml_UNDEFINED_TOKEN_CODE_PAGE;
1920 /* The token map does not exist */
1921 DebugLog(("map_token(codepage = %u, token = %u: "
1922 wbxml_UNDEFINED_TOKEN_MAP "\n", codepage, token));
1923 return wbxml_UNDEFINED_TOKEN_MAP;
1927 /* Returns a pointer to the WBXML token map for the given WBXML public
1928 * identifier value (see WINA for a table with defined identifiers). */
1929 static const wbxml_token_map *wbxml_content_map (guint32 publicid,
1930 const char *content_type) {
1933 DebugLog(("wbxml_token_map: publicid = %u, content_type = [%s]\n",
1934 publicid, content_type));
1935 /* First look whether we have a publicid mapping */
1936 while (map[i].defined) {
1937 if (map[i].publicid == publicid)
1941 /* Then look if the content type has a mapping */
1942 if (content_type && content_type[0]) {
1943 DebugLog(("wbxml_token_map(no match for publicid = %u;"
1944 " looking up content_type = [%s])\n",
1945 publicid, content_type));
1947 while(textual_map[i].defined) {
1948 if (strcasecmp(content_type, textual_map[i].content_type) == 0) {
1949 return &(textual_map[i]);
1954 DebugLog(("wbxml_token_map(no match for publicid = %u"
1955 " or content_type = [%s])\n",
1956 publicid, content_type));
1961 /************************** Function prototypes **************************/
1965 dissect_wbxml(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
1968 proto_register_wbxml(void);
1970 /* Parse and display the WBXML string table */
1972 show_wbxml_string_table (proto_tree *tree, tvbuff_t *tvb, guint32 str_tbl,
1973 guint32 str_tbl_len);
1975 /* Parse data while in STAG state */
1977 parse_wbxml_tag (proto_tree *tree, tvbuff_t *tvb, guint32 offset,
1978 guint32 str_tbl, guint8 *level);
1980 /* Parse data while in STAG state;
1981 * interpret tokens as defined by content type */
1983 parse_wbxml_tag_defined (proto_tree *tree, tvbuff_t *tvb, guint32 offset,
1984 guint32 str_tbl, guint8 *level,
1985 const wbxml_token_map *map);
1987 /* Parse data while in ATTR state */
1989 parse_wbxml_attribute_list (proto_tree *tree, tvbuff_t *tvb,
1990 guint32 offset, guint32 str_tbl, guint8 level);
1992 /* Parse data while in ATTR state;
1993 * interpret tokens as defined by content type */
1995 parse_wbxml_attribute_list_defined (proto_tree *tree, tvbuff_t *tvb,
1996 guint32 offset, guint32 str_tbl, guint8 level,
1997 const wbxml_token_map *map);
2000 /****************** WBXML protocol dissection functions ******************/
2003 /* Code to actually dissect the packets */
2005 dissect_wbxml(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2007 /* Set up structures needed to add the protocol subtree and manage it */
2009 proto_tree *wbxml_tree; /* Main WBXML tree */
2010 proto_tree *wbxml_str_tbl_tree; /* String table subtree */
2011 proto_tree *wbxml_content_tree; /* Content subtree */
2016 guint32 charset_len;
2018 guint32 publicid_index = 0;
2019 guint32 publicid_len;
2021 guint32 str_tbl_len;
2022 guint8 level = 0; /* WBXML recursion level */
2023 const wbxml_token_map *content_map = NULL;
2025 DebugLog(("dissect_wbxml: Dissecting packet %u\n", pinfo->fd->num));
2028 * Version 1.0: version publicid strtbl BODY
2029 * Version 1.x: version publicid charset strtbl BODY
2031 * Last valid format: WBXML 1.3
2033 switch ( version = tvb_get_guint8 (tvb, 0) ) {
2034 case 0x00: /* WBXML/1.0 */
2037 case 0x01: /* WBXML/1.1 */
2038 case 0x02: /* WBXML/1.2 */
2039 case 0x03: /* WBXML/1.3 */
2046 if (check_col(pinfo->cinfo, COL_INFO))
2047 col_append_fstr(pinfo->cinfo, COL_INFO, " (WBXML %s:",
2048 match_strval (version, vals_wbxml_versions));
2050 /* In the interest of speed, if "tree" is NULL, don't do any work not
2051 necessary to generate protocol tree items. */
2053 /* create display subtree for the protocol */
2054 ti = proto_tree_add_item (tree, proto_wbxml, tvb, 0, -1, FALSE);
2055 wbxml_tree = proto_item_add_subtree(ti, ett_wbxml);
2058 proto_tree_add_uint (wbxml_tree, hf_wbxml_version,
2059 tvb, 0, 1, version);
2062 publicid = tvb_get_guintvar(tvb, 1, &publicid_len);
2063 if (publicid) { /* Known Public ID */
2064 if (check_col(pinfo->cinfo, COL_INFO))
2065 col_append_fstr(pinfo->cinfo, COL_INFO, " Public ID \"%s\")",
2066 match_strval (publicid, vals_wbxml_public_ids));
2067 proto_tree_add_uint(wbxml_tree, hf_wbxml_public_id_known,
2068 tvb, 1, publicid_len, publicid);
2069 } else { /* Public identifier in string table */
2070 publicid_index = tvb_get_guintvar (tvb, 1+publicid_len, &len);
2071 publicid_len += len;
2073 offset = 1 + publicid_len;
2075 /* Version-specific handling of Charset */
2076 switch ( version ) {
2077 case 0x00: /* WBXML/1.0 */
2081 case 0x01: /* WBXML/1.1 */
2082 case 0x02: /* WBXML/1.2 */
2083 case 0x03: /* WBXML/1.3 */
2085 charset = tvb_get_guintvar (tvb, offset, &charset_len);
2086 offset += charset_len;
2089 default: /* Impossible since return already earlier */
2093 /* String table: read string table length in bytes */
2094 str_tbl_len = tvb_get_guintvar (tvb, offset, &len);
2095 str_tbl = offset + len; /* Start of 1st string in string table */
2097 /* Now we can add public ID, charset (if available),
2098 * and string table */
2099 if ( ! publicid ) { /* Read Public ID from string table */
2100 len = tvb_strsize (tvb, str_tbl+publicid_index);
2101 if (check_col(pinfo->cinfo, COL_INFO))
2102 col_append_fstr(pinfo->cinfo, COL_INFO, " Public ID \"%s\")",
2103 tvb_format_text (tvb,
2104 str_tbl+publicid_index,
2106 proto_tree_add_item (wbxml_tree, hf_wbxml_public_id_literal,
2107 tvb, 1, publicid_len, FALSE);
2109 if ( version ) { /* Charset */
2110 proto_tree_add_uint (wbxml_tree, hf_wbxml_charset,
2111 tvb, 1+publicid_len, charset_len, charset);
2114 ti = proto_tree_add_text(wbxml_tree,
2115 tvb, offset, len + str_tbl_len, "String table: %u bytes",
2118 if (wbxml_tree && str_tbl_len) { /* Display string table as subtree */
2119 wbxml_str_tbl_tree = proto_item_add_subtree (ti,
2121 show_wbxml_string_table (wbxml_str_tbl_tree, tvb,
2122 str_tbl, str_tbl_len);
2125 /* Data starts HERE */
2126 offset += len + str_tbl_len;
2128 /* The WBXML BODY starts here */
2129 ti = proto_tree_add_text (wbxml_tree, tvb, offset, -1,
2130 "Data representation");
2131 wbxml_content_tree = proto_item_add_subtree (ti, ett_wbxml_content);
2133 /* The parse_wbxml_X() functions will process the content correctly,
2134 * irrespective of the WBXML version used. For the WBXML body, this
2135 * means that there is a different processing for the global token
2136 * RESERVED_2 (WBXML 1.0) or OPAQUE (WBXML 1.x with x > 0). */
2137 if (wbxml_tree) { /* Show only if visible */
2139 /* Retrieve the content token mapping if available */
2140 content_map = wbxml_content_map (publicid, pinfo->match_string);
2142 /* Is there a defined token mapping for publicid? */
2143 if (content_map->defined) {
2144 if (content_map->content_type) {
2145 proto_item_append_text(ti,
2146 " is based on Content-Type: %s",
2147 content_map->content_type);
2149 proto_tree_add_text (wbxml_content_tree, tvb,
2151 "Level | State | Codepage "
2152 "| WBXML Token Description "
2154 len = parse_wbxml_tag_defined (wbxml_content_tree,
2155 tvb, offset, str_tbl, &level, content_map);
2159 proto_tree_add_text (wbxml_content_tree, tvb,
2161 "[Rendering of this content type"
2162 " not (yet) supported]");
2164 /* Default: WBXML only, no interpretation of the content */
2165 proto_tree_add_text (wbxml_content_tree, tvb, offset, -1,
2166 "Level | State | Codepage "
2167 "| WBXML Token Description "
2169 len = parse_wbxml_tag (wbxml_content_tree, tvb, offset,
2178 /* Parse and display the WBXML string table (in a 3-column table format).
2179 * This function displays:
2180 * - the offset in the string table,
2181 * - the length of the string
2185 show_wbxml_string_table (proto_tree *tree, tvbuff_t *tvb, guint32 str_tbl,
2186 guint32 str_tbl_len)
2188 guint32 off = str_tbl;
2190 guint32 end = str_tbl + str_tbl_len;
2192 proto_tree_add_text (tree, tvb, off, end,
2193 "Start | Length | String");
2195 len = tvb_strsize (tvb, off);
2196 proto_tree_add_text (tree, tvb, off, len,
2199 tvb_format_text (tvb, off, len-1));
2205 /* Indentation code is based on a static const array of space characters.
2206 * At least one single space is returned */
2207 static const char indent_buffer[514] = " "
2216 ; /* Generate XML indentation (length = 1 + 2 * 256 + 1 for '\0') */
2218 static const char * Indent (guint8 level) {
2219 return indent_buffer + (512 - 2 * (level));
2223 /********************
2224 * WBXML tag tokens *
2225 ********************
2227 * Bit Mask : Example
2228 * -------------------
2229 * 00.. .... : <tag />
2236 * atrtribute1="value1"
2237 * atrtribute2="value2"
2241 * atrtribute1="value1"
2242 * atrtribute2="value2"
2248 * - An XML PI is parsed as an attribute list (same syntax).
2249 * - A code page switch only applies to the single token that follows.
2253 /* This function parses the WBXML and maps known token interpretations
2254 * to the WBXML tokens. As a result, the original XML document can be
2255 * recreated. Indentation is generated in order to ease reading.
2257 * Attribute parsing is done in parse_wbxml_attribute_list_defined().
2259 * The wbxml_token_map entry *map contains the actual token mapping.
2261 * NOTE: In order to parse the content, some recursion is required.
2262 * However, for performance reasons, recursion has been avoided
2263 * where possible (tags without content within tags with content).
2264 * This is achieved by means of the parsing_tag_content and tag_save*
2267 * NOTE: See above for known token mappings.
2269 * NOTE: As tags can be opened and closed, a tag representation lookup
2270 * may happen once or twice for a given tag. For efficiency reasons,
2271 * the literal tag value is stored and used throughout the code.
2272 * With the introduction of code page support, this solution is robust
2273 * as the lookup only occurs once, removing the need for storage of
2274 * the used code page.
2277 parse_wbxml_tag_defined (proto_tree *tree, tvbuff_t *tvb, guint32 offset,
2278 guint32 str_tbl, guint8 *level,
2279 const wbxml_token_map *map)
2281 guint32 tvb_len = tvb_reported_length (tvb);
2282 guint32 off = offset;
2288 guint32 tag_len; /* Length of the index (uintvar) from a LITERAL tag */
2289 guint8 tag_save_known = 0; /* Will contain peek & 0x3F (tag identity) */
2290 guint8 tag_new_known = 0; /* Will contain peek & 0x3F (tag identity) */
2291 const char *tag_save_literal; /* Will contain the LITERAL tag identity */
2292 const char *tag_new_literal; /* Will contain the LITERAL tag identity */
2293 guint8 codepage_stag = 0; /* Initial codepage in state = STAG */
2294 guint8 parsing_tag_content = FALSE; /* Are we parsing content from a
2295 tag with content: <x>Content</x>
2297 The initial state is FALSE.
2298 This state will trigger recursion. */
2299 tag_save_literal = NULL; /* Prevents compiler warning */
2301 DebugLog(("parse_wbxml_tag_defined (level = %u, offset = %u)\n", *level, offset));
2302 while (off < tvb_len) {
2303 peek = tvb_get_guint8 (tvb, off);
2304 DebugLog(("STAG: (top of while) level = %3u, peek = 0x%02X, off = %u, tvb_len = %u\n", *level, peek, off, tvb_len));
2305 if ((peek & 0x3F) < 4) switch (peek) { /* Global tokens in state = STAG
2306 but not the LITERAL tokens */
2307 case 0x00: /* SWITCH_PAGE */
2308 codepage_stag = tvb_get_guint8 (tvb, off+1);
2309 proto_tree_add_text (tree, tvb, off, 2,
2310 " | Tag | T 0->%3d "
2311 "| SWITCH_PAGE (Tag code page) "
2316 case 0x01: /* END: only possible for Tag with Content */
2317 if (tag_save_known) { /* Known TAG */
2318 proto_tree_add_text (tree, tvb, off, 1,
2320 "| END (Known Tag 0x%02X) "
2322 *level, tag_save_known, Indent (*level),
2323 tag_save_literal); /* We already looked it up! */
2324 } else { /* Literal TAG */
2325 proto_tree_add_text (tree, tvb, off, 1,
2327 "| END (Literal Tag) "
2329 *level, Indent (*level),
2334 /* Reset code page: not needed as return from recursion */
2335 DebugLog(("STAG: level = %u, Return: len = %u\n", *level, off - offset));
2336 return (off - offset);
2338 case 0x02: /* ENTITY */
2339 ent = tvb_get_guintvar (tvb, off+1, &len);
2340 proto_tree_add_text (tree, tvb, off, 1+len,
2344 *level, Indent (*level), ent);
2347 case 0x03: /* STR_I */
2348 len = tvb_strsize (tvb, off+1);
2349 proto_tree_add_text (tree, tvb, off, 1+len,
2351 "| STR_I (Inline string) "
2353 *level, Indent(*level),
2354 tvb_format_text (tvb, off+1, len-1));
2357 case 0x40: /* EXT_I_0 */
2358 case 0x41: /* EXT_I_1 */
2359 case 0x42: /* EXT_I_2 */
2360 /* Extension tokens */
2361 len = tvb_strsize (tvb, off+1);
2362 if (codepage_stag) { /* Not default code page */
2363 proto_tree_add_text (tree, tvb, off, 1+len,
2364 " %3d | Tag | T %3d->0 "
2365 "| EXT_I_%1x (Extension Token) "
2367 *level, codepage_stag, peek & 0x0f, Indent (*level),
2368 map_token (map->global, codepage_stag, peek),
2369 tvb_format_text (tvb, off+1, len-1));
2370 /* Reset code page */
2372 } else { /* Code page 0 */
2373 proto_tree_add_text (tree, tvb, off, 1+len,
2375 "| EXT_I_%1x (Extension Token) "
2377 *level, peek & 0x0f, Indent (*level),
2378 map_token (map->global, codepage_stag, peek),
2379 tvb_format_text (tvb, off+1, len-1));
2384 proto_tree_add_text (tree, tvb, off, 1,
2386 "| PI (XML Processing Instruction) "
2388 *level, Indent (*level));
2389 len = parse_wbxml_attribute_list_defined (tree, tvb, off, str_tbl,
2391 /* Check that there is still room in packet */
2393 if (off >= tvb_len) {
2394 DebugLog(("STAG: level = %u, ThrowException: len = %u (short frame)\n", *level, off - offset));
2395 THROW(ReportedBoundsError);
2397 proto_tree_add_text (tree, tvb, off-1, 1,
2401 *level, Indent (*level));
2403 case 0x80: /* EXT_T_0 */
2404 case 0x81: /* EXT_T_1 */
2405 case 0x82: /* EXT_T_2 */
2406 /* Extension tokens */
2407 index = tvb_get_guintvar (tvb, off+1, &len);
2408 str_len = tvb_strsize (tvb, str_tbl+index);
2409 if (codepage_stag) { /* Not default code page */
2410 proto_tree_add_text (tree, tvb, off, 1+len,
2411 " %3d | Tag | T %3d->0 "
2412 "| EXT_T_%1x (Extension Token) "
2414 *level, codepage_stag, peek & 0x0f, Indent (*level),
2415 map_token (map->global, codepage_stag, peek),
2416 tvb_format_text (tvb, str_tbl+index, str_len-1));
2417 /* Reset code page */
2419 } else { /* Code page 0 */
2420 proto_tree_add_text (tree, tvb, off, 1+len,
2422 "| EXT_T_%1x (Extension Token) "
2424 *level, peek & 0x0f, Indent (*level),
2425 map_token (map->global, codepage_stag, peek),
2426 tvb_format_text (tvb, str_tbl+index, str_len-1));
2430 case 0x83: /* STR_T */
2431 index = tvb_get_guintvar (tvb, off+1, &len);
2432 str_len = tvb_strsize (tvb, str_tbl+index);
2433 proto_tree_add_text (tree, tvb, off, 1+len,
2435 "| STR_T (Tableref string) "
2437 *level, Indent (*level),
2438 tvb_format_text (tvb, str_tbl+index, str_len-1));
2441 case 0xC0: /* EXT_0 */
2442 case 0xC1: /* EXT_1 */
2443 case 0xC2: /* EXT_2 */
2444 /* Extension tokens */
2445 if (codepage_stag) { /* Not default code page */
2446 proto_tree_add_text (tree, tvb, off, 1,
2447 " %3d | Tag | T %3d->0 "
2448 "| EXT_%1x (Extension Token) "
2450 *level, codepage_stag, peek & 0x0f, Indent (*level),
2451 map_token (map->global, codepage_stag, peek));
2452 /* Reset code page */
2454 } else { /* Code page 0 */
2455 proto_tree_add_text (tree, tvb, off, 1,
2457 "| EXT_%1x (Extension Token) "
2459 *level, peek & 0x0f, Indent (*level),
2460 map_token (map->global, codepage_stag, peek));
2464 case 0xC3: /* OPAQUE - WBXML 1.1 and newer */
2465 if (tvb_get_guint8 (tvb, 0)) { /* WBXML 1.x (x > 0) */
2466 index = tvb_get_guintvar (tvb, off+1, &len);
2467 proto_tree_add_text (tree, tvb, off, 1 + len + index,
2469 "| OPAQUE (Opaque data) "
2470 "| %s(%d bytes of opaque data)",
2471 *level, Indent (*level), index);
2473 } else { /* WBXML 1.0 - RESERVED_2 token (invalid) */
2474 proto_tree_add_text (tree, tvb, off, 1,
2476 "| RESERVED_2 (Invalid Token!) "
2477 "| WBXML 1.0 parsing stops here.",
2479 /* Stop processing as it is impossible to parse now */
2481 DebugLog(("STAG: level = %u, Return: len = %u\n", *level, off - offset));
2482 return (off - offset);
2486 /* No default clause, as all cases have been treated */
2487 } else { /* LITERAL or Known TAG */
2488 /* We must store the initial tag, and also retrieve the new tag.
2489 * For efficiency reasons, we store the literal tag representation
2490 * for known tags too, so we can easily close the tag without the
2491 * need of a new lookup and avoiding storage of token codepage.
2493 * There are 4 possibilities:
2495 * 1. Known tag followed by a known tag
2496 * 2. Known tag followed by a LITERAL tag
2497 * 3. LITERAL tag followed by Known tag
2498 * 4. LITERAL tag followed by LITERAL tag
2501 /* Store the new tag */
2503 if ((peek & 0x3F) == 4) { /* LITERAL */
2504 DebugLog(("STAG: LITERAL tag (peek = 0x%02X, off = %u) - TableRef follows!\n", peek, off));
2505 index = tvb_get_guintvar (tvb, off+1, &tag_len);
2506 str_len = tvb_strsize (tvb, str_tbl+index);
2507 tag_new_literal = tvb_get_ptr (tvb, str_tbl+index, str_len);
2508 tag_new_known = 0; /* invalidate known tag_new */
2509 } else { /* Known tag */
2510 tag_new_known = peek & 0x3F;
2511 tag_new_literal = map_token (map->tags, codepage_stag,
2513 /* Stored looked up tag name string */
2516 /* Parsing of TAG starts HERE */
2517 if (peek & 0x40) { /* Content present */
2519 * [!] An explicit END token is expected in these cases!
2520 * ==> Recursion possible if we encounter a tag with content;
2521 * recursion will return at the explicit END token.
2523 if (parsing_tag_content) { /* Recurse */
2524 DebugLog(("STAG: Tag in Tag - RECURSE! (off = %u)\n", off));
2525 /* Do not process the attribute list:
2526 * recursion will take care of it */
2528 len = parse_wbxml_tag_defined (tree, tvb, off, str_tbl,
2531 } else { /* Now we will have content to parse */
2532 /* Save the start tag so we can properly close it later. */
2533 if ((peek & 0x3F) == 4) { /* Literal tag */
2534 tag_save_literal = tag_new_literal;
2536 } else { /* Known tag */
2537 tag_save_known = tag_new_known;
2538 tag_save_literal = tag_new_literal;
2539 /* The last statement avoids needless lookups */
2541 /* Process the attribute list if present */
2542 if (peek & 0x80) { /* Content and Attribute list present */
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 (AC) "
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 (AC) "
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_AC (Literal tag) (AC) "
2569 *level, Indent (*level), tag_new_literal);
2572 len = parse_wbxml_attribute_list_defined (tree, tvb,
2573 off, str_tbl, *level, map);
2574 /* Check that there is still room in packet */
2576 if (off >= tvb_len) {
2577 DebugLog(("STAG: level = %u, ThrowException: len = %u (short frame)\n", *level, off - offset));
2578 THROW(ReportedBoundsError);
2580 proto_tree_add_text (tree, tvb, off-1, 1,
2582 "| END (attribute list) "
2584 *level, Indent (*level));
2585 } else { /* Content, no Attribute list */
2586 if (tag_new_known) { /* Known tag */
2587 if (codepage_stag) { /* Not default code page */
2588 proto_tree_add_text (tree, tvb, off, 1,
2589 " %3d | Tag | T %3d->0 "
2590 "| Known Tag 0x%02X (.C) "
2592 *level, codepage_stag, tag_new_known,
2595 /* Tag string already looked up earlier! */
2596 /* Reset code page */
2598 } else { /* Code page 0 */
2599 proto_tree_add_text (tree, tvb, off, 1,
2601 "| Known Tag 0x%02X (.C) "
2603 *level, tag_new_known,
2606 /* Tag string already looked up earlier! */
2609 } else { /* LITERAL tag */
2610 proto_tree_add_text (tree, tvb, off, 1,
2612 "| LITERAL_C (Literal Tag) (.C) "
2614 *level, Indent (*level), tag_new_literal);
2618 /* The data that follows in the parsing process
2619 * represents content for the opening tag
2620 * we've just processed in the lines above.
2621 * Next time we encounter a tag with content: recurse
2623 parsing_tag_content = TRUE;
2624 DebugLog(("Tag in Tag - No recursion this time! (off = %u)\n", off));
2626 } else { /* No Content */
2627 DebugLog(("<Tag/> in Tag - No recursion! (off = %u)\n", off));
2629 if (peek & 0x80) { /* No Content, Attribute list present */
2630 if (tag_new_known) { /* Known tag */
2631 if (codepage_stag) { /* Not default code page */
2632 proto_tree_add_text (tree, tvb, off, 1,
2633 " %3d | Tag | T %3d->0 "
2634 "| Known Tag 0x%02X (A.) "
2636 *level, codepage_stag, tag_new_known,
2637 Indent (*level), tag_new_literal);
2638 /* Tag string already looked up earlier! */
2639 /* Reset code page */
2641 } else { /* Code page 0 */
2642 proto_tree_add_text (tree, tvb, off, 1,
2644 "| Known Tag 0x%02X (A.) "
2646 *level, tag_new_known,
2647 Indent (*level), tag_new_literal);
2648 /* Tag string already looked up earlier! */
2651 len = parse_wbxml_attribute_list_defined (tree, tvb,
2652 off, str_tbl, *level, map);
2653 /* Check that there is still room in packet */
2655 if (off >= tvb_len) {
2656 DebugLog(("STAG: level = %u, ThrowException: len = %u (short frame)\n", *level, off - offset));
2657 THROW(ReportedBoundsError);
2659 proto_tree_add_text (tree, tvb, off-1, 1,
2661 "| END (Known Tag) "
2663 *level, Indent (*level));
2664 } else { /* LITERAL tag */
2665 proto_tree_add_text (tree, tvb, off, 1,
2667 "| LITERAL_A (Literal Tag) (A.) "
2669 *level, Indent (*level), tag_new_literal);
2671 len = parse_wbxml_attribute_list_defined (tree, tvb,
2672 off, str_tbl, *level, map);
2673 /* Check that there is still room in packet */
2675 if (off >= tvb_len) {
2676 DebugLog(("STAG: level = %u, ThrowException: len = %u (short frame)\n", *level, off - offset));
2677 THROW(ReportedBoundsError);
2679 proto_tree_add_text (tree, tvb, off-1, 1,
2681 "| END (Literal Tag) "
2683 *level, Indent (*level));
2685 } else { /* No Content, No Attribute list */
2686 if (tag_new_known) { /* Known tag */
2687 if (codepage_stag) { /* Not default code page */
2688 proto_tree_add_text (tree, tvb, off, 1,
2689 " %3d | Tag | T %3d->0 "
2690 "| Known Tag 0x%02x (..) "
2692 *level, codepage_stag, tag_new_known,
2693 Indent (*level), tag_new_literal);
2694 /* Tag string already looked up earlier! */
2695 /* Reset code page */
2697 } else { /* Code page 0 */
2698 proto_tree_add_text (tree, tvb, off, 1,
2700 "| Known Tag 0x%02x (..) "
2702 *level, tag_new_known,
2703 Indent (*level), tag_new_literal);
2704 /* Tag string already looked up earlier! */
2707 } else { /* LITERAL tag */
2708 proto_tree_add_text (tree, tvb, off, 1,
2710 "| LITERAL (Literal Tag) (..) "
2712 *level, Indent (*level), tag_new_literal);
2717 /* TODO: Do I have to reset code page here? */
2719 } /* if (tag & 0x3F) >= 5 */
2721 DebugLog(("STAG: level = %u, Return: len = %u (end of function body)\n", *level, off - offset));
2722 return (off - offset);
2726 /* This function performs the WBXML decoding as in parse_wbxml_tag_defined()
2727 * but this time no WBXML mapping is performed.
2729 * Attribute parsing is done in parse_wbxml_attribute_list().
2732 parse_wbxml_tag (proto_tree *tree, tvbuff_t *tvb, guint32 offset,
2733 guint32 str_tbl, guint8 *level)
2735 guint32 tvb_len = tvb_reported_length (tvb);
2736 guint32 off = offset;
2742 guint32 tag_len; /* Length of the index (uintvar) from a LITERAL tag */
2743 guint8 tag_save_known = 0; /* Will contain peek & 0x3F (tag identity) */
2744 guint8 tag_new_known = 0; /* Will contain peek & 0x3F (tag identity) */
2745 const char *tag_save_literal; /* Will contain the LITERAL tag identity */
2746 const char *tag_new_literal; /* Will contain the LITERAL tag identity */
2747 char tag_save_buf[10]; /* Will contain "tag_0x%02X" */
2748 char tag_new_buf[10]; /* Will contain "tag_0x%02X" */
2749 guint8 codepage_stag = 0; /* Initial codepage in state = STAG */
2750 guint8 parsing_tag_content = FALSE; /* Are we parsing content from a
2751 tag with content: <x>Content</x>
2753 The initial state is FALSE.
2754 This state will trigger recursion. */
2755 tag_save_literal = NULL; /* Prevents compiler warning */
2757 DebugLog(("parse_wbxml_tag (level = %u, offset = %u)\n", *level, offset));
2758 while (off < tvb_len) {
2759 peek = tvb_get_guint8 (tvb, off);
2760 DebugLog(("STAG: (top of while) level = %3u, peek = 0x%02X, off = %u, tvb_len = %u\n", *level, peek, off, tvb_len));
2761 if ((peek & 0x3F) < 4) switch (peek) { /* Global tokens in state = STAG
2762 but not the LITERAL tokens */
2763 case 0x00: /* SWITCH_PAGE */
2764 codepage_stag = tvb_get_guint8 (tvb, off+1);
2765 proto_tree_add_text (tree, tvb, off, 2,
2766 " | Tag | T 0->%3d "
2767 "| SWITCH_PAGE (Tag code page) "
2772 case 0x01: /* END: only possible for Tag with Content */
2773 if (tag_save_known) { /* Known TAG */
2774 proto_tree_add_text (tree, tvb, off, 1,
2776 "| END (Known Tag 0x%02X) "
2778 *level, tag_save_known, Indent (*level),
2779 tag_save_literal); /* We already looked it up! */
2780 } else { /* Literal TAG */
2781 proto_tree_add_text (tree, tvb, off, 1,
2783 "| END (Literal Tag) "
2785 *level, Indent (*level),
2790 /* Reset code page: not needed as return from recursion */
2791 DebugLog(("STAG: level = %u, Return: len = %u\n", *level, off - offset));
2792 return (off - offset);
2794 case 0x02: /* ENTITY */
2795 ent = tvb_get_guintvar (tvb, off+1, &len);
2796 proto_tree_add_text (tree, tvb, off, 1+len,
2800 *level, Indent (*level), ent);
2803 case 0x03: /* STR_I */
2804 len = tvb_strsize (tvb, off+1);
2805 proto_tree_add_text (tree, tvb, off, 1+len,
2807 "| STR_I (Inline string) "
2809 *level, Indent(*level),
2810 tvb_format_text (tvb, off+1, len-1));
2813 case 0x40: /* EXT_I_0 */
2814 case 0x41: /* EXT_I_1 */
2815 case 0x42: /* EXT_I_2 */
2816 /* Extension tokens */
2817 len = tvb_strsize (tvb, off+1);
2818 if (codepage_stag) { /* Not default code page */
2819 proto_tree_add_text (tree, tvb, off, 1+len,
2820 " %3d | Tag | T %3d->0 "
2821 "| EXT_I_%1x (Extension Token) "
2822 "| %s(Inline string extension: \'%s\')",
2823 *level, codepage_stag, peek & 0x0f, Indent (*level),
2824 tvb_format_text (tvb, off+1, len-1));
2825 /* Reset code page */
2827 } else { /* Code page 0 */
2828 proto_tree_add_text (tree, tvb, off, 1+len,
2830 "| EXT_I_%1x (Extension Token) "
2831 "| %s(Inline string extension: \'%s\')",
2832 *level, peek & 0x0f, Indent (*level),
2833 tvb_format_text (tvb, off+1, len-1));
2838 proto_tree_add_text (tree, tvb, off, 1,
2840 "| PI (XML Processing Instruction) "
2842 *level, Indent (*level));
2843 len = parse_wbxml_attribute_list (tree, tvb, off, str_tbl, *level);
2844 /* Check that there is still room in packet */
2846 if (off >= tvb_len) {
2847 DebugLog(("STAG: level = %u, ThrowException: len = %u (short frame)\n", *level, off - offset));
2848 THROW(ReportedBoundsError);
2850 proto_tree_add_text (tree, tvb, off-1, 1,
2854 *level, Indent (*level));
2856 case 0x80: /* EXT_T_0 */
2857 case 0x81: /* EXT_T_1 */
2858 case 0x82: /* EXT_T_2 */
2859 /* Extension tokens */
2860 index = tvb_get_guintvar (tvb, off+1, &len);
2861 str_len = tvb_strsize (tvb, str_tbl+index);
2862 if (codepage_stag) { /* Not default code page */
2863 proto_tree_add_text (tree, tvb, off, 1+len,
2864 " %3d | Tag | T %3d->0 "
2865 "| EXT_T_%1x (Extension Token) "
2866 "| %s(Tableref string extension: \'%s\')",
2867 *level, codepage_stag, peek & 0x0f, Indent (*level),
2868 tvb_format_text (tvb, str_tbl+index, str_len-1));
2869 /* Reset code page */
2871 } else { /* Code page 0 */
2872 proto_tree_add_text (tree, tvb, off, 1+len,
2874 "| EXT_T_%1x (Extension Token) "
2875 "| %s(Tableref string extension: \'%s\')",
2876 *level, peek & 0x0f, Indent (*level),
2877 tvb_format_text (tvb, str_tbl+index, str_len-1));
2881 case 0x83: /* STR_T */
2882 index = tvb_get_guintvar (tvb, off+1, &len);
2883 str_len = tvb_strsize (tvb, str_tbl+index);
2884 proto_tree_add_text (tree, tvb, off, 1+len,
2886 "| STR_T (Tableref string) "
2888 *level, Indent (*level),
2889 tvb_format_text (tvb, str_tbl+index, str_len-1));
2892 case 0xC0: /* EXT_0 */
2893 case 0xC1: /* EXT_1 */
2894 case 0xC2: /* EXT_2 */
2895 /* Extension tokens */
2896 if (codepage_stag) { /* Not default code page */
2897 proto_tree_add_text (tree, tvb, off, 1,
2898 " %3d | Tag | T %3d->0 "
2899 "| EXT_%1x (Extension Token) "
2900 "| %s(Single-byte extension)",
2901 *level, codepage_stag, peek & 0x0f,
2903 /* Reset code page */
2905 } else { /* Code page 0 */
2906 proto_tree_add_text (tree, tvb, off, 1,
2908 "| EXT_%1x (Extension Token) "
2909 "| %s(Single-byte extension)",
2910 *level, peek & 0x0f, Indent (*level));
2914 case 0xC3: /* OPAQUE - WBXML 1.1 and newer */
2915 if (tvb_get_guint8 (tvb, 0)) { /* WBXML 1.x (x > 0) */
2916 index = tvb_get_guintvar (tvb, off+1, &len);
2917 proto_tree_add_text (tree, tvb, off, 1 + len + index,
2919 "| OPAQUE (Opaque data) "
2920 "| %s(%d bytes of opaque data)",
2921 *level, Indent (*level), index);
2923 } else { /* WBXML 1.0 - RESERVED_2 token (invalid) */
2924 proto_tree_add_text (tree, tvb, off, 1,
2926 "| RESERVED_2 (Invalid Token!) "
2927 "| WBXML 1.0 parsing stops here.",
2929 /* Stop processing as it is impossible to parse now */
2931 DebugLog(("STAG: level = %u, Return: len = %u\n", *level, off - offset));
2932 return (off - offset);
2936 /* No default clause, as all cases have been treated */
2937 } else { /* LITERAL or Known TAG */
2938 /* We must store the initial tag, and also retrieve the new tag.
2939 * For efficiency reasons, we store the literal tag representation
2940 * for known tags too, so we can easily close the tag without the
2941 * need of a new lookup and avoiding storage of token codepage.
2943 * There are 4 possibilities:
2945 * 1. Known tag followed by a known tag
2946 * 2. Known tag followed by a LITERAL tag
2947 * 3. LITERAL tag followed by Known tag
2948 * 4. LITERAL tag followed by LITERAL tag
2951 /* Store the new tag */
2953 if ((peek & 0x3F) == 4) { /* LITERAL */
2954 DebugLog(("STAG: LITERAL tag (peek = 0x%02X, off = %u) - TableRef follows!\n", peek, off));
2955 index = tvb_get_guintvar (tvb, off+1, &tag_len);
2956 str_len = tvb_strsize (tvb, str_tbl+index);
2957 tag_new_literal = tvb_get_ptr (tvb, str_tbl+index, str_len);
2958 tag_new_known = 0; /* invalidate known tag_new */
2959 } else { /* Known tag */
2960 tag_new_known = peek & 0x3F;
2961 sprintf (tag_new_buf, "Tag_0x%02X",
2963 tag_new_literal = tag_new_buf;
2964 /* Stored looked up tag name string */
2967 /* Parsing of TAG starts HERE */
2968 if (peek & 0x40) { /* Content present */
2970 * [!] An explicit END token is expected in these cases!
2971 * ==> Recursion possible if we encounter a tag with content;
2972 * recursion will return at the explicit END token.
2974 if (parsing_tag_content) { /* Recurse */
2975 DebugLog(("STAG: Tag in Tag - RECURSE! (off = %u)\n", off));
2976 /* Do not process the attribute list:
2977 * recursion will take care of it */
2979 len = parse_wbxml_tag (tree, tvb, off, str_tbl, level);
2981 } else { /* Now we will have content to parse */
2982 /* Save the start tag so we can properly close it later. */
2983 if ((peek & 0x3F) == 4) { /* Literal tag */
2984 tag_save_literal = tag_new_literal;
2986 } else { /* Known tag */
2987 tag_save_known = tag_new_known;
2988 sprintf (tag_save_buf, "Tag_0x%02X",
2990 tag_save_literal = tag_save_buf;
2991 /* The last statement avoids needless lookups */
2993 /* Process the attribute list if present */
2994 if (peek & 0x80) { /* Content and Attribute list present */
2995 if (tag_new_known) { /* Known tag */
2996 if (codepage_stag) { /* Not default code page */
2997 proto_tree_add_text (tree, tvb, off, 1,
2998 " %3d | Tag | T %3d->0 "
2999 "| Known Tag 0x%02X (AC) "
3001 *level, codepage_stag, tag_new_known,
3002 Indent (*level), tag_new_literal);
3003 /* Tag string already looked up earlier! */
3004 /* Reset code page */
3006 } else { /* Code page 0 */
3007 proto_tree_add_text (tree, tvb, off, 1,
3009 "| Known Tag 0x%02X (AC) "
3011 *level, tag_new_known,
3012 Indent (*level), tag_new_literal);
3013 /* Tag string already looked up earlier! */
3016 } else { /* LITERAL tag */
3017 proto_tree_add_text (tree, tvb, off, 1,
3019 "| LITERAL_AC (Literal tag) (AC) "
3021 *level, Indent (*level), tag_new_literal);
3024 len = parse_wbxml_attribute_list (tree, tvb,
3025 off, str_tbl, *level);
3026 /* Check that there is still room in packet */
3028 if (off >= tvb_len) {
3029 DebugLog(("STAG: level = %u, ThrowException: len = %u (short frame)\n", *level, off - offset));
3030 THROW(ReportedBoundsError);
3032 proto_tree_add_text (tree, tvb, off-1, 1,
3034 "| END (attribute list) "
3036 *level, Indent (*level));
3037 } else { /* Content, no Attribute list */
3038 if (tag_new_known) { /* Known tag */
3039 if (codepage_stag) { /* Not default code page */
3040 proto_tree_add_text (tree, tvb, off, 1,
3041 " %3d | Tag | T %3d->0 "
3042 "| Known Tag 0x%02X (.C) "
3044 *level, codepage_stag, tag_new_known,
3047 /* Tag string already looked up earlier! */
3048 /* Reset code page */
3050 } else { /* Code page 0 */
3051 proto_tree_add_text (tree, tvb, off, 1,
3053 "| Known Tag 0x%02X (.C) "
3055 *level, tag_new_known,
3058 /* Tag string already looked up earlier! */
3061 } else { /* LITERAL tag */
3062 proto_tree_add_text (tree, tvb, off, 1,
3064 "| LITERAL_C (Literal Tag) (.C) "
3066 *level, Indent (*level), tag_new_literal);
3070 /* The data that follows in the parsing process
3071 * represents content for the opening tag
3072 * we've just processed in the lines above.
3073 * Next time we encounter a tag with content: recurse
3075 parsing_tag_content = TRUE;
3076 DebugLog(("Tag in Tag - No recursion this time! (off = %u)\n", off));
3078 } else { /* No Content */
3079 DebugLog(("<Tag/> in Tag - No recursion! (off = %u)\n", off));
3081 if (peek & 0x80) { /* No Content, Attribute list present */
3082 if (tag_new_known) { /* Known tag */
3083 if (codepage_stag) { /* Not default code page */
3084 proto_tree_add_text (tree, tvb, off, 1,
3085 " %3d | Tag | T %3d->0 "
3086 "| Known Tag 0x%02X (A.) "
3088 *level, codepage_stag, tag_new_known,
3089 Indent (*level), tag_new_literal);
3090 /* Tag string already looked up earlier! */
3091 /* Reset code page */
3093 } else { /* Code page 0 */
3094 proto_tree_add_text (tree, tvb, off, 1,
3096 "| Known Tag 0x%02X (A.) "
3098 *level, tag_new_known,
3099 Indent (*level), tag_new_literal);
3100 /* Tag string already looked up earlier! */
3103 len = parse_wbxml_attribute_list (tree, tvb,
3104 off, str_tbl, *level);
3105 /* Check that there is still room in packet */
3107 if (off >= tvb_len) {
3108 DebugLog(("STAG: level = %u, ThrowException: len = %u (short frame)\n", *level, off - offset));
3109 THROW(ReportedBoundsError);
3111 proto_tree_add_text (tree, tvb, off-1, 1,
3113 "| END (Known Tag) "
3115 *level, Indent (*level));
3116 } else { /* LITERAL tag */
3117 proto_tree_add_text (tree, tvb, off, 1,
3119 "| LITERAL_A (Literal Tag) (A.) "
3121 *level, Indent (*level), tag_new_literal);
3123 len = parse_wbxml_attribute_list (tree, tvb,
3124 off, str_tbl, *level);
3125 /* Check that there is still room in packet */
3127 if (off >= tvb_len) {
3128 DebugLog(("STAG: level = %u, ThrowException: len = %u (short frame)\n", *level, off - offset));
3129 THROW(ReportedBoundsError);
3131 proto_tree_add_text (tree, tvb, off-1, 1,
3133 "| END (Literal Tag) "
3135 *level, Indent (*level));
3137 } else { /* No Content, No Attribute list */
3138 if (tag_new_known) { /* Known tag */
3139 if (codepage_stag) { /* Not default code page */
3140 proto_tree_add_text (tree, tvb, off, 1,
3141 " %3d | Tag | T %3d->0 "
3142 "| Known Tag 0x%02x (..) "
3144 *level, codepage_stag, tag_new_known,
3145 Indent (*level), tag_new_literal);
3146 /* Tag string already looked up earlier! */
3147 /* Reset code page */
3149 } else { /* Code page 0 */
3150 proto_tree_add_text (tree, tvb, off, 1,
3152 "| Known Tag 0x%02x (..) "
3154 *level, tag_new_known,
3155 Indent (*level), tag_new_literal);
3156 /* Tag string already looked up earlier! */
3159 } else { /* LITERAL tag */
3160 proto_tree_add_text (tree, tvb, off, 1,
3162 "| LITERAL (Literal Tag) (..) "
3164 *level, Indent (*level), tag_new_literal);
3169 /* TODO: Do I have to reset code page here? */
3171 } /* if (tag & 0x3F) >= 5 */
3173 DebugLog(("STAG: level = %u, Return: len = %u (end of function body)\n", *level, off - offset));
3174 return (off - offset);
3178 /**************************
3179 * WBXML Attribute tokens *
3180 **************************
3181 * Bit Mask : Example
3182 * -------------------
3183 * 0... .... : attr= (attribute name)
3184 * href='http://' (attribute name with start of attribute value)
3185 * 1... .... : 'www.' (attribute value, or part of it)
3190 /* This function parses the WBXML and maps known token interpretations
3191 * to the WBXML tokens. As a result, the original XML document can be
3192 * recreated. Indentation is generated in order to ease reading.
3194 * This function performs attribute list parsing.
3196 * The wbxml_token_map entry *map contains the actual token mapping.
3198 * NOTE: See above for known token mappings.
3201 parse_wbxml_attribute_list_defined (proto_tree *tree, tvbuff_t *tvb,
3202 guint32 offset, guint32 str_tbl, guint8 level,
3203 const wbxml_token_map *map)
3205 guint32 tvb_len = tvb_reported_length (tvb);
3206 guint32 off = offset;
3212 guint8 codepage_attr = 0; /* Initial codepage in state = ATTR */
3214 DebugLog(("parse_wbxml_attr_defined (level = %u, offset = %u)\n", level, offset));
3215 /* Parse attributes */
3216 while (off < tvb_len) {
3217 peek = tvb_get_guint8 (tvb, off);
3218 DebugLog(("ATTR: (top of while) level = %3u, peek = 0x%02X, off = %u, tvb_len = %u\n", level, peek, off, tvb_len));
3219 if ((peek & 0x3F) < 5) switch (peek) { /* Global tokens
3221 case 0x00: /* SWITCH_PAGE */
3222 codepage_attr = tvb_get_guint8 (tvb, off+1);
3223 proto_tree_add_text (tree, tvb, off, 2,
3224 " | Attr | A 0->%3d "
3225 "| SWITCH_PAGE (Attr code page) |",
3229 case 0x01: /* END */
3231 * The Attribute END token means either ">" or "/>"
3232 * and as a consequence both must be treated separately.
3233 * This is done in the TAG state parser.
3236 DebugLog(("ATTR: level = %u, Return: len = %u\n", level, off - offset));
3237 return (off - offset);
3238 case 0x02: /* ENTITY */
3239 ent = tvb_get_guintvar (tvb, off+1, &len);
3240 proto_tree_add_text (tree, tvb, off, 1+len,
3244 level, Indent (level), ent);
3247 case 0x03: /* STR_I */
3248 len = tvb_strsize (tvb, off+1);
3249 proto_tree_add_text (tree, tvb, off, 1+len,
3251 "| STR_I (Inline string) "
3253 level, Indent (level),
3254 tvb_format_text (tvb, off+1, len-1));
3257 case 0x04: /* LITERAL */
3258 index = tvb_get_guintvar (tvb, off+1, &len);
3259 str_len = tvb_strsize (tvb, str_tbl+index);
3260 proto_tree_add_text (tree, tvb, off, 1+len,
3262 "| LITERAL (Literal Attribute) "
3264 level, Indent (level),
3265 tvb_format_text (tvb, str_tbl+index, str_len-1));
3268 case 0x40: /* EXT_I_0 */
3269 case 0x41: /* EXT_I_1 */
3270 case 0x42: /* EXT_I_2 */
3271 /* Extension tokens */
3272 len = tvb_strsize (tvb, off+1);
3273 if (codepage_attr) { /* Not default code page */
3274 proto_tree_add_text (tree, tvb, off, 1+len,
3275 " %3d | Attr | A %3d->0 "
3276 "| EXT_I_%1x (Extension Token) "
3278 level, codepage_attr, peek & 0x0f, Indent (level),
3279 map_token (map->global, codepage_attr, peek),
3280 tvb_format_text (tvb, off+1, len-1));
3281 /* Reset code page */
3283 } else { /* Code page 0 */
3284 proto_tree_add_text (tree, tvb, off, 1+len,
3286 "| EXT_I_%1x (Extension Token) "
3288 level, peek & 0x0f, Indent (level),
3289 map_token (map->global, codepage_attr, peek),
3290 tvb_format_text (tvb, off+1, len-1));
3294 /* 0x43 impossible in ATTR state */
3295 /* 0x44 impossible in ATTR state */
3296 case 0x80: /* EXT_T_0 */
3297 case 0x81: /* EXT_T_1 */
3298 case 0x82: /* EXT_T_2 */
3299 /* Extension tokens */
3300 index = tvb_get_guintvar (tvb, off+1, &len);
3301 str_len = tvb_strsize (tvb, str_tbl+index);
3302 if (codepage_attr) { /* Not default code page */
3303 proto_tree_add_text (tree, tvb, off, 1+len,
3304 " %3d | Attr | A %3d->0 "
3305 "| EXT_T_%1x (Extension Token) "
3307 level, codepage_attr, peek & 0x0f, Indent (level),
3308 map_token (map->global, codepage_attr, peek),
3309 tvb_format_text (tvb, str_tbl+index, str_len-1));
3310 /* Reset code page */
3312 } else { /* Code page 0 */
3313 proto_tree_add_text (tree, tvb, off, 1+len,
3315 "| EXT_T_%1x (Extension Token) "
3317 level, peek & 0x0f, Indent (level),
3318 map_token (map->global, codepage_attr, peek),
3319 tvb_format_text (tvb, str_tbl+index, str_len-1));
3323 case 0x83: /* STR_T */
3324 index = tvb_get_guintvar (tvb, off+1, &len);
3325 str_len = tvb_strsize (tvb, str_tbl+index);
3326 proto_tree_add_text (tree, tvb, off, 1+len,
3328 "| STR_T (Tableref string) "
3330 level, Indent (level),
3331 tvb_format_text (tvb, str_tbl+index, str_len-1));
3334 /* 0x84 impossible in ATTR state */
3335 case 0xC0: /* EXT_0 */
3336 case 0xC1: /* EXT_1 */
3337 case 0xC2: /* EXT_2 */
3338 /* Extension tokens */
3339 if (codepage_attr) { /* Not default code page */
3340 proto_tree_add_text (tree, tvb, off, 1,
3341 " %3d | Attr | A %3d->0 "
3342 "| EXT_%1x (Extension Token) "
3344 level, codepage_attr, peek & 0x0f, Indent (level),
3345 map_token (map->global, codepage_attr, peek));
3346 /* Reset code page */
3348 } else { /* Code page 0 */
3349 proto_tree_add_text (tree, tvb, off, 1,
3351 "| EXT_%1x (Extension Token) "
3353 level, peek & 0x0f, Indent (level),
3354 map_token (map->global, codepage_attr, peek));
3358 case 0xC3: /* OPAQUE - WBXML 1.1 and newer */
3359 if (tvb_get_guint8 (tvb, 0)) { /* WBXML 1.x (x > 0) */
3360 index = tvb_get_guintvar (tvb, off+1, &len);
3361 proto_tree_add_text (tree, tvb, off, 1 + len + index,
3363 "| OPAQUE (Opaque data) "
3364 "| %s(%d bytes of opaque data)",
3365 level, Indent (level), index);
3367 } else { /* WBXML 1.0 - RESERVED_2 token (invalid) */
3368 proto_tree_add_text (tree, tvb, off, 1,
3370 "| RESERVED_2 (Invalid Token!) "
3371 "| WBXML 1.0 parsing stops here.",
3373 /* Stop processing as it is impossible to parse now */
3375 DebugLog(("ATTR: level = %u, Return: len = %u\n", level, off - offset));
3376 return (off - offset);
3379 /* 0xC4 impossible in ATTR state */
3381 proto_tree_add_text (tree, tvb, off, 1,
3383 "| %-10s (Invalid Token!) "
3384 "| WBXML parsing stops here.",
3385 level, match_strval (peek, vals_wbxml1x_global_tokens));
3386 /* Move to end of buffer */
3389 } else { /* Known atribute token */
3390 if (peek & 0x80) { /* attrValue */
3391 if (codepage_attr) { /* Not default code page */
3392 proto_tree_add_text (tree, tvb, off, 1,
3393 " %3d | Attr | A %3d->0 "
3394 "| Known attrValue 0x%02X "
3396 level, codepage_attr, peek & 0x7f, Indent (level),
3397 map_token (map->attrValue, codepage_attr, peek));
3398 /* Reset code page */
3400 } else { /* Code page 0 */
3401 proto_tree_add_text (tree, tvb, off, 1,
3403 "| Known attrValue 0x%02X "
3405 level, peek & 0x7f, Indent (level),
3406 map_token (map->attrValue, codepage_attr, peek));
3409 } else { /* attrStart */
3410 if (codepage_attr) { /* Not default code page */
3411 proto_tree_add_text (tree, tvb, off, 1,
3412 " %3d | Attr | A %3d->0 "
3413 "| Known attrStart 0x%02X "
3415 level, codepage_attr, peek & 0x7f, Indent (level),
3416 map_token (map->attrStart, codepage_attr, peek));
3417 /* Reset code page */
3419 } else { /* Code page 0 */
3420 proto_tree_add_text (tree, tvb, off, 1,
3422 "| Known attrStart 0x%02X "
3424 level, peek & 0x7f, Indent (level),
3425 map_token (map->attrStart, codepage_attr, peek));
3431 DebugLog(("ATTR: level = %u, Return: len = %u (end of function body)\n", level, off - offset));
3432 return (off - offset);
3436 /* This function performs the WBXML attribute decoding as in
3437 * parse_wbxml_attribute_list_defined() but this time no WBXML mapping
3440 * This function performs attribute list parsing.
3442 * NOTE: Code page switches not yet processed in the code!
3445 parse_wbxml_attribute_list (proto_tree *tree, tvbuff_t *tvb,
3446 guint32 offset, guint32 str_tbl, guint8 level)
3448 guint32 tvb_len = tvb_reported_length (tvb);
3449 guint32 off = offset;
3455 guint8 codepage_attr = 0; /* Initial codepage in state = ATTR */
3457 DebugLog(("parse_wbxml_attr (level = %u, offset = %u)\n", level, offset));
3458 /* Parse attributes */
3459 while (off < tvb_len) {
3460 peek = tvb_get_guint8 (tvb, off);
3461 DebugLog(("ATTR: (top of while) level = %3u, peek = 0x%02X, off = %u, tvb_len = %u\n", level, peek, off, tvb_len));
3462 if ((peek & 0x3F) < 5) switch (peek) { /* Global tokens
3464 case 0x00: /* SWITCH_PAGE */
3465 codepage_attr = tvb_get_guint8 (tvb, off+1);
3466 proto_tree_add_text (tree, tvb, off, 2,
3467 " | Attr | A 0->%3d "
3468 "| SWITCH_PAGE (Attr code page) |",
3472 case 0x01: /* END */
3474 * The Attribute END token means either ">" or "/>"
3475 * and as a consequence both must be treated separately.
3476 * This is done in the TAG state parser.
3479 DebugLog(("ATTR: level = %u, Return: len = %u\n", level, off - offset));
3480 return (off - offset);
3481 case 0x02: /* ENTITY */
3482 ent = tvb_get_guintvar (tvb, off+1, &len);
3483 proto_tree_add_text (tree, tvb, off, 1+len,
3487 level, Indent (level), ent);
3490 case 0x03: /* STR_I */
3491 len = tvb_strsize (tvb, off+1);
3492 proto_tree_add_text (tree, tvb, off, 1+len,
3494 "| STR_I (Inline string) "
3496 level, Indent (level),
3497 tvb_format_text (tvb, off+1, len-1));
3500 case 0x04: /* LITERAL */
3501 index = tvb_get_guintvar (tvb, off+1, &len);
3502 str_len = tvb_strsize (tvb, str_tbl+index);
3503 proto_tree_add_text (tree, tvb, off, 1+len,
3505 "| LITERAL (Literal Attribute) "
3507 level, Indent (level),
3508 tvb_format_text (tvb, str_tbl+index, str_len-1));
3511 case 0x40: /* EXT_I_0 */
3512 case 0x41: /* EXT_I_1 */
3513 case 0x42: /* EXT_I_2 */
3514 /* Extension tokens */
3515 len = tvb_strsize (tvb, off+1);
3516 if (codepage_attr) { /* Not default code page */
3517 proto_tree_add_text (tree, tvb, off, 1+len,
3518 " %3d | Attr | A %3d->0 "
3519 "| EXT_I_%1x (Extension Token) "
3520 "| %s(Inline string extension: \'%s\')",
3521 level, codepage_attr, peek & 0x0f, Indent (level),
3522 tvb_format_text (tvb, off+1, len-1));
3523 /* Reset code page */
3525 } else { /* Code page 0 */
3526 proto_tree_add_text (tree, tvb, off, 1+len,
3528 "| EXT_I_%1x (Extension Token) "
3529 "| %s(Inline string extension: \'%s\')",
3530 level, peek & 0x0f, Indent (level),
3531 tvb_format_text (tvb, off+1, len-1));
3535 /* 0x43 impossible in ATTR state */
3536 /* 0x44 impossible in ATTR state */
3537 case 0x80: /* EXT_T_0 */
3538 case 0x81: /* EXT_T_1 */
3539 case 0x82: /* EXT_T_2 */
3540 /* Extension tokens */
3541 index = tvb_get_guintvar (tvb, off+1, &len);
3542 str_len = tvb_strsize (tvb, str_tbl+index);
3543 if (codepage_attr) { /* Not default code page */
3544 proto_tree_add_text (tree, tvb, off, 1+len,
3545 " %3d | Attr | A %3d->0 "
3546 "| EXT_T_%1x (Extension Token) "
3547 "| %s(Tableref string extension: \'%s\')",
3548 level, codepage_attr, peek & 0x0f, Indent (level),
3549 tvb_format_text (tvb, str_tbl+index, str_len-1));
3550 /* Reset code page */
3552 } else { /* Code page 0 */
3553 proto_tree_add_text (tree, tvb, off, 1+len,
3555 "| EXT_T_%1x (Extension Token) "
3556 "| %s(Tableref string extension: \'%s\')",
3557 level, peek & 0x0f, Indent (level),
3558 tvb_format_text (tvb, str_tbl+index, str_len-1));
3562 case 0x83: /* STR_T */
3563 index = tvb_get_guintvar (tvb, off+1, &len);
3564 str_len = tvb_strsize (tvb, str_tbl+index);
3565 proto_tree_add_text (tree, tvb, off, 1+len,
3567 "| STR_T (Tableref string) "
3569 level, Indent (level),
3570 tvb_format_text (tvb, str_tbl+index, str_len-1));
3573 /* 0x84 impossible in ATTR state */
3574 case 0xC0: /* EXT_0 */
3575 case 0xC1: /* EXT_1 */
3576 case 0xC2: /* EXT_2 */
3577 /* Extension tokens */
3578 if (codepage_attr) { /* Not default code page */
3579 proto_tree_add_text (tree, tvb, off, 1,
3580 " %3d | Attr | A %3d->0 "
3581 "| EXT_%1x (Extension Token) "
3582 "| %s(Single-byte extension)",
3583 level, codepage_attr, peek & 0x0f, Indent (level));
3584 /* Reset code page */
3586 } else { /* Code page 0 */
3587 proto_tree_add_text (tree, tvb, off, 1,
3589 "| EXT_%1x (Extension Token) "
3590 "| %s(Single-byte extension)",
3591 level, peek & 0x0f, Indent (level));
3595 case 0xC3: /* OPAQUE - WBXML 1.1 and newer */
3596 if (tvb_get_guint8 (tvb, 0)) { /* WBXML 1.x (x > 0) */
3597 index = tvb_get_guintvar (tvb, off+1, &len);
3598 proto_tree_add_text (tree, tvb, off, 1 + len + index,
3600 "| OPAQUE (Opaque data) "
3601 "| %s(%d bytes of opaque data)",
3602 level, Indent (level), index);
3604 } else { /* WBXML 1.0 - RESERVED_2 token (invalid) */
3605 proto_tree_add_text (tree, tvb, off, 1,
3607 "| RESERVED_2 (Invalid Token!) "
3608 "| WBXML 1.0 parsing stops here.",
3610 /* Stop processing as it is impossible to parse now */
3612 DebugLog(("ATTR: level = %u, Return: len = %u\n", level, off - offset));
3613 return (off - offset);
3616 /* 0xC4 impossible in ATTR state */
3618 proto_tree_add_text (tree, tvb, off, 1,
3620 "| %-10s (Invalid Token!) "
3621 "| WBXML parsing stops here.",
3622 level, match_strval (peek, vals_wbxml1x_global_tokens));
3623 /* Move to end of buffer */
3626 } else { /* Known atribute token */
3627 if (peek & 0x80) { /* attrValue */
3628 if (codepage_attr) { /* Not default code page */
3629 proto_tree_add_text (tree, tvb, off, 1,
3630 " %3d | Attr | A %3d->0 "
3631 "| Known attrValue 0x%02X "
3632 "| %sattrValue_0x%02X",
3633 level, codepage_attr, peek & 0x7f, Indent (level),
3635 /* Reset code page */
3637 } else { /* Code page 0 */
3638 proto_tree_add_text (tree, tvb, off, 1,
3640 "| Known attrValue 0x%02X "
3641 "| %sattrValue_0x%02X",
3642 level, peek & 0x7f, Indent (level),
3646 } else { /* attrStart */
3647 if (codepage_attr) { /* Not default code page */
3648 proto_tree_add_text (tree, tvb, off, 1,
3649 " %3d | Attr | A %3d->0 "
3650 "| Known attrStart 0x%02X "
3651 "| %sattrStart_0x%02X",
3652 level, codepage_attr, peek & 0x7f, Indent (level),
3654 /* Reset code page */
3656 } else { /* Code page 0 */
3657 proto_tree_add_text (tree, tvb, off, 1,
3659 "| Known attrStart 0x%02X "
3660 "| %sattrStart_0x%02X",
3661 level, peek & 0x7f, Indent (level),
3668 DebugLog(("ATTR: level = %u, Return: len = %u (end of function body)\n", level, off - offset));
3669 return (off - offset);
3673 /****************** Register the protocol with Ethereal ******************/
3676 /* This format is required because a script is used to build the C function
3677 * that calls the protocol registration. */
3680 proto_register_wbxml(void)
3681 { /* Setup list of header fields. See Section 1.6.1 for details. */
3682 static hf_register_info hf[] = {
3683 { &hf_wbxml_version,
3687 VALS ( vals_wbxml_versions ), 0x00,
3688 "WBXML Version", HFILL }
3690 { &hf_wbxml_public_id_known,
3691 { "Public Identifier (known)",
3692 "wbxml.public_id.known",
3693 FT_UINT32, BASE_HEX,
3694 VALS ( vals_wbxml_public_ids ), 0x00,
3695 "WBXML Known Public Identifier (integer)", HFILL }
3697 { &hf_wbxml_public_id_literal,
3698 { "Public Identifier (literal)",
3699 "wbxml.public_id.literal",
3700 FT_STRING, BASE_NONE,
3702 "WBXML Literal Public Identifier (text string)", HFILL }
3704 { &hf_wbxml_charset,
3707 FT_UINT32, BASE_HEX,
3708 VALS ( vals_character_sets ), 0x00,
3709 "WBXML Character Set", HFILL }
3713 /* Setup protocol subtree array */
3714 static gint *ett[] = {
3720 /* Register the protocol name and description */
3721 proto_wbxml = proto_register_protocol(
3727 /* Required function calls to register the header fields
3728 * and subtrees used */
3729 proto_register_field_array(proto_wbxml, hf, array_length(hf));
3730 proto_register_subtree_array(ett, array_length(ett));
3732 register_dissector("wbxml", dissect_wbxml, proto_wbxml);
3737 proto_reg_handoff_wbxml(void)
3739 dissector_handle_t wbxml_handle;
3741 /* Heuristic dissectors would be declared by means of:
3742 * heur_dissector_add("wsp", dissect_wbxml_heur, proto_wbxml);
3745 wbxml_handle = create_dissector_handle(dissect_wbxml, proto_wbxml);
3747 /* Register the WSP content types (defined as protocol port)
3748 * for WBXML dissection.
3750 * See http://www.wapforum.org/wina/wsp-content-type.htm
3752 * As the media types for WSP and HTTP are the same, the WSP dissector
3753 * uses the same string dissector table as the HTTP protocol.
3756 /**** Well-known WBXML WSP Content-Type values ****/
3758 dissector_add_string("media_type",
3759 "application/vnd.wap.wmlc", wbxml_handle);
3760 dissector_add_string("media_type",
3761 "application/vnd.wap.wta-eventc", wbxml_handle);
3762 dissector_add_string("media_type",
3763 "application/vnd.wap.wbxml", wbxml_handle);
3764 dissector_add_string("media_type",
3765 "application/vnd.wap.sic", wbxml_handle);
3766 dissector_add_string("media_type",
3767 "application/vnd.wap.slc", wbxml_handle);
3768 dissector_add_string("media_type",
3769 "application/vnd.wap.coc", wbxml_handle);
3770 dissector_add_string("media_type",
3771 "application/vnd.wap.connectivity-wbxml", wbxml_handle);
3772 dissector_add_string("media_type",
3773 "application/vnd.wap.locc+wbxml", wbxml_handle);
3774 dissector_add_string("media_type",
3775 "application/vnd.syncml.dm+wbxml", wbxml_handle);
3776 dissector_add_string("media_type",
3777 "application/vnd.oma.drm.rights+wbxml", wbxml_handle);
3779 /**** Registered WBXML WSP Content-Type values ****/
3781 dissector_add_string("media_type",
3782 "application/vnd.uplanet.cacheop-wbxml", wbxml_handle);
3783 dissector_add_string("media_type",
3784 "application/vnd.uplanet.alert-wbxml", wbxml_handle);
3785 dissector_add_string("media_type",
3786 "application/vnd.uplanet.list-wbxml", wbxml_handle);
3787 dissector_add_string("media_type",
3788 "application/vnd.uplanet.listcmd-wbxml", wbxml_handle);
3789 dissector_add_string("media_type",
3790 "application/vnd.uplanet.channel-wbxml", wbxml_handle);
3791 dissector_add_string("media_type",
3792 "application/vnd.uplanet.bearer-choice-wbxml", wbxml_handle);
3793 dissector_add_string("media_type",
3794 "application/vnd.phonecom.mmc-wbxml", wbxml_handle);
3795 dissector_add_string("media_type",
3796 "application/vnd.nokia.syncset+wbxml", wbxml_handle);
3798 /***** Content types that only have a textual representation *****/
3799 dissector_add_string("media_type",
3800 "application/x-wap-prov.browser-bookmarks", wbxml_handle);
3801 dissector_add_string("media_type",
3802 "application/x-wap-prov.browser-settings", wbxml_handle);
3803 /* Same as application/vnd.nokia.syncset+wbxml */
3804 dissector_add_string("media_type",
3805 "application/x-prov.syncset+wbxml", wbxml_handle);