Rename "proto_alloc_dfilter_string()" to
[obnox/wireshark/wip.git] / packet-wbxml.c
1 /* packet-wbxml.c
2  * Routines for wbxml dissection
3  * Copyright 2003, Olivier Biot <olivier.biot (ad) siemens.com>
4  *
5  * $Id: packet-wbxml.c,v 1.9 2003/05/01 18:18:20 guy Exp $
6  *
7  * Ethereal - Network traffic analyzer
8  * By Gerald Combs <gerald@ethereal.com>
9  * Copyright 1998 Gerald Combs
10  *
11  * WAP Binary XML decoding functionality provided by Olivier Biot.
12  * 
13  * The WAP specifications are found at the WAP Forum:
14  * http://www.wapforum.org/what/Technical.htm
15  * 
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.
20  * 
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.
25  * 
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.
29  */
30
31 /* Edit this file with 4-space tabulation */
32
33 #ifdef HAVE_CONFIG_H
34 # include "config.h"
35 #endif
36
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40
41 #include <glib.h>
42
43 #ifdef NEED_SNPRINTF_H
44 # include "snprintf.h"
45 #endif
46
47 #include <epan/packet.h>
48
49 /* We need the function tvb_get_guintvar() */
50 #include "packet-wap.h"
51
52 /* The code in this source file dissects the WAP Binary XML content,
53  * and if possible renders it. WBXML mappings are defined in the
54  * "wbxml_map[]" array.
55  *
56  * NOTES:
57  *
58  *  - Code page switches only apply to the following token. In the WBXML/1.x
59  *    ABNF notation, it can be proven that the switch_page can only precede
60  *    the following tokens:
61  *      o  stag      : TAG | LITERAL | LITERAL_A | LITERAL_C | LITERAL_AC
62  *      o  attr      : ATTRSTART | ATTRVALUE
63  *      o  extension : EXT_I | EXT_T | EXT
64  *    Code page switches are displayed in a separate column. The only allowed
65  *    code page switches are from code page 0 to another codepage (by means of
66  *    a SWITCH_PAGE token), and from this other code page back to code page 0
67  *    (this happens automatically).
68  *
69  *  - In order to render the XML content, recursion is inevitable at some
70  *    point (when a tag with content occurs in the content of a tag with
71  *    content). The code will however not recurse if this is not strictly
72  *    required (e.g., tag without content in the content of a tag with
73  *    content).
74  *
75  *  - I found it useful to display the XML nesting level as a first "column",
76  *    followed by the abbreviated WBXML token interpretation. When a mapping
77  *    is defined for the parsed WBXML content, then the XML rendering is
78  *    displayed with appropriate indentation (maximum nesting level = 255,
79  *    after which the nesting and level will safely roll-over to 0).
80  *
81  *  - The WAP Forum defines the order of precedence for finding out the
82  *    WBXML content type (same rules for charset) as follows:
83  *      1. Look in the Content-Type WSP header
84  *      2. Look in the WBXML header
85  *    Currently there is no means of using content type parameters:
86  *      o  Type=<some_type>
87  *      o  Charset=<charset_of_the_content>
88  *    So it is possible some WBXML content types are incorrectly parsed.
89  *    This would only be the case when the content type declaration in the
90  *    WSP Content-Type header would be different (or would have parameters
91  *    which are relevant to the WBXML decoding) from the content type
92  *    identifier specified in the WBXML header.
93  *    TODO: investigate this and provide correct decoding at all times.
94  */
95
96 typedef struct _value_valuestring {
97   guint32 value;
98   const value_string *valstrptr;
99 } value_valuestring;
100
101 /* Tries to match val against each element in the value_value_string array vvs.
102  * Returns the associated value_string ptr on a match, or NULL on failure. */
103 static const value_string *
104 val_to_valstr(guint32 val, const value_valuestring *vvs)
105 {
106   gint i = 0;
107
108   while (vvs[i].valstrptr) {
109         if (vvs[i].value == val)
110       return(vvs[i].valstrptr);
111       i++;
112   }
113
114   return(NULL);
115 }
116
117
118 /************************** Variable declarations **************************/
119
120
121 /* Initialize the protocol and registered fields */
122 static int proto_wbxml = -1;
123 static int hf_wbxml_version = -1;
124 static int hf_wbxml_public_id_known = -1;
125 static int hf_wbxml_public_id_literal = -1;
126 static int hf_wbxml_charset = -1;
127
128 /* Initialize the subtree pointers */
129 static gint ett_wbxml = -1;
130 static gint ett_wbxml_str_tbl = -1;
131 static gint ett_wbxml_content = -1;
132
133
134 /**************** WBXML related declarations and definitions ****************/
135
136
137 /* WBXML public ID mappings. For an up-to-date list, see
138  * http://www.wapforum.org/wina/wbxml-public-docid.htm */
139 static const value_string vals_wbxml_public_ids[] = {
140         /* 0x00 = literal public identifier */
141         { 0x01, "Unknown / missing Public Identifier" },
142         { 0x02, "-//WAPFORUM//DTD WML 1.0//EN (WML 1.0)" },
143         { 0x03, "-//WAPFORUM//DTD WTA 1.0//EN (WTA Event 1.0) - Deprecated" },
144         { 0x04, "-//WAPFORUM//DTD WML 1.1//EN (WML 1.1)" },
145         { 0x05, "-//WAPFORUM//DTD SI 1.0//EN (Service Indication 1.0)" },
146         { 0x06, "-//WAPFORUM//DTD SL 1.0//EN (Service Loading 1.0)" },
147         { 0x07, "-//WAPFORUM//DTD CO 1.0//EN (Cache Operation 1.0)" },
148         { 0x08, "-//WAPFORUM//DTD CHANNEL 1.0//EN (Channel 1.1)" },
149         { 0x09, "-//WAPFORUM//DTD WML 1.2//EN (WML 1.2)" },
150         { 0x0a, "-//WAPFORUM//DTD WML 1.3//EN (WML 1.3)" },
151         { 0x0b, "-//WAPFORUM//DTD PROV 1.0//EN (Provisioning 1.0)" },
152         { 0x0c, "-//WAPFORUM//DTD WTA-WML 1.2//EN (WTA-WML 1.2)" },
153         { 0x0d, "-//WAPFORUM//DTD EMN 1.0//EN (Email Notification 1.0)" },
154         { 0x0e, "-//WAPFORUM//DTD DRMREL 1.0//EN (DRMREL 1.0)" },
155         
156         /* Registered values - www.syncml.org */
157         { 0x0fd1, "-//SYNCML//DTD SyncML 1.0//EN (SyncML 1.0)" },
158         { 0x0fd3, "-//SYNCML//DTD SyncML 1.1//EN (SyncML 1.1)" },
159
160         /* Registered values - www.wapforum.org/wina/ */
161         { 0x1100, "-//PHONE.COM//DTD ALERT 1.0//EN" },
162         { 0x1101, "-//PHONE.COM//DTD CACHE-OPERATION 1.0//EN" },
163         { 0x1102, "-//PHONE.COM//DTD SIGNAL 1.0//EN" },
164         { 0x1103, "-//PHONE.COM//DTD LIST 1.0//EN" },
165         { 0x1104, "-//PHONE.COM//DTD LISTCMD 1.0//EN" },
166         { 0x1105, "-//PHONE.COM//DTD CHANNEL 1.0//EN" },
167         { 0x1106, "-//PHONE.COM//DTD MMC 1.0//EN" },
168         { 0x1107, "-//PHONE.COM//DTD BEARER-CHOICE 1.0//EN" },
169         { 0x1108, "-//PHONE.COM//DTD WML 1.1//EN (WML+ 1.1)" },
170         { 0x1109, "-//PHONE.COM//DTD CHANNEL 1.1//EN" },
171         { 0x110a, "-//PHONE.COM//DTD LIST 1.1//EN" },
172         { 0x110b, "-//PHONE.COM//DTD LISTCMD 1.1//EN" },
173         { 0x110c, "-//PHONE.COM//DTD MMC 1.1//EN" },
174         { 0x110d, "-//PHONE.COM//DTD WML 1.3//EN (WML+ 1.3)" },
175         { 0x110e, "-//PHONE.COM//DTD MMC 2.0//EN" },
176         
177         { 0x00, NULL }
178 };
179
180 static const value_string vals_wbxml_versions[] = {
181         { 0x00, "1.0" },        /* WAP-104-WBXML */
182         { 0x01, "1.1" },        /* WAP-135-WBXML */
183         { 0x02, "1.2" },        /* WAP-154-WBXML */
184         { 0x03, "1.3" },        /* WAP-192-WBXML */
185         
186         { 0x00, NULL }
187 };
188
189 /* See WAP-104-WBXML */
190 static const value_string vals_wbxml10_global_tokens[] = {
191         { 0x00, "SWITCH_PAGE" },
192         { 0x01, "END" },
193         { 0x02, "ENTITY" },
194         { 0x03, "STR_I" },
195         { 0x04, "LITERAL" },
196
197         { 0x40, "EXT_I_0" },
198         { 0x41, "EXT_I_1" },
199         { 0x42, "EXT_I_2" },
200         { 0x43, "PI" },
201         { 0x44, "LITERAL_C" },
202
203         { 0x80, "EXT_T_0" },
204         { 0x81, "EXT_T_1" },
205         { 0x82, "EXT_T_2" },
206         { 0x83, "STR_T" },
207         { 0x84, "LITERAL_A" },
208
209         { 0xC0, "EXT_0" },
210         { 0xC1, "EXT_1" },
211         { 0xC2, "EXT_2" },
212         { 0xC3, "RESERVED_2" },
213         { 0xC4, "LITERAL_AC" },
214
215         { 0x00, NULL }
216 };
217
218 /* See WAP-135-WBXML, WAP-154-WBXML, WAP-192-WBXML */
219 static const value_string vals_wbxml1x_global_tokens[] = {
220         { 0x00, "SWITCH_PAGE" },
221         { 0x01, "END" },
222         { 0x02, "ENTITY" },
223         { 0x03, "STR_I" },
224         { 0x04, "LITERAL" },
225
226         { 0x40, "EXT_I_0" },
227         { 0x41, "EXT_I_1" },
228         { 0x42, "EXT_I_2" },
229         { 0x43, "PI" },
230         { 0x44, "LITERAL_C" },
231
232         { 0x80, "EXT_T_0" },
233         { 0x81, "EXT_T_1" },
234         { 0x82, "EXT_T_2" },
235         { 0x83, "STR_T" },
236         { 0x84, "LITERAL_A" },
237
238         { 0xC0, "EXT_0" },
239         { 0xC1, "EXT_1" },
240         { 0xC2, "EXT_2" },
241         { 0xC3, "OPAQUE" },
242         { 0xC4, "LITERAL_AC" },
243
244         { 0x00, NULL }
245 };
246
247
248 /********************** WBXML token mapping definition **********************/
249
250
251 /* WML 1.0
252  * 
253  * Wireless Markup Language
254  ***************************************/
255
256 /*****   Global extension tokens   *****/
257 static const value_string wbxml_wmlc10_global_cp0[] = {
258         { 0x40, "Variable substitution - escaped" },
259         { 0x41, "Variable substitution - unescaped" },
260         { 0x42, "Variable substitution - no transformation" },
261         { 0x80, "Variable substitution - escaped" },
262         { 0x81, "Variable substitution - unescaped" },
263         { 0x82, "Variable substitution - no transformation" },
264         { 0xC0, "Reserved" },
265         { 0xC1, "Reserved" },
266         { 0xC2, "Reserved" },
267
268         { 0x00, NULL }
269 };
270
271 /*****         Tag tokens          *****/
272 static const value_string wbxml_wmlc10_tags_cp0[] = {
273         /* 0x00 -- 0x04 GLOBAL */
274         /* 0x05 -- 0xE1 */
275         { 0xE2, "A" },
276         { 0xE3, "ACCESS" },
277         { 0xE4, "B" },
278         { 0xE5, "BIG" },
279         { 0xE6, "BR" },
280         { 0xE7, "CARD" },
281         { 0xE8, "DO" },
282         { 0xE9, "EM" },
283         { 0xEA, "FIELDSET" },
284         { 0xEB, "GO" },
285         { 0xEC, "HEAD" },
286         { 0xED, "I" },
287         { 0xEE, "IMG" },
288         { 0xEF, "INPUT" },
289         { 0xF0, "META" },
290         { 0xF1, "NOOP" },
291         { 0xF2, "PREV" },
292         { 0xF3, "ONEVENT" },
293         { 0xF4, "OPTGROUP" },
294         { 0xF5, "OPTION" },
295         { 0xF6, "REFRESH" },
296         { 0xF7, "SELECT" },
297         { 0xF8, "SMALL" },
298         { 0xF9, "STRONG" },
299         { 0xFA, "TAB" },
300         { 0xFB, "TEMPLATE" },
301         { 0xFC, "TIMER" },
302         { 0xFD, "U" },
303         { 0xFE, "VAR" },
304         { 0xFF, "WML" },
305
306         { 0x00, NULL }
307 };
308
309 /*****    Attribute Start tokens   *****/
310 static const value_string wbxml_wmlc10_attrStart_cp0[] = {
311         /* 0x00 -- 0x04 GLOBAL */
312         { 0x05, "ACCEPT-CHARSET=" },
313         { 0x06, "ALIGN='BOTTOM'" },
314         { 0x07, "ALIGN='CENTER'" },
315         { 0x08, "ALIGN='LEFT'" },
316         { 0x09, "ALIGN='MIDDLE'" },
317         { 0x0A, "ALIGN='RIGHT'" },
318         { 0x0B, "ALIGN='TOP'" },
319         { 0x0C, "ALT=" },
320         { 0x0D, "CONTENT=" },
321         { 0x0E, "DEFAULT=" },
322         { 0x0F, "DOMAIN=" },
323         { 0x10, "EMPTYOK='FALSE'" },
324         { 0x11, "EMPTYOK='TRUE'" },
325         { 0x12, "FORMAT=" },
326         { 0x13, "HEIGHT=" },
327         { 0x14, "HSPACE=" },
328         { 0x15, "IDEFAULT=" },
329         { 0x16, "IKEY=" },
330         { 0x17, "KEY=" },
331         { 0x18, "LABEL=" },
332         { 0x19, "LOCALSRC=" },
333         { 0x1A, "MAXLENGTH=" },
334         { 0x1B, "METHOD='GET'" },
335         { 0x1C, "METHOD='POST'" },
336         { 0x1D, "MODE='NOWRAP'" },
337         { 0x1E, "MODE='WRAP'" },
338         { 0x1F, "MULTIPLE='FALSE'" },
339         { 0x20, "MULTIPLE='TRUE'" },
340         { 0x21, "NAME=" },
341         { 0x22, "NEWCONTEXT='FALSE'" },
342         { 0x23, "NEWCONTEXT='TRUE'" },
343         { 0x24, "ONCLICK=" },
344         { 0x25, "ONENTERBACKWARD=" },
345         { 0x26, "ONENTERFORWARD=" },
346         { 0x27, "ONTIMER=" },
347         { 0x28, "OPTIONAL='FALSE'" },
348         { 0x29, "OPTIONAL='TRUE'" },
349         { 0x2A, "PATH=" },
350         { 0x2B, "POSTDATA=" },
351         { 0x2C, "PUBLIC='FALSE'" },
352         { 0x2D, "PUBLIC='TRUE'" },
353         { 0x2E, "SCHEME=" },
354         { 0x2F, "SENDREFERER='FALSE'" },
355         { 0x30, "SENDREFERER='TRUE'" },
356         { 0x31, "SIZE=" },
357         { 0x32, "SRC=" },
358         { 0x33, "STYLE='LIST'" },
359         { 0x34, "STYLE='SET'" },
360         { 0x35, "TABINDEX=" },
361         { 0x36, "TITLE=" },
362         { 0x37, "TYPE=" },
363         { 0x38, "TYPE='ACCEPT'" },
364         { 0x39, "TYPE='DELETE'" },
365         { 0x3A, "TYPE='HELP'" },
366         { 0x3B, "TYPE='PASSWORD'" },
367         { 0x3C, "TYPE='ONCLICK'" },
368         { 0x3D, "TYPE='ONENTERBACKWARD'" },
369         { 0x3E, "TYPE='ONENTERFORWARD'" },
370         { 0x3F, "TYPE='ONTIMER'" },
371         /* 0x40 -- 0x44 GLOBAL */
372         { 0x45, "TYPE='OPTIONS'" },
373         { 0x46, "TYPE='PREV'" },
374         { 0x47, "TYPE='RESET'" },
375         { 0x48, "TYPE='TEXT'" },
376         { 0x49, "TYPE='vnd.'" },
377         { 0x4A, "URL=" },
378         { 0x4B, "URL='http://'" },
379         { 0x4C, "URL='https://'" },
380         { 0x4D, "USER-AGENT=" },
381         { 0x4E, "VALUE=" },
382         { 0x4F, "VSPACE=" },
383         { 0x50, "WIDTH=" },
384         { 0x51, "xml:lang=" },
385
386         { 0x00, NULL }
387 };
388
389 /*****    Attribute Value tokens   *****/
390 static const value_string wbxml_wmlc10_attrValue_cp0[] = {
391         /* 0x80 -- 0x84 GLOBAL */
392         { 0x85, "'.com/'" },
393         { 0x86, "'.edu/'" },
394         { 0x87, "'.net/'" },
395         { 0x88, "'.org/'" },
396         { 0x89, "'ACCEPT'" },
397         { 0x8A, "'BOTTOM'" },
398         { 0x8B, "'CLEAR'" },
399         { 0x8C, "'DELETE'" },
400         { 0x8D, "'HELP'" },
401         { 0x8E, "'http://'" },
402         { 0x8F, "'http://www.'" },
403         { 0x90, "'https://'" },
404         { 0x91, "'https://www.'" },
405         { 0x92, "'LIST'" },
406         { 0x93, "'MIDDLE'" },
407         { 0x94, "'NOWRAP'" },
408         { 0x95, "'ONCLICK'" },
409         { 0x96, "'ONENTERBACKWARD'" },
410         { 0x97, "'ONENTERFORWARD'" },
411         { 0x98, "'ONTIMER'" },
412         { 0x99, "'OPTIONS'" },
413         { 0x9A, "'PASSWORD'" },
414         { 0x9B, "'RESET'" },
415         { 0x9C, "'SET'" },
416         { 0x9D, "'TEXT'" },
417         { 0x9E, "'TOP'" },
418         { 0x9F, "'UNKNOWN'" },
419         { 0xA0, "'WRAP'" },
420         { 0xA1, "'www.'" },
421
422         { 0x00, NULL }
423 };
424
425 /***** Token code page aggregation *****/
426 static const value_valuestring wbxml_wmlc10_global[] = {
427         { 0, wbxml_wmlc10_global_cp0 },
428         { 0, NULL }
429 };
430
431 static const value_valuestring wbxml_wmlc10_tags[] = {
432         { 0, wbxml_wmlc10_tags_cp0 },
433         { 0, NULL }
434 };
435
436 static const value_valuestring wbxml_wmlc10_attrStart[] = {
437         { 0, wbxml_wmlc10_attrStart_cp0 },
438         { 0, NULL }
439 };
440
441 static const value_valuestring wbxml_wmlc10_attrValue[] = {
442         { 0, wbxml_wmlc10_attrValue_cp0 },
443         { 0, NULL }
444 };
445
446
447
448
449
450 /* WML 1.1
451  * 
452  * Wireless Markup Language
453  ***************************************/
454
455 /*****   Global extension tokens   *****/
456 /* Same as in WML 1.0 */
457
458 /*****         Tag tokens          *****/
459 static const value_string wbxml_wmlc11_tags_cp0[] = {
460         /* 0x00 -- 0x04 GLOBAL */
461         /* 0x05 -- 0x1B */
462         { 0x1C, "a" },
463         { 0x1D, "td" },
464         { 0x1E, "tr" },
465         { 0x1F, "table" },
466         { 0x20, "p" },
467         { 0x21, "postfield" },
468         { 0x22, "anchor" },
469         { 0x23, "access" },
470         { 0x24, "b" },
471         { 0x25, "big" },
472         { 0x26, "br" },
473         { 0x27, "card" },
474         { 0x28, "do" },
475         { 0x29, "em" },
476         { 0x2A, "fieldset" },
477         { 0x2B, "go" },
478         { 0x2C, "head" },
479         { 0x2D, "i" },
480         { 0x2E, "img" },
481         { 0x2F, "input" },
482         { 0x30, "meta" },
483         { 0x31, "noop" },
484         { 0x32, "prev" },
485         { 0x33, "onevent" },
486         { 0x34, "optgroup" },
487         { 0x35, "option" },
488         { 0x36, "refresh" },
489         { 0x37, "select" },
490         { 0x38, "small" },
491         { 0x39, "strong" },
492         /* 0x3A */
493         { 0x3B, "template" },
494         { 0x3C, "timer" },
495         { 0x3D, "u" },
496         { 0x3E, "setvar" },
497         { 0x3F, "wml" },
498
499         { 0x00, NULL }
500 };
501
502 /*****    Attribute Start tokens   *****/
503 static const value_string wbxml_wmlc11_attrStart_cp0[] = {
504         /* 0x00 -- 0x04 GLOBAL */
505         { 0x05, "accept-charset=" },
506         { 0x06, "align='bottom'" },
507         { 0x07, "align='center'" },
508         { 0x08, "align='left'" },
509         { 0x09, "align='middle'" },
510         { 0x0A, "align='right'" },
511         { 0x0B, "align='top'" },
512         { 0x0C, "alt=" },
513         { 0x0D, "content=" },
514         /* 0x0E */
515         { 0x0F, "domain=" },
516         { 0x10, "emptyok='false'" },
517         { 0x11, "emptyok='true'" },
518         { 0x12, "format=" },
519         { 0x13, "height=" },
520         { 0x14, "hspace=" },
521         { 0x15, "ivalue=" },
522         { 0x16, "iname=" },
523         /* 0x17 */
524         { 0x18, "label=" },
525         { 0x19, "localsrc=" },
526         { 0x1A, "maxlength=" },
527         { 0x1B, "method='get'" },
528         { 0x1C, "method='post'" },
529         { 0x1D, "mode='nowrap'" },
530         { 0x1E, "mode='wrap'" },
531         { 0x1F, "multiple='false'" },
532         { 0x20, "multiple='true'" },
533         { 0x21, "name=" },
534         { 0x22, "newcontext='false'" },
535         { 0x23, "newcontext='true'" },
536         { 0x24, "onpick=" },
537         { 0x25, "onenterbackward=" },
538         { 0x26, "onenterforward=" },
539         { 0x27, "ontimer=" },
540         { 0x28, "optional='false'" },
541         { 0x29, "optional='true'" },
542         { 0x2A, "path=" },
543         /* 0x2B -- 0x2D */
544         { 0x2E, "scheme=" },
545         { 0x2F, "sendreferer='false'" },
546         { 0x30, "sendreferer='true'" },
547         { 0x31, "size=" },
548         { 0x32, "src=" },
549         { 0x33, "ordered='false'" },
550         { 0x34, "ordered='true'" },
551         { 0x35, "tabindex=" },
552         { 0x36, "title=" },
553         { 0x37, "type=" },
554         { 0x38, "type='accept'" },
555         { 0x39, "type='delete'" },
556         { 0x3A, "type='help'" },
557         { 0x3B, "type='password'" },
558         { 0x3C, "type='onpick'" },
559         { 0x3D, "type='onenterbackward'" },
560         { 0x3E, "type='onenterforward'" },
561         { 0x3F, "type='ontimer'" },
562         /* 0x40 -- 0x44 GLOBAL */
563         { 0x45, "type='options'" },
564         { 0x46, "type='prev'" },
565         { 0x47, "type='reset'" },
566         { 0x48, "type='text'" },
567         { 0x49, "type='vnd.'" },
568         { 0x4A, "href=" },
569         { 0x4B, "href='http://'" },
570         { 0x4C, "href='https://'" },
571         { 0x4D, "value=" },
572         { 0x4E, "vspace=" },
573         { 0x4F, "width=" },
574         { 0x50, "xml:lang=" },
575         /* 0x51 */
576         { 0x52, "align=" },
577         { 0x53, "columns=" },
578         { 0x54, "class=" },
579         { 0x55, "id=" },
580         { 0x56, "forua='false'" },
581         { 0x57, "forua='true'" },
582         { 0x58, "src='http://'" },
583         { 0x59, "src='https://'" },
584         { 0x5A, "http-equiv=" },
585         { 0x5B, "http-equiv='Content-Type'" },
586         { 0x5C, "content='application/vnd.wap.wmlc;charset='" },
587         { 0x5D, "http-equiv='Expires'" },
588
589         { 0x00, NULL }
590 };
591
592 /*****    Attribute Value tokens   *****/
593 static const value_string wbxml_wmlc11_attrValue_cp0[] = {
594         /* 0x80 -- 0x84 GLOBAL */
595         { 0x85, "'.com/'" },
596         { 0x86, "'.edu/'" },
597         { 0x87, "'.net/'" },
598         { 0x88, "'.org/'" },
599         { 0x89, "'accept'" },
600         { 0x8A, "'bottom'" },
601         { 0x8B, "'clear'" },
602         { 0x8C, "'delete'" },
603         { 0x8D, "'help'" },
604         { 0x8E, "'http://'" },
605         { 0x8F, "'http://www.'" },
606         { 0x90, "'https://'" },
607         { 0x91, "'https://www.'" },
608         /* 0x92 */
609         { 0x93, "'middle'" },
610         { 0x94, "'nowrap'" },
611         { 0x95, "'onpick'" },
612         { 0x96, "'onenterbackward'" },
613         { 0x97, "'onenterforward'" },
614         { 0x98, "'ontimer'" },
615         { 0x99, "'options'" },
616         { 0x9A, "'password'" },
617         { 0x9B, "'reset'" },
618         /* 0x9C */
619         { 0x9D, "'text'" },
620         { 0x9E, "'top'" },
621         { 0x9F, "'unknown'" },
622         { 0xA0, "'wrap'" },
623         { 0xA1, "'www.'" },
624
625         { 0x00, NULL }
626 };
627
628 /***** Token code page aggregation *****/
629 static const value_valuestring wbxml_wmlc11_global[] = {
630         { 0, wbxml_wmlc10_global_cp0 }, /* Same as WML 1.0 */
631         { 0, NULL }
632 };
633
634 static const value_valuestring wbxml_wmlc11_tags[] = {
635         { 0, wbxml_wmlc11_tags_cp0 },
636         { 0, NULL }
637 };
638
639 static const value_valuestring wbxml_wmlc11_attrStart[] = {
640         { 0, wbxml_wmlc11_attrStart_cp0 },
641         { 0, NULL }
642 };
643
644 static const value_valuestring wbxml_wmlc11_attrValue[] = {
645         { 0, wbxml_wmlc11_attrValue_cp0 },
646         { 0, NULL }
647 };
648
649
650
651
652
653 /* WML 1.2
654  * 
655  * Wireless Markup Language
656  ***************************************/
657
658 /*****   Global extension tokens   *****/
659 /* Same as in WML 1.0 */
660
661 /*****         Tag tokens          *****/
662 static const value_string wbxml_wmlc12_tags_cp0[] = {
663         /* 0x00 -- 0x04 GLOBAL */
664         /* 0x05 -- 0x1A */
665         { 0x1B, "pre" },
666         { 0x1C, "a" },
667         { 0x1D, "td" },
668         { 0x1E, "tr" },
669         { 0x1F, "table" },
670         { 0x20, "p" },
671         { 0x21, "postfield" },
672         { 0x22, "anchor" },
673         { 0x23, "access" },
674         { 0x24, "b" },
675         { 0x25, "big" },
676         { 0x26, "br" },
677         { 0x27, "card" },
678         { 0x28, "do" },
679         { 0x29, "em" },
680         { 0x2A, "fieldset" },
681         { 0x2B, "go" },
682         { 0x2C, "head" },
683         { 0x2D, "i" },
684         { 0x2E, "img" },
685         { 0x2F, "input" },
686         { 0x30, "meta" },
687         { 0x31, "noop" },
688         { 0x32, "prev" },
689         { 0x33, "onevent" },
690         { 0x34, "optgroup" },
691         { 0x35, "option" },
692         { 0x36, "refresh" },
693         { 0x37, "select" },
694         { 0x38, "small" },
695         { 0x39, "strong" },
696         /* 0x3A */
697         { 0x3B, "template" },
698         { 0x3C, "timer" },
699         { 0x3D, "u" },
700         { 0x3E, "setvar" },
701         { 0x3F, "wml" },
702
703         { 0x00, NULL }
704 };
705
706 /*****    Attribute Start tokens   *****/
707 static const value_string wbxml_wmlc12_attrStart_cp0[] = {
708         /* 0x00 -- 0x04 GLOBAL */
709         { 0x05, "accept-charset=" },
710         { 0x06, "align='bottom'" },
711         { 0x07, "align='center'" },
712         { 0x08, "align='left'" },
713         { 0x09, "align='middle'" },
714         { 0x0A, "align='right'" },
715         { 0x0B, "align='top'" },
716         { 0x0C, "alt=" },
717         { 0x0D, "content=" },
718         /* 0x0E */
719         { 0x0F, "domain=" },
720         { 0x10, "emptyok='false'" },
721         { 0x11, "emptyok='true'" },
722         { 0x12, "format=" },
723         { 0x13, "height=" },
724         { 0x14, "hspace=" },
725         { 0x15, "ivalue=" },
726         { 0x16, "iname=" },
727         /* 0x17 */
728         { 0x18, "label=" },
729         { 0x19, "localsrc=" },
730         { 0x1A, "maxlength=" },
731         { 0x1B, "method='get'" },
732         { 0x1C, "method='post'" },
733         { 0x1D, "mode='nowrap'" },
734         { 0x1E, "mode='wrap'" },
735         { 0x1F, "multiple='false'" },
736         { 0x20, "multiple='true'" },
737         { 0x21, "name=" },
738         { 0x22, "newcontext='false'" },
739         { 0x23, "newcontext='true'" },
740         { 0x24, "onpick=" },
741         { 0x25, "onenterbackward=" },
742         { 0x26, "onenterforward=" },
743         { 0x27, "ontimer=" },
744         { 0x28, "optional='false'" },
745         { 0x29, "optional='true'" },
746         { 0x2A, "path=" },
747         /* 0x2B -- 0x2D */
748         { 0x2E, "scheme=" },
749         { 0x2F, "sendreferer='false'" },
750         { 0x30, "sendreferer='true'" },
751         { 0x31, "size=" },
752         { 0x32, "src=" },
753         { 0x33, "ordered='false'" },
754         { 0x34, "ordered='true'" },
755         { 0x35, "tabindex=" },
756         { 0x36, "title=" },
757         { 0x37, "type=" },
758         { 0x38, "type='accept'" },
759         { 0x39, "type='delete'" },
760         { 0x3A, "type='help'" },
761         { 0x3B, "type='password'" },
762         { 0x3C, "type='onpick'" },
763         { 0x3D, "type='onenterbackward'" },
764         { 0x3E, "type='onenterforward'" },
765         { 0x3F, "type='ontimer'" },
766         /* 0x40 -- 0x44 GLOBAL */
767         { 0x45, "type='options'" },
768         { 0x46, "type='prev'" },
769         { 0x47, "type='reset'" },
770         { 0x48, "type='text'" },
771         { 0x49, "type='vnd.'" },
772         { 0x4A, "href=" },
773         { 0x4B, "href='http://'" },
774         { 0x4C, "href='https://'" },
775         { 0x4D, "value=" },
776         { 0x4E, "vspace=" },
777         { 0x4F, "width=" },
778         { 0x50, "xml:lang=" },
779         /* 0x51 */
780         { 0x52, "align=" },
781         { 0x53, "columns=" },
782         { 0x54, "class=" },
783         { 0x55, "id=" },
784         { 0x56, "forua='false'" },
785         { 0x57, "forua='true'" },
786         { 0x58, "src='http://'" },
787         { 0x59, "src='https://'" },
788         { 0x5A, "http-equiv=" },
789         { 0x5B, "http-equiv='Content-Type'" },
790         { 0x5C, "content='application/vnd.wap.wmlc;charset='" },
791         { 0x5D, "http-equiv='Expires'" },
792         { 0x5E, "accesskey=" },
793         { 0x5F, "enctype=" },
794         { 0x60, "enctype='application/x-www-form-urlencoded'" },
795         { 0x61, "enctype='multipart/form-data'" },
796
797         { 0x00, NULL }
798 };
799
800 /*****    Attribute Value tokens   *****/
801 /* Same as in WML 1.1 */
802
803 /***** Token code page aggregation *****/
804 static const value_valuestring wbxml_wmlc12_global[] = {
805         { 0, wbxml_wmlc10_global_cp0 }, /* Same as WML 1.0 */
806         { 0, NULL }
807 };
808
809 static const value_valuestring wbxml_wmlc12_tags[] = {
810         { 0, wbxml_wmlc12_tags_cp0 },
811         { 0, NULL }
812 };
813
814 static const value_valuestring wbxml_wmlc12_attrStart[] = {
815         { 0, wbxml_wmlc12_attrStart_cp0 },
816         { 0, NULL }
817 };
818
819 static const value_valuestring wbxml_wmlc12_attrValue[] = {
820         { 0, wbxml_wmlc11_attrValue_cp0 }, /* Same as WML 1.1 */
821         { 0, NULL }
822 };
823
824
825
826
827
828 /* WML 1.3
829  * 
830  * Wireless Markup Language
831  ***************************************/
832
833 /*****   Global extension tokens   *****/
834 /* Same as in WML 1.0 */
835
836 /*****         Tag tokens          *****/
837 /* Same as in WML 1.2 */
838
839 /*****    Attribute Start tokens   *****/
840 static const value_string wbxml_wmlc13_attrStart_cp0[] = {
841         /* 0x00 -- 0x04 GLOBAL */
842         { 0x05, "accept-charset=" },
843         { 0x06, "align='bottom'" },
844         { 0x07, "align='center'" },
845         { 0x08, "align='left'" },
846         { 0x09, "align='middle'" },
847         { 0x0A, "align='right'" },
848         { 0x0B, "align='top'" },
849         { 0x0C, "alt=" },
850         { 0x0D, "content=" },
851         /* 0x0E */
852         { 0x0F, "domain=" },
853         { 0x10, "emptyok='false'" },
854         { 0x11, "emptyok='true'" },
855         { 0x12, "format=" },
856         { 0x13, "height=" },
857         { 0x14, "hspace=" },
858         { 0x15, "ivalue=" },
859         { 0x16, "iname=" },
860         /* 0x17 */
861         { 0x18, "label=" },
862         { 0x19, "localsrc=" },
863         { 0x1A, "maxlength=" },
864         { 0x1B, "method='get'" },
865         { 0x1C, "method='post'" },
866         { 0x1D, "mode='nowrap'" },
867         { 0x1E, "mode='wrap'" },
868         { 0x1F, "multiple='false'" },
869         { 0x20, "multiple='true'" },
870         { 0x21, "name=" },
871         { 0x22, "newcontext='false'" },
872         { 0x23, "newcontext='true'" },
873         { 0x24, "onpick=" },
874         { 0x25, "onenterbackward=" },
875         { 0x26, "onenterforward=" },
876         { 0x27, "ontimer=" },
877         { 0x28, "optional='false'" },
878         { 0x29, "optional='true'" },
879         { 0x2A, "path=" },
880         /* 0x2B -- 0x2D */
881         { 0x2E, "scheme=" },
882         { 0x2F, "sendreferer='false'" },
883         { 0x30, "sendreferer='true'" },
884         { 0x31, "size=" },
885         { 0x32, "src=" },
886         { 0x33, "ordered='false'" },
887         { 0x34, "ordered='true'" },
888         { 0x35, "tabindex=" },
889         { 0x36, "title=" },
890         { 0x37, "type=" },
891         { 0x38, "type='accept'" },
892         { 0x39, "type='delete'" },
893         { 0x3A, "type='help'" },
894         { 0x3B, "type='password'" },
895         { 0x3C, "type='onpick'" },
896         { 0x3D, "type='onenterbackward'" },
897         { 0x3E, "type='onenterforward'" },
898         { 0x3F, "type='ontimer'" },
899         /* 0x40 -- 0x44 GLOBAL */
900         { 0x45, "type='options'" },
901         { 0x46, "type='prev'" },
902         { 0x47, "type='reset'" },
903         { 0x48, "type='text'" },
904         { 0x49, "type='vnd.'" },
905         { 0x4A, "href=" },
906         { 0x4B, "href='http://'" },
907         { 0x4C, "href='https://'" },
908         { 0x4D, "value=" },
909         { 0x4E, "vspace=" },
910         { 0x4F, "width=" },
911         { 0x50, "xml:lang=" },
912         /* 0x51 */
913         { 0x52, "align=" },
914         { 0x53, "columns=" },
915         { 0x54, "class=" },
916         { 0x55, "id=" },
917         { 0x56, "forua='false'" },
918         { 0x57, "forua='true'" },
919         { 0x58, "src='http://'" },
920         { 0x59, "src='https://'" },
921         { 0x5A, "http-equiv=" },
922         { 0x5B, "http-equiv='Content-Type'" },
923         { 0x5C, "content='application/vnd.wap.wmlc;charset='" },
924         { 0x5D, "http-equiv='Expires'" },
925         { 0x5E, "accesskey=" },
926         { 0x5F, "enctype=" },
927         { 0x60, "enctype='application/x-www-form-urlencoded'" },
928         { 0x61, "enctype='multipart/form-data'" },
929         { 0x62, "xml:space='preserve'" },
930         { 0x63, "xml:space='default'" },
931         { 0x64, "cache-control='no-cache'" },
932
933         { 0x00, NULL }
934 };
935
936 /*****    Attribute Value tokens   *****/
937 /* Same as in WML 1.1 */
938
939 /***** Token code page aggregation *****/
940 static const value_valuestring wbxml_wmlc13_global[] = {
941         { 0, wbxml_wmlc10_global_cp0 }, /* Same as WML 1.0 */
942         { 0, NULL }
943 };
944
945 static const value_valuestring wbxml_wmlc13_tags[] = {
946         { 0, wbxml_wmlc12_tags_cp0 },
947         { 0, NULL }
948 };
949
950 static const value_valuestring wbxml_wmlc13_attrStart[] = {
951         { 0, wbxml_wmlc13_attrStart_cp0 },
952         { 0, NULL }
953 };
954
955 static const value_valuestring wbxml_wmlc13_attrValue[] = {
956         { 0, wbxml_wmlc11_attrValue_cp0 }, /* Same as WML 1.1 */
957         { 0, NULL }
958 };
959
960
961
962
963
964 /* SI 1.0
965  * 
966  * Service Indication
967  ***************************************/
968
969 /*****   Global extension tokens   *****/
970
971 /*****         Tag tokens          *****/
972 static const value_string wbxml_sic10_tags_cp0[] = {
973         /* 0x00 -- 0x04 GLOBAL */
974         { 0x05, "si" },
975         { 0x06, "indication" },
976         { 0x07, "info" },
977         { 0x08, "item" },
978
979         { 0x00, NULL }
980 };
981
982 /*****    Attribute Start tokens   *****/
983 static const value_string wbxml_sic10_attrStart_cp0[] = {
984         /* 0x00 -- 0x04 GLOBAL */
985         { 0x05, "action='signal-none'" },
986         { 0x06, "action='signal-low'" },
987         { 0x07, "action='signal-medium'" },
988         { 0x08, "action='signal-high'" },
989         { 0x09, "action='delete'" },
990         { 0x0a, "created=" },
991         { 0x0b, "href=" },
992         { 0x0c, "href='http://'" },
993         { 0x0d, "href='http://www.'" },
994         { 0x0e, "href='https://'" },
995         { 0x0f, "href='https://www.'" },
996         { 0x10, "si-expires=" },
997         { 0x11, "si-id=" },
998         { 0x12, "class=" },
999
1000         { 0x00, NULL }
1001 };
1002
1003 /*****    Attribute Value tokens   *****/
1004 static const value_string wbxml_sic10_attrValue_cp0[] = {
1005         /* 0x80 -- 0x84 GLOBAL */
1006         { 0x85, "'.com/'" },
1007         { 0x86, "'.edu/'" },
1008         { 0x87, "'.net/'" },
1009         { 0x88, "'.org/'" },
1010
1011         { 0x00, NULL }
1012 };
1013
1014 /***** Token code page aggregation *****/
1015 static const value_valuestring wbxml_sic10_tags[] = {
1016         { 0, wbxml_sic10_tags_cp0 },
1017         { 0, NULL }
1018 };
1019
1020 static const value_valuestring wbxml_sic10_attrStart[] = {
1021         { 0, wbxml_sic10_attrStart_cp0 },
1022         { 0, NULL }
1023 };
1024
1025 static const value_valuestring wbxml_sic10_attrValue[] = {
1026         { 0, wbxml_sic10_attrValue_cp0 },
1027         { 0, NULL }
1028 };
1029
1030
1031
1032
1033
1034 /* SL 1.0
1035  * 
1036  * Service Loading
1037  ***************************************/
1038
1039 /*****   Global extension tokens   *****/
1040
1041 /*****         Tag tokens          *****/
1042 static const value_string wbxml_slc10_tags_cp0[] = {
1043         /* 0x00 -- 0x04 GLOBAL */
1044         { 0x05, "sl" },
1045
1046         { 0x00, NULL }
1047 };
1048
1049 /*****    Attribute Start tokens   *****/
1050 static const value_string wbxml_slc10_attrStart_cp0[] = {
1051         /* 0x00 -- 0x04 GLOBAL */
1052         { 0x05, "action='execute-low'" },
1053         { 0x06, "action='execute-high'" },
1054         { 0x07, "action='cache'" },
1055         { 0x08, "href=" },
1056         { 0x09, "href='http://'" },
1057         { 0x0a, "href='http://www.'" },
1058         { 0x0b, "href='https://'" },
1059         { 0x0c, "href='https://www.'" },
1060
1061         { 0x00, NULL }
1062 };
1063
1064 /*****    Attribute Value tokens   *****/
1065 /* Same as in SI 1.0 */
1066
1067 /***** Token code page aggregation *****/
1068 static const value_valuestring wbxml_slc10_tags[] = {
1069         { 0, wbxml_slc10_tags_cp0 },
1070         { 0, NULL }
1071 };
1072
1073 static const value_valuestring wbxml_slc10_attrStart[] = {
1074         { 0, wbxml_slc10_attrStart_cp0 },
1075         { 0, NULL }
1076 };
1077
1078 static const value_valuestring wbxml_slc10_attrValue[] = {
1079         { 0, wbxml_sic10_attrValue_cp0 }, /* Same as SI 1.0 */
1080         { 0, NULL }
1081 };
1082
1083
1084
1085
1086
1087 /* CO 1.0
1088  * 
1089  * Cache Operation
1090  ***************************************/
1091
1092 /*****   Global extension tokens   *****/
1093
1094 /*****         Tag tokens          *****/
1095 static const value_string wbxml_coc10_tags_cp0[] = {
1096         /* 0x00 -- 0x04 GLOBAL */
1097         { 0x05, "co" },
1098         { 0x06, "invalidate-object" },
1099         { 0x07, "invalidate-service" },
1100
1101         { 0x00, NULL }
1102 };
1103
1104 /*****    Attribute Start tokens   *****/
1105 static const value_string wbxml_coc10_attrStart_cp0[] = {
1106         /* 0x00 -- 0x04 GLOBAL */
1107         { 0x05, "uri=" },
1108         { 0x06, "uri='http://'" },
1109         { 0x07, "uri='http://www.'" },
1110         { 0x08, "uri='https://'" },
1111         { 0x09, "uri='https://www.'" },
1112
1113         { 0x00, NULL }
1114 };
1115
1116 /*****    Attribute Value tokens   *****/
1117 /* Same as in SI 1.0 */
1118
1119 /***** Token code page aggregation *****/
1120 static const value_valuestring wbxml_coc10_tags[] = {
1121         { 0, wbxml_coc10_tags_cp0 },
1122         { 0, NULL }
1123 };
1124
1125 static const value_valuestring wbxml_coc10_attrStart[] = {
1126         { 0, wbxml_coc10_attrStart_cp0 },
1127         { 0, NULL }
1128 };
1129
1130 static const value_valuestring wbxml_coc10_attrValue[] = {
1131         { 0, wbxml_sic10_attrValue_cp0 }, /* Same as SI 1.0 */
1132         { 0, NULL }
1133 };
1134
1135
1136
1137
1138
1139 /* PROV 1.0
1140  *
1141  * Client Provisioning
1142  ***************************************/
1143
1144 /*****   Global extension tokens   *****/
1145
1146 /*****         Tag tokens          *****/
1147 static const value_string wbxml_provc10_tags_cp0[] = {
1148         /* 0x00 -- 0x04 GLOBAL */
1149         { 0x05, "wap-provisioningdoc" },
1150         { 0x06, "characteristic" },
1151         { 0x07, "parm" },
1152
1153         { 0x00, NULL }
1154 };
1155
1156 /*****    Attribute Start tokens   *****/
1157 static const value_string wbxml_provc10_attrStart_cp0[] = {
1158         /* 0x00 -- 0x04 GLOBAL */
1159         { 0x05, "name=" },
1160         { 0x06, "value=" },
1161         { 0x07, "name='NAME'" },
1162         { 0x08, "name='NAP-ADDRESS'" },
1163         { 0x09, "name='NAP-ADDRTYPE'" },
1164         { 0x0A, "name='CALLTYPE'" },
1165         { 0x0B, "name='VALIDUNTIL'" },
1166         { 0x0C, "name='AUTHTYPE'" },
1167         { 0x0D, "name='AUTHNAME'" },
1168         { 0x0E, "name='AUTHSECRET'" },
1169         { 0x0F, "name='LINGER'" },
1170         { 0x10, "name='BEARER'" },
1171         { 0x11, "name='NAPID'" },
1172         { 0x12, "name='COUNTRY'" },
1173         { 0x13, "name='NETWORK'" },
1174         { 0x14, "name='INTERNET'" },
1175         { 0x15, "name='PROXY-ID'" },
1176         { 0x16, "name='PROXY-PROVIDER-ID'" },
1177         { 0x17, "name='DOMAIN'" },
1178         { 0x18, "name='PROVURL'" },
1179         { 0x19, "name='PXAUTH-TYPE'" },
1180         { 0x1A, "name='PXAUTH-ID'" },
1181         { 0x1B, "name='PXAUTH-PW'" },
1182         { 0x1C, "name='STARTPAGE'" },
1183         { 0x1D, "name='BASAUTH-ID'" },
1184         { 0x1E, "name='BASAUTH-PW'" },
1185         { 0x1F, "name='PUSHENABLED'" },
1186         { 0x20, "name='PXADDR'" },
1187         { 0x21, "name='PXADDRTYPE'" },
1188         { 0x22, "name='TO-NAPID'" },
1189         { 0x23, "name='PORTNBR'" },
1190         { 0x24, "name='SERVICE'" },
1191         { 0x25, "name='LINKSPEED'" },
1192         { 0x26, "name='DNLINKSPEED'" },
1193         { 0x27, "name='LOCAL-ADDR'" },
1194         { 0x28, "name='LOCAL-ADDRTYPE'" },
1195         { 0x29, "name='CONTEXT-ALLOW'" },
1196         { 0x2A, "name='TRUST'" },
1197         { 0x2B, "name='MASTER'" },
1198         { 0x2C, "name='SID'" },
1199         { 0x2D, "name='SOC'" },
1200         { 0x2E, "name='WSP-VERSION'" },
1201         { 0x2F, "name='PHYSICAL-PROXY-ID'" },
1202         { 0x30, "name='CLIENT-ID'" },
1203         { 0x31, "name='DELIVERY-ERR-SDU'" },
1204         { 0x32, "name='DELIVERY-ORDER'" },
1205         { 0x33, "name='TRAFFIC-CLASS'" },
1206         { 0x34, "name='MAX-SDU-SIZE'" },
1207         { 0x35, "name='MAX-BITRATE-UPLINK'" },
1208         { 0x36, "name='MAX-BITRATE-DNLINK'" },
1209         { 0x37, "name='RESIDUAL-BER'" },
1210         { 0x38, "name='SDU-ERROR-RATIO'" },
1211         { 0x39, "name='TRAFFIC-HANDL-PRIO'" },
1212         { 0x3A, "name='TRANSFER-DELAY'" },
1213         { 0x3B, "name='GUARANTEED-BITRATE-UPLINK'" },
1214         { 0x3C, "name='GUARANTEED-BITRATE-DNLINK'" },
1215         /* 0x3D -- 0x3F */
1216         /* 0x40 -- 0x44 GLOBAL */
1217         { 0x45, "version=" },
1218         { 0x46, "version='1.0'" },
1219         /* 0x47 -- 0x4F */
1220         { 0x50, "type=" },
1221         { 0x51, "type='PXLOGICAL'" },
1222         { 0x52, "type='PXPHYSICAL'" },
1223         { 0x53, "type='PORT'" },
1224         { 0x54, "type='VALIDITY'" },
1225         { 0x55, "type='NAPDEF'" },
1226         { 0x56, "type='BOOTSTRAP'" },
1227         { 0x57, "type='VENDORCONFIG'" },
1228         { 0x58, "type='CLIENTIDENTITY'" },
1229         { 0x59, "type='PXAUTHINFO'" },
1230         { 0x5A, "type='NAPAUTHINFO'" },
1231
1232         { 0x00, NULL }
1233 };
1234
1235 /*****    Attribute Start tokens   *****/
1236 static const value_string wbxml_provc10_attrValue_cp0[] = {
1237         /* 0x80 -- 0x84 GLOBAL */
1238         { 0x85, "'IPV4'" },
1239         { 0x86, "'IPV6'" },
1240         { 0x87, "'E164'" },
1241         { 0x88, "'ALPHA'" },
1242         { 0x89, "'APN'" },
1243         { 0x8A, "'SCODE'" },
1244         { 0x8B, "'TETRA-ITSI'" },
1245         { 0x8C, "'MAN'" },
1246         /* 0x8D -- 0x8F */
1247         { 0x90, "'ANALOG-MODEM'" },
1248         { 0x91, "'V.120'" },
1249         { 0x92, "'V.110'" },
1250         { 0x93, "'X.31'" },
1251         { 0x94, "'BIT-TRANSPARENT'" },
1252         { 0x95, "'DIRECT-ASYNCHRONOUS-DATA-SERVICE'" },
1253         /* 0x96 -- 0x99 */
1254         { 0x9A, "'PAP'" },
1255         { 0x9B, "'CHAP'" },
1256         { 0x9C, "'HTTP-BASIC'" },
1257         { 0x9D, "'HTTP-DIGEST'" },
1258         { 0x9E, "'WTLS-SS'" },
1259         /* 0x9F -- 0xA1 */
1260         { 0xA2, "'GSM-USSD'" },
1261         { 0xA3, "'GSM-SMS'" },
1262         { 0xA4, "'ANSI-136-GUTS'" },
1263         { 0xA5, "'IS-95-CDMA-SMS'" },
1264         { 0xA6, "'IS-95-CDMA-CSD'" },
1265         { 0xA7, "'IS-95-CDMA-PACKET'" },
1266         { 0xA8, "'ANSI-136-CSD'" },
1267         { 0xA9, "'ANSI-136-GPRS'" },
1268         { 0xAA, "'GSM-CSD'" },
1269         { 0xAB, "'GSM-GPRS'" },
1270         { 0xAC, "'AMPS-CDPD'" },
1271         { 0xAD, "'PDC-CSD'" },
1272         { 0xAE, "'PDC-PACKET'" },
1273         { 0xAF, "'IDEN-SMS'" },
1274         { 0xB0, "'IDEN-CSD'" },
1275         { 0xB1, "'IDEN-PACKET'" },
1276         { 0xB2, "'FLEX/REFLEX'" },
1277         { 0xB3, "'PHS-SMS'" },
1278         { 0xB4, "'PHS-CSD'" },
1279         { 0xB5, "'TETRA-SDS'" },
1280         { 0xB6, "'TETRA-PACKET'" },
1281         { 0xB7, "'ANSI-136-GHOST'" },
1282         { 0xB8, "'MOBITEX-MPAK'" },
1283         /* 0xB9 -- 0xBF */
1284         /* 0xC0 -- 0xC4 GLOBAL */
1285         { 0xC5, "'AUTOBAUDING'" },
1286         /* 0xC6 -- 0xC9 */
1287         { 0xCA, "'CL-WSP'" },
1288         { 0xCB, "'CO-WSP'" },
1289         { 0xCC, "'CL-SEC-WSP'" },
1290         { 0xCD, "'CO-SEC-WSP'" },
1291         { 0xCE, "'CL-SEC-WTA'" },
1292         { 0xCF, "'CO-SEC-WTA'" },
1293
1294         { 0x00, NULL }
1295 };
1296
1297 /***** Token code page aggregation *****/
1298 static const value_valuestring wbxml_provc10_tags[] = {
1299         { 0, wbxml_provc10_tags_cp0 },
1300         { 0, NULL }
1301 };
1302
1303 static const value_valuestring wbxml_provc10_attrStart[] = {
1304         { 0, wbxml_provc10_attrStart_cp0 },
1305         { 0, NULL }
1306 };
1307
1308 static const value_valuestring wbxml_provc10_attrValue[] = {
1309         { 0, wbxml_provc10_attrValue_cp0 },
1310         { 0, NULL }
1311 };
1312
1313
1314
1315
1316
1317 /* EMN 1.0
1318  * 
1319  * Email Notification
1320  ***************************************/
1321
1322 /*****   Global extension tokens   *****/
1323
1324 /*****         Tag tokens          *****/
1325 static const value_string wbxml_emnc10_tags_cp0[] = {
1326         /* 0x00 -- 0x04 GLOBAL */
1327         { 0x05, "emn" },
1328
1329         { 0x00, NULL }
1330 };
1331
1332 /*****    Attribute Start tokens   *****/
1333 static const value_string wbxml_emnc10_attrStart_cp0[] = {
1334         /* 0x00 -- 0x04 GLOBAL */
1335         { 0x05, "timestamp=" },
1336         { 0x06, "mailbox=" },
1337         { 0x07, "mailbox='mailat:'" },
1338         { 0x08, "mailbox='pop://'" },
1339         { 0x09, "mailbox='imap://'" },
1340         { 0x0a, "mailbox='http://'" },
1341         { 0x0b, "mailbox='http://www.'" },
1342         { 0x0c, "mailbox='https://'" },
1343         { 0x0D, "mailbox='https://www.'" },
1344
1345         { 0x00, NULL }
1346 };
1347
1348 /*****    Attribute Value tokens   *****/
1349 /* Same as in SI 1.0 */
1350
1351 /***** Token code page aggregation *****/
1352 static const value_valuestring wbxml_emnc10_tags[] = {
1353         { 0, wbxml_emnc10_tags_cp0 },
1354         { 0, NULL }
1355 };
1356
1357 static const value_valuestring wbxml_emnc10_attrStart[] = {
1358         { 0, wbxml_emnc10_attrStart_cp0 },
1359         { 0, NULL }
1360 };
1361
1362 static const value_valuestring wbxml_emnc10_attrValue[] = {
1363         { 0, wbxml_sic10_attrValue_cp0 }, /* Same as SI 1.0 */
1364         { 0, NULL }
1365 };
1366
1367
1368
1369
1370
1371 /* SyncML 1.0
1372  * 
1373  * SyncML Representation Protocol
1374  ***************************************/
1375
1376 /*****   Global extension tokens   *****/
1377
1378 /*****         Tag tokens          *****/
1379 static const value_string wbxml_syncmlc10_tags_cp0[] = { /* SyncML 1.0 */
1380         /* 0x00 -- 0x04 GLOBAL */
1381         { 0x05, "Add" },
1382         { 0x06, "Alert" },
1383         { 0x07, "Archive" },
1384         { 0x08, "Atomic" },
1385         { 0x09, "Chal" },
1386         { 0x0A, "Cmd" },
1387         { 0x0B, "CmdID" },
1388         { 0x0C, "CmdRef" },
1389         { 0x0D, "Copy" },
1390         { 0x0E, "Cred" },
1391         { 0x0F, "Data" },
1392         { 0x10, "Delete" },
1393         { 0x11, "Exec" },
1394         { 0x12, "Final" },
1395         { 0x13, "Get" },
1396         { 0x14, "Item" },
1397         { 0x15, "Lang" },
1398         { 0x16, "LocName" },
1399         { 0x17, "LocURI" },
1400         { 0x18, "Map" },
1401         { 0x19, "MapItem" },
1402         { 0x1A, "Meta" },
1403         { 0x1B, "MsgID" },
1404         { 0x1C, "MsgRef" },
1405         { 0x1D, "NoResp" },
1406         { 0x1E, "NoResults" },
1407         { 0x1F, "Put" },
1408         { 0x20, "Replace" },
1409         { 0x21, "RespURI" },
1410         { 0x22, "Results" },
1411         { 0x23, "Search" },
1412         { 0x24, "Sequence" },
1413         { 0x25, "SessionID" },
1414         { 0x26, "SftDel" },
1415         { 0x27, "Source" },
1416         { 0x28, "SourceRef" },
1417         { 0x29, "Status" },
1418         { 0x2A, "Sync" },
1419         { 0x2B, "SyncBody" },
1420         { 0x2C, "SyncHdr" },
1421         { 0x2D, "SyncML" },
1422         { 0x2E, "Target" },
1423         { 0x2F, "TargetRef" },
1424         /* 0x30 - Reserved */
1425         { 0x31, "VerDTD" },
1426         { 0x32, "VerProto" },
1427
1428         { 0x00, NULL }
1429 };
1430
1431 static const value_string wbxml_syncmlc10_tags_cp1[] = { /* MetInf 1.0 */
1432         /* 0x00 -- 0x04 GLOBAL */
1433         { 0x05, "Anchor" },
1434         { 0x06, "EMI" },
1435         { 0x07, "Format" },
1436         { 0x08, "FreeID" },
1437         { 0x09, "FreeMem" },
1438         { 0x0A, "Last" },
1439         { 0x0B, "Mark" },
1440         { 0x0C, "MaxMsgSize" },
1441         { 0x0D, "Mem" },
1442         { 0x0E, "MetInf" },
1443         { 0x0F, "Next" },
1444         { 0x10, "NextNonce" },
1445         { 0x11, "SharedMem" },
1446         { 0x12, "Size" },
1447         { 0x13, "Type" },
1448         { 0x14, "Version" },
1449
1450         { 0x00, NULL }
1451 };
1452
1453 /*****    Attribute Start tokens   *****/
1454
1455 /*****    Attribute Value tokens   *****/
1456
1457 /***** Token code page aggregation *****/
1458 static const value_valuestring wbxml_syncmlc10_tags[] = {
1459         { 0, wbxml_syncmlc10_tags_cp0 }, /* -//SYNCML//DTD SyncML 1.0//EN */
1460         { 0, wbxml_syncmlc10_tags_cp1 }, /* -//SYNCML//DTD MetInf 1.0//EN */
1461         { 0, NULL }
1462 };
1463
1464
1465
1466
1467
1468 /* SyncML 1.1
1469  * 
1470  * SyncML Representation Protocol
1471  ***************************************/
1472
1473 /*****   Global extension tokens   *****/
1474
1475 /*****         Tag tokens          *****/
1476 static const value_string wbxml_syncmlc11_tags_cp0[] = { /* SyncML 1.1 */
1477         /* 0x00 -- 0x04 GLOBAL */
1478         { 0x05, "Add" },
1479         { 0x06, "Alert" },
1480         { 0x07, "Archive" },
1481         { 0x08, "Atomic" },
1482         { 0x09, "Chal" },
1483         { 0x0a, "Cmd" },
1484         { 0x0b, "CmdID" },
1485         { 0x0c, "CmdRef" },
1486         { 0x0d, "Copy" },
1487         { 0x0e, "Cred" },
1488         { 0x0f, "Data" },
1489         { 0x10, "Delete" },
1490         { 0x11, "Exec" },
1491         { 0x12, "Final" },
1492         { 0x13, "Get" },
1493         { 0x14, "Item" },
1494         { 0x15, "Lang" },
1495         { 0x16, "LocName" },
1496         { 0x17, "LocURI" },
1497         { 0x18, "Map" },
1498         { 0x19, "MapItem" },
1499         { 0x1a, "Meta" },
1500         { 0x1b, "MsgID" },
1501         { 0x1c, "MsgRef" },
1502         { 0x1d, "NoResp" },
1503         { 0x1e, "NoResults" },
1504         { 0x1f, "Put" },
1505         { 0x20, "Replace" },
1506         { 0x21, "RespURI" },
1507         { 0x22, "Results" },
1508         { 0x23, "Search" },
1509         { 0x24, "Sequence" },
1510         { 0x25, "SessionID" },
1511         { 0x26, "SftDel" },
1512         { 0x27, "Source" },
1513         { 0x28, "SourceRef" },
1514         { 0x29, "Status" },
1515         { 0x2a, "Sync" },
1516         { 0x2b, "SyncBody" },
1517         { 0x2c, "SyncHdr" },
1518         { 0x2d, "SyncML" },
1519         { 0x2e, "Target" },
1520         { 0x2f, "TargetRef" },
1521         /* 0x30 - Reserved */
1522         { 0x31, "VerDTD" },
1523         { 0x32, "VerProto" },
1524         { 0x33, "NumberOfChanges" },
1525         { 0x34, "MoreData" },
1526
1527         { 0x00, NULL }
1528 };
1529
1530 static const value_string wbxml_syncmlc11_tags_cp1[] = { /* MetInf 1.1 */
1531         /* 0x00 -- 0x04 GLOBAL */
1532         { 0x05, "Anchor" },
1533         { 0x06, "EMI" },
1534         { 0x07, "Format" },
1535         { 0x08, "FreeID" },
1536         { 0x09, "FreeMem" },
1537         { 0x0A, "Last" },
1538         { 0x0B, "Mark" },
1539         { 0x0C, "MaxMsgSize" },
1540         { 0x0D, "Mem" },
1541         { 0x0E, "MetInf" },
1542         { 0x0F, "Next" },
1543         { 0x10, "NextNonce" },
1544         { 0x11, "SharedMem" },
1545         { 0x12, "Size" },
1546         { 0x13, "Type" },
1547         { 0x14, "Version" },
1548         { 0x15, "MaxObjSize" },
1549
1550         { 0x00, NULL }
1551 };
1552
1553 /*****    Attribute Start tokens   *****/
1554
1555 /*****    Attribute Value tokens   *****/
1556
1557 /***** Token code page aggregation *****/
1558 static const value_valuestring wbxml_syncmlc11_tags[] = {
1559         { 0, wbxml_syncmlc11_tags_cp0 }, /* -//SYNCML//DTD SyncML 1.1//EN */
1560         { 0, wbxml_syncmlc11_tags_cp1 }, /* -//SYNCML//DTD MetInf 1.1//EN */
1561         { 0, NULL }
1562 };
1563
1564
1565
1566
1567
1568 /* CHANNEL 1.0
1569  * 
1570  * WTA Channel
1571  ***************************************/
1572
1573 /*****   Global extension tokens   *****/
1574
1575 /*****         Tag tokens          *****/
1576 static const value_string wbxml_channelc10_tags_cp0[] = {
1577         /* 0x00 -- 0x04 GLOBAL */
1578         { 0x05, "channel" },
1579         { 0x06, "title" },
1580         { 0x07, "abstract" },
1581         { 0x08, "resource" },
1582
1583         { 0x00, NULL }
1584 };
1585
1586 /*****    Attribute Start tokens   *****/
1587 static const value_string wbxml_channelc10_attrStart_cp0[] = {
1588         /* 0x00 -- 0x04 GLOBAL */
1589         { 0x05, "maxspace" },
1590         { 0x06, "base" },
1591         { 0x07, "href" },
1592         { 0x08, "href='http://'" },
1593         { 0x09, "href='https://'" },
1594         { 0x0A, "lastmod" },
1595         { 0x0B, "etag" },
1596         { 0x0C, "md5" },
1597         { 0x0D, "success" },
1598         { 0x0E, "success='http://'" },
1599         { 0x0F, "success='https://'" },
1600         { 0x10, "failure" },
1601         { 0x11, "failure='http://'" },
1602         { 0x12, "failure='https://'" },
1603         { 0x13, "EventId" },
1604
1605         { 0x00, NULL }
1606 };
1607
1608 /*****    Attribute Value tokens   *****/
1609
1610 /***** Token code page aggregation *****/
1611 static const value_valuestring wbxml_channelc10_tags[] = {
1612         { 0, wbxml_channelc10_tags_cp0 },
1613         { 0, NULL }
1614 };
1615
1616 static const value_valuestring wbxml_channelc10_attrStart[] = {
1617         { 0, wbxml_channelc10_attrStart_cp0 },
1618         { 0, NULL }
1619 };
1620
1621
1622
1623
1624
1625 /********************** WBXML token mapping aggregation **********************/
1626
1627
1628 /* The following structure links content types to their token mapping and
1629  * contains arrays of pointers to value_string arrays (one per code page).
1630  */
1631 typedef struct _wbxml_token_map {
1632         const guint32 publicid;  /* WBXML DTD number - see WINA */
1633         const guint8 defined;    /* Are there mapping tables defined */
1634         const value_valuestring *global;     /* Global token map */
1635         const value_valuestring *tags;       /* Tag token map */
1636         const value_valuestring *attrStart;  /* Attribute Start token map */
1637         const value_valuestring *attrValue;  /* Attribute Value token map */
1638 } wbxml_token_map;
1639
1640 static const wbxml_token_map *wbxml_content_map (guint32 publicid);
1641
1642 /**
1643  ** Aggregation of content type and aggregated code pages
1644  ** Content type map lookup will stop at the 1st entry with 2nd member = FALSE
1645  **/
1646 static const wbxml_token_map map[] = {
1647 #ifdef Test_the_parsers_without_token_mappings
1648         { 0, FALSE, NULL, NULL, NULL, NULL },
1649 #endif
1650         { 0x02, TRUE, /* WML 1.0 */
1651                 wbxml_wmlc10_global,
1652                 wbxml_wmlc10_tags,
1653                 wbxml_wmlc10_attrStart,
1654                 wbxml_wmlc10_attrValue
1655         },
1656 #ifdef remove_directive_and_set_TRUE_if_mapping_available
1657         { 0x03, FALSE, /* WTA 1.0 (deprecated) */
1658                 NULL, NULL, NULL, NULL
1659         },
1660 #endif
1661         { 0x04, TRUE, /* WML 1.1 */
1662                 wbxml_wmlc11_global,
1663                 wbxml_wmlc11_tags,
1664                 wbxml_wmlc11_attrStart,
1665                 wbxml_wmlc11_attrValue
1666         },
1667         { 0x05, TRUE, /* SI 1.0 */
1668                 NULL, /* wbxml_sic10_global - does not exist */
1669                 wbxml_sic10_tags,
1670                 wbxml_sic10_attrStart,
1671                 wbxml_sic10_attrValue
1672         },
1673         { 0x06, TRUE, /* SL 1.0 */
1674                 NULL, /* wbxml_slc10_global - does not exist */
1675                 wbxml_slc10_tags,
1676                 wbxml_slc10_attrStart,
1677                 wbxml_slc10_attrValue
1678         },
1679         { 0x07, TRUE, /* CO 1.0 */
1680                 NULL, /* wbxml_coc10_global - does not exist */
1681                 wbxml_coc10_tags,
1682                 wbxml_coc10_attrStart,
1683                 wbxml_coc10_attrValue
1684         },
1685         { 0x08, TRUE, /* CHANNEL 1.0 (deprecated) */
1686                 NULL, /* wbxml_channelc10_global - does not exist */
1687                 wbxml_channelc10_tags,
1688                 wbxml_channelc10_attrStart,
1689                 NULL, /* wbxml_channelc10_attrValue - does not exist */
1690         },
1691         { 0x09, TRUE, /* WML 1.2 */
1692                 wbxml_wmlc12_global,
1693                 wbxml_wmlc12_tags,
1694                 wbxml_wmlc12_attrStart,
1695                 wbxml_wmlc12_attrValue
1696         },
1697         { 0x0A, TRUE, /* WML 1.3 */
1698                 wbxml_wmlc13_global,
1699                 wbxml_wmlc13_tags,
1700                 wbxml_wmlc13_attrStart,
1701                 wbxml_wmlc13_attrValue
1702         },
1703         { 0x0B, TRUE, /* PROV 1.0 */
1704                 NULL, /* wbxml_provc10_global - does not exist */
1705                 wbxml_provc10_tags,
1706                 wbxml_provc10_attrStart,
1707                 wbxml_provc10_attrValue
1708         },
1709 #ifdef remove_directive_and_set_TRUE_if_mapping_available
1710         { 0x0C, FALSE, /* WTA-WML 1.2 */
1711                 NULL, NULL, NULL, NULL
1712         },
1713 #endif
1714         { 0x0D, TRUE, /* EMN 1.0 */
1715                 NULL, /* wbxml_emnc10_global - does not exist */
1716                 wbxml_emnc10_tags,
1717                 wbxml_emnc10_attrStart,
1718                 wbxml_emnc10_attrValue
1719         },
1720 #ifdef remove_directive_and_set_TRUE_if_mapping_available
1721         { 0x0E, FALSE, /* DRMREL 1.0 */
1722                 NULL, NULL, NULL, NULL
1723         },
1724 #endif
1725         { 0x0FD1, TRUE, /* SyncML 1.0 */
1726                 NULL, /* wbxml_syncmlc10_global - does not exist */
1727                 wbxml_syncmlc10_tags,
1728                 NULL, /* wbxml_syncmlc10_attrStart - does not exist */
1729                 NULL, /* wbxml_syncmlc10_attrValue - does not exist */
1730         },
1731         { 0x0FD3, TRUE, /* SyncML 1.1 */
1732                 NULL, /* wbxml_syncmlc11_global - does not exist */
1733                 wbxml_syncmlc11_tags,
1734                 NULL, /* wbxml_syncmlc11_attrStart - does not exist */
1735                 NULL, /* wbxml_syncmlc11_attrValue - does not exist */
1736         },
1737         { 0x1108, TRUE, /* Phone.com - WML+ 1.1 */
1738                 /* Note: I assumed WML+ 1.1 would be not that different from WML 1.1,
1739                  *       the real mapping should come from Phone.com (OpenWave)! */
1740                 wbxml_wmlc11_global, /* Not 100% true */
1741                 wbxml_wmlc11_tags, /* Not 100% true */
1742                 wbxml_wmlc11_attrStart, /* Not 100% true */
1743                 wbxml_wmlc11_attrValue /* Not 100% true */
1744         },
1745         { 0x110D, TRUE, /* Phone.com - WML+ 1.3 */
1746                 /* Note: I assumed WML+ 1.3 would be not that different from WML 1.3,
1747                  *       the real mapping should come from Phone.com (OpenWave)! */
1748                 wbxml_wmlc13_global, /* Not 100% true */
1749                 wbxml_wmlc13_tags, /* Not 100% true */
1750                 wbxml_wmlc13_attrStart, /* Not 100% true */
1751                 wbxml_wmlc13_attrValue /* Not 100% true */
1752         },
1753         
1754         { 0, FALSE, NULL, NULL, NULL, NULL }
1755 };
1756
1757
1758 /* WBXML content token mapping depends on the following parameters:
1759  *   - Content type (guint32)
1760  *   - Token type (global, tags, attrStart, attrValue)
1761  *   - Code page for tag and attribute
1762  *
1763  * This results in the following steps:
1764  *   1. Retrieve content type mapping
1765  *   2. If exists, retrieve token type mapping
1766  *   3. If exists, retrieve required code page
1767  *   4. If exists, retrieve token mapping
1768  */
1769
1770 /* Return token mapping for a given content mapping entry. */
1771 static const char *
1772 map_token (const value_valuestring *token_map, guint8 codepage, guint8 token) {
1773         const value_string *vs;
1774         const char *s;
1775
1776         if (token_map) { /* Found map */
1777                 if ((vs = val_to_valstr (codepage, token_map))) {
1778                         /* Found codepage map */
1779                         s = match_strval (token, vs);
1780                         if (s) /* Found valid token */
1781                                         return s;
1782                         /* No valid token mapping in specified code page of token map */
1783                         return "(Requested token not defined for this content type)";
1784                 }
1785                 /* There is no token map entry for the requested code page */
1786                 return "(Requested token code page not defined for this content type)";
1787         }
1788         /* The token map does not exist */
1789         return "(Requested token map not defined for this content type)";
1790 }
1791
1792
1793 /* Returns a pointer to the WBXML token map for the given WBXML public
1794  * identifier value (see WINA for a table with defined identifiers). */
1795 static const wbxml_token_map *wbxml_content_map (guint32 publicid) {
1796         gint i = 0;
1797
1798         while (map[i].defined) {
1799                 if (map[i].publicid == publicid)
1800                         return &(map[i]);
1801                 i++;
1802         }
1803         return NULL;
1804 }
1805
1806
1807 /************************** Function prototypes **************************/
1808
1809
1810 static void
1811 dissect_wbxml(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
1812
1813 void
1814 proto_register_wbxml(void);
1815
1816 /* Parse and display the WBXML string table */
1817 static void
1818 show_wbxml_string_table (proto_tree *tree, tvbuff_t *tvb, guint32 str_tbl,
1819                 guint32 str_tbl_len);
1820
1821 /* Return a pointer to the string in the string table.
1822  * Can also be hacked for inline string retrieval.  */
1823 static const char*
1824 strtbl_lookup (tvbuff_t *tvb, guint32 str_tbl, guint32 offset, guint32 *len);
1825
1826 /* Parse data while in STAG state */
1827 static void
1828 parse_wbxml_tag (proto_tree *tree, tvbuff_t *tvb, guint32 offset,
1829                 guint32 str_tbl, guint8 *level,
1830                 guint32 *parsed_length);
1831
1832 /* Parse data while in STAG state;
1833  * interpret tokens as defined by content type */
1834 static void
1835 parse_wbxml_tag_defined (proto_tree *tree, tvbuff_t *tvb, guint32 offset,
1836                 guint32 str_tbl, guint8 *level,
1837                 guint32 *parsed_length,
1838                 const wbxml_token_map *map);
1839
1840 /* Parse data while in ATTR state */
1841 static void
1842 parse_wbxml_attribute_list (proto_tree *tree, tvbuff_t *tvb,
1843                 guint32 offset, guint32 str_tbl, guint8 level,
1844                 guint32 *parsed_length);
1845
1846 /* Parse data while in ATTR state;
1847  * interpret tokens as defined by content type */
1848 static void
1849 parse_wbxml_attribute_list_defined (proto_tree *tree, tvbuff_t *tvb,
1850                 guint32 offset, guint32 str_tbl, guint8 level,
1851                 guint32 *parsed_length,
1852                 const wbxml_token_map *map);
1853
1854
1855 /****************** WBXML protocol dissection functions ******************/
1856
1857
1858 /* Code to actually dissect the packets */
1859 static void
1860 dissect_wbxml(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1861 {
1862         /* Set up structures needed to add the protocol subtree and manage it */
1863         proto_item *ti;
1864         proto_tree *wbxml_tree; /* Main WBXML tree */
1865         proto_tree *wbxml_str_tbl_tree; /* String table subtree */
1866         proto_tree *wbxml_content_tree; /* Content subtree */
1867         guint8 version;
1868         guint offset = 0;
1869         const char *token;
1870         guint32 len;
1871         guint32 charset=0;
1872         guint32 charset_len;
1873         guint32 publicid;
1874         guint32 publicid_index = 0;
1875         guint32 publicid_len;
1876         guint32 str_tbl;
1877         guint32 str_tbl_len;
1878         guint8 level = 0; /* WBXML recursion level */
1879         const wbxml_token_map *content_map = NULL;
1880
1881         /* WBXML format
1882          * 
1883          * Version 1.0: version publicid         strtbl BODY
1884          * Version 1.x: version publicid charset strtbl BODY
1885          *
1886          * Last valid format: WBXML 1.3
1887          */
1888         switch ( version = tvb_get_guint8 (tvb, 0) ) {
1889                 case 0x00: /* WBXML/1.0 */
1890                         break;
1891
1892                 case 0x01: /* WBXML/1.1 */
1893                 case 0x02: /* WBXML/1.2 */
1894                 case 0x03: /* WBXML/1.3 */
1895                         break;
1896
1897                 default:
1898                         return;
1899         }
1900
1901         if (check_col(pinfo->cinfo, COL_INFO))
1902                 col_append_fstr(pinfo->cinfo, COL_INFO, " (WBXML %s:",
1903                                 match_strval (version, vals_wbxml_versions));
1904
1905         /* In the interest of speed, if "tree" is NULL, don't do any work not
1906            necessary to generate protocol tree items. */
1907         if ( tree ) {
1908                 /* create display subtree for the protocol */
1909                 ti = proto_tree_add_item (tree, proto_wbxml, tvb, 0, -1, FALSE);
1910                 wbxml_tree = proto_item_add_subtree(ti, ett_wbxml);
1911
1912                 /* WBXML Version */
1913                 proto_tree_add_uint (wbxml_tree, hf_wbxml_version,
1914                                 tvb, 0, 1, version);
1915
1916                 /* Public ID */
1917                 publicid = tvb_get_guintvar(tvb, 1, &publicid_len);
1918                 if (publicid) { /* Known Public ID */
1919                         if (check_col(pinfo->cinfo, COL_INFO))
1920                                 col_append_fstr(pinfo->cinfo, COL_INFO, " Public ID \"%s\")",
1921                                                 match_strval (publicid, vals_wbxml_public_ids));
1922                         proto_tree_add_uint(wbxml_tree, hf_wbxml_public_id_known,
1923                                         tvb, 1, publicid_len, publicid);
1924                 } else { /* Public identifier in string table */
1925                         publicid_index = tvb_get_guintvar (tvb, 1+publicid_len, &len);
1926                         publicid_len += len;
1927                 }
1928                 offset = 1 + publicid_len;
1929
1930                 /* Version-specific handling of Charset */
1931                 switch ( version ) {
1932                         case 0x00: /* WBXML/1.0 */
1933                                 /* No charset */
1934                                 break;
1935
1936                         case 0x01: /* WBXML/1.1 */
1937                         case 0x02: /* WBXML/1.2 */
1938                         case 0x03: /* WBXML/1.3 */
1939                                 /* Get charset */
1940                                 charset = tvb_get_guintvar (tvb, offset, &charset_len);
1941                                 offset += charset_len;
1942                                 break;
1943
1944                         default: /* Impossible since return already earlier */
1945                                 break;
1946                 }
1947
1948                 /* String table: read string table length in bytes */
1949                 str_tbl_len = tvb_get_guintvar (tvb, offset, &len);
1950                 str_tbl = offset + len; /* Start of 1st string in string table */
1951
1952                 /* Now we can add public ID, charset (if available),
1953                  * and string table */
1954                 if ( ! publicid ) { /* Read Public ID from string table */
1955                         token = strtbl_lookup (tvb, str_tbl, publicid_index, NULL);
1956                         if (check_col(pinfo->cinfo, COL_INFO))
1957                                 col_append_fstr(pinfo->cinfo, COL_INFO, " Public ID \"%s\")",
1958                                                 token);
1959                         proto_tree_add_string (wbxml_tree, hf_wbxml_public_id_literal,
1960                                         tvb, 1, publicid_len, token?token:"[NULL STRING]");
1961                 }
1962                 if ( version ) { /* Charset */
1963                         proto_tree_add_uint (wbxml_tree, hf_wbxml_charset,
1964                                         tvb, 1+publicid_len, charset_len, charset);
1965                 }
1966                 /* String Table */
1967                 ti = proto_tree_add_text(wbxml_tree,
1968                                 tvb, offset, len + str_tbl_len, "String table: %u bytes",
1969                                 str_tbl_len);
1970
1971                 if (wbxml_tree && str_tbl_len) { /* Display string table as subtree */
1972                         wbxml_str_tbl_tree = proto_item_add_subtree (ti,
1973                                         ett_wbxml_str_tbl);
1974                         show_wbxml_string_table (wbxml_str_tbl_tree, tvb,
1975                                         str_tbl, str_tbl_len);
1976                 }
1977
1978                 /* Data starts HERE */
1979                 offset += len + str_tbl_len;
1980
1981                 /* The WBXML BODY starts here */
1982                 ti = proto_tree_add_text (wbxml_tree, tvb, offset, -1,
1983                                 "Data representation");
1984                 wbxml_content_tree = proto_item_add_subtree (ti, ett_wbxml_content);
1985
1986                 /* The parse_wbxml_X() functions will process the content correctly,
1987                  * irrespective of the WBXML version used. For the WBXML body, this
1988                  * means that there is a different processing for the global token
1989                  * RESERVED_2 (WBXML 1.0) or OPAQUE (WBXML 1.x with x > 0).  */
1990                 if (wbxml_tree) { /* Show only if visible */
1991                         if (publicid) {
1992                                 /* Retrieve the content token mapping if available */
1993                                 content_map = wbxml_content_map (publicid);
1994                                 if (content_map) {
1995                                         /* Is there a defined token mapping for publicid? */
1996                                         if (content_map->defined) {
1997                                                 proto_tree_add_text (wbxml_content_tree, tvb,
1998                                                                 offset, -1,
1999                                                                 "Level | State | Codepage "
2000                                                                 "| WBXML Token Description         "
2001                                                                 "| Rendering");
2002                                                 parse_wbxml_tag_defined (wbxml_content_tree,
2003                                                                 tvb, offset, str_tbl, &level,
2004                                                                 &len, content_map);
2005                                                 return;
2006                                         }
2007                                 }
2008                                 proto_tree_add_text (wbxml_content_tree, tvb,
2009                                                 offset, -1,
2010                                                 "[Rendering of this content type"
2011                                                 " not (yet) supported]");
2012                         }
2013                         /* Default: WBXML only, no interpretation of the content */
2014                         proto_tree_add_text (wbxml_content_tree, tvb, offset, -1,
2015                                         "Level | State | Codepage "
2016                                         "| WBXML Token Description         "
2017                                         "| Rendering");
2018                         parse_wbxml_tag (wbxml_content_tree, tvb, offset,
2019                                         str_tbl, &level, &len);
2020                         return;
2021                 } else {
2022                         proto_tree_add_text (wbxml_content_tree, tvb, offset, -1,
2023                                         "WBXML 1.0 decoding not (yet) supported");
2024                 }
2025                 return;
2026         }
2027 }
2028
2029
2030 /* Return a pointer to the string in the string table.
2031  * Can also be hacked for inline string retrieval.  */
2032 static const char*
2033 strtbl_lookup (tvbuff_t *tvb, guint32 str_tbl, guint32 offset, guint32 *len)
2034 {
2035         if (len) { /* The "hack" call for inline string reading */
2036                 *len = tvb_strsize (tvb, str_tbl+offset);
2037                 return tvb_get_ptr (tvb, str_tbl+offset, *len);
2038         } else { /* Normal string table reading */
2039                 return tvb_get_ptr (tvb, str_tbl+offset,
2040                                 tvb_strsize (tvb, str_tbl+offset));
2041         }
2042 }
2043
2044
2045 /* Parse and display the WBXML string table (in a 3-column table format).
2046  * This function displays:
2047  *  - the offset in the string table,
2048  *  - the length of the string
2049  *  - the string.
2050  */
2051 static void
2052 show_wbxml_string_table (proto_tree *tree, tvbuff_t *tvb, guint32 str_tbl,
2053                 guint32 str_tbl_len)
2054 {
2055         guint32 off = str_tbl;
2056         guint32 len = 0;
2057         guint32 end = str_tbl + str_tbl_len;
2058         const char *str;
2059
2060         proto_tree_add_text (tree, tvb, off, end,
2061                         "Start  | Length | String");
2062         while (off < end) {
2063                 /* Hack the string table lookup function */
2064                 str = strtbl_lookup (tvb, off, 0, &len);
2065                 proto_tree_add_text (tree, tvb, off, len,
2066                                 "%6d | %6d | '%s'",
2067                                 off - str_tbl, len, str);
2068                 off += len;
2069         }
2070 }
2071
2072
2073 /* Indentation code is based on a static const array of space characters.
2074  * At least one single space is returned */
2075 static const char indent_buffer[514] = " "
2076         "                                                                "
2077         "                                                                "
2078         "                                                                "
2079         "                                                                "
2080         "                                                                "
2081         "                                                                "
2082         "                                                                "
2083         "                                                                "
2084         ; /* Generate XML indentation (length = 1 + 2 * 256 + 1 for '\0') */
2085
2086 static const char * Indent (guint8 level) {
2087         return indent_buffer + (512 - 2 * (level));
2088 }
2089
2090
2091 /********************
2092  * WBXML tag tokens *
2093  ********************
2094  * 
2095  * Bit Mask  : Example
2096  * -------------------
2097  * 00.. .... : <tag />
2098  *
2099  * 01.. .... : <tag>
2100  *               CONTENT
2101  *             </tag>
2102  *
2103  * 10.. .... : <tag
2104  *               atrtribute1="value1"
2105  *               atrtribute2="value2"
2106  *             />
2107  * 
2108  * 11.. .... : <tag
2109  *               atrtribute1="value1"
2110  *               atrtribute2="value2"
2111  *             >
2112  *               CONTENT
2113  *             </tag>
2114  *
2115  * NOTES
2116  *   - An XML PI is parsed as an attribute list (same syntax).
2117  *   - A code page switch only applies to the single token that follows.
2118  */
2119
2120
2121 /* This function parses the WBXML and maps known token interpretations
2122  * to the WBXML tokens. As a result, the original XML document can be
2123  * recreated. Indentation is generated in order to ease reading.
2124  *
2125  * Attribute parsing is done in parse_wbxml_attribute_list_defined().
2126  *
2127  * The wbxml_token_map entry *map contains the actual token mapping.
2128  *
2129  * NOTE: In order to parse the content, some recursion is required.
2130  *       However, for performance reasons, recursion has been avoided
2131  *       where possible (tags without content within tags with content).
2132  *       This is achieved by means of the parsing_tag_content and tag_save*
2133  *       variables.
2134  *
2135  * NOTE: See above for known token mappings.
2136  *
2137  * NOTE: As tags can be opened and closed, a tag representation lookup
2138  *       may happen once or twice for a given tag. For efficiency reasons,
2139  *       the literal tag value is stored and used throughout the code.
2140  *       With the introduction of code page support, this solution is robust
2141  *       as the lookup only occurs once, removing the need for storage of
2142  *       the used code page.
2143  */
2144 static void
2145 parse_wbxml_tag_defined (proto_tree *tree, tvbuff_t *tvb, guint32 offset,
2146                 guint32 str_tbl, guint8 *level,
2147                 guint32 *parsed_length,
2148                 const wbxml_token_map *map)
2149 {
2150         guint32 tvb_len = tvb_reported_length (tvb);
2151         guint32 off = offset;
2152         guint32 len;
2153         guint32 ent;
2154         guint32 index;
2155         const char* str;
2156         guint8 peek;
2157         guint32 tag_len; /* Length of the index (uintvar) from a LITERAL tag */
2158         guint8 tag_save_known = 0; /* Will contain peek & 0x3F (tag identity) */
2159         guint8 tag_new_known = 0; /* Will contain peek & 0x3F (tag identity) */
2160         const char *tag_save_literal; /* Will contain the LITERAL tag identity */
2161         const char *tag_new_literal; /* Will contain the LITERAL tag identity */
2162         guint8 codepage_stag = 0; /* Initial codepage in state = STAG */
2163         guint8 parsing_tag_content = FALSE; /* Are we parsing content from a
2164                                                                                    tag with content: <x>Content</x>
2165                                                                                    
2166                                                                                    The initial state is FALSE.
2167                                                                                    This state will trigger recursion. */
2168         tag_save_literal = NULL; /* Prevents compiler warning */
2169
2170 #ifdef DEBUG
2171         printf ("WBXML - parse_wbxml_tag_defined (level = %d, offset = %d)\n",
2172                         *level, offset);
2173 #endif
2174         while (off < tvb_len) {
2175                 peek = tvb_get_guint8 (tvb, off);
2176 #ifdef DEBUG
2177                 printf("WBXML - STAG: level = %3d, peek = 0x%02X, off = %d, "
2178                                 "tvb_len = %d\n",
2179                                 *level, peek, off, tvb_len);
2180 #endif
2181                 if ((peek & 0x3F) < 4) switch (peek) { /* Global tokens in state = STAG
2182                                                                                                   but not the LITERAL tokens */
2183                         case 0x00: /* SWITCH_PAGE */
2184                                 codepage_stag = tvb_get_guint8 (tvb, off+1);
2185                                 proto_tree_add_text (tree, tvb, off, 2,
2186                                                 "      | Tag   | T 0->%3d "
2187                                                 "| SWITCH_PAGE (Tag code page)     "
2188                                                 "|",
2189                                                 codepage_stag);
2190                                 off += 2;
2191                                 break;
2192                         case 0x01: /* END: only possible for Tag with Content */
2193                                 if (tag_save_known) { /* Known TAG */
2194                                         proto_tree_add_text (tree, tvb, off, 1,
2195                                                         "  %3d | Tag   |          "
2196                                                         "| END (Known Tag 0x%02X)            "
2197                                                         "| %s</%s>",
2198                                                         *level, tag_save_known, Indent (*level),
2199                                                         tag_save_literal); /* We already looked it up! */
2200                                 } else { /* Literal TAG */
2201                                         proto_tree_add_text (tree, tvb, off, 1,
2202                                                         "  %3d | Tag   |          "
2203                                                         "| END (Literal Tag)               "
2204                                                         "| %s</%s>",
2205                                                         *level, Indent (*level),
2206                                                         tag_save_literal);
2207                                 }
2208                                 (*level)--;
2209                                 off++;
2210                                 *parsed_length = off - offset;
2211                                 /* Reset code page: not needed as return from recursion */
2212                                 return;
2213                                 break;
2214                         case 0x02: /* ENTITY */
2215                                 ent = tvb_get_guintvar (tvb, off+1, &len);
2216                                 proto_tree_add_text (tree, tvb, off, 1+len,
2217                                                 "  %3d | Tag   |          "
2218                                                 "| ENTITY                          "
2219                                                 "| %s'&#%u;'",
2220                                                 *level, Indent (*level), ent);
2221                                 off += 1+len;
2222                                 break;
2223                         case 0x03: /* STR_I */
2224                                 /* Hack the string table lookup function */
2225                                 str = strtbl_lookup (tvb, off+1, 0, &len);
2226                                 proto_tree_add_text (tree, tvb, off, 1+len,
2227                                                 "  %3d | Tag   |          "
2228                                                 "| STR_I (Inline string)           "
2229                                                 "| %s\'%s\'",
2230                                                 *level, Indent(*level), str);
2231                                 off += 1+len;
2232                                 break;
2233                         case 0x40: /* EXT_I_0 */
2234                         case 0x41: /* EXT_I_1 */
2235                         case 0x42: /* EXT_I_2 */
2236                                 /* Extension tokens */
2237                                 /* Hack the string table lookup function */
2238                                 str = strtbl_lookup (tvb, off+1, 0, &len);
2239                                 if (codepage_stag) { /* Not default code page */
2240                                         proto_tree_add_text (tree, tvb, off, 1+len,
2241                                                         "  %3d | Tag   | T %3d->0 "
2242                                                         "| EXT_I_%1x    (Extension Token)    "
2243                                                         "| %s(%s: \'%s\')",
2244                                                         *level, codepage_stag, peek & 0x0f, Indent (*level),
2245                                                         map_token (map->global, codepage_stag, peek), str);
2246                                         /* Reset code page */
2247                                         codepage_stag = 0;
2248                                 } else { /* Code page 0 */
2249                                         proto_tree_add_text (tree, tvb, off, 1+len,
2250                                                         "  %3d | Tag   |          "
2251                                                         "| EXT_I_%1x    (Extension Token)    "
2252                                                         "| %s(%s: \'%s\')",
2253                                                         *level, peek & 0x0f, Indent (*level),
2254                                                         map_token (map->global, codepage_stag, peek), str);
2255                                 }
2256                                 off += 1+len;
2257                                 break;
2258                         case 0x43: /* PI */
2259                                 proto_tree_add_text (tree, tvb, off, 1,
2260                                                 "  %3d | Tag   |          "
2261                                                 "| PI (XML Processing Instruction) "
2262                                                 "| %s<?xml",
2263                                                 *level, Indent (*level));
2264                                 parse_wbxml_attribute_list_defined (tree, tvb, off, str_tbl,
2265                                                 *level, &len, map);
2266                                 off += len;
2267                                 proto_tree_add_text (tree, tvb, off-1, 1,
2268                                                 "  %3d | Tag   |          "
2269                                                 "| END (PI)                        "
2270                                                 "| %s?>",
2271                                                 *level, Indent (*level));
2272                                 break;
2273                         case 0x80: /* EXT_T_0 */
2274                         case 0x81: /* EXT_T_1 */
2275                         case 0x82: /* EXT_T_2 */
2276                                 /* Extension tokens */
2277                                 index = tvb_get_guintvar (tvb, off+1, &len);
2278                                 str = strtbl_lookup (tvb, str_tbl, index, NULL);
2279                                 if (codepage_stag) { /* Not default code page */
2280                                         proto_tree_add_text (tree, tvb, off, 1+len,
2281                                                         "  %3d | Tag   | T %3d->0 "
2282                                                         "| EXT_T_%1x    (Extension Token)    "
2283                                                         "| %s(%s: \'%s\')",
2284                                                         *level, codepage_stag, peek & 0x0f, Indent (*level),
2285                                                         map_token (map->global, codepage_stag, peek), str);
2286                                         /* Reset code page */
2287                                         codepage_stag = 0;
2288                                 } else { /* Code page 0 */
2289                                         proto_tree_add_text (tree, tvb, off, 1+len,
2290                                                         "  %3d | Tag   |          "
2291                                                         "| EXT_T_%1x    (Extension Token)    "
2292                                                         "| %s(%s: \'%s\')",
2293                                                         *level, peek & 0x0f, Indent (*level),
2294                                                         map_token (map->global, codepage_stag, peek), str);
2295                                 }
2296                                 off += 1+len;
2297                                 break;
2298                         case 0x83: /* STR_T */
2299                                 index = tvb_get_guintvar (tvb, off+1, &len);
2300                                 str = strtbl_lookup (tvb, str_tbl, index, NULL);
2301                                 proto_tree_add_text (tree, tvb, off, 1+len,
2302                                                 "  %3d | Tag   |          "
2303                                                 "| STR_T (Tableref string)         "
2304                                                 "| %s\'%s\'",
2305                                                 *level, Indent (*level), str);
2306                                 off += 1+len;
2307                                 break;
2308                         case 0xC0: /* EXT_0 */
2309                         case 0xC1: /* EXT_1 */
2310                         case 0xC2: /* EXT_2 */
2311                                 /* Extension tokens */
2312                                 if (codepage_stag) { /* Not default code page */
2313                                         proto_tree_add_text (tree, tvb, off, 1,
2314                                                         "  %3d | Tag   | T %3d->0 "
2315                                                         "| EXT_%1x      (Extension Token)    "
2316                                                         "| %s(%s)",
2317                                                         *level, codepage_stag, peek & 0x0f, Indent (*level),
2318                                                         map_token (map->global, codepage_stag, peek));
2319                                         /* Reset code page */
2320                                         codepage_stag = 0;
2321                                 } else { /* Code page 0 */
2322                                         proto_tree_add_text (tree, tvb, off, 1,
2323                                                         "  %3d | Tag   |          "
2324                                                         "| EXT_%1x      (Extension Token)    "
2325                                                         "| %s(%s)",
2326                                                         *level, peek & 0x0f, Indent (*level),
2327                                                         map_token (map->global, codepage_stag, peek));
2328                                 }
2329                                 off++;
2330                                 break;
2331                         case 0xC3: /* OPAQUE - WBXML 1.1 and newer */
2332                                 if (tvb_get_guint8 (tvb, 0)) { /* WBXML 1.x (x > 0) */
2333                                         index = tvb_get_guintvar (tvb, off+1, &len);
2334                                         proto_tree_add_text (tree, tvb, off, 1 + len + index,
2335                                                         "  %3d | Tag   |          "
2336                                                         "| OPAQUE (Opaque data)            "
2337                                                         "| %s(%d bytes of opaque data)",
2338                                                         *level, Indent (*level), index);
2339                                         off += 1+len+index;
2340                                 } else { /* WBXML 1.0 - RESERVED_2 token (invalid) */
2341                                         proto_tree_add_text (tree, tvb, off, 1,
2342                                                         "        Tag   |          "
2343                                                         "| RESERVED_2     (Invalid Token!) "
2344                                                         "| WBXML 1.0 parsing stops here.");
2345                                         /* Stop processing as it is impossible to parse now */
2346                                         off = tvb_len;
2347                                         *parsed_length = off - offset;
2348                                         return;
2349                                 }
2350                                 break;
2351
2352                                 /* No default clause, as all cases have been treated */
2353                 } else { /* LITERAL or Known TAG */
2354                         /* We must store the initial tag, and also retrieve the new tag.
2355                          * For efficiency reasons, we store the literal tag representation
2356                          * for known tags too, so we can easily close the tag without the
2357                          * need of a new lookup and avoiding storage of token codepage.
2358                          * 
2359                          * There are 4 possibilities:
2360                          *
2361                          *  1. Known tag followed by a known tag
2362                          *  2. Known tag followed by a LITERAL tag
2363                          *  3. LITERAL tag followed by Known tag
2364                          *  4. LITERAL tag followed by LITERAL tag
2365                          */
2366
2367                         /* Store the new tag */
2368                         tag_len = 0;
2369                         if ((peek & 0x3F) == 4) { /* LITERAL */
2370                                 index = tvb_get_guintvar (tvb, off+1, &tag_len);
2371                                 tag_new_literal = strtbl_lookup (tvb, str_tbl, index, NULL);
2372                                 tag_new_known = 0; /* invalidate known tag_new */
2373                         } else { /* Known tag */
2374                                 tag_new_known = peek & 0x3F;
2375                                 tag_new_literal = map_token (map->tags, codepage_stag,
2376                                                                                 tag_new_known);
2377                                 /* Stored looked up tag name string */
2378                         }
2379
2380                         /* Parsing of TAG starts HERE */
2381                         if (peek & 0x40) { /* Content present */
2382                                 /* Content follows
2383                                  * [!] An explicit END token is expected in these cases!
2384                                  * ==> Recursion possible if we encounter a tag with content;
2385                                  *     recursion will return at the explicit END token.
2386                                  */
2387                                 if (parsing_tag_content) { /* Recurse */
2388 #ifdef DEBUG
2389                                         printf ("WBXML: Tag in Tag - RECURSE! (off = %d)\n",off);
2390 #endif
2391                                         /* Do not process the attribute list:
2392                                          * recursion will take care of it */
2393                                         (*level)++;
2394                                         parse_wbxml_tag_defined (tree, tvb, off, str_tbl, level,
2395                                                         &len, map);
2396                                         off += len;
2397                                 } else { /* Now we will have content to parse */
2398                                         /* Save the start tag so we can properly close it later. */
2399                                         if ((peek & 0x3F) == 4) { /* Literal tag */
2400                                                 tag_save_literal = tag_new_literal;
2401                                                 tag_save_known = 0;
2402                                         } else { /* Known tag */
2403                                                 tag_save_known = tag_new_known;
2404                                                 tag_save_literal = tag_new_literal;
2405                                                 /* The last statement avoids needless lookups */
2406                                         }
2407                                         /* Process the attribute list if present */
2408                                         if (peek & 0x80) { /* Content and Attribute list present */
2409                                                 if (tag_new_known) { /* Known tag */
2410                                                         if (codepage_stag) { /* Not default code page */
2411                                                                 proto_tree_add_text (tree, tvb, off, 1,
2412                                                                                 "  %3d | Tag   | T %3d->0 "
2413                                                                                 "|   Known Tag 0x%02X           (AC) "
2414                                                                                 "| %s<%s",
2415                                                                                 *level, codepage_stag, tag_new_known,
2416                                                                                 Indent (*level), tag_new_literal);
2417                                                                 /* Tag string already looked up earlier! */
2418                                                                 /* Reset code page */
2419                                                                 codepage_stag = 0;
2420                                                         } else { /* Code page 0 */
2421                                                                 proto_tree_add_text (tree, tvb, off, 1,
2422                                                                                 "  %3d | Tag   |          "
2423                                                                                 "|   Known Tag 0x%02X           (AC) "
2424                                                                                 "| %s<%s",
2425                                                                                 *level, tag_new_known,
2426                                                                                 Indent (*level), tag_new_literal);
2427                                                                 /* Tag string already looked up earlier! */
2428                                                         }
2429                                                         off++;
2430                                                 } else { /* LITERAL tag */
2431                                                         proto_tree_add_text (tree, tvb, off, 1,
2432                                                                         "  %3d | Tag   |          "
2433                                                                         "| LITERAL_AC (Literal tag)   (AC) "
2434                                                                         "| %s<%s",
2435                                                                         *level, Indent (*level), tag_new_literal);
2436                                                         off += 1 + tag_len;
2437                                                 }
2438                                                 parse_wbxml_attribute_list_defined (tree, tvb,
2439                                                                 off, str_tbl, *level, &len, map);
2440                                                 off += len;
2441                                                 proto_tree_add_text (tree, tvb, off-1, 1,
2442                                                                 "  %3d | Tag   |          "
2443                                                                 "| END (attribute list)            "
2444                                                                 "| %s>",
2445                                                                 *level, Indent (*level));
2446                                         } else { /* Content, no Attribute list */
2447                                                 if (tag_new_known) { /* Known tag */
2448                                                         if (codepage_stag) { /* Not default code page */
2449                                                                 proto_tree_add_text (tree, tvb, off, 1,
2450                                                                                 "  %3d | Tag   | T %3d->0 "
2451                                                                                 "|   Known Tag 0x%02X           (.C) "
2452                                                                                 "| %s<%s>",
2453                                                                                 *level, codepage_stag, tag_new_known,
2454                                                                                 Indent (*level),
2455                                                                                 tag_new_literal);
2456                                                                 /* Tag string already looked up earlier! */
2457                                                                 /* Reset code page */
2458                                                                 codepage_stag = 0;
2459                                                         } else { /* Code page 0 */
2460                                                                 proto_tree_add_text (tree, tvb, off, 1,
2461                                                                                 "  %3d | Tag   |          "
2462                                                                                 "|   Known Tag 0x%02X           (.C) "
2463                                                                                 "| %s<%s>",
2464                                                                                 *level, tag_new_known,
2465                                                                                 Indent (*level),
2466                                                                                 tag_new_literal);
2467                                                                 /* Tag string already looked up earlier! */
2468                                                         }
2469                                                         off++;
2470                                                 } else { /* LITERAL tag */
2471                                                         proto_tree_add_text (tree, tvb, off, 1,
2472                                                                         "  %3d | Tag   |          "
2473                                                                         "| LITERAL_C  (Literal Tag)   (.C) "
2474                                                                         "| %s<%s>",
2475                                                                         *level, Indent (*level), tag_new_literal);
2476                                                         off += 1 + tag_len;
2477                                                 }
2478                                         }
2479                                         /* The data that follows in the parsing process
2480                                          * represents content for the opening tag
2481                                          * we've just processed in the lines above.
2482                                          * Next time we encounter a tag with content: recurse
2483                                          */
2484                                         parsing_tag_content = TRUE;
2485 #ifdef DEBUG
2486                                         printf ("WBXML: Tag in Tag - No recursion this time! "
2487                                                         "(off = %d)\n", off);
2488 #endif
2489                                 }
2490                         } else { /* No Content */
2491 #ifdef DEBUG
2492                                 printf ("WBXML: <Tag/> in Tag - No recursion! "
2493                                                 "(off = %d)\n", off);
2494 #endif
2495                                 (*level)++;
2496                                 if (peek & 0x80) { /* No Content, Attribute list present */
2497                                         if (tag_new_known) { /* Known tag */
2498                                                 if (codepage_stag) { /* Not default code page */
2499                                                         proto_tree_add_text (tree, tvb, off, 1,
2500                                                                         "  %3d | Tag   | T %3d->0 "
2501                                                                         "|   Known Tag 0x%02X           (A.) "
2502                                                                         "| %s<%s",
2503                                                                         *level, codepage_stag, tag_new_known,
2504                                                                         Indent (*level), tag_new_literal);
2505                                                         /* Tag string already looked up earlier! */
2506                                                         /* Reset code page */
2507                                                         codepage_stag = 0;
2508                                                 } else { /* Code page 0 */
2509                                                         proto_tree_add_text (tree, tvb, off, 1,
2510                                                                         "  %3d | Tag   |          "
2511                                                                         "|   Known Tag 0x%02X           (A.) "
2512                                                                         "| %s<%s",
2513                                                                         *level, tag_new_known,
2514                                                                         Indent (*level), tag_new_literal);
2515                                                         /* Tag string already looked up earlier! */
2516                                                 }
2517                                                 off++;
2518                                                 parse_wbxml_attribute_list_defined (tree, tvb,
2519                                                                 off, str_tbl, *level, &len, map);
2520                                                 off += len;
2521                                                 proto_tree_add_text (tree, tvb, off-1, 1,
2522                                                                 "  %3d | Tag   |          "
2523                                                                 "| END (Known Tag)                 "
2524                                                                 "| %s/>",
2525                                                                 *level, Indent (*level));
2526                                         } else { /* LITERAL tag */
2527                                                 proto_tree_add_text (tree, tvb, off, 1,
2528                                                                 "  %3d | Tag   |          "
2529                                                                 "| LITERAL_A  (Literal Tag)   (A.) "
2530                                                                 "| %s<%s",
2531                                                                 *level, Indent (*level), tag_new_literal);
2532                                                 off += 1 + tag_len;
2533                                                 parse_wbxml_attribute_list_defined (tree, tvb,
2534                                                                 off, str_tbl, *level, &len, map);
2535                                                 off += len;
2536                                                 proto_tree_add_text (tree, tvb, off-1, 1,
2537                                                                 "  %3d | Tag   |          "
2538                                                                 "| END (Literal Tag)               "
2539                                                                 "| %s/>",
2540                                                                 *level, Indent (*level));
2541                                         }
2542                                 } else { /* No Content, No Attribute list */
2543                                         if (tag_new_known) { /* Known tag */
2544                                                 if (codepage_stag) { /* Not default code page */
2545                                                         proto_tree_add_text (tree, tvb, off, 1,
2546                                                                         "  %3d | Tag   | T %3d->0 "
2547                                                                         "|   Known Tag 0x%02x           (..) "
2548                                                                         "| %s<%s />",
2549                                                                         *level, codepage_stag, tag_new_known,
2550                                                                         Indent (*level), tag_new_literal);
2551                                                         /* Tag string already looked up earlier! */
2552                                                         /* Reset code page */
2553                                                         codepage_stag = 0;
2554                                                 } else { /* Code page 0 */
2555                                                         proto_tree_add_text (tree, tvb, off, 1,
2556                                                                         "  %3d | Tag   |          "
2557                                                                         "|   Known Tag 0x%02x           (..) "
2558                                                                         "| %s<%s />",
2559                                                                         *level, tag_new_known,
2560                                                                         Indent (*level), tag_new_literal);
2561                                                         /* Tag string already looked up earlier! */
2562                                                 }
2563                                                 off++;
2564                                         } else { /* LITERAL tag */
2565                                                 proto_tree_add_text (tree, tvb, off, 1,
2566                                                                 "  %3d | Tag   |          "
2567                                                                 "| LITERAL    (Literal Tag)   (..) "
2568                                                                 "| %s<%s />",
2569                                                                 *level, Indent (*level), tag_new_literal);
2570                                                 off += 1 + tag_len;
2571                                         }
2572                                 }
2573                                 (*level)--;
2574                                 /* TODO: Do I have to reset code page here? */
2575                         }
2576                 } /* if (tag & 0x3F) >= 5 */
2577         } /* while */
2578 }
2579
2580
2581 /* This function performs the WBXML decoding as in parse_wbxml_tag_defined()
2582  * but this time no WBXML mapping is performed.
2583  *
2584  * Attribute parsing is done in parse_wbxml_attribute_list().
2585  */
2586 static void
2587 parse_wbxml_tag (proto_tree *tree, tvbuff_t *tvb, guint32 offset,
2588                 guint32 str_tbl, guint8 *level,
2589                 guint32 *parsed_length)
2590 {
2591         guint32 tvb_len = tvb_reported_length (tvb);
2592         guint32 off = offset;
2593         guint32 len;
2594         guint32 ent;
2595         guint32 index;
2596         const char* str;
2597         guint8 peek;
2598         guint32 tag_len; /* Length of the index (uintvar) from a LITERAL tag */
2599         guint8 tag_save_known = 0; /* Will contain peek & 0x3F (tag identity) */
2600         guint8 tag_new_known = 0; /* Will contain peek & 0x3F (tag identity) */
2601         const char *tag_save_literal; /* Will contain the LITERAL tag identity */
2602         const char *tag_new_literal; /* Will contain the LITERAL tag identity */
2603         char tag_save_buf[10]; /* Will contain "tag_0x%02X" */
2604         char tag_new_buf[10]; /* Will contain "tag_0x%02X" */
2605         guint8 codepage_stag = 0; /* Initial codepage in state = STAG */
2606         guint8 parsing_tag_content = FALSE; /* Are we parsing content from a
2607                                                                                    tag with content: <x>Content</x>
2608                                                                                    
2609                                                                                    The initial state is FALSE.
2610                                                                                    This state will trigger recursion. */
2611         tag_save_literal = NULL; /* Prevents compiler warning */
2612
2613 #ifdef DEBUG
2614         printf ("WBXML - parse_wbxml_tag (level = %d, offset = %d)\n",
2615                         *level, offset);
2616 #endif
2617         while (off < tvb_len) {
2618                 peek = tvb_get_guint8 (tvb, off);
2619 #ifdef DEBUG
2620                 printf("WBXML - STAG: level = %3d, peek = 0x%02X, off = %d, "
2621                                 "tvb_len = %d\n",
2622                                 *level, peek, off, tvb_len);
2623 #endif
2624                 if ((peek & 0x3F) < 4) switch (peek) { /* Global tokens in state = STAG
2625                                                                                                   but not the LITERAL tokens */
2626                         case 0x00: /* SWITCH_PAGE */
2627                                 codepage_stag = tvb_get_guint8 (tvb, off+1);
2628                                 proto_tree_add_text (tree, tvb, off, 2,
2629                                                 "      | Tag   | T 0->%3d "
2630                                                 "| SWITCH_PAGE (Tag code page)     "
2631                                                 "|",
2632                                                 codepage_stag);
2633                                 off += 2;
2634                                 break;
2635                         case 0x01: /* END: only possible for Tag with Content */
2636                                 if (tag_save_known) { /* Known TAG */
2637                                         proto_tree_add_text (tree, tvb, off, 1,
2638                                                         "  %3d | Tag   |          "
2639                                                         "| END (Known Tag 0x%02X)            "
2640                                                         "| %s</%s>",
2641                                                         *level, tag_save_known, Indent (*level),
2642                                                         tag_save_literal); /* We already looked it up! */
2643                                 } else { /* Literal TAG */
2644                                         proto_tree_add_text (tree, tvb, off, 1,
2645                                                         "  %3d | Tag   |          "
2646                                                         "| END (Literal Tag)               "
2647                                                         "| %s</%s>",
2648                                                         *level, Indent (*level),
2649                                                         tag_save_literal);
2650                                 }
2651                                 (*level)--;
2652                                 off++;
2653                                 *parsed_length = off - offset;
2654                                 /* Reset code page: not needed as return from recursion */
2655                                 return;
2656                                 break;
2657                         case 0x02: /* ENTITY */
2658                                 ent = tvb_get_guintvar (tvb, off+1, &len);
2659                                 proto_tree_add_text (tree, tvb, off, 1+len,
2660                                                 "  %3d | Tag   |          "
2661                                                 "| ENTITY                          "
2662                                                 "| %s'&#%u;'",
2663                                                 *level, Indent (*level), ent);
2664                                 off += 1+len;
2665                                 break;
2666                         case 0x03: /* STR_I */
2667                                 /* Hack the string table lookup function */
2668                                 str = strtbl_lookup (tvb, off+1, 0, &len);
2669                                 proto_tree_add_text (tree, tvb, off, 1+len,
2670                                                 "  %3d | Tag   |          "
2671                                                 "| STR_I (Inline string)           "
2672                                                 "| %s\'%s\'",
2673                                                 *level, Indent(*level), str);
2674                                 off += 1+len;
2675                                 break;
2676                         case 0x40: /* EXT_I_0 */
2677                         case 0x41: /* EXT_I_1 */
2678                         case 0x42: /* EXT_I_2 */
2679                                 /* Extension tokens */
2680                                 /* Hack the string table lookup function */
2681                                 str = strtbl_lookup (tvb, off+1, 0, &len);
2682                                 if (codepage_stag) { /* Not default code page */
2683                                         proto_tree_add_text (tree, tvb, off, 1+len,
2684                                                         "  %3d | Tag   | T %3d->0 "
2685                                                         "| EXT_I_%1x    (Extension Token)    "
2686                                                         "| %s(Inline string extension: \'%s\')",
2687                                                         *level, codepage_stag, peek & 0x0f, Indent (*level),
2688                                                         str);
2689                                         /* Reset code page */
2690                                         codepage_stag = 0;
2691                                 } else { /* Code page 0 */
2692                                         proto_tree_add_text (tree, tvb, off, 1+len,
2693                                                         "  %3d | Tag   |          "
2694                                                         "| EXT_I_%1x    (Extension Token)    "
2695                                                         "| %s(Inline string extension: \'%s\')",
2696                                                         *level, peek & 0x0f, Indent (*level),
2697                                                         str);
2698                                 }
2699                                 off += 1+len;
2700                                 break;
2701                         case 0x43: /* PI */
2702                                 proto_tree_add_text (tree, tvb, off, 1,
2703                                                 "  %3d | Tag   |          "
2704                                                 "| PI (XML Processing Instruction) "
2705                                                 "| %s<?xml",
2706                                                 *level, Indent (*level));
2707                                 parse_wbxml_attribute_list (tree, tvb, off, str_tbl,
2708                                                 *level, &len);
2709                                 off += len;
2710                                 proto_tree_add_text (tree, tvb, off-1, 1,
2711                                                 "  %3d | Tag   |          "
2712                                                 "| END (PI)                        "
2713                                                 "| %s?>",
2714                                                 *level, Indent (*level));
2715                                 break;
2716                         case 0x80: /* EXT_T_0 */
2717                         case 0x81: /* EXT_T_1 */
2718                         case 0x82: /* EXT_T_2 */
2719                                 /* Extension tokens */
2720                                 index = tvb_get_guintvar (tvb, off+1, &len);
2721                                 str = strtbl_lookup (tvb, str_tbl, index, NULL);
2722                                 if (codepage_stag) { /* Not default code page */
2723                                         proto_tree_add_text (tree, tvb, off, 1+len,
2724                                                         "  %3d | Tag   | T %3d->0 "
2725                                                         "| EXT_T_%1x    (Extension Token)    "
2726                                                         "| %s(Tableref string extension: \'%s\')",
2727                                                         *level, codepage_stag, peek & 0x0f, Indent (*level),
2728                                                         str);
2729                                         /* Reset code page */
2730                                         codepage_stag = 0;
2731                                 } else { /* Code page 0 */
2732                                         proto_tree_add_text (tree, tvb, off, 1+len,
2733                                                         "  %3d | Tag   |          "
2734                                                         "| EXT_T_%1x    (Extension Token)    "
2735                                                         "| %s(Tableref string extension: \'%s\')",
2736                                                         *level, peek & 0x0f, Indent (*level),
2737                                                         str);
2738                                 }
2739                                 off += 1+len;
2740                                 break;
2741                         case 0x83: /* STR_T */
2742                                 index = tvb_get_guintvar (tvb, off+1, &len);
2743                                 str = strtbl_lookup (tvb, str_tbl, index, NULL);
2744                                 proto_tree_add_text (tree, tvb, off, 1+len,
2745                                                 "  %3d | Tag   |          "
2746                                                 "| STR_T (Tableref string)         "
2747                                                 "| %s\'%s\'",
2748                                                 *level, Indent (*level), str);
2749                                 off += 1+len;
2750                                 break;
2751                         case 0xC0: /* EXT_0 */
2752                         case 0xC1: /* EXT_1 */
2753                         case 0xC2: /* EXT_2 */
2754                                 /* Extension tokens */
2755                                 if (codepage_stag) { /* Not default code page */
2756                                         proto_tree_add_text (tree, tvb, off, 1,
2757                                                         "  %3d | Tag   | T %3d->0 "
2758                                                         "| EXT_%1x      (Extension Token)    "
2759                                                         "| %s(Single-byte extension)",
2760                                                         *level, codepage_stag, peek & 0x0f,
2761                                                         Indent (*level));
2762                                         /* Reset code page */
2763                                         codepage_stag = 0;
2764                                 } else { /* Code page 0 */
2765                                         proto_tree_add_text (tree, tvb, off, 1,
2766                                                         "  %3d | Tag   |          "
2767                                                         "| EXT_%1x      (Extension Token)    "
2768                                                         "| %s(Single-byte extension)",
2769                                                         *level, peek & 0x0f, Indent (*level));
2770                                 }
2771                                 off++;
2772                                 break;
2773                         case 0xC3: /* OPAQUE - WBXML 1.1 and newer */
2774                                 if (tvb_get_guint8 (tvb, 0)) { /* WBXML 1.x (x > 0) */
2775                                         index = tvb_get_guintvar (tvb, off+1, &len);
2776                                         proto_tree_add_text (tree, tvb, off, 1 + len + index,
2777                                                         "  %3d | Tag   |          "
2778                                                         "| OPAQUE (Opaque data)            "
2779                                                         "| %s(%d bytes of opaque data)",
2780                                                         *level, Indent (*level), index);
2781                                         off += 1+len+index;
2782                                 } else { /* WBXML 1.0 - RESERVED_2 token (invalid) */
2783                                         proto_tree_add_text (tree, tvb, off, 1,
2784                                                         "        Tag   |          "
2785                                                         "| RESERVED_2     (Invalid Token!) "
2786                                                         "| WBXML 1.0 parsing stops here.");
2787                                         /* Stop processing as it is impossible to parse now */
2788                                         off = tvb_len;
2789                                         *parsed_length = off - offset;
2790                                         return;
2791                                 }
2792                                 break;
2793
2794                                 /* No default clause, as all cases have been treated */
2795                 } else { /* LITERAL or Known TAG */
2796                         /* We must store the initial tag, and also retrieve the new tag.
2797                          * For efficiency reasons, we store the literal tag representation
2798                          * for known tags too, so we can easily close the tag without the
2799                          * need of a new lookup and avoiding storage of token codepage.
2800                          * 
2801                          * There are 4 possibilities:
2802                          *
2803                          *  1. Known tag followed by a known tag
2804                          *  2. Known tag followed by a LITERAL tag
2805                          *  3. LITERAL tag followed by Known tag
2806                          *  4. LITERAL tag followed by LITERAL tag
2807                          */
2808
2809                         /* Store the new tag */
2810                         tag_len = 0;
2811                         if ((peek & 0x3F) == 4) { /* LITERAL */
2812                                 index = tvb_get_guintvar (tvb, off+1, &tag_len);
2813                                 tag_new_literal = strtbl_lookup (tvb, str_tbl, index, NULL);
2814                                 tag_new_known = 0; /* invalidate known tag_new */
2815                         } else { /* Known tag */
2816                                 tag_new_known = peek & 0x3F;
2817                                 sprintf (tag_new_buf, "Tag_0x%02X",
2818                                                 tag_new_known);
2819                                 tag_new_literal = tag_new_buf;
2820                                 /* Stored looked up tag name string */
2821                         }
2822
2823                         /* Parsing of TAG starts HERE */
2824                         if (peek & 0x40) { /* Content present */
2825                                 /* Content follows
2826                                  * [!] An explicit END token is expected in these cases!
2827                                  * ==> Recursion possible if we encounter a tag with content;
2828                                  *     recursion will return at the explicit END token.
2829                                  */
2830                                 if (parsing_tag_content) { /* Recurse */
2831 #ifdef DEBUG
2832                                         printf ("WBXML: Tag in Tag - RECURSE! (off = %d)\n",off);
2833 #endif
2834                                         /* Do not process the attribute list:
2835                                          * recursion will take care of it */
2836                                         (*level)++;
2837                                         parse_wbxml_tag (tree, tvb, off, str_tbl, level,
2838                                                         &len);
2839                                         off += len;
2840                                 } else { /* Now we will have content to parse */
2841                                         /* Save the start tag so we can properly close it later. */
2842                                         if ((peek & 0x3F) == 4) { /* Literal tag */
2843                                                 tag_save_literal = tag_new_literal;
2844                                                 tag_save_known = 0;
2845                                         } else { /* Known tag */
2846                                                 tag_save_known = tag_new_known;
2847                                                 sprintf (tag_save_buf, "Tag_0x%02X",
2848                                                                 tag_new_known);
2849                                                 tag_save_literal = tag_save_buf;
2850                                                 /* The last statement avoids needless lookups */
2851                                         }
2852                                         /* Process the attribute list if present */
2853                                         if (peek & 0x80) { /* Content and Attribute list present */
2854                                                 if (tag_new_known) { /* Known tag */
2855                                                         if (codepage_stag) { /* Not default code page */
2856                                                                 proto_tree_add_text (tree, tvb, off, 1,
2857                                                                                 "  %3d | Tag   | T %3d->0 "
2858                                                                                 "|   Known Tag 0x%02X           (AC) "
2859                                                                                 "| %s<%s",
2860                                                                                 *level, codepage_stag, tag_new_known,
2861                                                                                 Indent (*level), tag_new_literal);
2862                                                                 /* Tag string already looked up earlier! */
2863                                                                 /* Reset code page */
2864                                                                 codepage_stag = 0;
2865                                                         } else { /* Code page 0 */
2866                                                                 proto_tree_add_text (tree, tvb, off, 1,
2867                                                                                 "  %3d | Tag   |          "
2868                                                                                 "|   Known Tag 0x%02X           (AC) "
2869                                                                                 "| %s<%s",
2870                                                                                 *level, tag_new_known,
2871                                                                                 Indent (*level), tag_new_literal);
2872                                                                 /* Tag string already looked up earlier! */
2873                                                         }
2874                                                         off++;
2875                                                 } else { /* LITERAL tag */
2876                                                         proto_tree_add_text (tree, tvb, off, 1,
2877                                                                         "  %3d | Tag   |          "
2878                                                                         "| LITERAL_AC (Literal tag)   (AC) "
2879                                                                         "| %s<%s",
2880                                                                         *level, Indent (*level), tag_new_literal);
2881                                                         off += 1 + tag_len;
2882                                                 }
2883                                                 parse_wbxml_attribute_list (tree, tvb,
2884                                                                 off, str_tbl, *level, &len);
2885                                                 off += len;
2886                                                 proto_tree_add_text (tree, tvb, off-1, 1,
2887                                                                 "  %3d | Tag   |          "
2888                                                                 "| END (attribute list)            "
2889                                                                 "| %s>",
2890                                                                 *level, Indent (*level));
2891                                         } else { /* Content, no Attribute list */
2892                                                 if (tag_new_known) { /* Known tag */
2893                                                         if (codepage_stag) { /* Not default code page */
2894                                                                 proto_tree_add_text (tree, tvb, off, 1,
2895                                                                                 "  %3d | Tag   | T %3d->0 "
2896                                                                                 "|   Known Tag 0x%02X           (.C) "
2897                                                                                 "| %s<%s>",
2898                                                                                 *level, codepage_stag, tag_new_known,
2899                                                                                 Indent (*level),
2900                                                                                 tag_new_literal);
2901                                                                 /* Tag string already looked up earlier! */
2902                                                                 /* Reset code page */
2903                                                                 codepage_stag = 0;
2904                                                         } else { /* Code page 0 */
2905                                                                 proto_tree_add_text (tree, tvb, off, 1,
2906                                                                                 "  %3d | Tag   |          "
2907                                                                                 "|   Known Tag 0x%02X           (.C) "
2908                                                                                 "| %s<%s>",
2909                                                                                 *level, tag_new_known,
2910                                                                                 Indent (*level),
2911                                                                                 tag_new_literal);
2912                                                                 /* Tag string already looked up earlier! */
2913                                                         }
2914                                                         off++;
2915                                                 } else { /* LITERAL tag */
2916                                                         proto_tree_add_text (tree, tvb, off, 1,
2917                                                                         "  %3d | Tag   |          "
2918                                                                         "| LITERAL_C  (Literal Tag)   (.C) "
2919                                                                         "| %s<%s>",
2920                                                                         *level, Indent (*level), tag_new_literal);
2921                                                         off += 1 + tag_len;
2922                                                 }
2923                                         }
2924                                         /* The data that follows in the parsing process
2925                                          * represents content for the opening tag
2926                                          * we've just processed in the lines above.
2927                                          * Next time we encounter a tag with content: recurse
2928                                          */
2929                                         parsing_tag_content = TRUE;
2930 #ifdef DEBUG
2931                                         printf ("WBXML: Tag in Tag - No recursion this time! "
2932                                                         "(off = %d)\n", off);
2933 #endif
2934                                 }
2935                         } else { /* No Content */
2936 #ifdef DEBUG
2937                                 printf ("WBXML: <Tag/> in Tag - No recursion! "
2938                                                 "(off = %d)\n", off);
2939 #endif
2940                                 (*level)++;
2941                                 if (peek & 0x80) { /* No Content, Attribute list present */
2942                                         if (tag_new_known) { /* Known tag */
2943                                                 if (codepage_stag) { /* Not default code page */
2944                                                         proto_tree_add_text (tree, tvb, off, 1,
2945                                                                         "  %3d | Tag   | T %3d->0 "
2946                                                                         "|   Known Tag 0x%02X           (A.) "
2947                                                                         "| %s<%s",
2948                                                                         *level, codepage_stag, tag_new_known,
2949                                                                         Indent (*level), tag_new_literal);
2950                                                         /* Tag string already looked up earlier! */
2951                                                         /* Reset code page */
2952                                                         codepage_stag = 0;
2953                                                 } else { /* Code page 0 */
2954                                                         proto_tree_add_text (tree, tvb, off, 1,
2955                                                                         "  %3d | Tag   |          "
2956                                                                         "|   Known Tag 0x%02X           (A.) "
2957                                                                         "| %s<%s",
2958                                                                         *level, tag_new_known,
2959                                                                         Indent (*level), tag_new_literal);
2960                                                         /* Tag string already looked up earlier! */
2961                                                 }
2962                                                 off++;
2963                                                 parse_wbxml_attribute_list (tree, tvb,
2964                                                                 off, str_tbl, *level, &len);
2965                                                 off += len;
2966                                                 proto_tree_add_text (tree, tvb, off-1, 1,
2967                                                                 "  %3d | Tag   |          "
2968                                                                 "| END (Known Tag)                 "
2969                                                                 "| %s/>",
2970                                                                 *level, Indent (*level));
2971                                         } else { /* LITERAL tag */
2972                                                 proto_tree_add_text (tree, tvb, off, 1,
2973                                                                 "  %3d | Tag   |          "
2974                                                                 "| LITERAL_A  (Literal Tag)   (A.) "
2975                                                                 "| %s<%s",
2976                                                                 *level, Indent (*level), tag_new_literal);
2977                                                 off += 1 + tag_len;
2978                                                 parse_wbxml_attribute_list (tree, tvb,
2979                                                                 off, str_tbl, *level, &len);
2980                                                 off += len;
2981                                                 proto_tree_add_text (tree, tvb, off-1, 1,
2982                                                                 "  %3d | Tag   |          "
2983                                                                 "| END (Literal Tag)               "
2984                                                                 "| %s/>",
2985                                                                 *level, Indent (*level));
2986                                         }
2987                                 } else { /* No Content, No Attribute list */
2988                                         if (tag_new_known) { /* Known tag */
2989                                                 if (codepage_stag) { /* Not default code page */
2990                                                         proto_tree_add_text (tree, tvb, off, 1,
2991                                                                         "  %3d | Tag   | T %3d->0 "
2992                                                                         "|   Known Tag 0x%02x           (..) "
2993                                                                         "| %s<%s />",
2994                                                                         *level, codepage_stag, tag_new_known,
2995                                                                         Indent (*level), tag_new_literal);
2996                                                         /* Tag string already looked up earlier! */
2997                                                         /* Reset code page */
2998                                                         codepage_stag = 0;
2999                                                 } else { /* Code page 0 */
3000                                                         proto_tree_add_text (tree, tvb, off, 1,
3001                                                                         "  %3d | Tag   |          "
3002                                                                         "|   Known Tag 0x%02x           (..) "
3003                                                                         "| %s<%s />",
3004                                                                         *level, tag_new_known,
3005                                                                         Indent (*level), tag_new_literal);
3006                                                         /* Tag string already looked up earlier! */
3007                                                 }
3008                                                 off++;
3009                                         } else { /* LITERAL tag */
3010                                                 proto_tree_add_text (tree, tvb, off, 1,
3011                                                                 "  %3d | Tag   |          "
3012                                                                 "| LITERAL    (Literal Tag)   (..) "
3013                                                                 "| %s<%s />",
3014                                                                 *level, Indent (*level), tag_new_literal);
3015                                                 off += 1 + tag_len;
3016                                         }
3017                                 }
3018                                 (*level)--;
3019                                 /* TODO: Do I have to reset code page here? */
3020                         }
3021                 } /* if (tag & 0x3F) >= 5 */
3022         } /* while */
3023 }
3024
3025
3026 /**************************
3027  * WBXML Attribute tokens *
3028  **************************
3029  * Bit Mask  : Example
3030  * -------------------
3031  * 0... .... : attr=             (attribute name)
3032  *             href='http://'    (attribute name with start of attribute value)
3033  * 1... .... : 'www.'            (attribute value, or part of it)
3034  * 
3035  */
3036
3037
3038 /* This function parses the WBXML and maps known token interpretations
3039  * to the WBXML tokens. As a result, the original XML document can be
3040  * recreated. Indentation is generated in order to ease reading.
3041  *
3042  * This function performs attribute list parsing.
3043  * 
3044  * The wbxml_token_map entry *map contains the actual token mapping.
3045  *
3046  * NOTE: See above for known token mappings.
3047  */
3048 static void
3049 parse_wbxml_attribute_list_defined (proto_tree *tree, tvbuff_t *tvb,
3050                 guint32 offset, guint32 str_tbl, guint8 level,
3051                 guint32 *parsed_length,
3052                 const wbxml_token_map *map)
3053 {
3054         guint32 tvb_len = tvb_reported_length (tvb);
3055         guint32 off = offset;
3056         guint32 len;
3057         guint32 ent;
3058         guint32 index;
3059         const char* str;
3060         guint8 peek;
3061         guint8 codepage_attr = 0; /* Initial codepage in state = ATTR */
3062
3063 #ifdef DEBUG
3064         printf ("WBXML - parse_wbxml_attr_defined (level = %d, offset = %d)\n",
3065                         level, offset);
3066 #endif
3067         /* Parse attributes */
3068         while (off < tvb_len) {
3069                 peek = tvb_get_guint8 (tvb, off);
3070 #ifdef DEBUG
3071                 printf("WBXML - ATTR: level = %3d, peek = 0x%02X, off = %d, "
3072                                 "tvb_len = %d\n",
3073                                 level, peek, off, tvb_len);
3074 #endif
3075                 if ((peek & 0x3F) < 5) switch (peek) { /* Global tokens
3076                                                                                                   in state = ATTR */
3077                         case 0x00: /* SWITCH_PAGE */
3078                                 codepage_attr = tvb_get_guint8 (tvb, off+1);
3079                                 proto_tree_add_text (tree, tvb, off, 2,
3080                                                 "      |  Attr | A 0->%3d "
3081                                                 "| SWITCH_PAGE (Attr code page)    |",
3082                                                 codepage_attr);
3083                                 off += 2;
3084                                 break;
3085                         case 0x01: /* END */
3086                                 /* BEWARE
3087                                  *   The Attribute END token means either ">" or "/>"
3088                                  *   and as a consequence both must be treated separately.
3089                                  *   This is done in the TAG state parser.
3090                                  */
3091                                 off++;
3092                                 *parsed_length = off - offset;
3093                                 return;
3094                         case 0x02: /* ENTITY */
3095                                 ent = tvb_get_guintvar (tvb, off+1, &len);
3096                                 proto_tree_add_text (tree, tvb, off, 1+len,
3097                                                 "  %3d |  Attr |          "
3098                                                 "| ENTITY                          "
3099                                                 "|     %s'&#%u;'",
3100                                                 level, Indent (level), ent);
3101                                 off += 1+len;
3102                                 break;
3103                         case 0x03: /* STR_I */
3104                                 /* Hack the string table lookup function */
3105                                 str = strtbl_lookup (tvb, off+1, 0, &len);
3106                                 proto_tree_add_text (tree, tvb, off, 1+len,
3107                                                 "  %3d |  Attr |          "
3108                                                 "| STR_I (Inline string)           "
3109                                                 "|     %s\'%s\'",
3110                                                 level, Indent (level), str);
3111                                 off += 1+len;
3112                                 break;
3113                         case 0x04: /* LITERAL */
3114                                 index = tvb_get_guintvar (tvb, off+1, &len);
3115                                 str = strtbl_lookup (tvb, str_tbl, index, NULL);
3116                                 proto_tree_add_text (tree, tvb, off, 1+len,
3117                                                 "  %3d |  Attr |          "
3118                                                 "| LITERAL (Literal Attribute)     "
3119                                                 "|   %s<%s />",
3120                                                 level, Indent (level), str);
3121                                 off += 1+len;
3122                                 break;
3123                         case 0x40: /* EXT_I_0 */
3124                         case 0x41: /* EXT_I_1 */
3125                         case 0x42: /* EXT_I_2 */
3126                                 /* Extension tokens */
3127                                 /* Hack the string table lookup function */
3128                                 str = strtbl_lookup (tvb, off+1, 0, &len);
3129                                 if (codepage_attr) { /* Not default code page */
3130                                         proto_tree_add_text (tree, tvb, off, 1+len,
3131                                                         "  %3d |  Attr | A %3d->0 "
3132                                                         "| EXT_I_%1x    (Extension Token)    "
3133                                                         "|     %s(%s: \'%s\')",
3134                                                         level, codepage_attr, peek & 0x0f, Indent (level),
3135                                                         map_token (map->global, codepage_attr, peek), str);
3136                                         /* Reset code page */
3137                                         codepage_attr = 0;
3138                                 } else { /* Code page 0 */
3139                                         proto_tree_add_text (tree, tvb, off, 1+len,
3140                                                         "  %3d |  Attr |          "
3141                                                         "| EXT_I_%1x    (Extension Token)    "
3142                                                         "|     %s(%s: \'%s\')",
3143                                                         level, peek & 0x0f, Indent (level),
3144                                                         map_token (map->global, codepage_attr, peek), str);
3145                                 }
3146                                 off += 1+len;
3147                                 break;
3148                         /* 0x43 impossible in ATTR state */
3149                         /* 0x44 impossible in ATTR state */
3150                         case 0x80: /* EXT_T_0 */
3151                         case 0x81: /* EXT_T_1 */
3152                         case 0x82: /* EXT_T_2 */
3153                                 /* Extension tokens */
3154                                 index = tvb_get_guintvar (tvb, off+1, &len);
3155                                 str = strtbl_lookup (tvb, str_tbl, index, NULL);
3156                                 if (codepage_attr) { /* Not default code page */
3157                                         proto_tree_add_text (tree, tvb, off, 1+len,
3158                                                         "  %3d |  Attr | A %3d->0 "
3159                                                         "| EXT_T_%1x    (Extension Token)    "
3160                                                         "|     %s(%s: \'%s\')",
3161                                                         level, codepage_attr, peek & 0x0f, Indent (level),
3162                                                         map_token (map->global, codepage_attr, peek), str);
3163                                         /* Reset code page */
3164                                         codepage_attr = 0;
3165                                 } else { /* Code page 0 */
3166                                         proto_tree_add_text (tree, tvb, off, 1+len,
3167                                                         "  %3d |  Attr |          "
3168                                                         "| EXT_T_%1x    (Extension Token)    "
3169                                                         "|     %s(%s: \'%s\')",
3170                                                         level, peek & 0x0f, Indent (level),
3171                                                         map_token (map->global, codepage_attr, peek), str);
3172                                 }
3173                                 off += 1+len;
3174                                 break;
3175                         case 0x83: /* STR_T */
3176                                 index = tvb_get_guintvar (tvb, off+1, &len);
3177                                 str = strtbl_lookup (tvb, str_tbl, index, NULL);
3178                                 proto_tree_add_text (tree, tvb, off, 1+len,
3179                                                 "  %3d |  Attr |          "
3180                                                 "| STR_T (Tableref string)         "
3181                                                 "|     %s\'%s\'",
3182                                                 level, Indent (level), str);
3183                                 off += 1+len;
3184                                 break;
3185                         /* 0x84 impossible in ATTR state */
3186                         case 0xC0: /* EXT_0 */
3187                         case 0xC1: /* EXT_1 */
3188                         case 0xC2: /* EXT_2 */
3189                                 /* Extension tokens */
3190                                 if (codepage_attr) { /* Not default code page */
3191                                         proto_tree_add_text (tree, tvb, off, 1,
3192                                                         "  %3d |  Attr | A %3d->0 "
3193                                                         "| EXT_%1x      (Extension Token)    "
3194                                                         "|     %s(%s)",
3195                                                         level, codepage_attr, peek & 0x0f, Indent (level),
3196                                                         map_token (map->global, codepage_attr, peek));
3197                                         /* Reset code page */
3198                                         codepage_attr = 0;
3199                                 } else { /* Code page 0 */
3200                                         proto_tree_add_text (tree, tvb, off, 1,
3201                                                         "  %3d |  Attr |          "
3202                                                         "| EXT_%1x      (Extension Token)    "
3203                                                         "|     %s(%s)",
3204                                                         level, peek & 0x0f, Indent (level),
3205                                                         map_token (map->global, codepage_attr, peek));
3206                                 }
3207                                 off++;
3208                                 break;
3209                         case 0xC3: /* OPAQUE - WBXML 1.1 and newer */
3210                                 if (tvb_get_guint8 (tvb, 0)) { /* WBXML 1.x (x > 0) */
3211                                         index = tvb_get_guintvar (tvb, off+1, &len);
3212                                         proto_tree_add_text (tree, tvb, off, 1 + len + index,
3213                                                         "  %3d |  Attr |          "
3214                                                         "| OPAQUE (Opaque data)            "
3215                                                         "|       %s(%d bytes of opaque data)",
3216                                                         level, Indent (level), index);
3217                                         off += 1+len+index;
3218                                 } else { /* WBXML 1.0 - RESERVED_2 token (invalid) */
3219                                         proto_tree_add_text (tree, tvb, off, 1,
3220                                                         "         Attr |          "
3221                                                         "| RESERVED_2     (Invalid Token!) "
3222                                                         "| WBXML 1.0 parsing stops here.");
3223                                         /* Stop processing as it is impossible to parse now */
3224                                         off = tvb_len;
3225                                         *parsed_length = off - offset;
3226                                         return;
3227                                 }
3228                                 break;
3229                         /* 0xC4 impossible in ATTR state */
3230                         default:
3231                                 proto_tree_add_text (tree, tvb, off, 1,
3232                                                 "  %3d |  Attr |          "
3233                                                 "| %-10s     (Invalid Token!) "
3234                                                 "| WBXML parsing stops here.",
3235                                                 level, match_strval (peek, vals_wbxml1x_global_tokens));
3236                                 /* Move to end of buffer */
3237                                 off = tvb_len;
3238                                 break;
3239                 } else { /* Known atribute token */
3240                         if (peek & 0x80) { /* attrValue */
3241                                 if (codepage_attr) { /* Not default code page */
3242                                         proto_tree_add_text (tree, tvb, off, 1,
3243                                                         "  %3d |  Attr | A %3d->0 "
3244                                                         "|   Known attrValue 0x%02X          "
3245                                                         "|       %s%s",
3246                                                         level, codepage_attr, peek & 0x7f, Indent (level),
3247                                                         map_token (map->attrValue, codepage_attr, peek));
3248                                         /* Reset code page */
3249                                         codepage_attr = 0;
3250                                 } else { /* Code page 0 */
3251                                         proto_tree_add_text (tree, tvb, off, 1,
3252                                                         "  %3d |  Attr |          "
3253                                                         "|   Known attrValue 0x%02X          "
3254                                                         "|       %s%s",
3255                                                         level, peek & 0x7f, Indent (level),
3256                                                         map_token (map->attrValue, codepage_attr, peek));
3257                                 }
3258                                 off++;
3259                         } else { /* attrStart */
3260                                 if (codepage_attr) { /* Not default code page */
3261                                         proto_tree_add_text (tree, tvb, off, 1,
3262                                                         "  %3d |  Attr | A %3d->0 "
3263                                                         "|   Known attrStart 0x%02X          "
3264                                                         "|   %s%s",
3265                                                         level, codepage_attr, peek & 0x7f, Indent (level),
3266                                                         map_token (map->attrStart, codepage_attr, peek));
3267                                         /* Reset code page */
3268                                         codepage_attr = 0;
3269                                 } else { /* Code page 0 */
3270                                         proto_tree_add_text (tree, tvb, off, 1,
3271                                                         "  %3d |  Attr |          "
3272                                                         "|   Known attrStart 0x%02X          "
3273                                                         "|   %s%s",
3274                                                         level, peek & 0x7f, Indent (level),
3275                                                         map_token (map->attrStart, codepage_attr, peek));
3276                                 }
3277                                 off++;
3278                         }
3279                 }
3280         } /* End WHILE */
3281 }
3282
3283
3284 /* This function performs the WBXML attribute decoding as in
3285  * parse_wbxml_attribute_list_defined() but this time no WBXML mapping
3286  * is performed.
3287  *
3288  * This function performs attribute list parsing.
3289  * 
3290  * NOTE: Code page switches not yet processed in the code!
3291  */
3292 static void
3293 parse_wbxml_attribute_list (proto_tree *tree, tvbuff_t *tvb,
3294                 guint32 offset, guint32 str_tbl, guint8 level,
3295                 guint32 *parsed_length)
3296 {
3297         guint32 tvb_len = tvb_reported_length (tvb);
3298         guint32 off = offset;
3299         guint32 len;
3300         guint32 ent;
3301         guint32 index;
3302         const char* str;
3303         guint8 peek;
3304         guint8 codepage_attr = 0; /* Initial codepage in state = ATTR */
3305
3306 #ifdef DEBUG
3307         printf ("WBXML - parse_wbxml_attr (level = %d, offset = %d)\n",
3308                         level, offset);
3309 #endif
3310         /* Parse attributes */
3311         while (off < tvb_len) {
3312                 peek = tvb_get_guint8 (tvb, off);
3313 #ifdef DEBUG
3314                 printf("WBXML - ATTR: level = %3d, peek = 0x%02X, off = %d, "
3315                                 "tvb_len = %d\n",
3316                                 level, peek, off, tvb_len);
3317 #endif
3318                 if ((peek & 0x3F) < 5) switch (peek) { /* Global tokens
3319                                                                                                   in state = ATTR */
3320                         case 0x00: /* SWITCH_PAGE */
3321                                 codepage_attr = tvb_get_guint8 (tvb, off+1);
3322                                 proto_tree_add_text (tree, tvb, off, 2,
3323                                                 "      |  Attr | A 0->%3d "
3324                                                 "| SWITCH_PAGE (Attr code page)    |",
3325                                                 codepage_attr);
3326                                 off += 2;
3327                                 break;
3328                         case 0x01: /* END */
3329                                 /* BEWARE
3330                                  *   The Attribute END token means either ">" or "/>"
3331                                  *   and as a consequence both must be treated separately.
3332                                  *   This is done in the TAG state parser.
3333                                  */
3334                                 off++;
3335                                 *parsed_length = off - offset;
3336                                 return;
3337                         case 0x02: /* ENTITY */
3338                                 ent = tvb_get_guintvar (tvb, off+1, &len);
3339                                 proto_tree_add_text (tree, tvb, off, 1+len,
3340                                                 "  %3d |  Attr |          "
3341                                                 "| ENTITY                          "
3342                                                 "|     %s'&#%u;'",
3343                                                 level, Indent (level), ent);
3344                                 off += 1+len;
3345                                 break;
3346                         case 0x03: /* STR_I */
3347                                 /* Hack the string table lookup function */
3348                                 str = strtbl_lookup (tvb, off+1, 0, &len);
3349                                 proto_tree_add_text (tree, tvb, off, 1+len,
3350                                                 "  %3d |  Attr |          "
3351                                                 "| STR_I (Inline string)           "
3352                                                 "|     %s\'%s\'",
3353                                                 level, Indent (level), str);
3354                                 off += 1+len;
3355                                 break;
3356                         case 0x04: /* LITERAL */
3357                                 index = tvb_get_guintvar (tvb, off+1, &len);
3358                                 str = strtbl_lookup (tvb, str_tbl, index, NULL);
3359                                 proto_tree_add_text (tree, tvb, off, 1+len,
3360                                                 "  %3d |  Attr |          "
3361                                                 "| LITERAL (Literal Attribute)     "
3362                                                 "|   %s<%s />",
3363                                                 level, Indent (level), str);
3364                                 off += 1+len;
3365                                 break;
3366                         case 0x40: /* EXT_I_0 */
3367                         case 0x41: /* EXT_I_1 */
3368                         case 0x42: /* EXT_I_2 */
3369                                 /* Extension tokens */
3370                                 /* Hack the string table lookup function */
3371                                 str = strtbl_lookup (tvb, off+1, 0, &len);
3372                                 if (codepage_attr) { /* Not default code page */
3373                                         proto_tree_add_text (tree, tvb, off, 1+len,
3374                                                         "  %3d |  Attr | A %3d->0 "
3375                                                         "| EXT_I_%1x    (Extension Token)    "
3376                                                         "|     %s(Inline string extension: \'%s\')",
3377                                                         level, codepage_attr, peek & 0x0f, Indent (level),
3378                                                         str);
3379                                         /* Reset code page */
3380                                         codepage_attr = 0;
3381                                 } else { /* Code page 0 */
3382                                         proto_tree_add_text (tree, tvb, off, 1+len,
3383                                                         "  %3d |  Attr |          "
3384                                                         "| EXT_I_%1x    (Extension Token)    "
3385                                                         "|     %s(Inline string extension: \'%s\')",
3386                                                         level, peek & 0x0f, Indent (level),
3387                                                         str);
3388                                 }
3389                                 off += 1+len;
3390                                 break;
3391                         /* 0x43 impossible in ATTR state */
3392                         /* 0x44 impossible in ATTR state */
3393                         case 0x80: /* EXT_T_0 */
3394                         case 0x81: /* EXT_T_1 */
3395                         case 0x82: /* EXT_T_2 */
3396                                 /* Extension tokens */
3397                                 index = tvb_get_guintvar (tvb, off+1, &len);
3398                                 str = strtbl_lookup (tvb, str_tbl, index, NULL);
3399                                 if (codepage_attr) { /* Not default code page */
3400                                         proto_tree_add_text (tree, tvb, off, 1+len,
3401                                                         "  %3d |  Attr | A %3d->0 "
3402                                                         "| EXT_T_%1x    (Extension Token)    "
3403                                                         "|     %s(Tableref string extension: \'%s\')",
3404                                                         level, codepage_attr, peek & 0x0f, Indent (level),
3405                                                         str);
3406                                         /* Reset code page */
3407                                         codepage_attr = 0;
3408                                 } else { /* Code page 0 */
3409                                         proto_tree_add_text (tree, tvb, off, 1+len,
3410                                                         "  %3d |  Attr |          "
3411                                                         "| EXT_T_%1x    (Extension Token)    "
3412                                                         "|     %s(Tableref string extension: \'%s\')",
3413                                                         level, peek & 0x0f, Indent (level),
3414                                                         str);
3415                                 }
3416                                 off += 1+len;
3417                                 break;
3418                         case 0x83: /* STR_T */
3419                                 index = tvb_get_guintvar (tvb, off+1, &len);
3420                                 str = strtbl_lookup (tvb, str_tbl, index, NULL);
3421                                 proto_tree_add_text (tree, tvb, off, 1+len,
3422                                                 "  %3d |  Attr |          "
3423                                                 "| STR_T (Tableref string)         "
3424                                                 "|     %s\'%s\'",
3425                                                 level, Indent (level), str);
3426                                 off += 1+len;
3427                                 break;
3428                         /* 0x84 impossible in ATTR state */
3429                         case 0xC0: /* EXT_0 */
3430                         case 0xC1: /* EXT_1 */
3431                         case 0xC2: /* EXT_2 */
3432                                 /* Extension tokens */
3433                                 if (codepage_attr) { /* Not default code page */
3434                                         proto_tree_add_text (tree, tvb, off, 1,
3435                                                         "  %3d |  Attr | A %3d->0 "
3436                                                         "| EXT_%1x      (Extension Token)    "
3437                                                         "|     %s(Single-byte extension)",
3438                                                         level, codepage_attr, peek & 0x0f, Indent (level));
3439                                         /* Reset code page */
3440                                         codepage_attr = 0;
3441                                 } else { /* Code page 0 */
3442                                         proto_tree_add_text (tree, tvb, off, 1,
3443                                                         "  %3d |  Attr |          "
3444                                                         "| EXT_%1x      (Extension Token)    "
3445                                                         "|     %s(Single-byte extension)",
3446                                                         level, peek & 0x0f, Indent (level));
3447                                 }
3448                                 off++;
3449                                 break;
3450                         case 0xC3: /* OPAQUE - WBXML 1.1 and newer */
3451                                 if (tvb_get_guint8 (tvb, 0)) { /* WBXML 1.x (x > 0) */
3452                                         index = tvb_get_guintvar (tvb, off+1, &len);
3453                                         proto_tree_add_text (tree, tvb, off, 1 + len + index,
3454                                                         "  %3d |  Attr |          "
3455                                                         "| OPAQUE (Opaque data)            "
3456                                                         "|       %s(%d bytes of opaque data)",
3457                                                         level, Indent (level), index);
3458                                         off += 1+len+index;
3459                                 } else { /* WBXML 1.0 - RESERVED_2 token (invalid) */
3460                                         proto_tree_add_text (tree, tvb, off, 1,
3461                                                         "         Attr |          "
3462                                                         "| RESERVED_2     (Invalid Token!) "
3463                                                         "| WBXML 1.0 parsing stops here.");
3464                                         /* Stop processing as it is impossible to parse now */
3465                                         off = tvb_len;
3466                                         *parsed_length = off - offset;
3467                                         return;
3468                                 }
3469                                 break;
3470                         /* 0xC4 impossible in ATTR state */
3471                         default:
3472                                 proto_tree_add_text (tree, tvb, off, 1,
3473                                                 "  %3d |  Attr |          "
3474                                                 "| %-10s     (Invalid Token!) "
3475                                                 "| WBXML parsing stops here.",
3476                                                 level, match_strval (peek, vals_wbxml1x_global_tokens));
3477                                 /* Move to end of buffer */
3478                                 off = tvb_len;
3479                                 break;
3480                 } else { /* Known atribute token */
3481                         if (peek & 0x80) { /* attrValue */
3482                                 if (codepage_attr) { /* Not default code page */
3483                                         proto_tree_add_text (tree, tvb, off, 1,
3484                                                         "  %3d |  Attr | A %3d->0 "
3485                                                         "|   Known attrValue 0x%02X          "
3486                                                         "|       %sattrValue_0x%02X",
3487                                                         level, codepage_attr, peek & 0x7f, Indent (level),
3488                                                         peek);
3489                                         /* Reset code page */
3490                                         codepage_attr = 0;
3491                                 } else { /* Code page 0 */
3492                                         proto_tree_add_text (tree, tvb, off, 1,
3493                                                         "  %3d |  Attr |          "
3494                                                         "|   Known attrValue 0x%02X          "
3495                                                         "|       %sattrValue_0x%02X",
3496                                                         level, peek & 0x7f, Indent (level),
3497                                                         peek);
3498                                 }
3499                                 off++;
3500                         } else { /* attrStart */
3501                                 if (codepage_attr) { /* Not default code page */
3502                                         proto_tree_add_text (tree, tvb, off, 1,
3503                                                         "  %3d |  Attr | A %3d->0 "
3504                                                         "|   Known attrStart 0x%02X          "
3505                                                         "|   %sattrStart_0x%02X",
3506                                                         level, codepage_attr, peek & 0x7f, Indent (level),
3507                                                         peek);
3508                                         /* Reset code page */
3509                                         codepage_attr = 0;
3510                                 } else { /* Code page 0 */
3511                                         proto_tree_add_text (tree, tvb, off, 1,
3512                                                         "  %3d |  Attr |          "
3513                                                         "|   Known attrStart 0x%02X          "
3514                                                         "|   %sattrStart_0x%02X",
3515                                                         level, peek & 0x7f, Indent (level),
3516                                                         peek);
3517                                 }
3518                                 off++;
3519                         }
3520                 }
3521         } /* End WHILE */
3522 }
3523
3524
3525 /****************** Register the protocol with Ethereal ******************/
3526
3527
3528 /* This format is required because a script is used to build the C function
3529  * that calls the protocol registration. */
3530
3531 void
3532 proto_register_wbxml(void)
3533 { /* Setup list of header fields. See Section 1.6.1 for details. */
3534         static hf_register_info hf[] = {
3535                 { &hf_wbxml_version,
3536                         { "Version",
3537                           "wbxml.version",
3538                           FT_UINT8, BASE_HEX,
3539                           VALS ( vals_wbxml_versions ), 0x00,
3540                           "WBXML Version", HFILL }
3541                 },
3542                 { &hf_wbxml_public_id_known,
3543                         { "Public Identifier (known)",
3544                           "wbxml.public_id.known",
3545                           FT_UINT32, BASE_HEX,
3546                           VALS ( vals_wbxml_public_ids ), 0x00,
3547                           "WBXML Known Public Identifier (integer)", HFILL }
3548                 },
3549                 { &hf_wbxml_public_id_literal,
3550                         { "Public Identifier (literal)",
3551                           "wbxml.public_id.literal",
3552                           FT_STRING, BASE_NONE,
3553                           NULL, 0x00,
3554                           "WBXML Literal Public Identifier (text string)", HFILL }
3555                 },
3556                 { &hf_wbxml_charset,
3557                         { "Character Set",
3558                           "wbxml.charset",
3559                           FT_UINT32, BASE_HEX,
3560                           VALS ( vals_character_sets ), 0x00,
3561                           "WBXML Character Set", HFILL }
3562                 },
3563         };
3564
3565         /* Setup protocol subtree array */
3566         static gint *ett[] = {
3567                 &ett_wbxml,
3568                 &ett_wbxml_str_tbl,
3569                 &ett_wbxml_content,
3570         };
3571
3572         /* Register the protocol name and description */
3573         proto_wbxml = proto_register_protocol(
3574                         "WAP Binary XML",
3575                         "WBXML",
3576                         "wbxml"
3577         );
3578
3579         /* Required function calls to register the header fields
3580          * and subtrees used */
3581         proto_register_field_array(proto_wbxml, hf, array_length(hf));
3582         proto_register_subtree_array(ett, array_length(ett));
3583
3584         register_dissector("wbxml", dissect_wbxml, proto_wbxml);
3585 };
3586
3587
3588 void
3589 proto_reg_handoff_wbxml(void)
3590 {
3591         dissector_handle_t wbxml_handle;
3592
3593         /* Heuristic dissectors would be declared by means of:
3594          * heur_dissector_add("wsp", dissect_wbxml_heur, proto_wbxml);
3595          */
3596
3597         wbxml_handle = create_dissector_handle(dissect_wbxml, proto_wbxml);
3598
3599         /* Register the WSP content types (defined as protocol port)
3600          * for WBXML dissection.
3601          * 
3602          * See http://www.wapforum.org/wina/wsp-content-type.htm
3603          */
3604
3605         /**** Well-known WBXML WSP Content-Type values ****/
3606         
3607         /* application/vnd.wap.wmlc */
3608         dissector_add("wsp.content_type.type", 0x14, wbxml_handle);
3609         
3610         /* application/vnd.wap.wta-eventc */
3611         dissector_add("wsp.content_type.type", 0x16, wbxml_handle);
3612         
3613         /* application/vnd.wap.wbxml */
3614         dissector_add("wsp.content_type.type", 0x29, wbxml_handle);
3615         
3616         /* application/vnd.wap.sic */
3617         dissector_add("wsp.content_type.type", 0x2E, wbxml_handle);
3618         
3619         /* application/vnd.wap.slc */
3620         dissector_add("wsp.content_type.type", 0x30, wbxml_handle);
3621         
3622         /* application/vnd.wap.coc */
3623         dissector_add("wsp.content_type.type", 0x32, wbxml_handle);
3624         
3625         /* application/vnd.wap.connectivity-wbxml */
3626         dissector_add("wsp.content_type.type", 0x36, wbxml_handle);
3627         
3628         /* application/vnd.wap.locc+wbxml */
3629         dissector_add("wsp.content_type.type", 0x40, wbxml_handle);
3630         
3631         /* application/vnd.syncml.dm+wbxml */
3632         dissector_add("wsp.content_type.type", 0x42, wbxml_handle);
3633         
3634         /* application/vnd.oma.drm.rights+wbxml */
3635         dissector_add("wsp.content_type.type", 0x4B, wbxml_handle);
3636
3637 #ifdef WSP_DISSECTOR_REGISTERS_ContentType_AS_FourByteGuint     
3638         
3639         /**** Registered WBXML WSP Content-Type values ****/
3640
3641         /* application/vnd.uplanet.cacheop-wbxml */
3642         dissector_add("wsp.content_type.type", 0x0201, wbxml_handle);
3643         
3644         /* application/vnd.uplanet.alert-wbxml */
3645         dissector_add("wsp.content_type.type", 0x0203, wbxml_handle);
3646         
3647         /* application/vnd.uplanet.list-wbxml */
3648         dissector_add("wsp.content_type.type", 0x0204, wbxml_handle);
3649         
3650         /* application/vnd.uplanet.listcmd-wbxml */
3651         dissector_add("wsp.content_type.type", 0x0205, wbxml_handle);
3652         
3653         /* application/vnd.uplanet.channel-wbxml */
3654         dissector_add("wsp.content_type.type", 0x0206, wbxml_handle);
3655         
3656         /* application/vnd.uplanet.bearer-choice-wbxml */
3657         dissector_add("wsp.content_type.type", 0x0209, wbxml_handle);
3658         
3659         /* application/vnd.phonecom.mmc-wbxml */
3660         dissector_add("wsp.content_type.type", 0x020A, wbxml_handle);
3661         
3662         /* application/vnd.nokia.syncset+wbxml */
3663         dissector_add("wsp.content_type.type", 0x020B, wbxml_handle);
3664 #endif
3665 }