As per a suggestion by Olivier Biot, note that objects pointed to by
[obnox/wireshark/wip.git] / packet-wbxml.c
index cf02e412c8a0a630e501b2d2110b080f58b0fb32..d14ae2e991eaa20be11a8b1d9947f25c5d480fa0 100644 (file)
@@ -2,13 +2,16 @@
  * Routines for wbxml dissection
  * Copyright 2003, Olivier Biot <olivier.biot (ad) siemens.com>
  *
- * $Id: packet-wbxml.c,v 1.2 2003/02/12 01:17:02 guy Exp $
+ * $Id: packet-wbxml.c,v 1.12 2003/10/09 18:54:06 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@ethereal.com>
  * Copyright 1998 Gerald Combs
  *
- * Wap Binary XML decoding functionality provided by Olivier Biot.
+ * WAP Binary XML decoding functionality provided by Olivier Biot.
+ * 
+ * The WAP specifications are found at the WAP Forum:
+ * http://www.wapforum.org/what/Technical.htm
  * 
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
 #endif
 
 #include <epan/packet.h>
+
+/* We need the function tvb_get_guintvar() */
 #include "packet-wap.h"
-#include "packet-wbxml.h"
 
 /* The code in this source file dissects the WAP Binary XML content,
- * and if possible renders it. WBXML mappings are defined in a struct
- * located at the very end of "packet-wbxml.h".
+ * and if possible renders it. WBXML mappings are defined in the
+ * "wbxml_map[]" array.
  *
  * NOTES:
  *
- *  - Although Code Page processing is already foreseen in the tag and
- *    attribute parsing code, there is no mechanism available yet to
- *    properly deal with multiple code pages (see, e.g., the wbxml_map[]
- *    array). As a consequence, the same token rendering will occur,
- *    irrespective of the code pages in use.
- *    As there currently is no registered WBXML type with support of more
- *    than one tag or attribute code page, this is a safe assumption.
+ *  - Code page switches only apply to the following token. In the WBXML/1.x
+ *    ABNF notation, it can be proven that the switch_page can only precede
+ *    the following tokens:
+ *      o  stag      : TAG | LITERAL | LITERAL_A | LITERAL_C | LITERAL_AC
+ *      o  attr      : ATTRSTART | ATTRVALUE
+ *      o  extension : EXT_I | EXT_T | EXT
+ *    Code page switches are displayed in a separate column. The only allowed
+ *    code page switches are from code page 0 to another codepage (by means of
+ *    a SWITCH_PAGE token), and from this other code page back to code page 0
+ *    (this happens automatically).
  *
  *  - In order to render the XML content, recursion is inevitable at some
  *    point (when a tag with content occurs in the content of a tag with
  *    is defined for the parsed WBXML content, then the XML rendering is
  *    displayed with appropriate indentation (maximum nesting level = 255,
  *    after which the nesting and level will safely roll-over to 0).
+ *
+ *  - The WAP Forum defines the order of precedence for finding out the
+ *    WBXML content type (same rules for charset) as follows:
+ *      1. Look in the Content-Type WSP header
+ *      2. Look in the WBXML header
+ *    Currently there is no means of using content type parameters:
+ *      o  Type=<some_type>
+ *      o  Charset=<charset_of_the_content>
+ *    So it is possible some WBXML content types are incorrectly parsed.
+ *    This would only be the case when the content type declaration in the
+ *    WSP Content-Type header would be different (or would have parameters
+ *    which are relevant to the WBXML decoding) from the content type
+ *    identifier specified in the WBXML header.
+ *    TODO: investigate this and provide correct decoding at all times.
  */
 
+typedef struct _value_valuestring {
+  guint32 value;
+  const value_string *valstrptr;
+} value_valuestring;
+
+/* Tries to match val against each element in the value_value_string array vvs.
+ * Returns the associated value_string ptr on a match, or NULL on failure. */
+static const value_string *
+val_to_valstr(guint32 val, const value_valuestring *vvs)
+{
+  gint i = 0;
+
+  while (vvs[i].valstrptr) {
+       if (vvs[i].value == val)
+      return(vvs[i].valstrptr);
+      i++;
+  }
+
+  return(NULL);
+}
+
+
+/************************** Variable declarations **************************/
+
+
 /* Initialize the protocol and registered fields */
 static int proto_wbxml = -1;
 static int hf_wbxml_version = -1;
@@ -81,84 +127,1717 @@ static int hf_wbxml_charset = -1;
 
 /* Initialize the subtree pointers */
 static gint ett_wbxml = -1;
+static gint ett_wbxml_str_tbl = -1;
 static gint ett_wbxml_content = -1;
 
-/*
- * Function prototypes
- */
 
