Don't capitalize "Filter" in "Display Filter" in the "Find" dialog box,
[obnox/wireshark/wip.git] / packet-wbxml.c
1 /* packet-wbxml.c
2  *
3  * Routines for WAP Binary XML dissection
4  * Copyright 2003, 2004, Olivier Biot.
5  *
6  * $Id: packet-wbxml.c,v 1.37 2004/05/14 16:32:49 obiot Exp $
7  *
8  * Refer to the AUTHORS file or the AUTHORS section in the man page
9  * for contacting the author(s) of this file.
10  *
11  * Ethereal - Network traffic analyzer
12  * By Gerald Combs <gerald@ethereal.com>
13  * Copyright 1998 Gerald Combs
14  *
15  * WAP Binary XML decoding functionality provided by Olivier Biot.
16  * 
17  * The WAP specifications used to be found at the WAP Forum:
18  *      <http://www.wapforum.org/what/Technical.htm>
19  * But now the correct link is at the Open Mobile Alliance:
20  *      <http://www.openmobilealliance.org/tech/affiliates/wap/wapindex.html>
21  * Media types defined by OMA affiliates will have their standards at:
22  *      <http://www.openmobilealliance.org/tech/affiliates/index.html>
23  *      <http://www.openmobilealliance.org/release_program/index.html>
24  * 
25  * This program is free software; you can redistribute it and/or
26  * modify it under the terms of the GNU General Public License
27  * as published by the Free Software Foundation; either version 2
28  * of the License, or (at your option) any later version.
29  * 
30  * This program is distributed in the hope that it will be useful,
31  * but WITHOUT ANY WARRANTY; without even the implied warranty of
32  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
33  * GNU General Public License for more details.
34  * 
35  * You should have received a copy of the GNU General Public License
36  * along with this program; if not, write to the Free Software
37  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
38  */
39
40 /* Edit this file with 4-space tabulation */
41
42 #ifdef HAVE_CONFIG_H
43 # include "config.h"
44 #endif
45
46 #include <stdio.h>
47 #include <stdlib.h>
48 #include <string.h>
49
50 #include <glib.h>
51
52 #include <epan/packet.h>
53
54 #include "prefs.h"
55
56 /* We need the function tvb_get_guintvar() */
57 #include "packet-wap.h"
58
59 /* General-purpose debug logger.
60  * Requires double parentheses because of variable arguments of printf().
61  *
62  * Enable debug logging for WBXML by defining AM_FLAGS
63  * so that it contains "-DDEBUG_wbxml"
64  */
65 #ifdef DEBUG_wbxml
66 #define DebugLog(x) \
67         printf("%s:%u: ", __FILE__, __LINE__); \
68         printf x; \
69         fflush(stdout)
70 #else
71 #define DebugLog(x) ;
72 #endif
73
74 /* The code in this source file dissects the WAP Binary XML content,
75  * and if possible renders it. WBXML mappings are defined in the
76  * "wbxml_decoding" structure.
77  *
78  * NOTES:
79  *
80  *  - Some WBXML content is *not* backwards compatible across minor versions.
81  *    This painful remark is true for:
82  *      o  WMLC 1.0 with respect to later WMLC 1.x
83  *      o  All WV-CSP versions (never backwards compatible)
84  *    The only way of correctly rendering the WBXML is to let the end-user
85  *    choose from the possible renderings. This only applies to the case when
86  *    the WBXML DocType is not included in the WBXML header (unknown/missing).
87  *
88  *  - Some WBXML content uses EXT_T_* in a non-tableref manner. This is the
89  *    case with WV-CSP 1.1 and up, where the index points to a value_string
90  *    containing WV-CSP specific token values. This is allowed as it is not
91  *    explicitly forbidden in the WBXML specifications. Hence the global token
92  *    map for content must also contain a function pointer if no tableref
93  *    string is used.
94  *
95  *  - Code page switches apply until a new code page switch. In the WBXML/1.x
96  *    ABNF notation, it can be proven that the switch_page can only precede
97  *    the following tokens:
98  *      o  stag      : TAG | LITERAL | LITERAL_A | LITERAL_C | LITERAL_AC
99  *      o  attr      : ATTRSTART | ATTRVALUE
100  *      o  extension : EXT_I | EXT_T | EXT
101  *    Code page switches are displayed in a separate column.
102  *
103  *  - The WBXML spec states that code pages are static to both the tag and the
104  *    attribute state parser. A SWITCH_PAGE within a state switches the code
105  *    page of the active state only. Note that code page 255 is reserved for
106  *    application-specific (read: testing) purposes.
107  *
108  *  - In order to render the XML content, recursion is inevitable at some
109  *    point (when a tag with content occurs in the content of a tag with
110  *    content). The code will however not recurse if this is not strictly
111  *    required (e.g., tag without content in the content of a tag with
112  *    content).
113  *
114  *  - I found it useful to display the XML nesting level as a first "column",
115  *    followed by the abbreviated WBXML token interpretation. When a mapping
116  *    is defined for the parsed WBXML content, then the XML rendering is
117  *    displayed with appropriate indentation (maximum nesting level = 255,
118  *    after which the nesting and level will safely roll-over to 0).
119  *
120  *  - The WAP Forum defines the order of precedence for finding out the
121  *    WBXML content type (same rules for charset) as follows:
122  *      1. Look in the Content-Type WSP header
123  *      2. Look in the WBXML header
124  *    Currently there is no means of using content type parameters:
125  *      o  Type=<some_type>
126  *      o  Charset=<charset_of_the_content>
127  *    So it is possible some WBXML content types are incorrectly parsed.
128  *    This would only be the case when the content type declaration in the
129  *    WSP Content-Type header would be different (or would have parameters
130  *    which are relevant to the WBXML decoding) from the content type
131  *    identifier specified in the WBXML header. This has to do with the
132  *    decoding of terminated text strings in the different character codings.
133  *    TODO: investigate this and provide correct decoding at all times.
134  */
135
136 typedef struct _value_valuestring {
137         guint32 value;
138         const value_string *valstrptr;
139 } value_valuestring;
140
141 /* Tries to match val against each element in the value_value_string array vvs.
142  * Returns the associated value_string ptr on a match, or NULL on failure. */
143 static const value_string *
144 val_to_valstr(guint32 val, const value_valuestring *vvs)
145 {
146   gint i = 0;
147
148   while (vvs[i].valstrptr) {
149         if (vvs[i].value == val)
150       return(vvs[i].valstrptr);
151       i++;
152   }
153
154   return(NULL);
155 }
156
157 /* Note on Token mapping
158  * ---------------------
159  *
160  * The WBXML dissector will try mapping the token decoding to their textual
161  * representation if the media type has a defined token representation. The
162  * following logic applies:
163  *
164  * a. Inspect the WBXML PublicID
165  *      This means that I need a list { PublicID, decoding }
166  *
167  * b. Inspect the literal media type
168  *      This requires a list { "media/type", discriminator, { decodings } }
169  *
170  *   b.1. Use a discriminator to choose an appropriate token mapping;
171  *      The disciminator needs a small number of bytes from the data tvbuff_t.
172  *
173  * else
174  *   b.2. Provide a list to the end-user with all possible token mappings.
175  *
176  * c. If none match then only show the tokens without mapping.
177  *
178  */
179
180 /* ext_t_func_ptr is a pointer to a function handling the EXT_T_i tokens:
181  *
182  * char * ext_t_function(tvbuff_t *tvb, guint32 value, guint32 strtbl);
183  */
184 typedef char * (* ext_t_func_ptr)(tvbuff_t *, guint32, guint32);
185
186 /* Note on parsing of OPAQUE data
187  * ------------------------------
188  *
189  * The WBXML encapsulation allows the insertion of opaque binary data in the
190  * WBXML body. Although this opaque data has no meaning in WBXML, the media
191  * type itself may define compact encoding of given input by encoding it in
192  * such a OPAQUE blob of bytes.
193  *
194  * The WBXML dissector now supports dissection of OPAQUE data by means of a
195  * mapping function that will operate based on the token (well-known or literal)
196  * and the active code page.
197  *
198  * For well-known tokens the simplest approach is to use a switch for the code
199  * pages and another switch for the relevant tokens within a code page.
200  *
201  * For literal tokens (tags and attribute names), the only approach is a string
202  * comparison with the literal representation of the given tag or attribute
203  * name.
204  *
205  * opaque_token_func_ptr is a pointer to a function handling OPAQUE values
206  * for binary tokens representing tags or attribute starts.
207  * opaque_literal_func_ptr is a pointer to a function handling OPAQUE values
208  * for literal tokens representing tags or attribute starts.
209  * 
210  * The length field of the OPAQUE entry starts at offset (not offset + 1).
211  * 
212  * The length of the processed OPAQUE value is returned by reference.
213  *
214  * char * opaque_token_function(tvbuff_t *tvb, guint32 offset,
215  *              guint8 token, guint8 codepage, guint32 *length);
216  * char * opaque_literal_function(tvbuff_t *tvb, guint32 offset,
217  *              const char *token, guint8 codepage, guint32 *length);
218  */
219 typedef char * (* opaque_token_func_ptr)(tvbuff_t *, guint32, guint8, guint8, guint32 *);
220 typedef char * (* opaque_literal_func_ptr)(tvbuff_t *, guint32, const char *, guint8, guint32 *);
221
222 char *
223 default_opaque_binary_tag(tvbuff_t *tvb, guint32 offset,
224                 guint8 token _U_, guint8 codepage _U_, guint32 *length)
225 {
226         guint32 data_len = tvb_get_guintvar(tvb, offset, length);
227         char *str = g_strdup_printf("(%d bytes of opaque data)", data_len);
228         *length += data_len;
229         return str;
230 }
231
232 char *
233 default_opaque_literal_tag(tvbuff_t *tvb, guint32 offset,
234                 const char *token _U_, guint8 codepage _U_, guint32 *length)
235 {
236         guint32 data_len = tvb_get_guintvar(tvb, offset, length);
237         char *str = g_strdup_printf("(%d bytes of opaque data)", data_len);
238         *length += data_len;
239         return str;
240 }
241
242 char *
243 default_opaque_binary_attr(tvbuff_t *tvb, guint32 offset,
244                 guint8 token _U_, guint8 codepage _U_, guint32 *length)
245 {
246         guint32 data_len = tvb_get_guintvar(tvb, offset, length);
247         char *str = g_strdup_printf("(%d bytes of opaque data)", data_len);
248         *length += data_len;
249         return str;
250 }
251
252 char *
253 default_opaque_literal_attr(tvbuff_t *tvb, guint32 offset,
254                 const char *token _U_, guint8 codepage _U_, guint32 *length)
255 {
256         guint32 data_len = tvb_get_guintvar(tvb, offset, length);
257         char *str = g_strdup_printf("(%d bytes of opaque data)", data_len);
258         *length += data_len;
259         return str;
260 }
261
262 /* Render a hex %dateTime encoded timestamp as a string.
263  * 0x20011231123456 becomes "2001-12-31T12:34:56Z" */
264 char *
265 date_time_from_opaque(tvbuff_t *tvb, guint32 offset, guint32 data_len)
266 {
267         char *str;
268
269         switch (data_len) {
270                 case 4: /* YYYY-MM-DD[T00:00:00Z] */
271                         str = g_strdup_printf("%%DateTime: "
272                                         "%02x%02x-%02x-%02xT00:00:00Z",
273                                         tvb_get_guint8(tvb, offset),
274                                         tvb_get_guint8(tvb, offset + 1),
275                                         tvb_get_guint8(tvb, offset + 2),
276                                         tvb_get_guint8(tvb, offset + 3));
277                         break;
278                 case 5: /* YYYY-MM-DDThh[:00:00Z] */
279                         str = g_strdup_printf("%%DateTime: "
280                                         "%02x%02x-%02x-%02xT%02x:00:00Z",
281                                         tvb_get_guint8(tvb, offset),
282                                         tvb_get_guint8(tvb, offset + 1),
283                                         tvb_get_guint8(tvb, offset + 2),
284                                         tvb_get_guint8(tvb, offset + 3),
285                                         tvb_get_guint8(tvb, offset + 4));
286                         break;
287                 case 6: /* YYYY-MM-DDThh:mm[:00Z] */
288                         str = g_strdup_printf("%%DateTime: "
289                                         "%02x%02x-%02x-%02xT%02x:%02x:00Z",
290                                         tvb_get_guint8(tvb, offset),
291                                         tvb_get_guint8(tvb, offset + 1),
292                                         tvb_get_guint8(tvb, offset + 2),
293                                         tvb_get_guint8(tvb, offset + 3),
294                                         tvb_get_guint8(tvb, offset + 4),
295                                         tvb_get_guint8(tvb, offset + 5));
296                         break;
297                 case 7: /* YYYY-MM-DDThh:mm[:00Z] */
298                         str = g_strdup_printf("%%DateTime: "
299                                         "%02x%02x-%02x-%02xT%02x:%02x:%02xZ",
300                                         tvb_get_guint8(tvb, offset),
301                                         tvb_get_guint8(tvb, offset + 1),
302                                         tvb_get_guint8(tvb, offset + 2),
303                                         tvb_get_guint8(tvb, offset + 3),
304                                         tvb_get_guint8(tvb, offset + 4),
305                                         tvb_get_guint8(tvb, offset + 5),
306                                         tvb_get_guint8(tvb, offset + 6));
307                         break;
308                 default:
309                         str = g_strdup_printf("<Error: invalid binary %%DateTime "
310                                         "(%d bytes of opaque data)>", data_len);
311                         break;
312         }
313
314         return str;
315 }
316
317 /* Is ALWAYS 6 bytes long:
318  * 00YY YYYY  YYYY YYMM  MMDD DDDh  hhhh mmmm  mmss ssss  ZZZZ ZZZZ */
319 char *
320 wv_datetime_from_opaque(tvbuff_t *tvb, guint32 offset, guint32 data_len)
321 {
322         char *str;
323         guint16 year;
324         guint8 month, day, hour, minute, second, timezone;
325         guint8 peek;
326
327         if (data_len == 6) { /* Valid */
328
329                 /* Octet 1: 00YY YYYY */
330                 year = tvb_get_guint8(tvb, offset) & 0x3F; /* ..11 1111 */
331                 year <<=6;
332                 /* Octet 2: YYYY YYMM */
333                 peek = tvb_get_guint8(tvb, offset + 1);
334                 year += (peek >> 2); /* 1111 11.. */
335                 month = (peek & 0x03) << 2; /* .... ..11 */
336                 /* Octet 3: MMDD DDDh */
337                 peek = tvb_get_guint8(tvb, offset + 2);
338                 month += (peek >> 6); /* 11.. .... */
339                 day = (peek & 0x3E) >> 1; /* ..11 111. */
340                 hour = (peek & 0x01) << 4; /* .... ...1 */
341                 /* Octet 4: hhhh mmmm */
342                 peek = tvb_get_guint8(tvb, offset + 3);
343                 hour += (peek >> 4);
344                 minute = (peek & 0x0F) << 2; /* .... 1111 */
345                 /* Octet 5: mmss ssss */
346                 peek = tvb_get_guint8(tvb, offset + 4);
347                 minute += (peek >> 6); /* 11.. .... */
348                 second = peek & 0x3F; /* ..11 1111 */
349                 /* octet 6: ZZZZZZZZ */
350                 timezone = tvb_get_guint8(tvb, offset + 5);
351                 /* Now construct the string */
352                 str = g_strdup_printf("WV-CSP DateTime: "
353                                 "%04d-%02d-%02dT%02d:%02d:%02d%c",
354                                 year, month, day, hour, minute, second, timezone);
355         } else { /* Invalid length for a WV-CSP DateTime tag value */
356                 str = g_strdup_printf("<Error: invalid binary WV-CSP DateTime value "
357                                 "(%d bytes of opaque data)>", data_len);
358         }
359         return str;
360 }
361
362 /* WV-CSP integer values for tag content is encoded in a fashion similar
363  * to a Long-Integer in WSP */
364 char *
365 wv_integer_from_opaque(tvbuff_t *tvb, guint32 offset, guint32 data_len)
366 {
367         char *str;
368
369         switch (data_len) {
370                 case 1:
371                         str = g_strdup_printf("WV-CSP Integer: %d",
372                                         tvb_get_guint8(tvb, offset));
373                         break;
374                 case 2:
375                         str = g_strdup_printf("WV-CSP Integer: %d",
376                                         tvb_get_ntohs(tvb, offset));
377                         break;
378                 case 3:
379                         str = g_strdup_printf("WV-CSP Integer: %d",
380                                         tvb_get_ntoh24(tvb, offset));
381                         break;
382                 case 4:
383                         str = g_strdup_printf("WV-CSP Integer: %d",
384                                         tvb_get_ntohl(tvb, offset));
385                         break;
386                 default:
387                         str = g_strdup_printf("<Error: invalid binary WV-CSP Integer value "
388                                         "(%d bytes of opaque data)>", data_len);
389                         break;
390         }
391
392         return str;
393 }
394
395 char *
396 wv_csp10_opaque_literal_tag(tvbuff_t *tvb, guint32 offset,
397                 const char *token, guint8 codepage _U_, guint32 *length)
398 {
399         guint32 data_len = tvb_get_guintvar(tvb, offset, length);
400         char *str = NULL;
401
402         if (   (strcmp(token, "Code") == 0)
403                 || (strcmp(token, "ContentSize") == 0)
404                 || (strcmp(token, "MessageCount") == 0)
405                 || (strcmp(token, "Validity") == 0)
406                 || (strcmp(token, "KeepAliveTime") == 0)
407                 || (strcmp(token, "TimeToLive") == 0)
408                 || (strcmp(token, "AcceptedContentLength") == 0)
409                 || (strcmp(token, "MultiTrans") == 0)
410                 || (strcmp(token, "ParserSize") == 0)
411                 || (strcmp(token, "ServerPollMin") == 0)
412                 || (strcmp(token, "TCPAddress") == 0)
413                 || (strcmp(token, "TCPPort") == 0)
414                 || (strcmp(token, "UDPPort") == 0) )
415         {
416                 str = wv_integer_from_opaque(tvb, offset + *length, data_len);
417         }
418         else if (strcmp(token, "DateTime") == 0)
419         {
420                 str = wv_datetime_from_opaque(tvb, offset + *length, data_len);
421         }
422
423         if (str == NULL) { /* Error, or not parsed */
424                 str = g_strdup_printf("(%d bytes of unparsed opaque data)", data_len);
425         }
426         *length += data_len;
427         return str;
428 }
429
430 char *
431 wv_csp10_opaque_binary_tag(tvbuff_t *tvb, guint32 offset,
432                 guint8 token, guint8 codepage, guint32 *length)
433 {
434         guint32 data_len = tvb_get_guintvar(tvb, offset, length);
435         char *str = NULL;
436
437         switch (codepage) {
438                 case 0: /* Common code page */
439                         switch (token) {
440                                 case 0x0B: /* <Code> */
441                                 case 0x0F: /* <ContentSize> */
442                                 case 0x1A: /* <MessageCount> */
443                                 case 0x3C: /* <Validity> */
444                                         str = wv_integer_from_opaque(tvb,
445                                                         offset + *length, data_len);
446                                         break;
447                                 case 0x11: /* <DateTime> */
448                                         str = wv_datetime_from_opaque(tvb,
449                                                         offset + *length, data_len);
450                                         break;
451                                 default:
452                                         break;
453                         }
454                         break;
455                 case 1: /* Access code page */
456                         switch (token) {
457                                 case 0x1C: /* <KeepAliveTime> */
458                                 case 0x32: /* <TimeToLive> */
459                                         str = wv_integer_from_opaque(tvb,
460                                                         offset + *length, data_len);
461                                         break;
462                                 default:
463                                         break;
464                         }
465                 case 3: /* Client capability code page */
466                         switch (token) {
467                                 case 0x06: /* <AcceptedContentLength> */
468                                 case 0x0C: /* <MultiTrans> */
469                                 case 0x0D: /* <ParserSize> */
470                                 case 0x0E: /* <ServerPollMin> */
471                                 case 0x11: /* <TCPAddress> */
472                                 case 0x12: /* <TCPPort> */
473                                 case 0x13: /* <UDPPort> */
474                                         str = wv_integer_from_opaque(tvb,
475                                                         offset + *length, data_len);
476                                         break;
477                                 default:
478                                         break;
479                         }
480                         break;
481                 default:
482                         break;
483         }
484         if (str == NULL) { /* Error, or not parsed */
485                 str = g_strdup_printf("(%d bytes of unparsed opaque data)", data_len);
486         }
487         *length += data_len;
488
489         return str;
490 }
491
492 char *
493 wv_csp11_opaque_literal_tag(tvbuff_t *tvb, guint32 offset,
494                 const char *token, guint8 codepage _U_, guint32 *length)
495 {
496         guint32 data_len = tvb_get_guintvar(tvb, offset, length);
497         char *str = NULL;
498
499         if (   (strcmp(token, "Code") == 0)
500                 || (strcmp(token, "ContentSize") == 0)
501                 || (strcmp(token, "MessageCount") == 0)
502                 || (strcmp(token, "Validity") == 0)
503                 || (strcmp(token, "KeepAliveTime") == 0)
504                 || (strcmp(token, "TimeToLive") == 0)
505                 || (strcmp(token, "AcceptedContentLength") == 0)
506                 || (strcmp(token, "MultiTrans") == 0)
507                 || (strcmp(token, "ParserSize") == 0)
508                 || (strcmp(token, "ServerPollMin") == 0)
509                 || (strcmp(token, "TCPPort") == 0)
510                 || (strcmp(token, "UDPPort") == 0) )
511         {
512                 str = wv_integer_from_opaque(tvb, offset + *length, data_len);
513         }
514         else
515         if (   (strcmp(token, "DateTime") == 0)
516                 || (strcmp(token, "DeliveryTime") == 0) )
517         {
518                 str = wv_datetime_from_opaque(tvb, offset + *length, data_len);
519         }
520
521         if (str == NULL) { /* Error, or not parsed */
522                 str = g_strdup_printf("(%d bytes of unparsed opaque data)", data_len);
523         }
524         *length += data_len;
525         return str;
526 }
527
528 char *
529 wv_csp11_opaque_binary_tag(tvbuff_t *tvb, guint32 offset,
530                 guint8 token, guint8 codepage, guint32 *length)
531 {
532         guint32 data_len = tvb_get_guintvar(tvb, offset, length);
533         char *str = NULL;
534
535         switch (codepage) {
536                 case 0: /* Common code page */
537                         switch (token) {
538                                 case 0x0B: /* <Code> */
539                                 case 0x0F: /* <ContentSize> */
540                                 case 0x1A: /* <MessageCount> */
541                                 case 0x3C: /* <Validity> */
542                                         str = wv_integer_from_opaque(tvb,
543                                                         offset + *length, data_len);
544                                         break;
545                                 case 0x11: /* <DateTime> */
546                                         str = wv_datetime_from_opaque(tvb,
547                                                         offset + *length, data_len);
548                                         break;
549                                 default:
550                                         break;
551                         }
552                         break;
553                 case 1: /* Access code page */
554                         switch (token) {
555                                 case 0x1C: /* <KeepAliveTime> */
556                                 case 0x32: /* <TimeToLive> */
557                                         str = wv_integer_from_opaque(tvb,
558                                                         offset + *length, data_len);
559                                         break;
560                                 default:
561                                         break;
562                         }
563                 case 3: /* Client capability code page */
564                         switch (token) {
565                                 case 0x06: /* <AcceptedContentLength> */
566                                 case 0x0C: /* <MultiTrans> */
567                                 case 0x0D: /* <ParserSize> */
568                                 case 0x0E: /* <ServerPollMin> */
569                                 case 0x12: /* <TCPPort> */
570                                 case 0x13: /* <UDPPort> */
571                                         str = wv_integer_from_opaque(tvb,
572                                                         offset + *length, data_len);
573                                         break;
574                                 default:
575                                         break;
576                         }
577                         break;
578                 case 6: /* Messaging code page */
579                         switch (token) {
580                                 case 0x1A: /* <DeliveryTime> - not in 1.0 */
581                                         str = wv_datetime_from_opaque(tvb,
582                                                         offset + *length, data_len);
583                                         break;
584                                 default:
585                                         break;
586                         }
587                         break;
588                 default:
589                         break;
590         }
591         if (str == NULL) { /* Error, or not parsed */
592                 str = g_strdup_printf("(%d bytes of unparsed opaque data)", data_len);
593         }
594         *length += data_len;
595
596         return str;
597 }
598
599 char *
600 wv_csp12_opaque_literal_tag(tvbuff_t *tvb, guint32 offset,
601                 const char *token, guint8 codepage _U_, guint32 *length)
602 {
603         guint32 data_len = tvb_get_guintvar(tvb, offset, length);
604         char *str = NULL;
605
606         if (   (strcmp(token, "Code") == 0)
607                 || (strcmp(token, "ContentSize") == 0)
608                 || (strcmp(token, "MessageCount") == 0)
609                 || (strcmp(token, "Validity") == 0)
610                 || (strcmp(token, "KeepAliveTime") == 0)
611                 || (strcmp(token, "TimeToLive") == 0)
612                 || (strcmp(token, "AcceptedContentLength") == 0)
613                 || (strcmp(token, "MultiTrans") == 0)
614                 || (strcmp(token, "ParserSize") == 0)
615                 || (strcmp(token, "ServerPollMin") == 0)
616                 || (strcmp(token, "TCPPort") == 0)
617                 || (strcmp(token, "UDPPort") == 0)
618                 || (strcmp(token, "HistoryPeriod") == 0)
619                 || (strcmp(token, "MaxWatcherList") == 0) )
620         {
621                 str = wv_integer_from_opaque(tvb, offset + *length, data_len);
622         }
623         else
624         if (   (strcmp(token, "DateTime") == 0)
625                 || (strcmp(token, "DeliveryTime") == 0) )
626         {
627                 str = wv_datetime_from_opaque(tvb, offset + *length, data_len);
628         }
629
630         if (str == NULL) { /* Error, or not parsed */
631                 str = g_strdup_printf("(%d bytes of unparsed opaque data)", data_len);
632         }
633         *length += data_len;
634         return str;
635 }
636
637 char *
638 wv_csp12_opaque_binary_tag(tvbuff_t *tvb, guint32 offset,
639                 guint8 token, guint8 codepage, guint32 *length)
640 {
641         guint32 data_len = tvb_get_guintvar(tvb, offset, length);
642         char *str = NULL;
643
644         switch (codepage) {
645                 case 0: /* Common code page */
646                         switch (token) {
647                                 case 0x0B: /* <Code> */
648                                 case 0x0F: /* <ContentSize> */
649                                 case 0x1A: /* <MessageCount> */
650                                 case 0x3C: /* <Validity> */
651                                         str = wv_integer_from_opaque(tvb,
652                                                         offset + *length, data_len);
653                                         break;
654                                 case 0x11: /* <DateTime> */
655                                         str = wv_datetime_from_opaque(tvb,
656                                                         offset + *length, data_len);
657                                         break;
658                                 default:
659                                         break;
660                         }
661                         break;
662                 case 1: /* Access code page */
663                         switch (token) {
664                                 case 0x1C: /* <KeepAliveTime> */
665                                 case 0x32: /* <TimeToLive> */
666                                         str = wv_integer_from_opaque(tvb,
667                                                         offset + *length, data_len);
668                                         break;
669                                 default:
670                                         break;
671                         }
672                 case 3: /* Client capability code page */
673                         switch (token) {
674                                 case 0x06: /* <AcceptedContentLength> */
675                                 case 0x0C: /* <MultiTrans> */
676                                 case 0x0D: /* <ParserSize> */
677                                 case 0x0E: /* <ServerPollMin> */
678                                 case 0x12: /* <TCPPort> */
679                                 case 0x13: /* <UDPPort> */
680                                         str = wv_integer_from_opaque(tvb,
681                                                         offset + *length, data_len);
682                                         break;
683                                 default:
684                                         break;
685                         }
686                         break;
687                 case 6: /* Messaging code page */
688                         switch (token) {
689                                 case 0x1A: /* <DeliveryTime> - not in 1.0 */
690                                         str = wv_datetime_from_opaque(tvb,
691                                                         offset + *length, data_len);
692                                         break;
693                                 default:
694                                         break;
695                         }
696                         break;
697                 case 9: /* Common code page (continued) */
698                         switch (token) {
699                                 case 0x08: /* <HistoryPeriod> - 1.2 only */
700                                 case 0x0A: /* <MaxWatcherList> - 1.2 only */
701                                         str = wv_integer_from_opaque(tvb,
702                                                         offset + *length, data_len);
703                                         break;
704                                 default:
705                                         break;
706                         }
707                         break;
708                 default:
709                         break;
710         }
711         if (str == NULL) { /* Error, or not parsed */
712                 str = g_strdup_printf("(%d bytes of unparsed opaque data)", data_len);
713         }
714         *length += data_len;
715
716         return str;
717 }
718
719 char *
720 sic10_opaque_literal_attr(tvbuff_t *tvb, guint32 offset,
721                 const char *token, guint8 codepage _U_, guint32 *length)
722 {
723         guint32 data_len = tvb_get_guintvar(tvb, offset, length);
724         char *str = NULL;
725
726         if (   (strcmp(token, "created") == 0)
727                 || (strcmp(token, "si-expires") == 0) )
728         {
729                 str = date_time_from_opaque(tvb, offset + *length, data_len);
730         }
731         if (str == NULL) { /* Error, or not parsed */
732                 str = g_strdup_printf("(%d bytes of unparsed opaque data)", data_len);
733         }
734         *length += data_len;
735
736         return str;
737 }
738
739 char *
740 sic10_opaque_binary_attr(tvbuff_t *tvb, guint32 offset,
741                 guint8 token, guint8 codepage, guint32 *length)
742 {
743         guint32 data_len = tvb_get_guintvar(tvb, offset, length);
744         char *str = NULL;
745
746         switch (codepage) {
747                 case 0: /* Only valid codepage for SI */
748                         switch (token) {
749                                 case 0x0A: /* created= */
750                                 case 0x10: /* si-expires= */
751                                         str = date_time_from_opaque(tvb,
752                                                         offset + *length, data_len);
753                                         break;
754                                 default:
755                                         break;
756                         }
757                         break;
758                 default:
759                         break;
760         }
761         if (str == NULL) { /* Error, or not parsed */
762                 str = g_strdup_printf("(%d bytes of unparsed opaque data)", data_len);
763         }
764         *length += data_len;
765
766         return str;
767 }
768
769 char *
770 emnc10_opaque_literal_attr(tvbuff_t *tvb, guint32 offset,
771                 const char *token, guint8 codepage _U_, guint32 *length)
772 {
773         guint32 data_len = tvb_get_guintvar(tvb, offset, length);
774         char *str = NULL;
775
776         if (   (strcmp(token, "timestamp") == 0) )
777         {
778                 str = date_time_from_opaque(tvb, offset + *length, data_len);
779         }
780         if (str == NULL) { /* Error, or not parsed */
781                 str = g_strdup_printf("(%d bytes of unparsed opaque data)", data_len);
782         }
783         *length += data_len;
784
785         return str;
786 }
787
788 char *
789 emnc10_opaque_binary_attr(tvbuff_t *tvb, guint32 offset,
790                 guint8 token, guint8 codepage, guint32 *length)
791 {
792         guint32 data_len = tvb_get_guintvar(tvb, offset, length);
793         char *str = NULL;
794
795         switch (codepage) {
796                 case 0: /* Only valid codepage for EMN */
797                         switch (token) {
798                                 case 0x05: /* timestamp= */
799                                         str = date_time_from_opaque(tvb,
800                                                         offset + *length, data_len);
801                                         break;
802                                 default:
803                                         break;
804                         }
805                         break;
806                 default:
807                         break;
808         }
809         if (str == NULL) { /* Error, or not parsed */
810                 str = g_strdup_printf("(%d bytes of unparsed opaque data)", data_len);
811         }
812         *length += data_len;
813
814         return str;
815 }
816
817 typedef struct _wbxml_decoding {
818     const char *name;
819     const char *abbrev;
820     ext_t_func_ptr ext_t[3];
821         opaque_token_func_ptr   opaque_binary_tag;
822         opaque_literal_func_ptr opaque_literal_tag;
823         opaque_token_func_ptr   opaque_binary_attr;
824         opaque_literal_func_ptr opaque_literal_attr;
825     const value_valuestring *global;
826     const value_valuestring *tags;
827     const value_valuestring *attrStart;
828     const value_valuestring *attrValue;
829 } wbxml_decoding;
830
831 /* Define a pointer to a discriminator function taking a tvb and the start
832  * offset of the WBXML tokens in the body as arguments.
833  */
834 typedef const wbxml_decoding * (* discriminator_func_ptr)(tvbuff_t *, guint32);
835
836 /* For the decoding lists based on the known WBXML public ID */
837 typedef struct _wbxml_integer_list {
838     guint32 public_id;
839     const wbxml_decoding *map;
840 } wbxml_integer_list;
841
842 /* For the decoding lists on the literal content type */ 
843 typedef struct _wbxml_literal_list {
844     const char *content_type;
845     discriminator_func_ptr discriminator; /* TODO */
846     const wbxml_decoding *map;
847 } wbxml_literal_list;
848
849 /************************** Variable declarations **************************/
850
851
852 /* Initialize the protocol and registered fields */
853 static int proto_wbxml = -1;
854 static int hf_wbxml_version = -1;
855 static int hf_wbxml_public_id_known = -1;
856 static int hf_wbxml_public_id_literal = -1;
857 static int hf_wbxml_charset = -1;
858
859 /* Initialize the subtree pointers */
860 static gint ett_wbxml = -1;
861 static gint ett_wbxml_str_tbl = -1;
862 static gint ett_wbxml_content = -1;
863
864 /* WBXML Preferences */
865 static gboolean skip_wbxml_token_mapping = FALSE;
866 static gboolean disable_wbxml_token_parsing = FALSE;
867
868
869 /**************** WBXML related declarations and definitions ****************/
870
871
872 /* WBXML public ID mappings. For an up-to-date list, see
873  * http://www.openmobilealliance.org/tech/omna/ */
874 static const value_string vals_wbxml_public_ids[] = {
875         /* 0x00 = literal public identifier */
876         { 0x01, "Unknown / missing Public Identifier" },
877         { 0x02, "-//WAPFORUM//DTD WML 1.0//EN (WML 1.0)" },
878         { 0x03, "-//WAPFORUM//DTD WTA 1.0//EN (WTA Event 1.0) - Deprecated" },
879         { 0x04, "-//WAPFORUM//DTD WML 1.1//EN (WML 1.1)" },
880         { 0x05, "-//WAPFORUM//DTD SI 1.0//EN (Service Indication 1.0)" },
881         { 0x06, "-//WAPFORUM//DTD SL 1.0//EN (Service Loading 1.0)" },
882         { 0x07, "-//WAPFORUM//DTD CO 1.0//EN (Cache Operation 1.0)" },
883         { 0x08, "-//WAPFORUM//DTD CHANNEL 1.1//EN (Channel 1.1)" },
884         { 0x09, "-//WAPFORUM//DTD WML 1.2//EN (WML 1.2)" },
885         { 0x0a, "-//WAPFORUM//DTD WML 1.3//EN (WML 1.3)" },
886         { 0x0b, "-//WAPFORUM//DTD PROV 1.0//EN (Provisioning 1.0)" },
887         { 0x0c, "-//WAPFORUM//DTD WTA-WML 1.2//EN (WTA-WML 1.2)" },
888         { 0x0d, "-//WAPFORUM//DTD EMN 1.0//EN (Email Notification 1.0)" },
889         { 0x0e, "-//WAPFORUM//DTD DRMREL 1.0//EN (DRMREL 1.0)" },
890         { 0x0f, "-//WIRELESSVILLAGE//DTD CSP 1.0//EN"
891                 " (Wireless Village Client-Server Protocol DTD v1.0)" },
892         { 0x10, "-//WIRELESSVILLAGE//DTD CSP 1.1//EN"
893                 " (Wireless Village Client-Server Protocol DTD v1.1)" },
894
895         /* Registered values - www.syncml.org */
896         { 0x0fd1, "-//SYNCML//DTD SyncML 1.0//EN (SyncML 1.0)" },
897         { 0x0fd3, "-//SYNCML//DTD SyncML 1.1//EN (SyncML 1.1)" },
898
899         /* Registered values - www.wapforum.org/wina/ */
900         { 0x1100, "-//PHONE.COM//DTD ALERT 1.0//EN" },
901         { 0x1101, "-//PHONE.COM//DTD CACHE-OPERATION 1.0//EN" },
902         { 0x1102, "-//PHONE.COM//DTD SIGNAL 1.0//EN" },
903         { 0x1103, "-//PHONE.COM//DTD LIST 1.0//EN" },
904         { 0x1104, "-//PHONE.COM//DTD LISTCMD 1.0//EN" },
905         { 0x1105, "-//PHONE.COM//DTD CHANNEL 1.0//EN" },
906         { 0x1106, "-//PHONE.COM//DTD MMC 1.0//EN" },
907         { 0x1107, "-//PHONE.COM//DTD BEARER-CHOICE 1.0//EN" },
908         { 0x1108, "-//PHONE.COM//DTD WML 1.1//EN (WML+ 1.1)" },
909         { 0x1109, "-//PHONE.COM//DTD CHANNEL 1.1//EN" },
910         { 0x110a, "-//PHONE.COM//DTD LIST 1.1//EN" },
911         { 0x110b, "-//PHONE.COM//DTD LISTCMD 1.1//EN" },
912         { 0x110c, "-//PHONE.COM//DTD MMC 1.1//EN" },
913         { 0x110d, "-//PHONE.COM//DTD WML 1.3//EN (WML+ 1.3)" },
914         { 0x110e, "-//PHONE.COM//DTD MMC 2.0//EN" },
915         /* 0x110F -- 0x11FF: unassigned */
916         { 0x1200, "-//3GPP2.COM//DTD IOTA 1.0//EN" },
917         
918         { 0x00, NULL }
919 };
920
921 static const value_string vals_wbxml_versions[] = {
922         { 0x00, "1.0" },        /* WAP-104-WBXML */
923         { 0x01, "1.1" },        /* WAP-135-WBXML */
924         { 0x02, "1.2" },        /* WAP-154-WBXML */
925         { 0x03, "1.3" },        /* WAP-192-WBXML */
926         
927         { 0x00, NULL }
928 };
929
930 /* WBXML 1.0 global tokens: WAP-104-WBXML
931  * Same token mapping as in vals_wbxml1x_global_tokens, but:
932  *   { 0xC3, "RESERVED_2" }
933  */
934
935 /* WBXML 1.x (x>0) global tokens: WAP-135-WBXML, WAP-154-WBXML, WAP-192-WBXML
936  */
937 static const value_string vals_wbxml1x_global_tokens[] = {
938         { 0x00, "SWITCH_PAGE" },
939         { 0x01, "END" },
940         { 0x02, "ENTITY" },
941         { 0x03, "STR_I" },
942         { 0x04, "LITERAL" },
943
944         { 0x40, "EXT_I_0" },
945         { 0x41, "EXT_I_1" },
946         { 0x42, "EXT_I_2" },
947         { 0x43, "PI" },
948         { 0x44, "LITERAL_C" },
949
950         { 0x80, "EXT_T_0" },
951         { 0x81, "EXT_T_1" },
952         { 0x82, "EXT_T_2" },
953         { 0x83, "STR_T" },
954         { 0x84, "LITERAL_A" },
955
956         { 0xC0, "EXT_0" },
957         { 0xC1, "EXT_1" },
958         { 0xC2, "EXT_2" },
959         { 0xC3, "OPAQUE" },
960         { 0xC4, "LITERAL_AC" },
961
962         { 0x00, NULL }
963 };
964
965
966
967
968
969 /********************** WBXML token mapping definition **********************/
970
971 /*
972  * NOTE: Please make sure the Attribute Start values all contain an equal sign
973  *       even in cases where they do not contain the start of an Attribute
974  *       Value.
975  */
976
977
978 /* WML 1.0
979  * 
980  * Wireless Markup Language
981  ***************************************/
982 static char *
983 ext_t_0_wml_10(tvbuff_t *tvb, guint32 value, guint32 str_tbl)
984 {
985     gint str_len = tvb_strsize (tvb, str_tbl + value);
986     char *str = g_strdup_printf("Variable substitution - escaped: '%s'",
987             tvb_get_ptr(tvb, str_tbl + value, str_len));
988     return str;
989 }
990
991 static char *
992 ext_t_1_wml_10(tvbuff_t *tvb, guint32 value, guint32 str_tbl)
993 {
994     gint str_len = tvb_strsize (tvb, str_tbl + value);
995     char *str = g_strdup_printf("Variable substitution - unescaped: '%s'",
996             tvb_get_ptr(tvb, str_tbl + value, str_len));
997     return str;
998 }
999
1000 static char *
1001 ext_t_2_wml_10(tvbuff_t *tvb, guint32 value, guint32 str_tbl)
1002 {
1003     gint str_len = tvb_strsize (tvb, str_tbl + value);
1004     char *str = g_strdup_printf("Variable substitution - no transformation: '%s'",
1005             tvb_get_ptr(tvb, str_tbl + value, str_len));
1006     return str;
1007 }
1008 /*****   Global extension tokens   *****/
1009 static const value_string wbxml_wmlc10_global_cp0[] = {
1010         { 0x40, "Variable substitution - escaped" },
1011         { 0x41, "Variable substitution - unescaped" },
1012         { 0x42, "Variable substitution - no transformation" },
1013         { 0x80, "Variable substitution - escaped" },
1014         { 0x81, "Variable substitution - unescaped" },
1015         { 0x82, "Variable substitution - no transformation" },
1016         { 0xC0, "Reserved" },
1017         { 0xC1, "Reserved" },
1018         { 0xC2, "Reserved" },
1019
1020         { 0x00, NULL }
1021 };
1022
1023 /*****         Tag tokens          *****/
1024 static const value_string wbxml_wmlc10_tags_cp0[] = {
1025         /* 0x00 -- 0x04 GLOBAL */
1026         /* 0x05 -- 0x21 */
1027         { 0x22, "A" },
1028         { 0x23, "ACCESS" },
1029         { 0x24, "B" },
1030         { 0x25, "BIG" },
1031         { 0x26, "BR" },
1032         { 0x27, "CARD" },
1033         { 0x28, "DO" },
1034         { 0x29, "EM" },
1035         { 0x2A, "FIELDSET" },
1036         { 0x2B, "GO" },
1037         { 0x2C, "HEAD" },
1038         { 0x2D, "I" },
1039         { 0x2E, "IMG" },
1040         { 0x2F, "INPUT" },
1041         { 0x30, "META" },
1042         { 0x31, "NOOP" },
1043         { 0x32, "PREV" },
1044         { 0x33, "ONEVENT" },
1045         { 0x34, "OPTGROUP" },
1046         { 0x35, "OPTION" },
1047         { 0x36, "REFRESH" },
1048         { 0x37, "SELECT" },
1049         { 0x38, "SMALL" },
1050         { 0x39, "STRONG" },
1051         { 0x3A, "TAB" },
1052         { 0x3B, "TEMPLATE" },
1053         { 0x3C, "TIMER" },
1054         { 0x3D, "U" },
1055         { 0x3E, "VAR" },
1056         { 0x3F, "WML" },
1057
1058         { 0x00, NULL }
1059 };
1060
1061 /*****    Attribute Start tokens   *****/
1062 static const value_string wbxml_wmlc10_attrStart_cp0[] = {
1063         /* 0x00 -- 0x04 GLOBAL */
1064         { 0x05, "ACCEPT-CHARSET=" },
1065         { 0x06, "ALIGN='BOTTOM'" },
1066         { 0x07, "ALIGN='CENTER'" },
1067         { 0x08, "ALIGN='LEFT'" },
1068         { 0x09, "ALIGN='MIDDLE'" },
1069         { 0x0A, "ALIGN='RIGHT'" },
1070         { 0x0B, "ALIGN='TOP'" },
1071         { 0x0C, "ALT=" },
1072         { 0x0D, "CONTENT=" },
1073         { 0x0E, "DEFAULT=" },
1074         { 0x0F, "DOMAIN=" },
1075         { 0x10, "EMPTYOK='FALSE'" },
1076         { 0x11, "EMPTYOK='TRUE'" },
1077         { 0x12, "FORMAT=" },
1078         { 0x13, "HEIGHT=" },
1079         { 0x14, "HSPACE=" },
1080         { 0x15, "IDEFAULT=" },
1081         { 0x16, "IKEY=" },
1082         { 0x17, "KEY=" },
1083         { 0x18, "LABEL=" },
1084         { 0x19, "LOCALSRC=" },
1085         { 0x1A, "MAXLENGTH=" },
1086         { 0x1B, "METHOD='GET'" },
1087         { 0x1C, "METHOD='POST'" },
1088         { 0x1D, "MODE='NOWRAP'" },
1089         { 0x1E, "MODE='WRAP'" },
1090         { 0x1F, "MULTIPLE='FALSE'" },
1091         { 0x20, "MULTIPLE='TRUE'" },
1092         { 0x21, "NAME=" },
1093         { 0x22, "NEWCONTEXT='FALSE'" },
1094         { 0x23, "NEWCONTEXT='TRUE'" },
1095         { 0x24, "ONCLICK=" },
1096         { 0x25, "ONENTERBACKWARD=" },
1097         { 0x26, "ONENTERFORWARD=" },
1098         { 0x27, "ONTIMER=" },
1099         { 0x28, "OPTIONAL='FALSE'" },
1100         { 0x29, "OPTIONAL='TRUE'" },
1101         { 0x2A, "PATH=" },
1102         { 0x2B, "POSTDATA=" },
1103         { 0x2C, "PUBLIC='FALSE'" },
1104         { 0x2D, "PUBLIC='TRUE'" },
1105         { 0x2E, "SCHEME=" },
1106         { 0x2F, "SENDREFERER='FALSE'" },
1107         { 0x30, "SENDREFERER='TRUE'" },
1108         { 0x31, "SIZE=" },
1109         { 0x32, "SRC=" },
1110         { 0x33, "STYLE='LIST'" },
1111         { 0x34, "STYLE='SET'" },
1112         { 0x35, "TABINDEX=" },
1113         { 0x36, "TITLE=" },
1114         { 0x37, "TYPE=" },
1115         { 0x38, "TYPE='ACCEPT'" },
1116         { 0x39, "TYPE='DELETE'" },
1117         { 0x3A, "TYPE='HELP'" },
1118         { 0x3B, "TYPE='PASSWORD'" },
1119         { 0x3C, "TYPE='ONCLICK'" },
1120         { 0x3D, "TYPE='ONENTERBACKWARD'" },
1121         { 0x3E, "TYPE='ONENTERFORWARD'" },
1122         { 0x3F, "TYPE='ONTIMER'" },
1123         /* 0x40 -- 0x44 GLOBAL */
1124         { 0x45, "TYPE='OPTIONS'" },
1125         { 0x46, "TYPE='PREV'" },
1126         { 0x47, "TYPE='RESET'" },
1127         { 0x48, "TYPE='TEXT'" },
1128         { 0x49, "TYPE='vnd.'" },
1129         { 0x4A, "URL=" },
1130         { 0x4B, "URL='http://'" },
1131         { 0x4C, "URL='https://'" },
1132         { 0x4D, "USER-AGENT=" },
1133         { 0x4E, "VALUE=" },
1134         { 0x4F, "VSPACE=" },
1135         { 0x50, "WIDTH=" },
1136         { 0x51, "xml:lang=" },
1137
1138         { 0x00, NULL }
1139 };
1140
1141 /*****    Attribute Value tokens   *****/
1142 static const value_string wbxml_wmlc10_attrValue_cp0[] = {
1143         /* 0x80 -- 0x84 GLOBAL */
1144         { 0x85, "'.com/'" },
1145         { 0x86, "'.edu/'" },
1146         { 0x87, "'.net/'" },
1147         { 0x88, "'.org/'" },
1148         { 0x89, "'ACCEPT'" },
1149         { 0x8A, "'BOTTOM'" },
1150         { 0x8B, "'CLEAR'" },
1151         { 0x8C, "'DELETE'" },
1152         { 0x8D, "'HELP'" },
1153         { 0x8E, "'http://'" },
1154         { 0x8F, "'http://www.'" },
1155         { 0x90, "'https://'" },
1156         { 0x91, "'https://www.'" },
1157         { 0x92, "'LIST'" },
1158         { 0x93, "'MIDDLE'" },
1159         { 0x94, "'NOWRAP'" },
1160         { 0x95, "'ONCLICK'" },
1161         { 0x96, "'ONENTERBACKWARD'" },
1162         { 0x97, "'ONENTERFORWARD'" },
1163         { 0x98, "'ONTIMER'" },
1164         { 0x99, "'OPTIONS'" },
1165         { 0x9A, "'PASSWORD'" },
1166         { 0x9B, "'RESET'" },
1167         { 0x9C, "'SET'" },
1168         { 0x9D, "'TEXT'" },
1169         { 0x9E, "'TOP'" },
1170         { 0x9F, "'UNKNOWN'" },
1171         { 0xA0, "'WRAP'" },
1172         { 0xA1, "'www.'" },
1173
1174         { 0x00, NULL }
1175 };
1176
1177 /***** Token code page aggregation *****/
1178 static const value_valuestring wbxml_wmlc10_global[] = {
1179         { 0, wbxml_wmlc10_global_cp0 },
1180         { 0, NULL }
1181 };
1182
1183 static const value_valuestring wbxml_wmlc10_tags[] = {
1184         { 0, wbxml_wmlc10_tags_cp0 },
1185         { 0, NULL }
1186 };
1187
1188 static const value_valuestring wbxml_wmlc10_attrStart[] = {
1189         { 0, wbxml_wmlc10_attrStart_cp0 },
1190         { 0, NULL }
1191 };
1192
1193 static const value_valuestring wbxml_wmlc10_attrValue[] = {
1194         { 0, wbxml_wmlc10_attrValue_cp0 },
1195         { 0, NULL }
1196 };
1197
1198 static const wbxml_decoding decode_wmlc_10 = {
1199     "Wireless Markup Language 1.0",
1200     "WML 1.0",
1201     { ext_t_0_wml_10, ext_t_1_wml_10, ext_t_2_wml_10 },
1202         default_opaque_binary_tag,
1203         default_opaque_literal_tag,
1204         default_opaque_binary_attr,
1205         default_opaque_literal_attr,
1206     wbxml_wmlc10_global,
1207     wbxml_wmlc10_tags,
1208     wbxml_wmlc10_attrStart,
1209     wbxml_wmlc10_attrValue
1210 };
1211
1212
1213
1214
1215 /* WML 1.1
1216  * 
1217  * Wireless Markup Language
1218  ***************************************/
1219
1220 /*****   Global extension tokens   *****/
1221 /* Same as in WML 1.0 */
1222
1223 /*****         Tag tokens          *****/
1224 static const value_string wbxml_wmlc11_tags_cp0[] = {
1225         /* 0x00 -- 0x04 GLOBAL */
1226         /* 0x05 -- 0x1B */
1227         { 0x1C, "a" },
1228         { 0x1D, "td" },
1229         { 0x1E, "tr" },
1230         { 0x1F, "table" },
1231         { 0x20, "p" },
1232         { 0x21, "postfield" },
1233         { 0x22, "anchor" },
1234         { 0x23, "access" },
1235         { 0x24, "b" },
1236         { 0x25, "big" },
1237         { 0x26, "br" },
1238         { 0x27, "card" },
1239         { 0x28, "do" },
1240         { 0x29, "em" },
1241         { 0x2A, "fieldset" },
1242         { 0x2B, "go" },
1243         { 0x2C, "head" },
1244         { 0x2D, "i" },
1245         { 0x2E, "img" },
1246         { 0x2F, "input" },
1247         { 0x30, "meta" },
1248         { 0x31, "noop" },
1249         { 0x32, "prev" },
1250         { 0x33, "onevent" },
1251         { 0x34, "optgroup" },
1252         { 0x35, "option" },
1253         { 0x36, "refresh" },
1254         { 0x37, "select" },
1255         { 0x38, "small" },
1256         { 0x39, "strong" },
1257         /* 0x3A */
1258         { 0x3B, "template" },
1259         { 0x3C, "timer" },
1260         { 0x3D, "u" },
1261         { 0x3E, "setvar" },
1262         { 0x3F, "wml" },
1263
1264         { 0x00, NULL }
1265 };
1266
1267 /*****    Attribute Start tokens   *****/
1268 static const value_string wbxml_wmlc11_attrStart_cp0[] = {
1269         /* 0x00 -- 0x04 GLOBAL */
1270         { 0x05, "accept-charset=" },
1271         { 0x06, "align='bottom'" },
1272         { 0x07, "align='center'" },
1273         { 0x08, "align='left'" },
1274         { 0x09, "align='middle'" },
1275         { 0x0A, "align='right'" },
1276         { 0x0B, "align='top'" },
1277         { 0x0C, "alt=" },
1278         { 0x0D, "content=" },
1279         /* 0x0E */
1280         { 0x0F, "domain=" },
1281         { 0x10, "emptyok='false'" },
1282         { 0x11, "emptyok='true'" },
1283         { 0x12, "format=" },
1284         { 0x13, "height=" },
1285         { 0x14, "hspace=" },
1286         { 0x15, "ivalue=" },
1287         { 0x16, "iname=" },
1288         /* 0x17 */
1289         { 0x18, "label=" },
1290         { 0x19, "localsrc=" },
1291         { 0x1A, "maxlength=" },
1292         { 0x1B, "method='get'" },
1293         { 0x1C, "method='post'" },
1294         { 0x1D, "mode='nowrap'" },
1295         { 0x1E, "mode='wrap'" },
1296         { 0x1F, "multiple='false'" },
1297         { 0x20, "multiple='true'" },
1298         { 0x21, "name=" },
1299         { 0x22, "newcontext='false'" },
1300         { 0x23, "newcontext='true'" },
1301         { 0x24, "onpick=" },
1302         { 0x25, "onenterbackward=" },
1303         { 0x26, "onenterforward=" },
1304         { 0x27, "ontimer=" },
1305         { 0x28, "optional='false'" },
1306         { 0x29, "optional='true'" },
1307         { 0x2A, "path=" },
1308         /* 0x2B -- 0x2D */
1309         { 0x2E, "scheme=" },
1310         { 0x2F, "sendreferer='false'" },
1311         { 0x30, "sendreferer='true'" },
1312         { 0x31, "size=" },
1313         { 0x32, "src=" },
1314         { 0x33, "ordered='false'" },
1315         { 0x34, "ordered='true'" },
1316         { 0x35, "tabindex=" },
1317         { 0x36, "title=" },
1318         { 0x37, "type=" },
1319         { 0x38, "type='accept'" },
1320         { 0x39, "type='delete'" },
1321         { 0x3A, "type='help'" },
1322         { 0x3B, "type='password'" },
1323         { 0x3C, "type='onpick'" },
1324         { 0x3D, "type='onenterbackward'" },
1325         { 0x3E, "type='onenterforward'" },
1326         { 0x3F, "type='ontimer'" },
1327         /* 0x40 -- 0x44 GLOBAL */
1328         { 0x45, "type='options'" },
1329         { 0x46, "type='prev'" },
1330         { 0x47, "type='reset'" },
1331         { 0x48, "type='text'" },
1332         { 0x49, "type='vnd.'" },
1333         { 0x4A, "href=" },
1334         { 0x4B, "href='http://'" },
1335         { 0x4C, "href='https://'" },
1336         { 0x4D, "value=" },
1337         { 0x4E, "vspace=" },
1338         { 0x4F, "width=" },
1339         { 0x50, "xml:lang=" },
1340         /* 0x51 */
1341         { 0x52, "align=" },
1342         { 0x53, "columns=" },
1343         { 0x54, "class=" },
1344         { 0x55, "id=" },
1345         { 0x56, "forua='false'" },
1346         { 0x57, "forua='true'" },
1347         { 0x58, "src='http://'" },
1348         { 0x59, "src='https://'" },
1349         { 0x5A, "http-equiv=" },
1350         { 0x5B, "http-equiv='Content-Type'" },
1351         { 0x5C, "content='application/vnd.wap.wmlc;charset='" },
1352         { 0x5D, "http-equiv='Expires'" },
1353
1354         { 0x00, NULL }
1355 };
1356
1357 /*****    Attribute Value tokens   *****/
1358 static const value_string wbxml_wmlc11_attrValue_cp0[] = {
1359         /* 0x80 -- 0x84 GLOBAL */
1360         { 0x85, "'.com/'" },
1361         { 0x86, "'.edu/'" },
1362         { 0x87, "'.net/'" },
1363         { 0x88, "'.org/'" },
1364         { 0x89, "'accept'" },
1365         { 0x8A, "'bottom'" },
1366         { 0x8B, "'clear'" },
1367         { 0x8C, "'delete'" },
1368         { 0x8D, "'help'" },
1369         { 0x8E, "'http://'" },
1370         { 0x8F, "'http://www.'" },
1371         { 0x90, "'https://'" },
1372         { 0x91, "'https://www.'" },
1373         /* 0x92 */
1374         { 0x93, "'middle'" },
1375         { 0x94, "'nowrap'" },
1376         { 0x95, "'onpick'" },
1377         { 0x96, "'onenterbackward'" },
1378         { 0x97, "'onenterforward'" },
1379         { 0x98, "'ontimer'" },
1380         { 0x99, "'options'" },
1381         { 0x9A, "'password'" },
1382         { 0x9B, "'reset'" },
1383         /* 0x9C */
1384         { 0x9D, "'text'" },
1385         { 0x9E, "'top'" },
1386         { 0x9F, "'unknown'" },
1387         { 0xA0, "'wrap'" },
1388         { 0xA1, "'www.'" },
1389
1390         { 0x00, NULL }
1391 };
1392
1393 /***** Token code page aggregation *****/
1394 static const value_valuestring wbxml_wmlc11_global[] = {
1395         { 0, wbxml_wmlc10_global_cp0 }, /* Same as WML 1.0 */
1396         { 0, NULL }
1397 };
1398
1399 static const value_valuestring wbxml_wmlc11_tags[] = {
1400         { 0, wbxml_wmlc11_tags_cp0 },
1401         { 0, NULL }
1402 };
1403
1404 static const value_valuestring wbxml_wmlc11_attrStart[] = {
1405         { 0, wbxml_wmlc11_attrStart_cp0 },
1406         { 0, NULL }
1407 };
1408
1409 static const value_valuestring wbxml_wmlc11_attrValue[] = {
1410         { 0, wbxml_wmlc11_attrValue_cp0 },
1411         { 0, NULL }
1412 };
1413
1414 static const wbxml_decoding decode_wmlc_11 = {
1415     "Wireless Markup Language 1.1",
1416     "WML 1.1",
1417     { ext_t_0_wml_10, ext_t_1_wml_10, ext_t_2_wml_10 },
1418         default_opaque_binary_tag,
1419         default_opaque_literal_tag,
1420         default_opaque_binary_attr,
1421         default_opaque_literal_attr,
1422     wbxml_wmlc11_global,
1423     wbxml_wmlc11_tags,
1424     wbxml_wmlc11_attrStart,
1425     wbxml_wmlc11_attrValue
1426 };
1427
1428
1429
1430
1431
1432 /* WML 1.2
1433  * 
1434  * Wireless Markup Language
1435  ***************************************/
1436
1437 /*****   Global extension tokens   *****/
1438 /* Same as in WML 1.0 */
1439
1440 /*****         Tag tokens          *****/
1441 static const value_string wbxml_wmlc12_tags_cp0[] = {
1442         /* 0x00 -- 0x04 GLOBAL */
1443         /* 0x05 -- 0x1A */
1444         { 0x1B, "pre" },
1445         { 0x1C, "a" },
1446         { 0x1D, "td" },
1447         { 0x1E, "tr" },
1448         { 0x1F, "table" },
1449         { 0x20, "p" },
1450         { 0x21, "postfield" },
1451         { 0x22, "anchor" },
1452         { 0x23, "access" },
1453         { 0x24, "b" },
1454         { 0x25, "big" },
1455         { 0x26, "br" },
1456         { 0x27, "card" },
1457         { 0x28, "do" },
1458         { 0x29, "em" },
1459         { 0x2A, "fieldset" },
1460         { 0x2B, "go" },
1461         { 0x2C, "head" },
1462         { 0x2D, "i" },
1463         { 0x2E, "img" },
1464         { 0x2F, "input" },
1465         { 0x30, "meta" },
1466         { 0x31, "noop" },
1467         { 0x32, "prev" },
1468         { 0x33, "onevent" },
1469         { 0x34, "optgroup" },
1470         { 0x35, "option" },
1471         { 0x36, "refresh" },
1472         { 0x37, "select" },
1473         { 0x38, "small" },
1474         { 0x39, "strong" },
1475         /* 0x3A */
1476         { 0x3B, "template" },
1477         { 0x3C, "timer" },
1478         { 0x3D, "u" },
1479         { 0x3E, "setvar" },
1480         { 0x3F, "wml" },
1481
1482         { 0x00, NULL }
1483 };
1484
1485 /*****    Attribute Start tokens   *****/
1486 static const value_string wbxml_wmlc12_attrStart_cp0[] = {
1487         /* 0x00 -- 0x04 GLOBAL */
1488         { 0x05, "accept-charset=" },
1489         { 0x06, "align='bottom'" },
1490         { 0x07, "align='center'" },
1491         { 0x08, "align='left'" },
1492         { 0x09, "align='middle'" },
1493         { 0x0A, "align='right'" },
1494         { 0x0B, "align='top'" },
1495         { 0x0C, "alt=" },
1496         { 0x0D, "content=" },
1497         /* 0x0E */
1498         { 0x0F, "domain=" },
1499         { 0x10, "emptyok='false'" },
1500         { 0x11, "emptyok='true'" },
1501         { 0x12, "format=" },
1502         { 0x13, "height=" },
1503         { 0x14, "hspace=" },
1504         { 0x15, "ivalue=" },
1505         { 0x16, "iname=" },
1506         /* 0x17 */
1507         { 0x18, "label=" },
1508         { 0x19, "localsrc=" },
1509         { 0x1A, "maxlength=" },
1510         { 0x1B, "method='get'" },
1511         { 0x1C, "method='post'" },
1512         { 0x1D, "mode='nowrap'" },
1513         { 0x1E, "mode='wrap'" },
1514         { 0x1F, "multiple='false'" },
1515         { 0x20, "multiple='true'" },
1516         { 0x21, "name=" },
1517         { 0x22, "newcontext='false'" },
1518         { 0x23, "newcontext='true'" },
1519         { 0x24, "onpick=" },
1520         { 0x25, "onenterbackward=" },
1521         { 0x26, "onenterforward=" },
1522         { 0x27, "ontimer=" },
1523         { 0x28, "optional='false'" },
1524         { 0x29, "optional='true'" },
1525         { 0x2A, "path=" },
1526         /* 0x2B -- 0x2D */
1527         { 0x2E, "scheme=" },
1528         { 0x2F, "sendreferer='false'" },
1529         { 0x30, "sendreferer='true'" },
1530         { 0x31, "size=" },
1531         { 0x32, "src=" },
1532         { 0x33, "ordered='false'" },
1533         { 0x34, "ordered='true'" },
1534         { 0x35, "tabindex=" },
1535         { 0x36, "title=" },
1536         { 0x37, "type=" },
1537         { 0x38, "type='accept'" },
1538         { 0x39, "type='delete'" },
1539         { 0x3A, "type='help'" },
1540         { 0x3B, "type='password'" },
1541         { 0x3C, "type='onpick'" },
1542         { 0x3D, "type='onenterbackward'" },
1543         { 0x3E, "type='onenterforward'" },
1544         { 0x3F, "type='ontimer'" },
1545         /* 0x40 -- 0x44 GLOBAL */
1546         { 0x45, "type='options'" },
1547         { 0x46, "type='prev'" },
1548         { 0x47, "type='reset'" },
1549         { 0x48, "type='text'" },
1550         { 0x49, "type='vnd.'" },
1551         { 0x4A, "href=" },
1552         { 0x4B, "href='http://'" },
1553         { 0x4C, "href='https://'" },
1554         { 0x4D, "value=" },
1555         { 0x4E, "vspace=" },
1556         { 0x4F, "width=" },
1557         { 0x50, "xml:lang=" },
1558         /* 0x51 */
1559         { 0x52, "align=" },
1560         { 0x53, "columns=" },
1561         { 0x54, "class=" },
1562         { 0x55, "id=" },
1563         { 0x56, "forua='false'" },
1564         { 0x57, "forua='true'" },
1565         { 0x58, "src='http://'" },
1566         { 0x59, "src='https://'" },
1567         { 0x5A, "http-equiv=" },
1568         { 0x5B, "http-equiv='Content-Type'" },
1569         { 0x5C, "content='application/vnd.wap.wmlc;charset='" },
1570         { 0x5D, "http-equiv='Expires'" },
1571         { 0x5E, "accesskey=" },
1572         { 0x5F, "enctype=" },
1573         { 0x60, "enctype='application/x-www-form-urlencoded'" },
1574         { 0x61, "enctype='multipart/form-data'" },
1575
1576         { 0x00, NULL }
1577 };
1578
1579 /*****    Attribute Value tokens   *****/
1580 /* Same as in WML 1.1 */
1581
1582 /***** Token code page aggregation *****/
1583 static const value_valuestring wbxml_wmlc12_global[] = {
1584         { 0, wbxml_wmlc10_global_cp0 }, /* Same as WML 1.0 */
1585         { 0, NULL }
1586 };
1587
1588 static const value_valuestring wbxml_wmlc12_tags[] = {
1589         { 0, wbxml_wmlc12_tags_cp0 },
1590         { 0, NULL }
1591 };
1592
1593 static const value_valuestring wbxml_wmlc12_attrStart[] = {
1594         { 0, wbxml_wmlc12_attrStart_cp0 },
1595         { 0, NULL }
1596 };
1597
1598 static const value_valuestring wbxml_wmlc12_attrValue[] = {
1599         { 0, wbxml_wmlc11_attrValue_cp0 }, /* Same as WML 1.1 */
1600         { 0, NULL }
1601 };
1602
1603 static const wbxml_decoding decode_wmlc_12 = {
1604     "Wireless Markup Language 1.2",
1605     "WML 1.2",
1606     { ext_t_0_wml_10, ext_t_1_wml_10, ext_t_2_wml_10 },
1607         default_opaque_binary_tag,
1608         default_opaque_literal_tag,
1609         default_opaque_binary_attr,
1610         default_opaque_literal_attr,
1611     wbxml_wmlc12_global,
1612     wbxml_wmlc12_tags,
1613     wbxml_wmlc12_attrStart,
1614     wbxml_wmlc12_attrValue
1615 };
1616
1617
1618
1619
1620
1621 /* WML 1.3
1622  * 
1623  * Wireless Markup Language
1624  ***************************************/
1625
1626 /*****   Global extension tokens   *****/
1627 /* Same as in WML 1.0 */
1628
1629 /*****         Tag tokens          *****/
1630 /* Same as in WML 1.2 */
1631
1632 /*****    Attribute Start tokens   *****/
1633 static const value_string wbxml_wmlc13_attrStart_cp0[] = {
1634         /* 0x00 -- 0x04 GLOBAL */
1635         { 0x05, "accept-charset=" },
1636         { 0x06, "align='bottom'" },
1637         { 0x07, "align='center'" },
1638         { 0x08, "align='left'" },
1639         { 0x09, "align='middle'" },
1640         { 0x0A, "align='right'" },
1641         { 0x0B, "align='top'" },
1642         { 0x0C, "alt=" },
1643         { 0x0D, "content=" },
1644         /* 0x0E */
1645         { 0x0F, "domain=" },
1646         { 0x10, "emptyok='false'" },
1647         { 0x11, "emptyok='true'" },
1648         { 0x12, "format=" },
1649         { 0x13, "height=" },
1650         { 0x14, "hspace=" },
1651         { 0x15, "ivalue=" },
1652         { 0x16, "iname=" },
1653         /* 0x17 */
1654         { 0x18, "label=" },
1655         { 0x19, "localsrc=" },
1656         { 0x1A, "maxlength=" },
1657         { 0x1B, "method='get'" },
1658         { 0x1C, "method='post'" },
1659         { 0x1D, "mode='nowrap'" },
1660         { 0x1E, "mode='wrap'" },
1661         { 0x1F, "multiple='false'" },
1662         { 0x20, "multiple='true'" },
1663         { 0x21, "name=" },
1664         { 0x22, "newcontext='false'" },
1665         { 0x23, "newcontext='true'" },
1666         { 0x24, "onpick=" },
1667         { 0x25, "onenterbackward=" },
1668         { 0x26, "onenterforward=" },
1669         { 0x27, "ontimer=" },
1670         { 0x28, "optional='false'" },
1671         { 0x29, "optional='true'" },
1672         { 0x2A, "path=" },
1673         /* 0x2B -- 0x2D */
1674         { 0x2E, "scheme=" },
1675         { 0x2F, "sendreferer='false'" },
1676         { 0x30, "sendreferer='true'" },
1677         { 0x31, "size=" },
1678         { 0x32, "src=" },
1679         { 0x33, "ordered='false'" },
1680         { 0x34, "ordered='true'" },
1681         { 0x35, "tabindex=" },
1682         { 0x36, "title=" },
1683         { 0x37, "type=" },
1684         { 0x38, "type='accept'" },
1685         { 0x39, "type='delete'" },
1686         { 0x3A, "type='help'" },
1687         { 0x3B, "type='password'" },
1688         { 0x3C, "type='onpick'" },
1689         { 0x3D, "type='onenterbackward'" },
1690         { 0x3E, "type='onenterforward'" },
1691         { 0x3F, "type='ontimer'" },
1692         /* 0x40 -- 0x44 GLOBAL */
1693         { 0x45, "type='options'" },
1694         { 0x46, "type='prev'" },
1695         { 0x47, "type='reset'" },
1696         { 0x48, "type='text'" },
1697         { 0x49, "type='vnd.'" },
1698         { 0x4A, "href=" },
1699         { 0x4B, "href='http://'" },
1700         { 0x4C, "href='https://'" },
1701         { 0x4D, "value=" },
1702         { 0x4E, "vspace=" },
1703         { 0x4F, "width=" },
1704         { 0x50, "xml:lang=" },
1705         /* 0x51 */
1706         { 0x52, "align=" },
1707         { 0x53, "columns=" },
1708         { 0x54, "class=" },
1709         { 0x55, "id=" },
1710         { 0x56, "forua='false'" },
1711         { 0x57, "forua='true'" },
1712         { 0x58, "src='http://'" },
1713         { 0x59, "src='https://'" },
1714         { 0x5A, "http-equiv=" },
1715         { 0x5B, "http-equiv='Content-Type'" },
1716         { 0x5C, "content='application/vnd.wap.wmlc;charset='" },
1717         { 0x5D, "http-equiv='Expires'" },
1718         { 0x5E, "accesskey=" },
1719         { 0x5F, "enctype=" },
1720         { 0x60, "enctype='application/x-www-form-urlencoded'" },
1721         { 0x61, "enctype='multipart/form-data'" },
1722         { 0x62, "xml:space='preserve'" },
1723         { 0x63, "xml:space='default'" },
1724         { 0x64, "cache-control='no-cache'" },
1725
1726         { 0x00, NULL }
1727 };
1728
1729 /*****    Attribute Value tokens   *****/
1730 /* Same as in WML 1.1 */
1731
1732 /***** Token code page aggregation *****/
1733 static const value_valuestring wbxml_wmlc13_global[] = {
1734         { 0, wbxml_wmlc10_global_cp0 }, /* Same as WML 1.0 */
1735         { 0, NULL }
1736 };
1737
1738 static const value_valuestring wbxml_wmlc13_tags[] = {
1739         { 0, wbxml_wmlc12_tags_cp0 },
1740         { 0, NULL }
1741 };
1742
1743 static const value_valuestring wbxml_wmlc13_attrStart[] = {
1744         { 0, wbxml_wmlc13_attrStart_cp0 },
1745         { 0, NULL }
1746 };
1747
1748 static const value_valuestring wbxml_wmlc13_attrValue[] = {
1749         { 0, wbxml_wmlc11_attrValue_cp0 }, /* Same as WML 1.1 */
1750         { 0, NULL }
1751 };
1752
1753 static const wbxml_decoding decode_wmlc_13 = {
1754     "Wireless Markup Language 1.3",
1755     "WML 1.3",
1756     { ext_t_0_wml_10, ext_t_1_wml_10, ext_t_2_wml_10 },
1757         default_opaque_binary_tag,
1758         default_opaque_literal_tag,
1759         default_opaque_binary_attr,
1760         default_opaque_literal_attr,
1761     wbxml_wmlc13_global,
1762     wbxml_wmlc13_tags,
1763     wbxml_wmlc13_attrStart,
1764     wbxml_wmlc13_attrValue
1765 };
1766
1767
1768
1769
1770
1771 /* SI 1.0
1772  * 
1773  * Service Indication
1774  ***************************************/
1775
1776 /*****   Global extension tokens   *****/
1777
1778 /*****         Tag tokens          *****/
1779 static const value_string wbxml_sic10_tags_cp0[] = {
1780         /* 0x00 -- 0x04 GLOBAL */
1781         { 0x05, "si" },
1782         { 0x06, "indication" },
1783         { 0x07, "info" },
1784         { 0x08, "item" },
1785
1786         { 0x00, NULL }
1787 };
1788
1789 /*****    Attribute Start tokens   *****/
1790 static const value_string wbxml_sic10_attrStart_cp0[] = {
1791         /* 0x00 -- 0x04 GLOBAL */
1792         { 0x05, "action='signal-none'" },
1793         { 0x06, "action='signal-low'" },
1794         { 0x07, "action='signal-medium'" },
1795         { 0x08, "action='signal-high'" },
1796         { 0x09, "action='delete'" },
1797         { 0x0a, "created=" },
1798         { 0x0b, "href=" },
1799         { 0x0c, "href='http://'" },
1800         { 0x0d, "href='http://www.'" },
1801         { 0x0e, "href='https://'" },
1802         { 0x0f, "href='https://www.'" },
1803         { 0x10, "si-expires=" },
1804         { 0x11, "si-id=" },
1805         { 0x12, "class=" },
1806
1807         { 0x00, NULL }
1808 };
1809
1810 /*****    Attribute Value tokens   *****/
1811 static const value_string wbxml_sic10_attrValue_cp0[] = {
1812         /* 0x80 -- 0x84 GLOBAL */
1813         { 0x85, "'.com/'" },
1814         { 0x86, "'.edu/'" },
1815         { 0x87, "'.net/'" },
1816         { 0x88, "'.org/'" },
1817
1818         { 0x00, NULL }
1819 };
1820
1821 /***** Token code page aggregation *****/
1822 static const value_valuestring wbxml_sic10_tags[] = {
1823         { 0, wbxml_sic10_tags_cp0 },
1824         { 0, NULL }
1825 };
1826
1827 static const value_valuestring wbxml_sic10_attrStart[] = {
1828         { 0, wbxml_sic10_attrStart_cp0 },
1829         { 0, NULL }
1830 };
1831
1832 static const value_valuestring wbxml_sic10_attrValue[] = {
1833         { 0, wbxml_sic10_attrValue_cp0 },
1834         { 0, NULL }
1835 };
1836
1837 static const wbxml_decoding decode_sic_10 = {
1838     "Service Indication 1.0",
1839     "SI 1.0",
1840     { NULL, NULL, NULL },
1841         default_opaque_binary_tag,
1842         default_opaque_literal_tag,
1843         sic10_opaque_binary_attr,
1844         sic10_opaque_literal_attr,
1845     NULL,
1846     wbxml_sic10_tags,
1847     wbxml_sic10_attrStart,
1848     wbxml_sic10_attrValue
1849 };
1850
1851
1852
1853
1854
1855 /* SL 1.0
1856  * 
1857  * Service Loading
1858  ***************************************/
1859
1860 /*****   Global extension tokens   *****/
1861
1862 /*****         Tag tokens          *****/
1863 static const value_string wbxml_slc10_tags_cp0[] = {
1864         /* 0x00 -- 0x04 GLOBAL */
1865         { 0x05, "sl" },
1866
1867         { 0x00, NULL }
1868 };
1869
1870 /*****    Attribute Start tokens   *****/
1871 static const value_string wbxml_slc10_attrStart_cp0[] = {
1872         /* 0x00 -- 0x04 GLOBAL */
1873         { 0x05, "action='execute-low'" },
1874         { 0x06, "action='execute-high'" },
1875         { 0x07, "action='cache'" },
1876         { 0x08, "href=" },
1877         { 0x09, "href='http://'" },
1878         { 0x0a, "href='http://www.'" },
1879         { 0x0b, "href='https://'" },
1880         { 0x0c, "href='https://www.'" },
1881
1882         { 0x00, NULL }
1883 };
1884
1885 /*****    Attribute Value tokens   *****/
1886 /* Same as in SI 1.0 */
1887
1888 /***** Token code page aggregation *****/
1889 static const value_valuestring wbxml_slc10_tags[] = {
1890         { 0, wbxml_slc10_tags_cp0 },
1891         { 0, NULL }
1892 };
1893
1894 static const value_valuestring wbxml_slc10_attrStart[] = {
1895         { 0, wbxml_slc10_attrStart_cp0 },
1896         { 0, NULL }
1897 };
1898
1899 static const value_valuestring wbxml_slc10_attrValue[] = {
1900         { 0, wbxml_sic10_attrValue_cp0 }, /* Same as SI 1.0 */
1901         { 0, NULL }
1902 };
1903
1904 static const wbxml_decoding decode_slc_10 = {
1905     "Service Loading 1.0",
1906     "SL 1.0",
1907     { NULL, NULL, NULL },
1908         default_opaque_binary_tag,
1909         default_opaque_literal_tag,
1910         default_opaque_binary_attr,
1911         default_opaque_literal_attr,
1912     NULL,
1913     wbxml_slc10_tags,
1914     wbxml_slc10_attrStart,
1915     wbxml_slc10_attrValue
1916 };
1917
1918
1919
1920
1921
1922 /* CO 1.0
1923  * 
1924  * Cache Operation
1925  ***************************************/
1926
1927 /*****   Global extension tokens   *****/
1928
1929 /*****         Tag tokens          *****/
1930 static const value_string wbxml_coc10_tags_cp0[] = {
1931         /* 0x00 -- 0x04 GLOBAL */
1932         { 0x05, "co" },
1933         { 0x06, "invalidate-object" },
1934         { 0x07, "invalidate-service" },
1935
1936         { 0x00, NULL }
1937 };
1938
1939 /*****    Attribute Start tokens   *****/
1940 static const value_string wbxml_coc10_attrStart_cp0[] = {
1941         /* 0x00 -- 0x04 GLOBAL */
1942         { 0x05, "uri=" },
1943         { 0x06, "uri='http://'" },
1944         { 0x07, "uri='http://www.'" },
1945         { 0x08, "uri='https://'" },
1946         { 0x09, "uri='https://www.'" },
1947
1948         { 0x00, NULL }
1949 };
1950
1951 /*****    Attribute Value tokens   *****/
1952 /* Same as in SI 1.0 */
1953
1954 /***** Token code page aggregation *****/
1955 static const value_valuestring wbxml_coc10_tags[] = {
1956         { 0, wbxml_coc10_tags_cp0 },
1957         { 0, NULL }
1958 };
1959
1960 static const value_valuestring wbxml_coc10_attrStart[] = {
1961         { 0, wbxml_coc10_attrStart_cp0 },
1962         { 0, NULL }
1963 };
1964
1965 static const value_valuestring wbxml_coc10_attrValue[] = {
1966         { 0, wbxml_sic10_attrValue_cp0 }, /* Same as SI 1.0 */
1967         { 0, NULL }
1968 };
1969
1970 static const wbxml_decoding decode_coc_10 = {
1971     "Cache Operation 1.0",
1972     "CO 1.0",
1973     { NULL, NULL, NULL },
1974         default_opaque_binary_tag,
1975         default_opaque_literal_tag,
1976         default_opaque_binary_attr,
1977         default_opaque_literal_attr,
1978     NULL,
1979     wbxml_coc10_tags,
1980     wbxml_coc10_attrStart,
1981     wbxml_coc10_attrValue
1982 };
1983
1984
1985
1986
1987
1988 /* PROV 1.0
1989  *
1990  * Client Provisioning
1991  ***************************************/
1992
1993 /*****   Global extension tokens   *****/
1994
1995 /*****         Tag tokens          *****/
1996 static const value_string wbxml_provc10_tags_cp0[] = {
1997         /* 0x00 -- 0x04 GLOBAL */
1998         { 0x05, "wap-provisioningdoc" },
1999         { 0x06, "characteristic" },
2000         { 0x07, "parm" },
2001
2002         { 0x00, NULL }
2003 };
2004 static const value_string wbxml_provc10_tags_cp1[] = {
2005         /* 0x00 -- 0x04 GLOBAL */
2006         /* 0x05 */
2007         { 0x06, "characteristic" },
2008         { 0x07, "parm" },
2009
2010         { 0x00, NULL }
2011 };
2012
2013 /*****    Attribute Start tokens   *****/
2014 static const value_string wbxml_provc10_attrStart_cp0[] = {
2015         /* 0x00 -- 0x04 GLOBAL */
2016         { 0x05, "name=" },
2017         { 0x06, "value=" },
2018         { 0x07, "name='NAME'" },
2019         { 0x08, "name='NAP-ADDRESS'" },
2020         { 0x09, "name='NAP-ADDRTYPE'" },
2021         { 0x0A, "name='CALLTYPE'" },
2022         { 0x0B, "name='VALIDUNTIL'" },
2023         { 0x0C, "name='AUTHTYPE'" },
2024         { 0x0D, "name='AUTHNAME'" },
2025         { 0x0E, "name='AUTHSECRET'" },
2026         { 0x0F, "name='LINGER'" },
2027         { 0x10, "name='BEARER'" },
2028         { 0x11, "name='NAPID'" },
2029         { 0x12, "name='COUNTRY'" },
2030         { 0x13, "name='NETWORK'" },
2031         { 0x14, "name='INTERNET'" },
2032         { 0x15, "name='PROXY-ID'" },
2033         { 0x16, "name='PROXY-PROVIDER-ID'" },
2034         { 0x17, "name='DOMAIN'" },
2035         { 0x18, "name='PROVURL'" },
2036         { 0x19, "name='PXAUTH-TYPE'" },
2037         { 0x1A, "name='PXAUTH-ID'" },
2038         { 0x1B, "name='PXAUTH-PW'" },
2039         { 0x1C, "name='STARTPAGE'" },
2040         { 0x1D, "name='BASAUTH-ID'" },
2041         { 0x1E, "name='BASAUTH-PW'" },
2042         { 0x1F, "name='PUSHENABLED'" },
2043         { 0x20, "name='PXADDR'" },
2044         { 0x21, "name='PXADDRTYPE'" },
2045         { 0x22, "name='TO-NAPID'" },
2046         { 0x23, "name='PORTNBR'" },
2047         { 0x24, "name='SERVICE'" },
2048         { 0x25, "name='LINKSPEED'" },
2049         { 0x26, "name='DNLINKSPEED'" },
2050         { 0x27, "name='LOCAL-ADDR'" },
2051         { 0x28, "name='LOCAL-ADDRTYPE'" },
2052         { 0x29, "name='CONTEXT-ALLOW'" },
2053         { 0x2A, "name='TRUST'" },
2054         { 0x2B, "name='MASTER'" },
2055         { 0x2C, "name='SID'" },
2056         { 0x2D, "name='SOC'" },
2057         { 0x2E, "name='WSP-VERSION'" },
2058         { 0x2F, "name='PHYSICAL-PROXY-ID'" },
2059         { 0x30, "name='CLIENT-ID'" },
2060         { 0x31, "name='DELIVERY-ERR-SDU'" },
2061         { 0x32, "name='DELIVERY-ORDER'" },
2062         { 0x33, "name='TRAFFIC-CLASS'" },
2063         { 0x34, "name='MAX-SDU-SIZE'" },
2064         { 0x35, "name='MAX-BITRATE-UPLINK'" },
2065         { 0x36, "name='MAX-BITRATE-DNLINK'" },
2066         { 0x37, "name='RESIDUAL-BER'" },
2067         { 0x38, "name='SDU-ERROR-RATIO'" },
2068         { 0x39, "name='TRAFFIC-HANDL-PRIO'" },
2069         { 0x3A, "name='TRANSFER-DELAY'" },
2070         { 0x3B, "name='GUARANTEED-BITRATE-UPLINK'" },
2071         { 0x3C, "name='GUARANTEED-BITRATE-DNLINK'" },
2072         { 0x3D, "name='PXADDR-FQDN'" },
2073         { 0x3E, "name='PROXY-PW'" },
2074         { 0x3F, "name='PPGAUTH-TYPE'" },
2075         /* 0x40 -- 0x44 GLOBAL */
2076         { 0x45, "version=" },
2077         { 0x46, "version='1.0'" },
2078         { 0x47, "name='PULLENABLED'" },
2079         { 0x48, "name='DNS-ADDR'" },
2080         { 0x49, "name='MAX-NUM-RETRY'" },
2081         { 0x4A, "name='FIRST-RETRY-TIMEOUT'" },
2082         { 0x4B, "name='REREG-THRESHOLD'" },
2083         { 0x4C, "name='T-BIT'" },
2084         /* 0x4D */
2085         { 0x4E, "name='AUTH-ENTITY'" },
2086         { 0x4F, "name='SPI'" },
2087         { 0x50, "type=" },
2088         { 0x51, "type='PXLOGICAL'" },
2089         { 0x52, "type='PXPHYSICAL'" },
2090         { 0x53, "type='PORT'" },
2091         { 0x54, "type='VALIDITY'" },
2092         { 0x55, "type='NAPDEF'" },
2093         { 0x56, "type='BOOTSTRAP'" },
2094         { 0x57, "type='VENDORCONFIG'" },
2095         { 0x58, "type='CLIENTIDENTITY'" },
2096         { 0x59, "type='PXAUTHINFO'" },
2097         { 0x5A, "type='NAPAUTHINFO'" },
2098         { 0x5B, "type='ACCESS'" },
2099
2100         { 0x00, NULL }
2101 };
2102 static const value_string wbxml_provc10_attrStart_cp1[] = {
2103         /* 0x00 -- 0x04 GLOBAL */
2104         /* 0x05 -- 0x06 */
2105         { 0x07, "name='NAME'" },
2106         /* 0x08 -- 0x13 */
2107         { 0x14, "name='INTERNET'" },
2108         /* 0x15 -- 0x1B */
2109         { 0x1C, "name='STARTPAGE'" },
2110         /* 0x1D -- 0x21 */
2111         { 0x22, "name='TO-NAPID'" },
2112         { 0x23, "name='PORTNBR'" },
2113         { 0x24, "name='SERVICE'" },
2114         /* 0x25 -- 0x2D */
2115         { 0x2E, "name='AACCEPT'" },
2116         { 0x2F, "name='AAUTHDATA'" },
2117         { 0x30, "name='AAUTHLEVEL'" },
2118         { 0x31, "name='AAUTHNAME'" },
2119         { 0x32, "name='AAUTHSECRET'" },
2120         { 0x33, "name='AAUTHTYPE'" },
2121         { 0x34, "name='ADDR'" },
2122         { 0x35, "name='ADDRTYPE'" },
2123         { 0x36, "name='APPID'" },
2124         { 0x37, "name='APROTOCOL'" },
2125         { 0x38, "name='PROVIDER-ID'" },
2126         { 0x39, "name='TO-PROXY'" },
2127         { 0x3A, "name='URI'" },
2128         { 0x3B, "name='RULE'" },
2129         /* 0x3C -- 0x3F */
2130         /* 0x40 -- 0x44 GLOBAL */
2131         /* 0x45 -- 0x4F */
2132         { 0x50, "type=" },
2133         /* 0x51 -- 0x52 */
2134         { 0x53, "type='PORT'" },
2135         /* 0x54 */
2136         { 0x55, "type='APPLICATION'" },
2137         { 0x56, "type='APPADDR'" },
2138         { 0x57, "type='APPAUTH'" },
2139         { 0x58, "type='CLIENTIDENTITY'" },
2140         { 0x59, "type='RESOURCE'" },
2141         /* 0x5A -- 0x7F */
2142
2143         { 0x00, NULL }
2144 };
2145
2146 /*****    Attribute Start tokens   *****/
2147 static const value_string wbxml_provc10_attrValue_cp0[] = {
2148         /* 0x80 -- 0x84 GLOBAL */
2149         { 0x85, "'IPV4'" },
2150         { 0x86, "'IPV6'" },
2151         { 0x87, "'E164'" },
2152         { 0x88, "'ALPHA'" },
2153         { 0x89, "'APN'" },
2154         { 0x8A, "'SCODE'" },
2155         { 0x8B, "'TETRA-ITSI'" },
2156         { 0x8C, "'MAN'" },
2157         /* 0x8D -- 0x8F */
2158         { 0x90, "'ANALOG-MODEM'" },
2159         { 0x91, "'V.120'" },
2160         { 0x92, "'V.110'" },
2161         { 0x93, "'X.31'" },
2162         { 0x94, "'BIT-TRANSPARENT'" },
2163         { 0x95, "'DIRECT-ASYNCHRONOUS-DATA-SERVICE'" },
2164         /* 0x96 -- 0x99 */
2165         { 0x9A, "'PAP'" },
2166         { 0x9B, "'CHAP'" },
2167         { 0x9C, "'HTTP-BASIC'" },
2168         { 0x9D, "'HTTP-DIGEST'" },
2169         { 0x9E, "'WTLS-SS'" },
2170         { 0x9F, "'MD5'" },
2171         /* 0xA0 -- 0xA1 */
2172         { 0xA2, "'GSM-USSD'" },
2173         { 0xA3, "'GSM-SMS'" },
2174         { 0xA4, "'ANSI-136-GUTS'" },
2175         { 0xA5, "'IS-95-CDMA-SMS'" },
2176         { 0xA6, "'IS-95-CDMA-CSD'" },
2177         { 0xA7, "'IS-95-CDMA-PACKET'" },
2178         { 0xA8, "'ANSI-136-CSD'" },
2179         { 0xA9, "'ANSI-136-GPRS'" },
2180         { 0xAA, "'GSM-CSD'" },
2181         { 0xAB, "'GSM-GPRS'" },
2182         { 0xAC, "'AMPS-CDPD'" },
2183         { 0xAD, "'PDC-CSD'" },
2184         { 0xAE, "'PDC-PACKET'" },
2185         { 0xAF, "'IDEN-SMS'" },
2186         { 0xB0, "'IDEN-CSD'" },
2187         { 0xB1, "'IDEN-PACKET'" },
2188         { 0xB2, "'FLEX/REFLEX'" },
2189         { 0xB3, "'PHS-SMS'" },
2190         { 0xB4, "'PHS-CSD'" },
2191         { 0xB5, "'TETRA-SDS'" },
2192         { 0xB6, "'TETRA-PACKET'" },
2193         { 0xB7, "'ANSI-136-GHOST'" },
2194         { 0xB8, "'MOBITEX-MPAK'" },
2195         { 0xB9, "'CDMA2000-IX-SIMPLE-IP'" },
2196         { 0xBA, "'CDMA2000-IX-MOBILE-IP'" },
2197         /* 0xBB -- 0xBF */
2198         /* 0xC0 -- 0xC4 GLOBAL */
2199         { 0xC5, "'AUTOBAUDING'" },
2200         /* 0xC6 -- 0xC9 */
2201         { 0xCA, "'CL-WSP'" },
2202         { 0xCB, "'CO-WSP'" },
2203         { 0xCC, "'CL-SEC-WSP'" },
2204         { 0xCD, "'CO-SEC-WSP'" },
2205         { 0xCE, "'CL-SEC-WTA'" },
2206         { 0xCF, "'CO-SEC-WTA'" },
2207         { 0xD0, "'OTA-HTTP-TO'" },
2208         { 0xD1, "'OTA-HTTP-TLS-TO'" },
2209         { 0xD2, "'OTA-HTTP-PO'" },
2210         { 0xD3, "'OTA-HTTP-TLS-PO'" },
2211         /* 0xD4 -- 0xFF */
2212
2213         { 0x00, NULL }
2214 };
2215 static const value_string wbxml_provc10_attrValue_cp1[] = {
2216         /* 0x80 -- 0x84 GLOBAL */
2217         /* 0x85 */
2218         { 0x86, "'IPV6'" },
2219         { 0x87, "'E164'" },
2220         { 0x88, "'ALPHA'" },
2221         { 0x8D, "'APPSRV'" },
2222         { 0x8E, "'OBEX'" },
2223         /* 0x8F */
2224
2225         /* XXX - Errors that require a fix in the OMA/WAP Client Provisioning specs:
2226         { 0xXXX, "','" },
2227         { 0xXXX, "'HTTP-'" },
2228         { 0xXXX, "'BASIC'" },
2229         { 0xXXX, "'DIGEST'" },
2230         */
2231
2232         { 0xE0, "'AAA'" },
2233         { 0xE1, "'HA'" },
2234
2235         { 0x00, NULL }
2236 };
2237
2238 /***** Token code page aggregation *****/
2239 static const value_valuestring wbxml_provc10_tags[] = {
2240         { 0, wbxml_provc10_tags_cp0 },
2241         { 1, wbxml_provc10_tags_cp1 },
2242         { 0, NULL }
2243 };
2244
2245 static const value_valuestring wbxml_provc10_attrStart[] = {
2246         { 0, wbxml_provc10_attrStart_cp0 },
2247         { 1, wbxml_provc10_attrStart_cp1 },
2248         { 0, NULL }
2249 };
2250
2251 static const value_valuestring wbxml_provc10_attrValue[] = {
2252         { 0, wbxml_provc10_attrValue_cp0 },
2253         { 1, wbxml_provc10_attrValue_cp1 },
2254         { 0, NULL }
2255 };
2256
2257 static const wbxml_decoding decode_provc_10 = {
2258     "WAP Client Provisioning Document 1.0",
2259     "WAP ProvisioningDoc 1.0",
2260     { NULL, NULL, NULL },
2261         default_opaque_binary_tag,
2262         default_opaque_literal_tag,
2263         default_opaque_binary_attr,
2264         default_opaque_literal_attr,
2265     NULL,
2266     wbxml_provc10_tags,
2267     wbxml_provc10_attrStart,
2268     wbxml_provc10_attrValue
2269 };
2270
2271
2272
2273
2274
2275 /* EMN 1.0
2276  * 
2277  * Email Notification
2278  ***************************************/
2279
2280 /*****   Global extension tokens   *****/
2281
2282 /*****         Tag tokens          *****/
2283 static const value_string wbxml_emnc10_tags_cp0[] = {
2284         /* 0x00 -- 0x04 GLOBAL */
2285         { 0x05, "emn" },
2286
2287         { 0x00, NULL }
2288 };
2289
2290 /*****    Attribute Start tokens   *****/
2291 static const value_string wbxml_emnc10_attrStart_cp0[] = {
2292         /* 0x00 -- 0x04 GLOBAL */
2293         { 0x05, "timestamp=" },
2294         { 0x06, "mailbox=" },
2295         { 0x07, "mailbox='mailat:'" },
2296         { 0x08, "mailbox='pop://'" },
2297         { 0x09, "mailbox='imap://'" },
2298         { 0x0a, "mailbox='http://'" },
2299         { 0x0b, "mailbox='http://www.'" },
2300         { 0x0c, "mailbox='https://'" },
2301         { 0x0D, "mailbox='https://www.'" },
2302
2303         { 0x00, NULL }
2304 };
2305
2306 /*****    Attribute Value tokens   *****/
2307 /* Same as in SI 1.0 */
2308
2309 /***** Token code page aggregation *****/
2310 static const value_valuestring wbxml_emnc10_tags[] = {
2311         { 0, wbxml_emnc10_tags_cp0 },
2312         { 0, NULL }
2313 };
2314
2315 static const value_valuestring wbxml_emnc10_attrStart[] = {
2316         { 0, wbxml_emnc10_attrStart_cp0 },
2317         { 0, NULL }
2318 };
2319
2320 static const value_valuestring wbxml_emnc10_attrValue[] = {
2321         { 0, wbxml_sic10_attrValue_cp0 }, /* Same as SI 1.0 */
2322         { 0, NULL }
2323 };
2324
2325 static const wbxml_decoding decode_emnc_10 = {
2326     "E-Mail Notification 1.0",
2327     "EMN 1.0",
2328     { NULL, NULL, NULL },
2329         default_opaque_binary_tag,
2330         default_opaque_literal_tag,
2331         emnc10_opaque_binary_attr,
2332         emnc10_opaque_literal_attr,
2333     NULL,
2334     wbxml_emnc10_tags,
2335     wbxml_emnc10_attrStart,
2336     wbxml_emnc10_attrValue
2337 };
2338
2339
2340
2341
2342
2343 /* SyncML 1.0
2344  * 
2345  * SyncML Representation Protocol
2346  ***************************************/
2347
2348 /*****   Global extension tokens   *****/
2349
2350 /*****         Tag tokens          *****/
2351 static const value_string wbxml_syncmlc10_tags_cp0[] = { /* SyncML 1.0 */
2352         /* 0x00 -- 0x04 GLOBAL */
2353         { 0x05, "Add" },
2354         { 0x06, "Alert" },
2355         { 0x07, "Archive" },
2356         { 0x08, "Atomic" },
2357         { 0x09, "Chal" },
2358         { 0x0A, "Cmd" },
2359         { 0x0B, "CmdID" },
2360         { 0x0C, "CmdRef" },
2361         { 0x0D, "Copy" },
2362         { 0x0E, "Cred" },
2363         { 0x0F, "Data" },
2364         { 0x10, "Delete" },
2365         { 0x11, "Exec" },
2366         { 0x12, "Final" },
2367         { 0x13, "Get" },
2368         { 0x14, "Item" },
2369         { 0x15, "Lang" },
2370         { 0x16, "LocName" },
2371         { 0x17, "LocURI" },
2372         { 0x18, "Map" },
2373         { 0x19, "MapItem" },
2374         { 0x1A, "Meta" },
2375         { 0x1B, "MsgID" },
2376         { 0x1C, "MsgRef" },
2377         { 0x1D, "NoResp" },
2378         { 0x1E, "NoResults" },
2379         { 0x1F, "Put" },
2380         { 0x20, "Replace" },
2381         { 0x21, "RespURI" },
2382         { 0x22, "Results" },
2383         { 0x23, "Search" },
2384         { 0x24, "Sequence" },
2385         { 0x25, "SessionID" },
2386         { 0x26, "SftDel" },
2387         { 0x27, "Source" },
2388         { 0x28, "SourceRef" },
2389         { 0x29, "Status" },
2390         { 0x2A, "Sync" },
2391         { 0x2B, "SyncBody" },
2392         { 0x2C, "SyncHdr" },
2393         { 0x2D, "SyncML" },
2394         { 0x2E, "Target" },
2395         { 0x2F, "TargetRef" },
2396         /* 0x30 - Reserved */
2397         { 0x31, "VerDTD" },
2398         { 0x32, "VerProto" },
2399
2400         { 0x00, NULL }
2401 };
2402
2403 static const value_string wbxml_syncmlc10_tags_cp1[] = { /* MetInf 1.0 */
2404         /* 0x00 -- 0x04 GLOBAL */
2405         { 0x05, "Anchor" },
2406         { 0x06, "EMI" },
2407         { 0x07, "Format" },
2408         { 0x08, "FreeID" },
2409         { 0x09, "FreeMem" },
2410         { 0x0A, "Last" },
2411         { 0x0B, "Mark" },
2412         { 0x0C, "MaxMsgSize" },
2413         { 0x0D, "Mem" },
2414         { 0x0E, "MetInf" },
2415         { 0x0F, "Next" },
2416         { 0x10, "NextNonce" },
2417         { 0x11, "SharedMem" },
2418         { 0x12, "Size" },
2419         { 0x13, "Type" },
2420         { 0x14, "Version" },
2421
2422         { 0x00, NULL }
2423 };
2424
2425 /*****    Attribute Start tokens   *****/
2426
2427 /*****    Attribute Value tokens   *****/
2428
2429 /***** Token code page aggregation *****/
2430 static const value_valuestring wbxml_syncmlc10_tags[] = {
2431         { 0, wbxml_syncmlc10_tags_cp0 }, /* -//SYNCML//DTD SyncML 1.0//EN */
2432         { 1, wbxml_syncmlc10_tags_cp1 }, /* -//SYNCML//DTD MetInf 1.0//EN */
2433         { 0, NULL }
2434 };
2435
2436 static const wbxml_decoding decode_syncmlc_10 = {
2437     "SyncML Representation Protocol 1.0",
2438     "SyncML 1.0",
2439     { NULL, NULL, NULL },
2440         default_opaque_binary_tag,
2441         default_opaque_literal_tag,
2442         default_opaque_binary_attr,
2443         default_opaque_literal_attr,
2444     NULL,
2445     wbxml_syncmlc10_tags,
2446     NULL,
2447     NULL
2448 };
2449
2450
2451
2452
2453
2454 /* SyncML 1.1
2455  * 
2456  * SyncML Representation Protocol
2457  ***************************************/
2458
2459 /*****   Global extension tokens   *****/
2460
2461 /*****         Tag tokens          *****/
2462 static const value_string wbxml_syncmlc11_tags_cp0[] = { /* SyncML 1.1 */
2463         /* 0x00 -- 0x04 GLOBAL */
2464         { 0x05, "Add" },
2465         { 0x06, "Alert" },
2466         { 0x07, "Archive" },
2467         { 0x08, "Atomic" },
2468         { 0x09, "Chal" },
2469         { 0x0a, "Cmd" },
2470         { 0x0b, "CmdID" },
2471         { 0x0c, "CmdRef" },
2472         { 0x0d, "Copy" },
2473         { 0x0e, "Cred" },
2474         { 0x0f, "Data" },
2475         { 0x10, "Delete" },
2476         { 0x11, "Exec" },
2477         { 0x12, "Final" },
2478         { 0x13, "Get" },
2479         { 0x14, "Item" },
2480         { 0x15, "Lang" },
2481         { 0x16, "LocName" },
2482         { 0x17, "LocURI" },
2483         { 0x18, "Map" },
2484         { 0x19, "MapItem" },
2485         { 0x1a, "Meta" },
2486         { 0x1b, "MsgID" },
2487         { 0x1c, "MsgRef" },
2488         { 0x1d, "NoResp" },
2489         { 0x1e, "NoResults" },
2490         { 0x1f, "Put" },
2491         { 0x20, "Replace" },
2492         { 0x21, "RespURI" },
2493         { 0x22, "Results" },
2494         { 0x23, "Search" },
2495         { 0x24, "Sequence" },
2496         { 0x25, "SessionID" },
2497         { 0x26, "SftDel" },
2498         { 0x27, "Source" },
2499         { 0x28, "SourceRef" },
2500         { 0x29, "Status" },
2501         { 0x2a, "Sync" },
2502         { 0x2b, "SyncBody" },
2503         { 0x2c, "SyncHdr" },
2504         { 0x2d, "SyncML" },
2505         { 0x2e, "Target" },
2506         { 0x2f, "TargetRef" },
2507         /* 0x30 - Reserved */
2508         { 0x31, "VerDTD" },
2509         { 0x32, "VerProto" },
2510         { 0x33, "NumberOfChanges" },
2511         { 0x34, "MoreData" },
2512
2513         { 0x00, NULL }
2514 };
2515
2516 static const value_string wbxml_syncmlc11_tags_cp1[] = { /* MetInf 1.1 */
2517         /* 0x00 -- 0x04 GLOBAL */
2518         { 0x05, "Anchor" },
2519         { 0x06, "EMI" },
2520         { 0x07, "Format" },
2521         { 0x08, "FreeID" },
2522         { 0x09, "FreeMem" },
2523         { 0x0A, "Last" },
2524         { 0x0B, "Mark" },
2525         { 0x0C, "MaxMsgSize" },
2526         { 0x0D, "Mem" },
2527         { 0x0E, "MetInf" },
2528         { 0x0F, "Next" },
2529         { 0x10, "NextNonce" },
2530         { 0x11, "SharedMem" },
2531         { 0x12, "Size" },
2532         { 0x13, "Type" },
2533         { 0x14, "Version" },
2534         { 0x15, "MaxObjSize" },
2535
2536         { 0x00, NULL }
2537 };
2538
2539 /*****    Attribute Start tokens   *****/
2540
2541 /*****    Attribute Value tokens   *****/
2542
2543 /***** Token code page aggregation *****/
2544 static const value_valuestring wbxml_syncmlc11_tags[] = {
2545         { 0, wbxml_syncmlc11_tags_cp0 }, /* -//SYNCML//DTD SyncML 1.1//EN */
2546         { 1, wbxml_syncmlc11_tags_cp1 }, /* -//SYNCML//DTD MetInf 1.1//EN */
2547         { 0, NULL }
2548 };
2549
2550 static const wbxml_decoding decode_syncmlc_11 = {
2551     "SyncML Representation Protocol 1.1",
2552     "SyncML 1.1",
2553     { NULL, NULL, NULL },
2554         default_opaque_binary_tag,
2555         default_opaque_literal_tag,
2556         default_opaque_binary_attr,
2557         default_opaque_literal_attr,
2558     NULL,
2559     wbxml_syncmlc11_tags,
2560     NULL,
2561     NULL
2562 };
2563
2564
2565
2566
2567
2568 /* CHANNEL 1.0
2569  * 
2570  * WTA Channel
2571  ***************************************/
2572
2573 /*****   Global extension tokens   *****/
2574
2575 /*****         Tag tokens          *****/
2576 static const value_string wbxml_channelc10_tags_cp0[] = {
2577         /* 0x00 -- 0x04 GLOBAL */
2578         { 0x05, "channel" },
2579         { 0x06, "title" },
2580         { 0x07, "abstract" },
2581         { 0x08, "resource" },
2582
2583         { 0x00, NULL }
2584 };
2585
2586 /*****    Attribute Start tokens   *****/
2587 static const value_string wbxml_channelc10_attrStart_cp0[] = {
2588         /* 0x00 -- 0x04 GLOBAL */
2589         { 0x05, "maxspace=" },
2590         { 0x06, "base=" },
2591         { 0x07, "href=" },
2592         { 0x08, "href='http://'" },
2593         { 0x09, "href='https://'" },
2594         { 0x0A, "lastmod=" },
2595         { 0x0B, "etag=" },
2596         { 0x0C, "md5=" },
2597         { 0x0D, "success=" },
2598         { 0x0E, "success='http://'" },
2599         { 0x0F, "success='https://'" },
2600         { 0x10, "failure=" },
2601         { 0x11, "failure='http://'" },
2602         { 0x12, "failure='https://'" },
2603         { 0x13, "EventId=" },
2604
2605         { 0x00, NULL }
2606 };
2607
2608 /*****    Attribute Value tokens   *****/
2609
2610 /***** Token code page aggregation *****/
2611 static const value_valuestring wbxml_channelc10_tags[] = {
2612         { 0, wbxml_channelc10_tags_cp0 },
2613         { 0, NULL }
2614 };
2615
2616 static const value_valuestring wbxml_channelc10_attrStart[] = {
2617         { 0, wbxml_channelc10_attrStart_cp0 },
2618         { 0, NULL }
2619 };
2620
2621 static const wbxml_decoding decode_channelc_10 = {
2622     "Wireless Telephony Application (WTA) Channel 1.0",
2623     "CHANNEL 1.0",
2624     { NULL, NULL, NULL },
2625         default_opaque_binary_tag,
2626         default_opaque_literal_tag,
2627         default_opaque_binary_attr,
2628         default_opaque_literal_attr,
2629     NULL,
2630     wbxml_channelc10_tags,
2631     wbxml_channelc10_attrStart,
2632     NULL
2633 };
2634
2635
2636
2637
2638
2639 /* application/x-wap-prov.browser-settings
2640  * application/x-wap-prov.browser-bookmarks
2641  * 
2642  * Nokia OTA Provisioning document format
2643  ***************************************/
2644
2645 /*****   Global extension tokens   *****/
2646
2647 /*****         Tag tokens          *****/
2648 static const value_string wbxml_nokiaprovc70_tags_cp0[] = {
2649         /* 0x00 -- 0x04 GLOBAL */
2650         { 0x05, "CHARACTERISTIC-LIST" },
2651         { 0x06, "CHARACTERISTIC" },
2652         { 0x07, "PARM" },
2653
2654         { 0x00, NULL }
2655 };
2656
2657 /*****    Attribute Start tokens   *****/
2658 static const value_string wbxml_nokiaprovc70_attrStart_cp0[] = {
2659         /* 0x00 -- 0x04 GLOBAL */
2660         { 0x06, "TYPE='ADDRESS'" },
2661         { 0x07, "TYPE='URL'" },
2662         { 0x08, "TYPE='NAME'" },
2663         { 0x10, "NAME=" },
2664         { 0x11, "VALUE=" },
2665         { 0x12, "NAME='BEARER'" },
2666         { 0x13, "NAME='PROXY'" },
2667         { 0x14, "NAME='PORT'" },
2668         { 0x15, "NAME='NAME'" },
2669         { 0x16, "NAME='PROXY_TYPE'" },
2670         { 0x17, "NAME='URL'" },
2671         { 0x18, "NAME='PROXY_AUTHNAME'" },
2672         { 0x19, "NAME='PROXY_AUTHSECRET'" },
2673         { 0x1A, "NAME='SMS_SMSC_ADDRESS'" },
2674         { 0x1B, "NAME='USSD_SERVICE_CODE'" },
2675         { 0x1C, "NAME='GPRS_ACCESSPOINTNAME'" },
2676         { 0x1D, "NAME='PPP_LOGINTYPE'" },
2677         { 0x1E, "NAME='PROXY_LOGINTYPE'" },
2678         { 0x21, "NAME='CSD_DIALSTRING'" },
2679         { 0x22, "NAME='PPP_AUTHTYPE'" },
2680         { 0x23, "NAME='PPP_AUTHNAME'" },
2681         { 0x24, "NAME='PPP_AUTHSECRET'" },
2682         { 0x28, "NAME='CSD_CALLTYPE'" },
2683         { 0x29, "NAME='CSD_CALLSPEED'" },
2684         { 0x45, "VALUE='GSM/CSD'" },
2685         { 0x46, "VALUE='GSM/SMS'" },
2686         { 0x47, "VALUE='GSM/USSD'" },
2687         { 0x48, "VALUE='IS-136/CSD'" },
2688         { 0x49, "VALUE='GPRS'" },
2689         { 0x60, "VALUE='9200'" },
2690         { 0x61, "VALUE='9201'" },
2691         { 0x62, "VALUE='9202'" },
2692         { 0x63, "VALUE='9203'" },
2693         { 0x64, "VALUE='AUTOMATIC'" },
2694         { 0x65, "VALUE='MANUAL'" },
2695         { 0x6A, "VALUE='AUTO'" },
2696         { 0x6B, "VALUE='9600'" },
2697         { 0x6C, "VALUE='14400'" },
2698         { 0x6D, "VALUE='19200'" },
2699         { 0x6E, "VALUE='28800'" },
2700         { 0x6F, "VALUE='38400'" },
2701         { 0x70, "VALUE='PAP'" },
2702         { 0x71, "VALUE='CHAP'" },
2703         { 0x72, "VALUE='ANALOGUE'" },
2704         { 0x73, "VALUE='ISDN'" },
2705         { 0x74, "VALUE='43200'" },
2706         { 0x75, "VALUE='57600'" },
2707         { 0x76, "VALUE='MSISDN_NO'" },
2708         { 0x77, "VALUE='IPV4'" },
2709         { 0x78, "VALUE='MS_CHAP'" },
2710         { 0x7C, "TYPE='MMSURL'" },
2711         { 0x7D, "TYPE='ID'" },
2712         { 0x7E, "NAME='ISP_NAME'" },
2713         { 0x7F, "TYPE='BOOKMARK'" },
2714
2715         { 0x00, NULL }
2716 };
2717
2718 /*****    Attribute Value tokens   *****/
2719
2720 /***** Token code page aggregation *****/
2721 static const value_valuestring wbxml_nokiaprovc70_tags[] = {
2722         { 0, wbxml_nokiaprovc70_tags_cp0 },
2723         { 0, NULL }
2724 };
2725
2726 static const value_valuestring wbxml_nokiaprovc70_attrStart[] = {
2727         { 0, wbxml_nokiaprovc70_attrStart_cp0 },
2728         { 0, NULL }
2729 };
2730
2731 static const wbxml_decoding decode_nokiaprovc_70 = {
2732     "Nokia Client Provisioning 7.0",
2733     "Nokia Client Provisioning 7.0",
2734     { NULL, NULL, NULL },
2735         default_opaque_binary_tag,
2736         default_opaque_literal_tag,
2737         default_opaque_binary_attr,
2738         default_opaque_literal_attr,
2739     NULL,
2740     wbxml_nokiaprovc70_tags,
2741     wbxml_nokiaprovc70_attrStart,
2742     NULL
2743 };
2744
2745
2746
2747
2748
2749 /* WV-CSP 1.0
2750  * 
2751  * Wireless Village Client Server Protocol
2752  ***************************************/
2753
2754 /*****   Global extension tokens   *****/
2755
2756 /*****         Tag tokens          *****/
2757 /* Common code page (0x00) */
2758 static const value_string wbxml_wv_csp_10_tags_cp0[] = {
2759         /* 0x00 -- 0x04 GLOBAL */
2760         { 0x05, "Acceptance" },
2761         { 0x06, "AddList" },
2762         { 0x07, "AddNickList" },
2763         { 0x08, "Attribute" },
2764         { 0x09, "AttributeList" },
2765         { 0x0A, "ClientID" },
2766         { 0x0B, "Code" },
2767         { 0x0C, "ContactList" },
2768         { 0x0D, "ContentData" },
2769         { 0x0E, "ContentEncoding" },
2770         { 0x0F, "ContentSize" },
2771         { 0x10, "ContentType" },
2772         { 0x11, "DateTime" },
2773         { 0x12, "Description" },
2774         { 0x13, "DetailedResult" },
2775         { 0x14, "EntityList" },
2776         { 0x15, "Group" },
2777         { 0x16, "GroupID" },
2778         { 0x17, "GroupList" },
2779         { 0x18, "InUse" },
2780         { 0x19, "Logo" },
2781         { 0x1A, "MessageCount" },
2782         { 0x1B, "MessageID" },
2783         { 0x1C, "MessageURI" },
2784         { 0x1D, "MSISDN" },
2785         { 0x1E, "Name" },
2786         { 0x1F, "NickList" },
2787         { 0x20, "NickName" },
2788         { 0x21, "Poll" },
2789         { 0x22, "Presence" },
2790         { 0x23, "PresenceSubList" },
2791         { 0x24, "PresenceValue" },
2792         { 0x25, "Property" },
2793         { 0x26, "Qualifier" },
2794         { 0x27, "Recipient" },
2795         { 0x28, "RemoveList" },
2796         { 0x29, "RemoveNickList" },
2797         { 0x2A, "Result" },
2798         { 0x2B, "ScreenName" },
2799         { 0x2C, "Sender" },
2800         { 0x2D, "Session" },
2801         { 0x2E, "SessionDescriptor" },
2802         { 0x2F, "SessionID" },
2803         { 0x30, "SessionType" },
2804         { 0x31, "Status" },
2805         { 0x32, "Transaction" },
2806         { 0x33, "TransactionContent" },
2807         { 0x34, "TransactionDescriptor" },
2808         { 0x35, "TransactionID" },
2809         { 0x36, "TransactionMode" },
2810         { 0x37, "URL" },
2811         { 0x38, "URLList" },
2812         { 0x39, "User" },
2813         { 0x3A, "UserID" },
2814         { 0x3B, "UserList" },
2815         { 0x3C, "Validity" },
2816         { 0x3D, "Value" },
2817         { 0x3E, "WV-CSP-Message" },
2818
2819         { 0x00, NULL }
2820 };
2821
2822 /* Access code page (0x01) */
2823 static const value_string wbxml_wv_csp_10_tags_cp1[] = {
2824         /* 0x00 -- 0x04 GLOBAL */
2825         { 0x05, "AllFunctions" },
2826         { 0x06, "AllFunctionsRequest" },
2827         { 0x07, "CancelInvite-Request" },
2828         { 0x08, "CancelInviteUser-Request" },
2829         { 0x09, "Capability" },
2830         { 0x0A, "CapabilityList" },
2831         { 0x0B, "CapabilityRequest" },
2832         { 0x0C, "ClientCapability-Request" },
2833         { 0x0D, "ClientCapability-Response" },
2834         { 0x0E, "DigestBytes" },
2835         { 0x0F, "DigestSchema" },
2836         { 0x10, "Disconnect" },
2837         { 0x11, "Functions" },
2838         { 0x12, "GetSPInfo-Request" },
2839         { 0x13, "GetSPInfo-Response" },
2840         { 0x14, "InviteID" },
2841         { 0x15, "InviteNote" },
2842         { 0x16, "Invite-Request" },
2843         { 0x17, "Invite-Response" },
2844         { 0x18, "InviteType" },
2845         { 0x19, "InviteUser-Request" },
2846         { 0x1A, "InviteUser-Response" },
2847         { 0x1B, "KeepAlive-Request" },
2848         { 0x1C, "KeepAliveTime" },
2849         { 0x1D, "Login-Request" },
2850         { 0x1E, "Login-Response" },
2851         { 0x1F, "Logout-Request" },
2852         { 0x20, "Nonce" },
2853         { 0x21, "Password" },
2854         { 0x22, "Polling-Request" },
2855         { 0x23, "ResponseNote" },
2856         { 0x24, "SearchElement" },
2857         { 0x25, "SearchFindings" },
2858         { 0x26, "SearchID" },
2859         { 0x27, "SearchIndex" },
2860         { 0x28, "SearchLimit" },
2861         { 0x29, "SearchOnlineStatus" },
2862         { 0x2A, "SearchPairList" },
2863         { 0x2B, "Search-Request" },
2864         { 0x2C, "Search-Response" },
2865         { 0x2D, "SearchResult" },
2866         { 0x2E, "Service-Request" },
2867         { 0x2F, "Service-Response" },
2868         { 0x30, "SessionCookie" },
2869         { 0x31, "StopSearch-Request" },
2870         { 0x32, "TimeToLive" },
2871
2872         { 0x00, NULL }
2873 };
2874
2875 /* Service code page (0x02) */
2876 static const value_string wbxml_wv_csp_10_tags_cp2[] = {
2877         /* 0x00 -- 0x04 GLOBAL */
2878         { 0x05, "ADDGM" },
2879         { 0x06, "AttListFunc" },
2880         { 0x07, "BLENT" },
2881         { 0x08, "CAAUT" },
2882         { 0x09, "CAINV" },
2883         { 0x0A, "CALI" },
2884         { 0x0B, "CCLI" },
2885         { 0x0C, "ContListFunc" },
2886         { 0x0D, "CREAG" },
2887         { 0x0E, "DALI" },
2888         { 0x0F, "DCLI" },
2889         { 0x10, "DELGR" },
2890         { 0x11, "FundamentalFeat" },
2891         { 0x12, "FWMSG" },
2892         { 0x13, "GALS" },
2893         { 0x14, "GCLI" },
2894         { 0x15, "GETGM" },
2895         { 0x16, "GETGP" },
2896         { 0x17, "GETLM" },
2897         { 0x18, "GETM" },
2898         { 0x19, "GETPR" },
2899         { 0x1A, "GETSPI" },
2900         { 0x1B, "GETWL" },
2901         { 0x1C, "GLBLU" },
2902         { 0x1D, "GRCHN" },
2903         { 0x1E, "GroupAuthFunc" },
2904         { 0x1F, "GroupFeat" },
2905         { 0x20, "GroupMgmtFunc" },
2906         { 0x21, "GroupUseFunc" },
2907         { 0x22, "IMAuthFunc" },
2908         { 0x23, "IMFeat" },
2909         { 0x24, "IMReceiveFunc" },
2910         { 0x25, "IMSendFunc" },
2911         { 0x26, "INVIT" },
2912         { 0x27, "InviteFunc" },
2913         { 0x28, "MBRAC" },
2914         { 0x29, "MCLS" },
2915         { 0x2A, "MDELIV" },
2916         { 0x2B, "NEWM" },
2917         { 0x2C, "NOTIF" },
2918         { 0x2D, "PresenceAuthFunc" },
2919         { 0x2E, "PresenceDeliverFunc" },
2920         { 0x2F, "PresenceFeat" },
2921         { 0x30, "REACT" },
2922         { 0x31, "REJCM" },
2923         { 0x32, "REJEC" },
2924         { 0x33, "RMVGM" },
2925         { 0x34, "SearchFunc" },
2926         { 0x35, "ServiceFunc" },
2927         { 0x36, "SETD" },
2928         { 0x37, "SETGP" },
2929         { 0x38, "SRCH" },
2930         { 0x39, "STSRC" },
2931         { 0x3A, "SUBGCN" },
2932         { 0x3B, "UPDPR" },
2933         { 0x3C, "WVCSPFeat" },
2934
2935         { 0x00, NULL }
2936 };
2937
2938 /* Client capability code page (0x03) */
2939 static const value_string wbxml_wv_csp_10_tags_cp3[] = {
2940         /* 0x00 -- 0x04 GLOBAL */
2941         { 0x05, "AcceptedCharset" },
2942         { 0x06, "AcceptedContentLength" },
2943         { 0x07, "AcceptedContentType" },
2944         { 0x08, "AcceptedTransferEncoding" },
2945         { 0x09, "AnyContent" },
2946         { 0x0A, "ClientType" },
2947         { 0x0B, "InitialDeliveryMethod" },
2948         { 0x0C, "MultiTrans" },
2949         { 0x0D, "ParserSize" },
2950         { 0x0E, "ServerPollMin" },
2951         { 0x0F, "SupportedBearer" },
2952         { 0x10, "SupportedCIRMethod" },
2953         { 0x11, "TCPAddress" },
2954         { 0x12, "TCPPort" },
2955         { 0x13, "UDPPort" },
2956
2957         { 0x00, NULL }
2958 };
2959
2960 /* Presence primitive code page (0x04) */
2961 static const value_string wbxml_wv_csp_10_tags_cp4[] = {
2962         /* 0x00 -- 0x04 GLOBAL */
2963         { 0x05, "CancelAuth-Request" },
2964         { 0x06, "ContactListProperties" },
2965         { 0x07, "CreateAttributeList-Request" },
2966         { 0x08, "CreateList-Request" },
2967         { 0x09, "DefaultAttributeList" },
2968         { 0x0A, "DefaultContactList" },
2969         { 0x0B, "DefaultList" },
2970         { 0x0C, "DeleteAttributeList-Request" },
2971         { 0x0D, "DeleteList-Request" },
2972         { 0x0E, "GetAttributeList-Request" },
2973         { 0x0F, "GetAttributeList-Response" },
2974         { 0x10, "GetList-Request" },
2975         { 0x11, "GetList-Response" },
2976         { 0x12, "GetPresence-Request" },
2977         { 0x13, "GetPresence-Response" },
2978         { 0x14, "GetWatcherList-Request" },
2979         { 0x15, "GetWatcherList-Response" },
2980         { 0x16, "ListManage-Request" },
2981         { 0x17, "ListManage-Response" },
2982         { 0x18, "Presence" },
2983         { 0x19, "PresenceAuth-Request" },
2984         { 0x1A, "PresenceAuth-Response" },
2985         { 0x1B, "PresenceNotification-Request" },
2986         { 0x1C, "PresenceValueList" },
2987         { 0x1D, "SubscribePresence-Request" },
2988         { 0x1E, "UnsubscribePresence-Request" },
2989         { 0x1F, "UpdatePresence-Request" },
2990
2991         { 0x00, NULL }
2992 };
2993
2994 /* Presence attribute code page (0x05) */
2995 static const value_string wbxml_wv_csp_10_tags_cp5[] = {
2996         /* 0x00 -- 0x04 GLOBAL */
2997         { 0x05, "Accuracy" },
2998         { 0x06, "Address" },
2999         { 0x07, "AddrPref" },
3000         { 0x08, "Alias" },
3001         { 0x09, "Altitude" },
3002         { 0x0A, "Building" },
3003         { 0x0B, "CAddr" },
3004         { 0x0C, "City" },
3005         { 0x0D, "ClientInfo" },
3006         { 0x0E, "ClientProducer" },
3007         { 0x0F, "ClientType" },
3008         { 0x10, "ClientVersion" },
3009         { 0x11, "CommC" },
3010         { 0x12, "CommCap" },
3011         { 0x13, "ContactInfo" },
3012         { 0x14, "ContainedvCard" },
3013         { 0x15, "Country" },
3014         { 0x16, "Crossing1" },
3015         { 0x17, "Crossing2" },
3016         { 0x18, "DevManufacturer" },
3017         { 0x19, "DirectContent" },
3018         { 0x1A, "FreeTextLocation" },
3019         { 0x1B, "GeoLocation" },
3020         { 0x1C, "Language" },
3021         { 0x1D, "Latitude" },
3022         { 0x1E, "Longitude" },
3023         { 0x1F, "Model" },
3024         { 0x20, "NamedArea" },
3025         { 0x21, "OnlineStatus" },
3026         { 0x22, "PLMN" },
3027         { 0x23, "PrefC" },
3028         { 0x24, "PreferredContacts" },
3029         { 0x25, "PreferredLanguage" },
3030         { 0x26, "ReferredContent" },
3031         { 0x27, "ReferredvCard" },
3032         { 0x28, "Registration" },
3033         { 0x29, "StatusContent" },
3034         { 0x2A, "StatusMood" },
3035         { 0x2B, "StatusText" },
3036         { 0x2C, "Street" },
3037         { 0x2D, "TimeZone" },
3038         { 0x2E, "UserAvailability" },
3039
3040         { 0x00, NULL }
3041 };
3042
3043 /* Messaging code page (0x06) */
3044 static const value_string wbxml_wv_csp_10_tags_cp6[] = {
3045         /* 0x00 -- 0x04 GLOBAL */
3046         { 0x05, "BlockList" },
3047         { 0x06, "BlockUser-Request" },
3048         { 0x07, "DeliveryMethod" },
3049         { 0x08, "DeliveryReport" },
3050         { 0x09, "DeliveryReport-Request" },
3051         { 0x0A, "ForwardMessage-Request" },
3052         { 0x0B, "GetBlockedList-Request" },
3053         { 0x0C, "GetBlockedList-Response" },
3054         { 0x0D, "GetMessageList-Request" },
3055         { 0x0E, "GetMessageList-Response" },
3056         { 0x0F, "GetMessage-Request" },
3057         { 0x10, "GetMessage-Response" },
3058         { 0x11, "GrantList" },
3059         { 0x12, "MessageDelivered" },
3060         { 0x13, "MessageInfo" },
3061         { 0x14, "MessageNotification" },
3062         { 0x15, "NewMessage" },
3063         { 0x16, "RejectMessage-Request" },
3064         { 0x17, "SendMessage-Request" },
3065         { 0x18, "SendMessage-Response" },
3066         { 0x19, "SetDeliveryMethod-Request" },
3067
3068         { 0x00, NULL }
3069 };
3070
3071 /* Group code page (0x07) */
3072 static const value_string wbxml_wv_csp_10_tags_cp7[] = {
3073         /* 0x00 -- 0x04 GLOBAL */
3074         { 0x05, "AddGroupMembers-Request" },
3075         { 0x06, "Admin" },
3076         { 0x07, "CreateGroup-Request" },
3077         { 0x08, "DeleteGroup-Request" },
3078         { 0x09, "GetGroupMembers-Request" },
3079         { 0x0A, "GetGroupMembers-Response" },
3080         { 0x0B, "GetGroupProps-Request" },
3081         { 0x0C, "GetGroupProps-Response" },
3082         { 0x0D, "GroupChangeNotice" },
3083         { 0x0E, "GroupProperties" },
3084         { 0x0F, "Joined" },
3085         { 0x10, "JoinedRequest" },
3086         { 0x11, "JoinGroup-Request" },
3087         { 0x12, "JoinGroup-Response" },
3088         { 0x13, "LeaveGroup-Request" },
3089         { 0x14, "LeaveGroup-Response" },
3090         { 0x15, "Left" },
3091         { 0x16, "MemberAccess-Request" },
3092         { 0x17, "Mod" },
3093         { 0x18, "OwnProperties" },
3094         { 0x19, "RejectList-Request" },
3095         { 0x1A, "RejectList-Response" },
3096         { 0x1B, "RemoveGroupMembers-Request" },
3097         { 0x1C, "SetGroupProps-Request" },
3098         { 0x1D, "SubscribeGroupNotice-Request" },
3099         { 0x1E, "SubscribeGroupNotice-Response" },
3100         { 0x1F, "Users" },
3101         { 0x20, "WelcomeNote" },
3102
3103         { 0x00, NULL }
3104 };
3105
3106 /*
3107  * Attribute start tokens
3108  */
3109 /* common code page (0x00) */
3110 static const value_string wbxml_wv_csp_10_attrStart_cp0[] = {
3111         /* 0x00 -- 0x04 GLOBAL */
3112         { 0x05, "xmlns='http://www.wireless-village.org/CSP'" },
3113         { 0x06, "xmlns='http://www.wireless-village.org/PA'" },
3114         { 0x07, "xmlns='http://www.wireless-village.org/TRC'" },
3115
3116         { 0x00, NULL }
3117 };
3118
3119 /*
3120  * Attribute value tokens
3121  */
3122 /* Common value tokens (0x00) */
3123 static const value_string wbxml_wv_csp_10_attrValue_cp0[] = {
3124         /* 0x80 -- 0x84 GLOBAL */
3125         { 0x85, "AccessType" },
3126         { 0x86, "ActiveUsers" },
3127         { 0x87, "Admin" },
3128         { 0x88, "application/" },
3129         { 0x89, "application/vnd.wap.mms-message" },
3130         { 0x8A, "application/x-sms" },
3131         { 0x8B, "BASE64" },
3132         { 0x8C, "Closed" },
3133         { 0x8D, "Default" },
3134         { 0x8E, "DisplayName" },
3135         { 0x8F, "False (No)" },
3136         { 0x90, "Get" },
3137         { 0x91, "Group (GR)" },
3138         { 0x92, "http://" },
3139         { 0x93, "https://" },
3140         { 0x94, "image/" },
3141         { 0x95, "Inband" },
3142         { 0x96, "Instant Messaging (IM)" },
3143         { 0x97, "MaxActiveUsers" },
3144         { 0x98, "Mod" },
3145         { 0x99, "Name" },
3146         { 0x9A, "None" },
3147         { 0x9B, "Notify/Get" },
3148         { 0x9C, "Open" },
3149         { 0x9D, "Outband" },
3150         { 0x9E, "Presence (PR)" },
3151         { 0x9F, "Private" },
3152         { 0xA0, "PrivateMessaging" },
3153         { 0xA1, "PrivilegeLevel" },
3154         { 0xA2, "Public" },
3155         { 0xA3, "Push" },
3156         { 0xA4, "Request" },
3157         { 0xA5, "Response" },
3158         { 0xA6, "ScreenName" },
3159         { 0xA7, "Searchable" },
3160         { 0xA8, "Set" },
3161         { 0xA9, "Shared Content (SC)" },
3162         { 0xAA, "text/" },
3163         { 0xAB, "text/plain" },
3164         { 0xAC, "text/x-vCalendar" },
3165         { 0xAD, "text/x-vCard" },
3166         { 0xAE, "Topic" },
3167         { 0xAF, "True (Yes)" },
3168         { 0xB0, "Type" },
3169         { 0xB1, "Unset" },
3170         { 0xB2, "User (US)" },
3171         { 0xB3, "www.wireless-village.org" },
3172
3173         { 0x00, NULL }
3174 };
3175
3176 /* Access value tokens (0x01) */
3177 static const value_string wbxml_wv_csp_10_attrValue_cp1[] = {
3178         /* 0x80 -- 0x84 GLOBAL */
3179         { 0x85, "GROUP_ID" },
3180         { 0x86, "GROUP_NAME" },
3181         { 0x87, "GROUP_TOPIC" },
3182         { 0x88, "GROUP_USER_ID_JOINED" },
3183         { 0x89, "HTTP" },
3184         { 0x8A, "SMS" },
3185         { 0x8B, "STCP" },
3186         { 0x8C, "SUDP" },
3187         { 0x8D, "USER_ALIAS" },
3188         { 0x8E, "USER_EMAIL_ADDRESS" },
3189         { 0x8F, "USER_FIRST_NAME" },
3190         { 0x90, "USER_ID" },
3191         { 0x91, "USER_LAST_NAME" },
3192         { 0x92, "USER_MOBILE_NUMBER" },
3193         { 0x93, "WAPSMS" },
3194         { 0x94, "WAPUDP" },
3195         { 0x95, "WSP" },
3196
3197         { 0x00, NULL }
3198 };
3199
3200 /* Presence value tokens (0x05) */
3201 static const value_string wbxml_wv_csp_10_attrValue_cp5[] = {
3202         /* 0x80 -- 0x84 GLOBAL */
3203         { 0x85, "ANGRY" },
3204         { 0x86, "ANXIOUS" },
3205         { 0x87, "ASHAMED" },
3206         { 0x88, "AUDIO_CALL" },
3207         { 0x89, "AVAILABLE" },
3208         { 0x8A, "BORED" },
3209         { 0x8B, "CALL" },
3210         { 0x8C, "CLI" },
3211         { 0x8D, "COMPUTER" },
3212         { 0x8E, "DISCREET" },
3213         { 0x8F, "EMAIL" },
3214         { 0x90, "EXCITED" },
3215         { 0x91, "HAPPY" },
3216         { 0x92, "IM" },
3217         { 0x93, "IM_OFFLINE" },
3218         { 0x94, "IM_ONLINE" },
3219         { 0x95, "IN_LOVE" },
3220         { 0x96, "INVINCIBLE" },
3221         { 0x97, "JEALOUS" },
3222         { 0x98, "MMS" },
3223         { 0x99, "MOBILE_PHONE" },
3224         { 0x9A, "NOT_AVAILABLE" },
3225         { 0x9B, "OTHER" },
3226         { 0x9C, "PDA" },
3227         { 0x9D, "SAD" },
3228         { 0x9E, "SLEEPY" },
3229         { 0x9F, "SMS" },
3230         { 0xA0, "VIDEO_CALL" },
3231         { 0xA1, "VIDEO_STREAM" },
3232
3233         { 0x00, NULL }
3234 };
3235
3236
3237 /***** Token code page aggregation *****/
3238 static const value_valuestring wbxml_wv_csp_10_tags[] = {
3239         { 0, wbxml_wv_csp_10_tags_cp0 },
3240         { 1, wbxml_wv_csp_10_tags_cp1 },
3241         { 2, wbxml_wv_csp_10_tags_cp2 },
3242         { 3, wbxml_wv_csp_10_tags_cp3 },
3243         { 4, wbxml_wv_csp_10_tags_cp4 },
3244         { 5, wbxml_wv_csp_10_tags_cp5 },
3245         { 6, wbxml_wv_csp_10_tags_cp6 },
3246         { 7, wbxml_wv_csp_10_tags_cp7 },
3247         { 0, NULL }
3248 };
3249
3250 static const value_valuestring wbxml_wv_csp_10_attrStart[] = {
3251         { 0, wbxml_wv_csp_10_attrStart_cp0 },
3252         { 0, NULL }
3253 };
3254
3255 static const value_valuestring wbxml_wv_csp_10_attrValue[] = {
3256         { 0, wbxml_wv_csp_10_attrValue_cp0 },
3257         { 1, wbxml_wv_csp_10_attrValue_cp1 },
3258         { 5, wbxml_wv_csp_10_attrValue_cp5 },
3259         { 0, NULL }
3260 };
3261
3262 static const wbxml_decoding decode_wv_cspc_10 = {
3263     "Wireless-Village Client-Server Protocol 1.0",
3264     "WV-CSP 1.0",
3265     { NULL, NULL, NULL },
3266         wv_csp10_opaque_binary_tag,
3267         default_opaque_literal_tag,
3268         default_opaque_binary_attr,
3269         default_opaque_literal_attr,
3270     NULL,
3271     wbxml_wv_csp_10_tags,
3272     wbxml_wv_csp_10_attrStart,
3273     wbxml_wv_csp_10_attrValue
3274 };
3275
3276
3277
3278
3279
3280 /* WV-CSP 1.1
3281  * 
3282  * Wireless Village Client Server Protocol
3283  ***************************************/
3284
3285 /*****   Global extension tokens   *****/
3286 static const value_string wbxml_wv_csp_11_global_cp0[] = {
3287         { 0x80, "Common Value" }, /* EXT_T_0 */
3288
3289         { 0x00, NULL }
3290 };
3291
3292 /*****         Tag tokens          *****/
3293 /* Common code page */
3294 static const value_string wbxml_wv_csp_11_tags_cp0[] = {
3295         /* 0x00 -- 0x04 GLOBAL */
3296         { 0x05, "Acceptance" },
3297         { 0x06, "AddList" },
3298         { 0x07, "AddNickList" },
3299         { 0x08, "SName" },              /* Was: Attribute */
3300         { 0x09, "WV-CSP-Message" },     /* Was: AttributeList */
3301         { 0x0A, "ClientID" },
3302         { 0x0B, "Code" },
3303         { 0x0C, "ContactList" },
3304         { 0x0D, "ContentData" },
3305         { 0x0E, "ContentEncoding" },
3306         { 0x0F, "ContentSize" },
3307         { 0x10, "ContentType" },
3308         { 0x11, "DateTime" },
3309         { 0x12, "Description" },
3310         { 0x13, "DetailedResult" },
3311         { 0x14, "EntityList" },
3312         { 0x15, "Group" },
3313         { 0x16, "GroupID" },
3314         { 0x17, "GroupList" },
3315         { 0x18, "InUse" },
3316         { 0x19, "Logo" },
3317         { 0x1A, "MessageCount" },
3318         { 0x1B, "MessageID" },
3319         { 0x1C, "MessageURI" },
3320         { 0x1D, "MSISDN" },
3321         { 0x1E, "Name" },
3322         { 0x1F, "NickList" },
3323         { 0x20, "NickName" },
3324         { 0x21, "Poll" },
3325         { 0x22, "Presence" },
3326         { 0x23, "PresenceSubList" },
3327         { 0x24, "PresenceValue" },
3328         { 0x25, "Property" },
3329         { 0x26, "Qualifier" },
3330         { 0x27, "Recipient" },
3331         { 0x28, "RemoveList" },
3332         { 0x29, "RemoveNickList" },
3333         { 0x2A, "Result" },
3334         { 0x2B, "ScreenName" },
3335         { 0x2C, "Sender" },
3336         { 0x2D, "Session" },
3337         { 0x2E, "SessionDescriptor" },
3338         { 0x2F, "SessionID" },
3339         { 0x30, "SessionType" },
3340         { 0x31, "Status" },
3341         { 0x32, "Transaction" },
3342         { 0x33, "TransactionContent" },
3343         { 0x34, "TransactionDescriptor" },
3344         { 0x35, "TransactionID" },
3345         { 0x36, "TransactionMode" },
3346         { 0x37, "URL" },
3347         { 0x38, "URLList" },
3348         { 0x39, "User" },
3349         { 0x3A, "UserID" },
3350         { 0x3B, "UserList" },
3351         { 0x3C, "Validity" },
3352         { 0x3D, "Value" },
3353         /* 0x3E - Removed: WV-CSP-Message */
3354
3355         { 0x00, NULL }
3356 };
3357
3358 /* Access code page */
3359 static const value_string wbxml_wv_csp_11_tags_cp1[] = {
3360         /* 0x00 -- 0x04 GLOBAL */
3361         { 0x05, "AllFunctions" },
3362         { 0x06, "AllFunctionsRequest" },
3363         { 0x07, "CancelInvite-Request" },
3364         { 0x08, "CancelInviteUser-Request" },
3365         { 0x09, "Capability" },
3366         { 0x0A, "CapabilityList" },
3367         { 0x0B, "CapabilityRequest" },
3368         { 0x0C, "ClientCapability-Request" },
3369         { 0x0D, "ClientCapability-Response" },
3370         { 0x0E, "DigestBytes" },
3371         { 0x0F, "DigestSchema" },
3372         { 0x10, "Disconnect" },
3373         { 0x11, "Functions" },
3374         { 0x12, "GetSPInfo-Request" },
3375         { 0x13, "GetSPInfo-Response" },
3376         { 0x14, "InviteID" },
3377         { 0x15, "InviteNote" },
3378         { 0x16, "Invite-Request" },
3379         { 0x17, "Invite-Response" },
3380         { 0x18, "InviteType" },
3381         { 0x19, "InviteUser-Request" },
3382         { 0x1A, "InviteUser-Response" },
3383         { 0x1B, "KeepAlive-Request" },
3384         { 0x1C, "KeepAliveTime" },
3385         { 0x1D, "Login-Request" },
3386         { 0x1E, "Login-Response" },
3387         { 0x1F, "Logout-Request" },
3388         { 0x20, "Nonce" },
3389         { 0x21, "Password" },
3390         { 0x22, "Polling-Request" },
3391         { 0x23, "ResponseNote" },
3392         { 0x24, "SearchElement" },
3393         { 0x25, "SearchFindings" },
3394         { 0x26, "SearchID" },
3395         { 0x27, "SearchIndex" },
3396         { 0x28, "SearchLimit" },
3397         { 0x29, "KeepAlive-Response" }, /* Was: SearchOnlineStatus */
3398         { 0x2A, "SearchPairList" },
3399         { 0x2B, "Search-Request" },
3400         { 0x2C, "Search-Response" },
3401         { 0x2D, "SearchResult" },
3402         { 0x2E, "Service-Request" },
3403         { 0x2F, "Service-Response" },
3404         { 0x30, "SessionCookie" },
3405         { 0x31, "StopSearch-Request" },
3406         { 0x32, "TimeToLive" },
3407         /* New in WV-CSP 1.1 */
3408         { 0x33, "SearchString" },
3409         { 0x34, "CompletionFlag" },
3410
3411         { 0x00, NULL }
3412 };
3413
3414 /* Service code page */
3415 /* Same as cp2 of WV-CSP 1.0 */
3416 #define wbxml_wv_csp_11_tags_cp2 wbxml_wv_csp_10_tags_cp2
3417
3418 /* Client capability code page */
3419 static const value_string wbxml_wv_csp_11_tags_cp3[] = {
3420         /* 0x00 -- 0x04 GLOBAL */
3421         { 0x05, "AcceptedCharset" },
3422         { 0x06, "AcceptedContentLength" },
3423         { 0x07, "AcceptedContentType" },
3424         { 0x08, "AcceptedTransferEncoding" },
3425         { 0x09, "AnyContent" },
3426         { 0x0A, "DefaultLanguage" },    /* Was: ClientType */
3427         { 0x0B, "InitialDeliveryMethod" },
3428         { 0x0C, "MultiTrans" },
3429         { 0x0D, "ParserSize" },
3430         { 0x0E, "ServerPollMin" },
3431         { 0x0F, "SupportedBearer" },
3432         { 0x10, "SupportedCIRMethod" },
3433         { 0x11, "TCPAddress" },
3434         { 0x12, "TCPPort" },
3435         { 0x13, "UDPPort" },
3436
3437         { 0x00, NULL }
3438 };
3439
3440 /* Presence primitive code page */
3441 static const value_string wbxml_wv_csp_11_tags_cp4[] = {
3442         /* 0x00 -- 0x04 GLOBAL */
3443         { 0x05, "CancelAuth-Request" },
3444         { 0x06, "ContactListProperties" },
3445         { 0x07, "CreateAttributeList-Request" },
3446         { 0x08, "CreateList-Request" },
3447         { 0x09, "DefaultAttributeList" },
3448         { 0x0A, "DefaultContactList" },
3449         { 0x0B, "DefaultList" },
3450         { 0x0C, "DeleteAttributeList-Request" },
3451         { 0x0D, "DeleteList-Request" },
3452         { 0x0E, "GetAttributeList-Request" },
3453         { 0x0F, "GetAttributeList-Response" },
3454         { 0x10, "GetList-Request" },
3455         { 0x11, "GetList-Response" },
3456         { 0x12, "GetPresence-Request" },
3457         { 0x13, "GetPresence-Response" },
3458         { 0x14, "GetWatcherList-Request" },
3459         { 0x15, "GetWatcherList-Response" },
3460         { 0x16, "ListManage-Request" },
3461         { 0x17, "ListManage-Response" },
3462         { 0x18, "UnsubscribePresence-Request" },        /* Was: Presence */
3463         { 0x19, "PresenceAuth-Request" },
3464         { 0x1A, "PresenceAuth-User" },          /* Was: PresenceAuth-Response */
3465         { 0x1B, "PresenceNotification-Request" },
3466         { 0x1C, "UpdatePresence-Request" },     /* Was: PresenceValueList */
3467         { 0x1D, "SubscribePresence-Request" },
3468         /* 0x1E - Removed: UnsubscribePresence-Request */
3469         /* 0x1F - Removed: UpdatePresence-Request */
3470
3471         { 0x00, NULL }
3472 };
3473
3474 /* Presence attribute code page */
3475 static const value_string wbxml_wv_csp_11_tags_cp5[] = {
3476         /* 0x00 -- 0x04 GLOBAL */
3477         { 0x05, "Accuracy" },
3478         { 0x06, "Address" },
3479         { 0x07, "AddrPref" },
3480         { 0x08, "Alias" },
3481         { 0x09, "Altitude" },
3482         { 0x0A, "Building" },
3483         { 0x0B, "Caddr" },
3484         { 0x0C, "City" },
3485         { 0x0D, "ClientInfo" },
3486         { 0x0E, "ClientProducer" },
3487         { 0x0F, "ClientType" },
3488         { 0x10, "ClientVersion" },
3489         { 0x11, "CommC" },
3490         { 0x12, "CommCap" },
3491         { 0x13, "ContactInfo" },
3492         { 0x14, "ContainedvCard" },
3493         { 0x15, "Country" },
3494         { 0x16, "Crossing1" },
3495         { 0x17, "Crossing2" },
3496         { 0x18, "DevManufacturer" },
3497         { 0x19, "DirectContent" },
3498         { 0x1A, "FreeTextLocation" },
3499         { 0x1B, "GeoLocation" },
3500         { 0x1C, "Language" },
3501         { 0x1D, "Latitude" },
3502         { 0x1E, "Longitude" },
3503         { 0x1F, "Model" },
3504         { 0x20, "NamedArea" },
3505         { 0x21, "OnlineStatus" },
3506         { 0x22, "PLMN" },
3507         { 0x23, "PrefC" },
3508         { 0x24, "PreferredContacts" },
3509         { 0x25, "PreferredLanguage" },
3510         { 0x26, "ReferredContent" },
3511         { 0x27, "ReferredvCard" },
3512         { 0x28, "Registration" },
3513         { 0x29, "StatusContent" },
3514         { 0x2A, "StatusMood" },
3515         { 0x2B, "StatusText" },
3516         { 0x2C, "Street" },
3517         { 0x2D, "TimeZone" },
3518         { 0x2E, "UserAvailability" },
3519         /* New in WV-CSP 1.1 */
3520         { 0x2F, "Cap" },
3521         { 0x30, "Cname" },
3522         { 0x31, "Contact" },
3523         { 0x32, "Cpriority" },
3524         { 0x33, "Cstatus" },
3525         { 0x34, "Note" },
3526         { 0x35, "Zone" },
3527
3528         { 0x00, NULL }
3529 };
3530
3531 /* Messaging code page */
3532 static const value_string wbxml_wv_csp_11_tags_cp6[] = {
3533         /* 0x00 -- 0x04 GLOBAL */
3534         { 0x05, "BlockList" },
3535         { 0x06, "BlockUser-Request" },
3536         { 0x07, "DeliveryMethod" },
3537         { 0x08, "DeliveryReport" },
3538         { 0x09, "DeliveryReport-Request" },
3539         { 0x0A, "ForwardMessage-Request" },
3540         { 0x0B, "GetBlockedList-Request" },
3541         { 0x0C, "GetBlockedList-Response" },
3542         { 0x0D, "GetMessageList-Request" },
3543         { 0x0E, "GetMessageList-Response" },
3544         { 0x0F, "GetMessage-Request" },
3545         { 0x10, "GetMessage-Response" },
3546         { 0x11, "GrantList" },
3547         { 0x12, "MessageDelivered" },
3548         { 0x13, "MessageInfo" },
3549         { 0x14, "MessageNotification" },
3550         { 0x15, "NewMessage" },
3551         { 0x16, "RejectMessage-Request" },
3552         { 0x17, "SendMessage-Request" },
3553         { 0x18, "SendMessage-Response" },
3554         { 0x19, "SetDeliveryMethod-Request" },
3555         /* New in WV-CSP 1.1 */
3556         { 0x1A, "DeliveryTime" },
3557
3558         { 0x00, NULL }
3559 };
3560
3561 /* Group code page */
3562 static const value_string wbxml_wv_csp_11_tags_cp7[] = {
3563         /* 0x00 -- 0x04 GLOBAL */
3564         { 0x05, "AddGroupMembers-Request" },
3565         { 0x06, "Admin" },
3566         { 0x07, "CreateGroup-Request" },
3567         { 0x08, "DeleteGroup-Request" },
3568         { 0x09, "GetGroupMembers-Request" },
3569         { 0x0A, "GetGroupMembers-Response" },
3570         { 0x0B, "GetGroupProps-Request" },
3571         { 0x0C, "GetGroupProps-Response" },
3572         { 0x0D, "GroupChangeNotice" },
3573         { 0x0E, "GroupProperties" },
3574         { 0x0F, "Joined" },
3575         { 0x10, "JoinedRequest" },
3576         { 0x11, "JoinGroup-Request" },
3577         { 0x12, "JoinGroup-Response" },
3578         { 0x13, "LeaveGroup-Request" },
3579         { 0x14, "LeaveGroup-Response" },
3580         { 0x15, "Left" },
3581         { 0x16, "MemberAccess-Request" },
3582         { 0x17, "Mod" },
3583         { 0x18, "OwnProperties" },
3584         { 0x19, "RejectList-Request" },
3585         { 0x1A, "RejectList-Response" },
3586         { 0x1B, "RemoveGroupMembers-Request" },
3587         { 0x1C, "SetGroupProps-Request" },
3588         { 0x1D, "SubscribeGroupNotice-Request" },
3589         { 0x1E, "SubscribeGroupNotice-Response" },
3590         { 0x1F, "Users" },
3591         { 0x20, "WelcomeNote" },
3592         /* New in WV-CSP 1.1 */
3593         { 0x21, "JoinGroup" },
3594         { 0x22, "SubscribeNotification" },
3595         { 0x23, "SubscribeType" },
3596
3597         { 0x00, NULL }
3598 };
3599
3600 /*****    Attribute Start tokens   *****/
3601 /* Common code page */
3602 /* Same as cp0 of WV-CSP 1.0 */
3603 #define wbxml_wv_csp_11_attrStart_cp0 wbxml_wv_csp_10_attrStart_cp0
3604
3605 /*****    Attribute Value tokens   *****/
3606 /*
3607  * Element value tokens
3608  *
3609  * NOTE - WV-CSP uses the EXT_T_0 token in a peculiar way: the mb_u_int32
3610  * does *not* reference an offset in the string table, but it refers to
3611  * the index in the following value_string.
3612  * 
3613  * Please note that:
3614  *  - Values 'T' and 'F' are Boolean values representing "True" and "False"
3615  *    (or "Yes" and "No" in some circumstances) respectively.
3616  *  - Values 'GR', 'IM', 'PR', 'SC', 'GM' and 'US' are enumerated values
3617  *    representing "Group", "Instant Messaging", "Presence", "Shared Content",
3618  *    "Group membership" and "User" respectively.
3619  *  - Values 'G', 'S' and 'U' are enumerated values representing "Get", "Set"
3620  *    and "Unset" respectively.
3621  *  - Values 'N' and 'P' are enumerated values representing "Notify/Get" and
3622  *    "Push" respectively.
3623  *
3624  * I repeat: this is NOT a attrValue[] array hence it is not called
3625  * wbxml_wv_XXX but vals_wv_XXX.
3626  *
3627  * Result: the attribute value token definitions from WV-CSP 1.0 are dropped.
3628  */
3629 static const value_string vals_wv_csp_11_element_value_tokens[] = {
3630         /*
3631          * Common value tokens
3632          */
3633         { 0x00, "AccessType" },
3634         { 0x01, "ActiveUsers" },
3635         { 0x02, "Admin" },
3636         { 0x03, "application/" },
3637         { 0x04, "application/vnd.wap.mms-message" },
3638         { 0x05, "application/x-sms" },
3639         { 0x06, "AutoJoin" },
3640         { 0x07, "BASE64" },
3641         { 0x08, "Closed" },
3642         { 0x09, "Default" },
3643         { 0x0A, "DisplayName" },
3644         { 0x0B, "F" },
3645         { 0x0C, "G" },
3646         { 0x0D, "GR" },
3647         { 0x0E, "http://" },
3648         { 0x0F, "https://" },
3649         { 0x10, "image/" },
3650         { 0x11, "Inband" },
3651         { 0x12, "IM" },
3652         { 0x13, "MaxActiveUsers" },
3653         { 0x14, "Mod" },
3654         { 0x15, "Name" },
3655         { 0x16, "None" },
3656         { 0x17, "N" },
3657         { 0x18, "Open" },
3658         { 0x19, "Outband" },
3659         { 0x1A, "PR" },
3660         { 0x1B, "Private" },
3661         { 0x1C, "PrivateMessaging" },
3662         { 0x1D, "PrivilegeLevel" },
3663         { 0x1E, "Public" },
3664         { 0x1F, "P" },
3665         { 0x20, "Request" },
3666         { 0x21, "Response" },
3667         { 0x22, "Restricted" },
3668         { 0x23, "ScreenName" },
3669         { 0x24, "Searchable" },
3670         { 0x25, "S" },
3671         { 0x26, "SC" },
3672         { 0x27, "text/" },
3673         { 0x28, "text/plain" },
3674         { 0x29, "text/x-vCalendar" },
3675         { 0x2A, "text/x-vCard" },
3676         { 0x2B, "Topic" },
3677         { 0x2C, "T" },
3678         { 0x2D, "Type" },
3679         { 0x2E, "U" },
3680         { 0x2F, "US" },
3681         { 0x30, "www.wireless-village.org" },
3682         /*
3683          * Access value tokens
3684          */
3685         { 0x3D, "GROUP_ID" },
3686         { 0x3E, "GROUP_NAME" },
3687         { 0x3F, "GROUP_TOPIC" },
3688         { 0x40, "GROUP_USER_ID_JOINED" },
3689         { 0x41, "GROUP_USER_ID_OWNER" },
3690         { 0x42, "HTTP" },
3691         { 0x43, "SMS" },
3692         { 0x44, "STCP" },
3693         { 0x45, "SUDP" },
3694         { 0x46, "USER_ALIAS" },
3695         { 0x47, "USER_EMAIL_ADDRESS" },
3696         { 0x48, "USER_FIRST_NAME" },
3697         { 0x49, "USER_ID" },
3698         { 0x4A, "USER_LAST_NAME" },
3699         { 0x4B, "USER_MOBILE_NUMBER" },
3700         { 0x4C, "USER_ONLINE_STATUS" },
3701         { 0x4D, "WAPSMS" },
3702         { 0x4E, "WAPUDP" },
3703         { 0x4F, "WSP" },
3704         /*
3705          * Presence value tokens
3706          */
3707         { 0x5B, "ANGRY" },
3708         { 0x5C, "ANXIOUS" },
3709         { 0x5D, "ASHAMED" },
3710         { 0x5E, "AUDIO_CALL" },
3711         { 0x5F, "AVAILABLE" },
3712         { 0x60, "BORED" },
3713         { 0x61, "CALL" },
3714         { 0x62, "CLI" },
3715         { 0x63, "COMPUTER" },
3716         { 0x64, "DISCREET" },
3717         { 0x65, "EMAIL" },
3718         { 0x66, "EXCITED" },
3719         { 0x67, "HAPPY" },
3720         { 0x68, "IM" },
3721         { 0x69, "IM_OFFLINE" },
3722         { 0x6A, "IM_ONLINE" },
3723         { 0x6B, "IN_LOVE" },
3724         { 0x6C, "INVINCIBLE" },
3725         { 0x6D, "JEALOUS" },
3726         { 0x6E, "MMS" },
3727         { 0x6F, "MOBILE_PHONE" },
3728         { 0x70, "NOT_AVAILABLE" },
3729         { 0x71, "OTHER" },
3730         { 0x72, "PDA" },
3731         { 0x73, "SAD" },
3732         { 0x74, "SLEEPY" },
3733         { 0x75, "SMS" },
3734         { 0x76, "VIDEO_CALL" },
3735         { 0x77, "VIDEO_STREAM" },
3736
3737         { 0x00, NULL }
3738 };
3739
3740
3741 /***** Token code page aggregation *****/
3742
3743 static char *
3744 ext_t_0_wv_cspc_11(tvbuff_t *tvb _U_, guint32 value, guint32 str_tbl _U_)
3745 {
3746     char *str = g_strdup_printf("Common Value: '%s'",
3747             val_to_str(value, vals_wv_csp_11_element_value_tokens,
3748                 "<Unknown WV-CSP 1.1 Common Value token 0x%X>"));
3749     return str;
3750 }
3751
3752 static const value_valuestring wbxml_wv_csp_11_global[] = {
3753         { 0, wbxml_wv_csp_11_global_cp0 },
3754         { 0, NULL }
3755 };
3756
3757 static const value_valuestring wbxml_wv_csp_11_tags[] = {
3758         { 0, wbxml_wv_csp_11_tags_cp0 },
3759         { 1, wbxml_wv_csp_11_tags_cp1 },
3760         { 2, wbxml_wv_csp_11_tags_cp2 },
3761         { 3, wbxml_wv_csp_11_tags_cp3 },
3762         { 4, wbxml_wv_csp_11_tags_cp4 },
3763         { 5, wbxml_wv_csp_11_tags_cp5 },
3764         { 6, wbxml_wv_csp_11_tags_cp6 },
3765         { 7, wbxml_wv_csp_11_tags_cp7 },
3766         { 0, NULL }
3767 };
3768
3769 static const value_valuestring wbxml_wv_csp_11_attrStart[] = {
3770         { 0, wbxml_wv_csp_11_attrStart_cp0 },
3771         { 0, NULL }
3772 };
3773
3774 static const wbxml_decoding decode_wv_cspc_11 = {
3775     "Wireless-Village Client-Server Protocol 1.1",
3776     "WV-CSP 1.1",
3777     { ext_t_0_wv_cspc_11, NULL, NULL },
3778         wv_csp11_opaque_binary_tag,
3779         default_opaque_literal_tag,
3780         default_opaque_binary_attr,
3781         default_opaque_literal_attr,
3782     wbxml_wv_csp_11_global,
3783     wbxml_wv_csp_11_tags,
3784     wbxml_wv_csp_11_attrStart,
3785     NULL
3786 };
3787
3788
3789
3790
3791
3792 /* WV-CSP 1.2
3793  * 
3794  * Wireless Village Client Server Protocol
3795  ***************************************/
3796 #ifdef Remove_this_comment_when_WV_CSP_will_be_an_approved_spec
3797
3798 /*****   Global extension tokens   *****/
3799 /* Same as WV-CSP 1.1 */
3800
3801 /*****         Tag tokens          *****/
3802 /* Common code page */
3803 /* Same as cp0 of WV-CSP 1.1 */
3804 #define wbxml_wv_csp_12_tags_cp0 wbxml_wv_csp_11_tags_cp0
3805 /* Note that the table continues in code page 0x09 */
3806
3807 /* Access code page (0x01) */
3808 static const value_string wbxml_wv_csp_12_tags_cp1[] = {
3809         /* 0x00 -- 0x04 GLOBAL */
3810         { 0x05, "AllFunctions" },
3811         { 0x06, "AllFunctionsRequest" },
3812         { 0x07, "CancelInvite-Request" },
3813         { 0x08, "CancelInviteUser-Request" },
3814         { 0x09, "Capability" },
3815         { 0x0A, "CapabilityList" },
3816         { 0x0B, "CapabilityRequest" },
3817         { 0x0C, "ClientCapability-Request" },
3818         { 0x0D, "ClientCapability-Response" },
3819         { 0x0E, "DigestBytes" },
3820         { 0x0F, "DigestSchema" },
3821         { 0x10, "Disconnect" },
3822         { 0x11, "Functions" },
3823         { 0x12, "GetSPInfo-Request" },
3824         { 0x13, "GetSPInfo-Response" },
3825         { 0x14, "InviteID" },
3826         { 0x15, "InviteNote" },
3827         { 0x16, "Invite-Request" },
3828         { 0x17, "Invite-Response" },
3829         { 0x18, "InviteType" },
3830         { 0x19, "InviteUser-Request" },
3831         { 0x1A, "InviteUser-Response" },
3832         { 0x1B, "KeepAlive-Request" },
3833         { 0x1C, "KeepAliveTime" },
3834         { 0x1D, "Login-Request" },
3835         { 0x1E, "Login-Response" },
3836         { 0x1F, "Logout-Request" },
3837         { 0x20, "Nonce" },
3838         { 0x21, "Password" },
3839         { 0x22, "Polling-Request" },
3840         { 0x23, "ResponseNote" },
3841         { 0x24, "SearchElement" },
3842         { 0x25, "SearchFindings" },
3843         { 0x26, "SearchID" },
3844         { 0x27, "SearchIndex" },
3845         { 0x28, "SearchLimit" },
3846         { 0x29, "KeepAlive-Response" },
3847         { 0x2A, "SearchPairList" },
3848         { 0x2B, "Search-Request" },
3849         { 0x2C, "Search-Response" },
3850         { 0x2D, "SearchResult" },
3851         { 0x2E, "Service-Request" },
3852         { 0x2F, "Service-Response" },
3853         { 0x30, "SessionCookie" },
3854         { 0x31, "StopSearch-Request" },
3855         { 0x32, "TimeToLive" },
3856         /* New in WV-CSP 1.1 */
3857         { 0x33, "SearchString" },
3858         { 0x34, "CompletionFlag" },
3859         /* New in WV-CSP 1.2 */
3860         { 0x36, "ReceiveList" },
3861         { 0x37, "VerifyID-Request" },
3862         { 0x38, "Extended-Request" },
3863         { 0x39, "Extended-Response" },
3864         { 0x3A, "AgreedCapabilityList" },
3865         { 0x3B, "ExtendedData" },
3866         { 0x3C, "OtherServer" },
3867         { 0x3D, "PresenceAttributeNSName" },
3868         { 0x3E, "SessionNSName" },
3869         { 0x3F, "TransactionNSName" },
3870
3871         { 0x00, NULL }
3872 };
3873 /* Note that the table continues in code page 0x0A */
3874
3875 /* Service code page (0x02) */
3876 static const value_string wbxml_wv_csp_12_tags_cp2[] = {
3877         /* 0x00 -- 0x04 GLOBAL */
3878         { 0x05, "ADDGM" },
3879         { 0x06, "AttListFunc" },
3880         { 0x07, "BLENT" },
3881         { 0x08, "CAAUT" },
3882         { 0x09, "CAINV" },
3883         { 0x0A, "CALI" },
3884         { 0x0B, "CCLI" },
3885         { 0x0C, "ContListFunc" },
3886         { 0x0D, "CREAG" },
3887         { 0x0E, "DALI" },
3888         { 0x0F, "DCLI" },
3889         { 0x10, "DELGR" },
3890         { 0x11, "FundamentalFeat" },
3891         { 0x12, "FWMSG" },
3892         { 0x13, "GALS" },
3893         { 0x14, "GCLI" },
3894         { 0x15, "GETGM" },
3895         { 0x16, "GETGP" },
3896         { 0x17, "GETLM" },
3897         { 0x18, "GETM" },
3898         { 0x19, "GETPR" },
3899         { 0x1A, "GETSPI" },
3900         { 0x1B, "GETWL" },
3901         { 0x1C, "GLBLU" },
3902         { 0x1D, "GRCHN" },
3903         { 0x1E, "GroupAuthFunc" },
3904         { 0x1F, "GroupFeat" },
3905         { 0x20, "GroupMgmtFunc" },
3906         { 0x21, "GroupUseFunc" },
3907         { 0x22, "IMAuthFunc" },
3908         { 0x23, "IMFeat" },
3909         { 0x24, "IMReceiveFunc" },
3910         { 0x25, "IMSendFunc" },
3911         { 0x26, "INVIT" },
3912         { 0x27, "InviteFunc" },
3913         { 0x28, "MBRAC" },
3914         { 0x29, "MCLS" },
3915         { 0x2A, "MDELIV" },
3916         { 0x2B, "NEWM" },
3917         { 0x2C, "NOTIF" },
3918         { 0x2D, "PresenceAuthFunc" },
3919         { 0x2E, "PresenceDeliverFunc" },
3920         { 0x2F, "PresenceFeat" },
3921         { 0x30, "REACT" },
3922         { 0x31, "REJCM" },
3923         { 0x32, "REJEC" },
3924         { 0x33, "RMVGM" },
3925         { 0x34, "SearchFunc" },
3926         { 0x35, "ServiceFunc" },
3927         { 0x36, "SETD" },
3928         { 0x37, "SETGP" },
3929         { 0x38, "SRCH" },
3930         { 0x39, "STSRC" },
3931         { 0x3A, "SUBGCN" },
3932         { 0x3B, "UPDPR" },
3933         { 0x3C, "WVCSPFeat" },
3934         /* New in WV-CSP 1.2 */
3935         { 0x3D, "MF" },
3936         { 0x3E, "MG" },
3937         { 0x3E, "VRID" }, /* Duplicate, and cp2 is full --> Will move to cp8? */
3938         { 0x3F, "MM" },
3939
3940         { 0x00, NULL }
3941 };
3942 /* Note that the table continues in code page 0x08 */
3943
3944 /* Client capability code page (0x03) */
3945 /* Same as cp3 of WV-CSP 1.1 */
3946 #define wbxml_wv_csp_12_tags_cp3 wbxml_wv_csp_11_tags_cp3
3947
3948 /* Presence primitive code page (0x04) */
3949 static const value_string wbxml_wv_csp_12_tags_cp4[] = {
3950         /* 0x00 -- 0x04 GLOBAL */
3951         { 0x05, "CancelAuth-Request" },
3952         { 0x06, "ContactListProperties" },
3953         { 0x07, "CreateAttributeList-Request" },
3954         { 0x08, "CreateList-Request" },
3955         { 0x09, "DefaultAttributeList" },
3956         { 0x0A, "DefaultContactList" },
3957         { 0x0B, "DefaultList" },
3958         { 0x0C, "DeleteAttributeList-Request" },
3959         { 0x0D, "DeleteList-Request" },
3960         { 0x0E, "GetAttributeList-Request" },
3961         { 0x0F, "GetAttributeList-Response" },
3962         { 0x10, "GetList-Request" },
3963         { 0x11, "GetList-Response" },
3964         { 0x12, "GetPresence-Request" },
3965         { 0x13, "GetPresence-Response" },
3966         { 0x14, "GetWatcherList-Request" },
3967         { 0x15, "GetWatcherList-Response" },
3968         { 0x16, "ListManage-Request" },
3969         { 0x17, "ListManage-Response" },
3970         { 0x18, "UnsubscribePresence-Request" },
3971         { 0x19, "PresenceAuth-Request" },
3972         { 0x1A, "PresenceAuth-User" },
3973         { 0x1B, "PresenceNotification-Request" },
3974         { 0x1C, "UpdatePresence-Request" },
3975         { 0x1D, "SubscribePresence-Request" },
3976         /* New in WV-CSP 1.2 */
3977         { 0x1E, "Auto-Subscribe" },
3978         /* 0x1E was defined in WV-CSP 1.0: UnsubscribePresence-Request */
3979         { 0x1F, "GetReactiveAuthStatus-Request" },
3980         /* 0x1F was defined in WV-CSP 1.0: UpdatePresence-Request */
3981         { 0x20, "GetReactiveAuthStatus-Response" },
3982
3983         { 0x00, NULL }
3984 };
3985
3986 /* Presence attribute code page (0x05) */
3987 static const value_string wbxml_wv_csp_12_tags_cp5[] = {
3988         /* 0x00 -- 0x04 GLOBAL */
3989         { 0x05, "Accuracy" },
3990         { 0x06, "Address" },
3991         { 0x07, "AddrPref" },
3992         { 0x08, "Alias" },
3993         { 0x09, "Altitude" },
3994         { 0x0A, "Building" },
3995         { 0x0B, "Caddr" },
3996         { 0x0C, "City" },
3997         { 0x0D, "ClientInfo" },
3998         { 0x0E, "ClientProducer" },
3999         { 0x0F, "ClientType" },
4000         { 0x10, "ClientVersion" },
4001         { 0x11, "CommC" },
4002         { 0x12, "CommCap" },
4003         { 0x13, "ContactInfo" },
4004         { 0x14, "ContainedvCard" },
4005         { 0x15, "Country" },
4006         { 0x16, "Crossing1" },
4007         { 0x17, "Crossing2" },
4008         { 0x18, "DevManufacturer" },
4009         { 0x19, "DirectContent" },
4010         { 0x1A, "FreeTextLocation" },
4011         { 0x1B, "GeoLocation" },
4012         { 0x1C, "Language" },
4013         { 0x1D, "Latitude" },
4014         { 0x1E, "Longitude" },
4015         { 0x1F, "Model" },
4016         { 0x20, "NamedArea" },
4017         { 0x21, "OnlineStatus" },
4018         { 0x22, "PLMN" },
4019         { 0x23, "PrefC" },
4020         { 0x24, "PreferredContacts" },
4021         { 0x25, "PreferredLanguage" },
4022         { 0x26, "ReferredContent" },
4023         { 0x27, "ReferredvCard" },
4024         { 0x28, "Registration" },
4025         { 0x29, "StatusContent" },
4026         { 0x2A, "StatusMood" },
4027         { 0x2B, "StatusText" },
4028         { 0x2C, "Street" },
4029         { 0x2D, "TimeZone" },
4030         { 0x2E, "UserAvailability" },
4031         /* New in WV-CSP 1.1 */
4032         { 0x2F, "Cap" },
4033         { 0x30, "Cname" },
4034         { 0x31, "Contact" },
4035         { 0x32, "Cpriority" },
4036         { 0x33, "Cstatus" },
4037         { 0x34, "Note" },
4038         { 0x35, "Zone" },
4039         /* New in WV-CSP 1.2 */
4040         { 0x36, "ContentType" },
4041         { 0x37, "Inf_link" },
4042         { 0x38, "InfoLink" },
4043         { 0x39, "Link" },
4044         { 0x3A, "Text" },
4045
4046         { 0x00, NULL }
4047 };
4048
4049 /* Messaging code page (0x06) */
4050 static const value_string wbxml_wv_csp_12_tags_cp6[] = {
4051         /* 0x00 -- 0x04 GLOBAL */
4052         { 0x05, "BlockList" },
4053         { 0x06, "BlockEntity-Request" }, /* Was: BlockUser-Request */
4054         { 0x07, "DeliveryMethod" },
4055         { 0x08, "DeliveryReport" },
4056         { 0x09, "DeliveryReport-Request" },
4057         { 0x0A, "ForwardMessage-Request" },
4058         { 0x0B, "GetBlockedList-Request" },
4059         { 0x0C, "GetBlockedList-Response" },
4060         { 0x0D, "GetMessageList-Request" },
4061         { 0x0E, "GetMessageList-Response" },
4062         { 0x0F, "GetMessage-Request" },
4063         { 0x10, "GetMessage-Response" },
4064         { 0x11, "GrantList" },
4065         { 0x12, "MessageDelivered" },
4066         { 0x13, "MessageInfo" },
4067         { 0x14, "MessageNotification" },
4068         { 0x15, "NewMessage" },
4069         { 0x16, "RejectMessage-Request" },
4070         { 0x17, "SendMessage-Request" },
4071         { 0x18, "SendMessage-Response" },
4072         { 0x19, "SetDeliveryMethod-Request" },
4073         { 0x1A, "DeliveryTime" },
4074
4075         { 0x00, NULL }
4076 };
4077
4078 /* Group code page (0x07) */
4079 static const value_string wbxml_wv_csp_12_tags_cp7[] = {
4080         /* 0x00 -- 0x04 GLOBAL */
4081         { 0x05, "AddGroupMembers-Request" },
4082         { 0x06, "Admin" },
4083         { 0x07, "CreateGroup-Request" },
4084         { 0x08, "DeleteGroup-Request" },
4085         { 0x09, "GetGroupMembers-Request" },
4086         { 0x0A, "GetGroupMembers-Response" },
4087         { 0x0B, "GetGroupProps-Request" },
4088         { 0x0C, "GetGroupProps-Response" },
4089         { 0x0D, "GroupChangeNotice" },
4090         { 0x0E, "GroupProperties" },
4091         { 0x0F, "Joined" },
4092         { 0x10, "JoinedRequest" },
4093         { 0x11, "JoinGroup-Request" },
4094         { 0x12, "JoinGroup-Response" },
4095         { 0x13, "LeaveGroup-Request" },
4096         { 0x14, "LeaveGroup-Response" },
4097         { 0x15, "Left" },
4098         { 0x16, "MemberAccess-Request" },
4099         { 0x17, "Mod" },
4100         { 0x18, "OwnProperties" },
4101         { 0x19, "RejectList-Request" },
4102         { 0x1A, "RejectList-Response" },
4103         { 0x1B, "RemoveGroupMembers-Request" },
4104         { 0x1C, "SetGroupProps-Request" },
4105         { 0x1D, "SubscribeGroupNotice-Request" },
4106         { 0x1E, "SubscribeGroupNotice-Response" },
4107         { 0x1F, "Users" },
4108         { 0x20, "WelcomeNote" },
4109         /* New in WV-CSP 1.1 */
4110         { 0x21, "JoinGroup" },
4111         { 0x22, "SubscribeNotification" },
4112         { 0x23, "SubscribeType" },
4113         /* New in WV-CSP 1.2 */
4114         { 0x24, "GetJoinedUsers-Request" },
4115         { 0x25, "GetJoinedUsers-Response" },
4116         { 0x26, "AdminMapList" },
4117         { 0x27, "AdminMapping" },
4118         { 0x28, "Mapping" },
4119         { 0x29, "ModMapping" },
4120         { 0x2A, "UserMapList" },
4121         { 0x2B, "UserMapping" },
4122
4123         { 0x00, NULL }
4124 };
4125
4126 /* Service negotiation code page - continued (0x08) */
4127 /* Same as cp8 of WV-CSP 1.1, but a new token is likely to be added. - XXX */
4128 static const value_string wbxml_wv_csp_12_tags_cp8[] = {
4129         /* 0x00 -- 0x04 GLOBAL */
4130         { 0x05, "MP" },
4131         { 0x06, "GETAUT" },
4132         { 0x07, "GETJU" },
4133
4134         { 0x00, NULL }
4135 };
4136
4137 /* Common code page - continued (0x09) */
4138 static const value_string wbxml_wv_csp_12_tags_cp9[] = {
4139         /* 0x00 -- 0x04 GLOBAL */
4140         { 0x05, "CIR" },
4141         { 0x06, "Domain" },
4142         { 0x07, "ExtBlock" },
4143         { 0x08, "HistoryPeriod" },
4144         { 0x09, "IDList" },
4145         { 0x0A, "MaxWatcherList" },
4146         { 0x0B, "ReactiveAuthState" },
4147         { 0x0C, "ReactiveAuthStatus" },
4148         { 0x0D, "ReactiveAuthStatusList" },
4149         { 0x0E, "Watcher" },
4150         { 0x0C, "WatcherStatus" }, /* Duplicate --> Will move to 0x0F? */
4151
4152         { 0x00, NULL }
4153 };
4154
4155 /* Access code page - continued (0x0A) */
4156 static const value_string wbxml_wv_csp_12_tags_cp10[] = {
4157         /* 0x00 -- 0x04 GLOBAL */
4158         { 0x05, "WV-CSP-NSDiscovery-Request" },
4159         { 0x06, "WV-CSP-NSDiscovery-Response" },
4160
4161         { 0x00, NULL }
4162 };
4163
4164 /*****    Attribute Start tokens   *****/
4165 /* Common code page (0x00) */
4166 static const value_string wbxml_wv_csp_12_attrStart_cp0[] = {
4167         /* 0x00 -- 0x04 GLOBAL */
4168         { 0x05, "xmlns='http://www.wireless-village.org/CSP'" },
4169         { 0x06, "xmlns='http://www.wireless-village.org/PA'" },
4170         { 0x07, "xmlns='http://www.wireless-village.org/TRC'" },
4171         /* New in WV-CSP 1.2 */
4172         { 0x08, "xmlns='http://www.openmobilealliance.org/DTD/WV-CSP'" },
4173         { 0x09, "xmlns='http://www.openmobilealliance.org/DTD/WV-PA'" },
4174         { 0x0A, "xmlns http://www.openmobilealliance.org/DTD/WV-TRC'" },
4175
4176         { 0x00, NULL }
4177 };
4178
4179 /*****    Attribute Value tokens   *****/
4180 /*
4181  * Element value tokens
4182  *
4183  * NOTE - WV-CSP uses the EXT_T_0 token in a peculiar way: the mb_u_int32
4184  * does *not* reference an offset in the string table, but it refers to
4185  * the index in the following value_string.
4186  *
4187  * Please note that:
4188  *  - Values 'T' and 'F' are Boolean values representing "True" and "False"
4189  *    (or "Yes" and "No" in some circumstances) respectively.
4190  *  - Values 'GR', 'IM', 'PR', 'SC', 'GM' and 'US' are enumerated values
4191  *    representing "Group", "Instant Messaging", "Presence", "Shared Content",
4192  *    "Group membership" and "User" respectively.
4193  *  - Values 'G', 'S' and 'U' are enumerated values representing "Get", "Set"
4194  *    and "Unset" respectively.
4195  *  - Values 'N' and 'P' are enumerated values representing "Notify/Get" and
4196  *    "Push" respectively.
4197  *
4198  * I repeat: this is NOT a attrValue[] array hence it is not called
4199  * wbxml_wv_XXX but vals_wv_XXX.
4200  */
4201 static const value_string vals_wv_csp_12_element_value_tokens[] = {
4202         /*
4203          * Common value tokens
4204          */
4205         { 0x00, "AccessType" },
4206         { 0x01, "ActiveUsers" },
4207         { 0x02, "Admin" },
4208         { 0x03, "application/" },
4209         { 0x04, "application/vnd.wap.mms-message" },
4210         { 0x05, "application/x-sms" },
4211         { 0x06, "AutoJoin" },
4212         { 0x07, "BASE64" },
4213         { 0x08, "Closed" },
4214         { 0x09, "Default" },
4215         { 0x0A, "DisplayName" },
4216         { 0x0B, "F" },
4217         { 0x0C, "G" },
4218         { 0x0D, "GR" },
4219         { 0x0E, "http://" },
4220         { 0x0F, "https://" },
4221         { 0x10, "image/" },
4222         { 0x11, "Inband" },
4223         { 0x12, "IM" },
4224         { 0x13, "MaxActiveUsers" },
4225         { 0x14, "Mod" },
4226         { 0x15, "Name" },
4227         { 0x16, "None" },
4228         { 0x17, "N" },
4229         { 0x18, "Open" },
4230         { 0x19, "Outband" },
4231         { 0x1A, "PR" },
4232         { 0x1B, "Private" },
4233         { 0x1C, "PrivateMessaging" },
4234         { 0x1D, "PrivilegeLevel" },
4235         { 0x1E, "Public" },
4236         { 0x1F, "P" },
4237         { 0x20, "Request" },
4238         { 0x21, "Response" },
4239         { 0x22, "Restricted" },
4240         { 0x23, "ScreenName" },
4241         { 0x24, "Searchable" },
4242         { 0x25, "S" },
4243         { 0x26, "SC" },
4244         { 0x27, "text/" },
4245         { 0x28, "text/plain" },
4246         { 0x29, "text/x-vCalendar" },
4247         { 0x2A, "text/x-vCard" },
4248         { 0x2B, "Topic" },
4249         { 0x2C, "T" },
4250         { 0x2D, "Type" },
4251         { 0x2E, "U" },
4252         { 0x2F, "US" },
4253         { 0x30, "www.wireless-village.org" },
4254         /* New in WV-CSP 1.2 */
4255         { 0x31, "AutoDelete" },
4256         { 0x32, "GM" },
4257         { 0x33, "Validity" },
4258         { 0x34, "DENIED" }, /* Duplicate */
4259         { 0x34, "ShowID" }, /* Duplicate */
4260         { 0x35, "GRANTED" },
4261         { 0x36, "PENDING" },
4262         /*
4263          * Access value tokens
4264          */
4265         { 0x3D, "GROUP_ID" },
4266         { 0x3E, "GROUP_NAME" },
4267         { 0x3F, "GROUP_TOPIC" },
4268         { 0x40, "GROUP_USER_ID_JOINED" },
4269         { 0x41, "GROUP_USER_ID_OWNER" },
4270         { 0x42, "HTTP" },
4271         { 0x43, "SMS" },
4272         { 0x44, "STCP" },
4273         { 0x45, "SUDP" },
4274         { 0x46, "USER_ALIAS" },
4275         { 0x47, "USER_EMAIL_ADDRESS" },
4276         { 0x48, "USER_FIRST_NAME" },
4277         { 0x49, "USER_ID" },
4278         { 0x4A, "USER_LAST_NAME" },
4279         { 0x4B, "USER_MOBILE_NUMBER" },
4280         { 0x4C, "USER_ONLINE_STATUS" },
4281         { 0x4D, "WAPSMS" },
4282         { 0x4E, "WAPUDP" },
4283         { 0x4F, "WSP" },
4284         /* New in WV-CSP 1.2 */
4285         { 0x50, "GROUP_USER_ID_AUTOJOIN" },
4286         /*
4287          * Presence value tokens
4288          */
4289         { 0x5B, "ANGRY" },
4290         { 0x5C, "ANXIOUS" },
4291         { 0x5D, "ASHAMED" },
4292         { 0x5E, "AUDIO_CALL" },
4293         { 0x5F, "AVAILABLE" },
4294         { 0x60, "BORED" },
4295         { 0x61, "CALL" },
4296         { 0x62, "CLI" },
4297         { 0x63, "COMPUTER" },
4298         { 0x64, "DISCREET" },
4299         { 0x65, "EMAIL" },
4300         { 0x66, "EXCITED" },
4301         { 0x67, "HAPPY" },
4302         { 0x68, "IM" },
4303         { 0x69, "IM_OFFLINE" },
4304         { 0x6A, "IM_ONLINE" },
4305         { 0x6B, "IN_LOVE" },
4306         { 0x6C, "INVINCIBLE" },
4307         { 0x6D, "JEALOUS" },
4308         { 0x6E, "MMS" },
4309         { 0x6F, "MOBILE_PHONE" },
4310         { 0x70, "NOT_AVAILABLE" },
4311         { 0x71, "OTHER" },
4312         { 0x72, "PDA" },
4313         { 0x73, "SAD" },
4314         { 0x74, "SLEEPY" },
4315         { 0x75, "SMS" },
4316         { 0x76, "VIDEO_CALL" },
4317         { 0x77, "VIDEO_STREAM" },
4318
4319         { 0x00, NULL }
4320 };
4321
4322
4323
4324 /***** Token code page aggregation *****/
4325
4326 static char *
4327 ext_t_0_wv_cspc_12(tvbuff_t *tvb _U_, guint32 value, guint32 str_tbl _U_)
4328 {
4329     char *str = g_strdup_printf("Common Value: '%s'",
4330             val_to_str(value, vals_wv_csp_12_element_value_tokens,
4331                 "<Unknown WV-CSP 1.2 Common Value token 0x%X>"));
4332     return str;
4333 }
4334
4335 #define wbxml_wv_csp_12_global wbxml_wv_csp_11_global
4336
4337 static const value_valuestring wbxml_wv_csp_12_tags[] = {
4338         {  0, wbxml_wv_csp_12_tags_cp0 },
4339         {  1, wbxml_wv_csp_12_tags_cp1 },
4340         {  2, wbxml_wv_csp_12_tags_cp2 },
4341         {  3, wbxml_wv_csp_12_tags_cp3 },
4342         {  4, wbxml_wv_csp_12_tags_cp4 },
4343         {  5, wbxml_wv_csp_12_tags_cp5 },
4344         {  6, wbxml_wv_csp_12_tags_cp6 },
4345         {  7, wbxml_wv_csp_12_tags_cp7 },
4346         {  8, wbxml_wv_csp_12_tags_cp8 },
4347         {  9, wbxml_wv_csp_12_tags_cp9 },
4348         { 10, wbxml_wv_csp_12_tags_cp10 },
4349         {  0, NULL }
4350 };
4351
4352 static const value_valuestring wbxml_wv_csp_12_attrStart[] = {
4353         { 0, wbxml_wv_csp_12_attrStart_cp0 },
4354         { 0, NULL }
4355 };
4356
4357 static const wbxml_decoding decode_wv_cspc_12 = {
4358     "Wireless-Village Client-Server Protocol 1.2",
4359     "WV-CSP 1.2",
4360     { ext_t_0_wv_cspc_12, NULL, NULL },
4361         wv_csp12_opaque_binary_tag,
4362         default_opaque_literal_tag,
4363         default_opaque_binary_attr,
4364         default_opaque_literal_attr,
4365     wbxml_wv_csp_12_global,
4366     wbxml_wv_csp_12_tags,
4367     wbxml_wv_csp_12_attrStart,
4368     NULL
4369 };
4370 #endif /* Remove_this_comment_when_WV_CSP_will_be_an_approved_spec */
4371
4372
4373
4374
4375
4376 /****************************** Discriminators ******************************/
4377 /* Discriminator for WV-CSP; allows version detection based on parsing parts
4378  * of the start of the WBXML body.
4379  */
4380 const wbxml_decoding *
4381 wv_csp_discriminator(tvbuff_t *tvb, guint32 offset)
4382 {
4383         guint32 magic_1 = tvb_get_ntohl(tvb, offset + 0);
4384         guint16 magic_2 = tvb_get_ntohs(tvb, offset + 4);
4385
4386         if (magic_1 == 0xFE050331 && magic_2 == 0x2e30) {
4387                 /* FE 05 03 31 23 30 --> WV-CSP 1.0 */
4388                 return &decode_wv_cspc_10;
4389         } else if (magic_1 == 0xC9050331 && magic_2 == 0x2e31) {
4390                 /* C9 05 03 31 23 31 --> WV-CSP 1.1 */
4391                 return &decode_wv_cspc_11;
4392 #ifdef Remove_this_comment_when_WV_CSP_will_be_an_approved_spec
4393         } else if (magic_1 == 0xC9050331 && magic_2 == 0x2e31) {
4394                 /* C9 05 03 31 23 32 --> WV-CSP 1.2 */
4395                 return &decode_wv_cspc_12;
4396 #endif /* Remove_this_comment_when_WV_CSP_will_be_an_approved_spec */
4397         }
4398
4399         /* Default: WV-CSP 1.1 */
4400         return &decode_wv_cspc_11;
4401 }
4402
4403 /********************** WBXML token mapping aggregation **********************/
4404
4405 static const wbxml_decoding *get_wbxml_decoding_from_public_id (guint32 publicid);
4406 static const wbxml_decoding *get_wbxml_decoding_from_content_type (
4407         const char *content_type, tvbuff_t *tvb, guint32 offset);
4408
4409
4410 /**
4411  ** Aggregation of content type and aggregated code pages
4412  ** Content type map lookup will stop at the 1st entry with 3rd member = FALSE
4413  **/
4414
4415 /*
4416  * The following map contains entries registered with a registered WBXML
4417  * public ID. See WAP WINA or OMA OMNA for registered values:
4418  * http://www.openmobilealliance.org/tech/omna/ */
4419 static const wbxml_integer_list well_known_public_id_list[] = {
4420     /* 0x00 - Unknown or missing Public ID */
4421     /* 0x01 - LITERAL PublicID - see String Table */
4422     { 0x02,     &decode_wmlc_10 },      /* WML 1.0 */
4423     /* 0x03 - WTA 1.0 */
4424     { 0x04,     &decode_wmlc_11 },      /* WML 1.1 */
4425     { 0x05,     &decode_sic_10 },       /* SI 1.0 */
4426     { 0x06,     &decode_slc_10 },       /* SL 1.0 */
4427     { 0x07,     &decode_coc_10 },       /* CO 1.0 */
4428     { 0x08,     &decode_channelc_10 },  /* CHANNEL 1.0 */
4429     { 0x09,     &decode_wmlc_12 },      /* WML 1.2 */
4430     { 0x0A,     &decode_wmlc_13 },      /* WML 1.3 */
4431     { 0x0B,     &decode_provc_10 },     /* PROV 1.0 */
4432     /* 0x0C - WTA-WML 1.2 */
4433     { 0x0D,     &decode_emnc_10 },      /* EMN 1.0 */
4434     /* 0x0E - DRMREL 1.0 */
4435     { 0x0F,     &decode_wv_cspc_10 },   /* WV-CSP 1.0 */
4436     { 0x10,     &decode_wv_cspc_11 },   /* WV-CSP 1.1 */
4437
4438     { 0x020B,   &decode_nokiaprovc_70 },/* Nokia OTA Provisioning 7.0 */
4439     { 0x0FD1,   &decode_syncmlc_10 },   /* SyncML 1.0 */
4440     { 0x0FD3,   &decode_syncmlc_11 },   /* SyncML 1.1 */
4441     /* Note: I assumed WML+ 1.x would be not that different from WML 1.x,
4442      *       the real mapping should come from Phone.com (OpenWave)! */
4443     { 0x1108,   &decode_wmlc_11 },      /* Phone.com WMLC+ 1.1 - not 100% correct */
4444     { 0x110D,   &decode_wmlc_13 },      /* Phone.com WMLC+ 1.3 - not 100% correct */
4445
4446     { 0x00,     NULL }
4447 };
4448
4449 /* The following map contains entries only registered with a literal media
4450  * type. */
4451 static const wbxml_literal_list content_type_list[] = {
4452     {   "application/x-wap-prov.browser-settings",
4453         NULL,
4454         &decode_nokiaprovc_70
4455     },
4456     {   "application/x-wap-prov.browser-bookmarks",
4457         NULL,
4458         &decode_nokiaprovc_70
4459     },
4460     {   "application/vnd.wv.csp.wbxml",
4461         wv_csp_discriminator,
4462         &decode_wv_cspc_11
4463     },
4464     {   NULL, NULL, NULL }
4465 };
4466         
4467
4468 /* Returns a pointer to the WBXML token map for the given WBXML public
4469  * identifier value (see WINA for a table with defined identifiers). */
4470 static const wbxml_decoding *get_wbxml_decoding_from_public_id (guint32 public_id)
4471 {
4472     const wbxml_decoding *map = NULL;
4473
4474     DebugLog(("get_wbxml_decoding_from_public_id: public_id = %u\n",
4475                 public_id));
4476     if (public_id >= 2) {
4477         const wbxml_integer_list *item = well_known_public_id_list;
4478
4479         while (item && item->public_id && item->map) {
4480             if (item->public_id == public_id) {
4481                 map = item->map;
4482                 break;
4483             }
4484             item++;
4485         }
4486     }
4487     return map;
4488 }
4489
4490 static const wbxml_decoding *get_wbxml_decoding_from_content_type (
4491         const char *content_type, tvbuff_t *tvb, guint32 offset)
4492 {
4493     const wbxml_decoding *map = NULL;
4494
4495     DebugLog(("get_wbxml_decoding_from_content_type: content_type = [%s]\n",
4496                 content_type));
4497     if (content_type && content_type[0]) {
4498         const wbxml_literal_list *item = content_type_list;
4499
4500         while (item && item->content_type) {
4501             if (strcasecmp(content_type, item->content_type) == 0) {
4502                 /* Try the discriminator */
4503                 if (item->discriminator != NULL) {
4504                     map = item->discriminator(tvb, offset);
4505                 }
4506                 if (map == NULL) {
4507                     map = item->map;
4508                 }
4509                 break;
4510             }
4511             item++;
4512         }
4513     }
4514     return map;
4515 }
4516
4517
4518 /* WBXML content token mapping depends on the following parameters:
4519  *   - Content type (guint32)
4520  *   - Token type (global, tags, attrStart, attrValue)
4521  *   - Code page for tag and attribute
4522  *
4523  * This results in the following steps:
4524  *   1. Retrieve content type mapping
4525  *   2. If exists, retrieve token type mapping
4526  *   3. If exists, retrieve required code page
4527  *   4. If exists, retrieve token mapping
4528  */
4529
4530 #define wbxml_UNDEFINED_TOKEN \
4531         "(Requested token not defined for this content type)"
4532 #define wbxml_UNDEFINED_TOKEN_CODE_PAGE \
4533         "(Requested token code page not defined for this content type)"
4534 #define wbxml_UNDEFINED_TOKEN_MAP \
4535         "(Requested token map not defined for this content type)"
4536 /* Return token mapping for a given content mapping entry. */
4537 static const char *
4538 map_token (const value_valuestring *token_map, guint8 codepage, guint8 token) {
4539         const value_string *vs;
4540         const char *s;
4541
4542         if (token_map) { /* Found map */
4543                 if ((vs = val_to_valstr (codepage, token_map))) {
4544                         /* Found codepage map */
4545                         s = match_strval (token, vs);
4546                         if (s) { /* Found valid token */
4547                                 DebugLog(("map_token(codepage = %u, token = %u: [%s]\n", codepage, token, s));
4548                                 return s;
4549                         }
4550                         /* No valid token mapping in specified code page of token map */
4551                         DebugLog(("map_token(codepage = %u, token = %u: "
4552                                                 wbxml_UNDEFINED_TOKEN "\n", codepage, token));
4553                         return wbxml_UNDEFINED_TOKEN;
4554                 }
4555                 /* There is no token map entry for the requested code page */
4556                 DebugLog(("map_token(codepage = %u, token = %u: "
4557                                         wbxml_UNDEFINED_TOKEN_CODE_PAGE "\n", codepage, token));
4558                 return wbxml_UNDEFINED_TOKEN_CODE_PAGE;
4559         }
4560         /* The token map does not exist */
4561         DebugLog(("map_token(codepage = %u, token = %u: "
4562                                 wbxml_UNDEFINED_TOKEN_MAP "\n", codepage, token));
4563         return wbxml_UNDEFINED_TOKEN_MAP;
4564 }
4565
4566
4567
4568
4569
4570 /************************** Function prototypes **************************/
4571
4572
4573 static void
4574 dissect_wbxml(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
4575
4576 void
4577 proto_register_wbxml(void);
4578
4579 /* Parse and display the WBXML string table */
4580 static void
4581 show_wbxml_string_table (proto_tree *tree, tvbuff_t *tvb, guint32 str_tbl,
4582                 guint32 str_tbl_len);
4583
4584 /* Parse data while in STAG state */
4585 static guint32
4586 parse_wbxml_tag (proto_tree *tree, tvbuff_t *tvb, guint32 offset,
4587                 guint32 str_tbl, guint8 *level, guint8 *codepage_stag, guint8 *codepage_attr);
4588
4589 /* Parse data while in STAG state;
4590  * interpret tokens as defined by content type */
4591 static guint32
4592 parse_wbxml_tag_defined (proto_tree *tree, tvbuff_t *tvb, guint32 offset,
4593                 guint32 str_tbl, guint8 *level, guint8 *codepage_stag, guint8 *codepage_attr,
4594                 const wbxml_decoding *map);
4595
4596 /* Parse data while in ATTR state */
4597 static guint32
4598 parse_wbxml_attribute_list (proto_tree *tree, tvbuff_t *tvb,
4599                 guint32 offset, guint32 str_tbl, guint8 level, guint8 *codepage_attr);
4600
4601 /* Parse data while in ATTR state;
4602  * interpret tokens as defined by content type */
4603 static guint32
4604 parse_wbxml_attribute_list_defined (proto_tree *tree, tvbuff_t *tvb,
4605                 guint32 offset, guint32 str_tbl, guint8 level, guint8 *codepage_attr,
4606                 const wbxml_decoding *map);
4607
4608
4609 /****************** WBXML protocol dissection functions ******************/
4610
4611
4612 /* Code to actually dissect the packets */
4613 static void
4614 dissect_wbxml(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
4615 {
4616         /* Set up structures needed to add the protocol subtree and manage it */
4617         proto_item *ti;
4618         proto_tree *wbxml_tree; /* Main WBXML tree */
4619         proto_tree *wbxml_str_tbl_tree; /* String table subtree */
4620         proto_tree *wbxml_content_tree; /* Content subtree */
4621         guint8 version;
4622         guint offset = 0;
4623         guint32 len;
4624         guint32 charset = 0;
4625         guint32 charset_len = 0;
4626         guint32 publicid;
4627         guint32 publicid_index = 0;
4628         guint32 publicid_len;
4629         guint32 str_tbl;
4630         guint32 str_tbl_len;
4631         guint32 str_tbl_len_len = 0;
4632         guint8 level = 0; /* WBXML recursion level */
4633         const wbxml_decoding *content_map = NULL;
4634         gchar *summary = NULL;
4635         guint8 codepage_stag = 0;
4636         guint8 codepage_attr = 0;
4637
4638         DebugLog(("dissect_wbxml: Dissecting packet %u\n", pinfo->fd->num));
4639         /* WBXML format
4640          * 
4641          * Version 1.0: version publicid         strtbl BODY
4642          * Version 1.x: version publicid charset strtbl BODY
4643          *
4644          * Last valid format: WBXML 1.3
4645          */
4646         switch ( version = tvb_get_guint8 (tvb, 0) ) {
4647                 case 0x00: /* WBXML/1.0 */
4648                         break;
4649
4650                 case 0x01: /* WBXML/1.1 */
4651                 case 0x02: /* WBXML/1.2 */
4652                 case 0x03: /* WBXML/1.3 */
4653                         break;
4654
4655                 default:
4656                         return;
4657         }
4658
4659         /* In order to properly construct the packet summary,
4660          * I need to read the entire WBXML header
4661          * up to the string table length.
4662          */
4663
4664         /* Public ID */
4665         publicid = tvb_get_guintvar(tvb, 1, &publicid_len);
4666         if (! publicid) {
4667                 /* Public identifier in string table */
4668                 publicid_index = tvb_get_guintvar (tvb, 1+publicid_len, &len);
4669                 publicid_len += len;
4670         }
4671         offset = 1 + publicid_len;
4672
4673         /* Version-specific handling of Charset */
4674         switch ( version ) {
4675                 case 0x00: /* WBXML/1.0 */
4676                         /* No charset */
4677                         break;
4678
4679                 case 0x01: /* WBXML/1.1 */
4680                 case 0x02: /* WBXML/1.2 */
4681                 case 0x03: /* WBXML/1.3 */
4682                         /* Get charset */
4683                         charset = tvb_get_guintvar (tvb, offset, &charset_len);
4684                         offset += charset_len;
4685                         break;
4686
4687                 default: /* Impossible since we returned already earlier */
4688                         g_error("%s:%u: WBXML version octet 0x%02X only partly supported!\n"
4689                                         "Please report this as a bug.\n", __FILE__, __LINE__, version);
4690                         g_assert_not_reached();
4691                         break;
4692         }
4693
4694         /* String table: read string table length in bytes */
4695         str_tbl_len = tvb_get_guintvar (tvb, offset, &str_tbl_len_len);
4696         str_tbl = offset + str_tbl_len_len; /* Start of 1st string in string table */
4697
4698         /* Compose the summary line */
4699         if ( publicid ) {
4700                 summary = g_strdup_printf("%s, Public ID: \"%s\"",
4701                                 match_strval (version, vals_wbxml_versions),
4702                                 match_strval (publicid, vals_wbxml_public_ids));
4703         } else {
4704                 /* Read length of Public ID from string table */
4705                 len = tvb_strsize (tvb, str_tbl + publicid_index);
4706                 summary = g_strdup_printf("%s, Public ID: \"%s\"",
4707                                 match_strval (version, vals_wbxml_versions),
4708                                 tvb_format_text (tvb, str_tbl + publicid_index, len - 1));
4709         }
4710
4711         /* Add summary to INFO column if it is enabled */
4712         if (check_col(pinfo->cinfo, COL_INFO))
4713                 col_append_fstr(pinfo->cinfo, COL_INFO, " (WBXML %s)", summary);
4714
4715         /* create display subtree for the protocol */
4716         ti = proto_tree_add_item (tree, proto_wbxml, tvb, 0, -1, FALSE);
4717         proto_item_append_text(ti, ", Version: %s", summary);
4718         g_free(summary);
4719         /*
4720          * Now show the protocol subtree, if tree is set.
4721          */
4722         if ( tree ) {
4723                 wbxml_tree = proto_item_add_subtree(ti, ett_wbxml);
4724
4725                 /* WBXML Version */
4726                 proto_tree_add_uint (wbxml_tree, hf_wbxml_version,
4727                                 tvb, 0, 1, version);
4728
4729                 /* Public ID */
4730                 if (publicid) { /* Known Public ID */
4731                         proto_tree_add_uint(wbxml_tree, hf_wbxml_public_id_known,
4732                                         tvb, 1, publicid_len, publicid);
4733                 } else { /* Public identifier in string table */
4734                         proto_tree_add_item (wbxml_tree, hf_wbxml_public_id_literal,
4735                                         tvb, 1, publicid_len, FALSE);
4736                 }
4737                 offset = 1 + publicid_len;
4738
4739                 if ( version ) { /* Charset */
4740                         proto_tree_add_uint (wbxml_tree, hf_wbxml_charset,
4741                                         tvb, 1 + publicid_len, charset_len, charset);
4742                         offset += charset_len;
4743                 }
4744
4745                 str_tbl_len = tvb_get_guintvar (tvb, offset, &len);
4746                 str_tbl = offset + len; /* Start of 1st string in string table */
4747
4748                 /* String Table */
4749                 ti = proto_tree_add_text(wbxml_tree,
4750                                 tvb, offset, len + str_tbl_len, "String table: %u bytes",
4751                                 str_tbl_len);
4752
4753                 if (wbxml_tree && str_tbl_len) { /* Display string table as subtree */
4754                         wbxml_str_tbl_tree = proto_item_add_subtree (ti,
4755                                         ett_wbxml_str_tbl);
4756                         show_wbxml_string_table (wbxml_str_tbl_tree, tvb,
4757                                         str_tbl, str_tbl_len);
4758                 }
4759
4760                 /* Data starts HERE */
4761                 offset += len + str_tbl_len;
4762
4763                 /* The WBXML BODY starts here */
4764                 if (disable_wbxml_token_parsing) {
4765                     ti = proto_tree_add_text (wbxml_tree, tvb, offset, -1,
4766                             "Data representation not shown "
4767                             "(edit WBXML preferences to show)");
4768                     return;
4769                 } /* Else: render the WBXML tokens */
4770                 ti = proto_tree_add_text (wbxml_tree, tvb, offset, -1,
4771                                 "Data representation");
4772                 wbxml_content_tree = proto_item_add_subtree (ti, ett_wbxml_content);
4773
4774                 /* The parse_wbxml_X() functions will process the content correctly,
4775                  * irrespective of the WBXML version used. For the WBXML body, this
4776                  * means that there is a different processing for the global token
4777                  * RESERVED_2 (WBXML 1.0) or OPAQUE (WBXML 1.x with x > 0).  */
4778                 if (wbxml_tree) { /* Show only if visible */
4779                     /* Retrieve the content token mapping if available */
4780                     content_map = get_wbxml_decoding_from_public_id (publicid);
4781                     if (! content_map) {
4782                         content_map = get_wbxml_decoding_from_content_type (pinfo->match_string, tvb, offset);
4783                         if (! content_map) {
4784                             proto_tree_add_text (wbxml_content_tree,
4785                                     tvb, offset, -1,
4786                                     "[Rendering of this content type"
4787                                     " not (yet) supported]");
4788                         } else {
4789                             proto_item_append_text(ti,
4790                                     " is based on Content-Type: %s "
4791                                     "(chosen decoding: %s)",
4792                                     pinfo->match_string, content_map->name);
4793                         }
4794                     }
4795                     if (content_map && skip_wbxml_token_mapping) {
4796                         proto_tree_add_text (wbxml_content_tree,
4797                                 tvb, offset, -1,
4798                                 "[Rendering of this content type"
4799                                 " has been disabled "
4800                                 "(edit WBXML preferences to enable)]");
4801                         content_map = NULL;
4802                     }
4803                     proto_tree_add_text (wbxml_content_tree, tvb,
4804                             offset, -1,
4805                             "Level | State | Codepage "
4806                             "| WBXML Token Description         "
4807                             "| Rendering");
4808                     if (content_map) {
4809                         len = parse_wbxml_tag_defined (wbxml_content_tree,
4810                                 tvb, offset, str_tbl, &level, &codepage_stag,
4811                                 &codepage_attr, content_map);
4812                     } else {
4813                         /* Default: WBXML only, no interpretation of the content */
4814                         len = parse_wbxml_tag (wbxml_content_tree, tvb, offset,
4815                                 str_tbl, &level, &codepage_stag, &codepage_attr);
4816                     }
4817                 }
4818                 return;
4819         }
4820 }
4821
4822
4823 /* Parse and display the WBXML string table (in a 3-column table format).
4824  * This function displays:
4825  *  - the offset in the string table,
4826  *  - the length of the string
4827  *  - the string.
4828  */
4829 static void
4830 show_wbxml_string_table (proto_tree *tree, tvbuff_t *tvb, guint32 str_tbl,
4831                 guint32 str_tbl_len)
4832 {
4833         guint32 off = str_tbl;
4834         guint32 len = 0;
4835         guint32 end = str_tbl + str_tbl_len;
4836
4837         proto_tree_add_text (tree, tvb, off, end,
4838                         "Start  | Length | String");
4839         while (off < end) {
4840                 len = tvb_strsize (tvb, off);
4841                 proto_tree_add_text (tree, tvb, off, len,
4842                                 "%6d | %6d | '%s'",
4843                                 off - str_tbl, len,
4844                                 tvb_format_text (tvb, off, len-1));
4845                 off += len;
4846         }
4847 }
4848
4849
4850 /* Indentation code is based on a static const array of space characters.
4851  * At least one single space is returned */
4852 static const char indent_buffer[514] = " "
4853         "                                                                "
4854         "                                                                "
4855         "                                                                "
4856         "                                                                "
4857         "                                                                "
4858         "                                                                "
4859         "                                                                "
4860         "                                                                "
4861         ; /* Generate XML indentation (length = 1 + 2 * 256 + 1 for '\0') */
4862
4863 static const char * Indent (guint8 level) {
4864         return indent_buffer + (512 - 2 * (level));
4865 }
4866
4867
4868 /********************
4869  * WBXML tag tokens *
4870  ********************
4871  * 
4872  * Bit Mask  : Example
4873  * -------------------
4874  * 00.. .... : <tag />
4875  *
4876  * 01.. .... : <tag>
4877  *               CONTENT
4878  *             </tag>
4879  *
4880  * 10.. .... : <tag
4881  *               atrtribute1="value1"
4882  *               atrtribute2="value2"
4883  *             />
4884  * 
4885  * 11.. .... : <tag
4886  *               atrtribute1="value1"
4887  *               atrtribute2="value2"
4888  *             >
4889  *               CONTENT
4890  *             </tag>
4891  *
4892  * NOTES
4893  *   - An XML PI is parsed as an attribute list (same syntax).
4894  *   - A code page switch only applies to the single token that follows.
4895  */
4896
4897
4898 /* This function parses the WBXML and maps known token interpretations
4899  * to the WBXML tokens. As a result, the original XML document can be
4900  * recreated. Indentation is generated in order to ease reading.
4901  *
4902  * Attribute parsing is done in parse_wbxml_attribute_list_defined().
4903  *
4904  * The wbxml_decoding entry *map contains the actual token mapping.
4905  *
4906  * NOTE: In order to parse the content, some recursion is required.
4907  *       However, for performance reasons, recursion has been avoided
4908  *       where possible (tags without content within tags with content).
4909  *       This is achieved by means of the parsing_tag_content and tag_save*
4910  *       variables.
4911  *
4912  * NOTE: See above for known token mappings.
4913  *
4914  * NOTE: As tags can be opened and closed, a tag representation lookup
4915  *       may happen once or twice for a given tag. For efficiency reasons,
4916  *       the literal tag value is stored and used throughout the code.
4917  *       With the introduction of code page support, this solution is robust
4918  *       as the lookup only occurs once, removing the need for storage of
4919  *       the used code page.
4920  */
4921 static guint32
4922 parse_wbxml_tag_defined (proto_tree *tree, tvbuff_t *tvb, guint32 offset,
4923                 guint32 str_tbl, guint8 *level, guint8 *codepage_stag, guint8 *codepage_attr,
4924                 const wbxml_decoding *map)
4925 {
4926         guint32 tvb_len = tvb_reported_length (tvb);
4927         guint32 off = offset;
4928         guint32 len;
4929         guint str_len;
4930         guint32 ent;
4931         guint32 index;
4932         guint8 peek;
4933         guint32 tag_len; /* Length of the index (uintvar) from a LITERAL tag */
4934         guint8 tag_save_known = 0; /* Will contain peek & 0x3F (tag identity) */
4935         guint8 tag_new_known = 0; /* Will contain peek & 0x3F (tag identity) */
4936         const char *tag_save_literal; /* Will contain the LITERAL tag identity */
4937         const char *tag_new_literal; /* Will contain the LITERAL tag identity */
4938         guint8 parsing_tag_content = FALSE; /* Are we parsing content from a
4939                                                                                    tag with content: <x>Content</x>
4940                                                                                    
4941                                                                                    The initial state is FALSE.
4942                                                                                    This state will trigger recursion. */
4943         tag_save_literal = NULL; /* Prevents compiler warning */
4944
4945         DebugLog(("parse_wbxml_tag_defined (level = %u, offset = %u)\n", *level, offset));
4946         while (off < tvb_len) {
4947                 peek = tvb_get_guint8 (tvb, off);
4948                 DebugLog(("STAG: (top of while) level = %3u, peek = 0x%02X, off = %u, tvb_len = %u\n", *level, peek, off, tvb_len));
4949                 if ((peek & 0x3F) < 4) switch (peek) { /* Global tokens in state = STAG
4950                                                                                                   but not the LITERAL tokens */
4951                         case 0x00: /* SWITCH_PAGE */
4952                                 *codepage_stag = tvb_get_guint8 (tvb, off+1);
4953                                 proto_tree_add_text (tree, tvb, off, 2,
4954                                                 "      | Tag   | T -->%3d "
4955                                                 "| SWITCH_PAGE (Tag code page)     "
4956                                                 "|",
4957                                                 *codepage_stag);
4958                                 off += 2;
4959                                 break;
4960                         case 0x01: /* END: only possible for Tag with Content */
4961                                 if (tag_save_known) { /* Known TAG */
4962                                         proto_tree_add_text (tree, tvb, off, 1,
4963                                                         "  %3d | Tag   | T %3d    "
4964                                                         "| END (Known Tag 0x%02X)            "
4965                                                         "| %s</%s>",
4966                                                         *level, *codepage_stag,
4967                                                         tag_save_known, Indent (*level),
4968                                                         tag_save_literal); /* We already looked it up! */
4969                                 } else { /* Literal TAG */
4970                                         proto_tree_add_text (tree, tvb, off, 1,
4971                                                         "  %3d | Tag   | T %3d    "
4972                                                         "| END (Literal Tag)               "
4973                                                         "| %s</%s>",
4974                                                         *level, *codepage_stag, Indent (*level),
4975                                                         tag_save_literal);
4976                                 }
4977                                 (*level)--;
4978                                 off++;
4979                                 /* Reset code page: not needed as return from recursion */
4980                                 DebugLog(("STAG: level = %u, Return: len = %u\n", *level, off - offset));
4981                                 return (off - offset);
4982                                 break;
4983                         case 0x02: /* ENTITY */
4984                                 ent = tvb_get_guintvar (tvb, off+1, &len);
4985                                 proto_tree_add_text (tree, tvb, off, 1+len,
4986                                                 "  %3d | Tag   | T %3d    "
4987                                                 "| ENTITY                          "
4988                                                 "| %s'&#%u;'",
4989                                                 *level, *codepage_stag, Indent (*level), ent);
4990                                 off += 1+len;
4991                                 break;
4992                         case 0x03: /* STR_I */
4993                                 len = tvb_strsize (tvb, off+1);
4994                                 proto_tree_add_text (tree, tvb, off, 1+len,
4995                                                 "  %3d | Tag   | T %3d    "
4996                                                 "| STR_I (Inline string)           "
4997                                                 "| %s\'%s\'",
4998                                                 *level, *codepage_stag, Indent(*level),
4999                                                 tvb_format_text (tvb, off+1, len-1));
5000                                 off += 1+len;
5001                                 break;
5002                         case 0x40: /* EXT_I_0 */
5003                         case 0x41: /* EXT_I_1 */
5004                         case 0x42: /* EXT_I_2 */
5005                                 /* Extension tokens */
5006                                 len = tvb_strsize (tvb, off+1);
5007                                 proto_tree_add_text (tree, tvb, off, 1+len,
5008                                                 "  %3d | Tag   | T %3d    "
5009                                                 "| EXT_I_%1x    (Extension Token)    "
5010                                                 "| %s(%s: \'%s\')",
5011                                                 *level, *codepage_stag,
5012                                                 peek & 0x0f, Indent (*level),
5013                                                 map_token (map->global, 0, peek),
5014                                                 tvb_format_text (tvb, off+1, len-1));
5015                                 off += 1+len;
5016                                 break;
5017                         case 0x43: /* PI */
5018                                 proto_tree_add_text (tree, tvb, off, 1,
5019                                                 "  %3d | Tag   | T %3d    "
5020                                                 "| PI (XML Processing Instruction) "
5021                                                 "| %s<?xml",
5022                                                 *level, *codepage_stag, Indent (*level));
5023                                 len = parse_wbxml_attribute_list_defined (tree, tvb, off,
5024                                                 str_tbl, *level, codepage_attr, map);
5025                                 /* Check that there is still room in packet */
5026                                 off += len;
5027                                 if (off >= tvb_len) {
5028                                         DebugLog(("STAG: level = %u, ThrowException: len = %u (short frame)\n", *level, off - offset));
5029                                         /*
5030                                          * TODO - Do we need to free g_malloc()ed memory?
5031                                          */
5032                                         THROW(ReportedBoundsError);
5033                                 }
5034                                 proto_tree_add_text (tree, tvb, off-1, 1,
5035                                                 "  %3d | Tag   | T %3d    "
5036                                                 "| END (PI)                        "
5037                                                 "| %s?>",
5038                                                 *level, *codepage_stag, Indent (*level));
5039                                 break;
5040                         case 0x80: /* EXT_T_0 */
5041                         case 0x81: /* EXT_T_1 */
5042                         case 0x82: /* EXT_T_2 */
5043                                 /* Extension tokens */
5044                                 index = tvb_get_guintvar (tvb, off+1, &len);
5045                                 {   char *s;
5046                                     if (map->ext_t[peek & 0x03])
5047                                         s = (map->ext_t[peek & 0x03])(tvb, index, str_tbl);
5048                                     else
5049                                         s = g_strdup_printf("EXT_T_%1x (%s)", peek & 0x03, 
5050                                                 map_token (map->global, 0, peek));
5051                                     proto_tree_add_text (tree, tvb, off, 1+len,
5052                                                 "  %3d | Tag   | T %3d    "
5053                                                 "| EXT_T_%1x    (Extension Token)    "
5054                                                 "| %s%s",
5055                                                 *level, *codepage_stag, peek & 0x0f, Indent (*level),
5056                                                 s);
5057                                     g_free(s);
5058                                 }
5059                                 off += 1+len;
5060                                 break;
5061                         case 0x83: /* STR_T */
5062                                 index = tvb_get_guintvar (tvb, off+1, &len);
5063                                 str_len = tvb_strsize (tvb, str_tbl+index);
5064                                 proto_tree_add_text (tree, tvb, off, 1+len,
5065                                                 "  %3d | Tag   | T %3d    "
5066                                                 "| STR_T (Tableref string)         "
5067                                                 "| %s\'%s\'",
5068                                                 *level, *codepage_stag, Indent (*level),
5069                                                 tvb_format_text (tvb, str_tbl+index, str_len-1));
5070                                 off += 1+len;
5071                                 break;
5072                         case 0xC0: /* EXT_0 */
5073                         case 0xC1: /* EXT_1 */
5074                         case 0xC2: /* EXT_2 */
5075                                 /* Extension tokens */
5076                                 proto_tree_add_text (tree, tvb, off, 1,
5077                                                 "  %3d | Tag   | T %3d    "
5078                                                 "| EXT_%1x      (Extension Token)    "
5079                                                 "| %s(%s)",
5080                                                 *level, *codepage_stag, peek & 0x0f, Indent (*level),
5081                                                 map_token (map->global, 0, peek));
5082                                 off++;
5083                                 break;
5084                         case 0xC3: /* OPAQUE - WBXML 1.1 and newer */
5085                                 if (tvb_get_guint8 (tvb, 0)) { /* WBXML 1.x (x > 0) */
5086                                         char *str;
5087                                         if (tag_save_known) { /* Knwon tag */
5088                                                 if (map->opaque_binary_tag) {
5089                                                         str = map->opaque_binary_tag(tvb, off + 1,
5090                                                                         tag_save_known, *codepage_stag, &len);
5091                                                 } else {
5092                                                         str = default_opaque_binary_tag(tvb, off + 1,
5093                                                                         tag_save_known, *codepage_stag, &len);
5094                                                 }
5095                                         } else { /* lITERAL tag */
5096                                                 if (map->opaque_literal_tag) {
5097                                                         str = map->opaque_literal_tag(tvb, off + 1,
5098                                                                         tag_save_literal, *codepage_stag, &len);
5099                                                 } else {
5100                                                         str = default_opaque_literal_tag(tvb, off + 1,
5101                                                                         tag_save_literal, *codepage_stag, &len);
5102                                                 }
5103                                         }
5104                                         proto_tree_add_text (tree, tvb, off, 1 + len,
5105                                                         "  %3d | Tag   | T %3d    "
5106                                                         "| OPAQUE (Opaque data)            "
5107                                                         "| %s%s",
5108                                                         *level, *codepage_stag, Indent (*level), str);
5109                                         g_free(str);
5110                                         off += 1 + len;
5111                                 } else { /* WBXML 1.0 - RESERVED_2 token (invalid) */
5112                                         proto_tree_add_text (tree, tvb, off, 1,
5113                                                         "  %3d | Tag   | T %3d    "
5114                                                         "| RESERVED_2     (Invalid Token!) "
5115                                                         "| WBXML 1.0 parsing stops here.",
5116                                                         *level, *codepage_stag);
5117                                         /* Stop processing as it is impossible to parse now */
5118                                         off = tvb_len;
5119                                         DebugLog(("STAG: level = %u, Return: len = %u\n", *level, off - offset));
5120                                         return (off - offset);
5121                                 }
5122                                 break;
5123
5124                                 /* No default clause, as all cases have been treated */
5125                 } else { /* LITERAL or Known TAG */
5126                         /* We must store the initial tag, and also retrieve the new tag.
5127                          * For efficiency reasons, we store the literal tag representation
5128                          * for known tags too, so we can easily close the tag without the
5129                          * need of a new lookup and avoiding storage of token codepage.
5130                          * 
5131                          * There are 4 possibilities:
5132                          *
5133                          *  1. Known tag followed by a known tag
5134                          *  2. Known tag followed by a LITERAL tag
5135                          *  3. LITERAL tag followed by Known tag
5136                          *  4. LITERAL tag followed by LITERAL tag
5137                          */
5138
5139                         /* Store the new tag */
5140                         tag_len = 0;
5141                         if ((peek & 0x3F) == 4) { /* LITERAL */
5142                                 DebugLog(("STAG: LITERAL tag (peek = 0x%02X, off = %u) - TableRef follows!\n", peek, off));
5143                                 index = tvb_get_guintvar (tvb, off+1, &tag_len);
5144                                 str_len = tvb_strsize (tvb, str_tbl+index);
5145                                 tag_new_literal = tvb_get_ptr (tvb, str_tbl+index, str_len);
5146                                 tag_new_known = 0; /* invalidate known tag_new */
5147                         } else { /* Known tag */
5148                                 tag_new_known = peek & 0x3F;
5149                                 tag_new_literal = map_token (map->tags, *codepage_stag,
5150                                                                                 tag_new_known);
5151                                 /* Stored looked up tag name string */
5152                         }
5153
5154                         /* Parsing of TAG starts HERE */
5155                         if (peek & 0x40) { /* Content present */
5156                                 /* Content follows
5157                                  * [!] An explicit END token is expected in these cases!
5158                                  * ==> Recursion possible if we encounter a tag with content;
5159                                  *     recursion will return at the explicit END token.
5160                                  */
5161                                 if (parsing_tag_content) { /* Recurse */
5162                                         DebugLog(("STAG: Tag in Tag - RECURSE! (off = %u)\n", off));
5163                                         /* Do not process the attribute list:
5164                                          * recursion will take care of it */
5165                                         (*level)++;
5166                                         len = parse_wbxml_tag_defined (tree, tvb, off, str_tbl,
5167                                                         level, codepage_stag, codepage_attr, map);
5168                                         off += len;
5169                                 } else { /* Now we will have content to parse */
5170                                         /* Save the start tag so we can properly close it later. */
5171                                         if ((peek & 0x3F) == 4) { /* Literal tag */
5172                                                 tag_save_literal = tag_new_literal;
5173                                                 tag_save_known = 0;
5174                                         } else { /* Known tag */
5175                                                 tag_save_known = tag_new_known;
5176                                                 tag_save_literal = tag_new_literal;
5177                                                 /* The last statement avoids needless lookups */
5178                                         }
5179                                         /* Process the attribute list if present */
5180                                         if (peek & 0x80) { /* Content and Attribute list present */
5181                                                 if (tag_new_known) { /* Known tag */
5182                                                         proto_tree_add_text (tree, tvb, off, 1,
5183                                                                         "  %3d | Tag   | T %3d    "
5184                                                                         "|   Known Tag 0x%02X           (AC) "
5185                                                                         "| %s<%s",
5186                                                                         *level, *codepage_stag, tag_new_known,
5187                                                                         Indent (*level), tag_new_literal);
5188                                                         /* Tag string already looked up earlier! */
5189                                                         off++;
5190                                                 } else { /* LITERAL tag */
5191                                                         proto_tree_add_text (tree, tvb, off, 1,
5192                                                                         "  %3d | Tag   | T %3d    "
5193                                                                         "| LITERAL_AC (Literal tag)   (AC) "
5194                                                                         "| %s<%s",
5195                                                                         *level, *codepage_stag, Indent (*level), tag_new_literal);
5196                                                         off += 1 + tag_len;
5197                                                 }
5198                                                 len = parse_wbxml_attribute_list_defined (tree, tvb,
5199                                                                 off, str_tbl, *level, codepage_attr, map);
5200                                                 /* Check that there is still room in packet */
5201                                                 off += len;
5202                                                 if (off >= tvb_len) {
5203                                                         DebugLog(("STAG: level = %u, ThrowException: len = %u (short frame)\n",
5204                                                                                 *level, off - offset));
5205                                                         /*
5206                                                          * TODO - Do we need to free g_malloc()ed memory?
5207                                                          */
5208                                                         THROW(ReportedBoundsError);
5209                                                 }
5210                                                 proto_tree_add_text (tree, tvb, off-1, 1,
5211                                                                 "  %3d | Tag   | T %3d    "
5212                                                                 "| END (attribute list)            "
5213                                                                 "| %s>",
5214                                                                 *level, *codepage_stag, Indent (*level));
5215                                         } else { /* Content, no Attribute list */
5216                                                 if (tag_new_known) { /* Known tag */
5217                                                         proto_tree_add_text (tree, tvb, off, 1,
5218                                                                         "  %3d | Tag   | T %3d    "
5219                                                                         "|   Known Tag 0x%02X           (.C) "
5220                                                                         "| %s<%s>",
5221                                                                         *level, *codepage_stag, tag_new_known,
5222                                                                         Indent (*level), tag_new_literal);
5223                                                         /* Tag string already looked up earlier! */
5224                                                         off++;
5225                                                 } else { /* LITERAL tag */
5226                                                         proto_tree_add_text (tree, tvb, off, 1,
5227                                                                         "  %3d | Tag   | T %3d    "
5228                                                                         "| LITERAL_C  (Literal Tag)   (.C) "
5229                                                                         "| %s<%s>",
5230                                                                         *level, *codepage_stag, Indent (*level),
5231                                                                         tag_new_literal);
5232                                                         off += 1 + tag_len;
5233                                                 }
5234                                         }
5235                                         /* The data that follows in the parsing process
5236                                          * represents content for the opening tag
5237                                          * we've just processed in the lines above.
5238                                          * Next time we encounter a tag with content: recurse
5239                                          */
5240                                         parsing_tag_content = TRUE;
5241                                         DebugLog(("Tag in Tag - No recursion this time! (off = %u)\n", off));
5242                                 }
5243                         } else { /* No Content */
5244                                 DebugLog(("<Tag/> in Tag - No recursion! (off = %u)\n", off));
5245                                 (*level)++;
5246                                 if (peek & 0x80) { /* No Content, Attribute list present */
5247                                         if (tag_new_known) { /* Known tag */
5248                                                 proto_tree_add_text (tree, tvb, off, 1,
5249                                                                 "  %3d | Tag   | T %3d    "
5250                                                                 "|   Known Tag 0x%02X           (A.) "
5251                                                                 "| %s<%s",
5252                                                                 *level, *codepage_stag, tag_new_known,
5253                                                                 Indent (*level), tag_new_literal);
5254                                                 /* Tag string already looked up earlier! */
5255                                                 off++;
5256                                                 len = parse_wbxml_attribute_list_defined (tree, tvb,
5257                                                                 off, str_tbl, *level, codepage_attr, map);
5258                                                 /* Check that there is still room in packet */
5259                                                 off += len;
5260                                                 if (off >= tvb_len) {
5261                                                         DebugLog(("STAG: level = %u, ThrowException: len = %u (short frame)\n", *level, off - offset));
5262                                                         /*
5263                                                          * TODO - Do we need to free g_malloc()ed memory?
5264                                                          */
5265                                                         THROW(ReportedBoundsError);
5266                                                 }
5267                                                 proto_tree_add_text (tree, tvb, off-1, 1,
5268                                                                 "  %3d | Tag   | T %3d    "
5269                                                                 "| END (Known Tag)                 "
5270                                                                 "| %s/>",
5271                                                                 *level, *codepage_stag, Indent (*level));
5272                                         } else { /* LITERAL tag */
5273                                                 proto_tree_add_text (tree, tvb, off, 1,
5274                                                                 "  %3d | Tag   | T %3d    "
5275                                                                 "| LITERAL_A  (Literal Tag)   (A.) "
5276                                                                 "| %s<%s",
5277                                                                 *level, *codepage_stag, Indent (*level), tag_new_literal);
5278                                                 off += 1 + tag_len;
5279                                                 len = parse_wbxml_attribute_list_defined (tree, tvb,
5280                                                                 off, str_tbl, *level, codepage_attr, map);
5281                                                 /* Check that there is still room in packet */
5282                                                 off += len;
5283                                                 if (off >= tvb_len) {
5284                                                         DebugLog(("STAG: level = %u, ThrowException: len = %u (short frame)\n", *level, off - offset));
5285                                                         /*
5286                                                          * TODO - Do we need to free g_malloc()ed memory?
5287                                                          */
5288                                                         THROW(ReportedBoundsError);
5289                                                 }
5290                                                 proto_tree_add_text (tree, tvb, off-1, 1,
5291                                                                 "  %3d | Tag   | T %3d    "
5292                                                                 "| END (Literal Tag)               "
5293                                                                 "| %s/>",
5294                                                                 *level, *codepage_stag, Indent (*level));
5295                                         }
5296                                 } else { /* No Content, No Attribute list */
5297                                         if (tag_new_known) { /* Known tag */
5298                                                 proto_tree_add_text (tree, tvb, off, 1,
5299                                                                 "  %3d | Tag   | T %3d    "
5300                                                                 "|   Known Tag 0x%02x           (..) "
5301                                                                 "| %s<%s />",
5302                                                                 *level, *codepage_stag, tag_new_known,
5303                                                                 Indent (*level), tag_new_literal);
5304                                                 /* Tag string already looked up earlier! */
5305                                                 off++;
5306                                         } else { /* LITERAL tag */
5307                                                 proto_tree_add_text (tree, tvb, off, 1,
5308                                                                 "  %3d | Tag   | T %3d    "
5309                                                                 "| LITERAL    (Literal Tag)   (..) "
5310                                                                 "| %s<%s />",
5311                                                                 *level, *codepage_stag, Indent (*level),
5312                                                                 tag_new_literal);
5313                                                 off += 1 + tag_len;
5314                                         }
5315                                 }
5316                                 (*level)--;
5317                                 /* TODO: Do I have to reset code page here? */
5318                         }
5319                 } /* if (tag & 0x3F) >= 5 */
5320         } /* while */
5321         DebugLog(("STAG: level = %u, Return: len = %u (end of function body)\n", *level, off - offset));
5322         return (off - offset);
5323 }
5324
5325
5326 /* This function performs the WBXML decoding as in parse_wbxml_tag_defined()
5327  * but this time no WBXML mapping is performed.
5328  *
5329  * Attribute parsing is done in parse_wbxml_attribute_list().
5330  */
5331 static guint32
5332 parse_wbxml_tag (proto_tree *tree, tvbuff_t *tvb, guint32 offset,
5333                 guint32 str_tbl, guint8 *level,
5334                 guint8 *codepage_stag, guint8 *codepage_attr)
5335 {
5336         guint32 tvb_len = tvb_reported_length (tvb);
5337         guint32 off = offset;
5338         guint32 len;
5339         guint str_len;
5340         guint32 ent;
5341         guint32 index;
5342         guint8 peek;
5343         guint32 tag_len; /* Length of the index (uintvar) from a LITERAL tag */
5344         guint8 tag_save_known = 0; /* Will contain peek & 0x3F (tag identity) */
5345         guint8 tag_new_known = 0; /* Will contain peek & 0x3F (tag identity) */
5346         const char *tag_save_literal; /* Will contain the LITERAL tag identity */
5347         const char *tag_new_literal; /* Will contain the LITERAL tag identity */
5348         char tag_save_buf[10]; /* Will contain "tag_0x%02X" */
5349         char tag_new_buf[10]; /* Will contain "tag_0x%02X" */
5350         guint8 parsing_tag_content = FALSE; /* Are we parsing content from a
5351                                                                                    tag with content: <x>Content</x>
5352                                                                                    
5353                                                                                    The initial state is FALSE.
5354                                                                                    This state will trigger recursion. */
5355         tag_save_literal = NULL; /* Prevents compiler warning */
5356
5357         DebugLog(("parse_wbxml_tag (level = %u, offset = %u)\n", *level, offset));
5358         while (off < tvb_len) {
5359                 peek = tvb_get_guint8 (tvb, off);
5360                 DebugLog(("STAG: (top of while) level = %3u, peek = 0x%02X, off = %u, tvb_len = %u\n", *level, peek, off, tvb_len));
5361                 if ((peek & 0x3F) < 4) switch (peek) { /* Global tokens in state = STAG
5362                                                                                                   but not the LITERAL tokens */
5363                         case 0x00: /* SWITCH_PAGE */
5364                                 *codepage_stag = tvb_get_guint8 (tvb, off+1);
5365                                 proto_tree_add_text (tree, tvb, off, 2,
5366                                                 "      | Tag   | T -->%3d "
5367                                                 "| SWITCH_PAGE (Tag code page)     "
5368                                                 "|",
5369                                                 *codepage_stag);
5370                                 off += 2;
5371                                 break;
5372                         case 0x01: /* END: only possible for Tag with Content */
5373                                 if (tag_save_known) { /* Known TAG */
5374                                         proto_tree_add_text (tree, tvb, off, 1,
5375                                                         "  %3d | Tag   | T %3d    "
5376                                                         "| END (Known Tag 0x%02X)            "
5377                                                         "| %s</%s>",
5378                                                         *level, *codepage_stag, tag_save_known,
5379                                                         Indent (*level),
5380                                                         tag_save_literal); /* We already looked it up! */
5381                                 } else { /* Literal TAG */
5382                                         proto_tree_add_text (tree, tvb, off, 1,
5383                                                         "  %3d | Tag   | T %3d    "
5384                                                         "| END (Literal Tag)               "
5385                                                         "| %s</%s>",
5386                                                         *level, *codepage_stag, Indent (*level),
5387                                                         tag_save_literal);
5388                                 }
5389                                 (*level)--;
5390                                 off++;
5391                                 /* Reset code page: not needed as return from recursion */
5392                                 DebugLog(("STAG: level = %u, Return: len = %u\n",
5393                                                         *level, off - offset));
5394                                 return (off - offset);
5395                                 break;
5396                         case 0x02: /* ENTITY */
5397                                 ent = tvb_get_guintvar (tvb, off+1, &len);
5398                                 proto_tree_add_text (tree, tvb, off, 1+len,
5399                                                 "  %3d | Tag   | T %3d    "
5400                                                 "| ENTITY                          "
5401                                                 "| %s'&#%u;'",
5402                                                 *level, *codepage_stag, Indent (*level), ent);
5403                                 off += 1+len;
5404                                 break;
5405                         case 0x03: /* STR_I */
5406                                 len = tvb_strsize (tvb, off+1);
5407                                 proto_tree_add_text (tree, tvb, off, 1+len,
5408                                                 "  %3d | Tag   | T %3d    "
5409                                                 "| STR_I (Inline string)           "
5410                                                 "| %s\'%s\'",
5411                                                 *level, *codepage_stag, Indent(*level),
5412                                                 tvb_format_text (tvb, off+1, len-1));
5413                                 off += 1+len;
5414                                 break;
5415                         case 0x40: /* EXT_I_0 */
5416                         case 0x41: /* EXT_I_1 */
5417                         case 0x42: /* EXT_I_2 */
5418                                 /* Extension tokens */
5419                                 len = tvb_strsize (tvb, off+1);
5420                                 proto_tree_add_text (tree, tvb, off, 1+len,
5421                                                 "  %3d | Tag   | T %3d    "
5422                                                 "| EXT_I_%1x    (Extension Token)    "
5423                                                 "| %s(Inline string extension: \'%s\')",
5424                                                 *level, *codepage_stag, peek & 0x0f, Indent (*level),
5425                                                 tvb_format_text (tvb, off+1, len-1));
5426                                 off += 1+len;
5427                                 break;
5428                         case 0x43: /* PI */
5429                                 proto_tree_add_text (tree, tvb, off, 1,
5430                                                 "  %3d | Tag   | T %3d    "
5431                                                 "| PI (XML Processing Instruction) "
5432                                                 "| %s<?xml",
5433                                                 *level, *codepage_stag, Indent (*level));
5434                                 len = parse_wbxml_attribute_list (tree, tvb, off, str_tbl,
5435                                                 *level, codepage_attr);
5436                                 /* Check that there is still room in packet */
5437                                 off += len;
5438                                 if (off >= tvb_len) {
5439                                         DebugLog(("STAG: level = %u, ThrowException: len = %u (short frame)\n",
5440                                                                 *level, off - offset));
5441                                         /*
5442                                          * TODO - Do we need to free g_malloc()ed memory?
5443                                          */
5444                                         THROW(ReportedBoundsError);
5445                                 }
5446                                 proto_tree_add_text (tree, tvb, off-1, 1,
5447                                                 "  %3d | Tag   | T %3d    "
5448                                                 "| END (PI)                        "
5449                                                 "| %s?>",
5450                                                 *level, *codepage_stag, Indent (*level));
5451                                 break;
5452                         case 0x80: /* EXT_T_0 */
5453                         case 0x81: /* EXT_T_1 */
5454                         case 0x82: /* EXT_T_2 */
5455                                 /* Extension tokens */
5456                                 index = tvb_get_guintvar (tvb, off+1, &len);
5457                                 proto_tree_add_text (tree, tvb, off, 1+len,
5458                                                 "  %3d | Tag   | T %3d    "
5459                                                 "| EXT_T_%1x    (Extension Token)    "
5460                                                 "| %s(Extension Token, integer value: %u)",
5461                                                 *level, *codepage_stag, peek & 0x0f, Indent (*level),
5462                                                 index);
5463                                 off += 1+len;
5464                                 break;
5465                         case 0x83: /* STR_T */
5466                                 index = tvb_get_guintvar (tvb, off+1, &len);
5467                                 str_len = tvb_strsize (tvb, str_tbl+index);
5468                                 proto_tree_add_text (tree, tvb, off, 1+len,
5469                                                 "  %3d | Tag   | T %3d    "
5470                                                 "| STR_T (Tableref string)         "
5471                                                 "| %s\'%s\'",
5472                                                 *level, *codepage_stag, Indent (*level),
5473                                                 tvb_format_text (tvb, str_tbl+index, str_len-1));
5474                                 off += 1+len;
5475                                 break;
5476                         case 0xC0: /* EXT_0 */
5477                         case 0xC1: /* EXT_1 */
5478                         case 0xC2: /* EXT_2 */
5479                                 /* Extension tokens */
5480                                 proto_tree_add_text (tree, tvb, off, 1,
5481                                                 "  %3d | Tag   | T %3d    "
5482                                                 "| EXT_%1x      (Extension Token)    "
5483                                                 "| %s(Single-byte extension)",
5484                                                 *level, *codepage_stag, peek & 0x0f, Indent (*level));
5485                                 off++;
5486                                 break;
5487                         case 0xC3: /* OPAQUE - WBXML 1.1 and newer */
5488                                 if (tvb_get_guint8 (tvb, 0)) { /* WBXML 1.x (x > 0) */
5489                                         index = tvb_get_guintvar (tvb, off+1, &len);
5490                                         proto_tree_add_text (tree, tvb, off, 1 + len + index,
5491                                                         "  %3d | Tag   | T %3d    "
5492                                                         "| OPAQUE (Opaque data)            "
5493                                                         "| %s(%d bytes of opaque data)",
5494                                                         *level, *codepage_stag, Indent (*level), index);
5495                                         off += 1+len+index;
5496                                 } else { /* WBXML 1.0 - RESERVED_2 token (invalid) */
5497                                         proto_tree_add_text (tree, tvb, off, 1,
5498                                                         "  %3d | Tag   | T %3d    "
5499                                                         "| RESERVED_2     (Invalid Token!) "
5500                                                         "| WBXML 1.0 parsing stops here.",
5501                                                         *level, *codepage_stag);
5502                                         /* Stop processing as it is impossible to parse now */
5503                                         off = tvb_len;
5504                                         DebugLog(("STAG: level = %u, Return: len = %u\n",
5505                                                                 *level, off - offset));
5506                                         return (off - offset);
5507                                 }
5508                                 break;
5509
5510                                 /* No default clause, as all cases have been treated */
5511                 } else { /* LITERAL or Known TAG */
5512                         /* We must store the initial tag, and also retrieve the new tag.
5513                          * For efficiency reasons, we store the literal tag representation
5514                          * for known tags too, so we can easily close the tag without the
5515                          * need of a new lookup and avoiding storage of token codepage.
5516                          * 
5517                          * There are 4 possibilities:
5518                          *
5519                          *  1. Known tag followed by a known tag
5520                          *  2. Known tag followed by a LITERAL tag
5521                          *  3. LITERAL tag followed by Known tag
5522                          *  4. LITERAL tag followed by LITERAL tag
5523                          */
5524
5525                         /* Store the new tag */
5526                         tag_len = 0;
5527                         if ((peek & 0x3F) == 4) { /* LITERAL */
5528                                 DebugLog(("STAG: LITERAL tag (peek = 0x%02X, off = %u)"
5529                                                         " - TableRef follows!\n", peek, off));
5530                                 index = tvb_get_guintvar (tvb, off+1, &tag_len);
5531                                 str_len = tvb_strsize (tvb, str_tbl+index);
5532                                 tag_new_literal = tvb_get_ptr (tvb, str_tbl+index, str_len);
5533                                 tag_new_known = 0; /* invalidate known tag_new */
5534                         } else { /* Known tag */
5535                                 tag_new_known = peek & 0x3F;
5536                                 sprintf (tag_new_buf, "Tag_0x%02X",
5537                                                 tag_new_known);
5538                                 tag_new_literal = tag_new_buf;
5539                                 /* Stored looked up tag name string */
5540                         }
5541
5542                         /* Parsing of TAG starts HERE */
5543                         if (peek & 0x40) { /* Content present */
5544                                 /* Content follows
5545                                  * [!] An explicit END token is expected in these cases!
5546                                  * ==> Recursion possible if we encounter a tag with content;
5547                                  *     recursion will return at the explicit END token.
5548                                  */
5549                                 if (parsing_tag_content) { /* Recurse */
5550                                         DebugLog(("STAG: Tag in Tag - RECURSE! (off = %u)\n", off));
5551                                         /* Do not process the attribute list:
5552                                          * recursion will take care of it */
5553                                         (*level)++;
5554                                         len = parse_wbxml_tag (tree, tvb, off, str_tbl, level,
5555                                                         codepage_stag, codepage_attr);
5556                                         off += len;
5557                                 } else { /* Now we will have content to parse */
5558                                         /* Save the start tag so we can properly close it later. */
5559                                         if ((peek & 0x3F) == 4) { /* Literal tag */
5560                                                 tag_save_literal = tag_new_literal;
5561                                                 tag_save_known = 0;
5562                                         } else { /* Known tag */
5563                                                 tag_save_known = tag_new_known;
5564                                                 sprintf (tag_save_buf, "Tag_0x%02X",
5565                                                                 tag_new_known);
5566                                                 tag_save_literal = tag_save_buf;
5567                                                 /* The last statement avoids needless lookups */
5568                                         }
5569                                         /* Process the attribute list if present */
5570                                         if (peek & 0x80) { /* Content and Attribute list present */
5571                                                 if (tag_new_known) { /* Known tag */
5572                                                         proto_tree_add_text (tree, tvb, off, 1,
5573                                                                         "  %3d | Tag   | T %3d    "
5574                                                                         "|   Known Tag 0x%02X           (AC) "
5575                                                                         "| %s<%s",
5576                                                                         *level, *codepage_stag, tag_new_known,
5577                                                                         Indent (*level), tag_new_literal);
5578                                                         /* Tag string already looked up earlier! */
5579                                                         off++;
5580                                                 } else { /* LITERAL tag */
5581                                                         proto_tree_add_text (tree, tvb, off, 1,
5582                                                                         "  %3d | Tag   | T %3d    "
5583                                                                         "| LITERAL_AC (Literal tag)   (AC) "
5584                                                                         "| %s<%s",
5585                                                                         *level, *codepage_stag, Indent (*level),
5586                                                                         tag_new_literal);
5587                                                         off += 1 + tag_len;
5588                                                 }
5589                                                 len = parse_wbxml_attribute_list (tree, tvb,
5590                                                                 off, str_tbl, *level, codepage_attr);
5591                                                 /* Check that there is still room in packet */
5592                                                 off += len;
5593                                                 if (off >= tvb_len) {
5594                                                         DebugLog(("STAG: level = %u, ThrowException: "
5595                                                                                 "len = %u (short frame)\n",
5596                                                                                 *level, off - offset));
5597                                                         /*
5598                                                          * TODO - Do we need to free g_malloc()ed memory?
5599                                                          */
5600                                                         THROW(ReportedBoundsError);
5601                                                 }
5602                                                 proto_tree_add_text (tree, tvb, off-1, 1,
5603                                                                 "  %3d | Tag   | T %3d    "
5604                                                                 "| END (attribute list)            "
5605                                                                 "| %s>",
5606                                                                 *level, *codepage_stag, Indent (*level));
5607                                         } else { /* Content, no Attribute list */
5608                                                 if (tag_new_known) { /* Known tag */
5609                                                         proto_tree_add_text (tree, tvb, off, 1,
5610                                                                         "  %3d | Tag   | T %3d    "
5611                                                                         "|   Known Tag 0x%02X           (.C) "
5612                                                                         "| %s<%s>",
5613                                                                         *level, *codepage_stag, tag_new_known,
5614                                                                         Indent (*level), tag_new_literal);
5615                                                         /* Tag string already looked up earlier! */
5616                                                         off++;
5617                                                 } else { /* LITERAL tag */
5618                                                         proto_tree_add_text (tree, tvb, off, 1,
5619                                                                         "  %3d | Tag   | T %3d    "
5620                                                                         "| LITERAL_C  (Literal Tag)   (.C) "
5621                                                                         "| %s<%s>",
5622                                                                         *level, *codepage_stag, Indent (*level),
5623                                                                         tag_new_literal);
5624                                                         off += 1 + tag_len;
5625                                                 }
5626                                         }
5627                                         /* The data that follows in the parsing process
5628                                          * represents content for the opening tag
5629                                          * we've just processed in the lines above.
5630                                          * Next time we encounter a tag with content: recurse
5631                                          */
5632                                         parsing_tag_content = TRUE;
5633                                         DebugLog(("Tag in Tag - No recursion this time! "
5634                                                                 "(off = %u)\n", off));
5635                                 }
5636                         } else { /* No Content */
5637                                 DebugLog(("<Tag/> in Tag - No recursion! (off = %u)\n", off));
5638                                 (*level)++;
5639                                 if (peek & 0x80) { /* No Content, Attribute list present */
5640                                         if (tag_new_known) { /* Known tag */
5641                                                 proto_tree_add_text (tree, tvb, off, 1,
5642                                                                 "  %3d | Tag   | T %3d    "
5643                                                                 "|   Known Tag 0x%02X           (A.) "
5644                                                                 "| %s<%s",
5645                                                                 *level, *codepage_stag, tag_new_known,
5646                                                                 Indent (*level), tag_new_literal);
5647                                                 /* Tag string already looked up earlier! */
5648                                                 off++;
5649                                                 len = parse_wbxml_attribute_list (tree, tvb,
5650                                                                 off, str_tbl, *level, codepage_attr);
5651                                                 /* Check that there is still room in packet */
5652                                                 off += len;
5653                                                 if (off >= tvb_len) {
5654                                                         DebugLog(("STAG: level = %u, ThrowException: "
5655                                                                                 "len = %u (short frame)\n",
5656                                                                                 *level, off - offset));
5657                                                         /*
5658                                                          * TODO - Do we need to free g_malloc()ed memory?
5659                                                          */
5660                                                         THROW(ReportedBoundsError);
5661                                                 }
5662                                                 proto_tree_add_text (tree, tvb, off-1, 1,
5663                                                                 "  %3d | Tag   | T %3d    "
5664                                                                 "| END (Known Tag)                 "
5665                                                                 "| %s/>",
5666                                                                 *level, *codepage_stag, Indent (*level));
5667                                         } else { /* LITERAL tag */
5668                                                 proto_tree_add_text (tree, tvb, off, 1,
5669                                                                 "  %3d | Tag   | T %3d    "
5670                                                                 "| LITERAL_A  (Literal Tag)   (A.) "
5671                                                                 "| %s<%s",
5672                                                                 *level, *codepage_stag, Indent (*level),
5673                                                                 tag_new_literal);
5674                                                 off += 1 + tag_len;
5675                                                 len = parse_wbxml_attribute_list (tree, tvb,
5676                                                                 off, str_tbl, *level, codepage_attr);
5677                                                 /* Check that there is still room in packet */
5678                                                 off += len;
5679                                                 if (off >= tvb_len) {
5680                                                         DebugLog(("STAG: level = %u, ThrowException: "
5681                                                                                 "len = %u (short frame)\n",
5682                                                                                 *level, off - offset));
5683                                                         /*
5684                                                          * TODO - Do we need to free g_malloc()ed memory?
5685                                                          */
5686                                                         THROW(ReportedBoundsError);
5687                                                 }
5688                                                 proto_tree_add_text (tree, tvb, off-1, 1,
5689                                                                 "  %3d | Tag   | T %3d    "
5690                                                                 "| END (Literal Tag)               "
5691                                                                 "| %s/>",
5692                                                                 *level, *codepage_stag, Indent (*level));
5693                                         }
5694                                 } else { /* No Content, No Attribute list */
5695                                         if (tag_new_known) { /* Known tag */
5696                                                 proto_tree_add_text (tree, tvb, off, 1,
5697                                                                 "  %3d | Tag   | T %3d    "
5698                                                                 "|   Known Tag 0x%02x           (..) "
5699                                                                 "| %s<%s />",
5700                                                                 *level, *codepage_stag, tag_new_known,
5701                                                                 Indent (*level), tag_new_literal);
5702                                                 /* Tag string already looked up earlier! */
5703                                                 off++;
5704                                         } else { /* LITERAL tag */
5705                                                 proto_tree_add_text (tree, tvb, off, 1,
5706                                                                 "  %3d | Tag   | T %3d    "
5707                                                                 "| LITERAL    (Literal Tag)   (..) "
5708                                                                 "| %s<%s />",
5709                                                                 *level, *codepage_stag, Indent (*level),
5710                                                                 tag_new_literal);
5711                                                 off += 1 + tag_len;
5712                                         }
5713                                 }
5714                                 (*level)--;
5715                                 /* TODO: Do I have to reset code page here? */
5716                         }
5717                 } /* if (tag & 0x3F) >= 5 */
5718         } /* while */
5719         DebugLog(("STAG: level = %u, Return: len = %u (end of function body)\n",
5720                                 *level, off - offset));
5721         return (off - offset);
5722 }
5723
5724
5725 /**************************
5726  * WBXML Attribute tokens *
5727  **************************
5728  * Bit Mask  : Example
5729  * -------------------
5730  * 0... .... : attr=             (attribute name)
5731  *             href='http://'    (attribute name with start of attribute value)
5732  * 1... .... : 'www.'            (attribute value, or part of it)
5733  * 
5734  */
5735
5736
5737 /* This function parses the WBXML and maps known token interpretations
5738  * to the WBXML tokens. As a result, the original XML document can be
5739  * recreated. Indentation is generated in order to ease reading.
5740  *
5741  * This function performs attribute list parsing.
5742  * 
5743  * The wbxml_decoding entry *map contains the actual token mapping.
5744  *
5745  * NOTE: See above for known token mappings.
5746  */
5747 static guint32
5748 parse_wbxml_attribute_list_defined (proto_tree *tree, tvbuff_t *tvb,
5749                 guint32 offset, guint32 str_tbl, guint8 level, guint8 *codepage_attr,
5750                 const wbxml_decoding *map)
5751 {
5752         guint32 tvb_len = tvb_reported_length (tvb);
5753         guint32 off = offset;
5754         guint32 len;
5755         guint str_len;
5756         guint32 ent;
5757         guint32 index;
5758         guint8 peek;
5759         guint8 attr_save_known = 0; /* Will contain peek & 0x3F (attr identity) */
5760         const char *attr_save_literal = NULL; /* Will contain the LITERAL attr identity */
5761
5762         DebugLog(("parse_wbxml_attr_defined (level = %u, offset = %u)\n",
5763                                 level, offset));
5764         /* Parse attributes */
5765         while (off < tvb_len) {
5766                 peek = tvb_get_guint8 (tvb, off);
5767                 DebugLog(("ATTR: (top of while) level = %3u, peek = 0x%02X, "
5768                                         "off = %u, tvb_len = %u\n", level, peek, off, tvb_len));
5769                 if ((peek & 0x3F) < 5) switch (peek) { /* Global tokens
5770                                                                                                   in state = ATTR */
5771                         case 0x00: /* SWITCH_PAGE */
5772                                 *codepage_attr = tvb_get_guint8 (tvb, off+1);
5773                                 proto_tree_add_text (tree, tvb, off, 2,
5774                                                 "      |  Attr | A -->%3d "
5775                                                 "| SWITCH_PAGE (Attr code page)    |",
5776                                                 *codepage_attr);
5777                                 off += 2;
5778                                 break;
5779                         case 0x01: /* END */
5780                                 /* BEWARE
5781                                  *   The Attribute END token means either ">" or "/>"
5782                                  *   and as a consequence both must be treated separately.
5783                                  *   This is done in the TAG state parser.
5784                                  */
5785                                 off++;
5786                                 DebugLog(("ATTR: level = %u, Return: len = %u\n",
5787                                                         level, off - offset));
5788                                 return (off - offset);
5789                         case 0x02: /* ENTITY */
5790                                 ent = tvb_get_guintvar (tvb, off+1, &len);
5791                                 proto_tree_add_text (tree, tvb, off, 1+len,
5792                                                 "  %3d |  Attr | A %3d    "
5793                                                 "| ENTITY                          "
5794                                                 "|     %s'&#%u;'",
5795                                                 level, *codepage_attr, Indent (level), ent);
5796                                 off += 1+len;
5797                                 break;
5798                         case 0x03: /* STR_I */
5799                                 len = tvb_strsize (tvb, off+1);
5800                                 proto_tree_add_text (tree, tvb, off, 1+len,
5801                                                 "  %3d |  Attr | A %3d    "
5802                                                 "| STR_I (Inline string)           "
5803                                                 "|     %s\'%s\'",
5804                                                 level, *codepage_attr, Indent (level),
5805                                                 tvb_format_text (tvb, off+1, len-1));
5806                                 off += 1+len;
5807                                 break;
5808                         case 0x04: /* LITERAL */
5809                                 /* ALWAYS means the start of a new attribute,
5810                                  * and may only contain the NAME of the attribute.
5811                                  */
5812                                 index = tvb_get_guintvar (tvb, off+1, &len);
5813                                 str_len = tvb_strsize (tvb, str_tbl+index);
5814                                 attr_save_known = 0;
5815                                 attr_save_literal = tvb_format_text (tvb,
5816                                                 str_tbl+index, str_len-1);
5817                                 proto_tree_add_text (tree, tvb, off, 1+len,
5818                                                 "  %3d |  Attr | A %3d    "
5819                                                 "| LITERAL (Literal Attribute)     "
5820                                                 "|   %s<%s />",
5821                                                 level, *codepage_attr, Indent (level),
5822                                                 attr_save_literal);
5823                                 off += 1+len;
5824                                 break;
5825                         case 0x40: /* EXT_I_0 */
5826                         case 0x41: /* EXT_I_1 */
5827                         case 0x42: /* EXT_I_2 */
5828                                 /* Extension tokens */
5829                                 len = tvb_strsize (tvb, off+1);
5830                                 proto_tree_add_text (tree, tvb, off, 1+len,
5831                                                 "  %3d |  Attr | A %3d    "
5832                                                 "| EXT_I_%1x    (Extension Token)    "
5833                                                 "|     %s(%s: \'%s\')",
5834                                                 level, *codepage_attr, peek & 0x0f, Indent (level),
5835                                                 map_token (map->global, 0, peek),
5836                                                 tvb_format_text (tvb, off+1, len-1));
5837                                 off += 1+len;
5838                                 break;
5839                         /* 0x43 impossible in ATTR state */
5840                         /* 0x44 impossible in ATTR state */
5841                         case 0x80: /* EXT_T_0 */
5842                         case 0x81: /* EXT_T_1 */
5843                         case 0x82: /* EXT_T_2 */
5844                                 /* Extension tokens */
5845                                 index = tvb_get_guintvar (tvb, off+1, &len);
5846                                 {   char *s;
5847
5848                                     if (map->ext_t[peek & 0x03])
5849                                         s = (map->ext_t[peek & 0x03])(tvb, index, str_tbl);
5850                                     else
5851                                         s = g_strdup_printf("EXT_T_%1x (%s)", peek & 0x03, 
5852                                                 map_token (map->global, 0, peek));
5853
5854                                     proto_tree_add_text (tree, tvb, off, 1+len,
5855                                                 "  %3d | Tag   | T %3d    "
5856                                                 "| EXT_T_%1x    (Extension Token)    "
5857                                                 "| %s%s)",
5858                                                 level, *codepage_attr, peek & 0x0f, Indent (level),
5859                                                 s);
5860                                     g_free(s);
5861                                 }
5862                                 off += 1+len;
5863                                 break;
5864                         case 0x83: /* STR_T */
5865                                 index = tvb_get_guintvar (tvb, off+1, &len);
5866                                 str_len = tvb_strsize (tvb, str_tbl+index);
5867                                 proto_tree_add_text (tree, tvb, off, 1+len,
5868                                                 "  %3d |  Attr | A %3d    "
5869                                                 "| STR_T (Tableref string)         "
5870                                                 "|     %s\'%s\'",
5871                                                 level, *codepage_attr, Indent (level),
5872                                                 tvb_format_text (tvb, str_tbl+index, str_len-1));
5873                                 off += 1+len;
5874                                 break;
5875                         /* 0x84 impossible in ATTR state */
5876                         case 0xC0: /* EXT_0 */
5877                         case 0xC1: /* EXT_1 */
5878                         case 0xC2: /* EXT_2 */
5879                                 /* Extension tokens */
5880                                 proto_tree_add_text (tree, tvb, off, 1,
5881                                                 "  %3d |  Attr | A %3d    "
5882                                                 "| EXT_%1x      (Extension Token)    "
5883                                                 "|     %s(%s)",
5884                                                 level, *codepage_attr, peek & 0x0f, Indent (level),
5885                                                 map_token (map->global, 0, peek));
5886                                 off++;
5887                                 break;
5888                         case 0xC3: /* OPAQUE - WBXML 1.1 and newer */
5889                                 if (tvb_get_guint8 (tvb, 0)) { /* WBXML 1.x (x > 0) */
5890                                         char *str;
5891                                         if (attr_save_known) { /* Knwon attribute */
5892                                                 if (map->opaque_binary_attr) {
5893                                                         str = map->opaque_binary_attr(tvb, off + 1,
5894                                                                         attr_save_known, *codepage_attr, &len);
5895                                                 } else {
5896                                                         str = default_opaque_binary_attr(tvb, off + 1,
5897                                                                         attr_save_known, *codepage_attr, &len);
5898                                                 }
5899                                         } else { /* lITERAL attribute */
5900                                                 if (map->opaque_literal_tag) {
5901                                                         str = map->opaque_literal_attr(tvb, off + 1,
5902                                                                         attr_save_literal, *codepage_attr, &len);
5903                                                 } else {
5904                                                         str = default_opaque_literal_attr(tvb, off + 1,
5905                                                                         attr_save_literal, *codepage_attr, &len);
5906                                                 }
5907                                         }
5908                                         proto_tree_add_text (tree, tvb, off, 1 + len,
5909                                                         "  %3d |  Attr | A %3d    "
5910                                                         "| OPAQUE (Opaque data)            "
5911                                                         "|       %s%s",
5912                                                         level, *codepage_attr, Indent (level), str);
5913                                         g_free(str);
5914                                         off += 1 + len;
5915                                 } else { /* WBXML 1.0 - RESERVED_2 token (invalid) */
5916                                         proto_tree_add_text (tree, tvb, off, 1,
5917                                                         "  %3d |  Attr | A %3d    "
5918                                                         "| RESERVED_2     (Invalid Token!) "
5919                                                         "| WBXML 1.0 parsing stops here.",
5920                                                         level, *codepage_attr);
5921                                         /* Stop processing as it is impossible to parse now */
5922                                         off = tvb_len;
5923                                         DebugLog(("ATTR: level = %u, Return: len = %u\n",
5924                                                                 level, off - offset));
5925                                         return (off - offset);
5926                                 }
5927                                 break;
5928                         /* 0xC4 impossible in ATTR state */
5929                         default:
5930                                 proto_tree_add_text (tree, tvb, off, 1,
5931                                                 "  %3d |  Attr | A %3d    "
5932                                                 "| %-10s     (Invalid Token!) "
5933                                                 "| WBXML parsing stops here.",
5934                                                 level, *codepage_attr,
5935                                                 match_strval (peek, vals_wbxml1x_global_tokens));
5936                                 /* Move to end of buffer */
5937                                 off = tvb_len;
5938                                 break;
5939                 } else { /* Known atribute token */
5940                         if (peek & 0x80) { /* attrValue */
5941                                 proto_tree_add_text (tree, tvb, off, 1,
5942                                                 "  %3d |  Attr | A %3d    "
5943                                                 "|   Known attrValue 0x%02X          "
5944                                                 "|       %s%s",
5945                                                 level, *codepage_attr, peek & 0x7f, Indent (level),
5946                                                 map_token (map->attrValue, *codepage_attr, peek));
5947                                 off++;
5948                         } else { /* attrStart */
5949                                 attr_save_known = peek & 0x7f;
5950                                 proto_tree_add_text (tree, tvb, off, 1,
5951                                                 "  %3d |  Attr | A %3d    "
5952                                                 "|   Known attrStart 0x%02X          "
5953                                                 "|   %s%s",
5954                                                 level, *codepage_attr, attr_save_known, Indent (level),
5955                                                 map_token (map->attrStart, *codepage_attr, peek));
5956                                 off++;
5957                         }
5958                 }
5959         } /* End WHILE */
5960         DebugLog(("ATTR: level = %u, Return: len = %u (end of function body)\n",
5961                                 level, off - offset));
5962         return (off - offset);
5963 }
5964
5965
5966 /* This function performs the WBXML attribute decoding as in
5967  * parse_wbxml_attribute_list_defined() but this time no WBXML mapping
5968  * is performed.
5969  *
5970  * This function performs attribute list parsing.
5971  * 
5972  * NOTE: Code page switches not yet processed in the code!
5973  */
5974 static guint32
5975 parse_wbxml_attribute_list (proto_tree *tree, tvbuff_t *tvb,
5976                 guint32 offset, guint32 str_tbl, guint8 level, guint8 *codepage_attr)
5977 {
5978         guint32 tvb_len = tvb_reported_length (tvb);
5979         guint32 off = offset;
5980         guint32 len;
5981         guint str_len;
5982         guint32 ent;
5983         guint32 index;
5984         guint8 peek;
5985
5986         DebugLog(("parse_wbxml_attr (level = %u, offset = %u)\n", level, offset));
5987         /* Parse attributes */
5988         while (off < tvb_len) {
5989                 peek = tvb_get_guint8 (tvb, off);
5990                 DebugLog(("ATTR: (top of while) level = %3u, peek = 0x%02X, "
5991                                         "off = %u, tvb_len = %u\n", level, peek, off, tvb_len));
5992                 if ((peek & 0x3F) < 5) switch (peek) { /* Global tokens
5993                                                                                                   in state = ATTR */
5994                         case 0x00: /* SWITCH_PAGE */
5995                                 *codepage_attr = tvb_get_guint8 (tvb, off+1);
5996                                 proto_tree_add_text (tree, tvb, off, 2,
5997                                                 "      |  Attr | A -->%3d "
5998                                                 "| SWITCH_PAGE (Attr code page)    |",
5999                                                 *codepage_attr);
6000                                 off += 2;
6001                                 break;
6002                         case 0x01: /* END */
6003                                 /* BEWARE
6004                                  *   The Attribute END token means either ">" or "/>"
6005                                  *   and as a consequence both must be treated separately.
6006                                  *   This is done in the TAG state parser.
6007                                  */
6008                                 off++;
6009                                 DebugLog(("ATTR: level = %u, Return: len = %u\n",
6010                                                         level, off - offset));
6011                                 return (off - offset);
6012                         case 0x02: /* ENTITY */
6013                                 ent = tvb_get_guintvar (tvb, off+1, &len);
6014                                 proto_tree_add_text (tree, tvb, off, 1+len,
6015                                                 "  %3d |  Attr | A %3d    "
6016                                                 "| ENTITY                          "
6017                                                 "|     %s'&#%u;'",
6018                                                 level, *codepage_attr, Indent (level), ent);
6019                                 off += 1+len;
6020                                 break;
6021                         case 0x03: /* STR_I */
6022                                 len = tvb_strsize (tvb, off+1);
6023                                 proto_tree_add_text (tree, tvb, off, 1+len,
6024                                                 "  %3d |  Attr | A %3d    "
6025                                                 "| STR_I (Inline string)           "
6026                                                 "|     %s\'%s\'",
6027                                                 level, *codepage_attr, Indent (level),
6028                                                 tvb_format_text (tvb, off+1, len-1));
6029                                 off += 1+len;
6030                                 break;
6031                         case 0x04: /* LITERAL */
6032                                 index = tvb_get_guintvar (tvb, off+1, &len);
6033                                 str_len = tvb_strsize (tvb, str_tbl+index);
6034                                 proto_tree_add_text (tree, tvb, off, 1+len,
6035                                                 "  %3d |  Attr | A %3d    "
6036                                                 "| LITERAL (Literal Attribute)     "
6037                                                 "|   %s<%s />",
6038                                                 level, *codepage_attr, Indent (level),
6039                                                 tvb_format_text (tvb, str_tbl+index, str_len-1));
6040                                 off += 1+len;
6041                                 break;
6042                         case 0x40: /* EXT_I_0 */
6043                         case 0x41: /* EXT_I_1 */
6044                         case 0x42: /* EXT_I_2 */
6045                                 /* Extension tokens */
6046                                 len = tvb_strsize (tvb, off+1);
6047                                 proto_tree_add_text (tree, tvb, off, 1+len,
6048                                                 "  %3d |  Attr | A %3d    "
6049                                                 "| EXT_I_%1x    (Extension Token)    "
6050                                                 "|     %s(Inline string extension: \'%s\')",
6051                                                 level, *codepage_attr, peek & 0x0f, Indent (level),
6052                                                 tvb_format_text (tvb, off+1, len-1));
6053                                 off += 1+len;
6054                                 break;
6055                         /* 0x43 impossible in ATTR state */
6056                         /* 0x44 impossible in ATTR state */
6057                         case 0x80: /* EXT_T_0 */
6058                         case 0x81: /* EXT_T_1 */
6059                         case 0x82: /* EXT_T_2 */
6060                                 /* Extension tokens */
6061                                 index = tvb_get_guintvar (tvb, off+1, &len);
6062                                 proto_tree_add_text (tree, tvb, off, 1+len,
6063                                                 "  %3d |  Attr | A %3d    "
6064                                                 "| EXT_T_%1x    (Extension Token)    "
6065                                                 "|     %s(Extension Token, integer value: %u)",
6066                                                 level, *codepage_attr, peek & 0x0f, Indent (level),
6067                                                 index);
6068                                 off += 1+len;
6069                                 break;
6070                         case 0x83: /* STR_T */
6071                                 index = tvb_get_guintvar (tvb, off+1, &len);
6072                                 str_len = tvb_strsize (tvb, str_tbl+index);
6073                                 proto_tree_add_text (tree, tvb, off, 1+len,
6074                                                 "  %3d |  Attr | A %3d    "
6075                                                 "| STR_T (Tableref string)         "
6076                                                 "|     %s\'%s\'",
6077                                                 level, *codepage_attr, Indent (level),
6078                                                 tvb_format_text (tvb, str_tbl+index, str_len-1));
6079                                 off += 1+len;
6080                                 break;
6081                         /* 0x84 impossible in ATTR state */
6082                         case 0xC0: /* EXT_0 */
6083                         case 0xC1: /* EXT_1 */
6084                         case 0xC2: /* EXT_2 */
6085                                 /* Extension tokens */
6086                                 proto_tree_add_text (tree, tvb, off, 1,
6087                                                 "  %3d |  Attr | A %3d    "
6088                                                 "| EXT_%1x      (Extension Token)    "
6089                                                 "|     %s(Single-byte extension)",
6090                                                 level, *codepage_attr, peek & 0x0f, Indent (level));
6091                                 off++;
6092                                 break;
6093                         case 0xC3: /* OPAQUE - WBXML 1.1 and newer */
6094                                 if (tvb_get_guint8 (tvb, 0)) { /* WBXML 1.x (x > 0) */
6095                                         index = tvb_get_guintvar (tvb, off+1, &len);
6096                                         proto_tree_add_text (tree, tvb, off, 1 + len + index,
6097                                                         "  %3d |  Attr | A %3d    "
6098                                                         "| OPAQUE (Opaque data)            "
6099                                                         "|       %s(%d bytes of opaque data)",
6100                                                         level, *codepage_attr, Indent (level), index);
6101                                         off += 1+len+index;
6102                                 } else { /* WBXML 1.0 - RESERVED_2 token (invalid) */
6103                                         proto_tree_add_text (tree, tvb, off, 1,
6104                                                         "  %3d |  Attr | A %3d    "
6105                                                         "| RESERVED_2     (Invalid Token!) "
6106                                                         "| WBXML 1.0 parsing stops here.",
6107                                                         level, *codepage_attr);
6108                                         /* Stop processing as it is impossible to parse now */
6109                                         off = tvb_len;
6110                                         DebugLog(("ATTR: level = %u, Return: len = %u\n",
6111                                                                 level, off - offset));
6112                                         return (off - offset);
6113                                 }
6114                                 break;
6115                         /* 0xC4 impossible in ATTR state */
6116                         default:
6117                                 proto_tree_add_text (tree, tvb, off, 1,
6118                                                 "  %3d |  Attr | A %3d    "
6119                                                 "| %-10s     (Invalid Token!) "
6120                                                 "| WBXML parsing stops here.",
6121                                                 level, *codepage_attr,
6122                                                 match_strval (peek, vals_wbxml1x_global_tokens));
6123                                 /* Move to end of buffer */
6124                                 off = tvb_len;
6125                                 break;
6126                 } else { /* Known atribute token */
6127                         if (peek & 0x80) { /* attrValue */
6128                                 proto_tree_add_text (tree, tvb, off, 1,
6129                                                 "  %3d |  Attr | A %3d    "
6130                                                 "|   Known attrValue 0x%02X          "
6131                                                 "|       %sattrValue_0x%02X",
6132                                                 level, *codepage_attr, peek & 0x7f, Indent (level),
6133                                                 peek);
6134                                 off++;
6135                         } else { /* attrStart */
6136                                 proto_tree_add_text (tree, tvb, off, 1,
6137                                                 "  %3d |  Attr | A %3d    "
6138                                                 "|   Known attrStart 0x%02X          "
6139                                                 "|   %sattrStart_0x%02X",
6140                                                 level, *codepage_attr, peek & 0x7f, Indent (level),
6141                                                 peek);
6142                                 off++;
6143                         }
6144                 }
6145         } /* End WHILE */
6146         DebugLog(("ATTR: level = %u, Return: len = %u (end of function body)\n",
6147                                 level, off - offset));
6148         return (off - offset);
6149 }
6150
6151
6152 /****************** Register the protocol with Ethereal ******************/
6153
6154
6155 /* This format is required because a script is used to build the C function
6156  * that calls the protocol registration. */
6157
6158 void
6159 proto_register_wbxml(void)
6160 {
6161         module_t *wbxml_module; /* WBXML Preferences */
6162
6163         /* Setup list of header fields. */
6164         static hf_register_info hf[] = {
6165                 { &hf_wbxml_version,
6166                         { "Version",
6167                           "wbxml.version",
6168                           FT_UINT8, BASE_HEX,
6169                           VALS ( vals_wbxml_versions ), 0x00,
6170                           "WBXML Version", HFILL }
6171                 },
6172                 { &hf_wbxml_public_id_known,
6173                         { "Public Identifier (known)",
6174                           "wbxml.public_id.known",
6175                           FT_UINT32, BASE_HEX,
6176                           VALS ( vals_wbxml_public_ids ), 0x00,
6177                           "WBXML Known Public Identifier (integer)", HFILL }
6178                 },
6179                 { &hf_wbxml_public_id_literal,
6180                         { "Public Identifier (literal)",
6181                           "wbxml.public_id.literal",
6182                           FT_STRING, BASE_NONE,
6183                           NULL, 0x00,
6184                           "WBXML Literal Public Identifier (text string)", HFILL }
6185                 },
6186                 { &hf_wbxml_charset,
6187                         { "Character Set",
6188                           "wbxml.charset",
6189                           FT_UINT32, BASE_HEX,
6190                           VALS ( vals_character_sets ), 0x00,
6191                           "WBXML Character Set", HFILL }
6192                 },
6193         };
6194
6195         /* Setup protocol subtree array */
6196         static gint *ett[] = {
6197                 &ett_wbxml,
6198                 &ett_wbxml_str_tbl,
6199                 &ett_wbxml_content,
6200         };
6201
6202         /* Register the protocol name and description */
6203         proto_wbxml = proto_register_protocol(
6204                         "WAP Binary XML",
6205                         "WBXML",
6206                         "wbxml"
6207         );
6208
6209         /* Required function calls to register the header fields
6210          * and subtrees used */
6211         proto_register_field_array(proto_wbxml, hf, array_length(hf));
6212         proto_register_subtree_array(ett, array_length(ett));
6213
6214         /* Preferences */
6215         wbxml_module = prefs_register_protocol(proto_wbxml, NULL);
6216         prefs_register_bool_preference(wbxml_module,
6217                         "skip_wbxml_token_mapping",
6218                         "Skip the mapping of WBXML tokens to media type tokens.",
6219                         "Enable this preference if you want to view the WBXML "
6220                         "tokens without the representation in a media type "
6221                         "(e.g., WML). Tokens will show up as Tag_0x12, "
6222                         "attrStart_0x08 or attrValue_0x0B for example.",
6223                         &skip_wbxml_token_mapping);
6224         prefs_register_bool_preference(wbxml_module,
6225                         "disable_wbxml_token_parsing",
6226                         "Disable the parsing of the WBXML tokens.",
6227                         "Enable this preference if you want to skip the "
6228                         "parsing of the WBXML tokens that constitute the body "
6229                         "of the WBXML document. Only the WBXML header will be "
6230                         "dissected (and visualized) then.",
6231                         &disable_wbxml_token_parsing);
6232
6233         register_dissector("wbxml", dissect_wbxml, proto_wbxml);
6234 }
6235
6236
6237 void
6238 proto_reg_handoff_wbxml(void)
6239 {
6240         dissector_handle_t wbxml_handle;
6241
6242         /* Heuristic dissectors would be declared by means of:
6243          * heur_dissector_add("wsp", dissect_wbxml_heur, proto_wbxml);
6244          */
6245
6246         wbxml_handle = create_dissector_handle(dissect_wbxml, proto_wbxml);
6247
6248         /* Register the WSP content types (defined as protocol port)
6249          * for WBXML dissection.
6250          * 
6251          * See http://www.wapforum.org/wina/wsp-content-type.htm
6252          * 
6253          * As the media types for WSP and HTTP are the same, the WSP dissector
6254          * uses the same string dissector table as the HTTP protocol.
6255          */
6256
6257         /**** Well-known WBXML WSP Content-Type values ****/
6258         
6259         dissector_add_string("media_type",
6260                         "application/vnd.wap.wmlc", wbxml_handle);
6261         dissector_add_string("media_type",
6262                         "application/vnd.wap.wta-eventc", wbxml_handle);
6263         dissector_add_string("media_type",
6264                         "application/vnd.wap.wbxml", wbxml_handle);
6265         dissector_add_string("media_type",
6266                         "application/vnd.wap.sic", wbxml_handle);
6267         dissector_add_string("media_type",
6268                         "application/vnd.wap.slc", wbxml_handle);
6269         dissector_add_string("media_type",
6270                         "application/vnd.wap.coc", wbxml_handle);
6271         dissector_add_string("media_type",
6272                         "application/vnd.wap.connectivity-wbxml", wbxml_handle);
6273         dissector_add_string("media_type",
6274                         "application/vnd.wap.locc+wbxml", wbxml_handle);
6275         dissector_add_string("media_type",
6276                         "application/vnd.syncml+wbxml", wbxml_handle);
6277         dissector_add_string("media_type",
6278                         "application/vnd.syncml.dm+wbxml", wbxml_handle);
6279         dissector_add_string("media_type",
6280                         "application/vnd.oma.drm.rights+wbxml", wbxml_handle);
6281         dissector_add_string("media_type",
6282                         "application/vnd.wv.csp.wbxml", wbxml_handle);
6283
6284         /**** Registered WBXML WSP Content-Type values ****/
6285
6286         dissector_add_string("media_type",
6287                         "application/vnd.uplanet.cacheop-wbxml", wbxml_handle);
6288         dissector_add_string("media_type",
6289                         "application/vnd.uplanet.alert-wbxml", wbxml_handle);
6290         dissector_add_string("media_type",
6291                         "application/vnd.uplanet.list-wbxml", wbxml_handle);
6292         dissector_add_string("media_type",
6293                         "application/vnd.uplanet.listcmd-wbxml", wbxml_handle);
6294         dissector_add_string("media_type",
6295                         "application/vnd.uplanet.channel-wbxml", wbxml_handle);
6296         dissector_add_string("media_type",
6297                         "application/vnd.uplanet.bearer-choice-wbxml", wbxml_handle);
6298         dissector_add_string("media_type",
6299                         "application/vnd.phonecom.mmc-wbxml", wbxml_handle);
6300         dissector_add_string("media_type",
6301                         "application/vnd.nokia.syncset+wbxml", wbxml_handle);
6302
6303         /***** Content types that only have a textual representation *****/
6304         dissector_add_string("media_type",
6305                         "application/x-wap-prov.browser-bookmarks", wbxml_handle);
6306         dissector_add_string("media_type",
6307                         "application/x-wap-prov.browser-settings", wbxml_handle);
6308         /* Same as application/vnd.nokia.syncset+wbxml */
6309         dissector_add_string("media_type",
6310                         "application/x-prov.syncset+wbxml", wbxml_handle);
6311         
6312 }