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