-static void
-dissect_wbxml(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
+/**************** WBXML related declarations and definitions ****************/
+
+
+/* WBXML public ID mappings. For an up-to-date list, see
+ * http://www.wapforum.org/wina/wbxml-public-docid.htm */
+static const value_string vals_wbxml_public_ids[] = {
+       /* 0x00 = literal public identifier */
+       { 0x01, "Unknown / missing Public Identifier" },
+       { 0x02, "-//WAPFORUM//DTD WML 1.0//EN (WML 1.0)" },
+       { 0x03, "-//WAPFORUM//DTD WTA 1.0//EN (WTA Event 1.0) - Deprecated" },
+       { 0x04, "-//WAPFORUM//DTD WML 1.1//EN (WML 1.1)" },
+       { 0x05, "-//WAPFORUM//DTD SI 1.0//EN (Service Indication 1.0)" },
+       { 0x06, "-//WAPFORUM//DTD SL 1.0//EN (Service Loading 1.0)" },
+       { 0x07, "-//WAPFORUM//DTD CO 1.0//EN (Cache Operation 1.0)" },
+       { 0x08, "-//WAPFORUM//DTD CHANNEL 1.0//EN (Channel 1.1)" },
+       { 0x09, "-//WAPFORUM//DTD WML 1.2//EN (WML 1.2)" },
+       { 0x0a, "-//WAPFORUM//DTD WML 1.3//EN (WML 1.3)" },
+       { 0x0b, "-//WAPFORUM//DTD PROV 1.0//EN (Provisioning 1.0)" },
+       { 0x0c, "-//WAPFORUM//DTD WTA-WML 1.2//EN (WTA-WML 1.2)" },
+       { 0x0d, "-//WAPFORUM//DTD EMN 1.0//EN (Email Notification 1.0)" },
+       { 0x0e, "-//WAPFORUM//DTD DRMREL 1.0//EN (DRMREL 1.0)" },
+       
+       /* Registered values - www.syncml.org */
+       { 0x0fd1, "-//SYNCML//DTD SyncML 1.0//EN (SyncML 1.0)" },
+       { 0x0fd3, "-//SYNCML//DTD SyncML 1.1//EN (SyncML 1.1)" },
+
+       /* Registered values - www.wapforum.org/wina/ */
+       { 0x1100, "-//PHONE.COM//DTD ALERT 1.0//EN" },
+       { 0x1101, "-//PHONE.COM//DTD CACHE-OPERATION 1.0//EN" },
+       { 0x1102, "-//PHONE.COM//DTD SIGNAL 1.0//EN" },
+       { 0x1103, "-//PHONE.COM//DTD LIST 1.0//EN" },
+       { 0x1104, "-//PHONE.COM//DTD LISTCMD 1.0//EN" },
+       { 0x1105, "-//PHONE.COM//DTD CHANNEL 1.0//EN" },
+       { 0x1106, "-//PHONE.COM//DTD MMC 1.0//EN" },
+       { 0x1107, "-//PHONE.COM//DTD BEARER-CHOICE 1.0//EN" },
+       { 0x1108, "-//PHONE.COM//DTD WML 1.1//EN (WML+ 1.1)" },
+       { 0x1109, "-//PHONE.COM//DTD CHANNEL 1.1//EN" },
+       { 0x110a, "-//PHONE.COM//DTD LIST 1.1//EN" },
+       { 0x110b, "-//PHONE.COM//DTD LISTCMD 1.1//EN" },
+       { 0x110c, "-//PHONE.COM//DTD MMC 1.1//EN" },
+       { 0x110d, "-//PHONE.COM//DTD WML 1.3//EN (WML+ 1.3)" },
+       { 0x110e, "-//PHONE.COM//DTD MMC 2.0//EN" },
+       
+       { 0x00, NULL }
+};
 
-void
-proto_register_wbxml(void);
+static const value_string vals_wbxml_versions[] = {
+       { 0x00, "1.0" },        /* WAP-104-WBXML */
+       { 0x01, "1.1" },        /* WAP-135-WBXML */
+       { 0x02, "1.2" },        /* WAP-154-WBXML */
+       { 0x03, "1.3" },        /* WAP-192-WBXML */
+       
+       { 0x00, NULL }
+};
 
+/* WBXML 1.0 global tokens: WAP-104-WBXML
+ * Same token mapping as in vals_wbxml1x_global_tokens, but:
+ *   { 0xC3, "RESERVED_2" }
+ */
 
-/* Parse data while in STAG state
+/* WBXML 1.x (x>0) global tokens: WAP-135-WBXML, WAP-154-WBXML, WAP-192-WBXML
  */
-void
-parse_wbxml_tag (proto_tree *tree, tvbuff_t *tvb, guint32 offset,
-               guint32 str_tbl, guint8 *level,
-               guint8 *codepage_stag, guint8 *codepage_attr, guint32 *parsed_length);
+static const value_string vals_wbxml1x_global_tokens[] = {
+       { 0x00, "SWITCH_PAGE" },
+       { 0x01, "END" },
+       { 0x02, "ENTITY" },
+       { 0x03, "STR_I" },
+       { 0x04, "LITERAL" },
+
+       { 0x40, "EXT_I_0" },
+       { 0x41, "EXT_I_1" },
+       { 0x42, "EXT_I_2" },
+       { 0x43, "PI" },
+       { 0x44, "LITERAL_C" },
+
+       { 0x80, "EXT_T_0" },
+       { 0x81, "EXT_T_1" },
+       { 0x82, "EXT_T_2" },
+       { 0x83, "STR_T" },
+       { 0x84, "LITERAL_A" },
+
+       { 0xC0, "EXT_0" },
+       { 0xC1, "EXT_1" },
+       { 0xC2, "EXT_2" },
+       { 0xC3, "OPAQUE" },
+       { 0xC4, "LITERAL_AC" },
+
+       { 0x00, NULL }
+};
 
 
-/* Parse data while in STAG state;
- * interpret tokens as defined by content type
- */
-void
-parse_wbxml_tag_defined (proto_tree *tree, tvbuff_t *tvb, guint32 offset,
-               guint32 str_tbl, guint8 *level,
-               guint8 *codepage_stag, guint8 *codepage_attr, guint32 *parsed_length,
-               const wbxml_mapping_table *map);
+/********************** WBXML token mapping definition **********************/
+
+
+/* WML 1.0
+ * 
+ * Wireless Markup Language
+ ***************************************/
+
+/*****   Global extension tokens   *****/
+static const value_string wbxml_wmlc10_global_cp0[] = {
+       { 0x40, "Variable substitution - escaped" },
+       { 0x41, "Variable substitution - unescaped" },
+       { 0x42, "Variable substitution - no transformation" },
+       { 0x80, "Variable substitution - escaped" },
+       { 0x81, "Variable substitution - unescaped" },
+       { 0x82, "Variable substitution - no transformation" },
+       { 0xC0, "Reserved" },
+       { 0xC1, "Reserved" },
+       { 0xC2, "Reserved" },
+
+       { 0x00, NULL }
+};
+
+/*****         Tag tokens          *****/
+static const value_string wbxml_wmlc10_tags_cp0[] = {
+       /* 0x00 -- 0x04 GLOBAL */
+       /* 0x05 -- 0xE1 */
+       { 0xE2, "A" },
+       { 0xE3, "ACCESS" },
+       { 0xE4, "B" },
+       { 0xE5, "BIG" },
+       { 0xE6, "BR" },
+       { 0xE7, "CARD" },
+       { 0xE8, "DO" },
+       { 0xE9, "EM" },
+       { 0xEA, "FIELDSET" },
+       { 0xEB, "GO" },
+       { 0xEC, "HEAD" },
+       { 0xED, "I" },
+       { 0xEE, "IMG" },
+       { 0xEF, "INPUT" },
+       { 0xF0, "META" },
+       { 0xF1, "NOOP" },
+       { 0xF2, "PREV" },
+       { 0xF3, "ONEVENT" },
+       { 0xF4, "OPTGROUP" },
+       { 0xF5, "OPTION" },
+       { 0xF6, "REFRESH" },
+       { 0xF7, "SELECT" },
+       { 0xF8, "SMALL" },
+       { 0xF9, "STRONG" },
+       { 0xFA, "TAB" },
+       { 0xFB, "TEMPLATE" },
+       { 0xFC, "TIMER" },
+       { 0xFD, "U" },
+       { 0xFE, "VAR" },
+       { 0xFF, "WML" },
+
+       { 0x00, NULL }
+};
+
+/*****    Attribute Start tokens   *****/
+static const value_string wbxml_wmlc10_attrStart_cp0[] = {
+       /* 0x00 -- 0x04 GLOBAL */
+       { 0x05, "ACCEPT-CHARSET=" },
+       { 0x06, "ALIGN='BOTTOM'" },
+       { 0x07, "ALIGN='CENTER'" },
+       { 0x08, "ALIGN='LEFT'" },
+       { 0x09, "ALIGN='MIDDLE'" },
+       { 0x0A, "ALIGN='RIGHT'" },
+       { 0x0B, "ALIGN='TOP'" },
+       { 0x0C, "ALT=" },
+       { 0x0D, "CONTENT=" },
+       { 0x0E, "DEFAULT=" },
+       { 0x0F, "DOMAIN=" },
+       { 0x10, "EMPTYOK='FALSE'" },
+       { 0x11, "EMPTYOK='TRUE'" },
+       { 0x12, "FORMAT=" },
+       { 0x13, "HEIGHT=" },
+       { 0x14, "HSPACE=" },
+       { 0x15, "IDEFAULT=" },
+       { 0x16, "IKEY=" },
+       { 0x17, "KEY=" },
+       { 0x18, "LABEL=" },
+       { 0x19, "LOCALSRC=" },
+       { 0x1A, "MAXLENGTH=" },
+       { 0x1B, "METHOD='GET'" },
+       { 0x1C, "METHOD='POST'" },
+       { 0x1D, "MODE='NOWRAP'" },
+       { 0x1E, "MODE='WRAP'" },
+       { 0x1F, "MULTIPLE='FALSE'" },
+       { 0x20, "MULTIPLE='TRUE'" },
+       { 0x21, "NAME=" },
+       { 0x22, "NEWCONTEXT='FALSE'" },
+       { 0x23, "NEWCONTEXT='TRUE'" },
+       { 0x24, "ONCLICK=" },
+       { 0x25, "ONENTERBACKWARD=" },
+       { 0x26, "ONENTERFORWARD=" },
+       { 0x27, "ONTIMER=" },
+       { 0x28, "OPTIONAL='FALSE'" },
+       { 0x29, "OPTIONAL='TRUE'" },
+       { 0x2A, "PATH=" },
+       { 0x2B, "POSTDATA=" },
+       { 0x2C, "PUBLIC='FALSE'" },
+       { 0x2D, "PUBLIC='TRUE'" },
+       { 0x2E, "SCHEME=" },
+       { 0x2F, "SENDREFERER='FALSE'" },
+       { 0x30, "SENDREFERER='TRUE'" },
+       { 0x31, "SIZE=" },
+       { 0x32, "SRC=" },
+       { 0x33, "STYLE='LIST'" },
+       { 0x34, "STYLE='SET'" },
+       { 0x35, "TABINDEX=" },
+       { 0x36, "TITLE=" },
+       { 0x37, "TYPE=" },
+       { 0x38, "TYPE='ACCEPT'" },
+       { 0x39, "TYPE='DELETE'" },
+       { 0x3A, "TYPE='HELP'" },
+       { 0x3B, "TYPE='PASSWORD'" },
+       { 0x3C, "TYPE='ONCLICK'" },
+       { 0x3D, "TYPE='ONENTERBACKWARD'" },
+       { 0x3E, "TYPE='ONENTERFORWARD'" },
+       { 0x3F, "TYPE='ONTIMER'" },
+       /* 0x40 -- 0x44 GLOBAL */
+       { 0x45, "TYPE='OPTIONS'" },
+       { 0x46, "TYPE='PREV'" },
+       { 0x47, "TYPE='RESET'" },
+       { 0x48, "TYPE='TEXT'" },
+       { 0x49, "TYPE='vnd.'" },
+       { 0x4A, "URL=" },
+       { 0x4B, "URL='http://'" },
+       { 0x4C, "URL='https://'" },
+       { 0x4D, "USER-AGENT=" },
+       { 0x4E, "VALUE=" },
+       { 0x4F, "VSPACE=" },
+       { 0x50, "WIDTH=" },
+       { 0x51, "xml:lang=" },
+
+       { 0x00, NULL }
+};
+
+/*****    Attribute Value tokens   *****/
+static const value_string wbxml_wmlc10_attrValue_cp0[] = {
+       /* 0x80 -- 0x84 GLOBAL */
+       { 0x85, "'.com/'" },
+       { 0x86, "'.edu/'" },
+       { 0x87, "'.net/'" },
+       { 0x88, "'.org/'" },
+       { 0x89, "'ACCEPT'" },
+       { 0x8A, "'BOTTOM'" },
+       { 0x8B, "'CLEAR'" },
+       { 0x8C, "'DELETE'" },
+       { 0x8D, "'HELP'" },
+       { 0x8E, "'http://'" },
+       { 0x8F, "'http://www.'" },
+       { 0x90, "'https://'" },
+       { 0x91, "'https://www.'" },
+       { 0x92, "'LIST'" },
+       { 0x93, "'MIDDLE'" },
+       { 0x94, "'NOWRAP'" },
+       { 0x95, "'ONCLICK'" },
+       { 0x96, "'ONENTERBACKWARD'" },
+       { 0x97, "'ONENTERFORWARD'" },
+       { 0x98, "'ONTIMER'" },
+       { 0x99, "'OPTIONS'" },
+       { 0x9A, "'PASSWORD'" },
+       { 0x9B, "'RESET'" },
+       { 0x9C, "'SET'" },
+       { 0x9D, "'TEXT'" },
+       { 0x9E, "'TOP'" },
+       { 0x9F, "'UNKNOWN'" },
+       { 0xA0, "'WRAP'" },
+       { 0xA1, "'www.'" },
+
+       { 0x00, NULL }
+};
+
+/***** Token code page aggregation *****/
+static const value_valuestring wbxml_wmlc10_global[] = {
+       { 0, wbxml_wmlc10_global_cp0 },
+       { 0, NULL }
+};
+
+static const value_valuestring wbxml_wmlc10_tags[] = {
+       { 0, wbxml_wmlc10_tags_cp0 },
+       { 0, NULL }
+};
+
+static const value_valuestring wbxml_wmlc10_attrStart[] = {
+       { 0, wbxml_wmlc10_attrStart_cp0 },
+       { 0, NULL }
+};
+
+static const value_valuestring wbxml_wmlc10_attrValue[] = {
+       { 0, wbxml_wmlc10_attrValue_cp0 },
+       { 0, NULL }
+};
+
+
+
+
+
+/* WML 1.1
+ * 
+ * Wireless Markup Language
+ ***************************************/
+
+/*****   Global extension tokens   *****/
+/* Same as in WML 1.0 */
+
+/*****         Tag tokens          *****/
+static const value_string wbxml_wmlc11_tags_cp0[] = {
+       /* 0x00 -- 0x04 GLOBAL */
+       /* 0x05 -- 0x1B */
+       { 0x1C, "a" },
+       { 0x1D, "td" },
+       { 0x1E, "tr" },
+       { 0x1F, "table" },
+       { 0x20, "p" },
+       { 0x21, "postfield" },
+       { 0x22, "anchor" },
+       { 0x23, "access" },
+       { 0x24, "b" },
+       { 0x25, "big" },
+       { 0x26, "br" },
+       { 0x27, "card" },
+       { 0x28, "do" },
+       { 0x29, "em" },
+       { 0x2A, "fieldset" },
+       { 0x2B, "go" },
+       { 0x2C, "head" },
+       { 0x2D, "i" },
+       { 0x2E, "img" },
+       { 0x2F, "input" },
+       { 0x30, "meta" },
+       { 0x31, "noop" },
+       { 0x32, "prev" },
+       { 0x33, "onevent" },
+       { 0x34, "optgroup" },
+       { 0x35, "option" },
+       { 0x36, "refresh" },
+       { 0x37, "select" },
+       { 0x38, "small" },
+       { 0x39, "strong" },
+       /* 0x3A */
+       { 0x3B, "template" },
+       { 0x3C, "timer" },
+       { 0x3D, "u" },
+       { 0x3E, "setvar" },
+       { 0x3F, "wml" },
+
+       { 0x00, NULL }
+};
+
+/*****    Attribute Start tokens   *****/
+static const value_string wbxml_wmlc11_attrStart_cp0[] = {
+       /* 0x00 -- 0x04 GLOBAL */
+       { 0x05, "accept-charset=" },
+       { 0x06, "align='bottom'" },
+       { 0x07, "align='center'" },
+       { 0x08, "align='left'" },
+       { 0x09, "align='middle'" },
+       { 0x0A, "align='right'" },
+       { 0x0B, "align='top'" },
+       { 0x0C, "alt=" },
+       { 0x0D, "content=" },
+       /* 0x0E */
+       { 0x0F, "domain=" },
+       { 0x10, "emptyok='false'" },
+       { 0x11, "emptyok='true'" },
+       { 0x12, "format=" },
+       { 0x13, "height=" },
+       { 0x14, "hspace=" },
+       { 0x15, "ivalue=" },
+       { 0x16, "iname=" },
+       /* 0x17 */
+       { 0x18, "label=" },
+       { 0x19, "localsrc=" },
+       { 0x1A, "maxlength=" },
+       { 0x1B, "method='get'" },
+       { 0x1C, "method='post'" },
+       { 0x1D, "mode='nowrap'" },
+       { 0x1E, "mode='wrap'" },
+       { 0x1F, "multiple='false'" },
+       { 0x20, "multiple='true'" },
+       { 0x21, "name=" },
+       { 0x22, "newcontext='false'" },
+       { 0x23, "newcontext='true'" },
+       { 0x24, "onpick=" },
+       { 0x25, "onenterbackward=" },
+       { 0x26, "onenterforward=" },
+       { 0x27, "ontimer=" },
+       { 0x28, "optional='false'" },
+       { 0x29, "optional='true'" },
+       { 0x2A, "path=" },
+       /* 0x2B -- 0x2D */
+       { 0x2E, "scheme=" },
+       { 0x2F, "sendreferer='false'" },
+       { 0x30, "sendreferer='true'" },
+       { 0x31, "size=" },
+       { 0x32, "src=" },
+       { 0x33, "ordered='false'" },
+       { 0x34, "ordered='true'" },
+       { 0x35, "tabindex=" },
+       { 0x36, "title=" },
+       { 0x37, "type=" },
+       { 0x38, "type='accept'" },
+       { 0x39, "type='delete'" },
+       { 0x3A, "type='help'" },
+       { 0x3B, "type='password'" },
+       { 0x3C, "type='onpick'" },
+       { 0x3D, "type='onenterbackward'" },
+       { 0x3E, "type='onenterforward'" },
+       { 0x3F, "type='ontimer'" },
+       /* 0x40 -- 0x44 GLOBAL */
+       { 0x45, "type='options'" },
+       { 0x46, "type='prev'" },
+       { 0x47, "type='reset'" },
+       { 0x48, "type='text'" },
+       { 0x49, "type='vnd.'" },
+       { 0x4A, "href=" },
+       { 0x4B, "href='http://'" },
+       { 0x4C, "href='https://'" },
+       { 0x4D, "value=" },
+       { 0x4E, "vspace=" },
+       { 0x4F, "width=" },
+       { 0x50, "xml:lang=" },
+       /* 0x51 */
+       { 0x52, "align=" },
+       { 0x53, "columns=" },
+       { 0x54, "class=" },
+       { 0x55, "id=" },
+       { 0x56, "forua='false'" },
+       { 0x57, "forua='true'" },
+       { 0x58, "src='http://'" },
+       { 0x59, "src='https://'" },
+       { 0x5A, "http-equiv=" },
+       { 0x5B, "http-equiv='Content-Type'" },
+       { 0x5C, "content='application/vnd.wap.wmlc;charset='" },
+       { 0x5D, "http-equiv='Expires'" },
+
+       { 0x00, NULL }
+};
+
+/*****    Attribute Value tokens   *****/
+static const value_string wbxml_wmlc11_attrValue_cp0[] = {
+       /* 0x80 -- 0x84 GLOBAL */
+       { 0x85, "'.com/'" },
+       { 0x86, "'.edu/'" },
+       { 0x87, "'.net/'" },
+       { 0x88, "'.org/'" },
+       { 0x89, "'accept'" },
+       { 0x8A, "'bottom'" },
+       { 0x8B, "'clear'" },
+       { 0x8C, "'delete'" },
+       { 0x8D, "'help'" },
+       { 0x8E, "'http://'" },
+       { 0x8F, "'http://www.'" },
+       { 0x90, "'https://'" },
+       { 0x91, "'https://www.'" },
+       /* 0x92 */
+       { 0x93, "'middle'" },
+       { 0x94, "'nowrap'" },
+       { 0x95, "'onpick'" },
+       { 0x96, "'onenterbackward'" },
+       { 0x97, "'onenterforward'" },
+       { 0x98, "'ontimer'" },
+       { 0x99, "'options'" },
+       { 0x9A, "'password'" },
+       { 0x9B, "'reset'" },
+       /* 0x9C */
+       { 0x9D, "'text'" },
+       { 0x9E, "'top'" },
+       { 0x9F, "'unknown'" },
+       { 0xA0, "'wrap'" },
+       { 0xA1, "'www.'" },
+
+       { 0x00, NULL }
+};
+
+/***** Token code page aggregation *****/
+static const value_valuestring wbxml_wmlc11_global[] = {
+       { 0, wbxml_wmlc10_global_cp0 }, /* Same as WML 1.0 */
+       { 0, NULL }
+};
+
+static const value_valuestring wbxml_wmlc11_tags[] = {
+       { 0, wbxml_wmlc11_tags_cp0 },
+       { 0, NULL }
+};
+
+static const value_valuestring wbxml_wmlc11_attrStart[] = {
+       { 0, wbxml_wmlc11_attrStart_cp0 },
+       { 0, NULL }
+};
+
+static const value_valuestring wbxml_wmlc11_attrValue[] = {
+       { 0, wbxml_wmlc11_attrValue_cp0 },
+       { 0, NULL }
+};
+
+
+
+
+
+/* WML 1.2
+ * 
+ * Wireless Markup Language
+ ***************************************/
+
+/*****   Global extension tokens   *****/
+/* Same as in WML 1.0 */
+
+/*****         Tag tokens          *****/
+static const value_string wbxml_wmlc12_tags_cp0[] = {
+       /* 0x00 -- 0x04 GLOBAL */
+       /* 0x05 -- 0x1A */
+       { 0x1B, "pre" },
+       { 0x1C, "a" },
+       { 0x1D, "td" },
+       { 0x1E, "tr" },
+       { 0x1F, "table" },
+       { 0x20, "p" },
+       { 0x21, "postfield" },
+       { 0x22, "anchor" },
+       { 0x23, "access" },
+       { 0x24, "b" },
+       { 0x25, "big" },
+       { 0x26, "br" },
+       { 0x27, "card" },
+       { 0x28, "do" },
+       { 0x29, "em" },
+       { 0x2A, "fieldset" },
+       { 0x2B, "go" },
+       { 0x2C, "head" },
+       { 0x2D, "i" },
+       { 0x2E, "img" },
+       { 0x2F, "input" },
+       { 0x30, "meta" },
+       { 0x31, "noop" },
+       { 0x32, "prev" },
+       { 0x33, "onevent" },
+       { 0x34, "optgroup" },
+       { 0x35, "option" },
+       { 0x36, "refresh" },
+       { 0x37, "select" },
+       { 0x38, "small" },
+       { 0x39, "strong" },
+       /* 0x3A */
+       { 0x3B, "template" },
+       { 0x3C, "timer" },
+       { 0x3D, "u" },
+       { 0x3E, "setvar" },
+       { 0x3F, "wml" },
+
+       { 0x00, NULL }
+};
+
+/*****    Attribute Start tokens   *****/
+static const value_string wbxml_wmlc12_attrStart_cp0[] = {
+       /* 0x00 -- 0x04 GLOBAL */
+       { 0x05, "accept-charset=" },
+       { 0x06, "align='bottom'" },
+       { 0x07, "align='center'" },
+       { 0x08, "align='left'" },
+       { 0x09, "align='middle'" },
+       { 0x0A, "align='right'" },
+       { 0x0B, "align='top'" },
+       { 0x0C, "alt=" },
+       { 0x0D, "content=" },
+       /* 0x0E */
+       { 0x0F, "domain=" },
+       { 0x10, "emptyok='false'" },
+       { 0x11, "emptyok='true'" },
+       { 0x12, "format=" },
+       { 0x13, "height=" },
+       { 0x14, "hspace=" },
+       { 0x15, "ivalue=" },
+       { 0x16, "iname=" },
+       /* 0x17 */
+       { 0x18, "label=" },
+       { 0x19, "localsrc=" },
+       { 0x1A, "maxlength=" },
+       { 0x1B, "method='get'" },
+       { 0x1C, "method='post'" },
+       { 0x1D, "mode='nowrap'" },
+       { 0x1E, "mode='wrap'" },
+       { 0x1F, "multiple='false'" },
+       { 0x20, "multiple='true'" },
+       { 0x21, "name=" },
+       { 0x22, "newcontext='false'" },
+       { 0x23, "newcontext='true'" },
+       { 0x24, "onpick=" },
+       { 0x25, "onenterbackward=" },
+       { 0x26, "onenterforward=" },
+       { 0x27, "ontimer=" },
+       { 0x28, "optional='false'" },
+       { 0x29, "optional='true'" },
+       { 0x2A, "path=" },
+       /* 0x2B -- 0x2D */
+       { 0x2E, "scheme=" },
+       { 0x2F, "sendreferer='false'" },
+       { 0x30, "sendreferer='true'" },
+       { 0x31, "size=" },
+       { 0x32, "src=" },
+       { 0x33, "ordered='false'" },
+       { 0x34, "ordered='true'" },
+       { 0x35, "tabindex=" },
+       { 0x36, "title=" },
+       { 0x37, "type=" },
+       { 0x38, "type='accept'" },
+       { 0x39, "type='delete'" },
+       { 0x3A, "type='help'" },
+       { 0x3B, "type='password'" },
+       { 0x3C, "type='onpick'" },
+       { 0x3D, "type='onenterbackward'" },
+       { 0x3E, "type='onenterforward'" },
+       { 0x3F, "type='ontimer'" },
+       /* 0x40 -- 0x44 GLOBAL */
+       { 0x45, "type='options'" },
+       { 0x46, "type='prev'" },
+       { 0x47, "type='reset'" },
+       { 0x48, "type='text'" },
+       { 0x49, "type='vnd.'" },
+       { 0x4A, "href=" },
+       { 0x4B, "href='http://'" },
+       { 0x4C, "href='https://'" },
+       { 0x4D, "value=" },
+       { 0x4E, "vspace=" },
+       { 0x4F, "width=" },
+       { 0x50, "xml:lang=" },
+       /* 0x51 */
+       { 0x52, "align=" },
+       { 0x53, "columns=" },
+       { 0x54, "class=" },
+       { 0x55, "id=" },
+       { 0x56, "forua='false'" },
+       { 0x57, "forua='true'" },
+       { 0x58, "src='http://'" },
+       { 0x59, "src='https://'" },
+       { 0x5A, "http-equiv=" },
+       { 0x5B, "http-equiv='Content-Type'" },
+       { 0x5C, "content='application/vnd.wap.wmlc;charset='" },
+       { 0x5D, "http-equiv='Expires'" },
+       { 0x5E, "accesskey=" },
+       { 0x5F, "enctype=" },
+       { 0x60, "enctype='application/x-www-form-urlencoded'" },
+       { 0x61, "enctype='multipart/form-data'" },
+
+       { 0x00, NULL }
+};
+
+/*****    Attribute Value tokens   *****/
+/* Same as in WML 1.1 */
+
+/***** Token code page aggregation *****/
+static const value_valuestring wbxml_wmlc12_global[] = {
+       { 0, wbxml_wmlc10_global_cp0 }, /* Same as WML 1.0 */
+       { 0, NULL }
+};
+
+static const value_valuestring wbxml_wmlc12_tags[] = {
+       { 0, wbxml_wmlc12_tags_cp0 },
+       { 0, NULL }
+};
+
+static const value_valuestring wbxml_wmlc12_attrStart[] = {
+       { 0, wbxml_wmlc12_attrStart_cp0 },
+       { 0, NULL }
+};
+
+static const value_valuestring wbxml_wmlc12_attrValue[] = {
+       { 0, wbxml_wmlc11_attrValue_cp0 }, /* Same as WML 1.1 */
+       { 0, NULL }
+};
+
+
+
+
+
+/* WML 1.3
+ * 
+ * Wireless Markup Language
+ ***************************************/
+
+/*****   Global extension tokens   *****/
+/* Same as in WML 1.0 */
+
+/*****         Tag tokens          *****/
+/* Same as in WML 1.2 */
+
+/*****    Attribute Start tokens   *****/
+static const value_string wbxml_wmlc13_attrStart_cp0[] = {
+       /* 0x00 -- 0x04 GLOBAL */
+       { 0x05, "accept-charset=" },
+       { 0x06, "align='bottom'" },
+       { 0x07, "align='center'" },
+       { 0x08, "align='left'" },
+       { 0x09, "align='middle'" },
+       { 0x0A, "align='right'" },
+       { 0x0B, "align='top'" },
+       { 0x0C, "alt=" },
+       { 0x0D, "content=" },
+       /* 0x0E */
+       { 0x0F, "domain=" },
+       { 0x10, "emptyok='false'" },
+       { 0x11, "emptyok='true'" },
+       { 0x12, "format=" },
+       { 0x13, "height=" },
+       { 0x14, "hspace=" },
+       { 0x15, "ivalue=" },
+       { 0x16, "iname=" },
+       /* 0x17 */
+       { 0x18, "label=" },
+       { 0x19, "localsrc=" },
+       { 0x1A, "maxlength=" },
+       { 0x1B, "method='get'" },
+       { 0x1C, "method='post'" },
+       { 0x1D, "mode='nowrap'" },
+       { 0x1E, "mode='wrap'" },
+       { 0x1F, "multiple='false'" },
+       { 0x20, "multiple='true'" },
+       { 0x21, "name=" },
+       { 0x22, "newcontext='false'" },
+       { 0x23, "newcontext='true'" },
+       { 0x24, "onpick=" },
+       { 0x25, "onenterbackward=" },
+       { 0x26, "onenterforward=" },
+       { 0x27, "ontimer=" },
+       { 0x28, "optional='false'" },
+       { 0x29, "optional='true'" },
+       { 0x2A, "path=" },
+       /* 0x2B -- 0x2D */
+       { 0x2E, "scheme=" },
+       { 0x2F, "sendreferer='false'" },
+       { 0x30, "sendreferer='true'" },
+       { 0x31, "size=" },
+       { 0x32, "src=" },
+       { 0x33, "ordered='false'" },
+       { 0x34, "ordered='true'" },
+       { 0x35, "tabindex=" },
+       { 0x36, "title=" },
+       { 0x37, "type=" },
+       { 0x38, "type='accept'" },
+       { 0x39, "type='delete'" },
+       { 0x3A, "type='help'" },
+       { 0x3B, "type='password'" },
+       { 0x3C, "type='onpick'" },
+       { 0x3D, "type='onenterbackward'" },
+       { 0x3E, "type='onenterforward'" },
+       { 0x3F, "type='ontimer'" },
+       /* 0x40 -- 0x44 GLOBAL */
+       { 0x45, "type='options'" },
+       { 0x46, "type='prev'" },
+       { 0x47, "type='reset'" },
+       { 0x48, "type='text'" },
+       { 0x49, "type='vnd.'" },
+       { 0x4A, "href=" },
+       { 0x4B, "href='http://'" },
+       { 0x4C, "href='https://'" },
+       { 0x4D, "value=" },
+       { 0x4E, "vspace=" },
+       { 0x4F, "width=" },
+       { 0x50, "xml:lang=" },
+       /* 0x51 */
+       { 0x52, "align=" },
+       { 0x53, "columns=" },
+       { 0x54, "class=" },
+       { 0x55, "id=" },
+       { 0x56, "forua='false'" },
+       { 0x57, "forua='true'" },
+       { 0x58, "src='http://'" },
+       { 0x59, "src='https://'" },
+       { 0x5A, "http-equiv=" },
+       { 0x5B, "http-equiv='Content-Type'" },
+       { 0x5C, "content='application/vnd.wap.wmlc;charset='" },
+       { 0x5D, "http-equiv='Expires'" },
+       { 0x5E, "accesskey=" },
+       { 0x5F, "enctype=" },
+       { 0x60, "enctype='application/x-www-form-urlencoded'" },
+       { 0x61, "enctype='multipart/form-data'" },
+       { 0x62, "xml:space='preserve'" },
+       { 0x63, "xml:space='default'" },
+       { 0x64, "cache-control='no-cache'" },
+
+       { 0x00, NULL }
+};
+
+/*****    Attribute Value tokens   *****/
+/* Same as in WML 1.1 */
+
+/***** Token code page aggregation *****/
+static const value_valuestring wbxml_wmlc13_global[] = {
+       { 0, wbxml_wmlc10_global_cp0 }, /* Same as WML 1.0 */
+       { 0, NULL }
+};
+
+static const value_valuestring wbxml_wmlc13_tags[] = {
+       { 0, wbxml_wmlc12_tags_cp0 },
+       { 0, NULL }
+};
+
+static const value_valuestring wbxml_wmlc13_attrStart[] = {
+       { 0, wbxml_wmlc13_attrStart_cp0 },
+       { 0, NULL }
+};
+
+static const value_valuestring wbxml_wmlc13_attrValue[] = {
+       { 0, wbxml_wmlc11_attrValue_cp0 }, /* Same as WML 1.1 */
+       { 0, NULL }
+};
+
+
+
+
+
+/* SI 1.0
+ * 
+ * Service Indication
+ ***************************************/
+
+/*****   Global extension tokens   *****/
+
+/*****         Tag tokens          *****/
+static const value_string wbxml_sic10_tags_cp0[] = {
+       /* 0x00 -- 0x04 GLOBAL */
+       { 0x05, "si" },
+       { 0x06, "indication" },
+       { 0x07, "info" },
+       { 0x08, "item" },
+
+       { 0x00, NULL }
+};
+
+/*****    Attribute Start tokens   *****/
+static const value_string wbxml_sic10_attrStart_cp0[] = {
+       /* 0x00 -- 0x04 GLOBAL */
+       { 0x05, "action='signal-none'" },
+       { 0x06, "action='signal-low'" },
+       { 0x07, "action='signal-medium'" },
+       { 0x08, "action='signal-high'" },
+       { 0x09, "action='delete'" },
+       { 0x0a, "created=" },
+       { 0x0b, "href=" },
+       { 0x0c, "href='http://'" },
+       { 0x0d, "href='http://www.'" },
+       { 0x0e, "href='https://'" },
+       { 0x0f, "href='https://www.'" },
+       { 0x10, "si-expires=" },
+       { 0x11, "si-id=" },
+       { 0x12, "class=" },
+
+       { 0x00, NULL }
+};
+
+/*****    Attribute Value tokens   *****/
+static const value_string wbxml_sic10_attrValue_cp0[] = {
+       /* 0x80 -- 0x84 GLOBAL */
+       { 0x85, "'.com/'" },
+       { 0x86, "'.edu/'" },
+       { 0x87, "'.net/'" },
+       { 0x88, "'.org/'" },
+
+       { 0x00, NULL }
+};
+
+/***** Token code page aggregation *****/
+static const value_valuestring wbxml_sic10_tags[] = {
+       { 0, wbxml_sic10_tags_cp0 },
+       { 0, NULL }
+};
+
+static const value_valuestring wbxml_sic10_attrStart[] = {
+       { 0, wbxml_sic10_attrStart_cp0 },
+       { 0, NULL }
+};
+
+static const value_valuestring wbxml_sic10_attrValue[] = {
+       { 0, wbxml_sic10_attrValue_cp0 },
+       { 0, NULL }
+};
+
+
+
+
+
+/* SL 1.0
+ * 
+ * Service Loading
+ ***************************************/
+
+/*****   Global extension tokens   *****/
+
+/*****         Tag tokens          *****/
+static const value_string wbxml_slc10_tags_cp0[] = {
+       /* 0x00 -- 0x04 GLOBAL */
+       { 0x05, "sl" },
+
+       { 0x00, NULL }
+};
+
+/*****    Attribute Start tokens   *****/
+static const value_string wbxml_slc10_attrStart_cp0[] = {
+       /* 0x00 -- 0x04 GLOBAL */
+       { 0x05, "action='execute-low'" },
+       { 0x06, "action='execute-high'" },
+       { 0x07, "action='cache'" },
+       { 0x08, "href=" },
+       { 0x09, "href='http://'" },
+       { 0x0a, "href='http://www.'" },
+       { 0x0b, "href='https://'" },
+       { 0x0c, "href='https://www.'" },
+
+       { 0x00, NULL }
+};
+
+/*****    Attribute Value tokens   *****/
+/* Same as in SI 1.0 */
+
+/***** Token code page aggregation *****/
+static const value_valuestring wbxml_slc10_tags[] = {
+       { 0, wbxml_slc10_tags_cp0 },
+       { 0, NULL }
+};
+
+static const value_valuestring wbxml_slc10_attrStart[] = {
+       { 0, wbxml_slc10_attrStart_cp0 },
+       { 0, NULL }
+};
+
+static const value_valuestring wbxml_slc10_attrValue[] = {
+       { 0, wbxml_sic10_attrValue_cp0 }, /* Same as SI 1.0 */
+       { 0, NULL }
+};
+
+
+
+
+
+/* CO 1.0
+ * 
+ * Cache Operation
+ ***************************************/
+
+/*****   Global extension tokens   *****/
+
+/*****         Tag tokens          *****/
+static const value_string wbxml_coc10_tags_cp0[] = {
+       /* 0x00 -- 0x04 GLOBAL */
+       { 0x05, "co" },
+       { 0x06, "invalidate-object" },
+       { 0x07, "invalidate-service" },
+
+       { 0x00, NULL }
+};
+
+/*****    Attribute Start tokens   *****/
+static const value_string wbxml_coc10_attrStart_cp0[] = {
+       /* 0x00 -- 0x04 GLOBAL */
+       { 0x05, "uri=" },
+       { 0x06, "uri='http://'" },
+       { 0x07, "uri='http://www.'" },
+       { 0x08, "uri='https://'" },
+       { 0x09, "uri='https://www.'" },
+
+       { 0x00, NULL }
+};
+
+/*****    Attribute Value tokens   *****/
+/* Same as in SI 1.0 */
+
+/***** Token code page aggregation *****/
+static const value_valuestring wbxml_coc10_tags[] = {
+       { 0, wbxml_coc10_tags_cp0 },
+       { 0, NULL }
+};
+
+static const value_valuestring wbxml_coc10_attrStart[] = {
+       { 0, wbxml_coc10_attrStart_cp0 },
+       { 0, NULL }
+};
+
+static const value_valuestring wbxml_coc10_attrValue[] = {
+       { 0, wbxml_sic10_attrValue_cp0 }, /* Same as SI 1.0 */
+       { 0, NULL }
+};
+
+
+
+
+
+/* PROV 1.0
+ *
+ * Client Provisioning
+ ***************************************/
+
+/*****   Global extension tokens   *****/
+
+/*****         Tag tokens          *****/
+static const value_string wbxml_provc10_tags_cp0[] = {
+       /* 0x00 -- 0x04 GLOBAL */
+       { 0x05, "wap-provisioningdoc" },
+       { 0x06, "characteristic" },
+       { 0x07, "parm" },
+
+       { 0x00, NULL }
+};
+
+/*****    Attribute Start tokens   *****/
+static const value_string wbxml_provc10_attrStart_cp0[] = {
+       /* 0x00 -- 0x04 GLOBAL */
+       { 0x05, "name=" },
+       { 0x06, "value=" },
+       { 0x07, "name='NAME'" },
+       { 0x08, "name='NAP-ADDRESS'" },
+       { 0x09, "name='NAP-ADDRTYPE'" },
+       { 0x0A, "name='CALLTYPE'" },
+       { 0x0B, "name='VALIDUNTIL'" },
+       { 0x0C, "name='AUTHTYPE'" },
+       { 0x0D, "name='AUTHNAME'" },
+       { 0x0E, "name='AUTHSECRET'" },
+       { 0x0F, "name='LINGER'" },
+       { 0x10, "name='BEARER'" },
+       { 0x11, "name='NAPID'" },
+       { 0x12, "name='COUNTRY'" },
+       { 0x13, "name='NETWORK'" },
+       { 0x14, "name='INTERNET'" },
+       { 0x15, "name='PROXY-ID'" },
+       { 0x16, "name='PROXY-PROVIDER-ID'" },
+       { 0x17, "name='DOMAIN'" },
+       { 0x18, "name='PROVURL'" },
+       { 0x19, "name='PXAUTH-TYPE'" },
+       { 0x1A, "name='PXAUTH-ID'" },
+       { 0x1B, "name='PXAUTH-PW'" },
+       { 0x1C, "name='STARTPAGE'" },
+       { 0x1D, "name='BASAUTH-ID'" },
+       { 0x1E, "name='BASAUTH-PW'" },
+       { 0x1F, "name='PUSHENABLED'" },
+       { 0x20, "name='PXADDR'" },
+       { 0x21, "name='PXADDRTYPE'" },
+       { 0x22, "name='TO-NAPID'" },
+       { 0x23, "name='PORTNBR'" },
+       { 0x24, "name='SERVICE'" },
+       { 0x25, "name='LINKSPEED'" },
+       { 0x26, "name='DNLINKSPEED'" },
+       { 0x27, "name='LOCAL-ADDR'" },
+       { 0x28, "name='LOCAL-ADDRTYPE'" },
+       { 0x29, "name='CONTEXT-ALLOW'" },
+       { 0x2A, "name='TRUST'" },
+       { 0x2B, "name='MASTER'" },
+       { 0x2C, "name='SID'" },
+       { 0x2D, "name='SOC'" },
+       { 0x2E, "name='WSP-VERSION'" },
+       { 0x2F, "name='PHYSICAL-PROXY-ID'" },
+       { 0x30, "name='CLIENT-ID'" },
+       { 0x31, "name='DELIVERY-ERR-SDU'" },
+       { 0x32, "name='DELIVERY-ORDER'" },
+       { 0x33, "name='TRAFFIC-CLASS'" },
+       { 0x34, "name='MAX-SDU-SIZE'" },
+       { 0x35, "name='MAX-BITRATE-UPLINK'" },
+       { 0x36, "name='MAX-BITRATE-DNLINK'" },
+       { 0x37, "name='RESIDUAL-BER'" },
+       { 0x38, "name='SDU-ERROR-RATIO'" },
+       { 0x39, "name='TRAFFIC-HANDL-PRIO'" },
+       { 0x3A, "name='TRANSFER-DELAY'" },
+       { 0x3B, "name='GUARANTEED-BITRATE-UPLINK'" },
+       { 0x3C, "name='GUARANTEED-BITRATE-DNLINK'" },
+       /* 0x3D -- 0x3F */
+       /* 0x40 -- 0x44 GLOBAL */
+       { 0x45, "version=" },
+       { 0x46, "version='1.0'" },
+       /* 0x47 -- 0x4F */
+       { 0x50, "type=" },
+       { 0x51, "type='PXLOGICAL'" },
+       { 0x52, "type='PXPHYSICAL'" },
+       { 0x53, "type='PORT'" },
+       { 0x54, "type='VALIDITY'" },
+       { 0x55, "type='NAPDEF'" },
+       { 0x56, "type='BOOTSTRAP'" },
+       { 0x57, "type='VENDORCONFIG'" },
+       { 0x58, "type='CLIENTIDENTITY'" },
+       { 0x59, "type='PXAUTHINFO'" },
+       { 0x5A, "type='NAPAUTHINFO'" },
+
+       { 0x00, NULL }
+};
+
+/*****    Attribute Start tokens   *****/
+static const value_string wbxml_provc10_attrValue_cp0[] = {
+       /* 0x80 -- 0x84 GLOBAL */
+       { 0x85, "'IPV4'" },
+       { 0x86, "'IPV6'" },
+       { 0x87, "'E164'" },
+       { 0x88, "'ALPHA'" },
+       { 0x89, "'APN'" },
+       { 0x8A, "'SCODE'" },
+       { 0x8B, "'TETRA-ITSI'" },
+       { 0x8C, "'MAN'" },
+       /* 0x8D -- 0x8F */
+       { 0x90, "'ANALOG-MODEM'" },
+       { 0x91, "'V.120'" },
+       { 0x92, "'V.110'" },
+       { 0x93, "'X.31'" },
+       { 0x94, "'BIT-TRANSPARENT'" },
+       { 0x95, "'DIRECT-ASYNCHRONOUS-DATA-SERVICE'" },
+       /* 0x96 -- 0x99 */
+       { 0x9A, "'PAP'" },
+       { 0x9B, "'CHAP'" },
+       { 0x9C, "'HTTP-BASIC'" },
+       { 0x9D, "'HTTP-DIGEST'" },
+       { 0x9E, "'WTLS-SS'" },
+       /* 0x9F -- 0xA1 */
+       { 0xA2, "'GSM-USSD'" },
+       { 0xA3, "'GSM-SMS'" },
+       { 0xA4, "'ANSI-136-GUTS'" },
+       { 0xA5, "'IS-95-CDMA-SMS'" },
+       { 0xA6, "'IS-95-CDMA-CSD'" },
+       { 0xA7, "'IS-95-CDMA-PACKET'" },
+       { 0xA8, "'ANSI-136-CSD'" },
+       { 0xA9, "'ANSI-136-GPRS'" },
+       { 0xAA, "'GSM-CSD'" },
+       { 0xAB, "'GSM-GPRS'" },
+       { 0xAC, "'AMPS-CDPD'" },
+       { 0xAD, "'PDC-CSD'" },
+       { 0xAE, "'PDC-PACKET'" },
+       { 0xAF, "'IDEN-SMS'" },
+       { 0xB0, "'IDEN-CSD'" },
+       { 0xB1, "'IDEN-PACKET'" },
+       { 0xB2, "'FLEX/REFLEX'" },
+       { 0xB3, "'PHS-SMS'" },
+       { 0xB4, "'PHS-CSD'" },
+       { 0xB5, "'TETRA-SDS'" },
+       { 0xB6, "'TETRA-PACKET'" },
+       { 0xB7, "'ANSI-136-GHOST'" },
+       { 0xB8, "'MOBITEX-MPAK'" },
+       /* 0xB9 -- 0xBF */
+       /* 0xC0 -- 0xC4 GLOBAL */
+       { 0xC5, "'AUTOBAUDING'" },
+       /* 0xC6 -- 0xC9 */
+       { 0xCA, "'CL-WSP'" },
+       { 0xCB, "'CO-WSP'" },
+       { 0xCC, "'CL-SEC-WSP'" },
+       { 0xCD, "'CO-SEC-WSP'" },
+       { 0xCE, "'CL-SEC-WTA'" },
+       { 0xCF, "'CO-SEC-WTA'" },
+
+       { 0x00, NULL }
+};
+
+/***** Token code page aggregation *****/
+static const value_valuestring wbxml_provc10_tags[] = {
+       { 0, wbxml_provc10_tags_cp0 },
+       { 0, NULL }
+};
+
+static const value_valuestring wbxml_provc10_attrStart[] = {
+       { 0, wbxml_provc10_attrStart_cp0 },
+       { 0, NULL }
+};
+
+static const value_valuestring wbxml_provc10_attrValue[] = {
+       { 0, wbxml_provc10_attrValue_cp0 },
+       { 0, NULL }
+};
+
+
+
+
+
+/* EMN 1.0
+ * 
+ * Email Notification
+ ***************************************/
+
+/*****   Global extension tokens   *****/
+
+/*****         Tag tokens          *****/
+static const value_string wbxml_emnc10_tags_cp0[] = {
+       /* 0x00 -- 0x04 GLOBAL */
+       { 0x05, "emn" },
+
+       { 0x00, NULL }
+};
+
+/*****    Attribute Start tokens   *****/
+static const value_string wbxml_emnc10_attrStart_cp0[] = {
+       /* 0x00 -- 0x04 GLOBAL */
+       { 0x05, "timestamp=" },
+       { 0x06, "mailbox=" },
+       { 0x07, "mailbox='mailat:'" },
+       { 0x08, "mailbox='pop://'" },
+       { 0x09, "mailbox='imap://'" },
+       { 0x0a, "mailbox='http://'" },
+       { 0x0b, "mailbox='http://www.'" },
+       { 0x0c, "mailbox='https://'" },
+       { 0x0D, "mailbox='https://www.'" },
+
+       { 0x00, NULL }
+};
+
+/*****    Attribute Value tokens   *****/
+/* Same as in SI 1.0 */
+
+/***** Token code page aggregation *****/
+static const value_valuestring wbxml_emnc10_tags[] = {
+       { 0, wbxml_emnc10_tags_cp0 },
+       { 0, NULL }
+};
+
+static const value_valuestring wbxml_emnc10_attrStart[] = {
+       { 0, wbxml_emnc10_attrStart_cp0 },
+       { 0, NULL }
+};
+
+static const value_valuestring wbxml_emnc10_attrValue[] = {
+       { 0, wbxml_sic10_attrValue_cp0 }, /* Same as SI 1.0 */
+       { 0, NULL }
+};
+
+
+
+
+
+/* SyncML 1.0
+ * 
+ * SyncML Representation Protocol
+ ***************************************/
+
+/*****   Global extension tokens   *****/
+
+/*****         Tag tokens          *****/
+static const value_string wbxml_syncmlc10_tags_cp0[] = { /* SyncML 1.0 */
+       /* 0x00 -- 0x04 GLOBAL */
+       { 0x05, "Add" },
+       { 0x06, "Alert" },
+       { 0x07, "Archive" },
+       { 0x08, "Atomic" },
+       { 0x09, "Chal" },
+       { 0x0A, "Cmd" },
+       { 0x0B, "CmdID" },
+       { 0x0C, "CmdRef" },
+       { 0x0D, "Copy" },
+       { 0x0E, "Cred" },
+       { 0x0F, "Data" },
+       { 0x10, "Delete" },
+       { 0x11, "Exec" },
+       { 0x12, "Final" },
+       { 0x13, "Get" },
+       { 0x14, "Item" },
+       { 0x15, "Lang" },
+       { 0x16, "LocName" },
+       { 0x17, "LocURI" },
+       { 0x18, "Map" },
+       { 0x19, "MapItem" },
+       { 0x1A, "Meta" },
+       { 0x1B, "MsgID" },
+       { 0x1C, "MsgRef" },
+       { 0x1D, "NoResp" },
+       { 0x1E, "NoResults" },
+       { 0x1F, "Put" },
+       { 0x20, "Replace" },
+       { 0x21, "RespURI" },
+       { 0x22, "Results" },
+       { 0x23, "Search" },
+       { 0x24, "Sequence" },
+       { 0x25, "SessionID" },
+       { 0x26, "SftDel" },
+       { 0x27, "Source" },
+       { 0x28, "SourceRef" },
+       { 0x29, "Status" },
+       { 0x2A, "Sync" },
+       { 0x2B, "SyncBody" },
+       { 0x2C, "SyncHdr" },
+       { 0x2D, "SyncML" },
+       { 0x2E, "Target" },
+       { 0x2F, "TargetRef" },
+       /* 0x30 - Reserved */
+       { 0x31, "VerDTD" },
+       { 0x32, "VerProto" },
+
+       { 0x00, NULL }
+};
+
+static const value_string wbxml_syncmlc10_tags_cp1[] = { /* MetInf 1.0 */
+       /* 0x00 -- 0x04 GLOBAL */
+       { 0x05, "Anchor" },
+       { 0x06, "EMI" },
+       { 0x07, "Format" },
+       { 0x08, "FreeID" },
+       { 0x09, "FreeMem" },
+       { 0x0A, "Last" },
+       { 0x0B, "Mark" },
+       { 0x0C, "MaxMsgSize" },
+       { 0x0D, "Mem" },
+       { 0x0E, "MetInf" },
+       { 0x0F, "Next" },
+       { 0x10, "NextNonce" },
+       { 0x11, "SharedMem" },
+       { 0x12, "Size" },
+       { 0x13, "Type" },
+       { 0x14, "Version" },
+
+       { 0x00, NULL }
+};
+
+/*****    Attribute Start tokens   *****/
+
+/*****    Attribute Value tokens   *****/
+
+/***** Token code page aggregation *****/
+static const value_valuestring wbxml_syncmlc10_tags[] = {
+       { 0, wbxml_syncmlc10_tags_cp0 }, /* -//SYNCML//DTD SyncML 1.0//EN */
+       { 0, wbxml_syncmlc10_tags_cp1 }, /* -//SYNCML//DTD MetInf 1.0//EN */
+       { 0, NULL }
+};
 
 
-/* Parse data while in ATTR state
+
+
+
+/* SyncML 1.1
+ * 
+ * SyncML Representation Protocol
+ ***************************************/
+
+/*****   Global extension tokens   *****/
+
+/*****         Tag tokens          *****/
+static const value_string wbxml_syncmlc11_tags_cp0[] = { /* SyncML 1.1 */
+       /* 0x00 -- 0x04 GLOBAL */
+       { 0x05, "Add" },
+       { 0x06, "Alert" },
+       { 0x07, "Archive" },
+       { 0x08, "Atomic" },
+       { 0x09, "Chal" },
+       { 0x0a, "Cmd" },
+       { 0x0b, "CmdID" },
+       { 0x0c, "CmdRef" },
+       { 0x0d, "Copy" },
+       { 0x0e, "Cred" },
+       { 0x0f, "Data" },
+       { 0x10, "Delete" },
+       { 0x11, "Exec" },
+       { 0x12, "Final" },
+       { 0x13, "Get" },
+       { 0x14, "Item" },
+       { 0x15, "Lang" },
+       { 0x16, "LocName" },
+       { 0x17, "LocURI" },
+       { 0x18, "Map" },
+       { 0x19, "MapItem" },
+       { 0x1a, "Meta" },
+       { 0x1b, "MsgID" },
+       { 0x1c, "MsgRef" },
+       { 0x1d, "NoResp" },
+       { 0x1e, "NoResults" },
+       { 0x1f, "Put" },
+       { 0x20, "Replace" },
+       { 0x21, "RespURI" },
+       { 0x22, "Results" },
+       { 0x23, "Search" },
+       { 0x24, "Sequence" },
+       { 0x25, "SessionID" },
+       { 0x26, "SftDel" },
+       { 0x27, "Source" },
+       { 0x28, "SourceRef" },
+       { 0x29, "Status" },
+       { 0x2a, "Sync" },
+       { 0x2b, "SyncBody" },
+       { 0x2c, "SyncHdr" },
+       { 0x2d, "SyncML" },
+       { 0x2e, "Target" },
+       { 0x2f, "TargetRef" },
+       /* 0x30 - Reserved */
+       { 0x31, "VerDTD" },
+       { 0x32, "VerProto" },
+       { 0x33, "NumberOfChanges" },
+       { 0x34, "MoreData" },
+
+       { 0x00, NULL }
+};
+
+static const value_string wbxml_syncmlc11_tags_cp1[] = { /* MetInf 1.1 */
+       /* 0x00 -- 0x04 GLOBAL */
+       { 0x05, "Anchor" },
+       { 0x06, "EMI" },
+       { 0x07, "Format" },
+       { 0x08, "FreeID" },
+       { 0x09, "FreeMem" },
+       { 0x0A, "Last" },
+       { 0x0B, "Mark" },
+       { 0x0C, "MaxMsgSize" },
+       { 0x0D, "Mem" },
+       { 0x0E, "MetInf" },
+       { 0x0F, "Next" },
+       { 0x10, "NextNonce" },
+       { 0x11, "SharedMem" },
+       { 0x12, "Size" },
+       { 0x13, "Type" },
+       { 0x14, "Version" },
+       { 0x15, "MaxObjSize" },
+
+       { 0x00, NULL }
+};
+
+/*****    Attribute Start tokens   *****/
+
+/*****    Attribute Value tokens   *****/
+
+/***** Token code page aggregation *****/
+static const value_valuestring wbxml_syncmlc11_tags[] = {
+       { 0, wbxml_syncmlc11_tags_cp0 }, /* -//SYNCML//DTD SyncML 1.1//EN */
+       { 0, wbxml_syncmlc11_tags_cp1 }, /* -//SYNCML//DTD MetInf 1.1//EN */
+       { 0, NULL }
+};
+
+
+
+
+
+/* CHANNEL 1.0
+ * 
+ * WTA Channel
+ ***************************************/
+
+/*****   Global extension tokens   *****/
+
+/*****         Tag tokens          *****/
+static const value_string wbxml_channelc10_tags_cp0[] = {
+       /* 0x00 -- 0x04 GLOBAL */
+       { 0x05, "channel" },
+       { 0x06, "title" },
+       { 0x07, "abstract" },
+       { 0x08, "resource" },
+
+       { 0x00, NULL }
+};
+
+/*****    Attribute Start tokens   *****/
+static const value_string wbxml_channelc10_attrStart_cp0[] = {
+       /* 0x00 -- 0x04 GLOBAL */
+       { 0x05, "maxspace" },
+       { 0x06, "base" },
+       { 0x07, "href" },
+       { 0x08, "href='http://'" },
+       { 0x09, "href='https://'" },
+       { 0x0A, "lastmod" },
+       { 0x0B, "etag" },
+       { 0x0C, "md5" },
+       { 0x0D, "success" },
+       { 0x0E, "success='http://'" },
+       { 0x0F, "success='https://'" },
+       { 0x10, "failure" },
+       { 0x11, "failure='http://'" },
+       { 0x12, "failure='https://'" },
+       { 0x13, "EventId" },
+
+       { 0x00, NULL }
+};
+
+/*****    Attribute Value tokens   *****/
+
+/***** Token code page aggregation *****/
+static const value_valuestring wbxml_channelc10_tags[] = {
+       { 0, wbxml_channelc10_tags_cp0 },
+       { 0, NULL }
+};
+
+static const value_valuestring wbxml_channelc10_attrStart[] = {
+       { 0, wbxml_channelc10_attrStart_cp0 },
+       { 0, NULL }
+};
+
+
+
+
+
+/********************** WBXML token mapping aggregation **********************/
+
+
+/* The following structure links content types to their token mapping and
+ * contains arrays of pointers to value_string arrays (one per code page).
  */
-void
-parse_wbxml_attribute_list (proto_tree *tree, tvbuff_t *tvb, guint32 offset,
-               guint32 str_tbl, guint8 level, guint8 *codepage_attr, guint32 *parsed_length);
+typedef struct _wbxml_token_map {
+       const guint32 publicid;  /* WBXML DTD number - see WINA */
+       const guint8 defined;    /* Are there mapping tables defined */
+       const value_valuestring *global;     /* Global token map */
+       const value_valuestring *tags;       /* Tag token map */
+       const value_valuestring *attrStart;  /* Attribute Start token map */
+       const value_valuestring *attrValue;  /* Attribute Value token map */
+} wbxml_token_map;
+
+static const wbxml_token_map *wbxml_content_map (guint32 publicid);
+
+/**
+ ** Aggregation of content type and aggregated code pages
+ ** Content type map lookup will stop at the 1st entry with 2nd member = FALSE
+ **/
+static const wbxml_token_map map[] = {
+#ifdef Test_the_WBXML_parser_without_token_mappings
+       { 0, FALSE, NULL, NULL, NULL, NULL },
+#endif
+       { 0x02, TRUE, /* WML 1.0 */
+               wbxml_wmlc10_global,
+               wbxml_wmlc10_tags,
+               wbxml_wmlc10_attrStart,
+               wbxml_wmlc10_attrValue
+       },
+#ifdef remove_directive_and_set_TRUE_if_mapping_available
+       { 0x03, FALSE, /* WTA 1.0 (deprecated) */
+               NULL, NULL, NULL, NULL
+       },
+#endif
+       { 0x04, TRUE, /* WML 1.1 */
+               wbxml_wmlc11_global,
+               wbxml_wmlc11_tags,
+               wbxml_wmlc11_attrStart,
+               wbxml_wmlc11_attrValue
+       },
+       { 0x05, TRUE, /* SI 1.0 */
+               NULL, /* wbxml_sic10_global - does not exist */
+               wbxml_sic10_tags,
+               wbxml_sic10_attrStart,
+               wbxml_sic10_attrValue
+       },
+       { 0x06, TRUE, /* SL 1.0 */
+               NULL, /* wbxml_slc10_global - does not exist */
+               wbxml_slc10_tags,
+               wbxml_slc10_attrStart,
+               wbxml_slc10_attrValue
+       },
+       { 0x07, TRUE, /* CO 1.0 */
+               NULL, /* wbxml_coc10_global - does not exist */
+               wbxml_coc10_tags,
+               wbxml_coc10_attrStart,
+               wbxml_coc10_attrValue
+       },
+       { 0x08, TRUE, /* CHANNEL 1.0 (deprecated) */
+               NULL, /* wbxml_channelc10_global - does not exist */
+               wbxml_channelc10_tags,
+               wbxml_channelc10_attrStart,
+               NULL, /* wbxml_channelc10_attrValue - does not exist */
+       },
+       { 0x09, TRUE, /* WML 1.2 */
+               wbxml_wmlc12_global,
+               wbxml_wmlc12_tags,
+               wbxml_wmlc12_attrStart,
+               wbxml_wmlc12_attrValue
+       },
+       { 0x0A, TRUE, /* WML 1.3 */
+               wbxml_wmlc13_global,
+               wbxml_wmlc13_tags,
+               wbxml_wmlc13_attrStart,
+               wbxml_wmlc13_attrValue
+       },
+       { 0x0B, TRUE, /* PROV 1.0 */
+               NULL, /* wbxml_provc10_global - does not exist */
+               wbxml_provc10_tags,
+               wbxml_provc10_attrStart,
+               wbxml_provc10_attrValue
+       },
+#ifdef remove_directive_and_set_TRUE_if_mapping_available
+       { 0x0C, FALSE, /* WTA-WML 1.2 */
+               NULL, NULL, NULL, NULL
+       },
+#endif
+       { 0x0D, TRUE, /* EMN 1.0 */
+               NULL, /* wbxml_emnc10_global - does not exist */
+               wbxml_emnc10_tags,
+               wbxml_emnc10_attrStart,
+               wbxml_emnc10_attrValue
+       },
+#ifdef remove_directive_and_set_TRUE_if_mapping_available
+       { 0x0E, FALSE, /* DRMREL 1.0 */
+               NULL, NULL, NULL, NULL
+       },
+#endif
+       { 0x0FD1, TRUE, /* SyncML 1.0 */
+               NULL, /* wbxml_syncmlc10_global - does not exist */
+               wbxml_syncmlc10_tags,
+               NULL, /* wbxml_syncmlc10_attrStart - does not exist */
+               NULL, /* wbxml_syncmlc10_attrValue - does not exist */
+       },
+       { 0x0FD3, TRUE, /* SyncML 1.1 */
+               NULL, /* wbxml_syncmlc11_global - does not exist */
+               wbxml_syncmlc11_tags,
+               NULL, /* wbxml_syncmlc11_attrStart - does not exist */
+               NULL, /* wbxml_syncmlc11_attrValue - does not exist */
+       },
+       { 0x1108, TRUE, /* Phone.com - WML+ 1.1 */
+               /* Note: I assumed WML+ 1.1 would be not that different from WML 1.1,
+                *       the real mapping should come from Phone.com (OpenWave)! */
+               wbxml_wmlc11_global, /* Not 100% true */
+               wbxml_wmlc11_tags, /* Not 100% true */
+               wbxml_wmlc11_attrStart, /* Not 100% true */
+               wbxml_wmlc11_attrValue /* Not 100% true */
+       },
+       { 0x110D, TRUE, /* Phone.com - WML+ 1.3 */
+               /* Note: I assumed WML+ 1.3 would be not that different from WML 1.3,
+                *       the real mapping should come from Phone.com (OpenWave)! */
+               wbxml_wmlc13_global, /* Not 100% true */
+               wbxml_wmlc13_tags, /* Not 100% true */
+               wbxml_wmlc13_attrStart, /* Not 100% true */
+               wbxml_wmlc13_attrValue /* Not 100% true */
+       },
+       
+       { 0, FALSE, NULL, NULL, NULL, NULL }
+};
 
 
-/* Parse data while in ATTR state;
- * interpret tokens as defined by content type
+/* WBXML content token mapping depends on the following parameters:
+ *   - Content type (guint32)
+ *   - Token type (global, tags, attrStart, attrValue)
+ *   - Code page for tag and attribute
+ *
+ * This results in the following steps:
+ *   1. Retrieve content type mapping
+ *   2. If exists, retrieve token type mapping
+ *   3. If exists, retrieve required code page
+ *   4. If exists, retrieve token mapping
  */
-void
-parse_wbxml_attribute_list_defined (proto_tree *tree, tvbuff_t *tvb, guint32 offset,
-               guint32 str_tbl, guint8 level, guint8 *codepage_attr, guint32 *parsed_length,
-               const wbxml_mapping_table *map);
 
+/* Return token mapping for a given content mapping entry. */
+static const char *
+map_token (const value_valuestring *token_map, guint8 codepage, guint8 token) {
+       const value_string *vs;
+       const char *s;
+
+       if (token_map) { /* Found map */
+               if ((vs = val_to_valstr (codepage, token_map))) {
+                       /* Found codepage map */
+                       s = match_strval (token, vs);
+                       if (s) /* Found valid token */
+                                       return s;
+                       /* No valid token mapping in specified code page of token map */
+                       return "(Requested token not defined for this content type)";
+               }
+               /* There is no token map entry for the requested code page */
+               return "(Requested token code page not defined for this content type)";
+       }
+       /* The token map does not exist */
+       return "(Requested token map not defined for this content type)";
+}
 
 
-/* "INLINE" functions */
+/* Returns a pointer to the WBXML token map for the given WBXML public
+ * identifier value (see WINA for a table with defined identifiers). */
+static const wbxml_token_map *wbxml_content_map (guint32 publicid) {
+       gint i = 0;
 
-/* Return a pointer to the string in the string table.
- * Can also be hacked for inline string retrieval.
- */
-const char*
-strtbl_lookup (tvbuff_t *tvb, guint32 str_tbl, guint32 offset, guint32 *len)
-{
-       if (len) { /* The "hack" call for inline string reading */
-               *len = tvb_strsize (tvb, str_tbl+offset);
-               return tvb_get_ptr (tvb, str_tbl+offset, *len);
-       } else { /* Normal string table reading */
-               return tvb_get_ptr (tvb, str_tbl+offset, tvb_strsize (tvb, str_tbl+offset));
+       while (map[i].defined) {
+               if (map[i].publicid == publicid)
+                       return &(map[i]);
+               i++;
        }
+       return NULL;
 }
 
 
+/************************** Function prototypes **************************/
+
+
+static void
+dissect_wbxml(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
+
+void
+proto_register_wbxml(void);
+
+/* Parse and display the WBXML string table */
+static void
+show_wbxml_string_table (proto_tree *tree, tvbuff_t *tvb, guint32 str_tbl,
+               guint32 str_tbl_len);
+
+/* Parse data while in STAG state */
+static void
+parse_wbxml_tag (proto_tree *tree, tvbuff_t *tvb, guint32 offset,
+               guint32 str_tbl, guint8 *level,
+               guint32 *parsed_length);
+
+/* Parse data while in STAG state;
+ * interpret tokens as defined by content type */
+static void
+parse_wbxml_tag_defined (proto_tree *tree, tvbuff_t *tvb, guint32 offset,
+               guint32 str_tbl, guint8 *level,
+               guint32 *parsed_length,
+               const wbxml_token_map *map);
+
+/* Parse data while in ATTR state */
+static void
+parse_wbxml_attribute_list (proto_tree *tree, tvbuff_t *tvb,
+               guint32 offset, guint32 str_tbl, guint8 level,
+               guint32 *parsed_length);
+
+/* Parse data while in ATTR state;
+ * interpret tokens as defined by content type */
+static void
+parse_wbxml_attribute_list_defined (proto_tree *tree, tvbuff_t *tvb,
+               guint32 offset, guint32 str_tbl, guint8 level,
+               guint32 *parsed_length,
+               const wbxml_token_map *map);
+
+
+/****************** WBXML protocol dissection functions ******************/
+
 
 /* Code to actually dissect the packets */
 static void
 dissect_wbxml(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 {
-
-/* Set up structures needed to add the protocol subtree and manage it */
+       /* Set up structures needed to add the protocol subtree and manage it */
        proto_item *ti;
-       proto_tree *wbxml_tree;
-       proto_tree *wbxml_content_tree;
+       proto_tree *wbxml_tree; /* Main WBXML tree */
+       proto_tree *wbxml_str_tbl_tree; /* String table subtree */
+       proto_tree *wbxml_content_tree; /* Content subtree */
        guint8 version;
        guint offset = 0;
-       const char *token;
        guint32 len;
        guint32 charset=0;
        guint32 charset_len;
@@ -166,10 +1845,9 @@ dissect_wbxml(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
        guint32 publicid_index = 0;
        guint32 publicid_len;
        guint32 str_tbl;
-       guint32 str_len;
+       guint32 str_tbl_len;
        guint8 level = 0; /* WBXML recursion level */
-       guint8 codepage_stag = 0; /* Initial codepage in state = STAG */
-       guint8 codepage_attr = 0; /* Initial codepage in state = ATTR */
+       const wbxml_token_map *content_map = NULL;
 
        /* WBXML format
         * 
@@ -191,6 +1869,10 @@ dissect_wbxml(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
                        return;
        }
 
+       if (check_col(pinfo->cinfo, COL_INFO))
+               col_append_fstr(pinfo->cinfo, COL_INFO, " (WBXML %s:",
+                               match_strval (version, vals_wbxml_versions));
+
        /* In the interest of speed, if "tree" is NULL, don't do any work not
           necessary to generate protocol tree items. */
        if ( tree ) {
@@ -205,6 +1887,9 @@ dissect_wbxml(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
                /* Public ID */
                publicid = tvb_get_guintvar(tvb, 1, &publicid_len);
                if (publicid) { /* Known Public ID */
+                       if (check_col(pinfo->cinfo, COL_INFO))
+                               col_append_fstr(pinfo->cinfo, COL_INFO, " Public ID \"%s\")",
+                                               match_strval (publicid, vals_wbxml_public_ids));
                        proto_tree_add_uint(wbxml_tree, hf_wbxml_public_id_known,
                                        tvb, 1, publicid_len, publicid);
                } else { /* Public identifier in string table */
@@ -231,27 +1916,40 @@ dissect_wbxml(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
                                break;
                }
 
-               /* String table */
-               str_len = tvb_get_guintvar (tvb, offset, &len); /* Length of string table */
+               /* String table: read string table length in bytes */
+               str_tbl_len = tvb_get_guintvar (tvb, offset, &len);
                str_tbl = offset + len; /* Start of 1st string in string table */
 
-
-               /* Now we can add public ID, charset (if available), and string table */
+               /* Now we can add public ID, charset (if available),
+                * and string table */
                if ( ! publicid ) { /* Read Public ID from string table */
-                       token = strtbl_lookup (tvb, str_tbl, publicid_index, NULL);
-                       proto_tree_add_string (wbxml_tree, hf_wbxml_public_id_literal,
-                                       tvb, 1, publicid_len, token?token:"[NULL STRING]");
+                       len = tvb_strsize (tvb, str_tbl+publicid_index);
+                       if (check_col(pinfo->cinfo, COL_INFO))
+                               col_append_fstr(pinfo->cinfo, COL_INFO, " Public ID \"%s\")",
+                                               tvb_format_text (tvb,
+                                                   str_tbl+publicid_index,
+                                                   len-1));
+                       proto_tree_add_item (wbxml_tree, hf_wbxml_public_id_literal,
+                                       tvb, 1, publicid_len, FALSE);
                }
                if ( version ) { /* Charset */
                        proto_tree_add_uint (wbxml_tree, hf_wbxml_charset,
                                        tvb, 1+publicid_len, charset_len, charset);
                }
                /* String Table */
-               proto_tree_add_text(wbxml_tree,
-                               tvb, offset, len + str_len, "String table: %u bytes", str_len);
+               ti = proto_tree_add_text(wbxml_tree,
+                               tvb, offset, len + str_tbl_len, "String table: %u bytes",
+                               str_tbl_len);
+
+               if (wbxml_tree && str_tbl_len) { /* Display string table as subtree */
+                       wbxml_str_tbl_tree = proto_item_add_subtree (ti,
+                                       ett_wbxml_str_tbl);
+                       show_wbxml_string_table (wbxml_str_tbl_tree, tvb,
+                                       str_tbl, str_tbl_len);
+               }
 
                /* Data starts HERE */
-               offset += len + str_len;
+               offset += len + str_tbl_len;
 
                /* The WBXML BODY starts here */
                ti = proto_tree_add_text (wbxml_tree, tvb, offset, -1,
@@ -261,49 +1959,71 @@ dissect_wbxml(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
                /* The parse_wbxml_X() functions will process the content correctly,
                 * irrespective of the WBXML version used. For the WBXML body, this
                 * means that there is a different processing for the global token
-                * RESERVED_2 (WBXML 1.0) or OPAQUE (WBXML 1.x with x > 0).
-                */
+                * RESERVED_2 (WBXML 1.0) or OPAQUE (WBXML 1.x with x > 0).  */
                if (wbxml_tree) { /* Show only if visible */
                        if (publicid) {
-#ifdef DEBUG
-                               printf ("WBXML - Content Type : \"%s\"\n",
-                                               match_strval (publicid, vals_wbxml_public_ids));
-#endif
-                               /* Look in wbxml_map[] table for defined mapping */
-                               if (publicid < WBXML_MAP_MAX_ID) {
-                                       if (wbxml_map[publicid].defined) {
-                                               proto_tree_add_text (wbxml_content_tree, tvb, offset, -1,
-                                                               "Level | State | Token                           "
+                               /* Retrieve the content token mapping if available */
+                               content_map = wbxml_content_map (publicid);
+                               if (content_map) {
+                                       /* Is there a defined token mapping for publicid? */
+                                       if (content_map->defined) {
+                                               proto_tree_add_text (wbxml_content_tree, tvb,
+                                                               offset, -1,
+                                                               "Level | State | Codepage "
+                                                               "| WBXML Token Description         "
                                                                "| Rendering");
                                                parse_wbxml_tag_defined (wbxml_content_tree,
                                                                tvb, offset, str_tbl, &level,
-                                                               &codepage_stag, &codepage_attr, &len,
-                                                               wbxml_map + publicid);
+                                                               &len, content_map);
                                                return;
                                        }
-                                       proto_tree_add_text (wbxml_content_tree, tvb,
-                                                       offset, -1,
-                                                       "Rendering of this content type"
-                                                       " not (yet) supported");
                                }
+                               proto_tree_add_text (wbxml_content_tree, tvb,
+                                               offset, -1,
+                                               "[Rendering of this content type"
+                                               " not (yet) supported]");
                        }
                        /* Default: WBXML only, no interpretation of the content */
                        proto_tree_add_text (wbxml_content_tree, tvb, offset, -1,
-                                       "Level | State | Token                           "
+                                       "Level | State | Codepage "
+                                       "| WBXML Token Description         "
                                        "| Rendering");
                        parse_wbxml_tag (wbxml_content_tree, tvb, offset,
-                                       str_tbl, &level,
-                                       &codepage_stag, &codepage_attr, &len);
+                                       str_tbl, &level, &len);
                        return;
-               } else {
-                       proto_tree_add_text (wbxml_content_tree, tvb, offset, -1,
-                                       "WBXML 1.0 decoding not yet supported");
                }
                return;
        }
 }
 
 
+/* Parse and display the WBXML string table (in a 3-column table format).
+ * This function displays:
+ *  - the offset in the string table,
+ *  - the length of the string
+ *  - the string.
+ */
+static void
+show_wbxml_string_table (proto_tree *tree, tvbuff_t *tvb, guint32 str_tbl,
+               guint32 str_tbl_len)
+{
+       guint32 off = str_tbl;
+       guint32 len = 0;
+       guint32 end = str_tbl + str_tbl_len;
+
+       proto_tree_add_text (tree, tvb, off, end,
+                       "Start  | Length | String");
+       while (off < end) {
+               len = tvb_strsize (tvb, off);
+               proto_tree_add_text (tree, tvb, off, len,
+                               "%6d | %6d | '%s'",
+                               off - str_tbl, len,
+                               tvb_format_text (tvb, off, len-1));
+               off += len;
+       }
+}
+
+
 /* Indentation code is based on a static const array of space characters.
  * At least one single space is returned */
 static const char indent_buffer[514] = " "
@@ -317,7 +2037,7 @@ static const char indent_buffer[514] = " "
        "                                                                "
        ; /* Generate XML indentation (length = 1 + 2 * 256 + 1 for '\0') */
 
-const char * Indent (guint8 level) {
+static const char * Indent (guint8 level) {
        return indent_buffer + (512 - 2 * (level));
 }
 
@@ -346,18 +2066,19 @@ const char * Indent (guint8 level) {
  *               CONTENT
  *             </tag>
  *
- * NOTE: an XML PI is parsed as an attribute list (same syntax).
+ * NOTES
+ *   - An XML PI is parsed as an attribute list (same syntax).
+ *   - A code page switch only applies to the single token that follows.
  */
 
 
-
 /* This function parses the WBXML and maps known token interpretations
  * to the WBXML tokens. As a result, the original XML document can be
  * recreated. Indentation is generated in order to ease reading.
  *
  * Attribute parsing is done in parse_wbxml_attribute_list_defined().
  *
- * The wbxml_mapping_table entry *map contains the actual token mapping.
+ * The wbxml_token_map entry *map contains the actual token mapping.
  *
  * NOTE: In order to parse the content, some recursion is required.
  *       However, for performance reasons, recursion has been avoided
@@ -365,32 +2086,38 @@ const char * Indent (guint8 level) {
  *       This is achieved by means of the parsing_tag_content and tag_save*
  *       variables.
  *
- * NOTE: Code page switches not yet processed in the code!
+ * NOTE: See above for known token mappings.
  *
- * NOTE: See packet-wbxml.h for known token mappings.
+ * NOTE: As tags can be opened and closed, a tag representation lookup
+ *       may happen once or twice for a given tag. For efficiency reasons,
+ *       the literal tag value is stored and used throughout the code.
+ *       With the introduction of code page support, this solution is robust
+ *       as the lookup only occurs once, removing the need for storage of
+ *       the used code page.
  */
-void
+static void
 parse_wbxml_tag_defined (proto_tree *tree, tvbuff_t *tvb, guint32 offset,
                guint32 str_tbl, guint8 *level,
-               guint8 *codepage_stag, guint8 *codepage_attr, guint32 *parsed_length,
-               const wbxml_mapping_table *map)
+               guint32 *parsed_length,
+               const wbxml_token_map *map)
 {
        guint32 tvb_len = tvb_reported_length (tvb);
        guint32 off = offset;
        guint32 len;
+       guint str_len;
        guint32 ent;
        guint32 index;
-       const char* str;
        guint8 peek;
        guint32 tag_len; /* Length of the index (uintvar) from a LITERAL tag */
-       guint8 tag_save_known = 0; /* Will contain peek & 0x3F thus the tag identity */
-       guint8 tag_new_known = 0; /* Will contain peek & 0x3F thus the tag identity */
+       guint8 tag_save_known = 0; /* Will contain peek & 0x3F (tag identity) */
+       guint8 tag_new_known = 0; /* Will contain peek & 0x3F (tag identity) */
        const char *tag_save_literal; /* Will contain the LITERAL tag identity */
        const char *tag_new_literal; /* Will contain the LITERAL tag identity */
+       guint8 codepage_stag = 0; /* Initial codepage in state = STAG */
        guint8 parsing_tag_content = FALSE; /* Are we parsing content from a
                                                                                   tag with content: <x>Content</x>
                                                                                   
-                                                                                  The initial state is FALSE of course.
+                                                                                  The initial state is FALSE.
                                                                                   This state will trigger recursion. */
        tag_save_literal = NULL; /* Prevents compiler warning */
 
@@ -401,78 +2128,100 @@ parse_wbxml_tag_defined (proto_tree *tree, tvbuff_t *tvb, guint32 offset,
        while (off < tvb_len) {
                peek = tvb_get_guint8 (tvb, off);
 #ifdef DEBUG
-               printf("WBXML - STAG: level = %3d, peek = 0x%02X, off = %d, tvb_len = %d\n",
+               printf("WBXML - STAG: level = %3d, peek = 0x%02X, off = %d, "
+                               "tvb_len = %d\n",
                                *level, peek, off, tvb_len);
 #endif
                if ((peek & 0x3F) < 4) switch (peek) { /* Global tokens in state = STAG
                                                                                                  but not the LITERAL tokens */
                        case 0x00: /* SWITCH_PAGE */
-                               peek = tvb_get_guint8 (tvb, off+1);
+                               codepage_stag = tvb_get_guint8 (tvb, off+1);
                                proto_tree_add_text (tree, tvb, off, 2,
-                                               "        Tag   | SWITCH_PAGE (Tag code page)     "
-                                               "| Code page switch (was: %d, is: %d)",
-                                               *codepage_stag, peek);
-                               *codepage_stag = peek;
+                                               "      | Tag   | T 0->%3d "
+                                               "| SWITCH_PAGE (Tag code page)     "
+                                               "|",
+                                               codepage_stag);
                                off += 2;
                                break;
                        case 0x01: /* END: only possible for Tag with Content */
-                               if (tag_save_known) {
+                               if (tag_save_known) { /* Known TAG */
                                        proto_tree_add_text (tree, tvb, off, 1,
-                                                       "  %3d | Tag   | END (Known Tag 0x%02X)            "
+                                                       "  %3d | Tag   |          "
+                                                       "| END (Known Tag 0x%02X)            "
                                                        "| %s</%s>",
                                                        *level, tag_save_known, Indent (*level),
-                                                       match_strval (tag_save_known, map->tags));
+                                                       tag_save_literal); /* We already looked it up! */
                                } else { /* Literal TAG */
                                        proto_tree_add_text (tree, tvb, off, 1,
-                                                       "  %3d | Tag   | END (Literal Tag)               "
+                                                       "  %3d | Tag   |          "
+                                                       "| END (Literal Tag)               "
                                                        "| %s</%s>",
-                                                       *level, Indent (*level), tag_save_literal);
+                                                       *level, Indent (*level),
+                                                       tag_save_literal);
                                }
                                (*level)--;
                                off++;
                                *parsed_length = off - offset;
+                               /* Reset code page: not needed as return from recursion */
                                return;
                                break;
                        case 0x02: /* ENTITY */
                                ent = tvb_get_guintvar (tvb, off+1, &len);
                                proto_tree_add_text (tree, tvb, off, 1+len,
-                                               "  %3d | Tag   | ENTITY                          "
+                                               "  %3d | Tag   |          "
+                                               "| ENTITY                          "
                                                "| %s'&#%u;'",
                                                *level, Indent (*level), ent);
                                off += 1+len;
                                break;
                        case 0x03: /* STR_I */
-                               /* Hack the string table lookup function */
-                               str = strtbl_lookup (tvb, off+1, 0, &len);
+                               len = tvb_strsize (tvb, off+1);
                                proto_tree_add_text (tree, tvb, off, 1+len,
-                                               "  %3d | Tag   | STR_I (Inline string)           "
+                                               "  %3d | Tag   |          "
+                                               "| STR_I (Inline string)           "
                                                "| %s\'%s\'",
-                                               *level, Indent(*level), str);
+                                               *level, Indent(*level),
+                                               tvb_format_text (tvb, off+1, len-1));
                                off += 1+len;
                                break;
                        case 0x40: /* EXT_I_0 */
                        case 0x41: /* EXT_I_1 */
                        case 0x42: /* EXT_I_2 */
                                /* Extension tokens */
-                               /* Hack the string table lookup function */
-                               str = strtbl_lookup (tvb, off+1, 0, &len);
-                               proto_tree_add_text (tree, tvb, off, 1+len,
-                                               "  %3d | Tag   | EXT_I_%1x    (Extension Token)    "
-                                               "| %s(%s: \'%s\')",
-                                               *level, peek & 0x0f, Indent (*level),
-                                               match_strval (peek, map->global), str);
+                               len = tvb_strsize (tvb, off+1);
+                               if (codepage_stag) { /* Not default code page */
+                                       proto_tree_add_text (tree, tvb, off, 1+len,
+                                                       "  %3d | Tag   | T %3d->0 "
+                                                       "| EXT_I_%1x    (Extension Token)    "
+                                                       "| %s(%s: \'%s\')",
+                                                       *level, codepage_stag, peek & 0x0f, Indent (*level),
+                                                       map_token (map->global, codepage_stag, peek),
+                                                       tvb_format_text (tvb, off+1, len-1));
+                                       /* Reset code page */
+                                       codepage_stag = 0;
+                               } else { /* Code page 0 */
+                                       proto_tree_add_text (tree, tvb, off, 1+len,
+                                                       "  %3d | Tag   |          "
+                                                       "| EXT_I_%1x    (Extension Token)    "
+                                                       "| %s(%s: \'%s\')",
+                                                       *level, peek & 0x0f, Indent (*level),
+                                                       map_token (map->global, codepage_stag, peek),
+                                                       tvb_format_text (tvb, off+1, len-1));
+                               }
                                off += 1+len;
                                break;
                        case 0x43: /* PI */
                                proto_tree_add_text (tree, tvb, off, 1,
-                                               "  %3d | Tag   | PI (XML Processing Instruction) "
+                                               "  %3d | Tag   |          "
+                                               "| PI (XML Processing Instruction) "
                                                "| %s<?xml",
                                                *level, Indent (*level));
-                               parse_wbxml_attribute_list (tree, tvb, off, str_tbl,
-                                               *level, codepage_attr, &len);
+                               parse_wbxml_attribute_list_defined (tree, tvb, off, str_tbl,
+                                               *level, &len, map);
                                off += len;
                                proto_tree_add_text (tree, tvb, off-1, 1,
-                                               "  %3d | Tag   | END (PI)                        "
+                                               "  %3d | Tag   |          "
+                                               "| END (PI)                        "
                                                "| %s?>",
                                                *level, Indent (*level));
                                break;
@@ -481,46 +2230,77 @@ parse_wbxml_tag_defined (proto_tree *tree, tvbuff_t *tvb, guint32 offset,
                        case 0x82: /* EXT_T_2 */
                                /* Extension tokens */
                                index = tvb_get_guintvar (tvb, off+1, &len);
-                               str = strtbl_lookup (tvb, str_tbl, index, NULL);
-                               proto_tree_add_text (tree, tvb, off, 1+len,
-                                               "  %3d | Tag   | EXT_T_%1x    (Extension Token)    "
-                                               "| %s(%s: \'%s\')",
-                                               *level, peek & 0x0f, Indent (*level),
-                                               match_strval (peek, map->global), str);
+                               str_len = tvb_strsize (tvb, str_tbl+index);
+                               if (codepage_stag) { /* Not default code page */
+                                       proto_tree_add_text (tree, tvb, off, 1+len,
+                                                       "  %3d | Tag   | T %3d->0 "
+                                                       "| EXT_T_%1x    (Extension Token)    "
+                                                       "| %s(%s: \'%s\')",
+                                                       *level, codepage_stag, peek & 0x0f, Indent (*level),
+                                                       map_token (map->global, codepage_stag, peek),
+                                                       tvb_format_text (tvb, str_tbl+index, str_len-1));
+                                       /* Reset code page */
+                                       codepage_stag = 0;
+                               } else { /* Code page 0 */
+                                       proto_tree_add_text (tree, tvb, off, 1+len,
+                                                       "  %3d | Tag   |          "
+                                                       "| EXT_T_%1x    (Extension Token)    "
+                                                       "| %s(%s: \'%s\')",
+                                                       *level, peek & 0x0f, Indent (*level),
+                                                       map_token (map->global, codepage_stag, peek),
+                                                       tvb_format_text (tvb, str_tbl+index, str_len-1));
+                               }
                                off += 1+len;
                                break;
                        case 0x83: /* STR_T */
                                index = tvb_get_guintvar (tvb, off+1, &len);
-                               str = strtbl_lookup (tvb, str_tbl, index, NULL);
+                               str_len = tvb_strsize (tvb, str_tbl+index);
                                proto_tree_add_text (tree, tvb, off, 1+len,
-                                               "  %3d | Tag   | STR_T (Tableref string)         "
+                                               "  %3d | Tag   |          "
+                                               "| STR_T (Tableref string)         "
                                                "| %s\'%s\'",
-                                               *level, Indent (*level), str);
+                                               *level, Indent (*level),
+                                               tvb_format_text (tvb, str_tbl+index, str_len-1));
                                off += 1+len;
                                break;
                        case 0xC0: /* EXT_0 */
                        case 0xC1: /* EXT_1 */
                        case 0xC2: /* EXT_2 */
                                /* Extension tokens */
-                               proto_tree_add_text (tree, tvb, off, 1,
-                                               "  %3d | Tag   | EXT_%1x      (Extension Token)    "
-                                               "| %s(%s)",
-                                               *level, peek & 0x0f, Indent (*level),
-                                               match_strval (peek, map->global));
+                               if (codepage_stag) { /* Not default code page */
+                                       proto_tree_add_text (tree, tvb, off, 1,
+                                                       "  %3d | Tag   | T %3d->0 "
+                                                       "| EXT_%1x      (Extension Token)    "
+                                                       "| %s(%s)",
+                                                       *level, codepage_stag, peek & 0x0f, Indent (*level),
+                                                       map_token (map->global, codepage_stag, peek));
+                                       /* Reset code page */
+                                       codepage_stag = 0;
+                               } else { /* Code page 0 */
+                                       proto_tree_add_text (tree, tvb, off, 1,
+                                                       "  %3d | Tag   |          "
+                                                       "| EXT_%1x      (Extension Token)    "
+                                                       "| %s(%s)",
+                                                       *level, peek & 0x0f, Indent (*level),
+                                                       map_token (map->global, codepage_stag, peek));
+                               }
                                off++;
                                break;
                        case 0xC3: /* OPAQUE - WBXML 1.1 and newer */
                                if (tvb_get_guint8 (tvb, 0)) { /* WBXML 1.x (x > 0) */
                                        index = tvb_get_guintvar (tvb, off+1, &len);
                                        proto_tree_add_text (tree, tvb, off, 1 + len + index,
-                                                       "  %3d | Tag   | OPAQUE (Opaque data)            "
+                                                       "  %3d | Tag   |          "
+                                                       "| OPAQUE (Opaque data)            "
                                                        "| %s(%d bytes of opaque data)",
                                                        *level, Indent (*level), index);
                                        off += 1+len+index;
                                } else { /* WBXML 1.0 - RESERVED_2 token (invalid) */
                                        proto_tree_add_text (tree, tvb, off, 1,
-                                                       "        Tag   | RESERVED_2     (Invalid Token!) "
-                                                       "| WBXML 1.0 parsing stops here.");
+                                                       "  %3d | Tag   |          "
+                                                       "| RESERVED_2     (Invalid Token!) "
+                                                       "| WBXML 1.0 parsing stops here.",
+                                                       *level);
                                        /* Stop processing as it is impossible to parse now */
                                        off = tvb_len;
                                        *parsed_length = off - offset;
@@ -530,8 +2310,10 @@ parse_wbxml_tag_defined (proto_tree *tree, tvbuff_t *tvb, guint32 offset,
 
                                /* No default clause, as all cases have been treated */
                } else { /* LITERAL or Known TAG */
-                       /*
-                        * We must store the initial tag, and also retrieve the new tag.
+                       /* We must store the initial tag, and also retrieve the new tag.
+                        * For efficiency reasons, we store the literal tag representation
+                        * for known tags too, so we can easily close the tag without the
+                        * need of a new lookup and avoiding storage of token codepage.
                         * 
                         * There are 4 possibilities:
                         *
@@ -545,20 +2327,21 @@ parse_wbxml_tag_defined (proto_tree *tree, tvbuff_t *tvb, guint32 offset,
                        tag_len = 0;
                        if ((peek & 0x3F) == 4) { /* LITERAL */
                                index = tvb_get_guintvar (tvb, off+1, &tag_len);
-                               tag_new_literal = strtbl_lookup (tvb, str_tbl, index, NULL);
+                               str_len = tvb_strsize (tvb, str_tbl+index);
+                               tag_new_literal = tvb_get_ptr (tvb, str_tbl+index, str_len);
                                tag_new_known = 0; /* invalidate known tag_new */
-                       } else {
+                       } else { /* Known tag */
                                tag_new_known = peek & 0x3F;
-                               tag_new_literal = NULL; /* invalidate LITERAL tag_new */
+                               tag_new_literal = map_token (map->tags, codepage_stag,
+                                                                               tag_new_known);
+                               /* Stored looked up tag name string */
                        }
 
-                       /*
-                        * Parsing of TAG starts HERE
-                        */
+                       /* Parsing of TAG starts HERE */
                        if (peek & 0x40) { /* Content present */
                                /* Content follows
                                 * [!] An explicit END token is expected in these cases!
-                                * ==> Recursion is possible if we encounter a tag with content;
+                                * ==> Recursion possible if we encounter a tag with content;
                                 *     recursion will return at the explicit END token.
                                 */
                                if (parsing_tag_content) { /* Recurse */
@@ -569,55 +2352,84 @@ parse_wbxml_tag_defined (proto_tree *tree, tvbuff_t *tvb, guint32 offset,
                                         * recursion will take care of it */
                                        (*level)++;
                                        parse_wbxml_tag_defined (tree, tvb, off, str_tbl, level,
-                                                       codepage_stag, codepage_attr, &len, map);
+                                                       &len, map);
                                        off += len;
                                } else { /* Now we will have content to parse */
                                        /* Save the start tag so we can properly close it later. */
-                                       if ((peek & 0x3F) == 4) {
+                                       if ((peek & 0x3F) == 4) { /* Literal tag */
                                                tag_save_literal = tag_new_literal;
                                                tag_save_known = 0;
-                                       } else {
+                                       } else { /* Known tag */
                                                tag_save_known = tag_new_known;
-                                               tag_save_literal = NULL;
+                                               tag_save_literal = tag_new_literal;
+                                               /* The last statement avoids needless lookups */
                                        }
                                        /* Process the attribute list if present */
                                        if (peek & 0x80) { /* Content and Attribute list present */
                                                if (tag_new_known) { /* Known tag */
-                                                       proto_tree_add_text (tree, tvb, off, 1,
-                                                                       "  %3d | Tag   "
-                                                                       "|   Known Tag 0x%02X           (AC) "
-                                                                       "| %s<%s",
-                                                                       *level, tag_new_known, Indent (*level),
-                                                                       match_strval (tag_new_known, map->tags));
+                                                       if (codepage_stag) { /* Not default code page */
+                                                               proto_tree_add_text (tree, tvb, off, 1,
+                                                                               "  %3d | Tag   | T %3d->0 "
+                                                                               "|   Known Tag 0x%02X           (AC) "
+                                                                               "| %s<%s",
+                                                                               *level, codepage_stag, tag_new_known,
+                                                                               Indent (*level), tag_new_literal);
+                                                               /* Tag string already looked up earlier! */
+                                                               /* Reset code page */
+                                                               codepage_stag = 0;
+                                                       } else { /* Code page 0 */
+                                                               proto_tree_add_text (tree, tvb, off, 1,
+                                                                               "  %3d | Tag   |          "
+                                                                               "|   Known Tag 0x%02X           (AC) "
+                                                                               "| %s<%s",
+                                                                               *level, tag_new_known,
+                                                                               Indent (*level), tag_new_literal);
+                                                               /* Tag string already looked up earlier! */
+                                                       }
                                                        off++;
                                                } else { /* LITERAL tag */
                                                        proto_tree_add_text (tree, tvb, off, 1,
-                                                                       "  %3d | Tag   "
+                                                                       "  %3d | Tag   |          "
                                                                        "| LITERAL_AC (Literal tag)   (AC) "
-                                                                       "|   %s<%s",
+                                                                       "| %s<%s",
                                                                        *level, Indent (*level), tag_new_literal);
                                                        off += 1 + tag_len;
                                                }
-                                               parse_wbxml_attribute_list_defined (tree, tvb, off, str_tbl,
-                                                               *level, codepage_attr, &len, map);
+                                               parse_wbxml_attribute_list_defined (tree, tvb,
+                                                               off, str_tbl, *level, &len, map);
                                                off += len;
                                                proto_tree_add_text (tree, tvb, off-1, 1,
-                                                               "  %3d | Tag   "
+                                                               "  %3d | Tag   |          "
                                                                "| END (attribute list)            "
                                                                "| %s>",
                                                                *level, Indent (*level));
                                        } else { /* Content, no Attribute list */
                                                if (tag_new_known) { /* Known tag */
-                                                       proto_tree_add_text (tree, tvb, off, 1,
-                                                                       "  %3d | Tag   "
-                                                                       "|   Known Tag 0x%02X           (.C) "
-                                                                       "| %s<%s>",
-                                                                       *level, tag_new_known, Indent (*level),
-                                                                       match_strval (tag_new_known, map->tags));
+                                                       if (codepage_stag) { /* Not default code page */
+                                                               proto_tree_add_text (tree, tvb, off, 1,
+                                                                               "  %3d | Tag   | T %3d->0 "
+                                                                               "|   Known Tag 0x%02X           (.C) "
+                                                                               "| %s<%s>",
+                                                                               *level, codepage_stag, tag_new_known,
+                                                                               Indent (*level),
+                                                                               tag_new_literal);
+                                                               /* Tag string already looked up earlier! */
+                                                               /* Reset code page */
+                                                               codepage_stag = 0;
+                                                       } else { /* Code page 0 */
+                                                               proto_tree_add_text (tree, tvb, off, 1,
+                                                                               "  %3d | Tag   |          "
+                                                                               "|   Known Tag 0x%02X           (.C) "
+                                                                               "| %s<%s>",
+                                                                               *level, tag_new_known,
+                                                                               Indent (*level),
+                                                                               tag_new_literal);
+                                                               /* Tag string already looked up earlier! */
+                                                       }
                                                        off++;
                                                } else { /* LITERAL tag */
                                                        proto_tree_add_text (tree, tvb, off, 1,
-                                                                       "  %3d | Tag   "
+                                                                       "  %3d | Tag   |          "
                                                                        "| LITERAL_C  (Literal Tag)   (.C) "
                                                                        "| %s<%s>",
                                                                        *level, Indent (*level), tag_new_literal);
@@ -631,59 +2443,87 @@ parse_wbxml_tag_defined (proto_tree *tree, tvbuff_t *tvb, guint32 offset,
                                         */
                                        parsing_tag_content = TRUE;
 #ifdef DEBUG
-                                       printf ("WBXML: Tag in Tag - No recursion this time! (off = %d)\n",off);
+                                       printf ("WBXML: Tag in Tag - No recursion this time! "
+                                                       "(off = %d)\n", off);
 #endif
                                }
                        } else { /* No Content */
 #ifdef DEBUG
-                               printf ("WBXML: <Tag/> in Tag - No recursion! (off = %d)\n",off);
+                               printf ("WBXML: <Tag/> in Tag - No recursion! "
+                                               "(off = %d)\n", off);
 #endif
                                (*level)++;
                                if (peek & 0x80) { /* No Content, Attribute list present */
                                        if (tag_new_known) { /* Known tag */
-                                               proto_tree_add_text (tree, tvb, off, 1,
-                                                               "  %3d | Tag   "
-                                                               "|   Known Tag 0x%02X           (A.) "
-                                                               "| %s<%s",
-                                                               *level, tag_new_known, Indent (*level),
-                                                               match_strval (tag_new_known, map->tags));
+                                               if (codepage_stag) { /* Not default code page */
+                                                       proto_tree_add_text (tree, tvb, off, 1,
+                                                                       "  %3d | Tag   | T %3d->0 "
+                                                                       "|   Known Tag 0x%02X           (A.) "
+                                                                       "| %s<%s",
+                                                                       *level, codepage_stag, tag_new_known,
+                                                                       Indent (*level), tag_new_literal);
+                                                       /* Tag string already looked up earlier! */
+                                                       /* Reset code page */
+                                                       codepage_stag = 0;
+                                               } else { /* Code page 0 */
+                                                       proto_tree_add_text (tree, tvb, off, 1,
+                                                                       "  %3d | Tag   |          "
+                                                                       "|   Known Tag 0x%02X           (A.) "
+                                                                       "| %s<%s",
+                                                                       *level, tag_new_known,
+                                                                       Indent (*level), tag_new_literal);
+                                                       /* Tag string already looked up earlier! */
+                                               }
                                                off++;
-                                               parse_wbxml_attribute_list_defined (tree, tvb, off, str_tbl,
-                                                               *level, codepage_attr, &len, map);
+                                               parse_wbxml_attribute_list_defined (tree, tvb,
+                                                               off, str_tbl, *level, &len, map);
                                                off += len;
                                                proto_tree_add_text (tree, tvb, off-1, 1,
-                                                               "  %3d | Tag   "
+                                                               "  %3d | Tag   |          "
                                                                "| END (Known Tag)                 "
                                                                "| %s/>",
                                                                *level, Indent (*level));
                                        } else { /* LITERAL tag */
                                                proto_tree_add_text (tree, tvb, off, 1,
-                                                               "  %3d | Tag   "
+                                                               "  %3d | Tag   |          "
                                                                "| LITERAL_A  (Literal Tag)   (A.) "
                                                                "| %s<%s",
                                                                *level, Indent (*level), tag_new_literal);
                                                off += 1 + tag_len;
-                                               parse_wbxml_attribute_list_defined (tree, tvb, off, str_tbl,
-                                                               *level, codepage_attr, &len, map);
+                                               parse_wbxml_attribute_list_defined (tree, tvb,
+                                                               off, str_tbl, *level, &len, map);
                                                off += len;
                                                proto_tree_add_text (tree, tvb, off-1, 1,
-                                                               "  %3d | Tag   "
+                                                               "  %3d | Tag   |          "
                                                                "| END (Literal Tag)               "
                                                                "| %s/>",
                                                                *level, Indent (*level));
                                        }
                                } else { /* No Content, No Attribute list */
                                        if (tag_new_known) { /* Known tag */
-                                               proto_tree_add_text (tree, tvb, off, 1,
-                                                               "  %3d | Tag   "
-                                                               "|   Known Tag 0x%02x           (..) "
-                                                               "| %s<%s />",
-                                                               *level, tag_new_known, Indent (*level),
-                                                               match_strval (tag_new_known, map->tags));
+                                               if (codepage_stag) { /* Not default code page */
+                                                       proto_tree_add_text (tree, tvb, off, 1,
+                                                                       "  %3d | Tag   | T %3d->0 "
+                                                                       "|   Known Tag 0x%02x           (..) "
+                                                                       "| %s<%s />",
+                                                                       *level, codepage_stag, tag_new_known,
+                                                                       Indent (*level), tag_new_literal);
+                                                       /* Tag string already looked up earlier! */
+                                                       /* Reset code page */
+                                                       codepage_stag = 0;
+                                               } else { /* Code page 0 */
+                                                       proto_tree_add_text (tree, tvb, off, 1,
+                                                                       "  %3d | Tag   |          "
+                                                                       "|   Known Tag 0x%02x           (..) "
+                                                                       "| %s<%s />",
+                                                                       *level, tag_new_known,
+                                                                       Indent (*level), tag_new_literal);
+                                                       /* Tag string already looked up earlier! */
+                                               }
                                                off++;
                                        } else { /* LITERAL tag */
                                                proto_tree_add_text (tree, tvb, off, 1,
-                                                               "  %3d | Tag   "
+                                                               "  %3d | Tag   |          "
                                                                "| LITERAL    (Literal Tag)   (..) "
                                                                "| %s<%s />",
                                                                *level, Indent (*level), tag_new_literal);
@@ -691,39 +2531,42 @@ parse_wbxml_tag_defined (proto_tree *tree, tvbuff_t *tvb, guint32 offset,
                                        }
                                }
                                (*level)--;
+                               /* TODO: Do I have to reset code page here? */
                        }
                } /* if (tag & 0x3F) >= 5 */
        } /* while */
 }
 
+
 /* This function performs the WBXML decoding as in parse_wbxml_tag_defined()
  * but this time no WBXML mapping is performed.
  *
  * Attribute parsing is done in parse_wbxml_attribute_list().
- *
- * NOTE: Code page switches not yet processed in the code!
  */
-void
+static void
 parse_wbxml_tag (proto_tree *tree, tvbuff_t *tvb, guint32 offset,
                guint32 str_tbl, guint8 *level,
-               guint8 *codepage_stag, guint8 *codepage_attr, guint32 *parsed_length)
+               guint32 *parsed_length)
 {
        guint32 tvb_len = tvb_reported_length (tvb);
        guint32 off = offset;
        guint32 len;
+       guint str_len;
        guint32 ent;
        guint32 index;
-       const char* str;
        guint8 peek;
        guint32 tag_len; /* Length of the index (uintvar) from a LITERAL tag */
-       guint8 tag_save_known = 0; /* Will contain peek & 0x3F thus the tag identity */
-       guint8 tag_new_known = 0; /* Will contain peek & 0x3F thus the tag identity */
+       guint8 tag_save_known = 0; /* Will contain peek & 0x3F (tag identity) */
+       guint8 tag_new_known = 0; /* Will contain peek & 0x3F (tag identity) */
        const char *tag_save_literal; /* Will contain the LITERAL tag identity */
        const char *tag_new_literal; /* Will contain the LITERAL tag identity */
+       char tag_save_buf[10]; /* Will contain "tag_0x%02X" */
+       char tag_new_buf[10]; /* Will contain "tag_0x%02X" */
+       guint8 codepage_stag = 0; /* Initial codepage in state = STAG */
        guint8 parsing_tag_content = FALSE; /* Are we parsing content from a
                                                                                   tag with content: <x>Content</x>
                                                                                   
-                                                                                  The initial state is FALSE of course.
+                                                                                  The initial state is FALSE.
                                                                                   This state will trigger recursion. */
        tag_save_literal = NULL; /* Prevents compiler warning */
 
@@ -734,77 +2577,98 @@ parse_wbxml_tag (proto_tree *tree, tvbuff_t *tvb, guint32 offset,
        while (off < tvb_len) {
                peek = tvb_get_guint8 (tvb, off);
 #ifdef DEBUG
-               printf("WBXML - STAG: level = %3d, peek = 0x%02X, off = %d, tvb_len = %d\n",
+               printf("WBXML - STAG: level = %3d, peek = 0x%02X, off = %d, "
+                               "tvb_len = %d\n",
                                *level, peek, off, tvb_len);
 #endif
                if ((peek & 0x3F) < 4) switch (peek) { /* Global tokens in state = STAG
                                                                                                  but not the LITERAL tokens */
                        case 0x00: /* SWITCH_PAGE */
-                               peek = tvb_get_guint8 (tvb, off+1);
+                               codepage_stag = tvb_get_guint8 (tvb, off+1);
                                proto_tree_add_text (tree, tvb, off, 2,
-                                               "        Tag   | SWITCH_PAGE (Tag code page)     "
-                                               "| Code page switch (was: %d, is: %d)",
-                                               *codepage_stag, peek);
-                               *codepage_stag = peek;
+                                               "      | Tag   | T 0->%3d "
+                                               "| SWITCH_PAGE (Tag code page)     "
+                                               "|",
+                                               codepage_stag);
                                off += 2;
                                break;
                        case 0x01: /* END: only possible for Tag with Content */
-                               if (tag_save_known) {
+                               if (tag_save_known) { /* Known TAG */
                                        proto_tree_add_text (tree, tvb, off, 1,
-                                                       "  %3d | Tag   | END (Known Tag 0x%02X)            "
-                                                       "| %s</Tag 0x%02X>",
+                                                       "  %3d | Tag   |          "
+                                                       "| END (Known Tag 0x%02X)            "
+                                                       "| %s</%s>",
                                                        *level, tag_save_known, Indent (*level),
-                                                       tag_save_known);
+                                                       tag_save_literal); /* We already looked it up! */
                                } else { /* Literal TAG */
                                        proto_tree_add_text (tree, tvb, off, 1,
-                                                       "  %3d | Tag   | END (Literal Tag)               "
+                                                       "  %3d | Tag   |          "
+                                                       "| END (Literal Tag)               "
                                                        "| %s</%s>",
-                                                       *level, Indent (*level), tag_save_literal);
+                                                       *level, Indent (*level),
+                                                       tag_save_literal);
                                }
                                (*level)--;
                                off++;
                                *parsed_length = off - offset;
+                               /* Reset code page: not needed as return from recursion */
                                return;
                                break;
                        case 0x02: /* ENTITY */
                                ent = tvb_get_guintvar (tvb, off+1, &len);
                                proto_tree_add_text (tree, tvb, off, 1+len,
-                                               "  %3d | Tag   | ENTITY                          "
+                                               "  %3d | Tag   |          "
+                                               "| ENTITY                          "
                                                "| %s'&#%u;'",
                                                *level, Indent (*level), ent);
                                off += 1+len;
                                break;
                        case 0x03: /* STR_I */
-                               /* Hack the string table lookup function */
-                               str = strtbl_lookup (tvb, off+1, 0, &len);
+                               len = tvb_strsize (tvb, off+1);
                                proto_tree_add_text (tree, tvb, off, 1+len,
-                                               "  %3d | Tag   | STR_I (Inline string)           "
+                                               "  %3d | Tag   |          "
+                                               "| STR_I (Inline string)           "
                                                "| %s\'%s\'",
-                                               *level, Indent(*level), str);
+                                               *level, Indent(*level),
+                                               tvb_format_text (tvb, off+1, len-1));
                                off += 1+len;
                                break;
                        case 0x40: /* EXT_I_0 */
                        case 0x41: /* EXT_I_1 */
                        case 0x42: /* EXT_I_2 */
                                /* Extension tokens */
-                               /* Hack the string table lookup function */
-                               str = strtbl_lookup (tvb, off+1, 0, &len);
-                               proto_tree_add_text (tree, tvb, off, 1+len,
-                                               "  %3d | Tag   | EXT_I_%1x    (Extension Token)    "
-                                               "| %s(Inline string extension: \'%s\')",
-                                               *level, peek & 0x0f, Indent (*level), str);
+                               len = tvb_strsize (tvb, off+1);
+                               if (codepage_stag) { /* Not default code page */
+                                       proto_tree_add_text (tree, tvb, off, 1+len,
+                                                       "  %3d | Tag   | T %3d->0 "
+                                                       "| EXT_I_%1x    (Extension Token)    "
+                                                       "| %s(Inline string extension: \'%s\')",
+                                                       *level, codepage_stag, peek & 0x0f, Indent (*level),
+                                                       tvb_format_text (tvb, off+1, len-1));
+                                       /* Reset code page */
+                                       codepage_stag = 0;
+                               } else { /* Code page 0 */
+                                       proto_tree_add_text (tree, tvb, off, 1+len,
+                                                       "  %3d | Tag   |          "
+                                                       "| EXT_I_%1x    (Extension Token)    "
+                                                       "| %s(Inline string extension: \'%s\')",
+                                                       *level, peek & 0x0f, Indent (*level),
+                                                       tvb_format_text (tvb, off+1, len-1));
+                               }
                                off += 1+len;
                                break;
                        case 0x43: /* PI */
                                proto_tree_add_text (tree, tvb, off, 1,
-                                               "  %3d | Tag   | PI (XML Processing Instruction) "
+                                               "  %3d | Tag   |          "
+                                               "| PI (XML Processing Instruction) "
                                                "| %s<?xml",
                                                *level, Indent (*level));
                                parse_wbxml_attribute_list (tree, tvb, off, str_tbl,
-                                               *level, codepage_attr, &len);
+                                               *level, &len);
                                off += len;
                                proto_tree_add_text (tree, tvb, off-1, 1,
-                                               "  %3d | Tag   | END (PI)                        "
+                                               "  %3d | Tag   |          "
+                                               "| END (PI)                        "
                                                "| %s?>",
                                                *level, Indent (*level));
                                break;
@@ -813,44 +2677,74 @@ parse_wbxml_tag (proto_tree *tree, tvbuff_t *tvb, guint32 offset,
                        case 0x82: /* EXT_T_2 */
                                /* Extension tokens */
                                index = tvb_get_guintvar (tvb, off+1, &len);
-                               str = strtbl_lookup (tvb, str_tbl, index, NULL);
-                               proto_tree_add_text (tree, tvb, off, 1+len,
-                                               "  %3d | Tag   | EXT_T_%1x    (Extension Token)    "
-                                               "| %s(Tableref string extension: \'%s\')",
-                                               *level, peek & 0x0f, Indent (*level), str);
+                               str_len = tvb_strsize (tvb, str_tbl+index);
+                               if (codepage_stag) { /* Not default code page */
+                                       proto_tree_add_text (tree, tvb, off, 1+len,
+                                                       "  %3d | Tag   | T %3d->0 "
+                                                       "| EXT_T_%1x    (Extension Token)    "
+                                                       "| %s(Tableref string extension: \'%s\')",
+                                                       *level, codepage_stag, peek & 0x0f, Indent (*level),
+                                                       tvb_format_text (tvb, str_tbl+index, str_len-1));
+                                       /* Reset code page */
+                                       codepage_stag = 0;
+                               } else { /* Code page 0 */
+                                       proto_tree_add_text (tree, tvb, off, 1+len,
+                                                       "  %3d | Tag   |          "
+                                                       "| EXT_T_%1x    (Extension Token)    "
+                                                       "| %s(Tableref string extension: \'%s\')",
+                                                       *level, peek & 0x0f, Indent (*level),
+                                                       tvb_format_text (tvb, str_tbl+index, str_len-1));
+                               }
                                off += 1+len;
                                break;
                        case 0x83: /* STR_T */
                                index = tvb_get_guintvar (tvb, off+1, &len);
-                               str = strtbl_lookup (tvb, str_tbl, index, NULL);
+                               str_len = tvb_strsize (tvb, str_tbl+index);
                                proto_tree_add_text (tree, tvb, off, 1+len,
-                                               "  %3d | Tag   | STR_T (Tableref string)         "
+                                               "  %3d | Tag   |          "
+                                               "| STR_T (Tableref string)         "
                                                "| %s\'%s\'",
-                                               *level, Indent (*level), str);
+                                               *level, Indent (*level),
+                                               tvb_format_text (tvb, str_tbl+index, str_len-1));
                                off += 1+len;
                                break;
                        case 0xC0: /* EXT_0 */
                        case 0xC1: /* EXT_1 */
                        case 0xC2: /* EXT_2 */
                                /* Extension tokens */
-                               proto_tree_add_text (tree, tvb, off, 1,
-                                               "  %3d | Tag   | EXT_%1x      (Extension Token)    "
-                                               "| %s(Single-byte extension)",
-                                               *level, peek & 0x0f, Indent (*level));
+                               if (codepage_stag) { /* Not default code page */
+                                       proto_tree_add_text (tree, tvb, off, 1,
+                                                       "  %3d | Tag   | T %3d->0 "
+                                                       "| EXT_%1x      (Extension Token)    "
+                                                       "| %s(Single-byte extension)",
+                                                       *level, codepage_stag, peek & 0x0f,
+                                                       Indent (*level));
+                                       /* Reset code page */
+                                       codepage_stag = 0;
+                               } else { /* Code page 0 */
+                                       proto_tree_add_text (tree, tvb, off, 1,
+                                                       "  %3d | Tag   |          "
+                                                       "| EXT_%1x      (Extension Token)    "
+                                                       "| %s(Single-byte extension)",
+                                                       *level, peek & 0x0f, Indent (*level));
+                               }
                                off++;
                                break;
                        case 0xC3: /* OPAQUE - WBXML 1.1 and newer */
                                if (tvb_get_guint8 (tvb, 0)) { /* WBXML 1.x (x > 0) */
                                        index = tvb_get_guintvar (tvb, off+1, &len);
                                        proto_tree_add_text (tree, tvb, off, 1 + len + index,
-                                                       "  %3d | Tag   | OPAQUE (Opaque data)            "
+                                                       "  %3d | Tag   |          "
+                                                       "| OPAQUE (Opaque data)            "
                                                        "| %s(%d bytes of opaque data)",
                                                        *level, Indent (*level), index);
                                        off += 1+len+index;
                                } else { /* WBXML 1.0 - RESERVED_2 token (invalid) */
                                        proto_tree_add_text (tree, tvb, off, 1,
-                                                       "        Tag   | RESERVED_2     (Invalid Token!) "
-                                                       "| WBXML 1.0 parsing stops here.");
+                                                       "  %3d | Tag   |          "
+                                                       "| RESERVED_2     (Invalid Token!) "
+                                                       "| WBXML 1.0 parsing stops here.",
+                                                       *level);
                                        /* Stop processing as it is impossible to parse now */
                                        off = tvb_len;
                                        *parsed_length = off - offset;
@@ -860,8 +2754,10 @@ parse_wbxml_tag (proto_tree *tree, tvbuff_t *tvb, guint32 offset,
 
                                /* No default clause, as all cases have been treated */
                } else { /* LITERAL or Known TAG */
-                       /*
-                        * We must store the initial tag, and also retrieve the new tag.
+                       /* We must store the initial tag, and also retrieve the new tag.
+                        * For efficiency reasons, we store the literal tag representation
+                        * for known tags too, so we can easily close the tag without the
+                        * need of a new lookup and avoiding storage of token codepage.
                         * 
                         * There are 4 possibilities:
                         *
@@ -875,20 +2771,22 @@ parse_wbxml_tag (proto_tree *tree, tvbuff_t *tvb, guint32 offset,
                        tag_len = 0;
                        if ((peek & 0x3F) == 4) { /* LITERAL */
                                index = tvb_get_guintvar (tvb, off+1, &tag_len);
-                               tag_new_literal = strtbl_lookup (tvb, str_tbl, index, NULL);
+                               str_len = tvb_strsize (tvb, str_tbl+index);
+                               tag_new_literal = tvb_get_ptr (tvb, str_tbl+index, str_len);
                                tag_new_known = 0; /* invalidate known tag_new */
-                       } else {
+                       } else { /* Known tag */
                                tag_new_known = peek & 0x3F;
-                               tag_new_literal = NULL; /* invalidate LITERAL tag_new */
+                               sprintf (tag_new_buf, "Tag_0x%02X",
+                                               tag_new_known);
+                               tag_new_literal = tag_new_buf;
+                               /* Stored looked up tag name string */
                        }
 
-                       /*
-                        * Parsing of TAG starts HERE
-                        */
+                       /* Parsing of TAG starts HERE */
                        if (peek & 0x40) { /* Content present */
                                /* Content follows
                                 * [!] An explicit END token is expected in these cases!
-                                * ==> Recursion is possible if we encounter a tag with content;
+                                * ==> Recursion possible if we encounter a tag with content;
                                 *     recursion will return at the explicit END token.
                                 */
                                if (parsing_tag_content) { /* Recurse */
@@ -899,55 +2797,86 @@ parse_wbxml_tag (proto_tree *tree, tvbuff_t *tvb, guint32 offset,
                                         * recursion will take care of it */
                                        (*level)++;
                                        parse_wbxml_tag (tree, tvb, off, str_tbl, level,
-                                                       codepage_stag, codepage_attr, &len);
+                                                       &len);
                                        off += len;
                                } else { /* Now we will have content to parse */
                                        /* Save the start tag so we can properly close it later. */
-                                       if ((peek & 0x3F) == 4) {
+                                       if ((peek & 0x3F) == 4) { /* Literal tag */
                                                tag_save_literal = tag_new_literal;
                                                tag_save_known = 0;
-                                       } else {
+                                       } else { /* Known tag */
                                                tag_save_known = tag_new_known;
-                                               tag_save_literal = NULL;
+                                               sprintf (tag_save_buf, "Tag_0x%02X",
+                                                               tag_new_known);
+                                               tag_save_literal = tag_save_buf;
+                                               /* The last statement avoids needless lookups */
                                        }
                                        /* Process the attribute list if present */
                                        if (peek & 0x80) { /* Content and Attribute list present */
                                                if (tag_new_known) { /* Known tag */
-                                                       proto_tree_add_text (tree, tvb, off, 1,
-                                                                       "  %3d | Tag   "
-                                                                       "|   Known Tag 0x%02X           (AC) "
-                                                                       "| %s<Tag 0x%02X",
-                                                                       *level, tag_new_known, Indent (*level),
-                                                                       tag_new_known);
+                                                       if (codepage_stag) { /* Not default code page */
+                                                               proto_tree_add_text (tree, tvb, off, 1,
+                                                                               "  %3d | Tag   | T %3d->0 "
+                                                                               "|   Known Tag 0x%02X           (AC) "
+                                                                               "| %s<%s",
+                                                                               *level, codepage_stag, tag_new_known,
+                                                                               Indent (*level), tag_new_literal);
+                                                               /* Tag string already looked up earlier! */
+                                                               /* Reset code page */
+                                                               codepage_stag = 0;
+                                                       } else { /* Code page 0 */
+                                                               proto_tree_add_text (tree, tvb, off, 1,
+                                                                               "  %3d | Tag   |          "
+                                                                               "|   Known Tag 0x%02X           (AC) "
+                                                                               "| %s<%s",
+                                                                               *level, tag_new_known,
+                                                                               Indent (*level), tag_new_literal);
+                                                               /* Tag string already looked up earlier! */
+                                                       }
                                                        off++;
                                                } else { /* LITERAL tag */
                                                        proto_tree_add_text (tree, tvb, off, 1,
-                                                                       "  %3d | Tag   "
+                                                                       "  %3d | Tag   |          "
                                                                        "| LITERAL_AC (Literal tag)   (AC) "
-                                                                       "|   %s<%s",
+                                                                       "| %s<%s",
                                                                        *level, Indent (*level), tag_new_literal);
                                                        off += 1 + tag_len;
                                                }
-                                               parse_wbxml_attribute_list (tree, tvb, off, str_tbl,
-                                                               *level, codepage_attr, &len);
+                                               parse_wbxml_attribute_list (tree, tvb,
+                                                               off, str_tbl, *level, &len);
                                                off += len;
                                                proto_tree_add_text (tree, tvb, off-1, 1,
-                                                               "  %3d | Tag   "
+                                                               "  %3d | Tag   |          "
                                                                "| END (attribute list)            "
                                                                "| %s>",
                                                                *level, Indent (*level));
                                        } else { /* Content, no Attribute list */
                                                if (tag_new_known) { /* Known tag */
-                                                       proto_tree_add_text (tree, tvb, off, 1,
-                                                                       "  %3d | Tag   "
-                                                                       "|   Known Tag 0x%02X           (.C) "
-                                                                       "| %s<Tag 0x%02X>",
-                                                                       *level, tag_new_known, Indent (*level),
-                                                                       tag_new_known);
+                                                       if (codepage_stag) { /* Not default code page */
+                                                               proto_tree_add_text (tree, tvb, off, 1,
+                                                                               "  %3d | Tag   | T %3d->0 "
+                                                                               "|   Known Tag 0x%02X           (.C) "
+                                                                               "| %s<%s>",
+                                                                               *level, codepage_stag, tag_new_known,
+                                                                               Indent (*level),
+                                                                               tag_new_literal);
+                                                               /* Tag string already looked up earlier! */
+                                                               /* Reset code page */
+                                                               codepage_stag = 0;
+                                                       } else { /* Code page 0 */
+                                                               proto_tree_add_text (tree, tvb, off, 1,
+                                                                               "  %3d | Tag   |          "
+                                                                               "|   Known Tag 0x%02X           (.C) "
+                                                                               "| %s<%s>",
+                                                                               *level, tag_new_known,
+                                                                               Indent (*level),
+                                                                               tag_new_literal);
+                                                               /* Tag string already looked up earlier! */
+                                                       }
                                                        off++;
                                                } else { /* LITERAL tag */
                                                        proto_tree_add_text (tree, tvb, off, 1,
-                                                                       "  %3d | Tag   "
+                                                                       "  %3d | Tag   |          "
                                                                        "| LITERAL_C  (Literal Tag)   (.C) "
                                                                        "| %s<%s>",
                                                                        *level, Indent (*level), tag_new_literal);
@@ -961,59 +2890,87 @@ parse_wbxml_tag (proto_tree *tree, tvbuff_t *tvb, guint32 offset,
                                         */
                                        parsing_tag_content = TRUE;
 #ifdef DEBUG
-                                       printf ("WBXML: Tag in Tag - No recursion this time! (off = %d)\n",off);
+                                       printf ("WBXML: Tag in Tag - No recursion this time! "
+                                                       "(off = %d)\n", off);
 #endif
                                }
                        } else { /* No Content */
 #ifdef DEBUG
-                               printf ("WBXML: <Tag/> in Tag - No recursion! (off = %d)\n",off);
+                               printf ("WBXML: <Tag/> in Tag - No recursion! "
+                                               "(off = %d)\n", off);
 #endif
                                (*level)++;
                                if (peek & 0x80) { /* No Content, Attribute list present */
                                        if (tag_new_known) { /* Known tag */
-                                               proto_tree_add_text (tree, tvb, off, 1,
-                                                               "  %3d | Tag   "
-                                                               "|   Known Tag 0x%02X           (A.) "
-                                                               "| %s<Tag 0x%02X",
-                                                               *level, tag_new_known, Indent (*level),
-                                                               tag_new_known);
+                                               if (codepage_stag) { /* Not default code page */
+                                                       proto_tree_add_text (tree, tvb, off, 1,
+                                                                       "  %3d | Tag   | T %3d->0 "
+                                                                       "|   Known Tag 0x%02X           (A.) "
+                                                                       "| %s<%s",
+                                                                       *level, codepage_stag, tag_new_known,
+                                                                       Indent (*level), tag_new_literal);
+                                                       /* Tag string already looked up earlier! */
+                                                       /* Reset code page */
+                                                       codepage_stag = 0;
+                                               } else { /* Code page 0 */
+                                                       proto_tree_add_text (tree, tvb, off, 1,
+                                                                       "  %3d | Tag   |          "
+                                                                       "|   Known Tag 0x%02X           (A.) "
+                                                                       "| %s<%s",
+                                                                       *level, tag_new_known,
+                                                                       Indent (*level), tag_new_literal);
+                                                       /* Tag string already looked up earlier! */
+                                               }
                                                off++;
-                                               parse_wbxml_attribute_list (tree, tvb, off, str_tbl,
-                                                               *level, codepage_attr, &len);
+                                               parse_wbxml_attribute_list (tree, tvb,
+                                                               off, str_tbl, *level, &len);
                                                off += len;
                                                proto_tree_add_text (tree, tvb, off-1, 1,
-                                                               "  %3d | Tag   "
+                                                               "  %3d | Tag   |          "
                                                                "| END (Known Tag)                 "
                                                                "| %s/>",
                                                                *level, Indent (*level));
                                        } else { /* LITERAL tag */
                                                proto_tree_add_text (tree, tvb, off, 1,
-                                                               "  %3d | Tag   "
+                                                               "  %3d | Tag   |          "
                                                                "| LITERAL_A  (Literal Tag)   (A.) "
                                                                "| %s<%s",
                                                                *level, Indent (*level), tag_new_literal);
                                                off += 1 + tag_len;
-                                               parse_wbxml_attribute_list (tree, tvb, off, str_tbl,
-                                                               *level, codepage_attr, &len);
+                                               parse_wbxml_attribute_list (tree, tvb,
+                                                               off, str_tbl, *level, &len);
                                                off += len;
                                                proto_tree_add_text (tree, tvb, off-1, 1,
-                                                               "  %3d | Tag   "
+                                                               "  %3d | Tag   |          "
                                                                "| END (Literal Tag)               "
                                                                "| %s/>",
                                                                *level, Indent (*level));
                                        }
                                } else { /* No Content, No Attribute list */
                                        if (tag_new_known) { /* Known tag */
-                                               proto_tree_add_text (tree, tvb, off, 1,
-                                                               "  %3d | Tag   "
-                                                               "|   Known Tag 0x%02x           (..) "
-                                                               "| %s<Tag 0x%02X />",
-                                                               *level, tag_new_known, Indent (*level),
-                                                               tag_new_known);
+                                               if (codepage_stag) { /* Not default code page */
+                                                       proto_tree_add_text (tree, tvb, off, 1,
+                                                                       "  %3d | Tag   | T %3d->0 "
+                                                                       "|   Known Tag 0x%02x           (..) "
+                                                                       "| %s<%s />",
+                                                                       *level, codepage_stag, tag_new_known,
+                                                                       Indent (*level), tag_new_literal);
+                                                       /* Tag string already looked up earlier! */
+                                                       /* Reset code page */
+                                                       codepage_stag = 0;
+                                               } else { /* Code page 0 */
+                                                       proto_tree_add_text (tree, tvb, off, 1,
+                                                                       "  %3d | Tag   |          "
+                                                                       "|   Known Tag 0x%02x           (..) "
+                                                                       "| %s<%s />",
+                                                                       *level, tag_new_known,
+                                                                       Indent (*level), tag_new_literal);
+                                                       /* Tag string already looked up earlier! */
+                                               }
                                                off++;
                                        } else { /* LITERAL tag */
                                                proto_tree_add_text (tree, tvb, off, 1,
-                                                               "  %3d | Tag   "
+                                                               "  %3d | Tag   |          "
                                                                "| LITERAL    (Literal Tag)   (..) "
                                                                "| %s<%s />",
                                                                *level, Indent (*level), tag_new_literal);
@@ -1021,21 +2978,21 @@ parse_wbxml_tag (proto_tree *tree, tvbuff_t *tvb, guint32 offset,
                                        }
                                }
                                (*level)--;
+                               /* TODO: Do I have to reset code page here? */
                        }
                } /* if (tag & 0x3F) >= 5 */
        } /* while */
 }
 
 
-
 /**************************
  * WBXML Attribute tokens *
  **************************
  * Bit Mask  : Example
  * -------------------
  * 0... .... : attr=             (attribute name)
- *             href="http://"    (attribute name with start of attribute value)
- * 1... .... : "www."            (attribute value, or part of it)
+ *             href='http://'    (attribute name with start of attribute value)
+ * 1... .... : 'www.'            (attribute value, or part of it)
  * 
  */
 
@@ -1046,49 +3003,51 @@ parse_wbxml_tag (proto_tree *tree, tvbuff_t *tvb, guint32 offset,
  *
  * This function performs attribute list parsing.
  * 
- * The wbxml_mapping_table entry *map contains the actual token mapping.
+ * The wbxml_token_map entry *map contains the actual token mapping.
  *
- * NOTE: See packet-wbxml.h for known token mappings.
- *
- * NOTE: Code page switches not yet processed in the code!
+ * NOTE: See above for known token mappings.
  */
-void
-parse_wbxml_attribute_list_defined (proto_tree *tree, tvbuff_t *tvb, guint32 offset,
-               guint32 str_tbl, guint8 level, guint8 *codepage_attr, guint32 *parsed_length,
-               const wbxml_mapping_table *map)
+static void
+parse_wbxml_attribute_list_defined (proto_tree *tree, tvbuff_t *tvb,
+               guint32 offset, guint32 str_tbl, guint8 level,
+               guint32 *parsed_length,
+               const wbxml_token_map *map)
 {
        guint32 tvb_len = tvb_reported_length (tvb);
        guint32 off = offset;
        guint32 len;
+       guint str_len;
        guint32 ent;
        guint32 index;
-       const char* str;
        guint8 peek;
+       guint8 codepage_attr = 0; /* Initial codepage in state = ATTR */
 
 #ifdef DEBUG
-       printf ("WBXML - parse_wbxml_attr_defined (level = %d, offset = %d)\n", level, offset);
+       printf ("WBXML - parse_wbxml_attr_defined (level = %d, offset = %d)\n",
+                       level, offset);
 #endif
        /* Parse attributes */
        while (off < tvb_len) {
                peek = tvb_get_guint8 (tvb, off);
 #ifdef DEBUG
-               printf("WBXML - ATTR: level = %3d, peek = 0x%02X, off = %d, tvb_len = %d\n",
+               printf("WBXML - ATTR: level = %3d, peek = 0x%02X, off = %d, "
+                               "tvb_len = %d\n",
                                level, peek, off, tvb_len);
 #endif
-               if ((peek & 0x3F) < 5) switch (peek) { /* Global tokens in state = ATTR */
+               if ((peek & 0x3F) < 5) switch (peek) { /* Global tokens
+                                                                                                 in state = ATTR */
                        case 0x00: /* SWITCH_PAGE */
-                               peek = tvb_get_guint8 (tvb, off+1);
+                               codepage_attr = tvb_get_guint8 (tvb, off+1);
                                proto_tree_add_text (tree, tvb, off, 2,
-                                               "         Attr | SWITCH_PAGE (Attr code page)    "
-                                               "| Code page switch (was: %d, is: %d)",
-                                               *codepage_attr, peek);
-                               *codepage_attr = peek;
+                                               "      |  Attr | A 0->%3d "
+                                               "| SWITCH_PAGE (Attr code page)    |",
+                                               codepage_attr);
                                off += 2;
                                break;
                        case 0x01: /* END */
                                /* BEWARE
                                 *   The Attribute END token means either ">" or "/>"
-                                *   and as a consequence both must be trated separately.
+                                *   and as a consequence both must be treated separately.
                                 *   This is done in the TAG state parser.
                                 */
                                off++;
@@ -1097,40 +3056,57 @@ parse_wbxml_attribute_list_defined (proto_tree *tree, tvbuff_t *tvb, guint32 off
                        case 0x02: /* ENTITY */
                                ent = tvb_get_guintvar (tvb, off+1, &len);
                                proto_tree_add_text (tree, tvb, off, 1+len,
-                                               "  %3d |  Attr | ENTITY                          "
+                                               "  %3d |  Attr |          "
+                                               "| ENTITY                          "
                                                "|     %s'&#%u;'",
                                                level, Indent (level), ent);
                                off += 1+len;
                                break;
                        case 0x03: /* STR_I */
-                               /* Hack the string table lookup function */
-                               str = strtbl_lookup (tvb, off+1, 0, &len);
+                               len = tvb_strsize (tvb, off+1);
                                proto_tree_add_text (tree, tvb, off, 1+len,
-                                               "  %3d |  Attr | STR_I (Inline string)           "
+                                               "  %3d |  Attr |          "
+                                               "| STR_I (Inline string)           "
                                                "|     %s\'%s\'",
-                                               level, Indent (level), str);
+                                               level, Indent (level),
+                                               tvb_format_text (tvb, off+1, len-1));
                                off += 1+len;
                                break;
                        case 0x04: /* LITERAL */
                                index = tvb_get_guintvar (tvb, off+1, &len);
-                               str = strtbl_lookup (tvb, str_tbl, index, NULL);
+                               str_len = tvb_strsize (tvb, str_tbl+index);
                                proto_tree_add_text (tree, tvb, off, 1+len,
-                                               "  %3d |  Attr | LITERAL (Literal Attribute)     "
+                                               "  %3d |  Attr |          "
+                                               "| LITERAL (Literal Attribute)     "
                                                "|   %s<%s />",
-                                               level, Indent (level), str);
+                                               level, Indent (level),
+                                               tvb_format_text (tvb, str_tbl+index, str_len-1));
                                off += 1+len;
                                break;
                        case 0x40: /* EXT_I_0 */
                        case 0x41: /* EXT_I_1 */
                        case 0x42: /* EXT_I_2 */
                                /* Extension tokens */
-                               /* Hack the string table lookup function */
-                               str = strtbl_lookup (tvb, off+1, 0, &len);
-                               proto_tree_add_text (tree, tvb, off, 1+len,
-                                               "  %3d |  Attr | EXT_I_%1x    (Extension Token)    "
-                                               "|     %s(%s: \'%s\')",
-                                               level, peek & 0x0f, Indent (level),
-                                               match_strval (peek, map->global), str);
+                               len = tvb_strsize (tvb, off+1);
+                               if (codepage_attr) { /* Not default code page */
+                                       proto_tree_add_text (tree, tvb, off, 1+len,
+                                                       "  %3d |  Attr | A %3d->0 "
+                                                       "| EXT_I_%1x    (Extension Token)    "
+                                                       "|     %s(%s: \'%s\')",
+                                                       level, codepage_attr, peek & 0x0f, Indent (level),
+                                                       map_token (map->global, codepage_attr, peek),
+                                                       tvb_format_text (tvb, off+1, len-1));
+                                       /* Reset code page */
+                                       codepage_attr = 0;
+                               } else { /* Code page 0 */
+                                       proto_tree_add_text (tree, tvb, off, 1+len,
+                                                       "  %3d |  Attr |          "
+                                                       "| EXT_I_%1x    (Extension Token)    "
+                                                       "|     %s(%s: \'%s\')",
+                                                       level, peek & 0x0f, Indent (level),
+                                                       map_token (map->global, codepage_attr, peek),
+                                                       tvb_format_text (tvb, off+1, len-1));
+                               }
                                off += 1+len;
                                break;
                        /* 0x43 impossible in ATTR state */
@@ -1140,21 +3116,37 @@ parse_wbxml_attribute_list_defined (proto_tree *tree, tvbuff_t *tvb, guint32 off
                        case 0x82: /* EXT_T_2 */
                                /* Extension tokens */
                                index = tvb_get_guintvar (tvb, off+1, &len);
-                               str = strtbl_lookup (tvb, str_tbl, index, NULL);
-                               proto_tree_add_text (tree, tvb, off, 1+len,
-                                               "  %3d |  Attr | EXT_T_%1x    (Extension Token)    "
-                                               "|     %s(%s: \'%s\')",
-                                               level, peek & 0x0f, Indent (level),
-                                               match_strval (peek, map->global), str);
+                               str_len = tvb_strsize (tvb, str_tbl+index);
+                               if (codepage_attr) { /* Not default code page */
+                                       proto_tree_add_text (tree, tvb, off, 1+len,
+                                                       "  %3d |  Attr | A %3d->0 "
+                                                       "| EXT_T_%1x    (Extension Token)    "
+                                                       "|     %s(%s: \'%s\')",
+                                                       level, codepage_attr, peek & 0x0f, Indent (level),
+                                                       map_token (map->global, codepage_attr, peek),
+                                                       tvb_format_text (tvb, str_tbl+index, str_len-1));
+                                       /* Reset code page */
+                                       codepage_attr = 0;
+                               } else { /* Code page 0 */
+                                       proto_tree_add_text (tree, tvb, off, 1+len,
+                                                       "  %3d |  Attr |          "
+                                                       "| EXT_T_%1x    (Extension Token)    "
+                                                       "|     %s(%s: \'%s\')",
+                                                       level, peek & 0x0f, Indent (level),
+                                                       map_token (map->global, codepage_attr, peek),
+                                                       tvb_format_text (tvb, str_tbl+index, str_len-1));
+                               }
                                off += 1+len;
                                break;
-                       case 0x83: /* EXT_T */
+                       case 0x83: /* STR_T */
                                index = tvb_get_guintvar (tvb, off+1, &len);
-                               str = strtbl_lookup (tvb, str_tbl, index, NULL);
+                               str_len = tvb_strsize (tvb, str_tbl+index);
                                proto_tree_add_text (tree, tvb, off, 1+len,
-                                               "  %3d |  Attr | STR_T (Tableref string)         "
+                                               "  %3d |  Attr |          "
+                                               "| STR_T (Tableref string)         "
                                                "|     %s\'%s\'",
-                                               level, Indent (level), str);
+                                               level, Indent (level),
+                                               tvb_format_text (tvb, str_tbl+index, str_len-1));
                                off += 1+len;
                                break;
                        /* 0x84 impossible in ATTR state */
@@ -1162,25 +3154,40 @@ parse_wbxml_attribute_list_defined (proto_tree *tree, tvbuff_t *tvb, guint32 off
                        case 0xC1: /* EXT_1 */
                        case 0xC2: /* EXT_2 */
                                /* Extension tokens */
-                               proto_tree_add_text (tree, tvb, off, 1,
-                                               "  %3d |  Attr | EXT_%1x      (Extension Token)    "
-                                               "|     %s(%s)",
-                                               level, peek & 0x0f, Indent (level),
-                                               match_strval (peek, map->global));
+                               if (codepage_attr) { /* Not default code page */
+                                       proto_tree_add_text (tree, tvb, off, 1,
+                                                       "  %3d |  Attr | A %3d->0 "
+                                                       "| EXT_%1x      (Extension Token)    "
+                                                       "|     %s(%s)",
+                                                       level, codepage_attr, peek & 0x0f, Indent (level),
+                                                       map_token (map->global, codepage_attr, peek));
+                                       /* Reset code page */
+                                       codepage_attr = 0;
+                               } else { /* Code page 0 */
+                                       proto_tree_add_text (tree, tvb, off, 1,
+                                                       "  %3d |  Attr |          "
+                                                       "| EXT_%1x      (Extension Token)    "
+                                                       "|     %s(%s)",
+                                                       level, peek & 0x0f, Indent (level),
+                                                       map_token (map->global, codepage_attr, peek));
+                               }
                                off++;
                                break;
                        case 0xC3: /* OPAQUE - WBXML 1.1 and newer */
                                if (tvb_get_guint8 (tvb, 0)) { /* WBXML 1.x (x > 0) */
                                        index = tvb_get_guintvar (tvb, off+1, &len);
                                        proto_tree_add_text (tree, tvb, off, 1 + len + index,
-                                                       "  %3d |  Attr | OPAQUE (Opaque data)            "
+                                                       "  %3d |  Attr |          "
+                                                       "| OPAQUE (Opaque data)            "
                                                        "|       %s(%d bytes of opaque data)",
                                                        level, Indent (level), index);
                                        off += 1+len+index;
                                } else { /* WBXML 1.0 - RESERVED_2 token (invalid) */
                                        proto_tree_add_text (tree, tvb, off, 1,
-                                                       "         Attr | RESERVED_2     (Invalid Token!) "
-                                                       "| WBXML 1.0 parsing stops here.");
+                                                       "  %3d |  Attr |          "
+                                                       "| RESERVED_2     (Invalid Token!) "
+                                                       "| WBXML 1.0 parsing stops here.",
+                                                       level);
                                        /* Stop processing as it is impossible to parse now */
                                        off = tvb_len;
                                        *parsed_length = off - offset;
@@ -1190,7 +3197,8 @@ parse_wbxml_attribute_list_defined (proto_tree *tree, tvbuff_t *tvb, guint32 off
                        /* 0xC4 impossible in ATTR state */
                        default:
                                proto_tree_add_text (tree, tvb, off, 1,
-                                               "  %3d |  Attr | %-10s     (Invalid Token!) "
+                                               "  %3d |  Attr |          "
+                                               "| %-10s     (Invalid Token!) "
                                                "| WBXML parsing stops here.",
                                                level, match_strval (peek, vals_wbxml1x_global_tokens));
                                /* Move to end of buffer */
@@ -1198,18 +3206,42 @@ parse_wbxml_attribute_list_defined (proto_tree *tree, tvbuff_t *tvb, guint32 off
                                break;
                } else { /* Known atribute token */
                        if (peek & 0x80) { /* attrValue */
-                               proto_tree_add_text (tree, tvb, off, 1,
-                                               "  %3d |  Attr |   Known attrValue 0x%02X          "
-                                               "|       %s%s",
-                                               level, peek & 0x7f, Indent (level),
-                                               match_strval (peek, map->attrValue));
+                               if (codepage_attr) { /* Not default code page */
+                                       proto_tree_add_text (tree, tvb, off, 1,
+                                                       "  %3d |  Attr | A %3d->0 "
+                                                       "|   Known attrValue 0x%02X          "
+                                                       "|       %s%s",
+                                                       level, codepage_attr, peek & 0x7f, Indent (level),
+                                                       map_token (map->attrValue, codepage_attr, peek));
+                                       /* Reset code page */
+                                       codepage_attr = 0;
+                               } else { /* Code page 0 */
+                                       proto_tree_add_text (tree, tvb, off, 1,
+                                                       "  %3d |  Attr |          "
+                                                       "|   Known attrValue 0x%02X          "
+                                                       "|       %s%s",
+                                                       level, peek & 0x7f, Indent (level),
+                                                       map_token (map->attrValue, codepage_attr, peek));
+                               }
                                off++;
                        } else { /* attrStart */
-                               proto_tree_add_text (tree, tvb, off, 1,
-                                               "  %3d |  Attr |   Known attrStart 0x%02X          "
-                                               "|   %s%s",
-                                               level, peek & 0x7f, Indent (level),
-                                               match_strval (peek, map->attrStart));
+                               if (codepage_attr) { /* Not default code page */
+                                       proto_tree_add_text (tree, tvb, off, 1,
+                                                       "  %3d |  Attr | A %3d->0 "
+                                                       "|   Known attrStart 0x%02X          "
+                                                       "|   %s%s",
+                                                       level, codepage_attr, peek & 0x7f, Indent (level),
+                                                       map_token (map->attrStart, codepage_attr, peek));
+                                       /* Reset code page */
+                                       codepage_attr = 0;
+                               } else { /* Code page 0 */
+                                       proto_tree_add_text (tree, tvb, off, 1,
+                                                       "  %3d |  Attr |          "
+                                                       "|   Known attrStart 0x%02X          "
+                                                       "|   %s%s",
+                                                       level, peek & 0x7f, Indent (level),
+                                                       map_token (map->attrStart, codepage_attr, peek));
+                               }
                                off++;
                        }
                }
@@ -1217,7 +3249,6 @@ parse_wbxml_attribute_list_defined (proto_tree *tree, tvbuff_t *tvb, guint32 off
 }
 
 
-
 /* This function performs the WBXML attribute decoding as in
  * parse_wbxml_attribute_list_defined() but this time no WBXML mapping
  * is performed.
@@ -1226,42 +3257,46 @@ parse_wbxml_attribute_list_defined (proto_tree *tree, tvbuff_t *tvb, guint32 off
  * 
  * NOTE: Code page switches not yet processed in the code!
  */
-void
-parse_wbxml_attribute_list (proto_tree *tree, tvbuff_t *tvb, guint32 offset,
-               guint32 str_tbl, guint8 level, guint8 *codepage_attr, guint32 *parsed_length)
+static void
+parse_wbxml_attribute_list (proto_tree *tree, tvbuff_t *tvb,
+               guint32 offset, guint32 str_tbl, guint8 level,
+               guint32 *parsed_length)
 {
        guint32 tvb_len = tvb_reported_length (tvb);
        guint32 off = offset;
        guint32 len;
+       guint str_len;
        guint32 ent;
        guint32 index;
-       const char* str;
        guint8 peek;
+       guint8 codepage_attr = 0; /* Initial codepage in state = ATTR */
 
 #ifdef DEBUG
-       printf ("WBXML - parse_wbxml_attr_defined (level = %d, offset = %d)\n", level, offset);
+       printf ("WBXML - parse_wbxml_attr (level = %d, offset = %d)\n",
+                       level, offset);
 #endif
        /* Parse attributes */
        while (off < tvb_len) {
                peek = tvb_get_guint8 (tvb, off);
 #ifdef DEBUG
-               printf("WBXML - ATTR: level = %3d, peek = 0x%02X, off = %d, tvb_len = %d\n",
+               printf("WBXML - ATTR: level = %3d, peek = 0x%02X, off = %d, "
+                               "tvb_len = %d\n",
                                level, peek, off, tvb_len);
 #endif
-               if ((peek & 0x3F) < 5) switch (peek) { /* Global tokens in state = ATTR */
+               if ((peek & 0x3F) < 5) switch (peek) { /* Global tokens
+                                                                                                 in state = ATTR */
                        case 0x00: /* SWITCH_PAGE */
-                               peek = tvb_get_guint8 (tvb, off+1);
+                               codepage_attr = tvb_get_guint8 (tvb, off+1);
                                proto_tree_add_text (tree, tvb, off, 2,
-                                               "         Attr | SWITCH_PAGE (Attr code page)    "
-                                               "| Code page switch (was: %d, is: %d)",
-                                               *codepage_attr, peek);
-                               *codepage_attr = peek;
+                                               "      |  Attr | A 0->%3d "
+                                               "| SWITCH_PAGE (Attr code page)    |",
+                                               codepage_attr);
                                off += 2;
                                break;
                        case 0x01: /* END */
                                /* BEWARE
                                 *   The Attribute END token means either ">" or "/>"
-                                *   and as a consequence both must be trated separately.
+                                *   and as a consequence both must be treated separately.
                                 *   This is done in the TAG state parser.
                                 */
                                off++;
@@ -1270,39 +3305,55 @@ parse_wbxml_attribute_list (proto_tree *tree, tvbuff_t *tvb, guint32 offset,
                        case 0x02: /* ENTITY */
                                ent = tvb_get_guintvar (tvb, off+1, &len);
                                proto_tree_add_text (tree, tvb, off, 1+len,
-                                               "  %3d |  Attr | ENTITY                          "
+                                               "  %3d |  Attr |          "
+                                               "| ENTITY                          "
                                                "|     %s'&#%u;'",
                                                level, Indent (level), ent);
                                off += 1+len;
                                break;
                        case 0x03: /* STR_I */
-                               /* Hack the string table lookup function */
-                               str = strtbl_lookup (tvb, off+1, 0, &len);
+                               len = tvb_strsize (tvb, off+1);
                                proto_tree_add_text (tree, tvb, off, 1+len,
-                                               "  %3d |  Attr | STR_I (Inline string)           "
+                                               "  %3d |  Attr |          "
+                                               "| STR_I (Inline string)           "
                                                "|     %s\'%s\'",
-                                               level, Indent (level), str);
+                                               level, Indent (level),
+                                               tvb_format_text (tvb, off+1, len-1));
                                off += 1+len;
                                break;
                        case 0x04: /* LITERAL */
                                index = tvb_get_guintvar (tvb, off+1, &len);
-                               str = strtbl_lookup (tvb, str_tbl, index, NULL);
+                               str_len = tvb_strsize (tvb, str_tbl+index);
                                proto_tree_add_text (tree, tvb, off, 1+len,
-                                               "  %3d |  Attr | LITERAL (Literal Attribute)     "
+                                               "  %3d |  Attr |          "
+                                               "| LITERAL (Literal Attribute)     "
                                                "|   %s<%s />",
-                                               level, Indent (level), str);
+                                               level, Indent (level),
+                                               tvb_format_text (tvb, str_tbl+index, str_len-1));
                                off += 1+len;
                                break;
                        case 0x40: /* EXT_I_0 */
                        case 0x41: /* EXT_I_1 */
                        case 0x42: /* EXT_I_2 */
                                /* Extension tokens */
-                               /* Hack the string table lookup function */
-                               str = strtbl_lookup (tvb, off+1, 0, &len);
-                               proto_tree_add_text (tree, tvb, off, 1+len,
-                                               "  %3d |  Attr | EXT_I_%1x    (Extension Token)    "
-                                               "|     %s(Inline string extension: \'%s\')",
-                                               level, peek & 0x0f, Indent (level), str);
+                               len = tvb_strsize (tvb, off+1);
+                               if (codepage_attr) { /* Not default code page */
+                                       proto_tree_add_text (tree, tvb, off, 1+len,
+                                                       "  %3d |  Attr | A %3d->0 "
+                                                       "| EXT_I_%1x    (Extension Token)    "
+                                                       "|     %s(Inline string extension: \'%s\')",
+                                                       level, codepage_attr, peek & 0x0f, Indent (level),
+                                                       tvb_format_text (tvb, off+1, len-1));
+                                       /* Reset code page */
+                                       codepage_attr = 0;
+                               } else { /* Code page 0 */
+                                       proto_tree_add_text (tree, tvb, off, 1+len,
+                                                       "  %3d |  Attr |          "
+                                                       "| EXT_I_%1x    (Extension Token)    "
+                                                       "|     %s(Inline string extension: \'%s\')",
+                                                       level, peek & 0x0f, Indent (level),
+                                                       tvb_format_text (tvb, off+1, len-1));
+                               }
                                off += 1+len;
                                break;
                        /* 0x43 impossible in ATTR state */
@@ -1312,20 +3363,35 @@ parse_wbxml_attribute_list (proto_tree *tree, tvbuff_t *tvb, guint32 offset,
                        case 0x82: /* EXT_T_2 */
                                /* Extension tokens */
                                index = tvb_get_guintvar (tvb, off+1, &len);
-                               str = strtbl_lookup (tvb, str_tbl, index, NULL);
-                               proto_tree_add_text (tree, tvb, off, 1+len,
-                                               "  %3d |  Attr | EXT_T_%1x    (Extension Token)    "
-                                               "|     %s(Tableref string extension: \'%s\')",
-                                               level, peek & 0x0f, Indent (level), str);
+                               str_len = tvb_strsize (tvb, str_tbl+index);
+                               if (codepage_attr) { /* Not default code page */
+                                       proto_tree_add_text (tree, tvb, off, 1+len,
+                                                       "  %3d |  Attr | A %3d->0 "
+                                                       "| EXT_T_%1x    (Extension Token)    "
+                                                       "|     %s(Tableref string extension: \'%s\')",
+                                                       level, codepage_attr, peek & 0x0f, Indent (level),
+                                                       tvb_format_text (tvb, str_tbl+index, str_len-1));
+                                       /* Reset code page */
+                                       codepage_attr = 0;
+                               } else { /* Code page 0 */
+                                       proto_tree_add_text (tree, tvb, off, 1+len,
+                                                       "  %3d |  Attr |          "
+                                                       "| EXT_T_%1x    (Extension Token)    "
+                                                       "|     %s(Tableref string extension: \'%s\')",
+                                                       level, peek & 0x0f, Indent (level),
+                                                       tvb_format_text (tvb, str_tbl+index, str_len-1));
+                               }
                                off += 1+len;
                                break;
-                       case 0x83: /* EXT_T */
+                       case 0x83: /* STR_T */
                                index = tvb_get_guintvar (tvb, off+1, &len);
-                               str = strtbl_lookup (tvb, str_tbl, index, NULL);
+                               str_len = tvb_strsize (tvb, str_tbl+index);
                                proto_tree_add_text (tree, tvb, off, 1+len,
-                                               "  %3d |  Attr | STR_T (Tableref string)         "
+                                               "  %3d |  Attr |          "
+                                               "| STR_T (Tableref string)         "
                                                "|     %s\'%s\'",
-                                               level, Indent (level), str);
+                                               level, Indent (level),
+                                               tvb_format_text (tvb, str_tbl+index, str_len-1));
                                off += 1+len;
                                break;
                        /* 0x84 impossible in ATTR state */
@@ -1333,24 +3399,38 @@ parse_wbxml_attribute_list (proto_tree *tree, tvbuff_t *tvb, guint32 offset,
                        case 0xC1: /* EXT_1 */
                        case 0xC2: /* EXT_2 */
                                /* Extension tokens */
-                               proto_tree_add_text (tree, tvb, off, 1,
-                                               "  %3d |  Attr | EXT_%1x      (Extension Token)    "
-                                               "|     %s(Single-byte extension)",
-                                               level, peek & 0x0f, Indent (level));
+                               if (codepage_attr) { /* Not default code page */
+                                       proto_tree_add_text (tree, tvb, off, 1,
+                                                       "  %3d |  Attr | A %3d->0 "
+                                                       "| EXT_%1x      (Extension Token)    "
+                                                       "|     %s(Single-byte extension)",
+                                                       level, codepage_attr, peek & 0x0f, Indent (level));
+                                       /* Reset code page */
+                                       codepage_attr = 0;
+                               } else { /* Code page 0 */
+                                       proto_tree_add_text (tree, tvb, off, 1,
+                                                       "  %3d |  Attr |          "
+                                                       "| EXT_%1x      (Extension Token)    "
+                                                       "|     %s(Single-byte extension)",
+                                                       level, peek & 0x0f, Indent (level));
+                               }
                                off++;
                                break;
                        case 0xC3: /* OPAQUE - WBXML 1.1 and newer */
                                if (tvb_get_guint8 (tvb, 0)) { /* WBXML 1.x (x > 0) */
                                        index = tvb_get_guintvar (tvb, off+1, &len);
                                        proto_tree_add_text (tree, tvb, off, 1 + len + index,
-                                                       "  %3d |  Attr | OPAQUE (Opaque data)            "
+                                                       "  %3d |  Attr |          "
+                                                       "| OPAQUE (Opaque data)            "
                                                        "|       %s(%d bytes of opaque data)",
                                                        level, Indent (level), index);
                                        off += 1+len+index;
                                } else { /* WBXML 1.0 - RESERVED_2 token (invalid) */
                                        proto_tree_add_text (tree, tvb, off, 1,
-                                                       "         Attr | RESERVED_2     (Invalid Token!) "
-                                                       "| WBXML 1.0 parsing stops here.");
+                                                       "  %3d |  Attr |          "
+                                                       "| RESERVED_2     (Invalid Token!) "
+                                                       "| WBXML 1.0 parsing stops here.",
+                                                       level);
                                        /* Stop processing as it is impossible to parse now */
                                        off = tvb_len;
                                        *parsed_length = off - offset;
@@ -1360,7 +3440,8 @@ parse_wbxml_attribute_list (proto_tree *tree, tvbuff_t *tvb, guint32 offset,
                        /* 0xC4 impossible in ATTR state */
                        default:
                                proto_tree_add_text (tree, tvb, off, 1,
-                                               "  %3d |  Attr | %-10s     (Invalid Token!) "
+                                               "  %3d |  Attr |          "
+                                               "| %-10s     (Invalid Token!) "
                                                "| WBXML parsing stops here.",
                                                level, match_strval (peek, vals_wbxml1x_global_tokens));
                                /* Move to end of buffer */
@@ -1368,16 +3449,42 @@ parse_wbxml_attribute_list (proto_tree *tree, tvbuff_t *tvb, guint32 offset,
                                break;
                } else { /* Known atribute token */
                        if (peek & 0x80) { /* attrValue */
-                               proto_tree_add_text (tree, tvb, off, 1,
-                                               "  %3d |  Attr |   Known attrValue 0x%02X          "
-                                               "|       %sattrValue 0x%02X",
-                                               level, peek & 0x7f, Indent (level), peek);
+                               if (codepage_attr) { /* Not default code page */
+                                       proto_tree_add_text (tree, tvb, off, 1,
+                                                       "  %3d |  Attr | A %3d->0 "
+                                                       "|   Known attrValue 0x%02X          "
+                                                       "|       %sattrValue_0x%02X",
+                                                       level, codepage_attr, peek & 0x7f, Indent (level),
+                                                       peek);
+                                       /* Reset code page */
+                                       codepage_attr = 0;
+                               } else { /* Code page 0 */
+                                       proto_tree_add_text (tree, tvb, off, 1,
+                                                       "  %3d |  Attr |          "
+                                                       "|   Known attrValue 0x%02X          "
+                                                       "|       %sattrValue_0x%02X",
+                                                       level, peek & 0x7f, Indent (level),
+                                                       peek);
+                               }
                                off++;
                        } else { /* attrStart */
-                               proto_tree_add_text (tree, tvb, off, 1,
-                                               "  %3d |  Attr |   Known attrStart 0x%02X          "
-                                               "|   %sattrStart 0x%02X",
-                                               level, peek & 0x7f, Indent (level), peek);
+                               if (codepage_attr) { /* Not default code page */
+                                       proto_tree_add_text (tree, tvb, off, 1,
+                                                       "  %3d |  Attr | A %3d->0 "
+                                                       "|   Known attrStart 0x%02X          "
+                                                       "|   %sattrStart_0x%02X",
+                                                       level, codepage_attr, peek & 0x7f, Indent (level),
+                                                       peek);
+                                       /* Reset code page */
+                                       codepage_attr = 0;
+                               } else { /* Code page 0 */
+                                       proto_tree_add_text (tree, tvb, off, 1,
+                                                       "  %3d |  Attr |          "
+                                                       "|   Known attrStart 0x%02X          "
+                                                       "|   %sattrStart_0x%02X",
+                                                       level, peek & 0x7f, Indent (level),
+                                                       peek);
+                               }
                                off++;
                        }
                }
@@ -1385,43 +3492,37 @@ parse_wbxml_attribute_list (proto_tree *tree, tvbuff_t *tvb, guint32 offset,
 }
 
 
+/****************** Register the protocol with Ethereal ******************/
 
-/* Register the protocol with Ethereal */
 
 /* This format is required because a script is used to build the C function
-   that calls the protocol registration.
-*/
+ * that calls the protocol registration. */
 
 void
 proto_register_wbxml(void)
-{                 
-
-/* Setup list of header fields  See Section 1.6.1 for details*/
+{ /* Setup list of header fields. See Section 1.6.1 for details. */
        static hf_register_info hf[] = {
                { &hf_wbxml_version,
                        { "Version",
                          "wbxml.version",
                          FT_UINT8, BASE_HEX,
                          VALS ( vals_wbxml_versions ), 0x00,
-                         "WBXML version", HFILL }
+                         "WBXML Version", HFILL }
                },
-
                { &hf_wbxml_public_id_known,
                        { "Public Identifier (known)",
-                         "wbxml.public_id",
+                         "wbxml.public_id.known",
                          FT_UINT32, BASE_HEX,
                          VALS ( vals_wbxml_public_ids ), 0x00,
-                         "WBXML Public Identifier (known)", HFILL }
+                         "WBXML Known Public Identifier (integer)", HFILL }
                },
-
                { &hf_wbxml_public_id_literal,
                        { "Public Identifier (literal)",
-                         "wbxml.public_id",
+                         "wbxml.public_id.literal",
                          FT_STRING, BASE_NONE,
                          NULL, 0x00,
-                         "WBXML Public Identifier (literal)", HFILL }
+                         "WBXML Literal Public Identifier (text string)", HFILL }
                },
-
                { &hf_wbxml_charset,
                        { "Character Set",
                          "wbxml.charset",
@@ -1429,29 +3530,28 @@ proto_register_wbxml(void)
                          VALS ( vals_character_sets ), 0x00,
                          "WBXML Character Set", HFILL }
                },
-
        };
 
-/* Setup protocol subtree array */
+       /* Setup protocol subtree array */
        static gint *ett[] = {
                &ett_wbxml,
+               &ett_wbxml_str_tbl,
                &ett_wbxml_content,
        };
 
-/* Register the protocol name and description */
+       /* Register the protocol name and description */
        proto_wbxml = proto_register_protocol(
                        "WAP Binary XML",
                        "WBXML",
                        "wbxml"
        );
 
-/* Required function calls to register the header fields and subtrees used */
+       /* Required function calls to register the header fields
+        * and subtrees used */
        proto_register_field_array(proto_wbxml, hf, array_length(hf));
        proto_register_subtree_array(ett, array_length(ett));
 
        register_dissector("wbxml", dissect_wbxml, proto_wbxml);
-/*     register_init_routine(dissect_wbxml); */
-       /* wbxml_handle = find_dissector("wsp-co"); */
 };
 
 
@@ -1460,14 +3560,116 @@ proto_reg_handoff_wbxml(void)
 {
        dissector_handle_t wbxml_handle;
 
-       /* heur_dissector_add("wsp", dissect_wbxml_heur, proto_wbxml); */
+       /* Heuristic dissectors would be declared by means of:
+        * heur_dissector_add("wsp", dissect_wbxml_heur, proto_wbxml);
+        */
+
        wbxml_handle = create_dissector_handle(dissect_wbxml, proto_wbxml);
 
        /* Register the WSP content types (defined as protocol port)
-        * for WBXML dissection */
-       dissector_add("wsp.content_type.type", 0x14, wbxml_handle); /* wmlc */
-       dissector_add("wsp.content_type.type", 0x16, wbxml_handle); /* channelc */
-       dissector_add("wsp.content_type.type", 0x2E, wbxml_handle); /* sic */
-       dissector_add("wsp.content_type.type", 0x30, wbxml_handle); /* slc */
-       dissector_add("wsp.content_type.type", 0x32, wbxml_handle); /* coc */
+        * for WBXML dissection.
+        * 
+        * See http://www.wapforum.org/wina/wsp-content-type.htm
+        */
+
+       /**** Well-known WBXML WSP Content-Type values ****/
+       
+       /* application/vnd.wap.wmlc */
+       dissector_add("wsp.content_type.integer", 0x14, wbxml_handle);
+       dissector_add_string("wsp.content_type.literal",
+                       "application/vnd.wap.wmlc", wbxml_handle);
+       
+       /* application/vnd.wap.wta-eventc */
+       dissector_add("wsp.content_type.integer", 0x16, wbxml_handle);
+       dissector_add_string("wsp.content_type.literal",
+                       "application/vnd.wap.wta-eventc", wbxml_handle);
+       
+       /* application/vnd.wap.wbxml */
+       dissector_add("wsp.content_type.integer", 0x29, wbxml_handle);
+       dissector_add_string("wsp.content_type.literal",
+                       "application/vnd.wap.wbxml", wbxml_handle);
+       
+       /* application/vnd.wap.sic */
+       dissector_add("wsp.content_type.integer", 0x2E, wbxml_handle);
+       dissector_add_string("wsp.content_type.literal",
+                       "application/vnd.wap.sic", wbxml_handle);
+       
+       /* application/vnd.wap.slc */
+       dissector_add("wsp.content_type.integer", 0x30, wbxml_handle);
+       dissector_add_string("wsp.content_type.literal",
+                       "application/vnd.wap.slc", wbxml_handle);
+       
+       /* application/vnd.wap.coc */
+       dissector_add("wsp.content_type.integer", 0x32, wbxml_handle);
+       dissector_add_string("wsp.content_type.literal",
+                       "application/vnd.wap.coc", wbxml_handle);
+       
+       /* application/vnd.wap.connectivity-wbxml */
+       dissector_add("wsp.content_type.integer", 0x36, wbxml_handle);
+       dissector_add_string("wsp.content_type.literal",
+                       "application/vnd.wap.connectivity-wbxml", wbxml_handle);
+       
+       /* application/vnd.wap.locc+wbxml */
+       dissector_add("wsp.content_type.integer", 0x40, wbxml_handle);
+       dissector_add_string("wsp.content_type.literal",
+                       "application/vnd.wap.locc+wbxml", wbxml_handle);
+       
+       /* application/vnd.syncml.dm+wbxml */
+       dissector_add("wsp.content_type.integer", 0x42, wbxml_handle);
+       dissector_add_string("wsp.content_type.literal",
+                       "application/vnd.syncml.dm+wbxml", wbxml_handle);
+       
+       /* application/vnd.oma.drm.rights+wbxml */
+       dissector_add("wsp.content_type.integer", 0x4B, wbxml_handle);
+       dissector_add_string("wsp.content_type.literal",
+                       "application/vnd.oma.drm.rights+wbxml", wbxml_handle);
+
+       /**** Registered WBXML WSP Content-Type values ****/
+
+       /* application/vnd.uplanet.cacheop-wbxml */
+       dissector_add("wsp.content_type.integer", 0x0201, wbxml_handle);
+       dissector_add_string("wsp.content_type.literal",
+                       "application/vnd.uplanet.cacheop-wbxml", wbxml_handle);
+       
+       /* application/vnd.uplanet.alert-wbxml */
+       dissector_add("wsp.content_type.integer", 0x0203, wbxml_handle);
+       dissector_add_string("wsp.content_type.literal",
+                       "application/vnd.uplanet.alert-wbxml", wbxml_handle);
+       
+       /* application/vnd.uplanet.list-wbxml */
+       dissector_add("wsp.content_type.integer", 0x0204, wbxml_handle);
+       dissector_add_string("wsp.content_type.literal",
+                       "application/vnd.uplanet.list-wbxml", wbxml_handle);
+       
+       /* application/vnd.uplanet.listcmd-wbxml */
+       dissector_add("wsp.content_type.integer", 0x0205, wbxml_handle);
+       dissector_add_string("wsp.content_type.literal",
+                       "application/vnd.uplanet.listcmd-wbxml", wbxml_handle);
+       
+       /* application/vnd.uplanet.channel-wbxml */
+       dissector_add("wsp.content_type.integer", 0x0206, wbxml_handle);
+       dissector_add_string("wsp.content_type.literal",
+                       "application/vnd.uplanet.channel-wbxml", wbxml_handle);
+       
+       /* application/vnd.uplanet.bearer-choice-wbxml */
+       dissector_add("wsp.content_type.integer", 0x0209, wbxml_handle);
+       dissector_add_string("wsp.content_type.literal",
+                       "application/vnd.uplanet.bearer-choice-wbxml", wbxml_handle);
+       
+       /* application/vnd.phonecom.mmc-wbxml */
+       dissector_add("wsp.content_type.integer", 0x020A, wbxml_handle);
+       dissector_add_string("wsp.content_type.literal",
+                       "application/vnd.phonecom.mmc-wbxml", wbxml_handle);
+       
+       /* application/vnd.nokia.syncset+wbxml */
+       dissector_add("wsp.content_type.integer", 0x020B, wbxml_handle);
+       dissector_add_string("wsp.content_type.literal",
+                       "application/vnd.nokia.syncset+wbxml", wbxml_handle);
+
+       /***** Content types that only have a textual representation *****/
+       dissector_add_string("wsp.content_type.literal",
+                       "application/x-wap-prov.browser-bookmarks", wbxml_handle);
+       dissector_add_string("wsp.content_type.literal",
+                       "application/x-wap-prov.browser-settings", wbxml_handle);
+       
 }