From Todd Sabin: allocate the buffer for the decrypted payload, rather
[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.6 2003/02/27 02:52:50 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  *  - Although Code Page processing is already foreseen in the tag and
59  *    attribute parsing code, there is no mechanism available yet to
60  *    properly deal with multiple code pages (see, e.g., the wbxml_map[]
61  *    array). As a consequence, the same token rendering will occur,
62  *    irrespective of the code pages in use.
63  *    As there currently is no registered WBXML type with support of more
64  *    than one tag or attribute code page, this is a safe assumption.
65  *
66  *  - In order to render the XML content, recursion is inevitable at some
67  *    point (when a tag with content occurs in the content of a tag with
68  *    content). The code will however not recurse if this is not strictly
69  *    required (e.g., tag without content in the content of a tag with
70  *    content).
71  *
72  *  - I found it useful to display the XML nesting level as a first "column",
73  *    followed by the abbreviated WBXML token interpretation. When a mapping
74  *    is defined for the parsed WBXML content, then the XML rendering is
75  *    displayed with appropriate indentation (maximum nesting level = 255,
76  *    after which the nesting and level will safely roll-over to 0).
77  */
78
79
80 /************************* Variable declarations *************************/
81
82
83 /* Initialize the protocol and registered fields */
84 static int proto_wbxml = -1;
85 static int hf_wbxml_version = -1;
86 static int hf_wbxml_public_id_known = -1;
87 static int hf_wbxml_public_id_literal = -1;
88 static int hf_wbxml_charset = -1;
89
90 /* Initialize the subtree pointers */
91 static gint ett_wbxml = -1;
92 static gint ett_wbxml_str_tbl = -1;
93 static gint ett_wbxml_content = -1;
94
95
96
97 /********** WBXML related declarations and definitions **********/
98
99 /* See http://www.wapforum.org/wina/ for an up-to-date list. */
100 #define WBXML_WML_10            0x02
101 #define WBXML_WTA_10            0x03
102 #define WBXML_WML_11            0x04
103 #define WBXML_SI_10                     0x05
104 #define WBXML_SL_10                     0x06
105 #define WBXML_CO_10                     0x07
106 #define WBXML_CHANNEL_10        0x08
107 #define WBXML_WML_12            0x09
108 #define WBXML_WML_13            0x0a
109 #define WBXML_PROV_10           0x0b
110 #define WBXML_WTAWML_12         0x0c
111 #define WBXML_EMN_10            0x0d
112 #define WBXML_DRMREL_10         0x0e
113
114 static const value_string vals_wbxml_public_ids[] = {
115         /* 0x00 = literal public identifier */
116         { 0x01, "Unknown / missing Public Identifier" },
117         { 0x02, "-//WAPFORUM//DTD WML 1.0//EN (WML 1.0)" },
118         { 0x03, "-//WAPFORUM//DTD WTA 1.0//EN (WTA Event 1.0) - Deprecated" },
119         { 0x04, "-//WAPFORUM//DTD WML 1.1//EN (WML 1.1)" },
120         { 0x05, "-//WAPFORUM//DTD SI 1.0//EN (Service Indication 1.0)" },
121         { 0x06, "-//WAPFORUM//DTD SL 1.0//EN (Service Loading 1.0)" },
122         { 0x07, "-//WAPFORUM//DTD CO 1.0//EN (Cache Operation 1.0)" },
123         { 0x08, "-//WAPFORUM//DTD CHANNEL 1.0//EN (Channel 1.1)" },
124         { 0x09, "-//WAPFORUM//DTD WML 1.2//EN (WML 1.2)" },
125         { 0x0a, "-//WAPFORUM//DTD WML 1.3//EN (WML 1.3)" },
126         { 0x0b, "-//WAPFORUM//DTD PROV 1.0//EN (Provisioning 1.0)" },
127         { 0x0c, "-//WAPFORUM//DTD WTA-WML 1.2//EN (WTA-WML 1.2)" },
128         { 0x0d, "-//WAPFORUM//DTD EMN 1.0//EN (Email Notification 1.0)" },
129         { 0x0e, "-//WAPFORUM//DTD DRMREL 1.0//EN (DRMREL 1.0)" },
130         
131         { 0x00, NULL }
132 };
133
134
135
136 static const value_string vals_wbxml_versions[] = {
137         { 0x00, "1.0" },
138         { 0x01, "1.1" },
139         { 0x02, "1.2" },
140         { 0x03, "1.3" },
141         
142         { 0x00, NULL }
143 };
144
145 /* See WAP-104-WBXML */
146 static const value_string vals_wbxml10_global_tokens[] = {
147         { 0x00, "SWITCH_PAGE" },
148         { 0x01, "END" },
149         { 0x02, "ENTITY" },
150         { 0x03, "STR_I" },
151         { 0x04, "LITERAL" },
152
153         { 0x40, "EXT_I_0" },
154         { 0x41, "EXT_I_1" },
155         { 0x42, "EXT_I_2" },
156         { 0x43, "PI" },
157         { 0x44, "LITERAL_C" },
158
159         { 0x80, "EXT_T_0" },
160         { 0x81, "EXT_T_1" },
161         { 0x82, "EXT_T_2" },
162         { 0x83, "STR_T" },
163         { 0x84, "LITERAL_A" },
164
165         { 0xC0, "EXT_0" },
166         { 0xC1, "EXT_1" },
167         { 0xC2, "EXT_2" },
168         { 0xC3, "RESERVED_2" },
169         { 0xC4, "LITERAL_AC" },
170
171         { 0x00, NULL }
172 };
173
174 /* See WAP-135-WBXML, WAP-154-WBXML, WAP-192-WBXML */
175 static const value_string vals_wbxml1x_global_tokens[] = {
176         { 0x00, "SWITCH_PAGE" },
177         { 0x01, "END" },
178         { 0x02, "ENTITY" },
179         { 0x03, "STR_I" },
180         { 0x04, "LITERAL" },
181
182         { 0x40, "EXT_I_0" },
183         { 0x41, "EXT_I_1" },
184         { 0x42, "EXT_I_2" },
185         { 0x43, "PI" },
186         { 0x44, "LITERAL_C" },
187
188         { 0x80, "EXT_T_0" },
189         { 0x81, "EXT_T_1" },
190         { 0x82, "EXT_T_2" },
191         { 0x83, "STR_T" },
192         { 0x84, "LITERAL_A" },
193
194         { 0xC0, "EXT_0" },
195         { 0xC1, "EXT_1" },
196         { 0xC2, "EXT_2" },
197         { 0xC3, "OPAQUE" },
198         { 0xC4, "LITERAL_AC" },
199
200         { 0x00, NULL }
201 };
202
203
204 /****************************************************************************/
205
206 /*******************************************
207  *      WML 1.0 - Global tokens (EXT)      *
208  *******************************************/
209 static const value_string vals_wmlc10_global[] = {
210         { 0x40, "Variable substitution - escaped" },
211         { 0x41, "Variable substitution - unescaped" },
212         { 0x42, "Variable substitution - no transformation" },
213         { 0x80, "Variable substitution - escaped" },
214         { 0x81, "Variable substitution - unescaped" },
215         { 0x82, "Variable substitution - no transformation" },
216         { 0xC0, "Reserved" },
217         { 0xC1, "Reserved" },
218         { 0xC2, "Reserved" },
219
220         { 0x00, NULL }
221 };
222
223 /*******************************************
224  *              WML 1.0 - Tags             *
225  *******************************************/
226 static const value_string vals_wmlc10_tags[] = {
227         /* 0x00 -- 0x04 GLOBAL */
228         /* 0x05 -- 0xE1 */
229         { 0xE2, "A" },
230         { 0xE3, "ACCESS" },
231         { 0xE4, "B" },
232         { 0xE5, "BIG" },
233         { 0xE6, "BR" },
234         { 0xE7, "CARD" },
235         { 0xE8, "DO" },
236         { 0xE9, "EM" },
237         { 0xEA, "FIELDSET" },
238         { 0xEB, "GO" },
239         { 0xEC, "HEAD" },
240         { 0xED, "I" },
241         { 0xEE, "IMG" },
242         { 0xEF, "INPUT" },
243         { 0xF0, "META" },
244         { 0xF1, "NOOP" },
245         { 0xF2, "PREV" },
246         { 0xF3, "ONEVENT" },
247         { 0xF4, "OPTGROUP" },
248         { 0xF5, "OPTION" },
249         { 0xF6, "REFRESH" },
250         { 0xF7, "SELECT" },
251         { 0xF8, "SMALL" },
252         { 0xF9, "STRONG" },
253         { 0xFA, "TAB" },
254         { 0xFB, "TEMPLATE" },
255         { 0xFC, "TIMER" },
256         { 0xFD, "U" },
257         { 0xFE, "VAR" },
258         { 0xFF, "WML" },
259
260         { 0x00, NULL }
261 };
262
263 /*******************************************
264  *       WML 1.0 - Attribute Start         *
265  *******************************************/
266 static const value_string vals_wmlc10_attrStart[] = {
267         /* 0x00 -- 0x04 GLOBAL */
268         { 0x05, "ACCEPT-CHARSET=" },
269         { 0x06, "ALIGN='BOTTOM'" },
270         { 0x07, "ALIGN='CENTER'" },
271         { 0x08, "ALIGN='LEFT'" },
272         { 0x09, "ALIGN='MIDDLE'" },
273         { 0x0A, "ALIGN='RIGHT'" },
274         { 0x0B, "ALIGN='TOP'" },
275         { 0x0C, "ALT=" },
276         { 0x0D, "CONTENT=" },
277         { 0x0E, "DEFAULT=" },
278         { 0x0F, "DOMAIN=" },
279         { 0x10, "EMPTYOK='FALSE'" },
280         { 0x11, "EMPTYOK='TRUE'" },
281         { 0x12, "FORMAT=" },
282         { 0x13, "HEIGHT=" },
283         { 0x14, "HSPACE=" },
284         { 0x15, "IDEFAULT=" },
285         { 0x16, "IKEY=" },
286         { 0x17, "KEY=" },
287         { 0x18, "LABEL=" },
288         { 0x19, "LOCALSRC=" },
289         { 0x1A, "MAXLENGTH=" },
290         { 0x1B, "METHOD='GET'" },
291         { 0x1C, "METHOD='POST'" },
292         { 0x1D, "MODE='NOWRAP'" },
293         { 0x1E, "MODE='WRAP'" },
294         { 0x1F, "MULTIPLE='FALSE'" },
295         { 0x20, "MULTIPLE='TRUE'" },
296         { 0x21, "NAME=" },
297         { 0x22, "NEWCONTEXT='FALSE'" },
298         { 0x23, "NEWCONTEXT='TRUE'" },
299         { 0x24, "ONCLICK=" },
300         { 0x25, "ONENTERBACKWARD=" },
301         { 0x26, "ONENTERFORWARD=" },
302         { 0x27, "ONTIMER=" },
303         { 0x28, "OPTIONAL='FALSE'" },
304         { 0x29, "OPTIONAL='TRUE'" },
305         { 0x2A, "PATH=" },
306         { 0x2B, "POSTDATA=" },
307         { 0x2C, "PUBLIC='FALSE'" },
308         { 0x2D, "PUBLIC='TRUE'" },
309         { 0x2E, "SCHEME=" },
310         { 0x2F, "SENDREFERER='FALSE'" },
311         { 0x30, "SENDREFERER='TRUE'" },
312         { 0x31, "SIZE=" },
313         { 0x32, "SRC=" },
314         { 0x33, "STYLE='LIST'" },
315         { 0x34, "STYLE='SET'" },
316         { 0x35, "TABINDEX=" },
317         { 0x36, "TITLE=" },
318         { 0x37, "TYPE=" },
319         { 0x38, "TYPE='ACCEPT'" },
320         { 0x39, "TYPE='DELETE'" },
321         { 0x3A, "TYPE='HELP'" },
322         { 0x3B, "TYPE='PASSWORD'" },
323         { 0x3C, "TYPE='ONCLICK'" },
324         { 0x3D, "TYPE='ONENTERBACKWARD'" },
325         { 0x3E, "TYPE='ONENTERFORWARD'" },
326         { 0x3F, "TYPE='ONTIMER'" },
327         /* 0x40 -- 0x44 GLOBAL */
328         { 0x45, "TYPE='OPTIONS'" },
329         { 0x46, "TYPE='PREV'" },
330         { 0x47, "TYPE='RESET'" },
331         { 0x48, "TYPE='TEXT'" },
332         { 0x49, "TYPE='vnd.'" },
333         { 0x4A, "URL=" },
334         { 0x4B, "URL='http://'" },
335         { 0x4C, "URL='https://'" },
336         { 0x4D, "USER-AGENT=" },
337         { 0x4E, "VALUE=" },
338         { 0x4F, "VSPACE=" },
339         { 0x50, "WIDTH=" },
340         { 0x51, "xml:lang=" },
341
342         { 0x00, NULL }
343 };
344
345 /*******************************************
346  *       WML 1.0 - Attribute Value         *
347  *******************************************/
348 static const value_string vals_wmlc10_attrValue[] = {
349         /* 0x80 -- 0x84 GLOBAL */
350         { 0x85, "'.com/'" },
351         { 0x86, "'.edu/'" },
352         { 0x87, "'.net/'" },
353         { 0x88, "'.org/'" },
354         { 0x89, "'ACCEPT'" },
355         { 0x8A, "'BOTTOM'" },
356         { 0x8B, "'CLEAR'" },
357         { 0x8C, "'DELETE'" },
358         { 0x8D, "'HELP'" },
359         { 0x8E, "'http://'" },
360         { 0x8F, "'http://www.'" },
361         { 0x90, "'https://'" },
362         { 0x91, "'https://www.'" },
363         { 0x92, "'LIST'" },
364         { 0x93, "'MIDDLE'" },
365         { 0x94, "'NOWRAP'" },
366         { 0x95, "'ONCLICK'" },
367         { 0x96, "'ONENTERBACKWARD'" },
368         { 0x97, "'ONENTERFORWARD'" },
369         { 0x98, "'ONTIMER'" },
370         { 0x99, "'OPTIONS'" },
371         { 0x9A, "'PASSWORD'" },
372         { 0x9B, "'RESET'" },
373         { 0x9C, "'SET'" },
374         { 0x9D, "'TEXT'" },
375         { 0x9E, "'TOP'" },
376         { 0x9F, "'UNKNOWN'" },
377         { 0xA0, "'WRAP'" },
378         { 0xA1, "'www.'" },
379
380         { 0x00, NULL }
381 };
382
383 /****************************************************************************/
384
385 /*******************************************
386  *      WML 1.1 - Global tokens (EXT)      *
387  *******************************************/
388 #define vals_wmlc11_global  vals_wmlc10_global
389
390 /*******************************************
391  *              WML 1.1 - Tags             *
392  *******************************************/
393 static const value_string vals_wmlc11_tags[] = {
394         /* 0x00 -- 0x04 GLOBAL */
395         /* 0x05 -- 0x1B */
396         { 0x1C, "a" },
397         { 0x1D, "td" },
398         { 0x1E, "tr" },
399         { 0x1F, "table" },
400         { 0x20, "p" },
401         { 0x21, "postfield" },
402         { 0x22, "anchor" },
403         { 0x23, "access" },
404         { 0x24, "b" },
405         { 0x25, "big" },
406         { 0x26, "br" },
407         { 0x27, "card" },
408         { 0x28, "do" },
409         { 0x29, "em" },
410         { 0x2A, "fieldset" },
411         { 0x2B, "go" },
412         { 0x2C, "head" },
413         { 0x2D, "i" },
414         { 0x2E, "img" },
415         { 0x2F, "input" },
416         { 0x30, "meta" },
417         { 0x31, "noop" },
418         { 0x32, "prev" },
419         { 0x33, "onevent" },
420         { 0x34, "optgroup" },
421         { 0x35, "option" },
422         { 0x36, "refresh" },
423         { 0x37, "select" },
424         { 0x38, "small" },
425         { 0x39, "strong" },
426         /* 0x3A */
427         { 0x3B, "template" },
428         { 0x3C, "timer" },
429         { 0x3D, "u" },
430         { 0x3E, "setvar" },
431         { 0x3F, "wml" },
432
433         { 0x00, NULL }
434 };
435
436 /*******************************************
437  *       WML 1.1 - Attribute Start         *
438  *******************************************/
439 static const value_string vals_wmlc11_attrStart[] = {
440         /* 0x00 -- 0x04 GLOBAL */
441         { 0x05, "accept-charset=" },
442         { 0x06, "align='bottom'" },
443         { 0x07, "align='center'" },
444         { 0x08, "align='left'" },
445         { 0x09, "align='middle'" },
446         { 0x0A, "align='right'" },
447         { 0x0B, "align='top'" },
448         { 0x0C, "alt=" },
449         { 0x0D, "content=" },
450         /* 0x0E */
451         { 0x0F, "domain=" },
452         { 0x10, "emptyok='false'" },
453         { 0x11, "emptyok='true'" },
454         { 0x12, "format=" },
455         { 0x13, "height=" },
456         { 0x14, "hspace=" },
457         { 0x15, "ivalue=" },
458         { 0x16, "iname=" },
459         /* 0x17 */
460         { 0x18, "label=" },
461         { 0x19, "localsrc=" },
462         { 0x1A, "maxlength=" },
463         { 0x1B, "method='get'" },
464         { 0x1C, "method='post'" },
465         { 0x1D, "mode='nowrap'" },
466         { 0x1E, "mode='wrap'" },
467         { 0x1F, "multiple='false'" },
468         { 0x20, "multiple='true'" },
469         { 0x21, "name=" },
470         { 0x22, "newcontext='false'" },
471         { 0x23, "newcontext='true'" },
472         { 0x24, "onpick=" },
473         { 0x25, "onenterbackward=" },
474         { 0x26, "onenterforward=" },
475         { 0x27, "ontimer=" },
476         { 0x28, "optional='false'" },
477         { 0x29, "optional='true'" },
478         { 0x2A, "path=" },
479         /* 0x2B -- 0x2D */
480         { 0x2E, "scheme=" },
481         { 0x2F, "sendreferer='false'" },
482         { 0x30, "sendreferer='true'" },
483         { 0x31, "size=" },
484         { 0x32, "src=" },
485         { 0x33, "ordered='false'" },
486         { 0x34, "ordered='true'" },
487         { 0x35, "tabindex=" },
488         { 0x36, "title=" },
489         { 0x37, "type=" },
490         { 0x38, "type='accept'" },
491         { 0x39, "type='delete'" },
492         { 0x3A, "type='help'" },
493         { 0x3B, "type='password'" },
494         { 0x3C, "type='onpick'" },
495         { 0x3D, "type='onenterbackward'" },
496         { 0x3E, "type='onenterforward'" },
497         { 0x3F, "type='ontimer'" },
498         /* 0x40 -- 0x44 GLOBAL */
499         { 0x45, "type='options'" },
500         { 0x46, "type='prev'" },
501         { 0x47, "type='reset'" },
502         { 0x48, "type='text'" },
503         { 0x49, "type='vnd.'" },
504         { 0x4A, "href=" },
505         { 0x4B, "href='http://'" },
506         { 0x4C, "href='https://'" },
507         { 0x4D, "value=" },
508         { 0x4E, "vspace=" },
509         { 0x4F, "width=" },
510         { 0x50, "xml:lang=" },
511         /* 0x51 */
512         { 0x52, "align=" },
513         { 0x53, "columns=" },
514         { 0x54, "class=" },
515         { 0x55, "id=" },
516         { 0x56, "forua='false'" },
517         { 0x57, "forua='true'" },
518         { 0x58, "src='http://'" },
519         { 0x59, "src='https://'" },
520         { 0x5A, "http-equiv=" },
521         { 0x5B, "http-equiv='Content-Type'" },
522         { 0x5C, "content='application/vnd.wap.wmlc;charset='" },
523         { 0x5D, "http-equiv='Expires'" },
524
525         { 0x00, NULL }
526 };
527
528 /*******************************************
529  *       WML 1.1 - Attribute Value         *
530  *******************************************/
531 static const value_string vals_wmlc11_attrValue[] = {
532         /* 0x80 -- 0x84 GLOBAL */
533         { 0x85, "'.com/'" },
534         { 0x86, "'.edu/'" },
535         { 0x87, "'.net/'" },
536         { 0x88, "'.org/'" },
537         { 0x89, "'accept'" },
538         { 0x8A, "'bottom'" },
539         { 0x8B, "'clear'" },
540         { 0x8C, "'delete'" },
541         { 0x8D, "'help'" },
542         { 0x8E, "'http://'" },
543         { 0x8F, "'http://www.'" },
544         { 0x90, "'https://'" },
545         { 0x91, "'https://www.'" },
546         /* 0x92 */
547         { 0x93, "'middle'" },
548         { 0x94, "'nowrap'" },
549         { 0x95, "'onpick'" },
550         { 0x96, "'onenterbackward'" },
551         { 0x97, "'onenterforward'" },
552         { 0x98, "'ontimer'" },
553         { 0x99, "'options'" },
554         { 0x9A, "'password'" },
555         { 0x9B, "'reset'" },
556         /* 0x9C */
557         { 0x9D, "'text'" },
558         { 0x9E, "'top'" },
559         { 0x9F, "'unknown'" },
560         { 0xA0, "'wrap'" },
561         { 0xA1, "'www.'" },
562
563         { 0x00, NULL }
564 };
565
566 /****************************************************************************/
567
568 /*******************************************
569  *      WML 1.2 - Global tokens (EXT)      *
570  *******************************************/
571 #define vals_wmlc12_global vals_wmlc11_global
572         
573 /*******************************************
574  *              WML 1.2 - Tags             *
575  *******************************************/
576 static const value_string vals_wmlc12_tags[] = {
577         /* 0x00 -- 0x04 GLOBAL */
578         /* 0x05 -- 0x1A */
579         { 0x1B, "pre" },
580         { 0x1C, "a" },
581         { 0x1D, "td" },
582         { 0x1E, "tr" },
583         { 0x1F, "table" },
584         { 0x20, "p" },
585         { 0x21, "postfield" },
586         { 0x22, "anchor" },
587         { 0x23, "access" },
588         { 0x24, "b" },
589         { 0x25, "big" },
590         { 0x26, "br" },
591         { 0x27, "card" },
592         { 0x28, "do" },
593         { 0x29, "em" },
594         { 0x2A, "fieldset" },
595         { 0x2B, "go" },
596         { 0x2C, "head" },
597         { 0x2D, "i" },
598         { 0x2E, "img" },
599         { 0x2F, "input" },
600         { 0x30, "meta" },
601         { 0x31, "noop" },
602         { 0x32, "prev" },
603         { 0x33, "onevent" },
604         { 0x34, "optgroup" },
605         { 0x35, "option" },
606         { 0x36, "refresh" },
607         { 0x37, "select" },
608         { 0x38, "small" },
609         { 0x39, "strong" },
610         /* 0x3A */
611         { 0x3B, "template" },
612         { 0x3C, "timer" },
613         { 0x3D, "u" },
614         { 0x3E, "setvar" },
615         { 0x3F, "wml" },
616
617         { 0x00, NULL }
618 };
619
620 /*******************************************
621  *       WML 1.2 - Attribute Start         *
622  *******************************************/
623 static const value_string vals_wmlc12_attrStart[] = {
624         /* 0x00 -- 0x04 GLOBAL */
625         { 0x05, "accept-charset=" },
626         { 0x06, "align='bottom'" },
627         { 0x07, "align='center'" },
628         { 0x08, "align='left'" },
629         { 0x09, "align='middle'" },
630         { 0x0A, "align='right'" },
631         { 0x0B, "align='top'" },
632         { 0x0C, "alt=" },
633         { 0x0D, "content=" },
634         /* 0x0E */
635         { 0x0F, "domain=" },
636         { 0x10, "emptyok='false'" },
637         { 0x11, "emptyok='true'" },
638         { 0x12, "format=" },
639         { 0x13, "height=" },
640         { 0x14, "hspace=" },
641         { 0x15, "ivalue=" },
642         { 0x16, "iname=" },
643         /* 0x17 */
644         { 0x18, "label=" },
645         { 0x19, "localsrc=" },
646         { 0x1A, "maxlength=" },
647         { 0x1B, "method='get'" },
648         { 0x1C, "method='post'" },
649         { 0x1D, "mode='nowrap'" },
650         { 0x1E, "mode='wrap'" },
651         { 0x1F, "multiple='false'" },
652         { 0x20, "multiple='true'" },
653         { 0x21, "name=" },
654         { 0x22, "newcontext='false'" },
655         { 0x23, "newcontext='true'" },
656         { 0x24, "onpick=" },
657         { 0x25, "onenterbackward=" },
658         { 0x26, "onenterforward=" },
659         { 0x27, "ontimer=" },
660         { 0x28, "optional='false'" },
661         { 0x29, "optional='true'" },
662         { 0x2A, "path=" },
663         /* 0x2B -- 0x2D */
664         { 0x2E, "scheme=" },
665         { 0x2F, "sendreferer='false'" },
666         { 0x30, "sendreferer='true'" },
667         { 0x31, "size=" },
668         { 0x32, "src=" },
669         { 0x33, "ordered='false'" },
670         { 0x34, "ordered='true'" },
671         { 0x35, "tabindex=" },
672         { 0x36, "title=" },
673         { 0x37, "type=" },
674         { 0x38, "type='accept'" },
675         { 0x39, "type='delete'" },
676         { 0x3A, "type='help'" },
677         { 0x3B, "type='password'" },
678         { 0x3C, "type='onpick'" },
679         { 0x3D, "type='onenterbackward'" },
680         { 0x3E, "type='onenterforward'" },
681         { 0x3F, "type='ontimer'" },
682         /* 0x40 -- 0x44 GLOBAL */
683         { 0x45, "type='options'" },
684         { 0x46, "type='prev'" },
685         { 0x47, "type='reset'" },
686         { 0x48, "type='text'" },
687         { 0x49, "type='vnd.'" },
688         { 0x4A, "href=" },
689         { 0x4B, "href='http://'" },
690         { 0x4C, "href='https://'" },
691         { 0x4D, "value=" },
692         { 0x4E, "vspace=" },
693         { 0x4F, "width=" },
694         { 0x50, "xml:lang=" },
695         /* 0x51 */
696         { 0x52, "align=" },
697         { 0x53, "columns=" },
698         { 0x54, "class=" },
699         { 0x55, "id=" },
700         { 0x56, "forua='false'" },
701         { 0x57, "forua='true'" },
702         { 0x58, "src='http://'" },
703         { 0x59, "src='https://'" },
704         { 0x5A, "http-equiv=" },
705         { 0x5B, "http-equiv='Content-Type'" },
706         { 0x5C, "content='application/vnd.wap.wmlc;charset='" },
707         { 0x5D, "http-equiv='Expires'" },
708         { 0x5E, "accesskey=" },
709         { 0x5F, "enctype=" },
710         { 0x60, "enctype='application/x-www-form-urlencoded'" },
711         { 0x61, "enctype='multipart/form-data'" },
712
713         { 0x00, NULL }
714 };
715
716 /*******************************************
717  *       WML 1.2 - Attribute Value         *
718  *******************************************/
719 #define vals_wmlc12_attrValue vals_wmlc11_attrValue
720 /* Same as WML 1.1 */
721
722
723 /****************************************************************************/
724
725 /*******************************************
726  *      WML 1.3 - Global tokens (EXT)      *
727  *******************************************/
728 #define vals_wmlc13_global vals_wmlc11_global
729
730 /*******************************************
731  *              WML 1.3 - Tags             *
732  *******************************************/
733 #define vals_wmlc13_tags vals_wmlc12_tags
734 /* Same as WML 1.1 */
735
736 /*******************************************
737  *       WML 1.3 - Attribute Start         *
738  *******************************************/
739 static const value_string vals_wmlc13_attrStart[] = {
740         /* 0x00 -- 0x04 GLOBAL */
741         { 0x05, "accept-charset=" },
742         { 0x06, "align='bottom'" },
743         { 0x07, "align='center'" },
744         { 0x08, "align='left'" },
745         { 0x09, "align='middle'" },
746         { 0x0A, "align='right'" },
747         { 0x0B, "align='top'" },
748         { 0x0C, "alt=" },
749         { 0x0D, "content=" },
750         /* 0x0E */
751         { 0x0F, "domain=" },
752         { 0x10, "emptyok='false'" },
753         { 0x11, "emptyok='true'" },
754         { 0x12, "format=" },
755         { 0x13, "height=" },
756         { 0x14, "hspace=" },
757         { 0x15, "ivalue=" },
758         { 0x16, "iname=" },
759         /* 0x17 */
760         { 0x18, "label=" },
761         { 0x19, "localsrc=" },
762         { 0x1A, "maxlength=" },
763         { 0x1B, "method='get'" },
764         { 0x1C, "method='post'" },
765         { 0x1D, "mode='nowrap'" },
766         { 0x1E, "mode='wrap'" },
767         { 0x1F, "multiple='false'" },
768         { 0x20, "multiple='true'" },
769         { 0x21, "name=" },
770         { 0x22, "newcontext='false'" },
771         { 0x23, "newcontext='true'" },
772         { 0x24, "onpick=" },
773         { 0x25, "onenterbackward=" },
774         { 0x26, "onenterforward=" },
775         { 0x27, "ontimer=" },
776         { 0x28, "optional='false'" },
777         { 0x29, "optional='true'" },
778         { 0x2A, "path=" },
779         /* 0x2B -- 0x2D */
780         { 0x2E, "scheme=" },
781         { 0x2F, "sendreferer='false'" },
782         { 0x30, "sendreferer='true'" },
783         { 0x31, "size=" },
784         { 0x32, "src=" },
785         { 0x33, "ordered='false'" },
786         { 0x34, "ordered='true'" },
787         { 0x35, "tabindex=" },
788         { 0x36, "title=" },
789         { 0x37, "type=" },
790         { 0x38, "type='accept'" },
791         { 0x39, "type='delete'" },
792         { 0x3A, "type='help'" },
793         { 0x3B, "type='password'" },
794         { 0x3C, "type='onpick'" },
795         { 0x3D, "type='onenterbackward'" },
796         { 0x3E, "type='onenterforward'" },
797         { 0x3F, "type='ontimer'" },
798         /* 0x40 -- 0x44 GLOBAL */
799         { 0x45, "type='options'" },
800         { 0x46, "type='prev'" },
801         { 0x47, "type='reset'" },
802         { 0x48, "type='text'" },
803         { 0x49, "type='vnd.'" },
804         { 0x4A, "href=" },
805         { 0x4B, "href='http://'" },
806         { 0x4C, "href='https://'" },
807         { 0x4D, "value=" },
808         { 0x4E, "vspace=" },
809         { 0x4F, "width=" },
810         { 0x50, "xml:lang=" },
811         /* 0x51 */
812         { 0x52, "align=" },
813         { 0x53, "columns=" },
814         { 0x54, "class=" },
815         { 0x55, "id=" },
816         { 0x56, "forua='false'" },
817         { 0x57, "forua='true'" },
818         { 0x58, "src='http://'" },
819         { 0x59, "src='https://'" },
820         { 0x5A, "http-equiv=" },
821         { 0x5B, "http-equiv='Content-Type'" },
822         { 0x5C, "content='application/vnd.wap.wmlc;charset='" },
823         { 0x5D, "http-equiv='Expires'" },
824         { 0x5E, "accesskey=" },
825         { 0x5F, "enctype=" },
826         { 0x60, "enctype='application/x-www-form-urlencoded'" },
827         { 0x61, "enctype='multipart/form-data'" },
828         { 0x62, "xml:space='preserve'" },
829         { 0x63, "xml:space='default'" },
830         { 0x64, "cache-control='no-cache'" },
831
832         { 0x00, NULL }
833 };
834
835 /*******************************************
836  *       WML 1.3 - Attribute Value         *
837  *******************************************/
838 #define vals_wmlc13_attrValue vals_wmlc11_attrValue
839 /* Same as WML 1.1 */
840
841
842 /****************************************************************************/
843
844 /*******************************************
845  *      SI 1.0 - Global tokens (EXT)       *
846  *******************************************/
847 static const value_string vals_sic10_global[] = {
848         { 0x00, NULL }
849 };
850
851
852 /*******************************************
853  *           SI 1.0 - Tags                 *
854  *******************************************/
855 static const value_string vals_sic10_tags[] = {
856         /* 0x00 -- 0x04 GLOBAL */
857         { 0x05, "si" },
858         { 0x06, "indication" },
859         { 0x07, "info" },
860         { 0x08, "item" },
861
862         { 0x00, NULL }
863 };
864
865 /*******************************************
866  *        SI 1.0 - Attribute Start         *
867  *******************************************/
868 static const value_string vals_sic10_attrStart[] = {
869         /* 0x00 -- 0x04 GLOBAL */
870         { 0x05, "action='signal-none'" },
871         { 0x06, "action='signal-low'" },
872         { 0x07, "action='signal-medium'" },
873         { 0x08, "action='signal-high'" },
874         { 0x09, "action='delete'" },
875         { 0x0a, "created=" },
876         { 0x0b, "href=" },
877         { 0x0c, "href='http://'" },
878         { 0x0d, "href='http://www.'" },
879         { 0x0e, "href='https://'" },
880         { 0x0f, "href='https://www.'" },
881         { 0x10, "si-expires=" },
882         { 0x11, "si-id=" },
883         { 0x12, "class=" },
884
885         { 0x00, NULL }
886 };
887
888 /*******************************************
889  *        SI 1.0 - Attribute Value         *
890  *******************************************/
891 static const value_string vals_sic10_attrValue[] = {
892         /* 0x80 -- 0x84 GLOBAL */
893         { 0x85, "'.com/'" },
894         { 0x86, "'.edu/'" },
895         { 0x87, "'.net/'" },
896         { 0x88, "'.org/'" },
897
898         { 0x00, NULL }
899 };
900
901 /****************************************************************************/
902
903
904 /*******************************************
905  *      SL 1.0 - Global tokens (EXT)       *
906  *******************************************/
907 static const value_string vals_slc10_global[] = {
908         { 0x00, NULL }
909 };
910
911
912 /*******************************************
913  *           SL 1.0 - Tags                 *
914  *******************************************/
915 static const value_string vals_slc10_tags[] = {
916         /* 0x00 -- 0x04 GLOBAL */
917         { 0x05, "sl" },
918
919         { 0x00, NULL }
920 };
921
922 /*******************************************
923  *        SL 1.0 - Attribute Start         *
924  *******************************************/
925 static const value_string vals_slc10_attrStart[] = {
926         /* 0x00 -- 0x04 GLOBAL */
927         { 0x05, "action='execute-low'" },
928         { 0x06, "action='execute-high'" },
929         { 0x07, "action='cache'" },
930         { 0x08, "href=" },
931         { 0x09, "href='http://'" },
932         { 0x0a, "href='http://www.'" },
933         { 0x0b, "href='https://'" },
934         { 0x0c, "href='https://www.'" },
935
936         { 0x00, NULL }
937 };
938
939 /*******************************************
940  *        SL 1.0 - Attribute Value         *
941  *******************************************/
942 static const value_string vals_slc10_attrValue[] = {
943         /* 0x80 -- 0x84 GLOBAL */
944         { 0x85, "'.com/'" },
945         { 0x86, "'.edu/'" },
946         { 0x87, "'.net/'" },
947         { 0x88, "'.org/'" },
948
949         { 0x00, NULL }
950 };
951
952 /****************************************************************************/
953
954
955 /*******************************************
956  *      CO 1.0 - Global tokens (EXT)       *
957  *******************************************/
958 static const value_string vals_coc10_global[] = {
959         { 0x00, NULL }
960 };
961
962
963 /*******************************************
964  *           CO 1.0 - Tags                 *
965  *******************************************/
966 static const value_string vals_coc10_tags[] = {
967         /* 0x00 -- 0x04 GLOBAL */
968         { 0x05, "co" },
969         { 0x06, "invalidate-object" },
970         { 0x07, "invalidate-service" },
971
972         { 0x00, NULL }
973 };
974
975 /*******************************************
976  *        CO 1.0 - Attribute Start         *
977  *******************************************/
978 static const value_string vals_coc10_attrStart[] = {
979         /* 0x00 -- 0x04 GLOBAL */
980         { 0x05, "uri=" },
981         { 0x06, "uri='http://'" },
982         { 0x07, "uri='http://www.'" },
983         { 0x08, "uri='https://'" },
984         { 0x09, "uri='https://www.'" },
985
986         { 0x00, NULL }
987 };
988
989 /*******************************************
990  *        CO 1.0 - Attribute Value         *
991  *******************************************/
992 static const value_string vals_coc10_attrValue[] = {
993         /* 0x80 -- 0x84 GLOBAL */
994         { 0x85, "'.com/'" },
995         { 0x86, "'.edu/'" },
996         { 0x87, "'.net/'" },
997         { 0x88, "'.org/'" },
998
999         { 0x00, NULL }
1000 };
1001
1002
1003 /****************************************************************************/
1004
1005
1006 /*******************************************
1007  *      PROV 1.0 - Global tokens (EXT)       *
1008  *******************************************/
1009 static const value_string vals_provc10_global[] = {
1010         { 0x00, NULL }
1011 };
1012
1013
1014 /*******************************************
1015  *           PROV 1.0 - Tags                 *
1016  *******************************************/
1017 static const value_string vals_provc10_tags[] = {
1018         /* 0x00 -- 0x04 GLOBAL */
1019         { 0x05, "wap-provisioningdoc" },
1020         { 0x06, "characteristic" },
1021         { 0x07, "parm" },
1022
1023         { 0x00, NULL }
1024 };
1025
1026 /*******************************************
1027  *        PROV 1.0 - Attribute Start         *
1028  *******************************************/
1029 static const value_string vals_provc10_attrStart[] = {
1030         /* 0x00 -- 0x04 GLOBAL */
1031         { 0x05, "name=" },
1032         { 0x06, "value=" },
1033         { 0x07, "name='NAME'" },
1034         { 0x08, "name='NAP-ADDRESS'" },
1035         { 0x09, "name='NAP-ADDRTYPE'" },
1036         { 0x0A, "name='CALLTYPE'" },
1037         { 0x0B, "name='VALIDUNTIL'" },
1038         { 0x0C, "name='AUTHTYPE'" },
1039         { 0x0D, "name='AUTHNAME'" },
1040         { 0x0E, "name='AUTHSECRET'" },
1041         { 0x0F, "name='LINGER'" },
1042         { 0x10, "name='BEARER'" },
1043         { 0x11, "name='NAPID'" },
1044         { 0x12, "name='COUNTRY'" },
1045         { 0x13, "name='NETWORK'" },
1046         { 0x14, "name='INTERNET'" },
1047         { 0x15, "name='PROXY-ID'" },
1048         { 0x16, "name='PROXY-PROVIDER-ID'" },
1049         { 0x17, "name='DOMAIN'" },
1050         { 0x18, "name='PROVURL'" },
1051         { 0x19, "name='PXAUTH-TYPE'" },
1052         { 0x1A, "name='PXAUTH-ID'" },
1053         { 0x1B, "name='PXAUTH-PW'" },
1054         { 0x1C, "name='STARTPAGE'" },
1055         { 0x1D, "name='BASAUTH-ID'" },
1056         { 0x1E, "name='BASAUTH-PW'" },
1057         { 0x1F, "name='PUSHENABLED'" },
1058         { 0x20, "name='PXADDR'" },
1059         { 0x21, "name='PXADDRTYPE'" },
1060         { 0x22, "name='TO-NAPID'" },
1061         { 0x23, "name='PORTNBR'" },
1062         { 0x24, "name='SERVICE'" },
1063         { 0x25, "name='LINKSPEED'" },
1064         { 0x26, "name='DNLINKSPEED'" },
1065         { 0x27, "name='LOCAL-ADDR'" },
1066         { 0x28, "name='LOCAL-ADDRTYPE'" },
1067         { 0x29, "name='CONTEXT-ALLOW'" },
1068         { 0x2A, "name='TRUST'" },
1069         { 0x2B, "name='MASTER'" },
1070         { 0x2C, "name='SID'" },
1071         { 0x2D, "name='SOC'" },
1072         { 0x2E, "name='WSP-VERSION'" },
1073         { 0x2F, "name='PHYSICAL-PROXY-ID'" },
1074         { 0x30, "name='CLIENT-ID'" },
1075         { 0x31, "name='DELIVERY-ERR-SDU'" },
1076         { 0x32, "name='DELIVERY-ORDER'" },
1077         { 0x33, "name='TRAFFIC-CLASS'" },
1078         { 0x34, "name='MAX-SDU-SIZE'" },
1079         { 0x35, "name='MAX-BITRATE-UPLINK'" },
1080         { 0x36, "name='MAX-BITRATE-DNLINK'" },
1081         { 0x37, "name='RESIDUAL-BER'" },
1082         { 0x38, "name='SDU-ERROR-RATIO'" },
1083         { 0x39, "name='TRAFFIC-HANDL-PRIO'" },
1084         { 0x3A, "name='TRANSFER-DELAY'" },
1085         { 0x3B, "name='GUARANTEED-BITRATE-UPLINK'" },
1086         { 0x3C, "name='GUARANTEED-BITRATE-DNLINK'" },
1087         /* 0x3D -- 0x3F */
1088         /* 0x40 -- 0x44 GLOBAL */
1089         { 0x45, "version=" },
1090         { 0x46, "version='1.0'" },
1091         /* 0x47 -- 0x4F */
1092         { 0x50, "type=" },
1093         { 0x51, "type='PXLOGICAL'" },
1094         { 0x52, "type='PXPHYSICAL'" },
1095         { 0x53, "type='PORT'" },
1096         { 0x54, "type='VALIDITY'" },
1097         { 0x55, "type='NAPDEF'" },
1098         { 0x56, "type='BOOTSTRAP'" },
1099         { 0x57, "type='VENDORCONFIG'" },
1100         { 0x58, "type='CLIENTIDENTITY'" },
1101         { 0x59, "type='PXAUTHINFO'" },
1102         { 0x5A, "type='NAPAUTHINFO'" },
1103
1104         { 0x00, NULL }
1105 };
1106
1107 /*******************************************
1108  *        PROV 1.0 - Attribute Value         *
1109  *******************************************/
1110 static const value_string vals_provc10_attrValue[] = {
1111         /* 0x80 -- 0x84 GLOBAL */
1112         { 0x85, "IPV4" },
1113         { 0x86, "IPV6" },
1114         { 0x87, "E164" },
1115         { 0x88, "ALPHA" },
1116         { 0x89, "APN" },
1117         { 0x8A, "SCODE" },
1118         { 0x8B, "TETRA-ITSI" },
1119         { 0x8C, "MAN" },
1120         /* 0x8D -- 0x8F */
1121         { 0x90, "ANALOG-MODEM" },
1122         { 0x91, "V.120" },
1123         { 0x92, "V.110" },
1124         { 0x93, "X.31" },
1125         { 0x94, "BIT-TRANSPARENT" },
1126         { 0x95, "DIRECT-ASYNCHRONOUS-DATA-SERVICE" },
1127         /* 0x96 -- 0x99 */
1128         { 0x9A, "PAP" },
1129         { 0x9B, "CHAP" },
1130         { 0x9C, "HTTP-BASIC" },
1131         { 0x9D, "HTTP-DIGEST" },
1132         { 0x9E, "WTLS-SS" },
1133         /* 0x9F -- 0xA1 */
1134         { 0xA2, "GSM-USSD" },
1135         { 0xA3, "GSM-SMS" },
1136         { 0xA4, "ANSI-136-GUTS" },
1137         { 0xA5, "IS-95-CDMA-SMS" },
1138         { 0xA6, "IS-95-CDMA-CSD" },
1139         { 0xA7, "IS-95-CDMA-PACKET" },
1140         { 0xA8, "ANSI-136-CSD" },
1141         { 0xA9, "ANSI-136-GPRS" },
1142         { 0xAA, "GSM-CSD" },
1143         { 0xAB, "GSM-GPRS" },
1144         { 0xAC, "AMPS-CDPD" },
1145         { 0xAD, "PDC-CSD" },
1146         { 0xAE, "PDC-PACKET" },
1147         { 0xAF, "IDEN-SMS" },
1148         { 0xB0, "IDEN-CSD" },
1149         { 0xB1, "IDEN-PACKET" },
1150         { 0xB2, "FLEX/REFLEX" },
1151         { 0xB3, "PHS-SMS" },
1152         { 0xB4, "PHS-CSD" },
1153         { 0xB5, "TETRA-SDS" },
1154         { 0xB6, "TETRA-PACKET" },
1155         { 0xB7, "ANSI-136-GHOST" },
1156         { 0xB8, "MOBITEX-MPAK" },
1157         /* 0xB9 -- 0xBF */
1158         /* 0xC0 -- 0xC4 GLOBAL */
1159         { 0xC5, "AUTOBAUDING" },
1160         /* 0xC6 -- 0xC9 */
1161         { 0xCA, "CL-WSP" },
1162         { 0xCB, "CO-WSP" },
1163         { 0xCC, "CL-SEC-WSP" },
1164         { 0xCD, "CO-SEC-WSP" },
1165         { 0xCE, "CL-SEC-WTA" },
1166         { 0xCF, "CO-SEC-WTA" },
1167
1168         { 0x00, NULL }
1169 };
1170
1171
1172 /****************************************************************************/
1173
1174
1175
1176 /* The struct object contains references to objects defined above!
1177  */
1178
1179 typedef struct {
1180         const guint8 defined;
1181         const value_string *global;
1182         const value_string *tags;
1183         const value_string *attrStart;
1184         const value_string *attrValue;
1185 } wbxml_mapping_table;
1186
1187 /* BEWARE: values 0 and 1 are not defined, so we start from 2
1188  */
1189 static const wbxml_mapping_table wbxml_map[] = {
1190         { /* 0x00 = literal public identifier */
1191                 FALSE, NULL, NULL, NULL, NULL
1192         },
1193         { /* 0x01 = Unknown or missing public identifier */
1194                 FALSE, NULL, NULL, NULL, NULL
1195         },
1196         { /* 0x02 = WML 1.0 */
1197                 TRUE, vals_wmlc10_global, vals_wmlc10_tags,
1198                 vals_wmlc10_attrStart, vals_wmlc10_attrValue
1199         },
1200         { /* 0x03 = WTA 1.0 - Deprecated */
1201                 FALSE, NULL, NULL, NULL, NULL
1202         },
1203         { /* 0x04 = WML 1.1 */
1204                 TRUE, vals_wmlc11_global, vals_wmlc11_tags,
1205                 vals_wmlc11_attrStart, vals_wmlc11_attrValue
1206         },
1207         { /* 0x05 = SI 1.0 */
1208                 TRUE, vals_sic10_global, vals_sic10_tags,
1209                 vals_sic10_attrStart, vals_sic10_attrValue
1210         },
1211         { /* 0x06 = SL 1.0 */
1212                 TRUE, vals_slc10_global, vals_slc10_tags,
1213                 vals_slc10_attrStart, vals_slc10_attrValue
1214         },
1215         { /* 0x07 = CO 1.0 */
1216                 TRUE, vals_coc10_global, vals_coc10_tags,
1217                 vals_coc10_attrStart, vals_coc10_attrValue
1218         },
1219         { /* 0x08 = CHANNEL 1.0 */
1220                 FALSE, NULL, NULL, NULL, NULL
1221         },
1222         { /* 0x09 = WML 1.2 */
1223                 TRUE, vals_wmlc12_global, vals_wmlc12_tags,
1224                 vals_wmlc12_attrStart, vals_wmlc12_attrValue
1225         },
1226         { /* 0x0A = WML 1.3 */
1227                 TRUE, vals_wmlc13_global, vals_wmlc13_tags,
1228                 vals_wmlc13_attrStart, vals_wmlc13_attrValue
1229         },
1230         { /* 0x0B = PROV 1.0 */
1231                 TRUE, vals_provc10_global, vals_provc10_tags,
1232                 vals_provc10_attrStart, vals_provc10_attrValue
1233         },
1234         { /* 0x0C = WTA-WML 1.2 */
1235                 FALSE, NULL, NULL, NULL, NULL
1236         },
1237         { /* 0x0D = EMN 1.0 */
1238                 FALSE, NULL, NULL, NULL, NULL
1239         },
1240         { /* 0x0E = DRMREL 1.0 */
1241                 FALSE, NULL, NULL, NULL, NULL
1242         },
1243 };
1244 /* Update the entry below when the table above is appended */
1245 #define WBXML_MAP_MAX_ID 0x0E
1246
1247
1248
1249
1250 /************************** Function prototypes **************************/
1251
1252
1253
1254 static void
1255 dissect_wbxml(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
1256
1257
1258 void
1259 proto_register_wbxml(void);
1260
1261
1262 /* Parse and display the WBXML string table
1263  */
1264 static void
1265 show_wbxml_string_table (proto_tree *tree, tvbuff_t *tvb, guint32 str_tbl,
1266                 guint32 str_tbl_len);
1267
1268
1269 /* Return a pointer to the string in the string table.
1270  * Can also be hacked for inline string retrieval.
1271  */
1272 static const char*
1273 strtbl_lookup (tvbuff_t *tvb, guint32 str_tbl, guint32 offset, guint32 *len);
1274
1275
1276 /* Parse data while in STAG state
1277  */
1278 static void
1279 parse_wbxml_tag (proto_tree *tree, tvbuff_t *tvb, guint32 offset,
1280                 guint32 str_tbl, guint8 *level,
1281                 guint8 *codepage_stag, guint8 *codepage_attr, guint32 *parsed_length);
1282
1283
1284 /* Parse data while in STAG state;
1285  * interpret tokens as defined by content type
1286  */
1287 static void
1288 parse_wbxml_tag_defined (proto_tree *tree, tvbuff_t *tvb, guint32 offset,
1289                 guint32 str_tbl, guint8 *level,
1290                 guint8 *codepage_stag, guint8 *codepage_attr, guint32 *parsed_length,
1291                 const wbxml_mapping_table *map);
1292
1293
1294 /* Parse data while in ATTR state
1295  */
1296 static void
1297 parse_wbxml_attribute_list (proto_tree *tree, tvbuff_t *tvb,
1298                 guint32 offset, guint32 str_tbl, guint8 level,
1299                 guint8 *codepage_attr, guint32 *parsed_length);
1300
1301
1302 /* Parse data while in ATTR state;
1303  * interpret tokens as defined by content type
1304  */
1305 static void
1306 parse_wbxml_attribute_list_defined (proto_tree *tree, tvbuff_t *tvb,
1307                 guint32 offset, guint32 str_tbl, guint8 level,
1308                 guint8 *codepage_attr, guint32 *parsed_length,
1309                 const wbxml_mapping_table *map);
1310
1311
1312
1313
1314 /****************** WBXML protocol dissection functions ******************/
1315
1316
1317
1318
1319 /* Code to actually dissect the packets */
1320 static void
1321 dissect_wbxml(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1322 {
1323
1324 /* Set up structures needed to add the protocol subtree and manage it */
1325         proto_item *ti;
1326         proto_tree *wbxml_tree; /* Main WBXML tree */
1327         proto_tree *wbxml_str_tbl_tree; /* String table subtree */
1328         proto_tree *wbxml_content_tree; /* Content subtree */
1329         guint8 version;
1330         guint offset = 0;
1331         const char *token;
1332         guint32 len;
1333         guint32 charset=0;
1334         guint32 charset_len;
1335         guint32 publicid;
1336         guint32 publicid_index = 0;
1337         guint32 publicid_len;
1338         guint32 str_tbl;
1339         guint32 str_tbl_len;
1340         guint8 level = 0; /* WBXML recursion level */
1341         guint8 codepage_stag = 0; /* Initial codepage in state = STAG */
1342         guint8 codepage_attr = 0; /* Initial codepage in state = ATTR */
1343
1344         /* WBXML format
1345          * 
1346          * Version 1.0: version publicid         strtbl BODY
1347          * Version 1.x: version publicid charset strtbl BODY
1348          *
1349          * Last valid format: WBXML 1.3
1350          */
1351         switch ( version = tvb_get_guint8 (tvb, 0) ) {
1352                 case 0x00: /* WBXML/1.0 */
1353                         break;
1354
1355                 case 0x01: /* WBXML/1.1 */
1356                 case 0x02: /* WBXML/1.2 */
1357                 case 0x03: /* WBXML/1.3 */
1358                         break;
1359
1360                 default:
1361                         return;
1362         }
1363
1364         if (check_col(pinfo->cinfo, COL_INFO))
1365                 col_append_fstr(pinfo->cinfo, COL_INFO, " (WBXML %s:",
1366                                 match_strval (version, vals_wbxml_versions));
1367
1368         /* In the interest of speed, if "tree" is NULL, don't do any work not
1369            necessary to generate protocol tree items. */
1370         if ( tree ) {
1371                 /* create display subtree for the protocol */
1372                 ti = proto_tree_add_item (tree, proto_wbxml, tvb, 0, -1, FALSE);
1373                 wbxml_tree = proto_item_add_subtree(ti, ett_wbxml);
1374
1375                 /* WBXML Version */
1376                 proto_tree_add_uint (wbxml_tree, hf_wbxml_version,
1377                                 tvb, 0, 1, version);
1378
1379                 /* Public ID */
1380                 publicid = tvb_get_guintvar(tvb, 1, &publicid_len);
1381                 if (publicid) { /* Known Public ID */
1382                         if (check_col(pinfo->cinfo, COL_INFO))
1383                                 col_append_fstr(pinfo->cinfo, COL_INFO, " Public ID \"%s\")",
1384                                                 match_strval (publicid, vals_wbxml_public_ids));
1385                         proto_tree_add_uint(wbxml_tree, hf_wbxml_public_id_known,
1386                                         tvb, 1, publicid_len, publicid);
1387                 } else { /* Public identifier in string table */
1388                         publicid_index = tvb_get_guintvar (tvb, 1+publicid_len, &len);
1389                         publicid_len += len;
1390                 }
1391                 offset = 1 + publicid_len;
1392
1393                 /* Version-specific handling of Charset */
1394                 switch ( version ) {
1395                         case 0x00: /* WBXML/1.0 */
1396                                 /* No charset */
1397                                 break;
1398
1399                         case 0x01: /* WBXML/1.1 */
1400                         case 0x02: /* WBXML/1.2 */
1401                         case 0x03: /* WBXML/1.3 */
1402                                 /* Get charset */
1403                                 charset = tvb_get_guintvar (tvb, offset, &charset_len);
1404                                 offset += charset_len;
1405                                 break;
1406
1407                         default: /* Impossible since return already earlier */
1408                                 break;
1409                 }
1410
1411                 /* String table: read string table length in bytes */
1412                 str_tbl_len = tvb_get_guintvar (tvb, offset, &len);
1413                 str_tbl = offset + len; /* Start of 1st string in string table */
1414
1415
1416                 /* Now we can add public ID, charset (if available),
1417                  * and string table */
1418                 if ( ! publicid ) { /* Read Public ID from string table */
1419                         token = strtbl_lookup (tvb, str_tbl, publicid_index, NULL);
1420                         if (check_col(pinfo->cinfo, COL_INFO))
1421                                 col_append_fstr(pinfo->cinfo, COL_INFO, " Public ID \"%s\")",
1422                                                 token);
1423                         proto_tree_add_string (wbxml_tree, hf_wbxml_public_id_literal,
1424                                         tvb, 1, publicid_len, token?token:"[NULL STRING]");
1425                 }
1426                 if ( version ) { /* Charset */
1427                         proto_tree_add_uint (wbxml_tree, hf_wbxml_charset,
1428                                         tvb, 1+publicid_len, charset_len, charset);
1429                 }
1430                 /* String Table */
1431                 ti = proto_tree_add_text(wbxml_tree,
1432                                 tvb, offset, len + str_tbl_len, "String table: %u bytes",
1433                                 str_tbl_len);
1434
1435                 if (wbxml_tree && str_tbl_len) { /* Display string table as subtree */
1436                         wbxml_str_tbl_tree = proto_item_add_subtree (ti,
1437                                         ett_wbxml_str_tbl);
1438                         show_wbxml_string_table (wbxml_str_tbl_tree, tvb,
1439                                         str_tbl, str_tbl_len);
1440                 }
1441
1442                 /* Data starts HERE */
1443                 offset += len + str_tbl_len;
1444
1445                 /* The WBXML BODY starts here */
1446                 ti = proto_tree_add_text (wbxml_tree, tvb, offset, -1,
1447                                 "Data representation");
1448                 wbxml_content_tree = proto_item_add_subtree (ti, ett_wbxml_content);
1449
1450                 /* The parse_wbxml_X() functions will process the content correctly,
1451                  * irrespective of the WBXML version used. For the WBXML body, this
1452                  * means that there is a different processing for the global token
1453                  * RESERVED_2 (WBXML 1.0) or OPAQUE (WBXML 1.x with x > 0).
1454                  */
1455                 if (wbxml_tree) { /* Show only if visible */
1456                         if (publicid) {
1457 #ifdef DEBUG
1458                                 printf ("WBXML - Content Type : \"%s\"\n",
1459                                                 match_strval (publicid, vals_wbxml_public_ids));
1460 #endif
1461                                 /* Look in wbxml_map[] table for defined mapping */
1462                                 if (publicid < WBXML_MAP_MAX_ID) {
1463                                         if (wbxml_map[publicid].defined) {
1464                                                 proto_tree_add_text (wbxml_content_tree, tvb,
1465                                                                 offset, -1,
1466                                                                 "Level | State "
1467                                                                 "| WBXML Token Description         "
1468                                                                 "| Rendering");
1469                                                 parse_wbxml_tag_defined (wbxml_content_tree,
1470                                                                 tvb, offset, str_tbl, &level,
1471                                                                 &codepage_stag, &codepage_attr, &len,
1472                                                                 wbxml_map + publicid);
1473                                                 return;
1474                                         }
1475                                         proto_tree_add_text (wbxml_content_tree, tvb,
1476                                                         offset, -1,
1477                                                         "Rendering of this content type"
1478                                                         " not (yet) supported");
1479                                 }
1480                         }
1481                         /* Default: WBXML only, no interpretation of the content */
1482                         proto_tree_add_text (wbxml_content_tree, tvb, offset, -1,
1483                                         "Level | State | WBXML Token Description         "
1484                                         "| Rendering");
1485                         parse_wbxml_tag (wbxml_content_tree, tvb, offset,
1486                                         str_tbl, &level,
1487                                         &codepage_stag, &codepage_attr, &len);
1488                         return;
1489                 } else {
1490                         proto_tree_add_text (wbxml_content_tree, tvb, offset, -1,
1491                                         "WBXML 1.0 decoding not yet supported");
1492                 }
1493                 return;
1494         }
1495 }
1496
1497
1498
1499
1500 /* Return a pointer to the string in the string table.
1501  * Can also be hacked for inline string retrieval.
1502  */
1503 static const char*
1504 strtbl_lookup (tvbuff_t *tvb, guint32 str_tbl, guint32 offset, guint32 *len)
1505 {
1506         if (len) { /* The "hack" call for inline string reading */
1507                 *len = tvb_strsize (tvb, str_tbl+offset);
1508                 return tvb_get_ptr (tvb, str_tbl+offset, *len);
1509         } else { /* Normal string table reading */
1510                 return tvb_get_ptr (tvb, str_tbl+offset,
1511                                 tvb_strsize (tvb, str_tbl+offset));
1512         }
1513 }
1514
1515
1516
1517
1518 /* Parse and display the WBXML string table (in a 3-column table format).
1519  * This function displays:
1520  *  - the offset in the string table,
1521  *  - the length of the string
1522  *  - the string.
1523  */
1524 static void
1525 show_wbxml_string_table (proto_tree *tree, tvbuff_t *tvb, guint32 str_tbl,
1526                 guint32 str_tbl_len)
1527 {
1528         guint32 off = str_tbl;
1529         guint32 len = 0;
1530         guint32 end = str_tbl + str_tbl_len;
1531         const char *str;
1532
1533         proto_tree_add_text (tree, tvb, off, end,
1534                         "Start  | Length | String");
1535         while (off < end) {
1536                 /* Hack the string table lookup function */
1537                 str = strtbl_lookup (tvb, off, 0, &len);
1538                 proto_tree_add_text (tree, tvb, off, len,
1539                                 "%6d | %6d | '%s'",
1540                                 off - str_tbl, len, str);
1541                 off += len;
1542         }
1543 }
1544
1545
1546
1547
1548 /* Indentation code is based on a static const array of space characters.
1549  * At least one single space is returned */
1550 static const char indent_buffer[514] = " "
1551         "                                                                "
1552         "                                                                "
1553         "                                                                "
1554         "                                                                "
1555         "                                                                "
1556         "                                                                "
1557         "                                                                "
1558         "                                                                "
1559         ; /* Generate XML indentation (length = 1 + 2 * 256 + 1 for '\0') */
1560
1561 static const char * Indent (guint8 level) {
1562         return indent_buffer + (512 - 2 * (level));
1563 }
1564
1565
1566
1567
1568 /********************
1569  * WBXML tag tokens *
1570  ********************
1571  * 
1572  * Bit Mask  : Example
1573  * -------------------
1574  * 00.. .... : <tag />
1575  *
1576  * 01.. .... : <tag>
1577  *               CONTENT
1578  *             </tag>
1579  *
1580  * 10.. .... : <tag
1581  *               atrtribute1="value1"
1582  *               atrtribute2="value2"
1583  *             />
1584  * 
1585  * 11.. .... : <tag
1586  *               atrtribute1="value1"
1587  *               atrtribute2="value2"
1588  *             >
1589  *               CONTENT
1590  *             </tag>
1591  *
1592  * NOTE: an XML PI is parsed as an attribute list (same syntax).
1593  */
1594
1595
1596
1597
1598 /* This function parses the WBXML and maps known token interpretations
1599  * to the WBXML tokens. As a result, the original XML document can be
1600  * recreated. Indentation is generated in order to ease reading.
1601  *
1602  * Attribute parsing is done in parse_wbxml_attribute_list_defined().
1603  *
1604  * The wbxml_mapping_table entry *map contains the actual token mapping.
1605  *
1606  * NOTE: In order to parse the content, some recursion is required.
1607  *       However, for performance reasons, recursion has been avoided
1608  *       where possible (tags without content within tags with content).
1609  *       This is achieved by means of the parsing_tag_content and tag_save*
1610  *       variables.
1611  *
1612  * NOTE: Code page switches not yet processed in the code!
1613  *
1614  * NOTE: See above for known token mappings.
1615  */
1616 static void
1617 parse_wbxml_tag_defined (proto_tree *tree, tvbuff_t *tvb, guint32 offset,
1618                 guint32 str_tbl, guint8 *level,
1619                 guint8 *codepage_stag, guint8 *codepage_attr, guint32 *parsed_length,
1620                 const wbxml_mapping_table *map)
1621 {
1622         guint32 tvb_len = tvb_reported_length (tvb);
1623         guint32 off = offset;
1624         guint32 len;
1625         guint32 ent;
1626         guint32 index;
1627         const char* str;
1628         guint8 peek;
1629         guint32 tag_len; /* Length of the index (uintvar) from a LITERAL tag */
1630         guint8 tag_save_known = 0; /* Will contain peek & 0x3F (tag identity) */
1631         guint8 tag_new_known = 0; /* Will contain peek & 0x3F (tag identity) */
1632         const char *tag_save_literal; /* Will contain the LITERAL tag identity */
1633         const char *tag_new_literal; /* Will contain the LITERAL tag identity */
1634         guint8 parsing_tag_content = FALSE; /* Are we parsing content from a
1635                                                                                    tag with content: <x>Content</x>
1636                                                                                    
1637                                                                                    The initial state is FALSE.
1638                                                                                    This state will trigger recursion. */
1639         tag_save_literal = NULL; /* Prevents compiler warning */
1640
1641 #ifdef DEBUG
1642         printf ("WBXML - parse_wbxml_tag_defined (level = %d, offset = %d)\n",
1643                         *level, offset);
1644 #endif
1645         while (off < tvb_len) {
1646                 peek = tvb_get_guint8 (tvb, off);
1647 #ifdef DEBUG
1648                 printf("WBXML - STAG: level = %3d, peek = 0x%02X, off = %d, "
1649                                 "tvb_len = %d\n",
1650                                 *level, peek, off, tvb_len);
1651 #endif
1652                 if ((peek & 0x3F) < 4) switch (peek) { /* Global tokens in state = STAG
1653                                                                                                   but not the LITERAL tokens */
1654                         case 0x00: /* SWITCH_PAGE */
1655                                 peek = tvb_get_guint8 (tvb, off+1);
1656                                 proto_tree_add_text (tree, tvb, off, 2,
1657                                                 "        Tag   | SWITCH_PAGE (Tag code page)     "
1658                                                 "| Code page switch (was: %d, is: %d)",
1659                                                 *codepage_stag, peek);
1660                                 *codepage_stag = peek;
1661                                 off += 2;
1662                                 break;
1663                         case 0x01: /* END: only possible for Tag with Content */
1664                                 if (tag_save_known) {
1665                                         proto_tree_add_text (tree, tvb, off, 1,
1666                                                         "  %3d | Tag   | END (Known Tag 0x%02X)            "
1667                                                         "| %s</%s>",
1668                                                         *level, tag_save_known, Indent (*level),
1669                                                         match_strval (tag_save_known, map->tags));
1670                                 } else { /* Literal TAG */
1671                                         proto_tree_add_text (tree, tvb, off, 1,
1672                                                         "  %3d | Tag   | END (Literal Tag)               "
1673                                                         "| %s</%s>",
1674                                                         *level, Indent (*level), tag_save_literal);
1675                                 }
1676                                 (*level)--;
1677                                 off++;
1678                                 *parsed_length = off - offset;
1679                                 return;
1680                                 break;
1681                         case 0x02: /* ENTITY */
1682                                 ent = tvb_get_guintvar (tvb, off+1, &len);
1683                                 proto_tree_add_text (tree, tvb, off, 1+len,
1684                                                 "  %3d | Tag   | ENTITY                          "
1685                                                 "| %s'&#%u;'",
1686                                                 *level, Indent (*level), ent);
1687                                 off += 1+len;
1688                                 break;
1689                         case 0x03: /* STR_I */
1690                                 /* Hack the string table lookup function */
1691                                 str = strtbl_lookup (tvb, off+1, 0, &len);
1692                                 proto_tree_add_text (tree, tvb, off, 1+len,
1693                                                 "  %3d | Tag   | STR_I (Inline string)           "
1694                                                 "| %s\'%s\'",
1695                                                 *level, Indent(*level), str);
1696                                 off += 1+len;
1697                                 break;
1698                         case 0x40: /* EXT_I_0 */
1699                         case 0x41: /* EXT_I_1 */
1700                         case 0x42: /* EXT_I_2 */
1701                                 /* Extension tokens */
1702                                 /* Hack the string table lookup function */
1703                                 str = strtbl_lookup (tvb, off+1, 0, &len);
1704                                 proto_tree_add_text (tree, tvb, off, 1+len,
1705                                                 "  %3d | Tag   | EXT_I_%1x    (Extension Token)    "
1706                                                 "| %s(%s: \'%s\')",
1707                                                 *level, peek & 0x0f, Indent (*level),
1708                                                 match_strval (peek, map->global), str);
1709                                 off += 1+len;
1710                                 break;
1711                         case 0x43: /* PI */
1712                                 proto_tree_add_text (tree, tvb, off, 1,
1713                                                 "  %3d | Tag   | PI (XML Processing Instruction) "
1714                                                 "| %s<?xml",
1715                                                 *level, Indent (*level));
1716                                 parse_wbxml_attribute_list (tree, tvb, off, str_tbl,
1717                                                 *level, codepage_attr, &len);
1718                                 off += len;
1719                                 proto_tree_add_text (tree, tvb, off-1, 1,
1720                                                 "  %3d | Tag   | END (PI)                        "
1721                                                 "| %s?>",
1722                                                 *level, Indent (*level));
1723                                 break;
1724                         case 0x80: /* EXT_T_0 */
1725                         case 0x81: /* EXT_T_1 */
1726                         case 0x82: /* EXT_T_2 */
1727                                 /* Extension tokens */
1728                                 index = tvb_get_guintvar (tvb, off+1, &len);
1729                                 str = strtbl_lookup (tvb, str_tbl, index, NULL);
1730                                 proto_tree_add_text (tree, tvb, off, 1+len,
1731                                                 "  %3d | Tag   | EXT_T_%1x    (Extension Token)    "
1732                                                 "| %s(%s: \'%s\')",
1733                                                 *level, peek & 0x0f, Indent (*level),
1734                                                 match_strval (peek, map->global), str);
1735                                 off += 1+len;
1736                                 break;
1737                         case 0x83: /* STR_T */
1738                                 index = tvb_get_guintvar (tvb, off+1, &len);
1739                                 str = strtbl_lookup (tvb, str_tbl, index, NULL);
1740                                 proto_tree_add_text (tree, tvb, off, 1+len,
1741                                                 "  %3d | Tag   | STR_T (Tableref string)         "
1742                                                 "| %s\'%s\'",
1743                                                 *level, Indent (*level), str);
1744                                 off += 1+len;
1745                                 break;
1746                         case 0xC0: /* EXT_0 */
1747                         case 0xC1: /* EXT_1 */
1748                         case 0xC2: /* EXT_2 */
1749                                 /* Extension tokens */
1750                                 proto_tree_add_text (tree, tvb, off, 1,
1751                                                 "  %3d | Tag   | EXT_%1x      (Extension Token)    "
1752                                                 "| %s(%s)",
1753                                                 *level, peek & 0x0f, Indent (*level),
1754                                                 match_strval (peek, map->global));
1755                                 off++;
1756                                 break;
1757                         case 0xC3: /* OPAQUE - WBXML 1.1 and newer */
1758                                 if (tvb_get_guint8 (tvb, 0)) { /* WBXML 1.x (x > 0) */
1759                                         index = tvb_get_guintvar (tvb, off+1, &len);
1760                                         proto_tree_add_text (tree, tvb, off, 1 + len + index,
1761                                                         "  %3d | Tag   | OPAQUE (Opaque data)            "
1762                                                         "| %s(%d bytes of opaque data)",
1763                                                         *level, Indent (*level), index);
1764                                         off += 1+len+index;
1765                                 } else { /* WBXML 1.0 - RESERVED_2 token (invalid) */
1766                                         proto_tree_add_text (tree, tvb, off, 1,
1767                                                         "        Tag   | RESERVED_2     (Invalid Token!) "
1768                                                         "| WBXML 1.0 parsing stops here.");
1769                                         /* Stop processing as it is impossible to parse now */
1770                                         off = tvb_len;
1771                                         *parsed_length = off - offset;
1772                                         return;
1773                                 }
1774                                 break;
1775
1776                                 /* No default clause, as all cases have been treated */
1777                 } else { /* LITERAL or Known TAG */
1778                         /*
1779                          * We must store the initial tag, and also retrieve the new tag.
1780                          * 
1781                          * There are 4 possibilities:
1782                          *
1783                          *  1. Known tag followed by a known tag
1784                          *  2. Known tag followed by a LITERAL tag
1785                          *  3. LITERAL tag followed by Known tag
1786                          *  4. LITERAL tag followed by LITERAL tag
1787                          */
1788
1789                         /* Store the new tag */
1790                         tag_len = 0;
1791                         if ((peek & 0x3F) == 4) { /* LITERAL */
1792                                 index = tvb_get_guintvar (tvb, off+1, &tag_len);
1793                                 tag_new_literal = strtbl_lookup (tvb, str_tbl, index, NULL);
1794                                 tag_new_known = 0; /* invalidate known tag_new */
1795                         } else {
1796                                 tag_new_known = peek & 0x3F;
1797                                 tag_new_literal = NULL; /* invalidate LITERAL tag_new */
1798                         }
1799
1800                         /*
1801                          * Parsing of TAG starts HERE
1802                          */
1803                         if (peek & 0x40) { /* Content present */
1804                                 /* Content follows
1805                                  * [!] An explicit END token is expected in these cases!
1806                                  * ==> Recursion possible if we encounter a tag with content;
1807                                  *     recursion will return at the explicit END token.
1808                                  */
1809                                 if (parsing_tag_content) { /* Recurse */
1810 #ifdef DEBUG
1811                                         printf ("WBXML: Tag in Tag - RECURSE! (off = %d)\n",off);
1812 #endif
1813                                         /* Do not process the attribute list:
1814                                          * recursion will take care of it */
1815                                         (*level)++;
1816                                         parse_wbxml_tag_defined (tree, tvb, off, str_tbl, level,
1817                                                         codepage_stag, codepage_attr, &len, map);
1818                                         off += len;
1819                                 } else { /* Now we will have content to parse */
1820                                         /* Save the start tag so we can properly close it later. */
1821                                         if ((peek & 0x3F) == 4) {
1822                                                 tag_save_literal = tag_new_literal;
1823                                                 tag_save_known = 0;
1824                                         } else {
1825                                                 tag_save_known = tag_new_known;
1826                                                 tag_save_literal = NULL;
1827                                         }
1828                                         /* Process the attribute list if present */
1829                                         if (peek & 0x80) { /* Content and Attribute list present */
1830                                                 if (tag_new_known) { /* Known tag */
1831                                                         proto_tree_add_text (tree, tvb, off, 1,
1832                                                                         "  %3d | Tag   "
1833                                                                         "|   Known Tag 0x%02X           (AC) "
1834                                                                         "| %s<%s",
1835                                                                         *level, tag_new_known, Indent (*level),
1836                                                                         match_strval (tag_new_known, map->tags));
1837                                                         off++;
1838                                                 } else { /* LITERAL tag */
1839                                                         proto_tree_add_text (tree, tvb, off, 1,
1840                                                                         "  %3d | Tag   "
1841                                                                         "| LITERAL_AC (Literal tag)   (AC) "
1842                                                                         "| %s<%s",
1843                                                                         *level, Indent (*level), tag_new_literal);
1844                                                         off += 1 + tag_len;
1845                                                 }
1846                                                 parse_wbxml_attribute_list_defined (tree, tvb,
1847                                                                 off, str_tbl,
1848                                                                 *level, codepage_attr, &len, map);
1849                                                 off += len;
1850                                                 proto_tree_add_text (tree, tvb, off-1, 1,
1851                                                                 "  %3d | Tag   "
1852                                                                 "| END (attribute list)            "
1853                                                                 "| %s>",
1854                                                                 *level, Indent (*level));
1855                                         } else { /* Content, no Attribute list */
1856                                                 if (tag_new_known) { /* Known tag */
1857                                                         proto_tree_add_text (tree, tvb, off, 1,
1858                                                                         "  %3d | Tag   "
1859                                                                         "|   Known Tag 0x%02X           (.C) "
1860                                                                         "| %s<%s>",
1861                                                                         *level, tag_new_known, Indent (*level),
1862                                                                         match_strval (tag_new_known, map->tags));
1863                                                         off++;
1864                                                 } else { /* LITERAL tag */
1865                                                         proto_tree_add_text (tree, tvb, off, 1,
1866                                                                         "  %3d | Tag   "
1867                                                                         "| LITERAL_C  (Literal Tag)   (.C) "
1868                                                                         "| %s<%s>",
1869                                                                         *level, Indent (*level), tag_new_literal);
1870                                                         off += 1 + tag_len;
1871                                                 }
1872                                         }
1873                                         /* The data that follows in the parsing process
1874                                          * represents content for the opening tag
1875                                          * we've just processed in the lines above.
1876                                          * Next time we encounter a tag with content: recurse
1877                                          */
1878                                         parsing_tag_content = TRUE;
1879 #ifdef DEBUG
1880                                         printf ("WBXML: Tag in Tag - No recursion this time! "
1881                                                         "(off = %d)\n", off);
1882 #endif
1883                                 }
1884                         } else { /* No Content */
1885 #ifdef DEBUG
1886                                 printf ("WBXML: <Tag/> in Tag - No recursion! "
1887                                                 "(off = %d)\n", off);
1888 #endif
1889                                 (*level)++;
1890                                 if (peek & 0x80) { /* No Content, Attribute list present */
1891                                         if (tag_new_known) { /* Known tag */
1892                                                 proto_tree_add_text (tree, tvb, off, 1,
1893                                                                 "  %3d | Tag   "
1894                                                                 "|   Known Tag 0x%02X           (A.) "
1895                                                                 "| %s<%s",
1896                                                                 *level, tag_new_known, Indent (*level),
1897                                                                 match_strval (tag_new_known, map->tags));
1898                                                 off++;
1899                                                 parse_wbxml_attribute_list_defined (tree, tvb,
1900                                                                 off, str_tbl,
1901                                                                 *level, codepage_attr, &len, map);
1902                                                 off += len;
1903                                                 proto_tree_add_text (tree, tvb, off-1, 1,
1904                                                                 "  %3d | Tag   "
1905                                                                 "| END (Known Tag)                 "
1906                                                                 "| %s/>",
1907                                                                 *level, Indent (*level));
1908                                         } else { /* LITERAL tag */
1909                                                 proto_tree_add_text (tree, tvb, off, 1,
1910                                                                 "  %3d | Tag   "
1911                                                                 "| LITERAL_A  (Literal Tag)   (A.) "
1912                                                                 "| %s<%s",
1913                                                                 *level, Indent (*level), tag_new_literal);
1914                                                 off += 1 + tag_len;
1915                                                 parse_wbxml_attribute_list_defined (tree, tvb,
1916                                                                 off, str_tbl,
1917                                                                 *level, codepage_attr, &len, map);
1918                                                 off += len;
1919                                                 proto_tree_add_text (tree, tvb, off-1, 1,
1920                                                                 "  %3d | Tag   "
1921                                                                 "| END (Literal Tag)               "
1922                                                                 "| %s/>",
1923                                                                 *level, Indent (*level));
1924                                         }
1925                                 } else { /* No Content, No Attribute list */
1926                                         if (tag_new_known) { /* Known tag */
1927                                                 proto_tree_add_text (tree, tvb, off, 1,
1928                                                                 "  %3d | Tag   "
1929                                                                 "|   Known Tag 0x%02x           (..) "
1930                                                                 "| %s<%s />",
1931                                                                 *level, tag_new_known, Indent (*level),
1932                                                                 match_strval (tag_new_known, map->tags));
1933                                                 off++;
1934                                         } else { /* LITERAL tag */
1935                                                 proto_tree_add_text (tree, tvb, off, 1,
1936                                                                 "  %3d | Tag   "
1937                                                                 "| LITERAL    (Literal Tag)   (..) "
1938                                                                 "| %s<%s />",
1939                                                                 *level, Indent (*level), tag_new_literal);
1940                                                 off += 1 + tag_len;
1941                                         }
1942                                 }
1943                                 (*level)--;
1944                         }
1945                 } /* if (tag & 0x3F) >= 5 */
1946         } /* while */
1947 }
1948
1949
1950
1951
1952 /* This function performs the WBXML decoding as in parse_wbxml_tag_defined()
1953  * but this time no WBXML mapping is performed.
1954  *
1955  * Attribute parsing is done in parse_wbxml_attribute_list().
1956  *
1957  * NOTE: Code page switches not yet processed in the code!
1958  */
1959 static void
1960 parse_wbxml_tag (proto_tree *tree, tvbuff_t *tvb, guint32 offset,
1961                 guint32 str_tbl, guint8 *level,
1962                 guint8 *codepage_stag, guint8 *codepage_attr, guint32 *parsed_length)
1963 {
1964         guint32 tvb_len = tvb_reported_length (tvb);
1965         guint32 off = offset;
1966         guint32 len;
1967         guint32 ent;
1968         guint32 index;
1969         const char* str;
1970         guint8 peek;
1971         guint32 tag_len; /* Length of the index (uintvar) from a LITERAL tag */
1972         guint8 tag_save_known = 0; /* Will contain peek & 0x3F (tag identity) */
1973         guint8 tag_new_known = 0; /* Will contain peek & 0x3F (tag identity) */
1974         const char *tag_save_literal; /* Will contain the LITERAL tag identity */
1975         const char *tag_new_literal; /* Will contain the LITERAL tag identity */
1976         guint8 parsing_tag_content = FALSE; /* Are we parsing content from a
1977                                                                                    tag with content: <x>Content</x>
1978                                                                                    
1979                                                                                    The initial state is FALSE.
1980                                                                                    This state will trigger recursion. */
1981         tag_save_literal = NULL; /* Prevents compiler warning */
1982
1983 #ifdef DEBUG
1984         printf ("WBXML - parse_wbxml_tag (level = %d, offset = %d)\n",
1985                         *level, offset);
1986 #endif
1987         while (off < tvb_len) {
1988                 peek = tvb_get_guint8 (tvb, off);
1989 #ifdef DEBUG
1990                 printf("WBXML - STAG: level = %3d, peek = 0x%02X, off = %d, "
1991                                 "tvb_len = %d\n",
1992                                 *level, peek, off, tvb_len);
1993 #endif
1994                 if ((peek & 0x3F) < 4) switch (peek) { /* Global tokens in state = STAG
1995                                                                                                   but not the LITERAL tokens */
1996                         case 0x00: /* SWITCH_PAGE */
1997                                 peek = tvb_get_guint8 (tvb, off+1);
1998                                 proto_tree_add_text (tree, tvb, off, 2,
1999                                                 "        Tag   | SWITCH_PAGE (Tag code page)     "
2000                                                 "| Code page switch (was: %d, is: %d)",
2001                                                 *codepage_stag, peek);
2002                                 *codepage_stag = peek;
2003                                 off += 2;
2004                                 break;
2005                         case 0x01: /* END: only possible for Tag with Content */
2006                                 if (tag_save_known) {
2007                                         proto_tree_add_text (tree, tvb, off, 1,
2008                                                         "  %3d | Tag   | END (Known Tag 0x%02X)            "
2009                                                         "| %s</Tag_0x%02X>",
2010                                                         *level, tag_save_known, Indent (*level),
2011                                                         tag_save_known);
2012                                 } else { /* Literal TAG */
2013                                         proto_tree_add_text (tree, tvb, off, 1,
2014                                                         "  %3d | Tag   | END (Literal Tag)               "
2015                                                         "| %s</%s>",
2016                                                         *level, Indent (*level), tag_save_literal);
2017                                 }
2018                                 (*level)--;
2019                                 off++;
2020                                 *parsed_length = off - offset;
2021                                 return;
2022                                 break;
2023                         case 0x02: /* ENTITY */
2024                                 ent = tvb_get_guintvar (tvb, off+1, &len);
2025                                 proto_tree_add_text (tree, tvb, off, 1+len,
2026                                                 "  %3d | Tag   | ENTITY                          "
2027                                                 "| %s'&#%u;'",
2028                                                 *level, Indent (*level), ent);
2029                                 off += 1+len;
2030                                 break;
2031                         case 0x03: /* STR_I */
2032                                 /* Hack the string table lookup function */
2033                                 str = strtbl_lookup (tvb, off+1, 0, &len);
2034                                 proto_tree_add_text (tree, tvb, off, 1+len,
2035                                                 "  %3d | Tag   | STR_I (Inline string)           "
2036                                                 "| %s\'%s\'",
2037                                                 *level, Indent(*level), str);
2038                                 off += 1+len;
2039                                 break;
2040                         case 0x40: /* EXT_I_0 */
2041                         case 0x41: /* EXT_I_1 */
2042                         case 0x42: /* EXT_I_2 */
2043                                 /* Extension tokens */
2044                                 /* Hack the string table lookup function */
2045                                 str = strtbl_lookup (tvb, off+1, 0, &len);
2046                                 proto_tree_add_text (tree, tvb, off, 1+len,
2047                                                 "  %3d | Tag   | EXT_I_%1x    (Extension Token)    "
2048                                                 "| %s(Inline string extension: \'%s\')",
2049                                                 *level, peek & 0x0f, Indent (*level), str);
2050                                 off += 1+len;
2051                                 break;
2052                         case 0x43: /* PI */
2053                                 proto_tree_add_text (tree, tvb, off, 1,
2054                                                 "  %3d | Tag   | PI (XML Processing Instruction) "
2055                                                 "| %s<?xml",
2056                                                 *level, Indent (*level));
2057                                 parse_wbxml_attribute_list (tree, tvb, off, str_tbl,
2058                                                 *level, codepage_attr, &len);
2059                                 off += len;
2060                                 proto_tree_add_text (tree, tvb, off-1, 1,
2061                                                 "  %3d | Tag   | END (PI)                        "
2062                                                 "| %s?>",
2063                                                 *level, Indent (*level));
2064                                 break;
2065                         case 0x80: /* EXT_T_0 */
2066                         case 0x81: /* EXT_T_1 */
2067                         case 0x82: /* EXT_T_2 */
2068                                 /* Extension tokens */
2069                                 index = tvb_get_guintvar (tvb, off+1, &len);
2070                                 str = strtbl_lookup (tvb, str_tbl, index, NULL);
2071                                 proto_tree_add_text (tree, tvb, off, 1+len,
2072                                                 "  %3d | Tag   | EXT_T_%1x    (Extension Token)    "
2073                                                 "| %s(Tableref string extension: \'%s\')",
2074                                                 *level, peek & 0x0f, Indent (*level), str);
2075                                 off += 1+len;
2076                                 break;
2077                         case 0x83: /* STR_T */
2078                                 index = tvb_get_guintvar (tvb, off+1, &len);
2079                                 str = strtbl_lookup (tvb, str_tbl, index, NULL);
2080                                 proto_tree_add_text (tree, tvb, off, 1+len,
2081                                                 "  %3d | Tag   | STR_T (Tableref string)         "
2082                                                 "| %s\'%s\'",
2083                                                 *level, Indent (*level), str);
2084                                 off += 1+len;
2085                                 break;
2086                         case 0xC0: /* EXT_0 */
2087                         case 0xC1: /* EXT_1 */
2088                         case 0xC2: /* EXT_2 */
2089                                 /* Extension tokens */
2090                                 proto_tree_add_text (tree, tvb, off, 1,
2091                                                 "  %3d | Tag   | EXT_%1x      (Extension Token)    "
2092                                                 "| %s(Single-byte extension)",
2093                                                 *level, peek & 0x0f, Indent (*level));
2094                                 off++;
2095                                 break;
2096                         case 0xC3: /* OPAQUE - WBXML 1.1 and newer */
2097                                 if (tvb_get_guint8 (tvb, 0)) { /* WBXML 1.x (x > 0) */
2098                                         index = tvb_get_guintvar (tvb, off+1, &len);
2099                                         proto_tree_add_text (tree, tvb, off, 1 + len + index,
2100                                                         "  %3d | Tag   | OPAQUE (Opaque data)            "
2101                                                         "| %s(%d bytes of opaque data)",
2102                                                         *level, Indent (*level), index);
2103                                         off += 1+len+index;
2104                                 } else { /* WBXML 1.0 - RESERVED_2 token (invalid) */
2105                                         proto_tree_add_text (tree, tvb, off, 1,
2106                                                         "        Tag   | RESERVED_2     (Invalid Token!) "
2107                                                         "| WBXML 1.0 parsing stops here.");
2108                                         /* Stop processing as it is impossible to parse now */
2109                                         off = tvb_len;
2110                                         *parsed_length = off - offset;
2111                                         return;
2112                                 }
2113                                 break;
2114
2115                                 /* No default clause, as all cases have been treated */
2116                 } else { /* LITERAL or Known TAG */
2117                         /*
2118                          * We must store the initial tag, and also retrieve the new tag.
2119                          * 
2120                          * There are 4 possibilities:
2121                          *
2122                          *  1. Known tag followed by a known tag
2123                          *  2. Known tag followed by a LITERAL tag
2124                          *  3. LITERAL tag followed by Known tag
2125                          *  4. LITERAL tag followed by LITERAL tag
2126                          */
2127
2128                         /* Store the new tag */
2129                         tag_len = 0;
2130                         if ((peek & 0x3F) == 4) { /* LITERAL */
2131                                 index = tvb_get_guintvar (tvb, off+1, &tag_len);
2132                                 tag_new_literal = strtbl_lookup (tvb, str_tbl, index, NULL);
2133                                 tag_new_known = 0; /* invalidate known tag_new */
2134                         } else {
2135                                 tag_new_known = peek & 0x3F;
2136                                 tag_new_literal = NULL; /* invalidate LITERAL tag_new */
2137                         }
2138
2139                         /*
2140                          * Parsing of TAG starts HERE
2141                          */
2142                         if (peek & 0x40) { /* Content present */
2143                                 /* Content follows
2144                                  * [!] An explicit END token is expected in these cases!
2145                                  * ==> Recursion possible if we encounter a tag with content;
2146                                  *     recursion will return at the explicit END token.
2147                                  */
2148                                 if (parsing_tag_content) { /* Recurse */
2149 #ifdef DEBUG
2150                                         printf ("WBXML: Tag in Tag - RECURSE! (off = %d)\n",off);
2151 #endif
2152                                         /* Do not process the attribute list:
2153                                          * recursion will take care of it */
2154                                         (*level)++;
2155                                         parse_wbxml_tag (tree, tvb, off, str_tbl, level,
2156                                                         codepage_stag, codepage_attr, &len);
2157                                         off += len;
2158                                 } else { /* Now we will have content to parse */
2159                                         /* Save the start tag so we can properly close it later. */
2160                                         if ((peek & 0x3F) == 4) {
2161                                                 tag_save_literal = tag_new_literal;
2162                                                 tag_save_known = 0;
2163                                         } else {
2164                                                 tag_save_known = tag_new_known;
2165                                                 tag_save_literal = NULL;
2166                                         }
2167                                         /* Process the attribute list if present */
2168                                         if (peek & 0x80) { /* Content and Attribute list present */
2169                                                 if (tag_new_known) { /* Known tag */
2170                                                         proto_tree_add_text (tree, tvb, off, 1,
2171                                                                         "  %3d | Tag   "
2172                                                                         "|   Known Tag 0x%02X           (AC) "
2173                                                                         "| %s<Tag_0x%02X",
2174                                                                         *level, tag_new_known, Indent (*level),
2175                                                                         tag_new_known);
2176                                                         off++;
2177                                                 } else { /* LITERAL tag */
2178                                                         proto_tree_add_text (tree, tvb, off, 1,
2179                                                                         "  %3d | Tag   "
2180                                                                         "| LITERAL_AC (Literal tag)   (AC) "
2181                                                                         "| %s<%s",
2182                                                                         *level, Indent (*level), tag_new_literal);
2183                                                         off += 1 + tag_len;
2184                                                 }
2185                                                 parse_wbxml_attribute_list (tree, tvb, off, str_tbl,
2186                                                                 *level, codepage_attr, &len);
2187                                                 off += len;
2188                                                 proto_tree_add_text (tree, tvb, off-1, 1,
2189                                                                 "  %3d | Tag   "
2190                                                                 "| END (attribute list)            "
2191                                                                 "| %s>",
2192                                                                 *level, Indent (*level));
2193                                         } else { /* Content, no Attribute list */
2194                                                 if (tag_new_known) { /* Known tag */
2195                                                         proto_tree_add_text (tree, tvb, off, 1,
2196                                                                         "  %3d | Tag   "
2197                                                                         "|   Known Tag 0x%02X           (.C) "
2198                                                                         "| %s<Tag_0x%02X>",
2199                                                                         *level, tag_new_known, Indent (*level),
2200                                                                         tag_new_known);
2201                                                         off++;
2202                                                 } else { /* LITERAL tag */
2203                                                         proto_tree_add_text (tree, tvb, off, 1,
2204                                                                         "  %3d | Tag   "
2205                                                                         "| LITERAL_C  (Literal Tag)   (.C) "
2206                                                                         "| %s<%s>",
2207                                                                         *level, Indent (*level), tag_new_literal);
2208                                                         off += 1 + tag_len;
2209                                                 }
2210                                         }
2211                                         /* The data that follows in the parsing process
2212                                          * represents content for the opening tag
2213                                          * we've just processed in the lines above.
2214                                          * Next time we encounter a tag with content: recurse
2215                                          */
2216                                         parsing_tag_content = TRUE;
2217 #ifdef DEBUG
2218                                         printf ("WBXML: Tag in Tag - No recursion this time! "
2219                                                         "(off = %d)\n", off);
2220 #endif
2221                                 }
2222                         } else { /* No Content */
2223 #ifdef DEBUG
2224                                 printf ("WBXML: <Tag/> in Tag - No recursion! "
2225                                                 "(off = %d)\n", off);
2226 #endif
2227                                 (*level)++;
2228                                 if (peek & 0x80) { /* No Content, Attribute list present */
2229                                         if (tag_new_known) { /* Known tag */
2230                                                 proto_tree_add_text (tree, tvb, off, 1,
2231                                                                 "  %3d | Tag   "
2232                                                                 "|   Known Tag 0x%02X           (A.) "
2233                                                                 "| %s<Tag 0x%02X",
2234                                                                 *level, tag_new_known, Indent (*level),
2235                                                                 tag_new_known);
2236                                                 off++;
2237                                                 parse_wbxml_attribute_list (tree, tvb, off, str_tbl,
2238                                                                 *level, codepage_attr, &len);
2239                                                 off += len;
2240                                                 proto_tree_add_text (tree, tvb, off-1, 1,
2241                                                                 "  %3d | Tag   "
2242                                                                 "| END (Known Tag)                 "
2243                                                                 "| %s/>",
2244                                                                 *level, Indent (*level));
2245                                         } else { /* LITERAL tag */
2246                                                 proto_tree_add_text (tree, tvb, off, 1,
2247                                                                 "  %3d | Tag   "
2248                                                                 "| LITERAL_A  (Literal Tag)   (A.) "
2249                                                                 "| %s<%s",
2250                                                                 *level, Indent (*level), tag_new_literal);
2251                                                 off += 1 + tag_len;
2252                                                 parse_wbxml_attribute_list (tree, tvb, off, str_tbl,
2253                                                                 *level, codepage_attr, &len);
2254                                                 off += len;
2255                                                 proto_tree_add_text (tree, tvb, off-1, 1,
2256                                                                 "  %3d | Tag   "
2257                                                                 "| END (Literal Tag)               "
2258                                                                 "| %s/>",
2259                                                                 *level, Indent (*level));
2260                                         }
2261                                 } else { /* No Content, No Attribute list */
2262                                         if (tag_new_known) { /* Known tag */
2263                                                 proto_tree_add_text (tree, tvb, off, 1,
2264                                                                 "  %3d | Tag   "
2265                                                                 "|   Known Tag 0x%02x           (..) "
2266                                                                 "| %s<Tag_0x%02X />",
2267                                                                 *level, tag_new_known, Indent (*level),
2268                                                                 tag_new_known);
2269                                                 off++;
2270                                         } else { /* LITERAL tag */
2271                                                 proto_tree_add_text (tree, tvb, off, 1,
2272                                                                 "  %3d | Tag   "
2273                                                                 "| LITERAL    (Literal Tag)   (..) "
2274                                                                 "| %s<%s />",
2275                                                                 *level, Indent (*level), tag_new_literal);
2276                                                 off += 1 + tag_len;
2277                                         }
2278                                 }
2279                                 (*level)--;
2280                         }
2281                 } /* if (tag & 0x3F) >= 5 */
2282         } /* while */
2283 }
2284
2285
2286
2287
2288 /**************************
2289  * WBXML Attribute tokens *
2290  **************************
2291  * Bit Mask  : Example
2292  * -------------------
2293  * 0... .... : attr=             (attribute name)
2294  *             href="http://"    (attribute name with start of attribute value)
2295  * 1... .... : "www."            (attribute value, or part of it)
2296  * 
2297  */
2298
2299
2300
2301
2302 /* This function parses the WBXML and maps known token interpretations
2303  * to the WBXML tokens. As a result, the original XML document can be
2304  * recreated. Indentation is generated in order to ease reading.
2305  *
2306  * This function performs attribute list parsing.
2307  * 
2308  * The wbxml_mapping_table entry *map contains the actual token mapping.
2309  *
2310  * NOTE: See above for known token mappings.
2311  *
2312  * NOTE: Code page switches not yet processed in the code!
2313  */
2314 static void
2315 parse_wbxml_attribute_list_defined (proto_tree *tree, tvbuff_t *tvb,
2316                 guint32 offset, guint32 str_tbl, guint8 level,
2317                 guint8 *codepage_attr, guint32 *parsed_length,
2318                 const wbxml_mapping_table *map)
2319 {
2320         guint32 tvb_len = tvb_reported_length (tvb);
2321         guint32 off = offset;
2322         guint32 len;
2323         guint32 ent;
2324         guint32 index;
2325         const char* str;
2326         guint8 peek;
2327
2328 #ifdef DEBUG
2329         printf ("WBXML - parse_wbxml_attr_defined (level = %d, offset = %d)\n",
2330                         level, offset);
2331 #endif
2332         /* Parse attributes */
2333         while (off < tvb_len) {
2334                 peek = tvb_get_guint8 (tvb, off);
2335 #ifdef DEBUG
2336                 printf("WBXML - ATTR: level = %3d, peek = 0x%02X, off = %d, "
2337                                 "tvb_len = %d\n",
2338                                 level, peek, off, tvb_len);
2339 #endif
2340                 if ((peek & 0x3F) < 5) switch (peek) { /* Global tokens
2341                                                                                                   in state = ATTR */
2342                         case 0x00: /* SWITCH_PAGE */
2343                                 peek = tvb_get_guint8 (tvb, off+1);
2344                                 proto_tree_add_text (tree, tvb, off, 2,
2345                                                 "         Attr | SWITCH_PAGE (Attr code page)    "
2346                                                 "| Code page switch (was: %d, is: %d)",
2347                                                 *codepage_attr, peek);
2348                                 *codepage_attr = peek;
2349                                 off += 2;
2350                                 break;
2351                         case 0x01: /* END */
2352                                 /* BEWARE
2353                                  *   The Attribute END token means either ">" or "/>"
2354                                  *   and as a consequence both must be trated separately.
2355                                  *   This is done in the TAG state parser.
2356                                  */
2357                                 off++;
2358                                 *parsed_length = off - offset;
2359                                 return;
2360                         case 0x02: /* ENTITY */
2361                                 ent = tvb_get_guintvar (tvb, off+1, &len);
2362                                 proto_tree_add_text (tree, tvb, off, 1+len,
2363                                                 "  %3d |  Attr | ENTITY                          "
2364                                                 "|     %s'&#%u;'",
2365                                                 level, Indent (level), ent);
2366                                 off += 1+len;
2367                                 break;
2368                         case 0x03: /* STR_I */
2369                                 /* Hack the string table lookup function */
2370                                 str = strtbl_lookup (tvb, off+1, 0, &len);
2371                                 proto_tree_add_text (tree, tvb, off, 1+len,
2372                                                 "  %3d |  Attr | STR_I (Inline string)           "
2373                                                 "|     %s\'%s\'",
2374                                                 level, Indent (level), str);
2375                                 off += 1+len;
2376                                 break;
2377                         case 0x04: /* LITERAL */
2378                                 index = tvb_get_guintvar (tvb, off+1, &len);
2379                                 str = strtbl_lookup (tvb, str_tbl, index, NULL);
2380                                 proto_tree_add_text (tree, tvb, off, 1+len,
2381                                                 "  %3d |  Attr | LITERAL (Literal Attribute)     "
2382                                                 "|   %s<%s />",
2383                                                 level, Indent (level), str);
2384                                 off += 1+len;
2385                                 break;
2386                         case 0x40: /* EXT_I_0 */
2387                         case 0x41: /* EXT_I_1 */
2388                         case 0x42: /* EXT_I_2 */
2389                                 /* Extension tokens */
2390                                 /* Hack the string table lookup function */
2391                                 str = strtbl_lookup (tvb, off+1, 0, &len);
2392                                 proto_tree_add_text (tree, tvb, off, 1+len,
2393                                                 "  %3d |  Attr | EXT_I_%1x    (Extension Token)    "
2394                                                 "|     %s(%s: \'%s\')",
2395                                                 level, peek & 0x0f, Indent (level),
2396                                                 match_strval (peek, map->global), str);
2397                                 off += 1+len;
2398                                 break;
2399                         /* 0x43 impossible in ATTR state */
2400                         /* 0x44 impossible in ATTR state */
2401                         case 0x80: /* EXT_T_0 */
2402                         case 0x81: /* EXT_T_1 */
2403                         case 0x82: /* EXT_T_2 */
2404                                 /* Extension tokens */
2405                                 index = tvb_get_guintvar (tvb, off+1, &len);
2406                                 str = strtbl_lookup (tvb, str_tbl, index, NULL);
2407                                 proto_tree_add_text (tree, tvb, off, 1+len,
2408                                                 "  %3d |  Attr | EXT_T_%1x    (Extension Token)    "
2409                                                 "|     %s(%s: \'%s\')",
2410                                                 level, peek & 0x0f, Indent (level),
2411                                                 match_strval (peek, map->global), str);
2412                                 off += 1+len;
2413                                 break;
2414                         case 0x83: /* EXT_T */
2415                                 index = tvb_get_guintvar (tvb, off+1, &len);
2416                                 str = strtbl_lookup (tvb, str_tbl, index, NULL);
2417                                 proto_tree_add_text (tree, tvb, off, 1+len,
2418                                                 "  %3d |  Attr | STR_T (Tableref string)         "
2419                                                 "|     %s\'%s\'",
2420                                                 level, Indent (level), str);
2421                                 off += 1+len;
2422                                 break;
2423                         /* 0x84 impossible in ATTR state */
2424                         case 0xC0: /* EXT_0 */
2425                         case 0xC1: /* EXT_1 */
2426                         case 0xC2: /* EXT_2 */
2427                                 /* Extension tokens */
2428                                 proto_tree_add_text (tree, tvb, off, 1,
2429                                                 "  %3d |  Attr | EXT_%1x      (Extension Token)    "
2430                                                 "|     %s(%s)",
2431                                                 level, peek & 0x0f, Indent (level),
2432                                                 match_strval (peek, map->global));
2433                                 off++;
2434                                 break;
2435                         case 0xC3: /* OPAQUE - WBXML 1.1 and newer */
2436                                 if (tvb_get_guint8 (tvb, 0)) { /* WBXML 1.x (x > 0) */
2437                                         index = tvb_get_guintvar (tvb, off+1, &len);
2438                                         proto_tree_add_text (tree, tvb, off, 1 + len + index,
2439                                                         "  %3d |  Attr | OPAQUE (Opaque data)            "
2440                                                         "|       %s(%d bytes of opaque data)",
2441                                                         level, Indent (level), index);
2442                                         off += 1+len+index;
2443                                 } else { /* WBXML 1.0 - RESERVED_2 token (invalid) */
2444                                         proto_tree_add_text (tree, tvb, off, 1,
2445                                                         "         Attr | RESERVED_2     (Invalid Token!) "
2446                                                         "| WBXML 1.0 parsing stops here.");
2447                                         /* Stop processing as it is impossible to parse now */
2448                                         off = tvb_len;
2449                                         *parsed_length = off - offset;
2450                                         return;
2451                                 }
2452                                 break;
2453                         /* 0xC4 impossible in ATTR state */
2454                         default:
2455                                 proto_tree_add_text (tree, tvb, off, 1,
2456                                                 "  %3d |  Attr | %-10s     (Invalid Token!) "
2457                                                 "| WBXML parsing stops here.",
2458                                                 level, match_strval (peek, vals_wbxml1x_global_tokens));
2459                                 /* Move to end of buffer */
2460                                 off = tvb_len;
2461                                 break;
2462                 } else { /* Known atribute token */
2463                         if (peek & 0x80) { /* attrValue */
2464                                 proto_tree_add_text (tree, tvb, off, 1,
2465                                                 "  %3d |  Attr |   Known attrValue 0x%02X          "
2466                                                 "|       %s%s",
2467                                                 level, peek & 0x7f, Indent (level),
2468                                                 match_strval (peek, map->attrValue));
2469                                 off++;
2470                         } else { /* attrStart */
2471                                 proto_tree_add_text (tree, tvb, off, 1,
2472                                                 "  %3d |  Attr |   Known attrStart 0x%02X          "
2473                                                 "|   %s%s",
2474                                                 level, peek & 0x7f, Indent (level),
2475                                                 match_strval (peek, map->attrStart));
2476                                 off++;
2477                         }
2478                 }
2479         } /* End WHILE */
2480 }
2481
2482
2483
2484
2485 /* This function performs the WBXML attribute decoding as in
2486  * parse_wbxml_attribute_list_defined() but this time no WBXML mapping
2487  * is performed.
2488  *
2489  * This function performs attribute list parsing.
2490  * 
2491  * NOTE: Code page switches not yet processed in the code!
2492  */
2493 static void
2494 parse_wbxml_attribute_list (proto_tree *tree, tvbuff_t *tvb,
2495                 guint32 offset, guint32 str_tbl, guint8 level,
2496                 guint8 *codepage_attr, guint32 *parsed_length)
2497 {
2498         guint32 tvb_len = tvb_reported_length (tvb);
2499         guint32 off = offset;
2500         guint32 len;
2501         guint32 ent;
2502         guint32 index;
2503         const char* str;
2504         guint8 peek;
2505
2506 #ifdef DEBUG
2507         printf ("WBXML - parse_wbxml_attr_defined (level = %d, offset = %d)\n",
2508                         level, offset);
2509 #endif
2510         /* Parse attributes */
2511         while (off < tvb_len) {
2512                 peek = tvb_get_guint8 (tvb, off);
2513 #ifdef DEBUG
2514                 printf("WBXML - ATTR: level = %3d, peek = 0x%02X, off = %d, "
2515                                 "tvb_len = %d\n",
2516                                 level, peek, off, tvb_len);
2517 #endif
2518                 if ((peek & 0x3F) < 5) switch (peek) { /* Global tokens
2519                                                                                                   in state = ATTR */
2520                         case 0x00: /* SWITCH_PAGE */
2521                                 peek = tvb_get_guint8 (tvb, off+1);
2522                                 proto_tree_add_text (tree, tvb, off, 2,
2523                                                 "         Attr | SWITCH_PAGE (Attr code page)    "
2524                                                 "| Code page switch (was: %d, is: %d)",
2525                                                 *codepage_attr, peek);
2526                                 *codepage_attr = peek;
2527                                 off += 2;
2528                                 break;
2529                         case 0x01: /* END */
2530                                 /* BEWARE
2531                                  *   The Attribute END token means either ">" or "/>"
2532                                  *   and as a consequence both must be trated separately.
2533                                  *   This is done in the TAG state parser.
2534                                  */
2535                                 off++;
2536                                 *parsed_length = off - offset;
2537                                 return;
2538                         case 0x02: /* ENTITY */
2539                                 ent = tvb_get_guintvar (tvb, off+1, &len);
2540                                 proto_tree_add_text (tree, tvb, off, 1+len,
2541                                                 "  %3d |  Attr | ENTITY                          "
2542                                                 "|     %s'&#%u;'",
2543                                                 level, Indent (level), ent);
2544                                 off += 1+len;
2545                                 break;
2546                         case 0x03: /* STR_I */
2547                                 /* Hack the string table lookup function */
2548                                 str = strtbl_lookup (tvb, off+1, 0, &len);
2549                                 proto_tree_add_text (tree, tvb, off, 1+len,
2550                                                 "  %3d |  Attr | STR_I (Inline string)           "
2551                                                 "|     %s\'%s\'",
2552                                                 level, Indent (level), str);
2553                                 off += 1+len;
2554                                 break;
2555                         case 0x04: /* LITERAL */
2556                                 index = tvb_get_guintvar (tvb, off+1, &len);
2557                                 str = strtbl_lookup (tvb, str_tbl, index, NULL);
2558                                 proto_tree_add_text (tree, tvb, off, 1+len,
2559                                                 "  %3d |  Attr | LITERAL (Literal Attribute)     "
2560                                                 "|   %s<%s />",
2561                                                 level, Indent (level), str);
2562                                 off += 1+len;
2563                                 break;
2564                         case 0x40: /* EXT_I_0 */
2565                         case 0x41: /* EXT_I_1 */
2566                         case 0x42: /* EXT_I_2 */
2567                                 /* Extension tokens */
2568                                 /* Hack the string table lookup function */
2569                                 str = strtbl_lookup (tvb, off+1, 0, &len);
2570                                 proto_tree_add_text (tree, tvb, off, 1+len,
2571                                                 "  %3d |  Attr | EXT_I_%1x    (Extension Token)    "
2572                                                 "|     %s(Inline string extension: \'%s\')",
2573                                                 level, peek & 0x0f, Indent (level), str);
2574                                 off += 1+len;
2575                                 break;
2576                         /* 0x43 impossible in ATTR state */
2577                         /* 0x44 impossible in ATTR state */
2578                         case 0x80: /* EXT_T_0 */
2579                         case 0x81: /* EXT_T_1 */
2580                         case 0x82: /* EXT_T_2 */
2581                                 /* Extension tokens */
2582                                 index = tvb_get_guintvar (tvb, off+1, &len);
2583                                 str = strtbl_lookup (tvb, str_tbl, index, NULL);
2584                                 proto_tree_add_text (tree, tvb, off, 1+len,
2585                                                 "  %3d |  Attr | EXT_T_%1x    (Extension Token)    "
2586                                                 "|     %s(Tableref string extension: \'%s\')",
2587                                                 level, peek & 0x0f, Indent (level), str);
2588                                 off += 1+len;
2589                                 break;
2590                         case 0x83: /* EXT_T */
2591                                 index = tvb_get_guintvar (tvb, off+1, &len);
2592                                 str = strtbl_lookup (tvb, str_tbl, index, NULL);
2593                                 proto_tree_add_text (tree, tvb, off, 1+len,
2594                                                 "  %3d |  Attr | STR_T (Tableref string)         "
2595                                                 "|     %s\'%s\'",
2596                                                 level, Indent (level), str);
2597                                 off += 1+len;
2598                                 break;
2599                         /* 0x84 impossible in ATTR state */
2600                         case 0xC0: /* EXT_0 */
2601                         case 0xC1: /* EXT_1 */
2602                         case 0xC2: /* EXT_2 */
2603                                 /* Extension tokens */
2604                                 proto_tree_add_text (tree, tvb, off, 1,
2605                                                 "  %3d |  Attr | EXT_%1x      (Extension Token)    "
2606                                                 "|     %s(Single-byte extension)",
2607                                                 level, peek & 0x0f, Indent (level));
2608                                 off++;
2609                                 break;
2610                         case 0xC3: /* OPAQUE - WBXML 1.1 and newer */
2611                                 if (tvb_get_guint8 (tvb, 0)) { /* WBXML 1.x (x > 0) */
2612                                         index = tvb_get_guintvar (tvb, off+1, &len);
2613                                         proto_tree_add_text (tree, tvb, off, 1 + len + index,
2614                                                         "  %3d |  Attr | OPAQUE (Opaque data)            "
2615                                                         "|       %s(%d bytes of opaque data)",
2616                                                         level, Indent (level), index);
2617                                         off += 1+len+index;
2618                                 } else { /* WBXML 1.0 - RESERVED_2 token (invalid) */
2619                                         proto_tree_add_text (tree, tvb, off, 1,
2620                                                         "         Attr | RESERVED_2     (Invalid Token!) "
2621                                                         "| WBXML 1.0 parsing stops here.");
2622                                         /* Stop processing as it is impossible to parse now */
2623                                         off = tvb_len;
2624                                         *parsed_length = off - offset;
2625                                         return;
2626                                 }
2627                                 break;
2628                         /* 0xC4 impossible in ATTR state */
2629                         default:
2630                                 proto_tree_add_text (tree, tvb, off, 1,
2631                                                 "  %3d |  Attr | %-10s     (Invalid Token!) "
2632                                                 "| WBXML parsing stops here.",
2633                                                 level, match_strval (peek, vals_wbxml1x_global_tokens));
2634                                 /* Move to end of buffer */
2635                                 off = tvb_len;
2636                                 break;
2637                 } else { /* Known atribute token */
2638                         if (peek & 0x80) { /* attrValue */
2639                                 proto_tree_add_text (tree, tvb, off, 1,
2640                                                 "  %3d |  Attr |   Known attrValue 0x%02X          "
2641                                                 "|       %sattrValue_0x%02X",
2642                                                 level, peek & 0x7f, Indent (level), peek);
2643                                 off++;
2644                         } else { /* attrStart */
2645                                 proto_tree_add_text (tree, tvb, off, 1,
2646                                                 "  %3d |  Attr |   Known attrStart 0x%02X          "
2647                                                 "|   %sattrStart_0x%02X",
2648                                                 level, peek & 0x7f, Indent (level), peek);
2649                                 off++;
2650                         }
2651                 }
2652         } /* End WHILE */
2653 }
2654
2655
2656
2657
2658 /****************** Register the protocol with Ethereal ******************/
2659
2660 /* This format is required because a script is used to build the C function
2661  * that calls the protocol registration.
2662  */
2663
2664 void
2665 proto_register_wbxml(void)
2666 {                 
2667
2668 /* Setup list of header fields  See Section 1.6.1 for details*/
2669         static hf_register_info hf[] = {
2670                 { &hf_wbxml_version,
2671                         { "Version",
2672                           "wbxml.version",
2673                           FT_UINT8, BASE_HEX,
2674                           VALS ( vals_wbxml_versions ), 0x00,
2675                           "WBXML Version", HFILL }
2676                 },
2677
2678                 { &hf_wbxml_public_id_known,
2679                         { "Public Identifier (known)",
2680                           "wbxml.public_id.known",
2681                           FT_UINT32, BASE_HEX,
2682                           VALS ( vals_wbxml_public_ids ), 0x00,
2683                           "WBXML Known Public Identifier (integer)",
2684                           HFILL }
2685                 },
2686
2687                 { &hf_wbxml_public_id_literal,
2688                         { "Public Identifier (literal)",
2689                           "wbxml.public_id.literal",
2690                           FT_STRING, BASE_NONE,
2691                           NULL, 0x00,
2692                           "WBXML Literal Public Identifier (text string)",
2693                           HFILL }
2694                 },
2695
2696                 { &hf_wbxml_charset,
2697                         { "Character Set",
2698                           "wbxml.charset",
2699                           FT_UINT32, BASE_HEX,
2700                           VALS ( vals_character_sets ), 0x00,
2701                           "WBXML Character Set", HFILL }
2702                 },
2703
2704         };
2705
2706 /* Setup protocol subtree array */
2707         static gint *ett[] = {
2708                 &ett_wbxml,
2709                 &ett_wbxml_str_tbl,
2710                 &ett_wbxml_content,
2711         };
2712
2713 /* Register the protocol name and description */
2714         proto_wbxml = proto_register_protocol(
2715                         "WAP Binary XML",
2716                         "WBXML",
2717                         "wbxml"
2718         );
2719
2720 /* Required function calls to register the header fields and subtrees used */
2721         proto_register_field_array(proto_wbxml, hf, array_length(hf));
2722         proto_register_subtree_array(ett, array_length(ett));
2723
2724         register_dissector("wbxml", dissect_wbxml, proto_wbxml);
2725 /*      register_init_routine(dissect_wbxml); */
2726         /* wbxml_handle = find_dissector("wsp-co"); */
2727 };
2728
2729
2730 void
2731 proto_reg_handoff_wbxml(void)
2732 {
2733         dissector_handle_t wbxml_handle;
2734
2735         /* Heuristic dissectors would be declared by means of:
2736          * heur_dissector_add("wsp", dissect_wbxml_heur, proto_wbxml);
2737          */
2738
2739         wbxml_handle = create_dissector_handle(dissect_wbxml, proto_wbxml);
2740
2741         /* Register the WSP content types (defined as protocol port)
2742          * for WBXML dissection.
2743          * 
2744          * See http://www.wapforum.org/wina/wsp-content-type.htm
2745          */
2746
2747         /**** Well-known WBXML WSP Content-Type values ****/
2748         
2749         /* application/vnd.wap.wmlc */
2750         dissector_add("wsp.content_type.type", 0x14, wbxml_handle);
2751         
2752         /* application/vnd.wap.wta-eventc */
2753         dissector_add("wsp.content_type.type", 0x16, wbxml_handle);
2754         
2755         /* application/vnd.wap.wbxml */
2756         dissector_add("wsp.content_type.type", 0x29, wbxml_handle);
2757         
2758         /* application/vnd.wap.sic */
2759         dissector_add("wsp.content_type.type", 0x2E, wbxml_handle);
2760         
2761         /* application/vnd.wap.slc */
2762         dissector_add("wsp.content_type.type", 0x30, wbxml_handle);
2763         
2764         /* application/vnd.wap.coc */
2765         dissector_add("wsp.content_type.type", 0x32, wbxml_handle);
2766         
2767         /* application/vnd.wap.connectivity-wbxml */
2768         dissector_add("wsp.content_type.type", 0x36, wbxml_handle);
2769         
2770         /* application/vnd.wap.locc+wbxml */
2771         dissector_add("wsp.content_type.type", 0x40, wbxml_handle);
2772         
2773         /* application/vnd.syncml.dm+wbxml */
2774         dissector_add("wsp.content_type.type", 0x42, wbxml_handle);
2775         
2776         /* application/vnd.oma.drm.rights+wbxml */
2777         dissector_add("wsp.content_type.type", 0x4B, wbxml_handle);
2778
2779 #ifdef WSP_DISSECTOR_REGISTERS_ContentType_AS_FourByteGuint     
2780         
2781         /**** Registered WBXML WSP Content-Type values ****/
2782
2783         /* application/vnd.uplanet.cacheop-wbxml */
2784         dissector_add("wsp.content_type.type", 0x0201, wbxml_handle);
2785         
2786         /* application/vnd.uplanet.alert-wbxml */
2787         dissector_add("wsp.content_type.type", 0x0203, wbxml_handle);
2788         
2789         /* application/vnd.uplanet.list-wbxml */
2790         dissector_add("wsp.content_type.type", 0x0204, wbxml_handle);
2791         
2792         /* application/vnd.uplanet.listcmd-wbxml */
2793         dissector_add("wsp.content_type.type", 0x0205, wbxml_handle);
2794         
2795         /* application/vnd.uplanet.channel-wbxml */
2796         dissector_add("wsp.content_type.type", 0x0206, wbxml_handle);
2797         
2798         /* application/vnd.uplanet.bearer-choice-wbxml */
2799         dissector_add("wsp.content_type.type", 0x0209, wbxml_handle);
2800         
2801         /* application/vnd.phonecom.mmc-wbxml */
2802         dissector_add("wsp.content_type.type", 0x020A, wbxml_handle);
2803         
2804         /* application/vnd.nokia.syncset+wbxml */
2805         dissector_add("wsp.content_type.type", 0x020B, wbxml_handle);
2806 #endif
2807 }